Test and debug a generic progress bar for tests
authorStavros Sachtouris <saxtouri@admin.grnet.gr>
Tue, 5 Feb 2013 15:33:35 +0000 (17:33 +0200)
committerStavros Sachtouris <saxtouri@admin.grnet.gr>
Tue, 5 Feb 2013 15:33:35 +0000 (17:33 +0200)
in client

kamaki/cli/utils.py
kamaki/clients/cyclades.py
kamaki/clients/tests/__init__.py
kamaki/clients/tests/cyclades.py

index 01ded66..4c7b76d 100644 (file)
@@ -33,6 +33,8 @@
 
 from sys import stdout, stdin
 from re import compile as regex_compile
+from time import sleep
+
 from kamaki.cli.errors import raiseCLIError
 
 try:
@@ -393,14 +395,16 @@ def ask_user(msg, true_resp=['Y', 'y']):
     return user_response[0] in true_resp + ['\n']
 
 
-def spiner():
+def spiner(size=None):
     spins = ('/', '-', '\\', '|')
-    i = 0
     stdout.write(' ')
-    while True:
+    size = size or -1
+    i = 0
+    while size - i:
         stdout.write('\b%s' % spins[i % len(spins)])
         stdout.flush()
         i += 1
+        sleep(0.1)
         yield
 
 if __name__ == '__main__':
index 21befb0..80179c1 100644 (file)
 # interpreted as representing official policies, either expressed
 # or implied, of GRNET S.A.
 
+from time import sleep
+
 from kamaki.clients.cyclades_rest_api import CycladesClientApi
 from kamaki.clients import ClientError
-from time import sleep
+from sys import stdout
 
 
 class CycladesClient(CycladesClientApi):
@@ -277,9 +279,15 @@ class CycladesClient(CycladesClientApi):
                     for i in range(int(old_wait), int(total_wait)):
                         wait_gen.next()
                     old_wait = total_wait
+                else:
+                    stdout.write('.')
+                    stdout.flush()
             else:
                 if wait_cb:
                     wait_gen.next()
+                else:
+                    stdout.write('.')
+                    stdout.flush()
                 total_wait += delay
             sleep(delay)
             r = self.get_server_details(server_id)
index 1c4c8aa..4984e2e 100644 (file)
 from unittest import TestCase, TestSuite, makeSuite, TextTestRunner
 from argparse import ArgumentParser
 from sys import stdout
-from traceback import extract_stack, print_stack
 from progress.bar import ShadyBar
 
 from kamaki.cli.config import Config
+from kamaki.cli.utils import spiner
 
 
 def _add_value(foo, value):
@@ -48,6 +48,7 @@ def _add_value(foo, value):
 
 class Generic(TestCase):
 
+    _waits = []
     _cnf = None
     _grp = None
     _fetched = {}
@@ -56,6 +57,9 @@ class Generic(TestCase):
         super(Generic, self).__init__(specific)
         self._cnf = Config(config_file)
         self._grp = group
+        self._waits.append(0.71828)
+        for i in range(10):
+            self._waits.append(self._waits[-1] * 2.71828)
 
     def __getitem__(self, key):
         key = self._key(key)
@@ -83,20 +87,34 @@ class Generic(TestCase):
     def _safe_progress_bar(self, msg):
         """Try to get a progress bar, but do not raise errors"""
         try:
-            progress_bar = ShadyBar()
-            gen = progress_bar.get_generator(msg)
+            wait_bar = ShadyBar(msg)
+
+            def wait_gen(n):
+                for i in wait_bar.iter(range(int(n))):
+                    yield
+                yield
+            wait_cb = wait_gen
         except Exception:
-            return (None, None)
-        return (progress_bar, gen)
+            stdout.write('%s:' % msg)
+            (wait_bar, wait_cb) = (None, spiner)
+        return (wait_bar, wait_cb)
 
     def _safe_progress_bar_finish(self, progress_bar):
         try:
             progress_bar.finish()
         except Exception:
-            pass
-
-    def do_with_progress_bar(self, action, msg, list, *args, **kwargs):
-        (action_bar, action_cb) = self._safe_progress_bar('')
+            print(' DONE')
+
+    def do_with_progress_bar(self, action, msg, items):
+        if not items:
+            print('%s: DONE' % msg)
+            return
+        (action_bar, action_cb) = self._safe_progress_bar(msg)
+        action_gen = action_cb(len(items))
+        for item in items:
+            action(item)
+            action_gen.next()
+        self._safe_progress_bar_finish(action_bar)
 
     def assert_dicts_are_deeply_equal(self, d1, d2):
         for k, v in d1.items():
@@ -144,13 +162,11 @@ def main(argv):
             suiteFew.addTest(unittest.makeSuite(testPithos))
         else:
             suiteFew.addTest(testPithos('test_' + argv[1]))
-    if len(argv) == 0 or argv[0] == 'cyclades':
-        if len(argv) == 1:
-            #suiteFew.addTest(unittest.makeSuite(testCyclades))
-            suiteFew.addTest(testCyclades('test_000'))
-        else:
-            suiteFew.addTest(testCyclades('test_' + argv[1]))
     """
+    if len(argv) == 0 or argv[0] == 'cyclades':
+        from kamaki.clients.tests.cyclades import Cyclades
+        test_method = 'test_%s' % (argv[1] if len(argv) > 1 else '000')
+        suiteFew.addTest(Cyclades(test_method))
     if len(argv) == 0 or argv[0] == 'image':
         from kamaki.clients.tests.image import Image
         test_method = 'test_%s' % (argv[1] if len(argv) > 1 else '000')
index f938569..48a5d0e 100644 (file)
@@ -32,8 +32,9 @@
 # or implied, of GRNET S.A.
 
 import time
+from progress.bar import ShadyBar
 
-from kamaki.clients import tests
+from kamaki.clients import tests, ClientError
 from kamaki.clients.cyclades import CycladesClient
 
 
@@ -86,14 +87,15 @@ class Cyclades(tests.Generic):
 
     def tearDown(self):
         """Destoy servers used in testing"""
-        print
-        for netid in self.networks.keys():
-            self._delete_network(netid)
-        if 0 >= len(self.servers):
-            return
-        print('-> Found %s servers to delete' % len(self.servers))
-        for server in self.servers.values():
-            self._delete_server(server['id'])
+        self.do_with_progress_bar(
+            self._delete_network,
+            'Delete %s networks' % len(self.networks),
+            self.networks.keys())
+        server_list = [server['id'] for server in self.servers.values()]
+        self.do_with_progress_bar(
+            self._delete_server,
+            'Delete %s servers %s' % (len(server_list), server_list),
+            server_list)
 
     def _create_server(self, servername, flavorid, imageid, personality=None):
         server = self.client.create_server(servername,
@@ -111,8 +113,8 @@ class Cyclades(tests.Generic):
                 return
         except:
             return
-        self.client.delete_server(servid)
         self._wait_for_status(servid, current_state)
+        self.client.delete_server(servid)
 
     def _create_network(self, netname, **kwargs):
         net = self.client.create_network(netname, **kwargs)
@@ -120,16 +122,91 @@ class Cyclades(tests.Generic):
         return net
 
     def _delete_network(self, netid):
-        sys.stdout.write('\tDelete network %s ' % netid)
+        print('Disconnect nics of network %s' % netid)
         self.client.disconnect_network_nics(netid)
-        wait = 3
-        while True:
+
+        def netwait(self, wait):
             try:
                 self.client.delete_network(netid)
-                print('\n\tSUCCESFULL COMMIT delete network %s' % netid)
-                break
-            except ClientError as err:
-                self.assertEqual(err.status, 421)
+            except ClientError:
                 time.sleep(wait)
-                wait += 3
-                sys.stdout.write('.')
+        self.do_with_progress_bar(
+            netwait,
+            'Delete network %s' % netid,
+            self._waits[:5])
+
+    def _wait_for_network(self, netid, status):
+
+        def netwait(self, wait):
+            r = self.client.get_network_details(netid)
+            if r['status'] == status:
+                return
+            time.sleep(wait)
+        self.do_with_progress_bar(
+            netwait,
+            'Wait network %s to reach status %s' % (netid, status),
+            self._waits[:5])
+
+    def _wait_for_nic(self, netid, servid, in_creation=True):
+        self._wait_for_network(netid, 'ACTIVE')
+
+        def nicwait(self, wait):
+            nics = self.client.list_server_nics(servid)
+            for net in nics:
+                found_nic = net['network_id'] == netid
+                if (in_creation and found_nic)\
+                or not (in_creation or found_nic):
+                    return
+            time.sleep(wait)
+        self.do_with_progress_bar(
+            nicwait,
+            'Wait nic-%s-%s to %sconnect' % (
+                netid,
+                servid,
+                '' if in_creation else 'dis'),
+            self._waits[:5])
+
+    def _has_status(self, servid, status):
+        r = self.client.get_server_details(servid)
+        return r['status'] == status
+
+    def _wait_for_status(self, servid, status):
+        (wait_bar, wait_cb) = self._safe_progress_bar(
+            'Server %s in %s' % (servid, status))
+        self.client.wait_server(servid, status, wait_cb=wait_cb)
+        self._safe_progress_bar_finish(wait_bar)
+
+    def test_list_servers(self):
+        """Test list servers"""
+        self.server1 = self._create_server(
+            self.servname1,
+            self.flavorid,
+            self.img)
+        return
+        self.server2 = self._create_server(
+            self.servname2,
+            self.flavorid + 2,
+            self.img)
+        self._test_list_servers()
+
+    def _test_list_servers(self):
+        servers = self.client.list_servers()
+        dservers = self.client.list_servers(detail=True)
+
+        """detailed and simple are same size"""
+        self.assertEqual(len(dservers), len(servers))
+        for i in range(len(servers)):
+            for field in ('created',
+            'flavorRef',
+            'hostId',
+            'imageRef',
+            'progress',
+            'status',
+            'updated'):
+                self.assertFalse(field in servers[i])
+                self.assertTrue(field in dservers[i])
+
+        """detailed and simple contain same names"""
+        names = sorted(map(lambda x: x["name"], servers))
+        dnames = sorted(map(lambda x: x["name"], dservers))
+        self.assertEqual(names, dnames)