Revision 5a673575

b/kamaki/cli/commands/__init__.py
49 49
        except KeyError:
50 50
            pass
51 51

  
52
    def _safe_progress_bar(self, msg, arg='progress_bar'):
53
        """Try to get a progress bar, but do not raise errors"""
54
        try:
55
            progress_bar = self.arguments[arg]
56
            gen = progress_bar.get_generator(msg)
57
        except Exception:
58
            return (None, None)
59
        return (progress_bar, gen)
60

  
61
    def _safe_progress_bar_finish(self, progress_bar):
62
        try:
63
            progress_bar.finish()
64
        except Exception:
65
            pass
66

  
52 67
    def __getitem__(self, argterm):
53 68
        """
54 69
        :param argterm: (str) the name/label of an argument in self.arguments
b/kamaki/cli/commands/cyclades_cli.py
179 179

  
180 180
    @errors.generic.all
181 181
    @errors.cyclades.connection
182
    @errors.cyclades.id
182
    @errors.cyclades.server_id
183 183
    def _run(self, server_id):
184 184
        server = self.client.get_server_details(server_id)
185 185
        self._print(server)
......
258 258
@command(server_cmds)
259 259
class server_rename(_init_cyclades):
260 260
    """Set/update a server (VM) name
261
    VM names are not unique, therefore multiple server may share the same name
261
    VM names are not unique, therefore multiple servers may share the same name
262 262
    """
263 263

  
264
    @errors.generic.all
265
    @errors.cyclades.connection
266
    @errors.cyclades.server_id
267
    def _run(self, server_id, new_name):
268
        self.client.update_server_name(int(server_id), new_name)
269

  
264 270
    def main(self, server_id, new_name):
265
        super(self.__class__, self).main()
266
        try:
267
            self.client.update_server_name(int(server_id), new_name)
268
        except ClientError as ce:
269
            if ce.status == 404:
270
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
271
            raise_if_connection_error(ce)
272
            raiseCLIError(ce)
273
        except ValueError as err:
274
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
275
                details=['Server id must be positive integer\n'],
276
                importance=1)
271
        super(self.__class__, self)._run()
272
        self._run(server_id=server_id, new_name=new_name)
277 273

  
278 274

  
279 275
@command(server_cmds)
280 276
class server_delete(_init_cyclades):
281 277
    """Delete a server (VM)"""
282 278

  
283
    def main(self, server_id):
284
        super(self.__class__, self).main()
285
        try:
279
    @errors.generic.all
280
    @errors.cyclades.connection
281
    @errors.cyclades.server_id
282
    def _run(self, server_id):
286 283
            self.client.delete_server(int(server_id))
287
        except ClientError as ce:
288
            if ce.status == 404:
289
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
290
            raise_if_connection_error(ce)
291
            raiseCLIError(ce)
292
        except ValueError as err:
293
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
294
                details=['Server id must be positive integer\n'],
295
                importance=1)
296
        except Exception as err:
297
            raiseCLIError(err)
284

  
285
    def main(self, server_id):
286
        super(self.__class__, self)._run()
287
        self._run(server_id=server_id)
298 288

  
299 289

  
300 290
@command(server_cmds)
......
305 295
        hard=FlagArgument('perform a hard reboot', '-f')
306 296
    )
307 297

  
298
    @errors.generic.all
299
    @errors.cyclades.connection
300
    @errors.cyclades.server_id
301
    def _run(self, server_id):
302
        self.client.reboot_server(int(server_id), self['hard'])
303

  
308 304
    def main(self, server_id):
309
        super(self.__class__, self).main()
310
        try:
311
            self.client.reboot_server(int(server_id), self['hard'])
312
        except ClientError as ce:
313
            if ce.status == 404:
314
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
315
            raise_if_connection_error(ce)
316
            raiseCLIError(ce)
317
        except ValueError as err:
318
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
319
                details=['Server id must be positive integer\n'],
320
                importance=1)
321
        except Exception as err:
322
            raiseCLIError(err)
305
        super(self.__class__, self)._run()
306
        self._run(server_id=server_id)
323 307

  
324 308

  
325 309
@command(server_cmds)
326 310
class server_start(_init_cyclades):
327 311
    """Start an existing server (VM)"""
328 312

  
313
    @errors.generic.all
314
    @errors.cyclades.connection
315
    @errors.cyclades.server_id
316
    def _run(self, server_id):
317
        self.client.start_server(int(server_id))
318

  
329 319
    def main(self, server_id):
330
        super(self.__class__, self).main()
331
        try:
332
            self.client.start_server(int(server_id))
333
        except ClientError as ce:
334
            if ce.status == 404:
335
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
336
            raise_if_connection_error(ce)
337
            raiseCLIError(ce)
338
        except ValueError as err:
339
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
340
                details=['Server id must be positive integer\n'],
341
                importance=1)
342
        except Exception as err:
343
            raiseCLIError(err)
320
        super(self.__class__, self)._run()
321
        self._run(server_id=server_id)
344 322

  
345 323

  
346 324
@command(server_cmds)
347 325
class server_shutdown(_init_cyclades):
348 326
    """Shutdown an active server (VM)"""
349 327

  
328
    @errors.generic.all
329
    @errors.cyclades.connection
330
    @errors.cyclades.server_id
331
    def _run(self, server_id):
332
        self.client.shutdown_server(int(server_id))
333

  
350 334
    def main(self, server_id):
351
        super(self.__class__, self).main()
352
        try:
353
            self.client.shutdown_server(int(server_id))
354
        except ClientError as ce:
355
            if ce.status == 404:
356
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
357
            raise_if_connection_error(ce)
358
            raiseCLIError(ce)
359
        except ValueError as err:
360
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
361
                details=['Server id must be positive integer\n'],
362
                importance=1)
363
        except Exception as err:
364
            raiseCLIError(err)
335
        super(self.__class__, self)._run()
336
        self._run(server_id=server_id)
365 337

  
366 338

  
367 339
@command(server_cmds)
......
373 345
    - password: for VNC authorization
374 346
    """
375 347

  
348
    @errors.generic.all
349
    @errors.cyclades.connection
350
    @errors.cyclades.server_id
351
    def _run(self, server_id):
352
        r = self.client.get_server_console(int(server_id))
353
        print_dict(r)
354

  
376 355
    def main(self, server_id):
377
        super(self.__class__, self).main()
378
        try:
379
            reply = self.client.get_server_console(int(server_id))
380
        except ClientError as ce:
381
            if ce.status == 404:
382
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
383
            raise_if_connection_error(ce)
384
            raiseCLIError(ce)
385
        except ValueError as err:
386
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
387
                details=['Server id must be positive integer\n'],
388
                importance=1)
389
        except Exception as err:
390
            raiseCLIError(err)
391
        print_dict(reply)
356
        super(self.__class__, self)._run()
357
        self._run(server_id=server_id)
392 358

  
393 359

  
394 360
@command(server_cmds)
......
400 366
    - PROTECTED: Firewall in secure mode
401 367
    """
402 368

  
369
    @errors.generic.all
370
    @errors.cyclades.connection
371
    @errors.cyclades.server_id
372
    @errors.cyclades.firewall
373
    def _run(self, server_id, profile):
374
        self.client.set_firewall_profile(
375
            server_id=int(server_id),
376
            profile=unicode(profile).upper())
377

  
403 378
    def main(self, server_id, profile):
404
        super(self.__class__, self).main()
405
        try:
406
            self.client.set_firewall_profile(
407
                int(server_id),
408
                unicode(profile).upper())
409
        except ClientError as ce:
410
            if ce.status == 400 and 'firewall' in '%s' % ce:
411
                raiseCLIError(ce,
412
                    '%s is an unsupported firewall profile' % profile)
413
            elif ce.status == 404:
414
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
415
            raise_if_connection_error(ce)
416
            raiseCLIError(ce)
417
        except ValueError as err:
418
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
419
                details=['Server id must be positive integer\n'],
420
                importance=1)
421
        except Exception as err:
422
            raiseCLIError(err)
379
        super(self.__class__, self)._run()
380
        self._run(server_id=server_id, profile=profile)
423 381

  
424 382

  
425 383
@command(server_cmds)
426 384
class server_addr(_init_cyclades):
427 385
    """List the addresses of all network interfaces on a server (VM)"""
428 386

  
429
    def main(self, server_id):
430
        super(self.__class__, self).main()
431
        try:
432
            reply = self.client.list_server_nics(int(server_id))
433
        except ClientError as ce:
434
            if ce.status == 404:
435
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
436
            raise_if_connection_error(ce)
437
            raiseCLIError(ce)
438
        except ValueError as err:
439
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
440
                details=['Server id must be positive integer\n'],
441
                importance=1)
442
        except Exception as err:
443
            raiseCLIError(err)
387
    @errors.generic.all
388
    @errors.cyclades.connection
389
    @errors.cyclades.server_id
390
    def _run(self, server_id):
391
        reply = self.client.list_server_nics(int(server_id))
444 392
        print_list(reply, with_enumeration=len(reply) > 1)
445 393

  
394
    def main(self, server_id):
395
        super(self.__class__, self)._run()
396
        self._run(server_id=server_id)
397

  
446 398

  
447 399
@command(server_cmds)
448 400
class server_meta(_init_cyclades):
......
450 402
    Metadata are formed as key:value pairs where key is used to retrieve them
451 403
    """
452 404

  
405
    @errors.generic.all
406
    @errors.cyclades.connection
407
    @errors.cyclades.server_id
408
    @errors.cyclades.metadata
409
    def _run(self, server_id, key=''):
410
        r = self.client.get_server_metadata(int(server_id), key)
411
        print_dict(r)
412

  
453 413
    def main(self, server_id, key=''):
454
        super(self.__class__, self).main()
455
        try:
456
            reply = self.client.get_server_metadata(int(server_id), key)
457
        except ClientError as ce:
458
            if ce.status == 404:
459
                msg = 'No metadata with key %s' % key\
460
                if 'Metadata' in '%s' % ce\
461
                else 'Server with id %s not found' % server_id
462
                raiseCLIError(ce, msg)
463
            raise_if_connection_error(ce)
464
            raiseCLIError(ce)
465
        except ValueError as err:
466
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
467
                details=['Server id must be positive integer\n'],
468
                importance=1)
469
        except Exception as err:
470
            raiseCLIError(err)
471
        print_dict(reply)
414
        super(self.__class__, self)._run()
415
        self._run(server_id=server_id, key=key)
472 416

  
473 417

  
474 418
@command(server_cmds)
......
477 421
    Metadata are formed as key:value pairs, both needed to set one
478 422
    """
479 423

  
480
    def main(self, server_id, key, val):
481
        super(self.__class__, self).main()
424
    @errors.generic.all
425
    @errors.cyclades.connection
426
    @errors.cyclades.server_id
427
    def _run(self, server_id, key, val):
482 428
        metadata = {key: val}
483
        try:
484
            reply = self.client.update_server_metadata(int(server_id),
485
                **metadata)
486
        except ClientError as ce:
487
            if ce.status == 404:
488
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
489
            raise_if_connection_error(ce)
490
            raiseCLIError(ce)
491
        except ValueError as err:
492
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
493
                details=['Server id must be positive integer\n'],
494
                importance=1)
495
        except Exception as err:
496
            raiseCLIError(err)
497
        print_dict(reply)
429
        r = self.client.update_server_metadata(int(server_id), **metadata)
430
        print_dict(r)
431

  
432
    def main(self, server_id, key, val):
433
        super(self.__class__, self)._run()
434
        self._run(server_id=server_id, key=key, val=val)
498 435

  
499 436

  
500 437
@command(server_cmds)
501 438
class server_delmeta(_init_cyclades):
502 439
    """Delete server (VM) metadata"""
503 440

  
441
    @errors.generic.all
442
    @errors.cyclades.connection
443
    @errors.cyclades.server_id
444
    @errors.cyclades.metadata
445
    def _run(self, server_id, key):
446
        self.client.delete_server_metadata(int(server_id), key)
447

  
504 448
    def main(self, server_id, key):
505
        super(self.__class__, self).main()
506
        try:
507
            self.client.delete_server_metadata(int(server_id), key)
508
        except ClientError as ce:
509
            if ce.status == 404:
510
                msg = 'No metadata with key %s' % key\
511
                if 'Metadata' in '%s' % ce\
512
                else 'Server with id %s not found' % server_id
513
                raiseCLIError(ce, msg)
514
            raise_if_connection_error(ce)
515
            raiseCLIError(ce)
516
        except ValueError as err:
517
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
518
                details=['Server id must be positive integer\n'],
519
                importance=1)
520
        except Exception as err:
521
            raiseCLIError(err)
449
        super(self.__class__, self)._run()
450
        self._run(server_id=server_id, key=key)
522 451

  
523 452

  
524 453
@command(server_cmds)
525 454
class server_stats(_init_cyclades):
526 455
    """Get server (VM) statistics"""
527 456

  
457
    @errors.generic.all
458
    @errors.cyclades.connection
459
    @errors.cyclades.server_id
460
    def _run(self, server_id):
461
        r = self.client.get_server_stats(int(server_id))
462
        print_dict(r, exclude=('serverRef',))
463

  
528 464
    def main(self, server_id):
529
        super(self.__class__, self).main()
530
        try:
531
            reply = self.client.get_server_stats(int(server_id))
532
        except ClientError as ce:
533
            if ce.status == 404:
534
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
535
            raise_if_connection_error(ce)
536
            raiseCLIError(ce)
537
        except ValueError as err:
538
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
539
                details=['Server id must be positive integer\n'],
540
                importance=1)
541
        except Exception as err:
542
            raiseCLIError(err)
543
        print_dict(reply, exclude=('serverRef',))
465
        super(self.__class__, self)._run()
466
        self._run(server_id=server_id)
544 467

  
545 468

  
546 469
@command(server_cmds)
......
555 478
        )
556 479
    )
557 480

  
558
    def main(self, server_id, currect_status='BUILD'):
559
        super(self.__class__, self).main()
560
        try:
561
            progress_bar = self.arguments['progress_bar']
562
            wait_cb = progress_bar.get_generator(\
563
                'Server %s still in %s mode' % (server_id, currect_status))
564
        except ValueError as err:
565
            raiseCLIError(err, 'Invalid server id %s ' % server_id,
566
                details=['Server id must be positive integer\n'],
567
                importance=1)
568
        except Exception:
569
            wait_cb = None
481
    @errors.generic.all
482
    @errors.cyclades.connection
483
    @errors.cyclades.server_id
484
    def _run(self, server_id, currect_status):
485
        (progress_bar, wait_cb) = self._safe_progress_bar(
486
            'Server %s still in %s mode' % (server_id, currect_status))
487

  
570 488
        try:
571
            new_mode = self.client.wait_server(server_id,
489
            new_mode = self.client.wait_server(
490
                server_id,
572 491
                currect_status,
573 492
                wait_cb=wait_cb)
574
            progress_bar.finish()
575
        except KeyboardInterrupt:
576
            print('\nCanceled')
577
            progress_bar.finish()
578
            return
579
        except ClientError as ce:
580
            progress_bar.finish()
581
            if ce.status == 404:
582
                raiseCLIError(ce, 'Server with id %s not found' % server_id)
583
            raise_if_connection_error(ce)
584
            raiseCLIError(ce)
493
        except Exception:
494
            self._safe_progress_bar_finish(progress_bar)
495
            raise
496
        finally:
497
            self._safe_progress_bar_finish(progress_bar)
585 498
        if new_mode:
586 499
            print('Server %s is now in %s mode' % (server_id, new_mode))
587 500
        else:
588 501
            raiseCLIError(None, 'Time out')
589 502

  
503
    def main(self, server_id, currect_status='BUILD'):
504
        super(self.__class__, self)._run()
505
        self._run(server_id=server_id, currect_status=currect_status)
506

  
590 507

  
591 508
@command(flavor_cmds)
592 509
class flavor_list(_init_cyclades):
......
600 517
        '--more')
601 518
    )
602 519

  
520
    @errors.generic.all
521
    @errors.cyclades.connection
522
    def _run(self):
523
        flavors = self.client.list_flavors(self['detail'])
524
        pg_size = 10 if self['more'] and not self['limit'] else self['limit']
525
        print_items(flavors, with_redundancy=self['detail'], page_size=pg_size)
526

  
603 527
    def main(self):
604
        super(self.__class__, self).main()
605
        try:
606
            flavors = self.client.list_flavors(self['detail'])
607
        except ClientError as ce:
608
            raise_if_connection_error(ce)
609
            raiseCLIError(ce)
610
        except Exception as err:
611
            raiseCLIError(err)
612
        if self['more']:
613
            print_items(
614
                flavors,
615
                with_redundancy=self['detail'],
616
                page_size=self['limit'] if self['limit'] else 10)
617
        else:
618
            print_items(
619
                flavors,
620
                with_redundancy=self['detail'],
621
                page_size=self['limit'])
528
        super(self.__class__, self)._run()
529
        self._run()
622 530

  
623 531

  
624 532
@command(flavor_cmds)
......
627 535
    To get a list of available flavors and flavor ids, try /flavor list
628 536
    """
629 537

  
630
    def main(self, flavor_id):
631
        super(self.__class__, self).main()
632
        try:
633
            flavor = self.client.get_flavor_details(int(flavor_id))
634
        except ClientError as ce:
635
            raise_if_connection_error(ce)
636
            raiseCLIError(ce)
637
        except ValueError as err:
638
            raiseCLIError(err,
639
                'Invalid flavor id %s' % flavor_id,
640
                importance=1,
641
                details=['Flavor id must be possitive integer'])
642
        except Exception as err:
643
            raiseCLIError(err)
538
    @errors.generic.all
539
    @errors.cyclades.connection
540
    @errors.cyclades.flavor_id
541
    def _run(self, flavor_id):
542
        flavor = self.client.get_flavor_details(int(flavor_id))
644 543
        print_dict(flavor)
645 544

  
545
    def main(self, flavor_id):
546
        super(self.__class__, self)._run()
547
        self._run(flavor_id=flavor_id)
548

  
646 549

  
647 550
@command(network_cmds)
648 551
class network_info(_init_cyclades):
......
657 560
            count = len(att)
658 561
            net['attachments'] = att if count else None
659 562

  
563
    @errors.generic.all
564
    @errors.cyclades.connection
565
    @errors.cyclades.network_id
566
    def _run(self, network_id):
567
        network = self.client.get_network_details(int(network_id))
568
        self._make_result_pretty(network)
569
        print_dict(network, exclude=('id'))
570

  
660 571
    def main(self, network_id):
661
        super(self.__class__, self).main()
662
        try:
663
            network = self.client.get_network_details(int(network_id))
664
            self._make_result_pretty(network)
665
        except ClientError as ce:
666
            raise_if_connection_error(ce)
667
            if ce.status == 404:
668
                raiseCLIError(ce,
669
                    'No network found with id %s' % network_id,
670
                    details=['To see a detailed list of available network ids',
671
                    ' try /network list'])
672
            raiseCLIError(ce)
673
        except ValueError as ve:
674
            raiseCLIError(ve,
675
                'Invalid network_id %s' % network_id,
676
                importance=1,
677
                details=['Network id must be a possitive integer'])
678
        except Exception as err:
679
            raiseCLIError(err)
680
        print_dict(network)
572
        super(self.__class__, self)._run()
573
        self._run(network_id=network_id)
681 574

  
682 575

  
683 576
@command(network_cmds)
......
696 589
        for net in nets:
697 590
            network_info._make_result_pretty(net)
698 591

  
699
    def main(self):
700
        super(self.__class__, self).main()
701
        try:
702
            networks = self.client.list_networks(self['detail'])
703
            if self['detail']:
704
                self._make_results_pretty(networks)
705
        except ClientError as ce:
706
            raise_if_connection_error(ce)
707
            if ce.status == 404:
708
                raiseCLIError(ce,
709
                    'No networks found on server %s' % self.client.base_url,
710
                    details=[
711
                    'Please, check if service url is correctly set',
712
                    '  to get current service url: /config get compute.url',
713
                    '  to set service url: /config set compute.url <URL>'])
714
            raiseCLIError(ce)
715
        except Exception as err:
716
            raiseCLIError(err)
592
    @errors.generic.all
593
    @errors.cyclades.connection
594
    def _run(self):
595
        networks = self.client.list_networks(self['detail'])
596
        if self['detail']:
597
            self._make_results_pretty(networks)
717 598
        if self['more']:
718 599
            print_items(networks,
719 600
                page_size=self['limit'] if self['limit'] else 10)
......
722 603
        else:
723 604
            print_items(networks)
724 605

  
606
    def main(self):
607
        super(self.__class__, self)._run()
608
        self._run()
609

  
725 610

  
726 611
@command(network_cmds)
727 612
class network_create(_init_cyclades):
......
734 619
        type=ValueArgument('explicitly set type', '--with-type')
735 620
    )
736 621

  
622
    @errors.generic.all
623
    @errors.cyclades.connection
624
    @errors.cyclades.network_max
625
    def _run(self, name):
626
        r = self.client.create_network(name,
627
            cidr=self['cidr'],
628
            gateway=self['gateway'],
629
            dhcp=self['dhcp'],
630
            type=self['type'])
631
        print_items([r])
632

  
737 633
    def main(self, name):
738
        super(self.__class__, self).main()
739
        try:
740
            reply = self.client.create_network(name,
741
                cidr=self['cidr'],
742
                gateway=self['gateway'],
743
                dhcp=self['dhcp'],
744
                type=self['type'])
745
        except ClientError as ce:
746
            raise_if_connection_error(ce)
747
            if ce.status == 413:
748
                raiseCLIError(ce,
749
                    'Cannot create another network',
750
                    details=['Maximum number of networks reached'])
751
            raiseCLIError(ce)
752
        except Exception as err:
753
            raiseCLIError(err)
754
        print_items([reply])
634
        super(self.__class__, self)._run()
635
        self._run(name)
755 636

  
756 637

  
757 638
@command(network_cmds)
758 639
class network_rename(_init_cyclades):
759 640
    """Set the name of a network"""
760 641

  
642
    @errors.generic.all
643
    @errors.cyclades.connection
644
    @errors.cyclades.network_id
645
    def _run(self, network_id, new_name):
646
        self.client.update_network_name(int(network_id), new_name)
647

  
761 648
    def main(self, network_id, new_name):
762
        super(self.__class__, self).main()
763
        try:
764
            self.client.update_network_name(int(network_id), new_name)
765
        except ClientError as ce:
766
            raise_if_connection_error(ce)
767
            if ce.status == 404:
768
                raiseCLIError(ce,
769
                    'No network found with id %s' % network_id,
770
                    details=['To see a detailed list of available network ids',
771
                    ' try /network list'])
772
            raiseCLIError(ce)
773
        except ValueError as ve:
774
            raiseCLIError(ve,
775
                'Invalid network_id %s' % network_id,
776
                importance=1,
777
                details=['Network id must be a possitive integer'])
778
        except Exception as err:
779
            raiseCLIError(err)
649
        super(self.__class__, self)._run()
650
        self._run(network_id=network_id, new_name=new_name)
780 651

  
781 652

  
782 653
@command(network_cmds)
783 654
class network_delete(_init_cyclades):
784 655
    """Delete a network"""
785 656

  
657
    @errors.generic.all
658
    @errors.cyclades.connection
659
    @errors.cyclades.network_id
660
    @errors.cyclades.network_in_use
661
    def _run(self, network_id):
662
        self.client.delete_network(int(network_id))
663

  
786 664
    def main(self, network_id):
787
        super(self.__class__, self).main()
788
        try:
789
            self.client.delete_network(int(network_id))
790
        except ClientError as ce:
791
            raise_if_connection_error(ce)
792
            if ce.status == 421:
793
                raiseCLIError(ce,
794
                    'Network with id %s is in use' % network_id,
795
                    details=[
796
                        'Disconnect all nics/VMs of this network first',
797
                        '  to get nics: /network info %s' % network_id,
798
                        '    (under "attachments" section)',
799
                        '  to disconnect: /network disconnect <nic id>'])
800
            elif ce.status == 404:
801
                raiseCLIError(ce,
802
                    'No network found with id %s' % network_id,
803
                    details=['To see a detailed list of available network ids',
804
                    ' try /network list'])
805
            raiseCLIError(ce)
806
        except ValueError as ve:
807
            raiseCLIError(ve,
808
                'Invalid network_id %s' % network_id,
809
                importance=1,
810
                details=['Network id must be a possitive integer'])
811
        except Exception as err:
812
            raiseCLIError(err)
665
        super(self.__class__, self)._run()
666
        self._run(network_id=network_id)
813 667

  
814 668

  
815 669
@command(network_cmds)
816 670
class network_connect(_init_cyclades):
817 671
    """Connect a server to a network"""
818 672

  
673
    @errors.generic.all
674
    @errors.cyclades.connection
675
    @errors.cyclades.server_id
676
    @errors.cyclades.network_id
677
    def _run(self, server_id, network_id):
678
        self.client.connect_server(int(server_id), int(network_id))
679

  
819 680
    def main(self, server_id, network_id):
820
        super(self.__class__, self).main()
821
        try:
822
            network_id = int(network_id)
823
            server_id = int(server_id)
824
            self.client.connect_server(server_id, network_id)
825
        except ClientError as ce:
826
            raise_if_connection_error(ce)
827
            if ce.status == 404:
828
                (thename, theid) = ('server', server_id)\
829
                    if 'server' in ('%s' % ce).lower()\
830
                    else ('network', network_id)
831
                raiseCLIError(ce,
832
                    'No %s found with id %s' % (thename, theid),
833
                    details=[
834
                    'To see a detailed list of available %s ids' % thename,
835
                    ' try /%s list' % thename])
836
            raiseCLIError(ce)
837
        except ValueError as ve:
838
            (thename, theid) = ('server', server_id)\
839
            if isinstance(network_id, int) else ('network', network_id)
840
            raiseCLIError(ve,
841
                'Invalid %s id %s' % (thename, theid),
842
                importance=1,
843
                details=['The %s id must be a possitive integer' % thename,
844
                '  to get available %s ids: /%s list' % (thename, thename)])
845
        except Exception as err:
846
            raiseCLIError(err)
681
        super(self.__class__, self)._run()
682
        self._run(server_id=server_id, network_id=network_id)
847 683

  
848 684

  
849 685
@command(network_cmds)
......
853 689
    To get detailed network information: /network info <network id>
854 690
    """
855 691

  
692
    @errors.cyclades.nic_format
693
    def _server_id_from_nic(self, nic_id):
694
        return nic_id.split('-')[1]
695

  
696
    @errors.generic.all
697
    @errors.cyclades.connection
698
    @errors.cyclades.server_id
699
    @errors.cyclades.nic_id
700
    def _run(self, nic_id, server_id):
701
        if not self.client.disconnect_server(server_id, nic_id):
702
            raise ClientError(
703
                'Network Interface %s not found on server %s' % (
704
                    nic_id,
705
                    server_id),
706
                status=404)
707

  
856 708
    def main(self, nic_id):
857
        super(self.__class__, self).main()
858
        try:
859
            server_id = nic_id.split('-')[1]
860
            if not self.client.disconnect_server(server_id, nic_id):
861
                raise ClientError('Network Interface not found', status=404)
862
        except ClientError as ce:
863
            raise_if_connection_error(ce)
864
            if ce.status == 404:
865
                if 'server' in ('%s' % ce).lower():
866
                    raiseCLIError(ce,
867
                        'No server found with id %s' % (server_id),
868
                        details=[
869
                        'To see a detailed list of available server ids',
870
                        ' try /server list'])
871
                raiseCLIError(ce,
872
                    'No nic %s in server with id %s' % (nic_id, server_id),
873
                    details=[
874
                    'To see a list of nic ids for server %s try:' % server_id,
875
                    '  /server addr %s' % server_id])
876
            raiseCLIError(ce)
877
        except IndexError as err:
878
            raiseCLIError(err,
879
                'Nic %s is of incorrect format' % nic_id,
880
                importance=1,
881
                details=['nid_id format: nic-<server_id>-<nic_index>',
882
                    '  to get nic ids of a network: /network info <net_id>',
883
                    '  they are listed under the "attachments" section'])
884
        except Exception as err:
885
            raiseCLIError(err)
709
        super(self.__class__, self)._run()
710
        server_id = self._server_id_from_nic(nic_id=nic_id)
711
        self._run(nic_id=nic_id, server_id=server_id)
b/kamaki/cli/commands/errors.py
70 70
                        '  to check if token is valid: /astakos authenticate',
71 71
                        '  to set token: /config set [.server.]token <token>',
72 72
                        '  to get current token: /config get [server.]token'])
73
                elif ce.status in range(-12, 200) + [403, 500]:
73
                elif ce.status in range(-12, 200) + [403, 302, 500]:
74 74
                    raiseCLIError(ce, importance=3, details=[
75 75
                        'Check if service is up or set to url %s' % base_url,
76 76
                        '  to get url: /config get %s' % base_url,
77 77
                        '  to set url: /config set %s <URL>' % base_url])
78
                elif ce.status == 404\
79
                and 'kamakihttpresponse' in ('%s' % ce).lower():
80
                    client = getattr(self, 'client', None)
81
                    if not client:
82
                        raise
83
                    url = getattr(client, 'base_url', '<empty>')
84
                    raiseCLIError(ce,
85
                        'Invalid service url %s' % url,
86
                        details=[
87
                        'Please, check if service url is correctly set',
88
                        '* to get current url: /config get compute.url',
89
                        '* to set url: /config set compute.url <URL>'])
78 90
                raise
79 91
        return _raise
80 92

  
......
150 162
        '* get a list of flavor ids: /flavor list',
151 163
        '* details of flavor: /flavor info <flavor id>']
152 164

  
165
    about_network_id = [
166
        'How to pick a valid network id:',
167
        '* get a list of network ids: /network list',
168
        '* details of network: /network info <network id>']
169

  
153 170
    @classmethod
154 171
    def connection(this, foo):
155 172
        return generic._connection(foo, 'compute.url')
......
168 185
        return _raise
169 186

  
170 187
    @classmethod
188
    def network_id(this, foo):
189
        def _raise(self, *args, **kwargs):
190
            network_id = kwargs.get('network_id', None)
191
            try:
192
                network_id = int(network_id)
193
                return foo(self, *args, **kwargs)
194
            except ValueError as ve:
195
                raiseCLIError(ve, 'Invalid network id %s ' % network_id,
196
                    details='network id must be a positive integer',
197
                    importance=1)
198
            except ClientError as ce:
199
                if network_id and ce.status == 404 and\
200
                    'network' in ('%s' % ce).lower():
201
                        raiseCLIError(ce,
202
                            'No network with id %s found' % network_id,
203
                            details=this.about_network_id)
204
                raise
205
        return _raise
206

  
207
    @classmethod
208
    def network_max(this, foo):
209
        def _raise(self, *args, **kwargs):
210
            try:
211
                return foo(self, *args, **kwargs)
212
            except ClientError as ce:
213
                if ce.status == 413:
214
                    raiseCLIError(ce,
215
                        'Cannot create another network',
216
                        details=['Maximum number of networks reached',
217
                            '* to get a list of networks: /network list',
218
                            '* to delete a network: /network delete <net id>'])
219
                raise
220
        return _raise
221

  
222
    @classmethod
223
    def network_in_use(this, foo):
224
        def _raise(self, *args, **kwargs):
225
            network_id = kwargs.get('network_id', None)
226
            try:
227
                return foo(self, *args, **kwargs)
228
            except ClientError as ce:
229
                if network_id or ce.status == 421:
230
                    raiseCLIError(ce,
231
                        'Network with id %s is in use' % network_id,
232
                        details=[
233
                            'Disconnect all nics/VMs of this network first',
234
                            '* to get nics: /network info %s' % network_id,
235
                            '.  (under "attachments" section)',
236
                            '* to disconnect: /network disconnect <nic id>'])
237
                raise
238
        return _raise
239

  
240
    @classmethod
171 241
    def flavor_id(this, foo):
172 242
        def _raise(self, *args, **kwargs):
173 243
            flavor_id = kwargs.get('flavor_id', None)
......
180 250
                    importance=1)
181 251
            except ClientError as ce:
182 252
                if flavor_id and ce.status == 404 and\
183
                    'flavor not found' in ('%s' % ce).lower():
253
                    'flavor' in ('%s' % ce).lower():
184 254
                        raiseCLIError(ce,
185 255
                            'No flavor with id %s found' % flavor_id,
186 256
                            details=this.about_flavor_id)
......
188 258
        return _raise
189 259

  
190 260
    @classmethod
191
    def id(this, foo):
261
    def server_id(this, foo):
192 262
        def _raise(self, *args, **kwargs):
193 263
            server_id = kwargs.get('server_id', None)
194 264
            try:
......
196 266
                return foo(self, *args, **kwargs)
197 267
            except ValueError as ve:
198 268
                raiseCLIError(ve,
199
                    'Invalid VM id %s' % server_id,
269
                    'Invalid server(VM) id %s' % server_id,
200 270
                    details=['id must be a positive integer'],
201 271
                    importance=1)
202 272
            except ClientError as ce:
203
                if ce.status == 404 or\
204
                (ce.status == 400 and 'not found' in ('%s' % ce).lower()):
205
                    raiseCLIError(ce, 'VM with id %s not found' % server_id)
273
                err_msg = ('%s' % ce).lower()
274
                if (ce.status == 404 and 'server' in err_msg)\
275
                or (ce.status == 400 and 'not found' in err_msg):
276
                    raiseCLIError(ce,
277
                        'server(VM) with id %s not found' % server_id,
278
                        details=[
279
                            '* to get existing VM ids: /server list',
280
                            '* to get VM details: /server info <VM id>'])
281
                raise
282
        return _raise
283

  
284
    @classmethod
285
    def firewall(this, foo):
286
        def _raise(self, *args, **kwargs):
287
            profile = kwargs.get('profile', None)
288
            try:
289
                return foo(self, *args, **kwargs)
290
            except ClientError as ce:
291
                if ce.status == 400 and profile\
292
                and 'firewall' in ('%s' % ce).lower():
293
                    raiseCLIError(ce,
294
                        '%s is an invalid firewall profile term' % profile,
295
                        details=['Try one of the following:',
296
                            '* DISABLED: Shutdown firewall',
297
                            '* ENABLED: Firewall in normal mode',
298
                            '* PROTECTED: Firewall in secure mode'])
299
                raise
300
        return _raise
301

  
302
    @classmethod
303
    def nic_id(this, foo):
304
        def _raise(self, *args, **kwargs):
305
            try:
306
                return foo(self, *args, **kwargs)
307
            except ClientError as ce:
308
                nic_id = kwargs.get('nic_id', None)
309
                if nic_id and ce.status == 404\
310
                and 'network interface' in ('%s' % ce).lower():
311
                    server_id = kwargs.get('server_id', '<no server>')
312
                    err_msg = 'No nic %s on server(VM) with id %s' % (
313
                        nic_id,
314
                        server_id)
315
                    raiseCLIError(ce, err_msg, details=[
316
                        '* check server(VM) with id %s: /server info %s' % (
317
                            server_id,
318
                            server_id),
319
                        '* list nics for server(VM) with id %s:' % server_id,
320
                        '      /server addr %s' % server_id])
321
                raise
322
        return _raise
323

  
324
    @classmethod
325
    def nic_format(this, foo):
326
        def _raise(self, *args, **kwargs):
327
            try:
328
                return foo(self, *args, **kwargs)
329
            except IndexError as ie:
330
                nic_id = kwargs.get('nic_id', None)
331
                raiseCLIError(ie,
332
                    'Invalid format for network interface (nic) %s' % nic_id,
333
                    importance=1,
334
                    details=[
335
                        'nid_id format: nic-<server id>-<nic id>',
336
                        '* get nics of a network: /network info <net id>',
337
                        '    (listed the "attachments" section)'])
338
        return _raise
339

  
340
    @classmethod
341
    def metadata(this, foo):
342
        def _raise(self, *args, **kwargs):
343
            key = kwargs.get('key', None)
344
            try:
345
                foo(self, *args, **kwargs)
346
            except ClientError as ce:
347
                if key and ce.status == 404\
348
                    and 'metadata' in ('%s' % ce).lower():
349
                        raiseCLIError(ce, 'No VM metadata with key %s' % key)
206 350
                raise
207 351
        return _raise
208 352

  

Also available in: Unified diff