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
            print
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
    print
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
    print
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
        print
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