Revision b0e7f310 snf-cyclades-app/synnefo/api/management/commands/server-list.py
b/snf-cyclades-app/synnefo/api/management/commands/server-list.py | ||
---|---|---|
1 |
# Copyright 2012 GRNET S.A. All rights reserved. |
|
1 |
# Copyright 2012-2013 GRNET S.A. All rights reserved.
|
|
2 | 2 |
# |
3 | 3 |
# Redistribution and use in source and binary forms, with or |
4 | 4 |
# without modification, are permitted provided that the following |
... | ... | |
33 | 33 |
|
34 | 34 |
from optparse import make_option |
35 | 35 |
|
36 |
from django.core.management.base import BaseCommand, CommandError |
|
37 |
from synnefo.management.common import (format_vm_state, get_backend, Omit, |
|
38 |
filter_results, pprint_table, UserCache) |
|
39 |
from synnefo.api.util import get_image |
|
36 |
from synnefo.webproject.management.commands import ListCommand |
|
40 | 37 |
from synnefo.db.models import VirtualMachine |
38 |
from synnefo.management.common import get_backend |
|
39 |
from synnefo.api.util import get_image |
|
41 | 40 |
|
42 |
import logging |
|
43 |
log = logging.getLogger(__name__) |
|
44 |
|
|
45 |
FIELDS = VirtualMachine._meta.get_all_field_names() |
|
41 |
from logging import getLogger |
|
42 |
log = getLogger(__name__) |
|
46 | 43 |
|
47 | 44 |
|
48 |
class Command(BaseCommand):
|
|
45 |
class Command(ListCommand):
|
|
49 | 46 |
help = "List servers" |
50 | 47 |
|
51 |
option_list = BaseCommand.option_list + ( |
|
52 |
make_option( |
|
53 |
'-c', |
|
54 |
action='store_true', |
|
55 |
dest='csv', |
|
56 |
default=False, |
|
57 |
help="Use pipes to separate values"), |
|
48 |
option_list = ListCommand.option_list + ( |
|
58 | 49 |
make_option( |
59 | 50 |
'--suspended', |
60 | 51 |
action='store_true', |
... | ... | |
62 | 53 |
default=False, |
63 | 54 |
help="List only suspended servers"), |
64 | 55 |
make_option( |
65 |
'--build', |
|
66 |
action='store_true', |
|
67 |
dest='build', |
|
68 |
default=False, |
|
69 |
help="List only servers in the building state"), |
|
70 |
make_option( |
|
71 |
'--deleted', |
|
72 |
action='store_true', |
|
73 |
dest='deleted', |
|
74 |
default=False, |
|
75 |
help="Include deleted servers"), |
|
76 |
make_option( |
|
77 | 56 |
'--backend-id', |
78 | 57 |
dest='backend_id', |
79 | 58 |
help="List only servers of the specified backend"), |
80 | 59 |
make_option( |
81 |
'--user', |
|
82 |
dest='user', |
|
83 |
help="List only servers of the specified user (uuid or email)"), |
|
84 |
make_option( |
|
85 |
'--filter-by', |
|
86 |
dest='filter_by', |
|
87 |
help="Filter results. Comma seperated list of key `cond` val pairs" |
|
88 |
" that displayed entries must satisfy. e.g." |
|
89 |
" --filter-by \"operstate=STARTED,id>=22\"." |
|
90 |
" Available keys are: %s" % ", ".join(FIELDS)), |
|
60 |
"--build", |
|
61 |
action="store_true", |
|
62 |
dest="build", |
|
63 |
default=False, |
|
64 |
help="List only servers in the building state"), |
|
91 | 65 |
make_option( |
92 |
'--displayname',
|
|
93 |
action='store_true',
|
|
94 |
dest='displayname',
|
|
66 |
"--image-name",
|
|
67 |
action="store_true",
|
|
68 |
dest="image_name",
|
|
95 | 69 |
default=False, |
96 |
help="Display both uuid and display name"),
|
|
70 |
help="Display image name instead of image ID"),
|
|
97 | 71 |
) |
98 | 72 |
|
99 |
def handle(self, *args, **options):
|
|
100 |
if args:
|
|
101 |
raise CommandError("Command doesn't accept any arguments")
|
|
73 |
object_class = VirtualMachine
|
|
74 |
deleted_field = "deleted"
|
|
75 |
user_uuid_field = "userid"
|
|
102 | 76 |
|
103 |
ucache = UserCache() |
|
104 |
|
|
105 |
if options['backend_id']: |
|
106 |
backend = get_backend(options['backend_id']) |
|
107 |
servers = backend.virtual_machines |
|
108 |
else: |
|
109 |
servers = VirtualMachine.objects |
|
77 |
def get_public_ip(vm): |
|
78 |
try: |
|
79 |
return vm.nics.all()[0].ipv4 |
|
80 |
except IndexError: |
|
81 |
return None |
|
110 | 82 |
|
111 |
if options['deleted']: |
|
112 |
servers = servers.all() |
|
83 |
def format_vm_state(vm): |
|
84 |
if vm.operstate == "BUILD": |
|
85 |
return "BUILD(" + str(vm.buildpercentage) + "%)" |
|
113 | 86 |
else: |
114 |
servers = servers.filter(deleted=False) |
|
115 |
|
|
116 |
if options['suspended']: |
|
117 |
servers = servers.filter(suspended=True) |
|
118 |
|
|
119 |
if options['build']: |
|
120 |
servers = servers.filter(operstate='BUILD') |
|
121 |
|
|
122 |
user = options['user'] |
|
123 |
if user: |
|
124 |
if '@' in user: |
|
125 |
user = ucache.get_uuid(user) |
|
126 |
servers = servers.filter(userid=user) |
|
127 |
|
|
128 |
filter_by = options['filter_by'] |
|
129 |
if filter_by: |
|
130 |
servers = filter_results(servers, filter_by) |
|
131 |
|
|
132 |
displayname = options['displayname'] |
|
133 |
|
|
134 |
cache = ImageCache() |
|
135 |
|
|
136 |
headers = filter(lambda x: x is not Omit, |
|
137 |
['id', |
|
138 |
'name', |
|
139 |
'owner_uuid', |
|
140 |
'owner_name' if displayname else Omit, |
|
141 |
'flavor', |
|
142 |
'image', |
|
143 |
'state', |
|
144 |
'backend', |
|
145 |
]) |
|
146 |
|
|
147 |
if displayname: |
|
148 |
uuids = list(set([server.userid for server in servers])) |
|
149 |
ucache.fetch_names(uuids) |
|
150 |
|
|
151 |
table = [] |
|
152 |
for server in servers.order_by('id'): |
|
153 |
try: |
|
154 |
name = server.name.decode('utf8') |
|
155 |
except UnicodeEncodeError: |
|
156 |
name = server.name |
|
157 |
|
|
158 |
flavor = server.flavor.name |
|
159 |
|
|
160 |
image = cache.get_image(server.imageid, server.userid) |
|
161 |
|
|
162 |
state = format_vm_state(server) |
|
163 |
|
|
164 |
uuid = server.userid |
|
165 |
if displayname: |
|
166 |
dname = ucache.get_name(server.userid) |
|
167 |
|
|
168 |
fields = filter(lambda x: x is not Omit, |
|
169 |
[str(server.id), |
|
170 |
name, |
|
171 |
uuid, |
|
172 |
dname if displayname else Omit, |
|
173 |
flavor, |
|
174 |
image, |
|
175 |
state, |
|
176 |
str(server.backend), |
|
177 |
]) |
|
178 |
table.append(fields) |
|
179 |
|
|
180 |
separator = " | " if options['csv'] else None |
|
181 |
pprint_table(self.stdout, table, headers, separator) |
|
87 |
return vm.operstate |
|
88 |
|
|
89 |
FIELDS = { |
|
90 |
"id": ("id", "ID of the server"), |
|
91 |
"name": ("name", "Name of the server"), |
|
92 |
"user.uuid": ("userid", "The UUID of the server's owner"), |
|
93 |
"flavor": ("flavor.name", "The name of the server's flavor"), |
|
94 |
"backend": ("backend", "The Ganeti backend that hosts the VM"), |
|
95 |
"image.id": ("imageid", "The ID of the server's image"), |
|
96 |
"image.name": ("image", "The name of the server's image"), |
|
97 |
"state": (format_vm_state, "The current state of the server"), |
|
98 |
"ip": (get_public_ip, "The public IP of the server"), |
|
99 |
"created": ("created", "The date the server was created"), |
|
100 |
"deleted": ("deleted", "Whether the server is deleted or not"), |
|
101 |
"suspended": ("suspended", "Whether the server is administratively" |
|
102 |
" suspended"), |
|
103 |
} |
|
104 |
|
|
105 |
fields = ["id", "name", "user.uuid", "state", "flavor", "image.id", |
|
106 |
"backend"] |
|
107 |
|
|
108 |
def handle_args(self, *args, **options): |
|
109 |
if options["suspended"]: |
|
110 |
self.filters["suspended"] = True |
|
111 |
|
|
112 |
if options["backend_id"]: |
|
113 |
backend = get_backend(options["backend_id"]) |
|
114 |
self.filters["backend"] = backend.id |
|
115 |
|
|
116 |
if options["build"]: |
|
117 |
self.filters["operstate"] = "BUILD" |
|
118 |
|
|
119 |
if options["image_name"]: |
|
120 |
self.fields.replace("image.id", "image.name") |
|
121 |
|
|
122 |
def handle_db_objects(self, rows, *args, **kwargs): |
|
123 |
icache = ImageCache() |
|
124 |
for vm in rows: |
|
125 |
vm.image = icache.get_image(vm.imageid, vm.userid) |
|
182 | 126 |
|
183 | 127 |
|
184 | 128 |
class ImageCache(object): |
Also available in: Unified diff