Adjust cyclades_cli up to create
authorStavros Sachtouris <saxtouri@admin.grnet.gr>
Wed, 23 Jan 2013 17:50:05 +0000 (19:50 +0200)
committerStavros Sachtouris <saxtouri@admin.grnet.gr>
Wed, 23 Jan 2013 17:50:05 +0000 (19:50 +0200)
kamaki/cli/commands/cyclades_cli.py
kamaki/cli/commands/errors.py
kamaki/cli/commands/image_cli.py

index e09ad92..58ef57b 100644 (file)
@@ -38,7 +38,7 @@ from kamaki.cli.errors import raiseCLIError, CLISyntaxError
 from kamaki.clients.cyclades import CycladesClient, ClientError
 from kamaki.cli.argument import FlagArgument, ValueArgument, KeyValueArgument
 from kamaki.cli.argument import ProgressBarArgument, DateArgument, IntArgument
-from kamaki.cli.commands import _command_init
+from kamaki.cli.commands import _command_init, errors
 
 from base64 import b64encode
 from os.path import exists
@@ -56,8 +56,8 @@ _commands = [server_cmds, flavor_cmds, image_cmds, network_cmds]
 
 
 about_authentication = '\n  User Authentication:\
-    \n    to check authentication: /astakos authenticate\
-    \n    to set authentication token: /config set token <token>'
+    \n* to check authentication: /astakos authenticate\
+    \n* to set authentication token: /config set token <token>'
 
 howto_personality = [
     'Defines a file to be injected to VMs personality.',
@@ -85,6 +85,7 @@ def raise_if_connection_error(err, base_url='compute.url'):
 
 
 class _init_cyclades(_command_init):
+    @errors.generic.all
     def _run(self, service='compute'):
         token = self.config.get(service, 'token')\
             or self.config.get('global', 'token')
@@ -92,8 +93,8 @@ class _init_cyclades(_command_init):
             or self.config.get('global', 'url')
         self.client = CycladesClient(base_url=base_url, token=token)
 
-    def main(self, service='compute'):
-        self._run(service)
+    def main(self):
+        self._run()
 
 
 @command(server_cmds)
@@ -129,21 +130,14 @@ class server_list(_init_cyclades):
             if 'metadata' in server:
                 server['metadata'] = server['metadata']['values']
 
-    def main(self):
-        super(self.__class__, self).main()
-        try:
-            servers = self.client.list_servers(self['detail'], self['since'])
-            if self['detail']:
-                self._make_results_pretty(servers)
-        except ClientError as ce:
-            if ce.status == 400 and 'changes-since' in ('%s' % ce):
-                raiseCLIError(None,
-                    'Incorrect date format for --since',
-                    details=['Accepted date format: d/m/y'])
-            raise_if_connection_error(ce)
-            raiseCLIError(ce)
-        except Exception as err:
-            raiseCLIError(err)
+    @errors.generic.all
+    @errors.cyclades.connection
+    @errors.cyclades.date
+    def _run(self):
+        servers = self.client.list_servers(self['detail'], self['since'])
+        if self['detail']:
+            self._make_results_pretty(servers)
+
         if self['more']:
             print_items(
                 servers,
@@ -152,6 +146,10 @@ class server_list(_init_cyclades):
             print_items(
                 servers[:self['limit'] if self['limit'] else len(servers)])
 
+    def main(self):
+        super(self.__class__, self)._run()
+        self._run()
+
 
 @command(server_cmds)
 class server_info(_init_cyclades):
@@ -163,7 +161,6 @@ class server_info(_init_cyclades):
     - hardware flavor and os image ids
     """
 
-    @classmethod
     def _print(self, server):
         addr_dict = {}
         if 'attachments' in server:
@@ -180,21 +177,17 @@ class server_info(_init_cyclades):
             server['metadata'] = server['metadata']['values']
         print_dict(server, ident=1)
 
-    def main(self, server_id):
-        super(self.__class__, self).main()
-        try:
-            server = self.client.get_server_details(int(server_id))
-        except ValueError as err:
-            raiseCLIError(err, 'Server id must be a positive integer', 1)
-        except ClientError as ce:
-            if ce.status == 404:
-                raiseCLIError(ce, 'Server with id %s not found' % server_id)
-            raise_if_connection_error(ce)
-            raiseCLIError(ce)
-        except Exception as err:
-            raiseCLIError(err)
+    @errors.generic.all
+    @errors.cyclades.connection
+    @errors.cyclades.id
+    def _run(self, server_id):
+        server = self.client.get_server_details(server_id)
         self._print(server)
 
+    def main(self, server_id):
+        super(self.__class__, self)._run()
+        self._run(server_id=server_id)
+
 
 class PersonalityArgument(KeyValueArgument):
     @property
@@ -241,44 +234,25 @@ class server_create(_init_cyclades):
 
     arguments = dict(
         personality=PersonalityArgument(
-            ' _ _ _ '.join(howto_personality),
-            parsed_name='--personality')
+            ' /// '.join(howto_personality),
+            '--personality')
     )
 
-    def main(self, name, flavor_id, image_id):
-        super(self.__class__, self).main()
+    @errors.generic.all
+    @errors.cyclades.connection
+    @errors.plankton.id
+    @errors.cyclades.flavor_id
+    def _run(self, name, flavor_id, image_id):
+        r = self.client.create_server(
+            name,
+            int(flavor_id),
+            image_id,
+            self['personality'])
+        print_dict(r)
 
-        try:
-            reply = self.client.create_server(
-                        name,
-                        int(flavor_id),
-                        image_id,
-                        self['personality']
-                    )
-        except ClientError as ce:
-            if ce.status == 404:
-                msg = ('%s' % ce).lower()
-                if 'flavor' in msg:
-                    raiseCLIError(ce,
-                        'Flavor id %s not found' % flavor_id,
-                        details=['How to pick a valid flavor id:',
-                        '  - get a list of flavor ids: /flavor list',
-                        '  - details on a flavor: /flavor info <flavor id>'])
-                elif 'image' in msg:
-                    raiseCLIError(ce,
-                        'Image id %s not found' % image_id,
-                        details=['How to pick a valid image id:',
-                        '  - get a list of image ids: /image list',
-                        '  - details on an image: /image info <image id>'])
-            raise_if_connection_error(ce)
-            raiseCLIError(ce)
-        except ValueError as err:
-            raiseCLIError(err, 'Invalid flavor id %s ' % flavor_id,
-                details='Flavor id must be a positive integer',
-                importance=1)
-        except Exception as err:
-            raiseCLIError(err, 'Syntax error: %s\n' % err, importance=1)
-        print_dict(reply)
+    def main(self, name, flavor_id, image_id):
+        super(self.__class__, self)._run()
+        self._run(name=name, flavor_id=flavor_id, image_id=image_id)
 
 
 @command(server_cmds)
index 5d40e49..6281b4b 100644 (file)
@@ -145,14 +145,73 @@ class history(object):
 
 
 class cyclades(object):
+    about_flavor_id = [
+        'How to pick a valid flavor id:',
+        '* get a list of flavor ids: /flavor list',
+        '* details of flavor: /flavor info <flavor id>']
+
     @classmethod
     def connection(this, foo):
         return generic._connection(foo, 'compute.url')
 
+    @classmethod
+    def date(this, foo):
+        def _raise(self, *args, **kwargs):
+            try:
+                return foo(self, *args, **kwargs)
+            except ClientError as ce:
+                if ce.status == 400 and 'changes-since' in ('%s' % ce):
+                    raise CLIError(
+                        'Incorrect date format for --since',
+                        details=['Accepted date format: d/m/y'])
+                raise
+        return _raise
+
+    @classmethod
+    def flavor_id(this, foo):
+        def _raise(self, *args, **kwargs):
+            flavor_id = kwargs.get('flavor_id', None)
+            try:
+                flavor_id = int(flavor_id)
+                return foo(self, *args, **kwargs)
+            except ValueError as ve:
+                raiseCLIError(ve, 'Invalid flavor id %s ' % flavor_id,
+                    details='Flavor id must be a positive integer',
+                    importance=1)
+            except ClientError as ce:
+                if flavor_id and ce.status == 404 and\
+                    'flavor not found' in ('%s' % ce).lower():
+                        raiseCLIError(ce,
+                            'No flavor with id %s found' % flavor_id,
+                            details=this.about_flavor_id)
+                raise
+        return _raise
+
+    @classmethod
+    def id(this, foo):
+        def _raise(self, *args, **kwargs):
+            server_id = kwargs.get('server_id', None)
+            try:
+                server_id = int(server_id)
+                return foo(self, *args, **kwargs)
+            except ValueError as ve:
+                raiseCLIError(ve,
+                    'Invalid VM id %s' % server_id,
+                    details=['id must be a positive integer'],
+                    importance=1)
+            except ClientError as ce:
+                if ce.status == 404 or\
+                (ce.status == 400 and 'not found' in ('%s' % ce).lower()):
+                    raiseCLIError(ce, 'VM with id %s not found' % server_id)
+                raise
+        return _raise
+
 
 class plankton(object):
 
-    about_image_id = ['To see a list of available image ids: /image list']
+    about_image_id = ['How to pick a suitable image:',
+        '* get a list of image ids: /image list',
+        '* details of image: /flavor info <image id>']
 
     @classmethod
     def connection(this, foo):
@@ -160,13 +219,15 @@ class plankton(object):
 
     @classmethod
     def id(this, foo):
-        def _raise(self, image_id, *args, **kwargs):
+        def _raise(self, *args, **kwargs):
+            image_id = kwargs.get('image_id', None)
             try:
-                foo(self, image_id, *args, **kwargs)
+                foo(self, *args, **kwargs)
             except ClientError as ce:
-                if image_id and (ce.status == 404 or (\
-                    ce.status == 400 and
-                    'image not found' in ('%s' % ce).lower())):
+                if image_id and (ce.status == 404\
+                    or (ce.status == 400 and
+                        'image not found' in ('%s' % ce).lower())\
+                    or ce.status == 411):
                         raiseCLIError(ce,
                             'No image with id %s found' % image_id,
                             details=this.about_image_id)
@@ -175,13 +236,13 @@ class plankton(object):
 
     @classmethod
     def metadata(this, foo):
-        def _raise(self, image_id, key, *args, **kwargs):
+        def _raise(self, *args, **kwargs):
+            key = kwargs.get('key', None)
             try:
-                foo(self, image_id, key, *args, **kwargs)
+                foo(self, *args, **kwargs)
             except ClientError as ce:
-                if image_id and (ce.status == 404 or (\
-                    ce.status == 400 and
-                    'metadata' in ('%s' % ce).lower())):
+                if ce.status == 404 or ((ce.status == 400\
+                    and 'metadata' in ('%s' % ce).lower())):
                         raiseCLIError(ce,
                             'No properties with key %s in this image' % key)
                 raise
index 266c283..f9875e2 100644 (file)
@@ -146,7 +146,7 @@ class image_meta(_init_image):
 
     def main(self, image_id):
         super(self.__class__, self)._run()
-        self._run(image_id)
+        self._run(image_id=image_id)
 
 
 @command(image_cmds)
@@ -221,7 +221,7 @@ class image_members(_init_image):
 
     def main(self, image_id):
         super(self.__class__, self)._run()
-        self._run(image_id)
+        self._run(image_id=image_id)
 
 
 @command(image_cmds)
@@ -246,12 +246,12 @@ class image_addmember(_init_image):
     @errors.generic.all
     @errors.plankton.connection
     @errors.plankton.id
-    def _run(self, image_id, member):
+    def _run(self, image_id=None, member=None):
             self.client.add_member(image_id, member)
 
     def main(self, image_id, member):
         super(self.__class__, self)._run()
-        self._run(image_id, member)
+        self._run(image_id=image_id, member=member)
 
 
 @command(image_cmds)
@@ -261,12 +261,12 @@ class image_delmember(_init_image):
     @errors.generic.all
     @errors.plankton.connection
     @errors.plankton.id
-    def _run(self, image_id, member):
+    def _run(self, image_id=None, member=None):
             self.client.remove_member(image_id, member)
 
     def main(self, image_id, member):
         super(self.__class__, self)._run()
-        self._run(image_id, member)
+        self._run(image_id=image_id, member=member)
 
 
 @command(image_cmds)
@@ -276,12 +276,12 @@ class image_setmembers(_init_image):
     @errors.generic.all
     @errors.plankton.connection
     @errors.plankton.id
-    def _run(self, image_id, *members):
+    def _run(self, image_id, members):
             self.client.set_members(image_id, members)
 
     def main(self, image_id, *members):
         super(self.__class__, self)._run()
-        self._run(image_id, members)
+        self._run(image_id=image_id, members=members)
 
 
 @command(image_cmds)
@@ -335,7 +335,7 @@ class image_info(_init_cyclades):
 
     def main(self, image_id):
         super(self.__class__, self)._run()
-        self._run(image_id)
+        self._run(image_id=image_id)
 
 
 @command(image_cmds)
@@ -350,7 +350,7 @@ class image_delete(_init_cyclades):
 
     def main(self, image_id):
         super(self.__class__, self)._run()
-        self._run(image_id)
+        self._run(image_id=image_id)
 
 
 @command(image_cmds)
@@ -367,7 +367,7 @@ class image_properties(_init_cyclades):
 
     def main(self, image_id, key=''):
         super(self.__class__, self)._run()
-        self._run(image_id, key)
+        self._run(image_id=image_id, key=key)
 
 
 @command(image_cmds)
@@ -377,13 +377,14 @@ class image_addproperty(_init_cyclades):
     @errors.generic.all
     @errors.cyclades.connection
     @errors.plankton.id
+    @errors.plankton.metadata
     def _run(self, image_id, key, val):
         r = self.client.create_image_metadata(image_id, key, val)
         print_dict(r)
 
     def main(self, image_id, key, val):
         super(self.__class__, self)._run()
-        self._run(image_id, key, val)
+        self._run(image_id=image_id, key=key, val=val)
 
 
 @command(image_cmds)
@@ -393,6 +394,7 @@ class image_setproperty(_init_cyclades):
     @errors.generic.all
     @errors.cyclades.connection
     @errors.plankton.id
+    @errors.plankton.metadata
     def _run(self, image_id, key, val):
         metadata = {key: val}
         r = self.client.update_image_metadata(image_id, **metadata)
@@ -400,7 +402,7 @@ class image_setproperty(_init_cyclades):
 
     def main(self, image_id, key, val):
         super(self.__class__, self)._run()
-        self._run(image_id, key, val)
+        self._run(image_id=image_id, key=key, val=val)
 
 
 @command(image_cmds)
@@ -416,4 +418,4 @@ class image_delproperty(_init_cyclades):
 
     def main(self, image_id, key):
         super(self.__class__, self)._run()
-        self._run(image_id, key)
+        self._run(image_id=image_id, key=key)