Commit 547290f1 authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

cyclades: Common module for pretty-printing

Create common module for pretty-printing database objects. Currently it
contains only functions for pretty-printing networks and ports.
parent 4c0f9b58
......@@ -39,6 +39,7 @@ from snf_django.management.utils import parse_bool
from synnefo.db.models import Network, Backend
from synnefo.logic import networks
from synnefo.management import pprint
NETWORK_FLAVORS = Network.FLAVORS.keys()
......@@ -194,4 +195,6 @@ class Command(BaseCommand):
floating_ip_pool=floating_ip_pool,
backends=backends, lazy_create=False)
self.stdout.write("Created network '%s' in DB.\n" % network)
self.stdout.write("Created network '%s' in DB:\n" % network)
pprint.pprint_network(network, stdout=self.stdout)
pprint.pprint_network_subnets(network, stdout=self.stdout)
......@@ -37,8 +37,7 @@ from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import convert_api_faults
from synnefo.api import util
from synnefo.management.common import (get_network, get_vm,
get_floating_ip_by_id)
from synnefo.management import common, pprint
from synnefo.logic import ports
HELP_MSG = """Create a new port.
......@@ -111,12 +110,12 @@ class Command(BaseCommand):
if server_id:
owner = "vm"
vm = get_vm(server_id)
vm = common.get_vm(server_id)
#if vm.router:
# raise CommandError("Server '%s' does not exist." % server_id)
elif router_id:
owner = "router"
vm = get_vm(router_id)
vm = common.get_vm(router_id)
if not vm.router:
raise CommandError("Router '%s' does not exist." % router_id)
else:
......@@ -124,14 +123,14 @@ class Command(BaseCommand):
floating_ip = None
if floating_ip_id:
floating_ip = get_floating_ip_by_id(floating_ip_id,
for_update=True)
floating_ip = common.get_floating_ip_by_id(floating_ip_id,
for_update=True)
if floating_ip.userid != vm.userid:
msg = "Floating IP %s does not belong to server/router owner."
raise CommandError(msg % floating_ip)
# get the network
network = get_network(network_id)
network = common.get_network(network_id)
# validate security groups
sg_list = []
......@@ -144,6 +143,8 @@ class Command(BaseCommand):
new_port = ports.create(network, vm, name=name, ipaddress=floating_ip,
security_groups=sg_list,
device_owner=owner)
self.stdout.write("Created port '%s' in DB.\n" % new_port)
self.stdout.write("Created port '%s' in DB:\n" % new_port)
pprint.pprint_port(new_port, stdout=self.stdout)
pprint.pprint_port_ips(new_port, stdout=self.stdout)
# TODO: Display port information, like ip address
# TODO: Add --wait argument to report progress about the Ganeti job.
# Copyright 2012 GRNET S.A. All rights reserved.
# Copyright 2013 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
......@@ -34,11 +34,9 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from synnefo.logic.rapi import GanetiApiError
from synnefo.management.common import convert_api_faults
from synnefo.logic.reconciliation import nics_from_instance
from snf_django.management.utils import pprint_table
from synnefo.api.util import get_port
from synnefo.management import pprint
class Command(BaseCommand):
......@@ -67,52 +65,10 @@ class Command(BaseCommand):
port = get_port(args[0], None)
db_nic = {
"id": port.id,
"name": port.name,
"userid": port.userid,
"server": port.machine_id,
"network": port.network_id,
"device_owner": port.device_owner,
"mac": port.mac,
"state": port.state}
pprint_table(self.stdout, db_nic.items(), None, separator=" | ",
title="State of port in DB")
pprint.pprint_port(port, stdout=self.stdout)
self.stdout.write('\n\n')
ips = list(port.ips.values_list("address", "network_id", "subnet_id",
"subnet__cidr", "floating_ip"))
headers = ["Address", "Network", "Subnet", "CIDR", "is_floating"]
pprint_table(self.stdout, ips, headers, separator=" | ",
title="IP Addresses")
pprint.pprint_port_ips(port, stdout=self.stdout)
self.stdout.write('\n\n')
vm = port.machine
if vm is None:
self.stdout.write("Port is not attached to any instance.\n")
return
client = vm.get_client()
try:
vm_info = client.GetInstance(vm.backend_vm_id)
except GanetiApiError as e:
if e.code == 404:
self.stdout.write("NIC seems attached to server %s, but"
" server does not exist in backend.\n"
% vm)
return
raise e
nics = nics_from_instance(vm_info)
try:
gnt_nic = filter(lambda nic: nic.get("name") == port.backend_uuid,
nics)[0]
except IndexError:
self.stdout.write("NIC %s is not attached to instance %s"
% (port, vm))
return
pprint_table(self.stdout, gnt_nic.items(), None, separator=" | ",
title="State of port in Ganeti")
vm.put_client(client)
pprint.pprint_port_in_ganeti(port, stdout=self.stdout)
......@@ -34,16 +34,7 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import get_network
from synnefo.db.models import (Backend, pooled_rapi_client)
from synnefo.logic.rapi import GanetiApiError
from snf_django.lib.astakos import UserCache
from synnefo.settings import (CYCLADES_SERVICE_TOKEN as ASTAKOS_TOKEN,
ASTAKOS_BASE_URL)
from util import pool_map_chunks
from snf_django.management.utils import pprint_table
from synnefo.lib.ordereddict import OrderedDict
from synnefo.management import pprint, common
class Command(BaseCommand):
......@@ -59,83 +50,17 @@ class Command(BaseCommand):
)
def handle(self, *args, **options):
write = self.stdout.write
if len(args) != 1:
raise CommandError("Please provide a network ID.")
network = get_network(args[0])
ucache = UserCache(ASTAKOS_BASE_URL, ASTAKOS_TOKEN)
network = common.get_network(args[0])
displayname = options['displayname']
userid = network.userid
db_network = OrderedDict([
("name", network.name),
("backend-name", network.backend_id),
("state", network.state),
("userid", userid),
("username", ucache.get_name(userid) if displayname else ""),
("public", network.public),
("floating_ip_pool", network.floating_ip_pool),
("external_router", network.external_router),
("drained", network.drained),
("MAC prefix", network.mac_prefix),
("flavor", network.flavor),
("link", network.link),
("mode", network.mode),
("deleted", network.deleted),
("tags", "), ".join(network.backend_tag)),
("action", network.action)])
pprint_table(self.stdout, db_network.items(), None, separator=" | ",
title="State of Network in DB")
subnets = list(network.subnets.values_list("id", "name", "ipversion",
"cidr", "gateway", "dhcp",
"deleted"))
headers = ["ID", "Name", "Version", "CIDR", "Gateway", "DHCP",
"Deleted"]
write("\n\n")
pprint_table(self.stdout, subnets, headers, separator=" | ",
title="Subnets")
bnets = list(network.backend_networks.values_list(
"backend__clustername",
"operstate", "deleted", "backendjobid",
"backendopcode", "backendjobstatus"))
headers = ["Backend", "State", "Deleted", "JobID", "Opcode",
"JobStatus"]
write("\n\n")
pprint_table(self.stdout, bnets, headers, separator=" | ",
title="Backend Networks")
write("\n\n")
for backend in Backend.objects.exclude(offline=True):
with pooled_rapi_client(backend) as client:
try:
g_net = client.GetNetwork(network.backend_id)
ip_map = g_net.pop("map")
pprint_table(self.stdout, g_net.items(), None,
title="State of network in backend: %s" %
backend.clustername)
write(splitPoolMap(ip_map, 80) + "\n\n")
except GanetiApiError as e:
if e.code == 404:
write('Network does not exist in backend %s\n' %
backend.clustername)
else:
raise e
def splitPoolMap(s, count):
chunks = pool_map_chunks(s, count)
acc = []
count = 0
for chunk in chunks:
chunk_len = len(chunk)
acc.append(str(count).rjust(3) + ' ' + chunk + ' ' +
str(count + chunk_len - 1).ljust(4))
count += chunk_len
return '\n' + '\n'.join(acc)
pprint.pprint_network(network, display_mails=displayname,
stdout=self.stdout)
self.stdout.write("\n\n")
pprint.pprint_network_subnets(network, stdout=self.stdout)
self.stdout.write("\n\n")
pprint.pprint_network_backends(network, stdout=self.stdout)
self.stdout.write("\n\n")
pprint.pprint_network_in_ganeti(network, stdout=self.stdout)
......@@ -34,8 +34,9 @@
from django.core.management.base import BaseCommand, CommandError
from optparse import make_option
from util import pool_table_from_type, pool_map_chunks
from synnefo.db.pools import bitarray_to_map
from synnefo.db.models import MacPrefixPoolTable, BridgePoolTable
from synnefo.management import pprint
POOL_CHOICES = ['bridge', 'mac-prefix']
......@@ -81,19 +82,18 @@ class Command(BaseCommand):
self.stdout.write(line.encode('utf8'))
step = (type_ == 'bridge') and 64 or 80
print_map('Pool', pool.to_map(), step, self.stdout)
print_map('Reserved', bitarray_to_map(pool.reserved[:pool_row.size]),
step, self.stdout)
pprint.pprint_pool('Available', pool.to_map(), step, self.stdout)
pprint.pprint_pool('Reserved',
bitarray_to_map(pool.reserved[:pool_row.size]),
step, self.stdout)
def print_map(name, pool_map, step, out):
sep = '*' * 80
out.write(sep + "\n")
out.write("%s: \n" % name)
out.write(sep + "\n")
count = 0
for chunk in pool_map_chunks(pool_map, step):
chunk_len = len(chunk)
out.write(("%s " % count).rjust(4))
out.write((chunk + " %d\n") % (count + chunk_len - 1))
count += chunk_len
def pool_table_from_type(type_):
if type_ == "mac-prefix":
return MacPrefixPoolTable
elif type_ == "bridge":
return BridgePoolTable
# elif type == "ip":
# return IPPoolTable
else:
raise ValueError("Invalid pool type")
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from synnefo.db.models import MacPrefixPoolTable, BridgePoolTable
def pool_table_from_type(type_):
if type_ == "mac-prefix":
return MacPrefixPoolTable
elif type_ == "bridge":
return BridgePoolTable
# elif type == "ip":
# return IPPoolTable
else:
raise ValueError("Invalid pool type")
def pool_map_chunks(smap, step=64):
for i in xrange(0, len(smap), step):
yield smap[i:i + step]
#Copyright (C) 2013 GRNET S.A. All rights reserved.
#
#Redistribution and use in source and binary forms, with or
#without modification, are permitted provided that the following
#conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
#OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
#PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A. OR
#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
#USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
#AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
#LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
#ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#POSSIBILITY OF SUCH DAMAGE.
#
#The views and conclusions contained in the software and
#documentation are those of the authors and should not be
#interpreted as representing official policies, either expressed
#or implied, of GRNET S.A.
import sys
from snf_django.management.utils import pprint_table
from synnefo.lib.ordereddict import OrderedDict
from snf_django.lib.astakos import UserCache
from synnefo.settings import (CYCLADES_SERVICE_TOKEN as ASTAKOS_TOKEN,
ASTAKOS_BASE_URL)
from synnefo.db.models import Backend, pooled_rapi_client
from synnefo.logic.rapi import GanetiApiError
from synnefo.logic.reconciliation import nics_from_instance
def pprint_network(network, display_mails=False, stdout=None, title=None):
if stdout is None:
stdout = sys.stdout
if title is None:
title = "State of Network %s in DB" % network.id
ucache = UserCache(ASTAKOS_BASE_URL, ASTAKOS_TOKEN)
userid = network.userid
db_network = OrderedDict([
("name", network.name),
("backend-name", network.backend_id),
("state", network.state),
("userid", userid),
("username", ucache.get_name(userid) if display_mails else userid),
("public", network.public),
("floating_ip_pool", network.floating_ip_pool),
("external_router", network.external_router),
("drained", network.drained),
("MAC prefix", network.mac_prefix),
("flavor", network.flavor),
("link", network.link),
("mode", network.mode),
("deleted", network.deleted),
("tags", "), ".join(network.backend_tag)),
("action", network.action)])
pprint_table(stdout, db_network.items(), None, separator=" | ",
title=title)
def pprint_network_subnets(network, stdout=None, title=None):
if stdout is None:
stdout = sys.stdout
if title is None:
title = "Subnets of network %s" % network.id
subnets = list(network.subnets.values_list("id", "name", "ipversion",
"cidr", "gateway", "dhcp",
"deleted"))
headers = ["ID", "Name", "Version", "CIDR", "Gateway", "DHCP",
"Deleted"]
pprint_table(stdout, subnets, headers, separator=" | ",
title=title)
def pprint_network_backends(network, stdout=None, title=None):
if stdout is None:
stdout = sys.stdout
if title is None:
title = "State of Network %s in DB for each backend" % network.id
bnets = list(network.backend_networks.values_list(
"backend__clustername",
"operstate", "deleted", "backendjobid",
"backendopcode", "backendjobstatus"))
headers = ["Backend", "State", "Deleted", "JobID", "Opcode",
"JobStatus"]
pprint_table(stdout, bnets, headers, separator=" | ",
title=title)
def pprint_network_in_ganeti(network, stdout=None):
if stdout is None:
stdout = sys.stdout
for backend in Backend.objects.exclude(offline=True):
with pooled_rapi_client(backend) as client:
try:
g_net = client.GetNetwork(network.backend_id)
ip_map = g_net.pop("map")
pprint_table(stdout, g_net.items(), None,
title="State of network in backend: %s" %
backend.clustername)
pprint_pool(None, ip_map, 80, stdout)
except GanetiApiError as e:
if e.code == 404:
stdout.write('Network does not exist in backend %s\n' %
backend.clustername)
else:
raise e
def pool_map_chunks(smap, step=64):
for i in xrange(0, len(smap), step):
yield smap[i:i + step]
def splitPoolMap(s, count):
chunks = pool_map_chunks(s, count)
acc = []
count = 0
for chunk in chunks:
chunk_len = len(chunk)
acc.append(str(count).rjust(3) + ' ' + chunk + ' ' +
str(count + chunk_len - 1).ljust(4))
count += chunk_len
return '\n' + '\n'.join(acc)
def pprint_pool(name, pool_map, step=80, stdout=None):
if stdout is None:
stdout = sys.stdout
if name is not None:
stdout.write("Pool: %s\n" % name)
stdout.write(splitPoolMap(pool_map, count=step))
stdout.write("\n")
def pprint_port(port, stdout=None, title=None):
if stdout is None:
stdout = sys.stdout
if title is None:
title = "State of Port %s in DB" % port.id
port = OrderedDict([
("id", port.id),
("name", port.name),
("userid", port.userid),
("server", port.machine_id),
("network", port.network_id),
("device_owner", port.device_owner),
("mac", port.mac),
("state", port.state)])
pprint_table(stdout, port.items(), None, separator=" | ",
title=title)
def pprint_port_ips(port, stdout=None, title=None):
if stdout is None:
stdout = sys.stdout
if title is None:
title = "IP Addresses of Port %s" % port.id
ips = list(port.ips.values_list("address", "network_id", "subnet_id",
"subnet__cidr", "floating_ip"))
headers = ["Address", "Network", "Subnet", "CIDR", "is_floating"]
pprint_table(stdout, ips, headers, separator=" | ",
title=title)
def pprint_port_in_ganeti(port, stdout=None, title=None):
if stdout is None:
stdout = sys.stdout
if title is None:
title = "State of Port %s in Ganeti" % port.id
vm = port.machine
if vm is None:
stdout.write("Port is not attached to any instance.\n")
return
client = vm.get_client()
try:
vm_info = client.GetInstance(vm.backend_vm_id)
except GanetiApiError as e:
if e.code == 404:
stdout.write("NIC seems attached to server %s, but"
" server does not exist in backend.\n"
% vm)
return
raise e
nics = nics_from_instance(vm_info)
try:
gnt_nic = filter(lambda nic: nic.get("name") == port.backend_uuid,
nics)[0]
gnt_nic["instance"] = vm_info["name"]
except IndexError:
stdout.write("NIC %s is not attached to instance %s" % (port, vm))
return
pprint_table(stdout, gnt_nic.items(), None, separator=" | ",
title=title)
vm.put_client(client)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment