Revision 38d247df snf-app/synnefo/tools/cloud.py

b/snf-app/synnefo/tools/cloud.py
1 1
#!/usr/bin/env python
2 2

  
3 3
# Copyright 2011 GRNET S.A. All rights reserved.
4
# 
4
#
5 5
# Redistribution and use in source and binary forms, with or
6 6
# without modification, are permitted provided that the following
7 7
# conditions are met:
8
# 
8
#
9 9
#   1. Redistributions of source code must retain the above
10 10
#      copyright notice, this list of conditions and the following
11 11
#      disclaimer.
12
# 
12
#
13 13
#   2. Redistributions in binary form must reproduce the above
14 14
#      copyright notice, this list of conditions and the following
15 15
#      disclaimer in the documentation and/or other materials
16 16
#      provided with the distribution.
17
# 
17
#
18 18
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 19
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 20
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
......
27 27
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 28
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 29
# POSSIBILITY OF SUCH DAMAGE.
30
# 
30
#
31 31
# The views and conclusions contained in the software and
32 32
# documentation are those of the authors and should not be
33 33
# interpreted as representing official policies, either expressed
......
43 43

  
44 44

  
45 45
DEFAULT_API_URL = 'http://127.0.0.1:8000/api/v1.1'
46
DEFAULT_TOKEN = '46e427d657b20defe352804f0eb6f8a2'
47 46

  
48 47
MARGIN = 14
49 48

  
......
62 61
        addr = ''
63 62
        if 'values' in net:
64 63
            addr = '[%s]' % ' '.join(ip['addr'] for ip in net['values'])
65
        
64

  
66 65
        val = '%s/%s %s %s' % (net['id'], net['name'], net['mac'], addr)
67 66
        if 'firewallProfile' in net:
68 67
            val += ' - %s' % net['firewallProfile']
......
92 91
        parser.add_option('--token',
93 92
                            dest='token',
94 93
                            metavar='TOKEN',
95
                            default=DEFAULT_TOKEN,
96 94
                            help='use user token TOKEN')
97 95
        parser.add_option('-v',
98 96
                            action='store_true',
......
101 99
                            help='use verbose output')
102 100
        self.add_options(parser)
103 101
        options, args = parser.parse_args(argv)
104
        
102

  
105 103
        # Add options to self
106 104
        for opt in parser.option_list:
107 105
            key = opt.dest
108 106
            if key:
109 107
                val = getattr(options, key)
110 108
                setattr(self, key, val)
111
        
109

  
112 110
        self.execute(*args)
113
    
111

  
114 112
    def add_options(self, parser):
115 113
        pass
116
    
114

  
117 115
    def execute(self, *args):
118 116
        pass
119
    
117

  
120 118
    def http_cmd(self, method, path, body=None, expected_status=200):
121 119
        p = urlparse(self.apiurl)
122 120
        if p.scheme == 'https':
......
165 163

  
166 164
    def http_get(self, path, expected_status=200):
167 165
        return self.http_cmd('GET', path, None, expected_status)
168
    
166

  
169 167
    def http_post(self, path, body, expected_status=202):
170 168
        return self.http_cmd('POST', path, body, expected_status)
171 169

  
......
179 177
@command_name('ls')
180 178
class ListServers(Command):
181 179
    description = 'list servers'
182
    
180

  
183 181
    def add_options(self, parser):
184 182
        parser.add_option('-l', action='store_true', dest='detail', default=False,
185 183
                            help='show detailed output')
186 184
        parser.add_option('-a', action='store_true', dest='show_empty', default=False,
187 185
                            help='include empty values')
188
    
186

  
189 187
    def execute(self):
190 188
        path = '/servers/detail' if self.detail else '/servers'
191 189
        reply = self.http_get(path)
......
205 203
class GetServerDetails(Command):
206 204
    description = 'get server details'
207 205
    syntax = '<server id>'
208
    
206

  
209 207
    def add_options(self, parser):
210 208
        parser.add_option('-a', action='store_true', dest='show_empty', default=False,
211 209
                            help='include empty values')
212
    
210

  
213 211
    def execute(self, server_id):
214 212
        path = '/servers/%d' % int(server_id)
215 213
        reply = self.http_get(path)
216 214
        server = reply['server']
217 215
        server.pop('id')
218 216
        print_dict(server, self.show_empty)
219
        
217

  
220 218

  
221 219
@command_name('create')
222 220
class CreateServer(Command):
223 221
    description = 'create server'
224 222
    syntax = '<server name>'
225
    
223

  
226 224
    def add_options(self, parser):
227 225
        parser.add_option('-f', dest='flavor', metavar='FLAVOR_ID', default=1,
228 226
                            help='use flavor FLAVOR_ID')
229 227
        parser.add_option('-i', dest='image', metavar='IMAGE_ID', default=1,
230 228
                            help='use image IMAGE_ID')
231
    
229

  
232 230
    def execute(self, name):
233 231
        server = {
234 232
            'name': name,
......
244 242
class UpdateServerName(Command):
245 243
    description = 'update server name'
246 244
    syntax = '<server id> <new name>'
247
    
245

  
248 246
    def execute(self, server_id, name):
249 247
        path = '/servers/%d' % int(server_id)
250 248
        body = json.dumps({'server': {'name': name}})
......
255 253
class DeleteServer(Command):
256 254
    description = 'delete server'
257 255
    syntax = '<server id>'
258
    
256

  
259 257
    def execute(self, server_id):
260 258
        path = '/servers/%d' % int(server_id)
261 259
        self.http_delete(path)
......
265 263
class RebootServer(Command):
266 264
    description = 'reboot server'
267 265
    syntax = '<server id>'
268
    
266

  
269 267
    def add_options(self, parser):
270 268
        parser.add_option('-f', action='store_true', dest='hard', default=False,
271 269
                            help='perform a hard reboot')
272
    
270

  
273 271
    def execute(self, server_id):
274 272
        path = '/servers/%d/action' % int(server_id)
275 273
        type = 'HARD' if self.hard else 'SOFT'
276 274
        body = json.dumps({'reboot': {'type': type}})
277 275
        self.http_post(path, body)
278
    
276

  
279 277

  
280 278
@command_name('start')
281 279
class StartServer(Command):
282 280
    description = 'start server'
283 281
    syntax = '<server id>'
284
    
282

  
285 283
    def execute(self, server_id):
286 284
        path = '/servers/%d/action' % int(server_id)
287 285
        body = json.dumps({'start': {}})
......
292 290
class StartServer(Command):
293 291
    description = 'shutdown server'
294 292
    syntax = '<server id>'
295
    
293

  
296 294
    def execute(self, server_id):
297 295
        path = '/servers/%d/action' % int(server_id)
298 296
        body = json.dumps({'shutdown': {}})
......
303 301
class ServerConsole(Command):
304 302
    description = 'get VNC console'
305 303
    syntax = '<server id>'
306
    
304

  
307 305
    def execute(self, server_id):
308 306
        path = '/servers/%d/action' % int(server_id)
309 307
        body = json.dumps({'console': {'type': 'vnc'}})
......
315 313
class SetFirewallProfile(Command):
316 314
    description = 'set the firewall profile'
317 315
    syntax = '<server id> <profile>'
318
    
316

  
319 317
    def execute(self, server_id, profile):
320 318
        path = '/servers/%d/action' % int(server_id)
321 319
        body = json.dumps({'firewallProfile': {'profile': profile}})
......
326 324
class ListAddresses(Command):
327 325
    description = 'list server addresses'
328 326
    syntax = '<server id> [network]'
329
    
327

  
330 328
    def execute(self, server_id, network=None):
331 329
        path = '/servers/%d/ips' % int(server_id)
332 330
        if network:
333 331
            path += '/%s' % network
334 332
        reply = self.http_get(path)
335
        
333

  
336 334
        addresses = [reply['network']] if network else reply['addresses']['values']
337 335
        print_addresses(addresses)
338 336

  
......
340 338
@command_name('lsflv')
341 339
class ListFlavors(Command):
342 340
    description = 'list flavors'
343
    
341

  
344 342
    def add_options(self, parser):
345 343
        parser.add_option('-l', action='store_true', dest='detail', default=False,
346 344
                            help='show detailed output')
347
    
345

  
348 346
    def execute(self):
349 347
        path = '/flavors/detail' if self.detail else '/flavors'
350 348
        reply = self.http_get(path)
351
        
349

  
352 350
        for flavor in reply['flavors']['values']:
353 351
            id = flavor.pop('id')
354 352
            name = flavor.pop('name')
......
360 358
class GetFlavorDetails(Command):
361 359
    description = 'get flavor details'
362 360
    syntax = '<flavor id>'
363
    
361

  
364 362
    def execute(self, flavor_id):
365 363
        path = '/flavors/%d' % int(flavor_id)
366 364
        reply = self.http_get(path)
367
        
365

  
368 366
        flavor = reply['flavor']
369 367
        id = flavor.pop('id')
370 368
        name = flavor.pop('name')
......
375 373
@command_name('lsimg')
376 374
class ListImages(Command):
377 375
    description = 'list images'
378
    
376

  
379 377
    def add_options(self, parser):
380 378
        parser.add_option('-l', action='store_true', dest='detail', default=False,
381 379
                            help='show detailed output')
382
    
380

  
383 381
    def execute(self):
384 382
        path = '/images/detail' if self.detail else '/images'
385 383
        reply = self.http_get(path)
386
        
384

  
387 385
        for image in reply['images']['values']:
388 386
            id = image.pop('id')
389 387
            name = image.pop('name')
......
399 397
class GetImageDetails(Command):
400 398
    description = 'get image details'
401 399
    syntax = '<image id>'
402
    
400

  
403 401
    def execute(self, image_id):
404 402
        path = '/images/%d' % int(image_id)
405 403
        reply = self.http_get(path)
......
412 410
class CreateImage(Command):
413 411
    description = 'create image'
414 412
    syntax = '<server id> <image name>'
415
    
413

  
416 414
    def execute(self, server_id, name):
417 415
        image = {'name': name, 'serverRef': int(server_id)}
418 416
        body = json.dumps({'image': image})
......
423 421
class DeleteImage(Command):
424 422
    description = 'delete image'
425 423
    syntax = '<image id>'
426
    
424

  
427 425
    def execute(self, image_id):
428 426
        path = '/images/%d' % int(image_id)
429 427
        self.http_delete(path)
......
638 636

  
639 637
def main():
640 638
    try:
641
        name = argv[1]    
639
        name = argv[1]
642 640
        cls = commands[name]
643 641
    except (IndexError, KeyError):
644 642
        print_usage()
645 643
        exit(1)
646
    
644

  
647 645
    try:
648 646
        cls(argv[2:])
649 647
    except TypeError:

Also available in: Unified diff