Fix "TypeError: format requires a mapping" in waiters

This is to fix the "TypeError: format requires a mapping" in
wait_for_image_imported_to_stores and wait_for_image_copied_to_stores.

Change-Id: I8a33bd4f4ea189ce9247dfecec1e53001682b870
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 789daaf..424fc5c 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -207,8 +207,8 @@
 
         time.sleep(client.build_interval)
 
-    message = ('Image %(image_id)s failed to import '
-               'on stores: %s' % str(image['os_glance_failed_import']))
+    message = ('Image %s failed to import on stores: %s' %
+               (image_id, str(image['os_glance_failed_import'])))
     caller = test_utils.find_test_caller()
     if caller:
         message = '(%s) %s' % (caller, message)
@@ -238,8 +238,8 @@
 
         time.sleep(client.build_interval)
 
-    message = ('Image %(image_id)s failed to finish the copy operation '
-               'on stores: %s' % str(store_left))
+    message = ('Image %s failed to finish the copy operation '
+               'on stores: %s' % (image_id, str(store_left)))
     caller = test_utils.find_test_caller()
     if caller:
         message = '(%s) %s' % (caller, message)
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index 73924bd..06c17e0 100755
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -55,6 +55,56 @@
                           waiters.wait_for_image_status,
                           self.client, 'fake_image_id', 'active')
 
+    def test_wait_for_image_imported_to_stores(self):
+        self.client.show_image.return_value = ({'status': 'active',
+                                                'stores': 'fake_store'})
+        start_time = int(time.time())
+        waiters.wait_for_image_imported_to_stores(
+            self.client, 'fake_image_id', 'fake_store')
+        end_time = int(time.time())
+        # Ensure waiter returns before build_timeout
+        self.assertLess((end_time - start_time), 10)
+
+    def test_wait_for_image_imported_to_stores_timeout(self):
+        time_mock = self.patch('time.time')
+        client = mock.MagicMock()
+        client.build_timeout = 2
+        self.patch('time.time', side_effect=[0., 1., 2.])
+        time_mock.side_effect = utils.generate_timeout_series(1)
+
+        client.show_image.return_value = ({
+            'status': 'saving',
+            'stores': 'fake_store',
+            'os_glance_failed_import': 'fake_os_glance_failed_import'})
+        self.assertRaises(lib_exc.TimeoutException,
+                          waiters.wait_for_image_imported_to_stores,
+                          client, 'fake_image_id', 'fake_store')
+
+    def test_wait_for_image_copied_to_stores(self):
+        self.client.show_image.return_value = ({
+            'status': 'active',
+            'os_glance_importing_to_stores': '',
+            'os_glance_failed_import': 'fake_os_glance_failed_import'})
+        start_time = int(time.time())
+        waiters.wait_for_image_copied_to_stores(
+            self.client, 'fake_image_id')
+        end_time = int(time.time())
+        # Ensure waiter returns before build_timeout
+        self.assertLess((end_time - start_time), 10)
+
+    def test_wait_for_image_copied_to_stores_timeout(self):
+        time_mock = self.patch('time.time')
+        self.patch('time.time', side_effect=[0., 1.])
+        time_mock.side_effect = utils.generate_timeout_series(1)
+
+        self.client.show_image.return_value = ({
+            'status': 'active',
+            'os_glance_importing_to_stores': 'processing',
+            'os_glance_failed_import': 'fake_os_glance_failed_import'})
+        self.assertRaises(lib_exc.TimeoutException,
+                          waiters.wait_for_image_copied_to_stores,
+                          self.client, 'fake_image_id')
+
 
 class TestInterfaceWaiters(base.TestCase):