Merge "Add coverage option to run_tests.sh"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index d6d0964..0554082 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -540,11 +540,11 @@
 # (string value)
 #region=
 
-# Number of seconds to time on waiting for a containerto
+# Number of seconds to time on waiting for a container to
 # container synchronization complete. (integer value)
 #container_sync_timeout=120
 
-# Number of seconds to wait while looping to check thestatus
+# Number of seconds to wait while looping to check the status
 # of a container to container synchronization (integer value)
 #container_sync_interval=5
 
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index 5019003..5058211 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -16,8 +16,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class InstanceActionsTestJSON(base.BaseV2ComputeTest):
@@ -31,7 +30,7 @@
         cls.request_id = resp['x-compute-request-id']
         cls.server_id = server['id']
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_instance_actions(self):
         # List actions of the provided server
         resp, body = self.client.reboot(self.server_id, 'HARD')
@@ -43,7 +42,7 @@
         self.assertTrue(any([i for i in body if i['action'] == 'create']))
         self.assertTrue(any([i for i in body if i['action'] == 'reboot']))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_instance_action(self):
         # Get the action details of the provided server
         resp, body = self.client.get_instance_action(self.server_id,
@@ -52,18 +51,6 @@
         self.assertEqual(self.server_id, body['instance_uuid'])
         self.assertEqual('create', body['action'])
 
-    @attr(type=['negative', 'gate'])
-    def test_list_instance_actions_invalid_server(self):
-        # List actions of the invalid server id
-        self.assertRaises(exceptions.NotFound,
-                          self.client.list_instance_actions, 'server-999')
-
-    @attr(type=['negative', 'gate'])
-    def test_get_instance_action_invalid_request(self):
-        # Get the action details of the provided server with invalid request
-        self.assertRaises(exceptions.NotFound, self.client.get_instance_action,
-                          self.server_id, '999')
-
 
 class InstanceActionsTestXML(InstanceActionsTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
new file mode 100644
index 0000000..68f2dcb
--- /dev/null
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -0,0 +1,50 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NEC Corporation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class InstanceActionsNegativeTestJSON(base.BaseV2ComputeTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(InstanceActionsNegativeTestJSON, cls).setUpClass()
+        cls.client = cls.servers_client
+        resp, server = cls.create_test_server(wait_until='ACTIVE')
+        cls.server_id = server['id']
+
+    @test.attr(type=['negative', 'gate'])
+    def test_list_instance_actions_non_existent_server(self):
+        # List actions of the non-existent server id
+        non_existent_server_id = data_utils.rand_uuid()
+        self.assertRaises(exceptions.NotFound,
+                          self.client.list_instance_actions,
+                          non_existent_server_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_get_instance_action_invalid_request(self):
+        # Get the action details of the provided server with invalid request
+        self.assertRaises(exceptions.NotFound, self.client.get_instance_action,
+                          self.server_id, '999')
+
+
+class InstanceActionsNegativeTestXML(InstanceActionsNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/compute/test_extensions.py b/tempest/api/compute/test_extensions.py
index b0bffc4..f9b44d8 100644
--- a/tempest/api/compute/test_extensions.py
+++ b/tempest/api/compute/test_extensions.py
@@ -17,10 +17,14 @@
 
 
 from tempest.api.compute import base
+from tempest.openstack.common import log as logging
 from tempest import test
 import testtools
 
 
+LOG = logging.getLogger(__name__)
+
+
 class ExtensionsTestJSON(base.BaseV2ComputeTest):
     _interface = 'json'
 
@@ -31,6 +35,9 @@
         # List of all extensions
         resp, extensions = self.extensions_client.list_extensions()
         self.assertIn("extensions", extensions)
+        extension_list = [extension.get('alias')
+                          for extension in extensions.get('extensions', {})]
+        LOG.debug("Nova extensions: %s" % ','.join(extension_list))
         self.assertEqual(200, resp.status)
         self.assertTrue(self.extensions_client.is_enabled("Consoles"))
 
diff --git a/tempest/api/compute/v3/admin/test_simple_tenant_usage.py b/tempest/api/compute/v3/admin/test_simple_tenant_usage.py
index 99f2c52..e08f16a 100644
--- a/tempest/api/compute/v3/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/v3/admin/test_simple_tenant_usage.py
@@ -18,6 +18,7 @@
 import datetime
 
 from tempest.api.compute import base
+from tempest import test
 from tempest.test import attr
 import time
 
@@ -50,6 +51,7 @@
         # Returns formatted datetime
         return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
 
+    @test.skip_because(bug='1265416')
     @attr(type='gate')
     def test_list_usage_all_tenants(self):
         # Get usage for all tenants
@@ -60,6 +62,7 @@
         self.assertEqual(200, resp.status)
         self.assertEqual(len(tenant_usage), 8)
 
+    @test.skip_because(bug='1265416')
     @attr(type='gate')
     def test_get_usage_tenant(self):
         # Get usage for a specific tenant
@@ -71,6 +74,7 @@
         self.assertEqual(200, resp.status)
         self.assertEqual(len(tenant_usage), 8)
 
+    @test.skip_because(bug='1265416')
     @attr(type='gate')
     def test_get_usage_tenant_with_non_admin_user(self):
         # Get usage for a specific tenant with non admin user
diff --git a/tempest/api/compute/v3/admin/test_simple_tenant_usage_negative.py b/tempest/api/compute/v3/admin/test_simple_tenant_usage_negative.py
index ef49ed7..f9dbe86 100644
--- a/tempest/api/compute/v3/admin/test_simple_tenant_usage_negative.py
+++ b/tempest/api/compute/v3/admin/test_simple_tenant_usage_negative.py
@@ -19,6 +19,7 @@
 
 from tempest.api.compute import base
 from tempest import exceptions
+from tempest import test
 from tempest.test import attr
 
 
@@ -50,6 +51,7 @@
                           self.adm_client.get_tenant_usage,
                           '', params)
 
+    @test.skip_because(bug='1265416')
     @attr(type=['negative', 'gate'])
     def test_get_usage_tenant_with_invalid_date(self):
         # Get usage for tenant with invalid date
@@ -62,6 +64,7 @@
                           self.adm_client.get_tenant_usage,
                           tenant_id, params)
 
+    @test.skip_because(bug='1265416')
     @attr(type=['negative', 'gate'])
     def test_list_usage_all_tenants_with_non_admin_user(self):
         # Get usage for all tenants with non admin user
diff --git a/tempest/api/compute/v3/servers/test_list_servers_negative.py b/tempest/api/compute/v3/servers/test_list_servers_negative.py
index 3f7f885..b8e3d10 100644
--- a/tempest/api/compute/v3/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/v3/servers/test_list_servers_negative.py
@@ -18,69 +18,18 @@
 import datetime
 
 from tempest.api.compute import base
-from tempest import clients
 from tempest import exceptions
 from tempest.test import attr
 
 
 class ListServersNegativeV3TestJSON(base.BaseV3ComputeTest):
     _interface = 'json'
-
-    @classmethod
-    def _ensure_no_servers(cls, servers, username, tenant_name):
-        """
-        If there are servers and there is tenant isolation then a
-        skipException is raised to skip the test since it requires no servers
-        to already exist for the given user/tenant.
-        If there are servers and there is not tenant isolation then the test
-        blocks while the servers are being deleted.
-        """
-        if len(servers):
-            if not cls.config.compute.allow_tenant_isolation:
-                for srv in servers:
-                    cls.client.wait_for_server_termination(srv['id'],
-                                                           ignore_error=True)
-            else:
-                msg = ("User/tenant %(u)s/%(t)s already have "
-                       "existing server instances. Skipping test." %
-                       {'u': username, 't': tenant_name})
-                raise cls.skipException(msg)
+    force_tenant_isolation = True
 
     @classmethod
     def setUpClass(cls):
         super(ListServersNegativeV3TestJSON, cls).setUpClass()
         cls.client = cls.servers_client
-        cls.servers = []
-
-        if cls.multi_user:
-            if cls.config.compute.allow_tenant_isolation:
-                creds = cls.isolated_creds.get_alt_creds()
-                username, tenant_name, password = creds
-                cls.alt_manager = clients.Manager(username=username,
-                                                  password=password,
-                                                  tenant_name=tenant_name)
-            else:
-                # Use the alt_XXX credentials in the config file
-                cls.alt_manager = clients.AltManager()
-            cls.alt_client = cls.alt_manager.servers_client
-
-        # Under circumstances when there is not a tenant/user
-        # created for the test case, the test case checks
-        # to see if there are existing servers for the
-        # either the normal user/tenant or the alt user/tenant
-        # and if so, the whole test is skipped. We do this
-        # because we assume a baseline of no servers at the
-        # start of the test instead of destroying any existing
-        # servers.
-        resp, body = cls.client.list_servers()
-        cls._ensure_no_servers(body['servers'],
-                               cls.os.username,
-                               cls.os.tenant_name)
-
-        resp, body = cls.alt_client.list_servers()
-        cls._ensure_no_servers(body['servers'],
-                               cls.alt_manager.username,
-                               cls.alt_manager.tenant_name)
 
         # The following servers are created for use
         # by the test methods in this class. These
diff --git a/tempest/api/compute/v3/test_extensions.py b/tempest/api/compute/v3/test_extensions.py
index 2affd86..72dfe14 100644
--- a/tempest/api/compute/v3/test_extensions.py
+++ b/tempest/api/compute/v3/test_extensions.py
@@ -17,9 +17,13 @@
 
 
 from tempest.api.compute import base
+from tempest.openstack.common import log as logging
 from tempest import test
 
 
+LOG = logging.getLogger(__name__)
+
+
 class ExtensionsV3TestJSON(base.BaseV3ComputeTest):
     _interface = 'json'
 
@@ -28,6 +32,9 @@
         # List of all extensions
         resp, extensions = self.extensions_client.list_extensions()
         self.assertIn("extensions", extensions)
+        extension_list = [extension.get('alias')
+                          for extension in extensions.get('extensions', {})]
+        LOG.debug("Nova extensions: %s" % ','.join(extension_list))
         self.assertEqual(200, resp.status)
         self.assertTrue(self.extensions_client.is_enabled("Consoles"))
 
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index 1ecc90c..d316ae1 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -28,10 +28,7 @@
         super(BaseTrustsV3Test, self).setUp()
         # Use alt_username as the trustee
         self.trustee_username = self.config.identity.alt_username
-
         self.trust_id = None
-        self.create_trustor_and_roles()
-        self.addCleanup(self.cleanup_user_and_roles)
 
     def tearDown(self):
         if self.trust_id:
@@ -50,7 +47,7 @@
         # Create a trustor User
         self.trustor_username = rand_name('user-')
         u_desc = self.trustor_username + 'description'
-        u_email = self.trustor_username + '@testmail.tm'
+        u_email = self.trustor_username + '@testmail.xx'
         self.trustor_password = rand_name('pass-')
         resp, user = self.v3_client.create_user(
             self.trustor_username,
@@ -193,6 +190,7 @@
     def setUp(self):
         super(TrustsV3TestJSON, self).setUp()
         self.create_trustor_and_roles()
+        self.addCleanup(self.cleanup_user_and_roles)
 
     @attr(type='smoke')
     def test_trust_impersonate(self):
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index e7cb806..47d8cca 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -101,6 +101,7 @@
 
         The containers should be visible from the container_client given.
         Will not throw any error if the containers don't exist.
+        Will not check that object and container deletions succeed.
 
         :param containers: list of container names to remove
         :param container_client: if None, use cls.container_client, this means
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index dcfe219..ec78774 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -16,25 +16,38 @@
 #    under the License.
 
 import time
+import urlparse
 
 from tempest.api.object_storage import base
 from tempest.common.utils import data_utils
 from tempest.test import attr
-from tempest.test import skip_because
+from tempest.test import HTTP_SUCCESS
+
+# This test can be quite long to run due to its
+# dependency on container-sync process running interval.
+# You can obviously reduce the container-sync interval in the
+# container-server configuration.
 
 
 class ContainerSyncTest(base.BaseObjectTest):
+
     @classmethod
     def setUpClass(cls):
         super(ContainerSyncTest, cls).setUpClass()
         cls.containers = []
         cls.objects = []
+
+        # Default container-server config only allows localhost
+        cls.local_ip = '127.0.0.1'
+
+        # Must be configure according to container-sync interval
         container_sync_timeout = \
             int(cls.config.object_storage.container_sync_timeout)
         cls.container_sync_interval = \
             int(cls.config.object_storage.container_sync_interval)
         cls.attempts = \
             int(container_sync_timeout / cls.container_sync_interval)
+
         # define container and object clients
         cls.clients = {}
         cls.clients[data_utils.rand_name(name='TestContainerSync')] = \
@@ -51,8 +64,7 @@
             cls.delete_containers(cls.containers, client[0], client[1])
         super(ContainerSyncTest, cls).tearDownClass()
 
-    @skip_because(bug="1093743")
-    @attr(type='gate')
+    @attr(type='slow')
     def test_container_synchronization(self):
         # container to container synchronization
         # to allow/accept sync requests to/from other accounts
@@ -62,51 +74,53 @@
             cont_client = [self.clients[c][0] for c in cont]
             obj_client = [self.clients[c][1] for c in cont]
             # tell first container to synchronize to a second
+            client_proxy_ip = \
+                urlparse.urlparse(cont_client[1].base_url).netloc.split(':')[0]
+            client_base_url = \
+                cont_client[1].base_url.replace(client_proxy_ip,
+                                                self.local_ip)
             headers = {'X-Container-Sync-Key': 'sync_key',
                        'X-Container-Sync-To': "%s/%s" %
-                       (cont_client[1].base_url, str(cont[1]))}
+                       (client_base_url, str(cont[1]))}
             resp, body = \
                 cont_client[0].put(str(cont[0]), body=None, headers=headers)
-            self.assertIn(resp['status'], ('202', '201'),
-                          'Error installing X-Container-Sync-To '
-                          'for the container "%s"' % (cont[0]))
+            self.assertIn(int(resp['status']), HTTP_SUCCESS)
             # create object in container
             object_name = data_utils.rand_name(name='TestSyncObject')
             data = object_name[::-1]  # data_utils.arbitrary_string()
             resp, _ = obj_client[0].create_object(cont[0], object_name, data)
-            self.assertEqual(resp['status'], '201',
-                             'Error creating the object "%s" in'
-                             'the container "%s"'
-                             % (object_name, cont[0]))
+            self.assertIn(int(resp['status']), HTTP_SUCCESS)
             self.objects.append(object_name)
 
         # wait until container contents list is not empty
         cont_client = [self.clients[c][0] for c in self.containers]
         params = {'format': 'json'}
         while self.attempts > 0:
-            # get first container content
-            resp, object_list_0 = \
-                cont_client[0].\
-                list_container_contents(self.containers[0], params=params)
-            self.assertEqual(resp['status'], '200',
-                             'Error listing the destination container`s'
-                             ' "%s" contents' % (self.containers[0]))
-            object_list_0 = dict((obj['name'], obj) for obj in object_list_0)
-            # get second container content
-            resp, object_list_1 = \
-                cont_client[1].\
-                list_container_contents(self.containers[1], params=params)
-            self.assertEqual(resp['status'], '200',
-                             'Error listing the destination container`s'
-                             ' "%s" contents' % (self.containers[1]))
-            object_list_1 = dict((obj['name'], obj) for obj in object_list_1)
+            object_lists = []
+            for client_index in (0, 1):
+                resp, object_list = \
+                    cont_client[client_index].\
+                    list_container_contents(self.containers[client_index],
+                                            params=params)
+                self.assertIn(int(resp['status']), HTTP_SUCCESS)
+                object_lists.append(dict(
+                    (obj['name'], obj) for obj in object_list))
             # check that containers are not empty and have equal keys()
             # or wait for next attempt
-            if not object_list_0 or not object_list_1 or \
-                    set(object_list_0.keys()) != set(object_list_1.keys()):
+            if not object_lists[0] or not object_lists[1] or \
+                    set(object_lists[0].keys()) != set(object_lists[1].keys()):
                 time.sleep(self.container_sync_interval)
                 self.attempts -= 1
             else:
                 break
-        self.assertEqual(object_list_0, object_list_1,
+
+        self.assertEqual(object_lists[0], object_lists[1],
                          'Different object lists in containers.')
+
+        # Verify object content
+        obj_clients = [(self.clients[c][1], c) for c in self.containers]
+        for obj_client, cont in obj_clients:
+            for obj_name in object_lists[0]:
+                resp, object_content = obj_client.get_object(cont, obj_name)
+                self.assertIn(int(resp['status']), HTTP_SUCCESS)
+                self.assertEqual(object_content, obj_name[::-1])
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index 4958f70..9c2834d 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -21,7 +21,6 @@
 from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
-from tempest.test import skip_because
 
 
 class ObjectExpiryTest(base.BaseObjectTest):
@@ -33,31 +32,20 @@
 
     @classmethod
     def tearDownClass(cls):
-        """The test script fails in tear down class
-        as the container contains expired objects (LP bug 1069849).
-        But delete action for the expired object is raising
-        NotFound exception and also non empty container cannot be deleted.
-        """
         cls.delete_containers([cls.container_name])
         super(ObjectExpiryTest, cls).tearDownClass()
 
-    @skip_because(bug="1069849")
-    @attr(type='gate')
-    def test_get_object_after_expiry_time(self):
-        # TODO(harika-vakadi): similar test case has to be created for
-        # "X-Delete-At", after this test case works.
-
+    def _test_object_expiry(self, metadata):
         # create object
         object_name = data_utils.rand_name(name='TestObject')
-        data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
-                                                   object_name, data)
-        # update object metadata with expiry time of 3 seconds
-        metadata = {'X-Delete-After': '3'}
+                                                   object_name, '')
+        # update object metadata
         resp, _ = \
             self.object_client.update_object_metadata(self.container_name,
                                                       object_name, metadata,
                                                       metadata_prefix='')
+        # verify object metadata
         resp, _ = \
             self.object_client.list_object_metadata(self.container_name,
                                                     object_name)
@@ -69,10 +57,20 @@
         self.assertEqual(resp['status'], '200')
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertIn('x-delete-at', resp)
-        # check data
-        self.assertEqual(body, data)
+
         # sleep for over 5 seconds, so that object expires
         time.sleep(5)
+
         # object should not be there anymore
         self.assertRaises(exceptions.NotFound, self.object_client.get_object,
                           self.container_name, object_name)
+
+    @attr(type='gate')
+    def test_get_object_after_expiry_time(self):
+        metadata = {'X-Delete-After': '3'}
+        self._test_object_expiry(metadata)
+
+    @attr(type='gate')
+    def test_get_object_at_expiry_time(self):
+        metadata = {'X-Delete-At': str(int(time.time()) + 3)}
+        self._test_object_expiry(metadata)
diff --git a/tempest/api/volume/test_extensions.py b/tempest/api/volume/test_extensions.py
index 90988a2..546c430 100644
--- a/tempest/api/volume/test_extensions.py
+++ b/tempest/api/volume/test_extensions.py
@@ -17,9 +17,13 @@
 
 
 from tempest.api.volume import base
+from tempest.openstack.common import log as logging
 from tempest.test import attr
 
 
+LOG = logging.getLogger(__name__)
+
+
 class ExtensionsTestJSON(base.BaseVolumeTest):
     _interface = 'json'
 
@@ -30,6 +34,8 @@
         self.assertEqual(200, resp.status)
         if len(self.config.volume_feature_enabled.api_extensions) == 0:
             raise self.skipException('There are not any extensions configured')
+        extension_list = [extension.get('alias') for extension in extensions]
+        LOG.debug("Cinder extensions: %s" % ','.join(extension_list))
         ext = self.config.volume_feature_enabled.api_extensions[0]
         if ext == 'all':
             self.assertIn('Hosts', map(lambda x: x['name'], extensions))
diff --git a/tempest/cli/simple_read_only/test_ceilometer.py b/tempest/cli/simple_read_only/test_ceilometer.py
index 8bdd633..b762b47 100644
--- a/tempest/cli/simple_read_only/test_ceilometer.py
+++ b/tempest/cli/simple_read_only/test_ceilometer.py
@@ -15,17 +15,16 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from oslo.config import cfg
-
-import tempest.cli
+from tempest import cli
+from tempest import config
 from tempest.openstack.common import log as logging
 
-CONF = cfg.CONF
+CONF = config.CONF
 
 LOG = logging.getLogger(__name__)
 
 
-class SimpleReadOnlyCeilometerClientTest(tempest.cli.ClientTestBase):
+class SimpleReadOnlyCeilometerClientTest(cli.ClientTestBase):
     """Basic, read-only tests for Ceilometer CLI client.
 
     Checks return values and output of read-only commands.
diff --git a/tempest/cli/simple_read_only/test_neutron.py b/tempest/cli/simple_read_only/test_neutron.py
index 61ffc25..34c6fd9 100644
--- a/tempest/cli/simple_read_only/test_neutron.py
+++ b/tempest/cli/simple_read_only/test_neutron.py
@@ -18,18 +18,17 @@
 import re
 import subprocess
 
-from oslo.config import cfg
-
-import tempest.cli
+from tempest import cli
+from tempest import config
 from tempest.openstack.common import log as logging
 from tempest import test
 
-CONF = cfg.CONF
+CONF = config.CONF
 
 LOG = logging.getLogger(__name__)
 
 
-class SimpleReadOnlyNeutronClientTest(tempest.cli.ClientTestBase):
+class SimpleReadOnlyNeutronClientTest(cli.ClientTestBase):
     """Basic, read-only tests for Neutron CLI client.
 
     Checks return values and output of read-only commands.
@@ -89,7 +88,7 @@
     def _test_neutron_lbaas_command(self, command):
         try:
             self.neutron(command)
-        except tempest.cli.CommandFailed as e:
+        except cli.CommandFailed as e:
             if '404 Not Found' not in e.stderr:
                 self.fail('%s: Unexpected failure.' % command)
 
@@ -156,7 +155,7 @@
                                'router-show', 'agent-update', 'help'))
         self.assertFalse(wanted_commands - commands)
 
-     # Optional arguments:
+    # Optional arguments:
 
     @test.attr(type='smoke')
     def test_neutron_version(self):
diff --git a/tempest/config.py b/tempest/config.py
index 8d6e52a..0fb4491 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -398,11 +398,11 @@
                     "one is used."),
     cfg.IntOpt('container_sync_timeout',
                default=120,
-               help="Number of seconds to time on waiting for a container"
+               help="Number of seconds to time on waiting for a container "
                     "to container synchronization complete."),
     cfg.IntOpt('container_sync_interval',
                default=5,
-               help="Number of seconds to wait while looping to check the"
+               help="Number of seconds to wait while looping to check the "
                     "status of a container to container synchronization"),
     cfg.StrOpt('operator_role',
                default='Member',
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 3618a14..52a36e6 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -213,6 +213,11 @@
             name = data_utils.rand_name('server-smoke-%d-' % i)
             self._create_server(name, network)
 
+    def _log_console_output(self):
+        for server, key in self.servers.items():
+            LOG.debug('Console output for %s', server.id)
+            LOG.debug(server.get_console_output())
+
     def _check_tenant_network_connectivity(self):
         if not CONF.network.tenant_networks_reachable:
             msg = 'Tenant networks not configured to be reachable.'
@@ -229,6 +234,7 @@
                                                     key.private_key)
         except Exception:
             LOG.exception('Tenant connectivity check failed')
+            self._log_console_output()
             debug.log_ip_ns()
             raise
 
@@ -253,6 +259,7 @@
         # The target login is assumed to have been configured for
         # key-based authentication by cloud-init.
         ssh_login = CONF.compute.image_ssh_user
+        LOG.debug('checking network connections')
         try:
             for floating_ip, server in self.floating_ips.iteritems():
                 ip_address = floating_ip.floating_ip_address
@@ -265,6 +272,7 @@
                                             should_connect=should_connect)
         except Exception:
             LOG.exception('Public network connectivity check failed')
+            self._log_console_output()
             debug.log_ip_ns()
             raise
 
diff --git a/tempest/services/compute/xml/common.py b/tempest/services/compute/xml/common.py
index d2a18a1..76ad1aa 100644
--- a/tempest/services/compute/xml/common.py
+++ b/tempest/services/compute/xml/common.py
@@ -124,9 +124,9 @@
         if tag.startswith("{"):
             ns, tag = tag.split("}", 1)
         if plurals is not None and tag in plurals:
-                json[tag] = parse_array(child)
+                json[tag] = parse_array(child, plurals)
         else:
-            json[tag] = xml_to_json(child)
+            json[tag] = xml_to_json(child, plurals)
     return json