Revision 9a60dacb
b/tools/snf-admin | ||
---|---|---|
68 | 68 |
margin = max(len(key) for key in d) + 1 |
69 | 69 |
|
70 | 70 |
for key, val in sorted(d.items()): |
71 |
if key in exclude: |
|
71 |
if key in exclude or key.startswith('_'):
|
|
72 | 72 |
continue |
73 | 73 |
print '%s: %s' % (key.rjust(margin), val) |
74 | 74 |
|
... | ... | |
76 | 76 |
for item in items: |
77 | 77 |
print '%d %s' % (item.id, item.name) |
78 | 78 |
if detail: |
79 |
print_dict(item.__dict__, exclude=('id', 'name', '_state'))
|
|
79 |
print_dict(item.__dict__, exclude=('id', 'name')) |
|
80 | 80 |
|
81 | 81 |
|
82 | 82 |
|
83 | 83 |
class Command(object): |
84 |
category = ''
|
|
85 |
name = '' |
|
84 |
group = '<group>'
|
|
85 |
name = '<command>'
|
|
86 | 86 |
syntax = '' |
87 | 87 |
description = '' |
88 | 88 |
|
89 |
def __init__(self, argv): |
|
89 |
def __init__(self, exe, argv):
|
|
90 | 90 |
parser = OptionParser() |
91 |
parser.usage = '%%prog %s %s %s' % (self.category, self.name, |
|
92 |
self.syntax) |
|
91 |
syntax = '%s [options]' % self.syntax if self.syntax else '[options]' |
|
92 |
parser.usage = '%s %s %s' % (exe, self.name, syntax) |
|
93 |
parser.description = self.description |
|
93 | 94 |
self.add_options(parser) |
94 | 95 |
options, self.args = parser.parse_args(argv) |
95 | 96 |
|
... | ... | |
120 | 121 |
|
121 | 122 |
|
122 | 123 |
class ListServers(Command): |
123 |
category = 'server'
|
|
124 |
group = 'server'
|
|
124 | 125 |
name = 'list' |
125 | 126 |
syntax = '[server id]' |
126 | 127 |
description = 'list servers' |
... | ... | |
151 | 152 |
|
152 | 153 |
|
153 | 154 |
class ListUsers(Command): |
154 |
category = 'user'
|
|
155 |
group = 'user'
|
|
155 | 156 |
name = 'list' |
156 | 157 |
syntax = '[user id]' |
157 | 158 |
description = 'list users' |
... | ... | |
169 | 170 |
|
170 | 171 |
|
171 | 172 |
class ListImages(Command): |
172 |
category = 'image'
|
|
173 |
group = 'image'
|
|
173 | 174 |
name = 'list' |
174 | 175 |
syntax = '[image id]' |
175 | 176 |
description = 'list images' |
... | ... | |
187 | 188 |
|
188 | 189 |
|
189 | 190 |
class RegisterImage(Command): |
190 |
category = 'image'
|
|
191 |
group = 'image'
|
|
191 | 192 |
name = 'register' |
192 | 193 |
syntax = '<name> <backend id>' |
193 | 194 |
description = 'register an image' |
... | ... | |
212 | 213 |
owner=user, |
213 | 214 |
backend_id=backend_id, |
214 | 215 |
public=self.public) |
216 |
|
|
217 |
print_items([image], detail=True) |
|
215 | 218 |
|
216 | 219 |
|
217 | 220 |
class ModifyImage(Command): |
218 |
category = 'image'
|
|
221 |
group = 'image'
|
|
219 | 222 |
name = 'modify' |
220 | 223 |
syntax = '<image id>' |
221 | 224 |
description = 'modify an image' |
... | ... | |
262 | 265 |
|
263 | 266 |
|
264 | 267 |
class ModifyImageMeta(Command): |
265 |
category = 'image'
|
|
268 |
group = 'image'
|
|
266 | 269 |
name = 'meta' |
267 | 270 |
syntax = '<image id> [key[=val]]' |
268 | 271 |
description = 'get and manipulate image metadata' |
... | ... | |
306 | 309 |
meta.delete() |
307 | 310 |
|
308 | 311 |
|
309 |
def print_categories(exe, categories): |
|
310 |
print 'Usage: %s <category> <command> [args]' % exe |
|
311 |
|
|
312 |
print 'Categories:' |
|
313 |
for category in sorted(categories): |
|
314 |
print ' %s' % category |
|
312 |
def print_usage(exe, groups, group=None, shortcut=False): |
|
313 |
nop = Command(exe, []) |
|
314 |
nop.parser.print_help() |
|
315 |
if group: |
|
316 |
groups = {group: groups[group]} |
|
315 | 317 |
|
316 |
def print_commands(exe, commands): |
|
317 |
print 'Usage: %s <command> [args]' % exe |
|
318 | 318 |
|
319 | 319 |
print 'Commands:' |
320 |
for command, cls in sorted(commands.items()): |
|
321 |
print ' %s %s' % (command.ljust(10), cls.description) |
|
320 |
|
|
321 |
for group, commands in sorted(groups.items()): |
|
322 |
for command, cls in sorted(commands.items()): |
|
323 |
name = ' %s %s' % (group, command) |
|
324 |
print '%s %s' % (name.ljust(22), cls.description) |
|
325 |
|
|
322 | 326 |
|
323 | 327 |
|
324 | 328 |
def main(): |
325 |
categories = defaultdict(dict)
|
|
329 |
groups = defaultdict(dict)
|
|
326 | 330 |
module = sys.modules[__name__] |
327 | 331 |
for name, cls in inspect.getmembers(module, inspect.isclass): |
328 |
if issubclass(cls, Command) and cls != Command: |
|
329 |
categories[cls.category][cls.name] = cls |
|
332 |
if not issubclass(cls, Command) or cls == Command: |
|
333 |
continue |
|
334 |
groups[cls.group][cls.name] = cls |
|
330 | 335 |
|
331 | 336 |
argv = list(sys.argv) |
332 | 337 |
exe = basename(argv.pop(0)) |
333 |
snf, sep, rest = exe.partition('-') |
|
334 |
if snf == 'snf' and sep and rest != 'admin': |
|
335 |
category = rest |
|
336 |
if category not in categories: |
|
337 |
print 'Invalid alias' |
|
338 |
sys.exit(1) |
|
338 |
prefix, sep, suffix = exe.partition('-') |
|
339 |
if sep and prefix == 'snf' and suffix in groups: |
|
340 |
# Allow shortcut aliases like snf-image, snf-server, etc |
|
341 |
group = suffix |
|
339 | 342 |
else: |
340 |
category = argv.pop(0) if argv else None |
|
341 |
if category: |
|
342 |
exe = '%s %s' % (exe, category) |
|
343 |
|
|
344 |
if not category or category not in categories: |
|
345 |
print_categories(exe, categories) |
|
346 |
sys.exit(1) |
|
343 |
group = argv.pop(0) if argv else None |
|
344 |
if group in groups: |
|
345 |
exe = '%s %s' % (exe, group) |
|
346 |
else: |
|
347 |
exe = '%s <group>' % exe |
|
348 |
group = None |
|
347 | 349 |
|
348 | 350 |
command = argv.pop(0) if argv else None |
349 | 351 |
|
350 |
if not command or command not in categories[category]:
|
|
351 |
print_commands(exe, categories[category])
|
|
352 |
if group not in groups or command not in groups[group]:
|
|
353 |
print_usage(exe, groups, group)
|
|
352 | 354 |
sys.exit(1) |
353 | 355 |
|
354 |
cls = categories[category][command]
|
|
355 |
cmd = cls(argv) |
|
356 |
cls = groups[group][command]
|
|
357 |
cmd = cls(exe, argv)
|
|
356 | 358 |
cmd.execute() |
357 | 359 |
|
358 | 360 |
|
Also available in: Unified diff