Input uses preferred encoding
[kamaki] / kamaki / cli / commands / errors.py
index 34fe109..911d4d2 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2011-2012 GRNET S.A. All rights reserved.
+# Copyright 2011-2013 GRNET S.A. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or
 # without modification, are permitted provided that the following
@@ -32,6 +32,7 @@
 # or implied, of GRNET S.A.command
 
 from traceback import print_stack, print_exc
+from astakosclient import AstakosClientException
 
 from kamaki.clients import ClientError
 from kamaki.cli.errors import CLIError, raiseCLIError, CLISyntaxError
@@ -45,10 +46,10 @@ CLOUDNAME = [
 class generic(object):
 
     @classmethod
-    def all(this, foo):
+    def all(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except Exception as e:
                 if _debug:
                     print_stack()
@@ -59,10 +60,10 @@ class generic(object):
         return _raise
 
     @classmethod
-    def _connection(this, foo):
+    def _connection(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                foo(self, *args, **kwargs)
+                func(self, *args, **kwargs)
             except ClientError as ce:
                 ce_msg = ('%s' % ce).lower()
                 if ce.status == 401:
@@ -101,9 +102,19 @@ class user(object):
         '*  (temporary):  re-run with <token> parameter'] + CLOUDNAME
 
     @classmethod
-    def load(this, foo):
+    def astakosclient(this, func):
         def _raise(self, *args, **kwargs):
-            r = foo(self, *args, **kwargs)
+            try:
+                r = func(self, *args, **kwargs)
+            except AstakosClientException as ace:
+                raiseCLIError(ace, 'Error in synnefo-AstakosClient')
+            return r
+        return _raise
+
+    @classmethod
+    def load(this, func):
+        def _raise(self, *args, **kwargs):
+            r = func(self, *args, **kwargs)
             try:
                 client = getattr(self, 'client')
             except AttributeError as ae:
@@ -112,7 +123,7 @@ class user(object):
                 kloger.warning(
                     'No permanent token (try:'
                     ' kamaki config set cloud.default.token <tkn>)')
-            if not getattr(client, 'base_url', False):
+            if not getattr(client, 'astakos_base_url', False):
                 msg = 'Missing synnefo authentication URL'
                 raise CLIError(msg, importance=3, details=[
                     'Check if authentication URL is correct',
@@ -124,41 +135,40 @@ class user(object):
         return _raise
 
     @classmethod
-    def authenticate(this, foo):
+    def authenticate(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
-            except ClientError as ce:
+                return func(self, *args, **kwargs)
+            except (ClientError, AstakosClientException) as ce:
                 if ce.status == 401:
                     token = kwargs.get('custom_token', 0) or self.client.token
-                    msg = (
-                        'Authorization failed for token %s' % token
-                    ) if token else 'No token provided',
+                    msg = ('Authorization failed for token %s' % token) if (
+                        token) else 'No token provided',
                     details = [] if token else this._token_details
                     raiseCLIError(ce, msg, details=details)
                 raise ce
-            self._raise = foo
+            self._raise = func
         return _raise
 
 
 class history(object):
     @classmethod
-    def init(this, foo):
+    def init(this, func):
         def _raise(self, *args, **kwargs):
-            r = foo(self, *args, **kwargs)
+            r = func(self, *args, **kwargs)
             if not hasattr(self, 'history'):
                 raise CLIError('Failed to load history', importance=2)
             return r
         return _raise
 
     @classmethod
-    def _get_cmd_ids(this, foo):
+    def _get_cmd_ids(this, func):
         def _raise(self, cmd_ids, *args, **kwargs):
             if not cmd_ids:
                 raise CLISyntaxError(
                     'Usage: <id1|id1-id2> [id3|id3-id4] ...',
                     details=self.__doc__.split('\n'))
-            return foo(self, cmd_ids, *args, **kwargs)
+            return func(self, cmd_ids, *args, **kwargs)
         return _raise
 
 
@@ -173,15 +183,17 @@ class cyclades(object):
         '* get a list of network ids: /network list',
         '* details of network: /network info <network id>']
 
+    net_types = ('CUSTOM', 'MAC_FILTERED', 'IP_LESS_ROUTED', 'PHYSICAL_VLAN')
+
     @classmethod
-    def connection(this, foo):
-        return generic._connection(foo)
+    def connection(this, func):
+        return generic._connection(func)
 
     @classmethod
-    def date(this, foo):
+    def date(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 if ce.status == 400 and 'changes-since' in ('%s' % ce):
                     raise CLIError(
@@ -191,15 +203,34 @@ class cyclades(object):
         return _raise
 
     @classmethod
-    def network_id(this, foo):
+    def cluster_size(this, func):
+        def _raise(self, *args, **kwargs):
+            size = kwargs.get('size', None)
+            try:
+                size = int(size)
+                assert size > 0, 'Cluster size must be a positive integer'
+                return func(self, *args, **kwargs)
+            except ValueError as ve:
+                msg = 'Invalid cluster size value %s' % size
+                raiseCLIError(ve, msg, importance=1, details=[
+                    'Cluster size must be a positive integer'])
+            except AssertionError as ae:
+                raiseCLIError(
+                    ae, 'Invalid cluster size %s' % size, importance=1)
+            except ClientError:
+                raise
+        return _raise
+
+    @classmethod
+    def network_id(this, func):
         def _raise(self, *args, **kwargs):
             network_id = kwargs.get('network_id', None)
             try:
                 network_id = int(network_id)
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ValueError as ve:
                 msg = 'Invalid network id %s ' % network_id
-                details = ['network id must be a positive integer']
+                details = 'network id must be a positive integer'
                 raiseCLIError(ve, msg, details=details, importance=1)
             except ClientError as ce:
                 if network_id and ce.status == 404 and (
@@ -211,10 +242,20 @@ class cyclades(object):
         return _raise
 
     @classmethod
-    def network_max(this, foo):
+    def network_type(this, func):
+        def _raise(self, *args, **kwargs):
+            network_type = kwargs.get('network_type', None)
+            msg = 'Invalid network type %s.\nValid types: %s' % (
+                network_type, ' '.join(this.net_types))
+            assert network_type in this.net_types, msg
+            return func(self, *args, **kwargs)
+        return _raise
+
+    @classmethod
+    def network_max(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 if ce.status == 413:
                     msg = 'Cannot create another network',
@@ -227,19 +268,19 @@ class cyclades(object):
         return _raise
 
     @classmethod
-    def network_in_use(this, foo):
+    def network_in_use(this, func):
         def _raise(self, *args, **kwargs):
             network_id = kwargs.get('network_id', None)
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
-                if network_id and ce.status == 400:
+                if network_id and ce.status in (400, ):
                     msg = 'Network with id %s does not exist' % network_id,
                     raiseCLIError(ce, msg, details=this.about_network_id)
-                elif network_id or ce.status == 421:
+                elif network_id or ce.status in (421, ):
                     msg = 'Network with id %s is in use' % network_id,
                     raiseCLIError(ce, msg, details=[
-                        'Disconnect all nics/VMs of this network first',
+                        'Disconnect all nics/servers of this network first',
                         '* to get nics: /network info %s' % network_id,
                         '.  (under "attachments" section)',
                         '* to disconnect: /network disconnect <nic id>'])
@@ -247,15 +288,15 @@ class cyclades(object):
         return _raise
 
     @classmethod
-    def flavor_id(this, foo):
+    def flavor_id(this, func):
         def _raise(self, *args, **kwargs):
             flavor_id = kwargs.get('flavor_id', None)
             try:
                 flavor_id = int(flavor_id)
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ValueError as ve:
                 msg = 'Invalid flavor id %s ' % flavor_id,
-                details = 'Flavor id must be a positive integer',
+                details = 'Flavor id must be a positive integer'
                 raiseCLIError(ve, msg, details=details, importance=1)
             except ClientError as ce:
                 if flavor_id and ce.status == 404 and (
@@ -267,15 +308,15 @@ class cyclades(object):
         return _raise
 
     @classmethod
-    def server_id(this, foo):
+    def server_id(this, func):
         def _raise(self, *args, **kwargs):
             server_id = kwargs.get('server_id', None)
             try:
                 server_id = int(server_id)
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ValueError as ve:
-                msg = 'Invalid server(VM) id %s' % server_id,
-                details = ['id must be a positive integer'],
+                msg = 'Invalid virtual server id %s' % server_id,
+                details = 'Server id must be a positive integer'
                 raiseCLIError(ve, msg, details=details, importance=1)
             except ClientError as ce:
                 err_msg = ('%s' % ce).lower()
@@ -284,19 +325,19 @@ class cyclades(object):
                 ) or (
                     ce.status == 400 and 'not found' in err_msg
                 ):
-                    msg = 'server(VM) with id %s not found' % server_id,
+                    msg = 'virtual server with id %s not found' % server_id,
                     raiseCLIError(ce, msg, details=[
-                        '* to get existing VM ids: /server list',
-                        '* to get VM details: /server info <VM id>'])
+                        '* to get ids of all servers: /server list',
+                        '* to get server details: /server info <server id>'])
                 raise
         return _raise
 
     @classmethod
-    def firewall(this, foo):
+    def firewall(this, func):
         def _raise(self, *args, **kwargs):
             profile = kwargs.get('profile', None)
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 if ce.status == 400 and profile and (
                     'firewall' in ('%s' % ce).lower()
@@ -311,33 +352,33 @@ class cyclades(object):
         return _raise
 
     @classmethod
-    def nic_id(this, foo):
+    def nic_id(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 nic_id = kwargs.get('nic_id', None)
                 if nic_id and ce.status == 404 and (
                     'network interface' in ('%s' % ce).lower()
                 ):
                     server_id = kwargs.get('server_id', '<no server>')
-                    err_msg = 'No nic %s on server(VM) with id %s' % (
+                    err_msg = 'No nic %s on virtual server with id %s' % (
                         nic_id,
                         server_id)
                     raiseCLIError(ce, err_msg, details=[
-                        '* check server(VM) with id %s: /server info %s' % (
+                        '* check v. server with id %s: /server info %s' % (
                             server_id,
                             server_id),
-                        '* list nics for server(VM) with id %s:' % server_id,
+                        '* list nics for v. server with id %s:' % server_id,
                         '      /server addr %s' % server_id])
                 raise
         return _raise
 
     @classmethod
-    def nic_format(this, foo):
+    def nic_format(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except IndexError as ie:
                 nic_id = kwargs.get('nic_id', None)
                 msg = 'Invalid format for network interface (nic) %s' % nic_id
@@ -348,16 +389,17 @@ class cyclades(object):
         return _raise
 
     @classmethod
-    def metadata(this, foo):
+    def metadata(this, func):
         def _raise(self, *args, **kwargs):
             key = kwargs.get('key', None)
             try:
-                foo(self, *args, **kwargs)
+                func(self, *args, **kwargs)
             except ClientError as ce:
                 if key and ce.status == 404 and (
                     'metadata' in ('%s' % ce).lower()
                 ):
-                        raiseCLIError(ce, 'No VM metadata with key %s' % key)
+                        raiseCLIError(
+                            ce, 'No virtual server metadata with key %s' % key)
                 raise
         return _raise
 
@@ -367,18 +409,18 @@ class plankton(object):
     about_image_id = [
         'How to pick a suitable image:',
         '* get a list of image ids: /image list',
-        '* details of image: /flavor info <image id>']
+        '* details of image: /image meta <image id>']
 
     @classmethod
-    def connection(this, foo):
-        return generic._connection(foo)
+    def connection(this, func):
+        return generic._connection(func)
 
     @classmethod
-    def id(this, foo):
+    def id(this, func):
         def _raise(self, *args, **kwargs):
             image_id = kwargs.get('image_id', None)
             try:
-                foo(self, *args, **kwargs)
+                func(self, *args, **kwargs)
             except ClientError as ce:
                 if image_id and (
                     ce.status == 404
@@ -393,11 +435,11 @@ class plankton(object):
         return _raise
 
     @classmethod
-    def metadata(this, foo):
+    def metadata(this, func):
         def _raise(self, *args, **kwargs):
             key = kwargs.get('key', None)
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 ce_msg = ('%s' % ce).lower()
                 if ce.status == 404 or (
@@ -418,14 +460,14 @@ class pithos(object):
         'For a list of containers: /file list']
 
     @classmethod
-    def connection(this, foo):
-        return generic._connection(foo)
+    def connection(this, func):
+        return generic._connection(func)
 
     @classmethod
-    def account(this, foo):
+    def account(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 if ce.status == 403:
                     raiseCLIError(
@@ -436,10 +478,10 @@ class pithos(object):
         return _raise
 
     @classmethod
-    def quota(this, foo):
+    def quota(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 if ce.status == 413:
                     raiseCLIError(ce, 'User quota exceeded', details=[
@@ -453,11 +495,11 @@ class pithos(object):
         return _raise
 
     @classmethod
-    def container(this, foo):
+    def container(this, func):
         def _raise(self, *args, **kwargs):
             dst_cont = kwargs.get('dst_cont', None)
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 if ce.status == 404 and 'container' in ('%s' % ce).lower():
                         cont = ('%s or %s' % (
@@ -469,21 +511,37 @@ class pithos(object):
         return _raise
 
     @classmethod
-    def local_path(this, foo):
+    def local_path_download(this, func):
+        def _raise(self, *args, **kwargs):
+            try:
+                return func(self, *args, **kwargs)
+            except IOError as ioe:
+                msg = 'Failed to access a local file',
+                raiseCLIError(ioe, msg, importance=2, details=[
+                    'Check if the file exists. Also check if the remote',
+                    'directories exist. All directories in a remote path',
+                    'must exist to succesfully download a container or a',
+                    'directory.',
+                    'To create a remote directory:',
+                    '  [kamaki] file mkdir REMOTE_DIRECTORY_PATH'])
+        return _raise
+
+    @classmethod
+    def local_path(this, func):
         def _raise(self, *args, **kwargs):
-            local_path = kwargs.get('local_path', '<None>')
+            local_path = kwargs.get('local_path', None)
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except IOError as ioe:
                 msg = 'Failed to access file %s' % local_path,
                 raiseCLIError(ioe, msg, importance=2)
         return _raise
 
     @classmethod
-    def object_path(this, foo):
+    def object_path(this, func):
         def _raise(self, *args, **kwargs):
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 err_msg = ('%s' % ce).lower()
                 if (
@@ -497,7 +555,7 @@ class pithos(object):
         return _raise
 
     @classmethod
-    def object_size(this, foo):
+    def object_size(this, func):
         def _raise(self, *args, **kwargs):
             size = kwargs.get('size', None)
             start = kwargs.get('start', 0)
@@ -529,7 +587,7 @@ class pithos(object):
                         importance=1)
                 size = end - start
             try:
-                return foo(self, *args, **kwargs)
+                return func(self, *args, **kwargs)
             except ClientError as ce:
                 err_msg = ('%s' % ce).lower()
                 expected = 'object length is smaller than range length'