Commit 1dd4f6c7 authored by Christos Stavrakakis's avatar Christos Stavrakakis

Merge branch 'feature-list-command' into develop

parents 5a265c71 c6b36078
# Copyright 2012 GRNET S.A. All rights reserved.
# Copyright 2012-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
......@@ -31,67 +31,28 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from optparse import make_option
from synnefo.webproject.management.commands import ListCommand
from synnefo.db.models import Flavor, VirtualMachine
from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import (format_bool, filter_results,
pprint_table)
from synnefo.db.models import Flavor
class Command(ListCommand):
help = "List available server flavors"
FIELDS = Flavor._meta.get_all_field_names()
object_class = Flavor
deleted_field = "deleted"
def get_vms(flavor):
return VirtualMachine.objects.filter(flavor=flavor, deleted=False)\
.count()
class Command(BaseCommand):
help = "List flavors"
FIELDS = {
"id": ("id", "Flavor's unique ID"),
"name": ("name", "Flavor's unique name"),
"cpu": ("cpu", "Number of CPUs"),
"ram": ("ram", "Size(MB) of RAM"),
"disk": ("disk", "Size(GB) of disk"),
"template": ("disk_template", "Disk template"),
"vms": (get_vms, "Number of active servers using this flavor")
}
option_list = BaseCommand.option_list + (
make_option(
'-c',
action='store_true',
dest='csv',
default=False,
help="Use pipes to separate values"),
make_option(
'--deleted',
action='store_true',
dest='deleted',
default=False,
help="Include deleted flavors"),
make_option(
'--filter-by',
dest='filter_by',
help="Filter results. Comma seperated list of key=val pairs"
" that displayed entries must satisfy. e.g."
" --filter-by \"cpu=1,ram!=1024\"."
"Available keys are: %s" % ", ".join(FIELDS))
)
def handle(self, *args, **options):
if args:
raise CommandError("Command doesn't accept any arguments")
if options['deleted']:
flavors = Flavor.objects.all()
else:
flavors = Flavor.objects.filter(deleted=False)
filter_by = options['filter_by']
if filter_by:
flavors = filter_results(flavors, filter_by)
headers = ('id', 'name', 'cpus', 'ram', 'disk', 'template', 'deleted')
table = []
for flavor in flavors.order_by('id'):
id = str(flavor.id)
cpu = str(flavor.cpu)
ram = str(flavor.ram)
disk = str(flavor.disk)
deleted = format_bool(flavor.deleted)
fields = (id, flavor.name, cpu, ram, disk, flavor.disk_template,
deleted)
table.append(fields)
separator = " | " if options['csv'] else None
pprint_table(self.stdout, table, headers, separator)
fields = ["id", "name", "cpu", "ram", "disk", "template", "vms"]
......@@ -37,21 +37,22 @@ from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import get_flavor
from logging import getLogger
log = getLogger(__name__)
class Command(BaseCommand):
args = "<flavor id>"
help = "Modify a flavor"
option_list = BaseCommand.option_list + (
make_option(
'--set-deleted',
action='store_true',
dest='deleted',
help="Mark a server as deleted"),
make_option(
'--set-undeleted',
action='store_true',
dest='undeleted',
help="Mark a server as not deleted"),
"--deleted",
dest="deleted",
metavar="True|False",
choices=["True", "False"],
default=None,
help="Mark/unmark a flavor as deleted"),
)
def handle(self, *args, **options):
......@@ -60,9 +61,10 @@ class Command(BaseCommand):
flavor = get_flavor(args[0])
if options.get('deleted'):
flavor.deleted = True
elif options.get('undeleted'):
flavor.deleted = False
flavor.save()
deleted = options['deleted']
if deleted:
log.info("Marking flavor %s as deleted=%s", flavor, deleted)
flavor.deleted = deleted
flavor.save()
else:
log.info("Nothing changed!")
......@@ -35,6 +35,7 @@ from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import validate_network_info, get_backend
from synnefo.webproject.management.util import pprint_table
from synnefo.db.models import Network
from synnefo.logic.backend import create_network
......@@ -50,6 +51,12 @@ class Command(BaseCommand):
help = "Create a new network"
option_list = BaseCommand.option_list + (
make_option(
"-n",
"--dry-run",
dest="dry_run",
default=False,
action="store_true"),
make_option(
'--name',
dest='name',
......@@ -129,6 +136,7 @@ class Command(BaseCommand):
if args:
raise CommandError("Command doesn't accept any arguments")
dry_run = options["dry_run"]
name = options['name']
subnet = options['subnet']
backend_id = options['backend_id']
......@@ -170,21 +178,28 @@ class Command(BaseCommand):
if not link or not mode:
raise CommandError("Can not create network."
" No connectivity link or mode")
network = Network.objects.create(name=name,
userid=options['owner'],
subnet=subnet,
gateway=gateway,
gateway6=gateway6,
subnet6=subnet6,
dhcp=options['dhcp'],
flavor=flavor,
public=public,
mode=mode,
link=link,
mac_prefix=mac_prefix,
tags=tags,
state='PENDING')
netinfo = {
"name": name,
"userid": options["owner"],
"subnet": subnet,
"gateway": gateway,
"gateway6": gateway6,
"subnet6": subnet6,
"dhcp": options["dhcp"],
"flavor": flavor,
"public": public,
"mode": mode,
"link": link,
"mac_prefix": mac_prefix,
"tags": tags,
"state": "PENDING"}
if dry_run:
self.stdout.write("Creating network:\n")
pprint_table(self.stdout, tuple(netinfo.items()))
return
network = Network.objects.create(**netinfo)
if public:
# Create BackendNetwork only to the specified Backend
......
# Copyright 2012 GRNET S.A. All rights reserved.
# Copyright 2012-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
......@@ -33,31 +33,15 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import (format_bool, filter_results, UserCache,
Omit)
from synnefo.webproject.management.commands import ListCommand
from synnefo.db.models import Network
from synnefo.management.common import pprint_table
FIELDS = Network._meta.get_all_field_names()
from logging import getLogger
log = getLogger(__name__)
class Command(BaseCommand):
help = "List networks"
option_list = BaseCommand.option_list + (
make_option(
'-c',
action='store_true',
dest='csv',
default=False,
help="Use pipes to separate values"),
make_option(
'--deleted',
action='store_true',
dest='deleted',
default=False,
help="Include deleted networks"),
class Command(ListCommand):
option_list = ListCommand.option_list + (
make_option(
'--public',
action='store_true',
......@@ -65,104 +49,51 @@ class Command(BaseCommand):
default=False,
help="List only public networks"),
make_option(
'--user',
dest='user',
help="List only networks of the specified user"
" (uuid or display name"),
make_option('--ipv6',
'--ipv6',
action='store_true',
dest='ipv6',
default=False,
help="Show IPv6 information of the network"),
make_option(
'--filter-by',
dest='filter_by',
help="Filter results. Comma seperated list of key 'cond' val pairs"
" that displayed entries must satisfy. e.g."
" --filter-by \"name=Network-1,link!=prv0\"."
" Available keys are: %s" % ", ".join(FIELDS)),
make_option(
'--displayname',
action='store_true',
dest='displayname',
default=False,
help="Display both uuid and display name"),
help="Include IPv6 information"),
)
def handle(self, *args, **options):
if args:
raise CommandError("Command doesn't accept any arguments")
ucache = UserCache()
if options['deleted']:
networks = Network.objects.all()
else:
networks = Network.objects.filter(deleted=False)
if options['public']:
networks = networks.filter(public=True)
user = options['user']
if user:
if '@' in user:
user = ucache.get_uuid(user)
networks = networks.filter(userid=user)
filter_by = options['filter_by']
if filter_by:
networks = filter_results(networks, filter_by)
displayname = options['displayname']
headers = filter(lambda x: x is not Omit,
['id',
'name',
'flavor',
'owner_uuid',
'owner_name' if displayname else Omit,
'mac_prefix',
'dhcp',
'state',
'link',
'vms',
'public',
])
if options['ipv6']:
headers.extend(['IPv6 Subnet', 'IPv6 Gateway'])
else:
headers.extend(['IPv4 Subnet', 'IPv4 Gateway'])
if displayname:
uuids = list(set([network.userid for network in networks]))
ucache.fetch_names(uuids)
table = []
for network in networks.order_by("id"):
uuid = network.userid
if displayname:
dname = ucache.get_name(uuid)
fields = filter(lambda x: x is not Omit,
[str(network.id),
network.name,
network.flavor,
uuid or '-',
dname or '-' if displayname else Omit,
network.mac_prefix or '-',
str(network.dhcp),
network.state,
network.link or '-',
str(network.machines.count()),
format_bool(network.public),
])
if options['ipv6']:
fields.extend([network.subnet6 or '', network.gateway6 or ''])
else:
fields.extend([network.subnet, network.gateway or ''])
table.append(fields)
separator = " | " if options['csv'] else None
pprint_table(self.stdout, table, headers, separator)
object_class = Network
deleted_field = "deleted"
user_uuid_field = "userid"
def get_machines(network):
return network.machines.filter(deleted=False).count()
def get_backends(network):
return network.backend_networks.values_list("backend_id", flat=True)
FIELDS = {
"id": ("id", "The ID of the network"),
"name": ("name", "The name of the network"),
"user.uuid": ("userid", "The UUID of the network's owner"),
"public": ("public", "Whether network is public or private"),
"flavor": ("flavor", "The network's flavor"),
"state": ("state", "The network's state"),
"dhcp": ("dhcp", "Whether network uses nfdhcpd or not"),
"subnet.ipv4": ("subnet", "The IPv4 subnet of the network"),
"gateway.ipv4": ("gateway", "The IPv4 gateway of the network"),
"subnet.ipv6": ("subnet", "The IPv6 subnet of the network"),
"gateway.ipv6": ("gateway", "The IPv6 gateway of the network"),
"created": ("created", "The date the network was created"),
"updated": ("created", "The date the network was updated"),
"deleted": ("deleted", "Whether the network is deleted or not"),
"mode": ("mode", "The mode of the network"),
"link": ("link", "The link of the network"),
"mac_prefix": ("mac_prefix", "The network's MAC prefix"),
"vms": (get_machines, "Number of connected servers"),
"backends": (get_backends, "IDs of Ganeti backends that the network is"
" connected to"),
}
fields = ["id", "name", "user.uuid", "state", "public", "subnet.ipv4",
"gateway.ipv4", "link", "mac_prefix"]
def handle_args(self, *args, **options):
if options["public"]:
self.filters["public"] = True
if options["ipv6"]:
self.fields.extend(["subnet.ipv6", "gateway.ipv6"])
# Copyright 2012 GRNET S.A. All rights reserved.
# Copyright 2012-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
......@@ -33,152 +33,96 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import (format_vm_state, get_backend, Omit,
filter_results, pprint_table, UserCache)
from synnefo.api.util import get_image
from synnefo.webproject.management.commands import ListCommand
from synnefo.db.models import VirtualMachine
from synnefo.management.common import get_backend
from synnefo.api.util import get_image
import logging
log = logging.getLogger(__name__)
FIELDS = VirtualMachine._meta.get_all_field_names()
from logging import getLogger
log = getLogger(__name__)
class Command(BaseCommand):
class Command(ListCommand):
help = "List servers"
option_list = BaseCommand.option_list + (
make_option(
'-c',
action='store_true',
dest='csv',
default=False,
help="Use pipes to separate values"),
option_list = ListCommand.option_list + (
make_option(
'--suspended',
action='store_true',
dest='suspended',
default=False,
help="List only suspended servers"),
make_option(
'--build',
action='store_true',
dest='build',
default=False,
help="List only servers in the building state"),
make_option(
'--deleted',
action='store_true',
dest='deleted',
default=False,
help="Include deleted servers"),
make_option(
'--backend-id',
dest='backend_id',
help="List only servers of the specified backend"),
make_option(
'--user',
dest='user',
help="List only servers of the specified user (uuid or email)"),
make_option(
'--filter-by',
dest='filter_by',
help="Filter results. Comma seperated list of key `cond` val pairs"
" that displayed entries must satisfy. e.g."
" --filter-by \"operstate=STARTED,id>=22\"."
" Available keys are: %s" % ", ".join(FIELDS)),
"--build",
action="store_true",
dest="build",
default=False,
help="List only servers in the building state"),
make_option(
'--displayname',
action='store_true',
dest='displayname',
"--image-name",
action="store_true",
dest="image_name",
default=False,
help="Display both uuid and display name"),
help="Display image name instead of image ID"),
)
def handle(self, *args, **options):
if args:
raise CommandError("Command doesn't accept any arguments")
object_class = VirtualMachine
deleted_field = "deleted"
user_uuid_field = "userid"
ucache = UserCache()
if options['backend_id']:
backend = get_backend(options['backend_id'])
servers = backend.virtual_machines
else:
servers = VirtualMachine.objects
def get_public_ip(vm):
try:
return vm.nics.all()[0].ipv4
except IndexError:
return None
if options['deleted']:
servers = servers.all()
def format_vm_state(vm):
if vm.operstate == "BUILD":
return "BUILD(" + str(vm.buildpercentage) + "%)"
else:
servers = servers.filter(deleted=False)
if options['suspended']:
servers = servers.filter(suspended=True)
if options['build']:
servers = servers.filter(operstate='BUILD')
user = options['user']
if user:
if '@' in user:
user = ucache.get_uuid(user)
servers = servers.filter(userid=user)
filter_by = options['filter_by']
if filter_by:
servers = filter_results(servers, filter_by)
displayname = options['displayname']
cache = ImageCache()
headers = filter(lambda x: x is not Omit,
['id',
'name',
'owner_uuid',
'owner_name' if displayname else Omit,
'flavor',
'image',
'state',
'backend',
])
if displayname:
uuids = list(set([server.userid for server in servers]))
ucache.fetch_names(uuids)
table = []
for server in servers.order_by('id'):
try:
name = server.name.decode('utf8')
except UnicodeEncodeError:
name = server.name
flavor = server.flavor.name
image = cache.get_image(server.imageid, server.userid)
state = format_vm_state(server)
uuid = server.userid
if displayname:
dname = ucache.get_name(server.userid)
fields = filter(lambda x: x is not Omit,
[str(server.id),
name,
uuid,
dname if displayname else Omit,
flavor,
image,
state,
str(server.backend),
])
table.append(fields)
separator = " | " if options['csv'] else None