Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / tools / admin.py @ 9c0ac5af

History | View | Annotate | Download (27.5 kB)

1 8cdde414 Giorgos Verigakis
#!/usr/bin/env python
2 8cdde414 Giorgos Verigakis
3 8cdde414 Giorgos Verigakis
# Copyright 2011 GRNET S.A. All rights reserved.
4 8cdde414 Giorgos Verigakis
# 
5 8cdde414 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
6 8cdde414 Giorgos Verigakis
# without modification, are permitted provided that the following
7 8cdde414 Giorgos Verigakis
# conditions are met:
8 8cdde414 Giorgos Verigakis
# 
9 8cdde414 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
10 8cdde414 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
11 8cdde414 Giorgos Verigakis
#      disclaimer.
12 8cdde414 Giorgos Verigakis
# 
13 8cdde414 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
14 8cdde414 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
15 8cdde414 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
16 8cdde414 Giorgos Verigakis
#      provided with the distribution.
17 8cdde414 Giorgos Verigakis
# 
18 8cdde414 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 8cdde414 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 8cdde414 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 8cdde414 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 8cdde414 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 8cdde414 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 8cdde414 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 8cdde414 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 8cdde414 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 8cdde414 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 8cdde414 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 8cdde414 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
30 8cdde414 Giorgos Verigakis
# 
31 8cdde414 Giorgos Verigakis
# The views and conclusions contained in the software and
32 8cdde414 Giorgos Verigakis
# documentation are those of the authors and should not be
33 8cdde414 Giorgos Verigakis
# interpreted as representing official policies, either expressed
34 8cdde414 Giorgos Verigakis
# or implied, of GRNET S.A.
35 8cdde414 Giorgos Verigakis
36 8cdde414 Giorgos Verigakis
from django.core.management import setup_environ
37 8cdde414 Giorgos Verigakis
try:
38 8cdde414 Giorgos Verigakis
    from synnefo import settings
39 8cdde414 Giorgos Verigakis
except ImportError:
40 8cdde414 Giorgos Verigakis
    raise Exception("Cannot import settings, make sure PYTHONPATH contains "
41 8cdde414 Giorgos Verigakis
                    "the parent directory of the Synnefo Django project.")
42 8cdde414 Giorgos Verigakis
setup_environ(settings)
43 8cdde414 Giorgos Verigakis
44 8cdde414 Giorgos Verigakis
import inspect
45 8cdde414 Giorgos Verigakis
import sys
46 8cdde414 Giorgos Verigakis
47 8cdde414 Giorgos Verigakis
from collections import defaultdict
48 910f53d9 Giorgos Verigakis
from itertools import product
49 8cdde414 Giorgos Verigakis
from optparse import OptionParser
50 8cdde414 Giorgos Verigakis
from os.path import basename
51 8cdde414 Giorgos Verigakis
52 8cdde414 Giorgos Verigakis
from synnefo.db import models
53 06b7df28 Giorgos Verigakis
from synnefo.invitations.invitations import add_invitation, send_invitation
54 87c1dadc Giorgos Verigakis
from synnefo.logic import backend, users
55 5adfb622 Giorgos Verigakis
from synnefo.plankton.backend import ImageBackend
56 9e98ba3c Giorgos Verigakis
from synnefo.util.dictconfig import dictConfig
57 8cdde414 Giorgos Verigakis
58 8cdde414 Giorgos Verigakis
59 8cdde414 Giorgos Verigakis
def get_user(uid):
60 8cdde414 Giorgos Verigakis
    try:
61 8cdde414 Giorgos Verigakis
        uid = int(uid)
62 8cdde414 Giorgos Verigakis
        return models.SynnefoUser.objects.get(id=uid)
63 8cdde414 Giorgos Verigakis
    except ValueError:
64 8cdde414 Giorgos Verigakis
        return None
65 8cdde414 Giorgos Verigakis
    except models.SynnefoUser.DoesNotExist:
66 8cdde414 Giorgos Verigakis
        return None
67 8cdde414 Giorgos Verigakis
68 8cdde414 Giorgos Verigakis
def print_dict(d, exclude=()):
69 ca8f8081 Giorgos Verigakis
    if not d:
70 ca8f8081 Giorgos Verigakis
        return
71 8cdde414 Giorgos Verigakis
    margin = max(len(key) for key in d) + 1
72 8cdde414 Giorgos Verigakis
73 8cdde414 Giorgos Verigakis
    for key, val in sorted(d.items()):
74 9a60dacb Giorgos Verigakis
        if key in exclude or key.startswith('_'):
75 8cdde414 Giorgos Verigakis
            continue
76 8cdde414 Giorgos Verigakis
        print '%s: %s' % (key.rjust(margin), val)
77 8cdde414 Giorgos Verigakis
78 13d2b7f7 Giorgos Verigakis
def print_item(item):
79 ead18dbc Giorgos Verigakis
    name = getattr(item, 'name', '')
80 ead18dbc Giorgos Verigakis
    print '%d %s' % (item.id, name)
81 13d2b7f7 Giorgos Verigakis
    print_dict(item.__dict__, exclude=('id', 'name'))
82 13d2b7f7 Giorgos Verigakis
83 1d133009 Giorgos Verigakis
def print_items(items, detail=False, keys=None):
84 1d133009 Giorgos Verigakis
    keys = keys or ('id', 'name')
85 8cdde414 Giorgos Verigakis
    for item in items:
86 1d133009 Giorgos Verigakis
        for key in keys:
87 1d133009 Giorgos Verigakis
            print getattr(item, key),
88 1d133009 Giorgos Verigakis
        print
89 1d133009 Giorgos Verigakis
        
90 8cdde414 Giorgos Verigakis
        if detail:
91 1d133009 Giorgos Verigakis
            print_dict(item.__dict__, exclude=keys)
92 8cdde414 Giorgos Verigakis
            print
93 8cdde414 Giorgos Verigakis
94 8cdde414 Giorgos Verigakis
95 8cdde414 Giorgos Verigakis
class Command(object):
96 9a60dacb Giorgos Verigakis
    group = '<group>'
97 9a60dacb Giorgos Verigakis
    name = '<command>'
98 8cdde414 Giorgos Verigakis
    syntax = ''
99 8cdde414 Giorgos Verigakis
    description = ''
100 735f44fe Giorgos Verigakis
    hidden = False
101 8cdde414 Giorgos Verigakis
    
102 9a60dacb Giorgos Verigakis
    def __init__(self, exe, argv):
103 8cdde414 Giorgos Verigakis
        parser = OptionParser()
104 9a60dacb Giorgos Verigakis
        syntax = '%s [options]' % self.syntax if self.syntax else '[options]'
105 9a60dacb Giorgos Verigakis
        parser.usage = '%s %s %s' % (exe, self.name, syntax)
106 9a60dacb Giorgos Verigakis
        parser.description = self.description
107 8cdde414 Giorgos Verigakis
        self.add_options(parser)
108 8cdde414 Giorgos Verigakis
        options, self.args = parser.parse_args(argv)
109 8cdde414 Giorgos Verigakis
        
110 8cdde414 Giorgos Verigakis
        # Add options to self
111 8cdde414 Giorgos Verigakis
        for opt in parser.option_list:
112 8cdde414 Giorgos Verigakis
            key = opt.dest
113 8cdde414 Giorgos Verigakis
            if key:
114 8cdde414 Giorgos Verigakis
                val = getattr(options, key)
115 8cdde414 Giorgos Verigakis
                setattr(self, key, val)
116 8cdde414 Giorgos Verigakis
        
117 8cdde414 Giorgos Verigakis
        self.parser = parser
118 8cdde414 Giorgos Verigakis
    
119 8cdde414 Giorgos Verigakis
    def add_options(self, parser):
120 8cdde414 Giorgos Verigakis
        pass
121 8cdde414 Giorgos Verigakis
    
122 8cdde414 Giorgos Verigakis
    def execute(self):
123 8cdde414 Giorgos Verigakis
        try:
124 8cdde414 Giorgos Verigakis
            self.main(*self.args)
125 8cdde414 Giorgos Verigakis
        except TypeError:
126 8cdde414 Giorgos Verigakis
            self.parser.print_help()
127 8cdde414 Giorgos Verigakis
128 8cdde414 Giorgos Verigakis
129 13d2b7f7 Giorgos Verigakis
# Server commands
130 13d2b7f7 Giorgos Verigakis
131 8cdde414 Giorgos Verigakis
class ListServers(Command):
132 9a60dacb Giorgos Verigakis
    group = 'server'
133 ca8f8081 Giorgos Verigakis
    name = 'list'
134 8cdde414 Giorgos Verigakis
    syntax = '[server id]'
135 8cdde414 Giorgos Verigakis
    description = 'list servers'
136 8cdde414 Giorgos Verigakis
    
137 8cdde414 Giorgos Verigakis
    def add_options(self, parser):
138 8cdde414 Giorgos Verigakis
        parser.add_option('-a', action='store_true', dest='show_deleted',
139 8cdde414 Giorgos Verigakis
                        default=False, help='also list deleted servers')
140 8cdde414 Giorgos Verigakis
        parser.add_option('-l', action='store_true', dest='detail',
141 8cdde414 Giorgos Verigakis
                        default=False, help='show detailed output')
142 8cdde414 Giorgos Verigakis
        parser.add_option('-u', dest='uid', metavar='UID',
143 8cdde414 Giorgos Verigakis
                            help='show servers of user with id UID')
144 8cdde414 Giorgos Verigakis
    
145 8cdde414 Giorgos Verigakis
    def main(self, server_id=None):
146 8cdde414 Giorgos Verigakis
        if server_id:
147 79c33f4e Giorgos Verigakis
            servers = [models.VirtualMachine.objects.get(id=server_id)]
148 79c33f4e Giorgos Verigakis
        else:
149 79c33f4e Giorgos Verigakis
            servers = models.VirtualMachine.objects.order_by('id')
150 79c33f4e Giorgos Verigakis
            if not self.show_deleted:
151 79c33f4e Giorgos Verigakis
                servers = servers.exclude(deleted=True)
152 79c33f4e Giorgos Verigakis
            if self.uid:
153 79c33f4e Giorgos Verigakis
                user = get_user(self.uid)
154 79c33f4e Giorgos Verigakis
                if user:
155 79c33f4e Giorgos Verigakis
                    servers = servers.filter(owner=user)
156 79c33f4e Giorgos Verigakis
                else:
157 79c33f4e Giorgos Verigakis
                    print 'Unknown user id'
158 79c33f4e Giorgos Verigakis
                    return
159 8cdde414 Giorgos Verigakis
        
160 8cdde414 Giorgos Verigakis
        print_items(servers, self.detail)
161 8cdde414 Giorgos Verigakis
162 8cdde414 Giorgos Verigakis
163 13d2b7f7 Giorgos Verigakis
# User commands
164 13d2b7f7 Giorgos Verigakis
165 735f44fe Giorgos Verigakis
class CreateUser(Command):
166 735f44fe Giorgos Verigakis
    group = 'user'
167 735f44fe Giorgos Verigakis
    name = 'create'
168 06b7df28 Giorgos Verigakis
    syntax = '<username> <email>'
169 735f44fe Giorgos Verigakis
    description = 'create a user'
170 735f44fe Giorgos Verigakis
    
171 735f44fe Giorgos Verigakis
    def add_options(self, parser):
172 735f44fe Giorgos Verigakis
        parser.add_option('--realname', dest='realname', metavar='NAME',
173 735f44fe Giorgos Verigakis
                            help='set real name of user')
174 735f44fe Giorgos Verigakis
        parser.add_option('--type', dest='type', metavar='TYPE',
175 735f44fe Giorgos Verigakis
                            help='set user type')
176 735f44fe Giorgos Verigakis
    
177 06b7df28 Giorgos Verigakis
    def main(self, username, email):
178 22f79931 Giorgos Verigakis
        username = username.decode('utf8')
179 06b7df28 Giorgos Verigakis
        realname = self.realname or username
180 06b7df28 Giorgos Verigakis
        type = self.type or 'USER'
181 d1ceb341 Giorgos Verigakis
        types = [x[0] for x in models.SynnefoUser.ACCOUNT_TYPE]
182 d1ceb341 Giorgos Verigakis
        if type not in types:
183 d1ceb341 Giorgos Verigakis
            valid = ', '.join(types)
184 d1ceb341 Giorgos Verigakis
            print 'Invalid type. Must be one of:', valid
185 06b7df28 Giorgos Verigakis
            return
186 735f44fe Giorgos Verigakis
        
187 87c1dadc Giorgos Verigakis
        user = users._register_user(realname, username, email, type)
188 735f44fe Giorgos Verigakis
        print_item(user)
189 735f44fe Giorgos Verigakis
190 735f44fe Giorgos Verigakis
191 06b7df28 Giorgos Verigakis
class InviteUser(Command):
192 06b7df28 Giorgos Verigakis
    group = 'user'
193 06b7df28 Giorgos Verigakis
    name = 'invite'
194 06b7df28 Giorgos Verigakis
    syntax = '<inviter id> <invitee name> <invitee email>'
195 06b7df28 Giorgos Verigakis
    description = 'invite a user'
196 06b7df28 Giorgos Verigakis
    
197 06b7df28 Giorgos Verigakis
    def main(self, inviter_id, name, email):
198 22f79931 Giorgos Verigakis
        name = name.decode('utf8')
199 06b7df28 Giorgos Verigakis
        inviter = get_user(inviter_id)
200 06b7df28 Giorgos Verigakis
        inv = add_invitation(inviter, name, email)
201 06b7df28 Giorgos Verigakis
        send_invitation(inv)
202 735f44fe Giorgos Verigakis
203 735f44fe Giorgos Verigakis
204 8cdde414 Giorgos Verigakis
class ListUsers(Command):
205 9a60dacb Giorgos Verigakis
    group = 'user'
206 ca8f8081 Giorgos Verigakis
    name = 'list'
207 8cdde414 Giorgos Verigakis
    syntax = '[user id]'
208 8cdde414 Giorgos Verigakis
    description = 'list users'
209 8cdde414 Giorgos Verigakis
    
210 8cdde414 Giorgos Verigakis
    def add_options(self, parser):
211 79c33f4e Giorgos Verigakis
        parser.add_option('-a', action='store_true', dest='show_deleted',
212 79c33f4e Giorgos Verigakis
                        default=False, help='also list deleted users')
213 8cdde414 Giorgos Verigakis
        parser.add_option('-l', action='store_true', dest='detail',
214 8cdde414 Giorgos Verigakis
                        default=False, help='show detailed output')
215 8cdde414 Giorgos Verigakis
    
216 8cdde414 Giorgos Verigakis
    def main(self, user_id=None):
217 8cdde414 Giorgos Verigakis
        if user_id:
218 8cdde414 Giorgos Verigakis
            users = [models.SynnefoUser.objects.get(id=user_id)]
219 8cdde414 Giorgos Verigakis
        else:
220 79c33f4e Giorgos Verigakis
            users = models.SynnefoUser.objects.order_by('id')
221 79c33f4e Giorgos Verigakis
            if not self.show_deleted:
222 79c33f4e Giorgos Verigakis
                users = users.exclude(state='DELETED')
223 1d133009 Giorgos Verigakis
        print_items(users, self.detail, keys=('id', 'name', 'uniq'))
224 8cdde414 Giorgos Verigakis
225 8cdde414 Giorgos Verigakis
226 13d2b7f7 Giorgos Verigakis
class ModifyUser(Command):
227 13d2b7f7 Giorgos Verigakis
    group = 'user'
228 13d2b7f7 Giorgos Verigakis
    name = 'modify'
229 13d2b7f7 Giorgos Verigakis
    syntax = '<user id>'
230 13d2b7f7 Giorgos Verigakis
    description = 'modify a user'
231 13d2b7f7 Giorgos Verigakis
    
232 13d2b7f7 Giorgos Verigakis
    def add_options(self, parser):
233 d1ceb341 Giorgos Verigakis
        types = ', '.join(x[0] for x in models.SynnefoUser.ACCOUNT_TYPE)
234 870c24a0 Giorgos Verigakis
        states = ', '.join(x[0] for x in models.SynnefoUser.ACCOUNT_STATE)
235 d1ceb341 Giorgos Verigakis
        
236 13d2b7f7 Giorgos Verigakis
        parser.add_option('--credit', dest='credit', metavar='VALUE',
237 13d2b7f7 Giorgos Verigakis
                            help='set user credits')
238 13d2b7f7 Giorgos Verigakis
        parser.add_option('--invitations', dest='invitations',
239 13d2b7f7 Giorgos Verigakis
                            metavar='VALUE', help='set max invitations')
240 13d2b7f7 Giorgos Verigakis
        parser.add_option('--realname', dest='realname', metavar='NAME',
241 13d2b7f7 Giorgos Verigakis
                            help='set real name of user')
242 13d2b7f7 Giorgos Verigakis
        parser.add_option('--type', dest='type', metavar='TYPE',
243 d1ceb341 Giorgos Verigakis
                            help='set user type (%s)' % types)
244 870c24a0 Giorgos Verigakis
        parser.add_option('--state', dest='state', metavar='STATE',
245 870c24a0 Giorgos Verigakis
                            help='set user state (%s)' % states)
246 735f44fe Giorgos Verigakis
        parser.add_option('--uniq', dest='uniq', metavar='ID',
247 735f44fe Giorgos Verigakis
                            help='set external unique ID')
248 13d2b7f7 Giorgos Verigakis
        parser.add_option('--username', dest='username', metavar='NAME',
249 13d2b7f7 Giorgos Verigakis
                            help='set username')
250 13d2b7f7 Giorgos Verigakis
    
251 13d2b7f7 Giorgos Verigakis
    def main(self, user_id):
252 13d2b7f7 Giorgos Verigakis
        user = get_user(user_id)
253 13d2b7f7 Giorgos Verigakis
        
254 13d2b7f7 Giorgos Verigakis
        if self.credit:
255 13d2b7f7 Giorgos Verigakis
            user.credit = self.credit
256 13d2b7f7 Giorgos Verigakis
        if self.invitations:
257 13d2b7f7 Giorgos Verigakis
            user.max_invitations = self.invitations
258 13d2b7f7 Giorgos Verigakis
        if self.realname:
259 13d2b7f7 Giorgos Verigakis
            user.realname = self.realname
260 13d2b7f7 Giorgos Verigakis
        if self.type:
261 13d2b7f7 Giorgos Verigakis
            allowed = [x[0] for x in models.SynnefoUser.ACCOUNT_TYPE]
262 13d2b7f7 Giorgos Verigakis
            if self.type not in allowed:
263 d1ceb341 Giorgos Verigakis
                valid = ', '.join(allowed)
264 d1ceb341 Giorgos Verigakis
                print 'Invalid type. Must be one of:', valid
265 13d2b7f7 Giorgos Verigakis
                return
266 13d2b7f7 Giorgos Verigakis
            user.type = self.type
267 870c24a0 Giorgos Verigakis
        if self.state:
268 870c24a0 Giorgos Verigakis
            allowed = [x[0] for x in models.SynnefoUser.ACCOUNT_STATE]
269 870c24a0 Giorgos Verigakis
            if self.state not in allowed:
270 870c24a0 Giorgos Verigakis
                valid = ', '.join(allowed)
271 870c24a0 Giorgos Verigakis
                print 'Invalid state. Must be one of:', valid
272 870c24a0 Giorgos Verigakis
                return
273 870c24a0 Giorgos Verigakis
            user.state = self.state
274 735f44fe Giorgos Verigakis
        if self.uniq:
275 735f44fe Giorgos Verigakis
            user.uniq = self.uniq
276 13d2b7f7 Giorgos Verigakis
        if self.username:
277 13d2b7f7 Giorgos Verigakis
            user.name = self.username
278 13d2b7f7 Giorgos Verigakis
        
279 13d2b7f7 Giorgos Verigakis
        user.save()
280 13d2b7f7 Giorgos Verigakis
        print_item(user)
281 13d2b7f7 Giorgos Verigakis
282 13d2b7f7 Giorgos Verigakis
283 13d2b7f7 Giorgos Verigakis
# Image commands
284 13d2b7f7 Giorgos Verigakis
285 8cdde414 Giorgos Verigakis
class ListImages(Command):
286 9a60dacb Giorgos Verigakis
    group = 'image'
287 ca8f8081 Giorgos Verigakis
    name = 'list'
288 8cdde414 Giorgos Verigakis
    syntax = '[image id]'
289 8cdde414 Giorgos Verigakis
    description = 'list images'
290 8cdde414 Giorgos Verigakis
    
291 8cdde414 Giorgos Verigakis
    def add_options(self, parser):
292 79c33f4e Giorgos Verigakis
        parser.add_option('-a', action='store_true', dest='show_deleted',
293 5adfb622 Giorgos Verigakis
                default=False, help='also list deleted images')
294 8cdde414 Giorgos Verigakis
        parser.add_option('-l', action='store_true', dest='detail',
295 5adfb622 Giorgos Verigakis
                default=False, help='show detailed output')
296 5adfb622 Giorgos Verigakis
        parser.add_option('-p', action='store_true', dest='pithos',
297 5adfb622 Giorgos Verigakis
                default=False, help='show images stored in Pithos')
298 5adfb622 Giorgos Verigakis
        parser.add_option('--user', dest='user',
299 921355f8 Giorgos Verigakis
                default=settings.SYSTEM_IMAGES_OWNER,
300 5adfb622 Giorgos Verigakis
                metavar='USER',
301 5adfb622 Giorgos Verigakis
                help='list images accessible to USER')
302 8cdde414 Giorgos Verigakis
    
303 8cdde414 Giorgos Verigakis
    def main(self, image_id=None):
304 5adfb622 Giorgos Verigakis
        if self.pithos:
305 5adfb622 Giorgos Verigakis
            return self.main_pithos(image_id)
306 5adfb622 Giorgos Verigakis
        
307 8cdde414 Giorgos Verigakis
        if image_id:
308 8cdde414 Giorgos Verigakis
            images = [models.Image.objects.get(id=image_id)]
309 8cdde414 Giorgos Verigakis
        else:
310 8cdde414 Giorgos Verigakis
            images = models.Image.objects.order_by('id')
311 79c33f4e Giorgos Verigakis
            if not self.show_deleted:
312 79c33f4e Giorgos Verigakis
                images = images.exclude(state='DELETED')
313 8cdde414 Giorgos Verigakis
        print_items(images, self.detail)
314 5adfb622 Giorgos Verigakis
    
315 5adfb622 Giorgos Verigakis
    def main_pithos(self, image_id=None):
316 5adfb622 Giorgos Verigakis
        backend = ImageBackend(self.user)
317 5adfb622 Giorgos Verigakis
        if image_id:
318 5adfb622 Giorgos Verigakis
            images = [backend.get_meta(image_id)]
319 5adfb622 Giorgos Verigakis
        else:
320 5adfb622 Giorgos Verigakis
            images = backend.iter_shared()
321 5adfb622 Giorgos Verigakis
        
322 5adfb622 Giorgos Verigakis
        for image in images:
323 5adfb622 Giorgos Verigakis
            print image['id'], image['name']
324 5adfb622 Giorgos Verigakis
            if self.detail:
325 5adfb622 Giorgos Verigakis
                print_dict(image, exclude=('id',))
326 5adfb622 Giorgos Verigakis
                print
327 5adfb622 Giorgos Verigakis
        
328 5adfb622 Giorgos Verigakis
        backend.close()
329 8cdde414 Giorgos Verigakis
330 8cdde414 Giorgos Verigakis
331 8cdde414 Giorgos Verigakis
class RegisterImage(Command):
332 9a60dacb Giorgos Verigakis
    group = 'image'
333 8cdde414 Giorgos Verigakis
    name = 'register'
334 921355f8 Giorgos Verigakis
    syntax = '<name> <Backend ID or Pithos URL> <disk format>'
335 8cdde414 Giorgos Verigakis
    description = 'register an image'
336 8cdde414 Giorgos Verigakis
    
337 8cdde414 Giorgos Verigakis
    def add_options(self, parser):
338 330c7d80 Giorgos Verigakis
        parser.add_option('--meta', dest='meta', action='append',
339 921355f8 Giorgos Verigakis
                metavar='KEY=VAL',
340 921355f8 Giorgos Verigakis
                help='add metadata (can be used multiple times)')
341 ca8f8081 Giorgos Verigakis
        parser.add_option('--public', action='store_true', dest='public',
342 921355f8 Giorgos Verigakis
                default=False, help='make image public')
343 8cdde414 Giorgos Verigakis
        parser.add_option('-u', dest='uid', metavar='UID',
344 921355f8 Giorgos Verigakis
                help='assign image to user with id UID')
345 8cdde414 Giorgos Verigakis
    
346 d1ceb341 Giorgos Verigakis
    def main(self, name, backend_id, format):
347 921355f8 Giorgos Verigakis
        if backend_id.startswith('pithos://'):
348 921355f8 Giorgos Verigakis
            return self.main_pithos(name, backend_id, format)
349 921355f8 Giorgos Verigakis
        
350 d1ceb341 Giorgos Verigakis
        formats = [x[0] for x in models.Image.FORMATS]
351 d1ceb341 Giorgos Verigakis
        if format not in formats:
352 d1ceb341 Giorgos Verigakis
            valid = ', '.join(formats)
353 d1ceb341 Giorgos Verigakis
            print 'Invalid format. Must be one of:', valid
354 d1ceb341 Giorgos Verigakis
            return
355 d1ceb341 Giorgos Verigakis
        
356 8cdde414 Giorgos Verigakis
        user = None
357 8cdde414 Giorgos Verigakis
        if self.uid:
358 8cdde414 Giorgos Verigakis
            user = get_user(self.uid)
359 8cdde414 Giorgos Verigakis
            if not user:
360 8cdde414 Giorgos Verigakis
                print 'Unknown user id'
361 8cdde414 Giorgos Verigakis
                return
362 8cdde414 Giorgos Verigakis
        
363 8cdde414 Giorgos Verigakis
        image = models.Image.objects.create(
364 8cdde414 Giorgos Verigakis
            name=name,
365 8cdde414 Giorgos Verigakis
            state='ACTIVE',
366 8cdde414 Giorgos Verigakis
            owner=user,
367 8cdde414 Giorgos Verigakis
            backend_id=backend_id,
368 d1ceb341 Giorgos Verigakis
            format=format,
369 8cdde414 Giorgos Verigakis
            public=self.public)
370 9a60dacb Giorgos Verigakis
        
371 330c7d80 Giorgos Verigakis
        if self.meta:
372 330c7d80 Giorgos Verigakis
            for m in self.meta:
373 330c7d80 Giorgos Verigakis
                key, sep, val = m.partition('=')
374 330c7d80 Giorgos Verigakis
                if key and val:
375 bb41504d Giorgos Verigakis
                    image.metadata.create(meta_key=key, meta_value=val)
376 330c7d80 Giorgos Verigakis
                else:
377 330c7d80 Giorgos Verigakis
                    print 'WARNING: Ignoring meta', m
378 330c7d80 Giorgos Verigakis
        
379 13d2b7f7 Giorgos Verigakis
        print_item(image)
380 921355f8 Giorgos Verigakis
    
381 921355f8 Giorgos Verigakis
    def main_pithos(self, name, url, disk_format):
382 921355f8 Giorgos Verigakis
        if disk_format not in settings.ALLOWED_DISK_FORMATS:
383 921355f8 Giorgos Verigakis
            print 'Invalid disk format'
384 921355f8 Giorgos Verigakis
            return
385 921355f8 Giorgos Verigakis
        
386 921355f8 Giorgos Verigakis
        params = {
387 921355f8 Giorgos Verigakis
            'disk_format': disk_format,
388 921355f8 Giorgos Verigakis
            'is_public': self.public,
389 921355f8 Giorgos Verigakis
            'properties': {}}
390 921355f8 Giorgos Verigakis
        
391 921355f8 Giorgos Verigakis
        if self.meta:
392 921355f8 Giorgos Verigakis
            for m in self.meta:
393 921355f8 Giorgos Verigakis
                key, sep, val = m.partition('=')
394 921355f8 Giorgos Verigakis
                if key and val:
395 921355f8 Giorgos Verigakis
                    params['properties'][key] = val
396 921355f8 Giorgos Verigakis
                else:
397 921355f8 Giorgos Verigakis
                    print 'WARNING: Ignoring meta', m
398 921355f8 Giorgos Verigakis
        
399 921355f8 Giorgos Verigakis
        backend = ImageBackend(self.uid or settings.SYSTEM_IMAGES_OWNER)
400 921355f8 Giorgos Verigakis
        backend.register(name, url, params)
401 921355f8 Giorgos Verigakis
        backend.close()
402 8cdde414 Giorgos Verigakis
403 8cdde414 Giorgos Verigakis
404 5adfb622 Giorgos Verigakis
class UploadImage(Command):
405 5adfb622 Giorgos Verigakis
    group = 'image'
406 5adfb622 Giorgos Verigakis
    name = 'upload'
407 5adfb622 Giorgos Verigakis
    syntax = '<name> <path>'
408 5adfb622 Giorgos Verigakis
    description = 'upload an image'
409 5adfb622 Giorgos Verigakis
    
410 5adfb622 Giorgos Verigakis
    def add_options(self, parser):
411 5adfb622 Giorgos Verigakis
        container_formats = ', '.join(settings.ALLOWED_CONTAINER_FORMATS)
412 5adfb622 Giorgos Verigakis
        disk_formats = ', '.join(settings.ALLOWED_DISK_FORMATS)
413 5adfb622 Giorgos Verigakis
        
414 5adfb622 Giorgos Verigakis
        parser.add_option('--container-format', dest='container_format',
415 5adfb622 Giorgos Verigakis
                default=settings.DEFAULT_CONTAINER_FORMAT,
416 5adfb622 Giorgos Verigakis
                metavar='FORMAT',
417 5adfb622 Giorgos Verigakis
                help='set container format (%s)' % container_formats)
418 5adfb622 Giorgos Verigakis
        parser.add_option('--disk-format', dest='disk_format',
419 5adfb622 Giorgos Verigakis
                default=settings.DEFAULT_DISK_FORMAT,
420 5adfb622 Giorgos Verigakis
                metavar='FORMAT',
421 5adfb622 Giorgos Verigakis
                help='set disk format (%s)' % disk_formats)
422 5adfb622 Giorgos Verigakis
        parser.add_option('--meta', dest='meta', action='append',
423 5adfb622 Giorgos Verigakis
                metavar='KEY=VAL',
424 5adfb622 Giorgos Verigakis
                help='add metadata (can be used multiple times)')
425 5adfb622 Giorgos Verigakis
        parser.add_option('--owner', dest='owner',
426 921355f8 Giorgos Verigakis
                default=settings.SYSTEM_IMAGES_OWNER,
427 5adfb622 Giorgos Verigakis
                metavar='USER',
428 5adfb622 Giorgos Verigakis
                help='set owner to USER')
429 5adfb622 Giorgos Verigakis
        parser.add_option('--public', action='store_true', dest='public',
430 5adfb622 Giorgos Verigakis
                default=False,
431 5adfb622 Giorgos Verigakis
                help='make image public')
432 5adfb622 Giorgos Verigakis
    
433 5adfb622 Giorgos Verigakis
    def main(self, name, path):
434 5adfb622 Giorgos Verigakis
        backend = ImageBackend(self.owner)
435 5adfb622 Giorgos Verigakis
        
436 5adfb622 Giorgos Verigakis
        params = {
437 5adfb622 Giorgos Verigakis
            'container_format': self.container_format,
438 5adfb622 Giorgos Verigakis
            'disk_format': self.disk_format,
439 5adfb622 Giorgos Verigakis
            'is_public': self.public,
440 5adfb622 Giorgos Verigakis
            'filename': basename(path),
441 5adfb622 Giorgos Verigakis
            'properties': {}}
442 5adfb622 Giorgos Verigakis
        
443 5adfb622 Giorgos Verigakis
        if self.meta:
444 5adfb622 Giorgos Verigakis
            for m in self.meta:
445 5adfb622 Giorgos Verigakis
                key, sep, val = m.partition('=')
446 5adfb622 Giorgos Verigakis
                if key and val:
447 5adfb622 Giorgos Verigakis
                    params['properties'][key] = val
448 5adfb622 Giorgos Verigakis
                else:
449 5adfb622 Giorgos Verigakis
                    print 'WARNING: Ignoring meta', m
450 5adfb622 Giorgos Verigakis
        
451 5adfb622 Giorgos Verigakis
        with open(path) as f:
452 5adfb622 Giorgos Verigakis
            backend.put(name, f, params)
453 5adfb622 Giorgos Verigakis
        
454 5adfb622 Giorgos Verigakis
        backend.close()
455 5adfb622 Giorgos Verigakis
456 5adfb622 Giorgos Verigakis
457 5adfb622 Giorgos Verigakis
class UpdateImage(Command):
458 5adfb622 Giorgos Verigakis
    group = 'image'
459 5adfb622 Giorgos Verigakis
    name = 'update'
460 5adfb622 Giorgos Verigakis
    syntax = '<image id>'
461 5adfb622 Giorgos Verigakis
    description = 'update an image stored in Pithos'
462 5adfb622 Giorgos Verigakis
    
463 5adfb622 Giorgos Verigakis
    def add_options(self, parser):
464 5adfb622 Giorgos Verigakis
        container_formats = ', '.join(settings.ALLOWED_CONTAINER_FORMATS)
465 5adfb622 Giorgos Verigakis
        disk_formats = ', '.join(settings.ALLOWED_DISK_FORMATS)
466 5adfb622 Giorgos Verigakis
        
467 5adfb622 Giorgos Verigakis
        parser.add_option('--container-format', dest='container_format',
468 5adfb622 Giorgos Verigakis
                metavar='FORMAT',
469 5adfb622 Giorgos Verigakis
                help='set container format (%s)' % container_formats)
470 5adfb622 Giorgos Verigakis
        parser.add_option('--disk-format', dest='disk_format',
471 5adfb622 Giorgos Verigakis
                metavar='FORMAT',
472 5adfb622 Giorgos Verigakis
                help='set disk format (%s)' % disk_formats)
473 5adfb622 Giorgos Verigakis
        parser.add_option('--name', dest='name',
474 5adfb622 Giorgos Verigakis
                metavar='NAME',
475 5adfb622 Giorgos Verigakis
                help='set name to NAME')
476 5adfb622 Giorgos Verigakis
        parser.add_option('--private', action='store_true', dest='private',
477 5adfb622 Giorgos Verigakis
                help='make image private')
478 5adfb622 Giorgos Verigakis
        parser.add_option('--public', action='store_true', dest='public',
479 5adfb622 Giorgos Verigakis
                help='make image public')
480 5adfb622 Giorgos Verigakis
        parser.add_option('--user', dest='user',
481 921355f8 Giorgos Verigakis
                default=settings.SYSTEM_IMAGES_OWNER,
482 5adfb622 Giorgos Verigakis
                metavar='USER',
483 921355f8 Giorgos Verigakis
                help='connect as USER')
484 5adfb622 Giorgos Verigakis
    
485 5adfb622 Giorgos Verigakis
    def main(self, image_id):
486 5adfb622 Giorgos Verigakis
        backend = ImageBackend(self.user)
487 5adfb622 Giorgos Verigakis
        
488 5adfb622 Giorgos Verigakis
        image = backend.get_meta(image_id)
489 5adfb622 Giorgos Verigakis
        if not image:
490 5adfb622 Giorgos Verigakis
            print 'Image not found'
491 5adfb622 Giorgos Verigakis
            return
492 5adfb622 Giorgos Verigakis
        
493 5adfb622 Giorgos Verigakis
        params = {}
494 5adfb622 Giorgos Verigakis
        
495 5adfb622 Giorgos Verigakis
        if self.container_format:
496 5adfb622 Giorgos Verigakis
            if self.container_format not in settings.ALLOWED_CONTAINER_FORMATS:
497 5adfb622 Giorgos Verigakis
                print 'Invalid container format'
498 5adfb622 Giorgos Verigakis
                return
499 5adfb622 Giorgos Verigakis
            params['container_format'] = self.container_format
500 5adfb622 Giorgos Verigakis
        if self.disk_format:
501 5adfb622 Giorgos Verigakis
            if self.disk_format not in settings.ALLOWED_DISK_FORMATS:
502 5adfb622 Giorgos Verigakis
                print 'Invalid disk format'
503 5adfb622 Giorgos Verigakis
                return
504 5adfb622 Giorgos Verigakis
            params['disk_format'] = self.disk_format
505 5adfb622 Giorgos Verigakis
        if self.name:
506 5adfb622 Giorgos Verigakis
            params['name'] = self.name
507 5adfb622 Giorgos Verigakis
        if self.private:
508 5adfb622 Giorgos Verigakis
            params['is_public'] = False
509 5adfb622 Giorgos Verigakis
        if self.public:
510 5adfb622 Giorgos Verigakis
            params['is_public'] = True
511 5adfb622 Giorgos Verigakis
        
512 5adfb622 Giorgos Verigakis
        backend.update(image_id, params)
513 5adfb622 Giorgos Verigakis
        backend.close()
514 5adfb622 Giorgos Verigakis
515 5adfb622 Giorgos Verigakis
516 8cdde414 Giorgos Verigakis
class ModifyImage(Command):
517 9a60dacb Giorgos Verigakis
    group = 'image'
518 8cdde414 Giorgos Verigakis
    name = 'modify'
519 8cdde414 Giorgos Verigakis
    syntax = '<image id>'
520 8cdde414 Giorgos Verigakis
    description = 'modify an image'
521 8cdde414 Giorgos Verigakis
    
522 8cdde414 Giorgos Verigakis
    def add_options(self, parser):
523 d1ceb341 Giorgos Verigakis
        states = ', '.join(x[0] for x in models.Image.IMAGE_STATES)
524 d1ceb341 Giorgos Verigakis
        formats = ', '.join(x[0] for x in models.Image.FORMATS)
525 d1ceb341 Giorgos Verigakis
526 8cdde414 Giorgos Verigakis
        parser.add_option('-b', dest='backend_id', metavar='BACKEND_ID',
527 5adfb622 Giorgos Verigakis
                help='set image backend id')
528 8cdde414 Giorgos Verigakis
        parser.add_option('-f', dest='format', metavar='FORMAT',
529 5adfb622 Giorgos Verigakis
                help='set image format (%s)' % formats)
530 8cdde414 Giorgos Verigakis
        parser.add_option('-n', dest='name', metavar='NAME',
531 5adfb622 Giorgos Verigakis
                help='set image name')
532 ca8f8081 Giorgos Verigakis
        parser.add_option('--public', action='store_true', dest='public',
533 5adfb622 Giorgos Verigakis
                help='make image public')
534 ca8f8081 Giorgos Verigakis
        parser.add_option('--nopublic', action='store_true', dest='private',
535 5adfb622 Giorgos Verigakis
                help='make image private')
536 5adfb622 Giorgos Verigakis
        parser.add_option('-s', dest='state', metavar='STATE',
537 5adfb622 Giorgos Verigakis
                help='set image state (%s)' % states)
538 8cdde414 Giorgos Verigakis
        parser.add_option('-u', dest='uid', metavar='UID',
539 5adfb622 Giorgos Verigakis
                help='assign image to user with id UID')
540 8cdde414 Giorgos Verigakis
    
541 8cdde414 Giorgos Verigakis
    def main(self, image_id):
542 8cdde414 Giorgos Verigakis
        try:
543 8cdde414 Giorgos Verigakis
            image = models.Image.objects.get(id=image_id)
544 8cdde414 Giorgos Verigakis
        except:
545 8cdde414 Giorgos Verigakis
            print 'Image not found'
546 8cdde414 Giorgos Verigakis
            return
547 8cdde414 Giorgos Verigakis
        
548 8cdde414 Giorgos Verigakis
        if self.backend_id:
549 8cdde414 Giorgos Verigakis
            image.backend_id = self.backend_id
550 8cdde414 Giorgos Verigakis
        if self.format:
551 13d2b7f7 Giorgos Verigakis
            allowed = [x[0] for x in models.Image.FORMATS]
552 13d2b7f7 Giorgos Verigakis
            if self.format not in allowed:
553 d1ceb341 Giorgos Verigakis
                valid = ', '.join(allowed)
554 d1ceb341 Giorgos Verigakis
                print 'Invalid format. Must be one of:', valid
555 13d2b7f7 Giorgos Verigakis
                return
556 13d2b7f7 Giorgos Verigakis
            image.format = self.format
557 8cdde414 Giorgos Verigakis
        if self.name:
558 8cdde414 Giorgos Verigakis
            image.name = self.name
559 8cdde414 Giorgos Verigakis
        if self.public:
560 8cdde414 Giorgos Verigakis
            image.public = True
561 8cdde414 Giorgos Verigakis
        if self.private:
562 8cdde414 Giorgos Verigakis
            image.public = False
563 8cdde414 Giorgos Verigakis
        if self.state:
564 13d2b7f7 Giorgos Verigakis
            allowed = [x[0] for x in models.Image.IMAGE_STATES]
565 13d2b7f7 Giorgos Verigakis
            if self.state not in allowed:
566 d1ceb341 Giorgos Verigakis
                valid = ', '.join(allowed)
567 d1ceb341 Giorgos Verigakis
                print 'Invalid state. Must be one of:', valid
568 13d2b7f7 Giorgos Verigakis
                return
569 8cdde414 Giorgos Verigakis
            image.state = self.state
570 8cdde414 Giorgos Verigakis
        if self.uid:
571 8cdde414 Giorgos Verigakis
            image.owner = get_user(self.uid)
572 8cdde414 Giorgos Verigakis
        
573 8cdde414 Giorgos Verigakis
        image.save()
574 13d2b7f7 Giorgos Verigakis
        print_item(image)
575 8cdde414 Giorgos Verigakis
576 8cdde414 Giorgos Verigakis
577 ca8f8081 Giorgos Verigakis
class ModifyImageMeta(Command):
578 9a60dacb Giorgos Verigakis
    group = 'image'
579 ca8f8081 Giorgos Verigakis
    name = 'meta'
580 ca8f8081 Giorgos Verigakis
    syntax = '<image id> [key[=val]]'
581 ca8f8081 Giorgos Verigakis
    description = 'get and manipulate image metadata'
582 ca8f8081 Giorgos Verigakis
    
583 921355f8 Giorgos Verigakis
    def add_options(self, parser):
584 921355f8 Giorgos Verigakis
        parser.add_option('--user', dest='user',
585 921355f8 Giorgos Verigakis
                default=settings.SYSTEM_IMAGES_OWNER,
586 921355f8 Giorgos Verigakis
                metavar='USER',
587 921355f8 Giorgos Verigakis
                help='connect as USER')
588 921355f8 Giorgos Verigakis
589 ca8f8081 Giorgos Verigakis
    def main(self, image_id, arg=''):
590 921355f8 Giorgos Verigakis
        if not image_id.isdigit():
591 921355f8 Giorgos Verigakis
            return self.main_pithos(image_id, arg)
592 921355f8 Giorgos Verigakis
        
593 ca8f8081 Giorgos Verigakis
        try:
594 ca8f8081 Giorgos Verigakis
            image = models.Image.objects.get(id=image_id)
595 ca8f8081 Giorgos Verigakis
        except:
596 ca8f8081 Giorgos Verigakis
            print 'Image not found'
597 ca8f8081 Giorgos Verigakis
            return
598 ca8f8081 Giorgos Verigakis
        
599 ca8f8081 Giorgos Verigakis
        key, sep, val = arg.partition('=')
600 ca8f8081 Giorgos Verigakis
        if not sep:
601 ca8f8081 Giorgos Verigakis
            val = None
602 ca8f8081 Giorgos Verigakis
        
603 ca8f8081 Giorgos Verigakis
        if not key:
604 ca8f8081 Giorgos Verigakis
            metadata = {}
605 7cc3c7d9 Giorgos Verigakis
            for meta in image.metadata.order_by('meta_key'):
606 ca8f8081 Giorgos Verigakis
                metadata[meta.meta_key] = meta.meta_value
607 ca8f8081 Giorgos Verigakis
            print_dict(metadata)
608 ca8f8081 Giorgos Verigakis
            return
609 ca8f8081 Giorgos Verigakis
        
610 ca8f8081 Giorgos Verigakis
        try:
611 7cc3c7d9 Giorgos Verigakis
            meta = image.metadata.get(meta_key=key)
612 ca8f8081 Giorgos Verigakis
        except models.ImageMetadata.DoesNotExist:
613 ca8f8081 Giorgos Verigakis
            meta = None
614 ca8f8081 Giorgos Verigakis
        
615 ca8f8081 Giorgos Verigakis
        if val is None:
616 ca8f8081 Giorgos Verigakis
            if meta:
617 ca8f8081 Giorgos Verigakis
                print_dict({key: meta.meta_value})
618 ca8f8081 Giorgos Verigakis
            return
619 ca8f8081 Giorgos Verigakis
        
620 ca8f8081 Giorgos Verigakis
        if val:
621 ca8f8081 Giorgos Verigakis
            if not meta:
622 7cc3c7d9 Giorgos Verigakis
                meta = image.metadata.create(meta_key=key)
623 ca8f8081 Giorgos Verigakis
            meta.meta_value = val
624 ca8f8081 Giorgos Verigakis
            meta.save()
625 ca8f8081 Giorgos Verigakis
        else:
626 ca8f8081 Giorgos Verigakis
            # Delete if val is empty
627 ca8f8081 Giorgos Verigakis
            if meta:
628 ca8f8081 Giorgos Verigakis
                meta.delete()
629 921355f8 Giorgos Verigakis
    
630 921355f8 Giorgos Verigakis
    def main_pithos(self, image_id, arg=''):
631 921355f8 Giorgos Verigakis
        backend = ImageBackend(self.user)
632 921355f8 Giorgos Verigakis
                
633 921355f8 Giorgos Verigakis
        try:
634 921355f8 Giorgos Verigakis
            image = backend.get_meta(image_id)
635 921355f8 Giorgos Verigakis
            if not image:
636 921355f8 Giorgos Verigakis
                print 'Image not found'
637 921355f8 Giorgos Verigakis
                return
638 921355f8 Giorgos Verigakis
            
639 921355f8 Giorgos Verigakis
            key, sep, val = arg.partition('=')
640 921355f8 Giorgos Verigakis
            if not sep:
641 921355f8 Giorgos Verigakis
                val = None
642 921355f8 Giorgos Verigakis
            
643 921355f8 Giorgos Verigakis
            properties = image.get('properties', {})
644 921355f8 Giorgos Verigakis
            
645 921355f8 Giorgos Verigakis
            if not key:
646 921355f8 Giorgos Verigakis
                print_dict(properties)
647 921355f8 Giorgos Verigakis
                return
648 921355f8 Giorgos Verigakis
            
649 921355f8 Giorgos Verigakis
            if val is None:
650 921355f8 Giorgos Verigakis
                if key in properties:
651 921355f8 Giorgos Verigakis
                    print_dict({key: properties[key]})
652 921355f8 Giorgos Verigakis
                return
653 921355f8 Giorgos Verigakis
            
654 921355f8 Giorgos Verigakis
            if val:
655 921355f8 Giorgos Verigakis
                properties[key] = val        
656 921355f8 Giorgos Verigakis
                params = {'properties': properties}
657 921355f8 Giorgos Verigakis
                backend.update(image_id, params)
658 921355f8 Giorgos Verigakis
        finally:
659 921355f8 Giorgos Verigakis
            backend.close()
660 ca8f8081 Giorgos Verigakis
661 ca8f8081 Giorgos Verigakis
662 910f53d9 Giorgos Verigakis
# Flavor commands
663 910f53d9 Giorgos Verigakis
664 910f53d9 Giorgos Verigakis
class CreateFlavor(Command):
665 910f53d9 Giorgos Verigakis
    group = 'flavor'
666 910f53d9 Giorgos Verigakis
    name = 'create'
667 910f53d9 Giorgos Verigakis
    syntax = '<cpu>[,<cpu>,...] <ram>[,<ram>,...] <disk>[,<disk>,...]'
668 910f53d9 Giorgos Verigakis
    description = 'create one or more flavors'
669 910f53d9 Giorgos Verigakis
    
670 c909cbbd Giorgos Verigakis
    def add_options(self, parser):
671 c909cbbd Giorgos Verigakis
        disk_templates = ', '.join(t for t in settings.GANETI_DISK_TEMPLATES)
672 c909cbbd Giorgos Verigakis
        parser.add_option('--disk-template',
673 c909cbbd Giorgos Verigakis
            dest='disk_template',
674 c909cbbd Giorgos Verigakis
            metavar='TEMPLATE',
675 c909cbbd Giorgos Verigakis
            default=settings.DEFAULT_GANETI_DISK_TEMPLATE,
676 c909cbbd Giorgos Verigakis
            help='available disk templates: %s' % disk_templates)
677 c909cbbd Giorgos Verigakis
    
678 910f53d9 Giorgos Verigakis
    def main(self, cpu, ram, disk):
679 910f53d9 Giorgos Verigakis
        cpus = cpu.split(',')
680 910f53d9 Giorgos Verigakis
        rams = ram.split(',')
681 910f53d9 Giorgos Verigakis
        disks = disk.split(',')
682 910f53d9 Giorgos Verigakis
        
683 910f53d9 Giorgos Verigakis
        flavors = []
684 910f53d9 Giorgos Verigakis
        for cpu, ram, disk in product(cpus, rams, disks):
685 910f53d9 Giorgos Verigakis
            try:
686 910f53d9 Giorgos Verigakis
                flavors.append((int(cpu), int(ram), int(disk)))
687 910f53d9 Giorgos Verigakis
            except ValueError:
688 910f53d9 Giorgos Verigakis
                print 'Invalid values'
689 910f53d9 Giorgos Verigakis
                return
690 910f53d9 Giorgos Verigakis
        
691 910f53d9 Giorgos Verigakis
        created = []
692 c909cbbd Giorgos Verigakis
        
693 910f53d9 Giorgos Verigakis
        for cpu, ram, disk in flavors:
694 c909cbbd Giorgos Verigakis
            flavor = models.Flavor.objects.create(
695 c909cbbd Giorgos Verigakis
                cpu=cpu,
696 c909cbbd Giorgos Verigakis
                ram=ram,
697 c909cbbd Giorgos Verigakis
                disk=disk,
698 c909cbbd Giorgos Verigakis
                disk_template=self.disk_template)
699 910f53d9 Giorgos Verigakis
            created.append(flavor)
700 910f53d9 Giorgos Verigakis
        
701 910f53d9 Giorgos Verigakis
        print_items(created, detail=True)
702 910f53d9 Giorgos Verigakis
703 910f53d9 Giorgos Verigakis
704 910f53d9 Giorgos Verigakis
class DeleteFlavor(Command):
705 910f53d9 Giorgos Verigakis
    group = 'flavor'
706 910f53d9 Giorgos Verigakis
    name = 'delete'
707 910f53d9 Giorgos Verigakis
    syntax = '<flavor id> [<flavor id>] [...]'
708 910f53d9 Giorgos Verigakis
    description = 'delete one or more flavors'
709 910f53d9 Giorgos Verigakis
    
710 910f53d9 Giorgos Verigakis
    def main(self, *args):
711 910f53d9 Giorgos Verigakis
        if not args:
712 910f53d9 Giorgos Verigakis
            raise TypeError
713 910f53d9 Giorgos Verigakis
        for flavor_id in args:
714 910f53d9 Giorgos Verigakis
            flavor = models.Flavor.objects.get(id=int(flavor_id))
715 870c24a0 Giorgos Verigakis
            flavor.deleted = True
716 870c24a0 Giorgos Verigakis
            flavor.save()
717 910f53d9 Giorgos Verigakis
718 910f53d9 Giorgos Verigakis
719 910f53d9 Giorgos Verigakis
class ListFlavors(Command):
720 910f53d9 Giorgos Verigakis
    group = 'flavor'
721 910f53d9 Giorgos Verigakis
    name = 'list'
722 910f53d9 Giorgos Verigakis
    syntax = '[flavor id]'
723 910f53d9 Giorgos Verigakis
    description = 'list images'
724 910f53d9 Giorgos Verigakis
    
725 910f53d9 Giorgos Verigakis
    def add_options(self, parser):
726 79c33f4e Giorgos Verigakis
        parser.add_option('-a', action='store_true', dest='show_deleted',
727 79c33f4e Giorgos Verigakis
                default=False, help='also list deleted flavors')
728 910f53d9 Giorgos Verigakis
        parser.add_option('-l', action='store_true', dest='detail',
729 910f53d9 Giorgos Verigakis
                        default=False, help='show detailed output')
730 910f53d9 Giorgos Verigakis
    
731 910f53d9 Giorgos Verigakis
    def main(self, flavor_id=None):
732 910f53d9 Giorgos Verigakis
        if flavor_id:
733 910f53d9 Giorgos Verigakis
            flavors = [models.Flavor.objects.get(id=flavor_id)]
734 910f53d9 Giorgos Verigakis
        else:
735 79c33f4e Giorgos Verigakis
            flavors = models.Flavor.objects.order_by('id')
736 79c33f4e Giorgos Verigakis
            if not self.show_deleted:
737 79c33f4e Giorgos Verigakis
                flavors = flavors.exclude(deleted=True)
738 910f53d9 Giorgos Verigakis
        print_items(flavors, self.detail)
739 910f53d9 Giorgos Verigakis
740 910f53d9 Giorgos Verigakis
741 87c1dadc Giorgos Verigakis
class ShowStats(Command):
742 87c1dadc Giorgos Verigakis
    group = 'stats'
743 87c1dadc Giorgos Verigakis
    name = None
744 87c1dadc Giorgos Verigakis
    description = 'show statistics'
745 87c1dadc Giorgos Verigakis
746 87c1dadc Giorgos Verigakis
    def main(self):
747 87c1dadc Giorgos Verigakis
        stats = {}
748 87c1dadc Giorgos Verigakis
        stats['Users'] = models.SynnefoUser.objects.count()
749 87c1dadc Giorgos Verigakis
        stats['Images'] = models.Image.objects.exclude(state='DELETED').count()
750 87c1dadc Giorgos Verigakis
        stats['Flavors'] = models.Flavor.objects.count()
751 87c1dadc Giorgos Verigakis
        stats['VMs'] = models.VirtualMachine.objects.filter(deleted=False).count()
752 87c1dadc Giorgos Verigakis
        stats['Networks'] = models.Network.objects.exclude(state='DELETED').count()
753 87c1dadc Giorgos Verigakis
        stats['Invitations'] = models.Invitations.objects.count()
754 87c1dadc Giorgos Verigakis
        
755 87c1dadc Giorgos Verigakis
        stats['Ganeti Instances'] = len(backend.get_ganeti_instances())
756 87c1dadc Giorgos Verigakis
        stats['Ganeti Nodes'] = len(backend.get_ganeti_nodes())
757 87c1dadc Giorgos Verigakis
        stats['Ganeti Jobs'] = len(backend.get_ganeti_jobs())
758 87c1dadc Giorgos Verigakis
        
759 87c1dadc Giorgos Verigakis
        print_dict(stats)
760 87c1dadc Giorgos Verigakis
761 87c1dadc Giorgos Verigakis
762 ead18dbc Giorgos Verigakis
class ListInvitations(Command):
763 ead18dbc Giorgos Verigakis
    group = 'invitation'
764 ead18dbc Giorgos Verigakis
    name = 'list'
765 ead18dbc Giorgos Verigakis
    syntax = '[invitation id]'
766 ead18dbc Giorgos Verigakis
    description = 'list invitations'
767 ead18dbc Giorgos Verigakis
    
768 ead18dbc Giorgos Verigakis
    def main(self, invitation_id=None):
769 ead18dbc Giorgos Verigakis
        if invitation_id:
770 ead18dbc Giorgos Verigakis
            invitations = [models.Invitations.objects.get(id=invitation_id)]
771 ead18dbc Giorgos Verigakis
        else:
772 ead18dbc Giorgos Verigakis
            invitations = models.Invitations.objects.order_by('id')
773 ead18dbc Giorgos Verigakis
        print_items(invitations, detail=True, keys=('id',))
774 ead18dbc Giorgos Verigakis
775 ead18dbc Giorgos Verigakis
776 ead18dbc Giorgos Verigakis
class ResendInviation(Command):
777 ead18dbc Giorgos Verigakis
    group = 'invitation'
778 ead18dbc Giorgos Verigakis
    name = 'resend'
779 ead18dbc Giorgos Verigakis
    syntax = '<invitation id>'
780 ead18dbc Giorgos Verigakis
    description = 'resend an invitation'
781 ead18dbc Giorgos Verigakis
782 ead18dbc Giorgos Verigakis
    def main(self, invitation_id):
783 ead18dbc Giorgos Verigakis
        invitation = models.Invitations.objects.get(id=invitation_id)
784 ead18dbc Giorgos Verigakis
        send_invitation(invitation)
785 ead18dbc Giorgos Verigakis
786 ead18dbc Giorgos Verigakis
787 9a60dacb Giorgos Verigakis
def print_usage(exe, groups, group=None, shortcut=False):
788 9a60dacb Giorgos Verigakis
    nop = Command(exe, [])
789 9a60dacb Giorgos Verigakis
    nop.parser.print_help()
790 9a60dacb Giorgos Verigakis
    if group:
791 9a60dacb Giorgos Verigakis
        groups = {group: groups[group]}
792 8cdde414 Giorgos Verigakis
793 8cdde414 Giorgos Verigakis
    print
794 8cdde414 Giorgos Verigakis
    print 'Commands:'
795 9a60dacb Giorgos Verigakis
    
796 9a60dacb Giorgos Verigakis
    for group, commands in sorted(groups.items()):
797 9a60dacb Giorgos Verigakis
        for command, cls in sorted(commands.items()):
798 735f44fe Giorgos Verigakis
            if cls.hidden:
799 735f44fe Giorgos Verigakis
                continue
800 ead18dbc Giorgos Verigakis
            name = '  %s %s' % (group, command or '')
801 9a60dacb Giorgos Verigakis
            print '%s %s' % (name.ljust(22), cls.description)
802 9a60dacb Giorgos Verigakis
        print
803 8cdde414 Giorgos Verigakis
804 8cdde414 Giorgos Verigakis
805 8cdde414 Giorgos Verigakis
def main():
806 9a60dacb Giorgos Verigakis
    groups = defaultdict(dict)
807 8cdde414 Giorgos Verigakis
    module = sys.modules[__name__]
808 8cdde414 Giorgos Verigakis
    for name, cls in inspect.getmembers(module, inspect.isclass):
809 9a60dacb Giorgos Verigakis
        if not issubclass(cls, Command) or cls == Command:
810 9a60dacb Giorgos Verigakis
            continue
811 9a60dacb Giorgos Verigakis
        groups[cls.group][cls.name] = cls
812 8cdde414 Giorgos Verigakis
    
813 8cdde414 Giorgos Verigakis
    argv = list(sys.argv)
814 8cdde414 Giorgos Verigakis
    exe = basename(argv.pop(0))
815 9a60dacb Giorgos Verigakis
    prefix, sep, suffix = exe.partition('-')
816 9a60dacb Giorgos Verigakis
    if sep and prefix == 'snf' and suffix in groups:
817 9a60dacb Giorgos Verigakis
        # Allow shortcut aliases like snf-image, snf-server, etc
818 9a60dacb Giorgos Verigakis
        group = suffix
819 8cdde414 Giorgos Verigakis
    else:
820 9a60dacb Giorgos Verigakis
        group = argv.pop(0) if argv else None
821 9a60dacb Giorgos Verigakis
        if group in groups:
822 9a60dacb Giorgos Verigakis
            exe = '%s %s' % (exe, group)
823 9a60dacb Giorgos Verigakis
        else:
824 9a60dacb Giorgos Verigakis
            exe = '%s <group>' % exe
825 9a60dacb Giorgos Verigakis
            group = None
826 8cdde414 Giorgos Verigakis
    
827 8cdde414 Giorgos Verigakis
    command = argv.pop(0) if argv else None
828 8cdde414 Giorgos Verigakis
    
829 9a60dacb Giorgos Verigakis
    if group not in groups or command not in groups[group]:
830 9a60dacb Giorgos Verigakis
        print_usage(exe, groups, group)
831 8cdde414 Giorgos Verigakis
        sys.exit(1)
832 8cdde414 Giorgos Verigakis
    
833 9a60dacb Giorgos Verigakis
    cls = groups[group][command]
834 9a60dacb Giorgos Verigakis
    cmd = cls(exe, argv)
835 8cdde414 Giorgos Verigakis
    cmd.execute()
836 8cdde414 Giorgos Verigakis
837 8cdde414 Giorgos Verigakis
838 8cdde414 Giorgos Verigakis
if __name__ == '__main__':
839 9e98ba3c Giorgos Verigakis
    dictConfig(settings.SNFADMIN_LOGGING)
840 8cdde414 Giorgos Verigakis
    main()