Revision 8cdde414

b/tools/snf-admin
1
#!/usr/bin/env python
2

  
3
# Copyright 2011 GRNET S.A. All rights reserved.
4
# 
5
# Redistribution and use in source and binary forms, with or
6
# without modification, are permitted provided that the following
7
# conditions are met:
8
# 
9
#   1. Redistributions of source code must retain the above
10
#      copyright notice, this list of conditions and the following
11
#      disclaimer.
12
# 
13
#   2. Redistributions in binary form must reproduce the above
14
#      copyright notice, this list of conditions and the following
15
#      disclaimer in the documentation and/or other materials
16
#      provided with the distribution.
17
# 
18
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
# POSSIBILITY OF SUCH DAMAGE.
30
# 
31
# The views and conclusions contained in the software and
32
# documentation are those of the authors and should not be
33
# interpreted as representing official policies, either expressed
34
# or implied, of GRNET S.A.
35

  
36
from django.core.management import setup_environ
37
try:
38
    from synnefo import settings
39
except ImportError:
40
    raise Exception("Cannot import settings, make sure PYTHONPATH contains "
41
                    "the parent directory of the Synnefo Django project.")
42
setup_environ(settings)
43

  
44
import inspect
45
import logging
46
import sys
47

  
48
from collections import defaultdict
49
from optparse import OptionParser
50
from os.path import basename
51

  
52
from synnefo.db import models
53

  
54

  
55
def get_user(uid):
56
    try:
57
        uid = int(uid)
58
        return models.SynnefoUser.objects.get(id=uid)
59
        servers = servers.filter(owner=user)
60
    except ValueError:
61
        return None
62
    except models.SynnefoUser.DoesNotExist:
63
        return None
64

  
65
def print_dict(d, exclude=()):
66
    margin = max(len(key) for key in d) + 1
67

  
68
    for key, val in sorted(d.items()):
69
        if key in exclude:
70
            continue
71
        print '%s: %s' % (key.rjust(margin), val)
72

  
73
def print_items(items, detail=False):
74
    for item in items:
75
        print '%d %s' % (item.id, item.name)
76
        if detail:
77
            print_dict(item.__dict__, exclude=('id', 'name', '_state'))
78
            print
79

  
80

  
81
class Command(object):
82
    category = ''
83
    name = ''
84
    syntax = ''
85
    description = ''
86
    
87
    def __init__(self, argv):
88
        parser = OptionParser()
89
        parser.usage = '%%prog %s %s %s' % (self.category, self.name,
90
                                            self.syntax)
91
        self.add_options(parser)
92
        options, self.args = parser.parse_args(argv)
93
        
94
        # Add options to self
95
        for opt in parser.option_list:
96
            key = opt.dest
97
            if key:
98
                val = getattr(options, key)
99
                setattr(self, key, val)
100
        
101
        ch = logging.StreamHandler()
102
        ch.setFormatter(logging.Formatter('%(message)s'))
103
        logger = logging.getLogger()
104
        logger.addHandler(ch)
105
        level = logging.WARNING
106
        logger.setLevel(level)
107
        
108
        self.parser = parser
109
    
110
    def add_options(self, parser):
111
        pass
112
    
113
    def execute(self):
114
        try:
115
            self.main(*self.args)
116
        except TypeError:
117
            self.parser.print_help()
118

  
119

  
120
class ListServers(Command):
121
    category = 'server'
122
    name = 'ls'
123
    syntax = '[server id]'
124
    description = 'list servers'
125
    
126
    def add_options(self, parser):
127
        parser.add_option('-a', action='store_true', dest='show_deleted',
128
                        default=False, help='also list deleted servers')
129
        parser.add_option('-l', action='store_true', dest='detail',
130
                        default=False, help='show detailed output')
131
        parser.add_option('-u', dest='uid', metavar='UID',
132
                            help='show servers of user with id UID')
133
    
134
    def main(self, server_id=None):
135
        servers = models.VirtualMachine.objects.order_by('id')
136
        if server_id:
137
            servers = servers.filter(id=server_id)
138
        if not self.show_deleted:
139
            servers = servers.filter(deleted=False)
140
        if self.uid:
141
            user = get_user(self.uid)
142
            if user:
143
                servers = servers.filter(owner=user)
144
            else:
145
                print 'Unknown user id'
146
                return
147
        
148
        print_items(servers, self.detail)
149

  
150

  
151
class ListUsers(Command):
152
    category = 'user'
153
    name = 'ls'
154
    syntax = '[user id]'
155
    description = 'list users'
156
    
157
    def add_options(self, parser):
158
        parser.add_option('-l', action='store_true', dest='detail',
159
                        default=False, help='show detailed output')
160
    
161
    def main(self, user_id=None):
162
        if user_id:
163
            users = [models.SynnefoUser.objects.get(id=user_id)]
164
        else:
165
            users = models.SynnefoUser.objects.order_by('id')
166
        print_items(users, self.detail)
167

  
168

  
169
class ListImages(Command):
170
    category = 'image'
171
    name = 'ls'
172
    syntax = '[image id]'
173
    description = 'list images'
174
    
175
    def add_options(self, parser):
176
        parser.add_option('-l', action='store_true', dest='detail',
177
                        default=False, help='show detailed output')
178
    
179
    def main(self, image_id=None):
180
        if image_id:
181
            images = [models.Image.objects.get(id=image_id)]
182
        else:
183
            images = models.Image.objects.order_by('id')
184
        print_items(images, self.detail)
185

  
186

  
187
class RegisterImage(Command):
188
    category = 'image'
189
    name = 'register'
190
    syntax = '<name> <backend id>'
191
    description = 'register an image'
192
    
193
    def add_options(self, parser):
194
        parser.add_option('-p', action='store_true', dest='public',
195
                            default=False, help='make image public')
196
        parser.add_option('-u', dest='uid', metavar='UID',
197
                            help='assign image to user with id UID')
198
    
199
    def main(self, name, backend_id):
200
        user = None
201
        if self.uid:
202
            user = get_user(self.uid)
203
            if not user:
204
                print 'Unknown user id'
205
                return
206
        
207
        image = models.Image.objects.create(
208
            name=name,
209
            state='ACTIVE',
210
            owner=user,
211
            backend_id=backend_id,
212
            public=self.public)
213

  
214

  
215
class ModifyImage(Command):
216
    category = 'image'
217
    name = 'modify'
218
    syntax = '<image id>'
219
    description = 'modify an image'
220
    
221
    def add_options(self, parser):
222
        parser.add_option('-b', dest='backend_id', metavar='BACKEND_ID',
223
                            help='set image backend id')
224
        parser.add_option('-f', dest='format', metavar='FORMAT',
225
                            help='set image format')
226
        parser.add_option('-n', dest='name', metavar='NAME',
227
                            help='set image name')
228
        parser.add_option('-p', action='store_true', dest='public',
229
                            default=False, help='make image public')
230
        parser.add_option('-r', action='store_true', dest='private',
231
                            default=False, help='make image private')
232
        parser.add_option('-s', dest='state', metavar='STATE',
233
                            default=False, help='set image state')
234
        parser.add_option('-u', dest='uid', metavar='UID',
235
                            help='assign image to user with id UID')
236
    
237
    def main(self, image_id):
238
        try:
239
            image = models.Image.objects.get(id=image_id)
240
        except:
241
            print 'Image not found'
242
            return
243
        
244
        if self.backend_id:
245
            image.backend_id = self.backend_id
246
        if self.format:
247
            image.format = format
248
        if self.name:
249
            image.name = self.name
250
        if self.public:
251
            image.public = True
252
        if self.private:
253
            image.public = False
254
        if self.state:
255
            image.state = self.state
256
        if self.uid:
257
            image.owner = get_user(self.uid)
258
        
259
        image.save()
260

  
261

  
262
def print_categories(exe, categories):
263
    print 'Usage: %s <category> <command>' % exe
264
    print
265
    print 'Categories:'
266
    for category in sorted(categories):
267
        print '  %s' % category
268

  
269
def print_commands(exe, commands):
270
    print 'Usage: %s <command>' % exe
271
    print
272
    print 'Commands:'
273
    for command, cls in sorted(commands.items()):
274
        print '  %s %s' % (command.ljust(10), cls.description)
275

  
276

  
277
def main():
278
    categories = defaultdict(dict)
279
    module = sys.modules[__name__]
280
    for name, cls in inspect.getmembers(module, inspect.isclass):
281
        if issubclass(cls, Command) and cls != Command:
282
            categories[cls.category][cls.name] = cls
283
    
284
    argv = list(sys.argv)
285
    exe = basename(argv.pop(0))
286
    snf, sep, rest = exe.partition('-')
287
    if snf == 'snf' and sep and rest != 'admin':
288
        category = rest
289
        if category not in categories:
290
            print 'Invalid alias'
291
            sys.exit(1)
292
    else:
293
        category = argv.pop(0) if argv else None
294
        if category:
295
            exe = '%s %s' % (exe, category)
296
    
297
    if not category or category not in categories:
298
        print_categories(exe, categories)
299
        sys.exit(1)
300
    
301
    command = argv.pop(0) if argv else None
302
    
303
    if not command or command not in categories[category]:
304
        print_commands(exe, categories[category])
305
        sys.exit(1)
306
    
307
    cls = categories[category][command]
308
    cmd = cls(argv)
309
    cmd.execute()
310

  
311

  
312
if __name__ == '__main__':
313
    main()
b/tools/snf-image
1
snf-admin
b/tools/snf-server
1
snf-admin
b/tools/snf-user
1
snf-admin

Also available in: Unified diff