Make wait mechanism usble by more cyclades methods
authorStavros Sachtouris <saxtouri@admin.grnet.gr>
Wed, 26 Jun 2013 13:47:22 +0000 (16:47 +0300)
committerStavros Sachtouris <saxtouri@admin.grnet.gr>
Wed, 26 Jun 2013 13:47:22 +0000 (16:47 +0300)
Refs: #3867

kamaki/cli/__init__.py
kamaki/cli/commands/cyclades.py
kamaki/clients/cyclades/__init__.py

index fe91d07..8c24ad2 100644 (file)
@@ -39,7 +39,7 @@ from inspect import getargspec
 from kamaki.cli.argument import ArgumentParseManager
 from kamaki.cli.history import History
 from kamaki.cli.utils import print_dict, red, magenta, yellow
-from kamaki.cli.errors import CLIError
+from kamaki.cli.errors import CLIError, CLICmdSpecError
 from kamaki.cli import logger
 
 _help = False
@@ -146,9 +146,13 @@ def command(cmd_tree, prefix='', descedants_depth=1):
                 kloger.warning('%s failed max_len test' % cls_name)
             return None
 
-        (
-            cls.description, sep, cls.long_description
-        ) = cls.__doc__.partition('\n')
+        try:
+            (
+                cls.description, sep, cls.long_description
+            ) = cls.__doc__.partition('\n')
+        except AttributeError:
+            raise CLICmdSpecError(
+                'No commend in %s (acts as cmd description)' % cls.__name__)
         _construct_command_syntax(cls)
 
         cmd_tree.add_command(cls_name, cls.description, cls)
index 9e8ffc6..16bfdf6 100644 (file)
@@ -87,7 +87,6 @@ class _server_wait(object):
                 currect_status,
                 wait_cb=wait_cb)
         except Exception:
-            self._safe_progress_bar_finish(progress_bar)
             raise
         finally:
             self._safe_progress_bar_finish(progress_bar)
@@ -97,6 +96,35 @@ class _server_wait(object):
             raiseCLIError(None, 'Time out')
 
 
+class _network_wait(object):
+
+    wait_arguments = dict(
+        progress_bar=ProgressBarArgument(
+            'do not show progress bar',
+            ('-N', '--no-progress-bar'),
+            False
+        )
+    )
+
+    def _wait(self, net_id, currect_status):
+        (progress_bar, wait_cb) = self._safe_progress_bar(
+            'Network %s still in %s mode' % (net_id, currect_status))
+
+        try:
+            new_mode = self.client.wait_network(
+                net_id,
+                currect_status,
+                wait_cb=wait_cb)
+        except Exception:
+            raise
+        finally:
+            self._safe_progress_bar_finish(progress_bar)
+        if new_mode:
+            print('Network %s is now in %s mode' % (net_id, new_mode))
+        else:
+            raiseCLIError(None, 'Time out')
+
+
 class _init_cyclades(_command_init):
     @errors.generic.all
     @addLogSettings
@@ -778,6 +806,21 @@ class network_disconnect(_init_cyclades):
         self._run(nic_id=nic_id, server_id=server_id)
 
 
+@command(network_cmds)
+class network_wait(_init_cyclades, _network_wait):
+    """Wait for server to finish [PENDING, ACTIVE, DELETED]"""
+
+    @errors.generic.all
+    @errors.cyclades.connection
+    @errors.cyclades.network_id
+    def _run(self, network_id, currect_status):
+        self._wait(network_id, currect_status)
+
+    def main(self, network_id, currect_status='PENDING'):
+        super(self.__class__, self)._run()
+        self._run(network_id=network_id, currect_status=currect_status)
+
+
 @command(floatingip_cmds)
 class floatingip_pools(_init_cyclades, _optional_json):
     """List all floating pools of floating ips"""
index 36dc828..6981e4d 100644 (file)
@@ -257,66 +257,104 @@ class CycladesClient(CycladesRestClient):
             req = dict(remove=dict(attachment=nic))
             self.networks_post(netid, 'action', json_data=req)
 
-    def wait_server(
-            self,
-            server_id,
-            current_status='BUILD',
-            delay=0.5,
-            max_wait=128,
-            wait_cb=None):
-        """Wait for server while its status is current_status
+    def _wait(
+            self, item_id, current_status, get_status,
+            delay=1, max_wait=100, wait_cb=None):
+        """Wait for item while its status is current_status
 
         :param server_id: integer (str or int)
 
-        :param current_status: (str) BUILD|ACTIVE|STOPPED|DELETED|REBOOT
+        :param current_status: (str)
+
+        :param get_status: (method(self, item_id)) if called, returns
+            (status, progress %) If no way to tell progress, return None
 
         :param delay: time interval between retries
 
-        :param wait_cb: if set a progressbar is used to show progress
+        :param wait_cb: if set a progress bar is used to show progress
 
-        :returns: (str) the new mode if succesfull, (bool) False if timed out
+        :returns: (str) the new mode if successful, (bool) False if timed out
         """
-        r = self.get_server_details(server_id)
-        if r['status'] != current_status:
-            return r['status']
+        status, progress = get_status(self, item_id)
+        if status != current_status:
+            return status
         old_wait = total_wait = 0
 
-        if current_status == 'BUILD':
-            max_wait = 100
-            wait_gen = wait_cb(max_wait) if wait_cb else None
-        elif wait_cb:
+        if wait_cb:
             wait_gen = wait_cb(1 + max_wait // delay)
             wait_gen.next()
 
-        while r['status'] == current_status and total_wait <= max_wait:
-            if current_status == 'BUILD':
-                total_wait = int(r['progress'])
-                if wait_cb:
-                    for i in range(int(old_wait), int(total_wait)):
+        while status == current_status and total_wait <= max_wait:
+            if wait_cb:
+                try:
+                    for i in range(total_wait - old_wait):
                         wait_gen.next()
-                    old_wait = total_wait
-                else:
-                    stdout.write('.')
-                    stdout.flush()
+                except Exception:
+                    break
             else:
-                if wait_cb:
-                    wait_gen.next()
-                else:
-                    stdout.write('.')
-                    stdout.flush()
-                total_wait += delay
+                stdout.write('.')
+                stdout.flush()
+            old_wait = total_wait
+            total_wait = progress or (total_wait + 1)
             sleep(delay)
-            r = self.get_server_details(server_id)
+            status, progress = get_status(self, item_id)
 
-        if r['status'] != current_status:
+        if total_wait < max_wait:
             if wait_cb:
                 try:
-                    while True:
+                    for i in range(max_wait):
                         wait_gen.next()
                 except:
                     pass
-            return r['status']
-        return False
+        return status if status != current_status else False
+
+    def wait_server(
+            self, server_id,
+            current_status='BUILD',
+            delay=1, max_wait=100, wait_cb=None):
+        """Wait for server while its status is current_status
+
+        :param server_id: integer (str or int)
+
+        :param current_status: (str) BUILD|ACTIVE|STOPPED|DELETED|REBOOT
+
+        :param delay: time interval between retries
+
+        :param wait_cb: if set a progressbar is used to show progress
+
+        :returns: (str) the new mode if succesfull, (bool) False if timed out
+        """
+
+        def get_status(self, server_id):
+            r = self.get_server_details(server_id)
+            return r['status'], (r.get('progress', None) if (
+                            current_status in ('BUILD', )) else None)
+
+        return self._wait(
+            server_id, current_status, get_status, delay, max_wait, wait_cb)
+
+    def wait_network(
+            self, net_id,
+            current_status='LALA', delay=1, max_wait=100, wait_cb=None):
+        """Wait for network while its status is current_status
+
+        :param net_id: integer (str or int)
+
+        :param current_status: (str) PENDING | ACTIVE | DELETED
+
+        :param delay: time interval between retries
+
+        :param wait_cb: if set a progressbar is used to show progress
+
+        :returns: (str) the new mode if succesfull, (bool) False if timed out
+        """
+
+        def get_status(self, net_id):
+            r = self.get_network_details(net_id)
+            return r['status'], None
+
+        return self._wait(
+            net_id, current_status, get_status, delay, max_wait, wait_cb)
 
     def get_floating_ip_pools(self):
         """