Typo fix
[kamaki] / kamaki / cli / commands / errors.py
index df88e80..76139db 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
 # or implied, of GRNET S.A.command
 
 from traceback import print_stack, print_exc
-import logging
+from astakosclient import AstakosClientException
 
 from kamaki.clients import ClientError
 from kamaki.cli.errors import CLIError, raiseCLIError, CLISyntaxError
 from kamaki.cli import _debug, kloger
 from kamaki.cli.utils import format_size
 
-sendlog = logging.getLogger('clients.send')
-datasendlog = logging.getLogger('data.send')
-recvlog = logging.getLogger('clients.recv')
-datarecvlog = logging.getLogger('data.recv')
+CLOUDNAME = [
+    'Note: If you use a named cloud, use its name instead of "default"']
 
 
 class generic(object):
@@ -56,11 +54,13 @@ class generic(object):
                 if _debug:
                     print_stack()
                     print_exc(e)
-                raiseCLIError(e)
+                if isinstance(e, CLIError) or isinstance(e, ClientError):
+                    raiseCLIError(e)
+                raiseCLIError(e, details=['%s, -d for debug info' % type(e)])
         return _raise
 
     @classmethod
-    def _connection(this, foo, base_url):
+    def _connection(this, foo):
         def _raise(self, *args, **kwargs):
             try:
                 foo(self, *args, **kwargs)
@@ -69,35 +69,47 @@ class generic(object):
                 if ce.status == 401:
                     raiseCLIError(ce, 'Authorization failed', details=[
                         'Make sure a valid token is provided:',
-                        '  to check if token is valid: /astakos authenticate',
-                        '  to set token: /config set [.server.]token <token>',
-                        '  to get current token: /config get [server.]token'])
+                        '  to check if token is valid: /user authenticate',
+                        '  to set token:',
+                        '    /config set cloud.default.token <token>',
+                        '  to get current token:',
+                        '    /config get cloud.default.token'] + CLOUDNAME)
                 elif ce.status in range(-12, 200) + [302, 401, 403, 500]:
                     raiseCLIError(ce, importance=3, details=[
-                        'Check if service is up or set to url %s' % base_url,
-                        '  to get url: /config get %s' % base_url,
-                        '  to set url: /config set %s <URL>' % base_url])
+                        'Check if service is up'])
                 elif ce.status == 404 and 'kamakihttpresponse' in ce_msg:
                     client = getattr(self, 'client', None)
                     if not client:
                         raise
                     url = getattr(client, 'base_url', '<empty>')
-                    msg = 'Invalid service url %s' % url
+                    msg = 'Invalid service URL %s' % url
                     raiseCLIError(ce, msg, details=[
-                        'Please, check if service url is correctly set',
-                        '* to get current url: /config get compute.url',
-                        '* to set url: /config set compute.url <URL>'])
+                        'Check if authentication URL is correct',
+                        '  check current URL:',
+                        '    /config get cloud.default.url',
+                        '  set new authentication URL:',
+                        '    /config set cloud.default.url'] + CLOUDNAME)
                 raise
         return _raise
 
 
-class astakos(object):
+class user(object):
 
     _token_details = [
-        'To check default token: /config get token',
+        'To check default token: /config get cloud.default.token',
         'If set/update a token:',
-        '*  (permanent):    /config set token <token>',
-        '*  (temporary):    re-run with <token> parameter']
+        '*  (permanent):  /config set cloud.default.token <token>',
+        '*  (temporary):  re-run with <token> parameter'] + CLOUDNAME
+
+    @classmethod
+    def astakosclient(this, foo):
+        def _raise(self, *args, **kwargs):
+            try:
+                r = foo(self, *args, **kwargs)
+            except AstakosClientException as ace:
+                raiseCLIError(ace, 'Error in synnefo-AstakosClient')
+            return r
+        return _raise
 
     @classmethod
     def load(this, foo):
@@ -109,13 +121,16 @@ class astakos(object):
                 raiseCLIError(ae, 'Client setup failure', importance=3)
             if not getattr(client, 'token', False):
                 kloger.warning(
-                    'No permanent token (try: kamaki config set token <tkn>)')
-            if not getattr(client, 'base_url', False):
-                msg = 'Missing astakos server URL'
+                    'No permanent token (try:'
+                    ' kamaki config set cloud.default.token <tkn>)')
+            if not getattr(client, 'astakos_base_url', False):
+                msg = 'Missing synnefo authentication URL'
                 raise CLIError(msg, importance=3, details=[
-                    'Check if astakos.url is set correctly',
-                    'To get astakos url:   /config get astakos.url',
-                    'To set astakos url:   /config set astakos.url <URL>'])
+                    'Check if authentication URL is correct',
+                        '  check current URL:',
+                        '    /config get cloud.default.url',
+                        '  set new auth. URL:',
+                        '    /config set cloud.default.url'] + CLOUDNAME)
             return r
         return _raise
 
@@ -124,14 +139,14 @@ class astakos(object):
         def _raise(self, *args, **kwargs):
             try:
                 return foo(self, *args, **kwargs)
-            except ClientError as ce:
+            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
         return _raise
 
@@ -168,9 +183,11 @@ 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, 'compute.url')
+        return generic._connection(foo)
 
     @classmethod
     def date(this, foo):
@@ -186,6 +203,25 @@ class cyclades(object):
         return _raise
 
     @classmethod
+    def cluster_size(this, foo):
+        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 foo(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, foo):
         def _raise(self, *args, **kwargs):
             network_id = kwargs.get('network_id', None)
@@ -194,7 +230,7 @@ class cyclades(object):
                 return foo(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 (
@@ -206,6 +242,16 @@ class cyclades(object):
         return _raise
 
     @classmethod
+    def network_type(this, foo):
+        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 foo(self, *args, **kwargs)
+        return _raise
+
+    @classmethod
     def network_max(this, foo):
         def _raise(self, *args, **kwargs):
             try:
@@ -228,13 +274,13 @@ class cyclades(object):
             try:
                 return foo(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=self.about_network_id)
-                elif network_id or ce.status == 421:
+                    raiseCLIError(ce, msg, details=this.about_network_id)
+                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>'])
@@ -250,7 +296,7 @@ class cyclades(object):
                 return foo(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 (
@@ -269,8 +315,8 @@ class cyclades(object):
                 server_id = int(server_id)
                 return foo(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()
@@ -279,10 +325,10 @@ 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
 
@@ -316,14 +362,14 @@ class cyclades(object):
                     '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
@@ -352,7 +398,8 @@ class cyclades(object):
                 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
 
@@ -362,11 +409,11 @@ 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, 'image.url')
+        return generic._connection(foo)
 
     @classmethod
     def id(this, foo):
@@ -392,7 +439,7 @@ class plankton(object):
         def _raise(self, *args, **kwargs):
             key = kwargs.get('key', None)
             try:
-                foo(self, *args, **kwargs)
+                return foo(self, *args, **kwargs)
             except ClientError as ce:
                 ce_msg = ('%s' % ce).lower()
                 if ce.status == 404 or (
@@ -406,15 +453,29 @@ class plankton(object):
 class pithos(object):
     container_howto = [
         'To specify a container:',
-        '  1. Set store.container variable (permanent)',
-        '     /config set store.container <container>',
-        '  2. --container=<container> (temporary, overrides 1)',
-        '  3. Use the container:path format (temporary, overrides all)',
-        'For a list of containers: /store list']
+        '  1. --container=<container> (temporary, overrides all)',
+        '  2. Use the container:path format (temporary, overrides 3)',
+        '  3. Set pithos_container variable (permanent)',
+        '     /config set pithos_container <container>',
+        'For a list of containers: /file list']
 
     @classmethod
     def connection(this, foo):
-        return generic._connection(foo, 'store.url')
+        return generic._connection(foo)
+
+    @classmethod
+    def account(this, foo):
+        def _raise(self, *args, **kwargs):
+            try:
+                return foo(self, *args, **kwargs)
+            except ClientError as ce:
+                if ce.status == 403:
+                    raiseCLIError(
+                        ce,
+                        'Invalid account credentials for this operation',
+                        details=['Check user account settings'])
+                raise
+        return _raise
 
     @classmethod
     def quota(this, foo):
@@ -425,11 +486,11 @@ class pithos(object):
                 if ce.status == 413:
                     raiseCLIError(ce, 'User quota exceeded', details=[
                         '* get quotas:',
-                        '  * upper total limit:      /store quota',
-                        '  * container limit:  /store quota <container>',
-                        '* set a higher quota (if permitted):',
-                        '    /store setquota <quota>[unit] <container>'
-                        '    as long as <container quota> <= <total quota>'])
+                        '  * upper total limit:      /file quota',
+                        '  * container limit:',
+                        '    /file containerlimit get <container>',
+                        '* set a higher container limit:',
+                        '    /file containerlimit set <limit> <container>'])
                 raise
         return _raise
 
@@ -450,9 +511,25 @@ class pithos(object):
         return _raise
 
     @classmethod
+    def local_path_download(this, foo):
+        def _raise(self, *args, **kwargs):
+            try:
+                return foo(self, *args, **kwargs)
+            except IOError as ioe:
+                msg = 'Failed to access a 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, foo):
         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)
             except IOError as ioe: