Merge "Ensure extension aliases are used for nova based services"
diff --git a/tempest/api/baremetal/admin/test_ports.py b/tempest/api/baremetal/admin/test_ports.py
index b3f9b7f..3392ab9 100644
--- a/tempest/api/baremetal/admin/test_ports.py
+++ b/tempest/api/baremetal/admin/test_ports.py
@@ -57,11 +57,13 @@
         _, body = self.client.show_port(uuid)
         self._assertExpected(port, body)
 
+    @test.skip_because(bug='1398350')
     @test.attr(type='smoke')
     def test_create_port_with_extra(self):
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
-        extra = {'key': 'value'}
+        extra = {'str': 'value', 'int': 123, 'float': 0.123,
+                 'bool': True, 'list': [1, 2, 3], 'dict': {'foo': 'bar'}}
 
         _, port = self.create_port(node_id=node_id, address=address,
                                    extra=extra)
@@ -224,6 +226,7 @@
         _, body = self.client.show_port(port['uuid'])
         self.assertEqual(extra, body['extra'])
 
+    @test.skip_because(bug='1398350')
     @test.attr(type='smoke')
     def test_update_port_mixed_ops(self):
         node_id = self.node['uuid']
@@ -234,7 +237,7 @@
                                    extra=extra)
 
         new_address = data_utils.rand_mac_address()
-        new_extra = {'key1': 'new-value1', 'key3': 'new-value3'}
+        new_extra = {'key1': 0.123, 'key3': {'cat': 'meow'}}
 
         patch = [{'path': '/address',
                   'op': 'replace',
diff --git a/tempest/api/baremetal/admin/test_ports_negative.py b/tempest/api/baremetal/admin/test_ports_negative.py
index ead3799..8080eb6 100644
--- a/tempest/api/baremetal/admin/test_ports_negative.py
+++ b/tempest/api/baremetal/admin/test_ports_negative.py
@@ -34,15 +34,6 @@
                           self.create_port, node_id=node_id, address=address)
 
     @test.attr(type=['negative', 'smoke'])
-    def test_create_port_malformed_extra(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key': 0.123}
-        self.assertRaises(exc.BadRequest,
-                          self.create_port, node_id=node_id,
-                          address=address, extra=extra)
-
-    @test.attr(type=['negative', 'smoke'])
     def test_create_port_nonexsistent_node_id(self):
         node_id = str(data_utils.rand_uuid())
         address = data_utils.rand_mac_address()
@@ -160,31 +151,6 @@
                                   'value': new_address}])
 
     @test.attr(type=['negative', 'smoke'])
-    def test_update_port_add_malformed_extra(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
-                          [{'path': '/extra/key', ' op': 'add',
-                            'value': 0.123}])
-
-    @test.attr(type=['negative', 'smoke'])
-    def test_update_port_add_whole_malformed_extra(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        self.assertRaises(exc.BadRequest, self.client.update_port, port_id,
-                          [{'path': '/extra',
-                            'op': 'add',
-                            'value': [1, 2, 3, 4, 'a']}])
-
-    @test.attr(type=['negative', 'smoke'])
     def test_update_port_add_nonexistent_property(self):
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
@@ -257,37 +223,6 @@
                           self.client.update_port, port_id, patch)
 
     @test.attr(type=['negative', 'smoke'])
-    def test_update_port_replace_extra_item_with_malformed(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-        extra = {'key': 'value'}
-
-        _, port = self.create_port(node_id=node_id, address=address,
-                                   extra=extra)
-        port_id = port['uuid']
-
-        patch = [{'path': '/extra/key',
-                  'op': 'replace',
-                  'value': 0.123}]
-        self.assertRaises(exc.BadRequest,
-                          self.client.update_port, port_id, patch)
-
-    @test.attr(type=['negative', 'smoke'])
-    def test_update_port_replace_whole_extra_with_malformed(self):
-        node_id = self.node['uuid']
-        address = data_utils.rand_mac_address()
-
-        _, port = self.create_port(node_id=node_id, address=address)
-        port_id = port['uuid']
-
-        patch = [{'path': '/extra',
-                  'op': 'replace',
-                  'value': [1, 2, 3, 4, 'a']}]
-
-        self.assertRaises(exc.BadRequest,
-                          self.client.update_port, port_id, patch)
-
-    @test.attr(type=['negative', 'smoke'])
     def test_update_port_replace_nonexistent_property(self):
         node_id = self.node['uuid']
         address = data_utils.rand_mac_address()
diff --git a/tempest/api/network/test_fwaas_extensions.py b/tempest/api/network/test_fwaas_extensions.py
index 12b8887..0c36820 100644
--- a/tempest/api/network/test_fwaas_extensions.py
+++ b/tempest/api/network/test_fwaas_extensions.py
@@ -38,6 +38,8 @@
         Update firewall policy
         Insert firewall rule to policy
         Remove firewall rule from policy
+        Insert firewall rule after/before rule in policy
+        Update firewall policy audited attribute
         Delete firewall policy
         Show firewall policy
         List firewall
@@ -222,14 +224,14 @@
         self.client.delete_firewall(firewall_id)
 
     @test.attr(type='smoke')
-    def test_insert_remove_firewall_rule_from_policy(self):
+    def test_firewall_rule_insertion_position_removal_rule_from_policy(self):
         # Create firewall rule
         resp, body = self.client.create_firewall_rule(
             name=data_utils.rand_name("fw-rule"),
             action="allow",
             protocol="tcp")
-        fw_rule_id = body['firewall_rule']['id']
-        self.addCleanup(self._try_delete_rule, fw_rule_id)
+        fw_rule_id1 = body['firewall_rule']['id']
+        self.addCleanup(self._try_delete_rule, fw_rule_id1)
         # Create firewall policy
         _, body = self.client.create_firewall_policy(
             name=data_utils.rand_name("fw-policy"))
@@ -238,19 +240,76 @@
 
         # Insert rule to firewall policy
         self.client.insert_firewall_rule_in_policy(
-            fw_policy_id, fw_rule_id, '', '')
+            fw_policy_id, fw_rule_id1, '', '')
 
         # Verify insertion of rule in policy
-        self.assertIn(fw_rule_id, self._get_list_fw_rule_ids(fw_policy_id))
+        self.assertIn(fw_rule_id1, self._get_list_fw_rule_ids(fw_policy_id))
+        # Create another firewall rule
+        _, body = self.client.create_firewall_rule(
+            name=data_utils.rand_name("fw-rule"),
+            action="allow",
+            protocol="icmp")
+        fw_rule_id2 = body['firewall_rule']['id']
+        self.addCleanup(self._try_delete_rule, fw_rule_id2)
+
+        # Insert rule to firewall policy after the first rule
+        self.client.insert_firewall_rule_in_policy(
+            fw_policy_id, fw_rule_id2, fw_rule_id1, '')
+
+        # Verify the posiition of rule after insertion
+        _, fw_rule = self.client.show_firewall_rule(
+            fw_rule_id2)
+
+        self.assertEqual(int(fw_rule['firewall_rule']['position']), 2)
         # Remove rule from the firewall policy
         self.client.remove_firewall_rule_from_policy(
-            fw_policy_id, fw_rule_id)
+            fw_policy_id, fw_rule_id2)
+        # Insert rule to firewall policy before the first rule
+        self.client.insert_firewall_rule_in_policy(
+            fw_policy_id, fw_rule_id2, '', fw_rule_id1)
+        # Verify the posiition of rule after insertion
+        _, fw_rule = self.client.show_firewall_rule(
+            fw_rule_id2)
+        self.assertEqual(int(fw_rule['firewall_rule']['position']), 1)
+        # Remove rule from the firewall policy
+        self.client.remove_firewall_rule_from_policy(
+            fw_policy_id, fw_rule_id2)
+        # Verify removal of rule from firewall policy
+        self.assertNotIn(fw_rule_id2, self._get_list_fw_rule_ids(fw_policy_id))
+
+        # Remove rule from the firewall policy
+        self.client.remove_firewall_rule_from_policy(
+            fw_policy_id, fw_rule_id1)
 
         # Verify removal of rule from firewall policy
-        self.assertNotIn(fw_rule_id, self._get_list_fw_rule_ids(fw_policy_id))
+        self.assertNotIn(fw_rule_id1, self._get_list_fw_rule_ids(fw_policy_id))
 
     def _get_list_fw_rule_ids(self, fw_policy_id):
         _, fw_policy = self.client.show_firewall_policy(
             fw_policy_id)
         return [ruleid for ruleid in fw_policy['firewall_policy']
                 ['firewall_rules']]
+
+    def test_update_firewall_policy_audited_attribute(self):
+        # Create firewall rule
+        _, body = self.client.create_firewall_rule(
+            name=data_utils.rand_name("fw-rule"),
+            action="allow",
+            protocol="icmp")
+        fw_rule_id = body['firewall_rule']['id']
+        self.addCleanup(self._try_delete_rule, fw_rule_id)
+        # Create firewall policy
+        _, body = self.client.create_firewall_policy(
+            name=data_utils.rand_name('fw-policy'))
+        fw_policy_id = body['firewall_policy']['id']
+        self.addCleanup(self._try_delete_policy, fw_policy_id)
+        self.assertFalse(body['firewall_policy']['audited'])
+        # Update firewall policy audited attribute to ture
+        self.client.update_firewall_policy(fw_policy_id,
+                                           audited=True)
+        # Insert Firewall rule to firewall policy
+        self.client.insert_firewall_rule_in_policy(
+            fw_policy_id, fw_rule_id, '', '')
+        _, body = self.client.show_firewall_policy(
+            fw_policy_id)
+        self.assertFalse(body['firewall_policy']['audited'])
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 52568cb..93f02c9 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -111,22 +111,24 @@
     while image['status'] != status:
         time.sleep(client.build_interval)
         resp, image = client.get_image(image_id)
-        if image['status'] == 'ERROR':
+        status_curr = image['status']
+        if status_curr == 'ERROR':
             raise exceptions.AddImageException(image_id=image_id)
 
         # check the status again to avoid a false negative where we hit
         # the timeout at the same time that the image reached the expected
         # status
-        if image['status'] == status:
+        if status_curr == status:
             return
 
         if int(time.time()) - start >= client.build_timeout:
-            message = ('Image %(image_id)s failed to reach %(status)s '
-                       'status within the required time (%(timeout)s s).' %
+            message = ('Image %(image_id)s failed to reach %(status)s state'
+                       '(current state %(status_curr)s) '
+                       'within the required time (%(timeout)s s).' %
                        {'image_id': image_id,
                         'status': status,
+                        'status_curr': status_curr,
                         'timeout': client.build_timeout})
-            message += ' Current status: %s.' % image['status']
             caller = misc_utils.find_test_caller()
             if caller:
                 message = '(%s) %s' % (caller, message)
@@ -144,7 +146,8 @@
     while node[attr] != status:
         time.sleep(client.build_interval)
         _, node = client.show_node(node_id)
-        if node[attr] == status:
+        status_curr = node[attr]
+        if status_curr == status:
             return
 
         if int(time.time()) - start >= client.build_timeout:
@@ -154,7 +157,7 @@
                         'attr': attr,
                         'status': status,
                         'timeout': client.build_timeout})
-            message += ' Current state of %s: %s.' % (attr, node[attr])
+            message += ' Current state of %s: %s.' % (attr, status_curr)
             caller = misc_utils.find_test_caller()
             if caller:
                 message = '(%s) %s' % (caller, message)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 522aa43..e46ec6d 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -297,7 +297,19 @@
 
         return secgroup
 
-    def get_remote_client(self, server_or_ip, username=None, private_key=None):
+    def get_remote_client(self, server_or_ip, username=None, private_key=None,
+                          log_console_of_servers=None):
+        """Get a SSH client to a remote server
+
+        @param server_or_ip a server object as returned by Tempest compute
+            client or an IP address to connect to
+        @param username name of the Linux account on the remote server
+        @param private_key the SSH private key to use
+        @param log_console_of_servers a list of server objects. Each server
+            in the list will have its console printed in the logs in case the
+            SSH connection failed to be established
+        @return a RemoteClient object
+        """
         if isinstance(server_or_ip, six.string_types):
             ip = server_or_ip
         else:
@@ -312,9 +324,13 @@
                                                   pkey=private_key)
         try:
             linux_client.validate_authentication()
-        except exceptions.SSHTimeout:
-            LOG.exception('ssh connection to %s failed' % ip)
+        except Exception:
+            LOG.exception('Initializing SSH connection to %s failed' % ip)
             debug.log_net_debug()
+            # If we don't explicitely set for which servers we want to
+            # log the console output then all the servers will be logged.
+            # See the definition of _log_console_output()
+            self._log_console_output(log_console_of_servers)
             raise
 
         return linux_client
@@ -989,6 +1005,10 @@
         self.addCleanup(self.delete_wrapper, router.delete)
         return router
 
+    def _update_router_admin_state(self, router, admin_state_up):
+        router.update(admin_state_up=admin_state_up)
+        self.assertEqual(admin_state_up, router.admin_state_up)
+
     def create_networks(self, client=None, tenant_id=None):
         """Create a network with a subnet connected to a router.
 
diff --git a/tempest/scenario/orchestration/test_server_cfn_init.py b/tempest/scenario/orchestration/test_server_cfn_init.py
index ddfabe4..f09f00c 100644
--- a/tempest/scenario/orchestration/test_server_cfn_init.py
+++ b/tempest/scenario/orchestration/test_server_cfn_init.py
@@ -119,14 +119,8 @@
         if self.keypair:
             # Check that the user can authenticate with the generated
             # keypair
-            try:
-                linux_client = self.get_remote_client(
-                    server_ip, username='ec2-user')
-                linux_client.validate_authentication()
-            except (exceptions.ServerUnreachable,
-                    exceptions.SSHTimeout) as e:
-                self._log_console_output(servers=[server])
-                raise e
+            self.get_remote_client(server_ip, username='ec2-user',
+                                   log_console_of_servers=[server])
 
     @test.attr(type='slow')
     @test.skip_because(bug='1374175')
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 59af6b3..16a65c9 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest.common import custom_matchers
-from tempest.common import debug
 from tempest import config
 from tempest import exceptions
 from tempest.openstack.common import log as logging
@@ -89,17 +88,6 @@
         self.servers_client.reboot(self.server['id'], 'SOFT')
         self._wait_for_server_status('ACTIVE')
 
-    def ssh_to_server(self):
-        try:
-            self.linux_client = self.get_remote_client(self.floating_ip['ip'])
-        except Exception as e:
-            LOG.exception('ssh to server failed')
-            self._log_console_output()
-            # network debug is called as part of ssh init
-            if not isinstance(e, test.exceptions.SSHTimeout):
-                debug.log_net_debug()
-            raise
-
     def check_partitions(self):
         # NOTE(andreaf) The device name may be different on different guest OS
         partitions = self.linux_client.get_partitions()
@@ -147,7 +135,9 @@
 
         self.floating_ip = self.create_floating_ip(self.server)
         self.create_and_add_security_group()
-        self.ssh_to_server()
+
+        self.linux_client = self.get_remote_client(self.floating_ip['ip'])
         self.nova_reboot()
-        self.ssh_to_server()
+
+        self.linux_client = self.get_remote_client(self.floating_ip['ip'])
         self.check_partitions()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 9618124..98a059f 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -170,8 +170,9 @@
                     server, ssh_login, self._get_server_key(server),
                     servers_for_debug=self.servers)
 
-    def check_public_network_connectivity(self, should_connect=True,
-                                          msg=None):
+    def check_public_network_connectivity(
+            self, should_connect=True, msg=None,
+            should_check_floating_ip_status=True):
         """Verifies connectivty to a VM via public network and floating IP,
         and verifies floating IP has resource status is correct.
 
@@ -180,6 +181,8 @@
         :param msg: Failure message to add to Error message. Should describe
         the place in the test scenario where the method was called,
         to indicate the context of the failure
+        :param should_check_floating_ip_status: bool. should status of
+        floating_ip be checked or not
         """
         ssh_login = CONF.compute.image_ssh_user
         floating_ip, server = self.floating_ip_tuple
@@ -193,7 +196,8 @@
         super(TestNetworkBasicOps, self).check_public_network_connectivity(
             ip_address, ssh_login, private_key, should_connect, msg,
             self.servers)
-        self.check_floating_ip_status(floating_ip, floatingip_status)
+        if should_check_floating_ip_status:
+            self.check_floating_ip_status(floating_ip, floatingip_status)
 
     def _disassociate_floating_ips(self):
         floating_ip, server = self.floating_ip_tuple
@@ -393,3 +397,31 @@
         self._create_new_network()
         self._hotplug_server()
         self._check_network_internal_connectivity(network=self.new_net)
+
+    @test.attr(type='smoke')
+    @test.services('compute', 'network')
+    def test_update_router_admin_state(self):
+        """
+        1. Check public connectivity before updating
+                admin_state_up attribute of router to False
+        2. Check public connectivity after updating
+                admin_state_up attribute of router to False
+        3. Check public connectivity after updating
+                admin_state_up attribute of router to True
+        """
+        self._setup_network_and_servers()
+        self.check_public_network_connectivity(
+            should_connect=True, msg="before updating "
+            "admin_state_up of router to False")
+        self._update_router_admin_state(self.router, False)
+        # TODO(alokmaurya): Remove should_check_floating_ip_status=False check
+        # once bug 1396310 is fixed
+
+        self.check_public_network_connectivity(
+            should_connect=False, msg="after updating "
+            "admin_state_up of router to False",
+            should_check_floating_ip_status=False)
+        self._update_router_admin_state(self.router, True)
+        self.check_public_network_connectivity(
+            should_connect=True, msg="after updating "
+            "admin_state_up of router to True")
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 7e512a9..23743c5 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -88,15 +88,10 @@
             self.floating_ips_client.associate_floating_ip_to_server(
                 floating_ip['ip'], self.instance['id'])
             # Check ssh
-            try:
-                self.get_remote_client(
-                    server_or_ip=floating_ip['ip'],
-                    username=self.image_utils.ssh_user(self.image_ref),
-                    private_key=self.keypair['private_key'])
-            except Exception:
-                LOG.exception('ssh to server failed')
-                self._log_console_output()
-                raise
+            self.get_remote_client(
+                server_or_ip=floating_ip['ip'],
+                username=self.image_utils.ssh_user(self.image_ref),
+                private_key=self.keypair['private_key'])
 
     @test.services('compute', 'network')
     def test_server_basicops(self):
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 159585b..5cb7c99 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -47,21 +47,13 @@
     def _add_keypair(self):
         self.keypair = self.create_keypair()
 
-    def _ssh_to_server(self, server_or_ip):
-        try:
-            return self.get_remote_client(server_or_ip)
-        except Exception:
-            LOG.exception('Initializing SSH connection failed')
-            self._log_console_output()
-            raise
-
     def _write_timestamp(self, server_or_ip):
-        ssh_client = self._ssh_to_server(server_or_ip)
+        ssh_client = self.get_remote_client(server_or_ip)
         ssh_client.exec_command('date > /tmp/timestamp; sync')
         self.timestamp = ssh_client.exec_command('cat /tmp/timestamp')
 
     def _check_timestamp(self, server_or_ip):
-        ssh_client = self._ssh_to_server(server_or_ip)
+        ssh_client = self.get_remote_client(server_or_ip)
         got_timestamp = ssh_client.exec_command('cat /tmp/timestamp')
         self.assertEqual(self.timestamp, got_timestamp)
 
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index dd115e7..c584a6e 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -110,14 +110,8 @@
             network_name_for_ssh = CONF.compute.network_for_ssh
             ip = server.networks[network_name_for_ssh][0]
 
-        try:
-            return self.get_remote_client(
-                ip,
-                private_key=keypair['private_key'])
-        except Exception:
-            LOG.exception('ssh to server failed')
-            self._log_console_output(servers=[server])
-            raise
+        return self.get_remote_client(ip, private_key=keypair['private_key'],
+                                      log_console_of_servers=[server])
 
     def _get_content(self, ssh_client):
         return ssh_client.exec_command('cat /tmp/text')
diff --git a/tempest/services/compute/json/interfaces_client.py b/tempest/services/compute/json/interfaces_client.py
index 83c253a..620ed68 100644
--- a/tempest/services/compute/json/interfaces_client.py
+++ b/tempest/services/compute/json/interfaces_client.py
@@ -79,9 +79,10 @@
             timed_out = int(time.time()) - start >= self.build_timeout
 
             if interface_status != status and timed_out:
-                message = ('Interface %s failed to reach %s status within '
-                           'the required time (%s s).' %
-                           (port_id, status, self.build_timeout))
+                message = ('Interface %s failed to reach %s status '
+                           '(current %s) within the required time (%s s).' %
+                           (port_id, status, interface_status,
+                            self.build_timeout))
                 raise exceptions.TimeoutException(message)
 
         return resp, body
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index b23b20b..afa6937 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -103,9 +103,10 @@
                 raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
 
             if int(time.time()) - start >= self.build_timeout:
-                message = ('Volume %s failed to reach %s status within '
-                           'the required time (%s s).' %
-                           (volume_id, status, self.build_timeout))
+                message = ('Volume %s failed to reach %s status (current %s) '
+                           'within the required time (%s s).' %
+                           (volume_id, status, volume_status,
+                            self.build_timeout))
                 raise exceptions.TimeoutException(message)
 
     def is_resource_deleted(self, id):
diff --git a/tempest/services/compute/v3/json/interfaces_client.py b/tempest/services/compute/v3/json/interfaces_client.py
index e99c124..ccc20c8 100644
--- a/tempest/services/compute/v3/json/interfaces_client.py
+++ b/tempest/services/compute/v3/json/interfaces_client.py
@@ -80,9 +80,10 @@
             timed_out = int(time.time()) - start >= self.build_timeout
 
             if interface_status != status and timed_out:
-                message = ('Interface %s failed to reach %s status within '
-                           'the required time (%s s).' %
-                           (port_id, status, self.build_timeout))
+                message = ('Interface %s failed to reach %s status '
+                           '(current %s) within the required time (%s s).' %
+                           (port_id, status, interface_status,
+                            self.build_timeout))
                 raise exceptions.TimeoutException(message)
 
         return resp, body
diff --git a/tempest/services/network/network_client_base.py b/tempest/services/network/network_client_base.py
index 5ad5f37..2c767d9 100644
--- a/tempest/services/network/network_client_base.py
+++ b/tempest/services/network/network_client_base.py
@@ -259,6 +259,7 @@
         # At this point, the wait has timed out
         message = 'Resource %s' % (str(resource))
         message += ' failed to reach status %s' % status
+        message += ' (current: %s)' % resource['status']
         message += ' within the required time %s' % timeout
         caller = misc.find_test_caller()
         if caller:
diff --git a/tempest/services/orchestration/json/orchestration_client.py b/tempest/services/orchestration/json/orchestration_client.py
index 15306a0..9b4700a 100644
--- a/tempest/services/orchestration/json/orchestration_client.py
+++ b/tempest/services/orchestration/json/orchestration_client.py
@@ -185,9 +185,12 @@
                         resource_status_reason=body['resource_status_reason'])
 
             if int(time.time()) - start >= self.build_timeout:
-                message = ('Resource %s failed to reach %s status within '
-                           'the required time (%s s).' %
-                           (resource_name, status, self.build_timeout))
+                message = ('Resource %s failed to reach %s status '
+                           '(current %s) within the required time (%s s).' %
+                           (resource_name,
+                            status,
+                            resource_status,
+                            self.build_timeout))
                 raise exceptions.TimeoutException(message)
             time.sleep(self.build_interval)
 
@@ -214,9 +217,10 @@
                     stack_status_reason=body['stack_status_reason'])
 
             if int(time.time()) - start >= self.build_timeout:
-                message = ('Stack %s failed to reach %s status within '
-                           'the required time (%s s).' %
-                           (stack_name, status, self.build_timeout))
+                message = ('Stack %s failed to reach %s status (current: %s) '
+                           'within the required time (%s s).' %
+                           (stack_name, status, stack_status,
+                            self.build_timeout))
                 raise exceptions.TimeoutException(message)
             time.sleep(self.build_interval)
 
diff --git a/tempest/services/volume/json/backups_client.py b/tempest/services/volume/json/backups_client.py
index da47639..51a017e 100644
--- a/tempest/services/volume/json/backups_client.py
+++ b/tempest/services/volume/json/backups_client.py
@@ -95,9 +95,10 @@
                 raise exceptions.VolumeBackupException(backup_id=backup_id)
 
             if int(time.time()) - start >= self.build_timeout:
-                message = ('Volume backup %s failed to reach %s status within '
-                           'the required time (%s s).' %
-                           (backup_id, status, self.build_timeout))
+                message = ('Volume backup %s failed to reach %s status '
+                           '(current %s) within the required time (%s s).' %
+                           (backup_id, status, backup_status,
+                            self.build_timeout))
                 raise exceptions.TimeoutException(message)
 
 
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index cf2837b..1e49e5a 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -174,10 +174,12 @@
                 raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
 
             if int(time.time()) - start >= self.build_timeout:
-                message = 'Volume %s failed to reach %s status within '\
-                          'the required time (%s s).' % (volume_id,
-                                                         status,
-                                                         self.build_timeout)
+                message = ('Volume %s failed to reach %s status (current: %s) '
+                           'within the required time '
+                           '(%s s).' % (volume_id,
+                                        status,
+                                        volume_status,
+                                        self.build_timeout))
                 raise exceptions.TimeoutException(message)
 
     def is_resource_deleted(self, id):