Commit 8d4176e5 authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

Add --filter-by option to *-list commands

Add --filter-by option to server-list, network-list and flavor-list
management commands. The value of this option is a comma-seperated list
of key 'cond' val pairs and, when used, only the DB entries that satisfy all of
the specified conditions are displayed.

The exact keys that can be used are displayed in the help message. Also
when a wrong key is used, all the available keys are displayed to the
error message. No attempt is made to "sanitize" the keys.

Examples:
snf-manage server-list --filter-by "deleted=True,state=STARTED"
snf-manage server-list --filter-by userid=cstavr@grnet.gr,flavor__cpu=2
snf-manage flavor-list --filter-by "ram>=1024,disk<20"
parent 87380d86
......@@ -34,10 +34,12 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import format_bool
from synnefo.management.common import format_bool, filter_results
from synnefo.db.models import Flavor
FIELDS = Flavor._meta.get_all_field_names()
class Command(BaseCommand):
help = "List flavors"
......@@ -53,6 +55,12 @@ class Command(BaseCommand):
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):
......@@ -73,6 +81,11 @@ class Command(BaseCommand):
else:
flavors = Flavor.objects.filter(deleted=False)
filter_by = options['filter_by']
if filter_by:
flavors = filter_results(flavors, filter_by)
for flavor in flavors.order_by('id'):
id = str(flavor.id)
cpu = str(flavor.cpu)
......
......@@ -34,10 +34,11 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import format_bool
from synnefo.management.common import format_bool, filter_results
from synnefo.db.models import Network
FIELDS = Network._meta.get_all_field_names()
class Command(BaseCommand):
help = "List networks"
......@@ -63,6 +64,13 @@ class Command(BaseCommand):
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))
)
def handle(self, *args, **options):
......@@ -77,6 +85,10 @@ class Command(BaseCommand):
if options['public']:
networks = networks.filter(public=True)
filter_by = options['filter_by']
if filter_by:
networks = filter_results(networks, filter_by)
labels = ['id', 'name', 'type', 'owner',
'mac_prefix', 'dhcp', 'state', 'link', 'vms', 'public']
columns = [3, 16, 22, 30, 10, 6, 8, 12, 4, 6]
......
......@@ -34,12 +34,15 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from synnefo.management.common import format_vm_state, get_backend
from synnefo.management.common import (format_vm_state, get_backend,
filter_results)
from synnefo.api.util import get_image
from synnefo.db.models import VirtualMachine
FIELDS = VirtualMachine._meta.get_all_field_names()
class Command(BaseCommand):
help = "List servers"
......@@ -59,11 +62,20 @@ class Command(BaseCommand):
dest='build',
default=False,
help="List only servers in the building state"),
make_option('--deleted', action='store_true', dest='deleted',
default=False,
help="Include deletd servers"),
make_option('--backend-id', dest='backend_id',
help="List only servers of the specified backend")
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('--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))
)
def handle(self, *args, **options):
......@@ -87,6 +99,10 @@ class Command(BaseCommand):
if options['build']:
servers = servers.filter(operstate='BUILD')
filter_by = options['filter_by']
if filter_by:
servers = filter_results(servers, filter_by)
labels = ('id', 'name', 'owner', 'flavor', 'image', 'state',
'backend')
columns = (3, 12, 20, 11, 12, 9, 40)
......
......@@ -41,6 +41,8 @@ from django.core.management import CommandError
from synnefo.db.models import Backend, VirtualMachine, Network, Flavor
from synnefo.api.util import get_image as backend_get_image
from synnefo.api.faults import ItemNotFound
from django.core.exceptions import FieldError
from synnefo.api.util import validate_network_size
from synnefo.settings import MAX_CIDR_BLOCK
......@@ -158,3 +160,44 @@ def get_flavor(flavor_id):
raise CommandError("Flavor with ID %s not found in DB."
" Use snf-manage flavor-list to find out"
" available flavor IDs." % flavor_id)
def filter_results(objects, filter_by):
filter_list = filter_by.split(",")
filter_dict = {}
exclude_dict = {}
def map_field_type(query):
def fix_bool(val):
if val.lower() in ("yes", "true", "t"):
return True
if val.lower() in ("no", "false", "f"):
return False
return val
if "!=" in query:
key, val = query.split("!=")
exclude_dict[key] = fix_bool(val)
return
OP_MAP = {
">=": "__gte",
"=>": "__gte",
">": "__gt",
"<=": "__lte",
"=<": "__lte",
"<": "__lt",
"=": ""
}
for op, new_op in OP_MAP.items():
if op in query:
key, val = query.split(op)
filter_dict[key + new_op] = fix_bool(val)
return
map(lambda x: map_field_type(x), filter_list)
try:
objects = objects.filter(**filter_dict)
return objects.exclude(**exclude_dict)
except FieldError as e:
raise CommandError(e)
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