Merge "Add Conflict exception in test_floating_ips_actions case"
diff --git a/HACKING.rst b/HACKING.rst
index 83d67a9..e57b670 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -36,11 +36,11 @@
 
 In most cases the very first issue is the most important information.
 
-Try to avoid using ``try`` blocks in the test cases, both the ``except``
-and ``finally`` block could replace the original exception,
+Try to avoid using ``try`` blocks in the test cases, as both the ``except``
+and ``finally`` blocks could replace the original exception,
 when the additional operations leads to another exception.
 
-Just letting an exception to propagate, is not bad idea in a test case,
+Just letting an exception to propagate, is not a bad idea in a test case,
 at all.
 
 Try to avoid using any exception handling construct which can hide the errors
@@ -54,10 +54,10 @@
 exceptions and still ensure resources are correctly cleaned up if the
 test fails part way through.
 
-Use the ``self.assert*`` methods provided by the unit test framework
-the signal failures early.
+Use the ``self.assert*`` methods provided by the unit test framework.
+This signals the failures early on.
 
-Avoid using the ``self.fail`` alone, it's stack trace will signal
+Avoid using the ``self.fail`` alone, its stack trace will signal
 the ``self.fail`` line as the origin of the error.
 
 Avoid constructing complex boolean expressions for assertion.
@@ -69,7 +69,7 @@
 Most other assert method can include more information by default.
 For example ``self.assertIn`` can include the whole set.
 
-Recommended to use testtools matcher for more tricky assertion.
+It is recommended to use testtools matcher for the more tricky assertions.
 `[doc] <http://testtools.readthedocs.org/en/latest/for-test-authors.html#matchers>`_
 
 You can implement your own specific matcher as well.
@@ -77,8 +77,8 @@
 
 If the test case fails you can see the related logs and the information
 carried by the exception (exception class, backtrack and exception info).
-This and the service logs are your only guide to find the root cause of flaky
-issue.
+This and the service logs are your only guide to finding the root cause of flaky
+issues.
 
 Test cases are independent
 --------------------------
@@ -87,7 +87,7 @@
 
 Test cases MAY depend on commonly initialized resources/facilities, like
 credentials management, testresources and so on. These facilities, MUST be able
-to work even if just one ``test_method`` selected for execution.
+to work even if just one ``test_method`` is selected for execution.
 
 Service Tagging
 ---------------
@@ -213,8 +213,10 @@
 Sample Configuration File
 -------------------------
 The sample config file is autogenerated using a script. If any changes are made
-to the config variables in tempest then the sample config file must be
-regenerated. This can be done running the script: tools/generate_sample.sh
+to the config variables in tempest/config.py then the sample config file must be
+regenerated. This can be done running::
+
+  tox -egenconfig
 
 Unit Tests
 ----------
@@ -260,15 +262,15 @@
 example of this would be::
 
     class TestVolumeBootPattern(manager.ScenarioTest):
-    """
-    This test case attempts to reproduce the following steps:
+        """
+        This test case attempts to reproduce the following steps:
 
-     * Create in Cinder some bootable volume importing a Glance image
-     * Boot an instance from the bootable volume
-     * Write content to the volume
-     * Delete an instance and Boot a new instance from the volume
-     * Check written content in the instance
-     * Create a volume snapshot while the instance is running
-     * Boot an additional instance from the new snapshot based volume
-     * Check written content in the instance booted from snapshot
-    """
+         * Create in Cinder some bootable volume importing a Glance image
+         * Boot an instance from the bootable volume
+         * Write content to the volume
+         * Delete an instance and Boot a new instance from the volume
+         * Check written content in the instance
+         * Create a volume snapshot while the instance is running
+         * Boot an additional instance from the new snapshot based volume
+         * Check written content in the instance booted from snapshot
+        """
diff --git a/README.rst b/README.rst
index ea36619..5284bbf 100644
--- a/README.rst
+++ b/README.rst
@@ -79,8 +79,10 @@
 document. The etc/tempest.conf.sample attempts to be a self
 documenting version of the configuration.
 
-The sample config file is auto generated using the script:
-tools/generate_sample.sh
+To generate the sample tempest.conf file, run the following
+command from the top level of the tempest directory:
+
+  tox -egenconfig
 
 The most important pieces that are needed are the user ids, openstack
 endpoints, and basic flavors and images needed to run tests.
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 9a9952d..f509cb4 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -429,7 +429,7 @@
 
 # Does the test environment support live migration available? (boolean
 # value)
-#live_migration = false
+#live_migration = true
 
 # Does the test environment support pausing? (boolean value)
 #pause = true
@@ -629,6 +629,9 @@
 # (boolean value)
 #trust = true
 
+# If false, skip all identity api tests with xml (boolean value)
+#xml_api = false
+
 
 [image]
 
@@ -758,8 +761,10 @@
 # value)
 #public_network_id =
 
-# Id of the public router that provides external connectivity (string
-# value)
+# Id of the public router that provides external connectivity. This
+# should only be used when Neutron's 'allow_overlapping_ips' is set to
+# 'False' in neutron.conf. usually not needed past 'Grizzly' release
+# (string value)
 #public_router_id =
 
 # The network region name to use. If empty, the value of
diff --git a/requirements.txt b/requirements.txt
index 708ede3..1e4c40b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,25 +5,25 @@
 anyjson>=0.3.3
 httplib2>=0.7.5
 jsonschema>=2.0.0,<3.0.0
-testtools>=0.9.34
+testtools>=0.9.36,!=1.2.0,!=1.4.0
 lxml>=2.3
 boto>=2.32.1
 paramiko>=1.13.0
 netaddr>=0.7.12
 python-ceilometerclient>=1.0.6
 python-glanceclient>=0.14.0
-python-keystoneclient>=0.10.0
+python-keystoneclient>=0.11.1
 python-novaclient>=2.18.0
 python-neutronclient>=2.3.6,<3
 python-cinderclient>=1.1.0
 python-heatclient>=0.2.9
 python-ironicclient>=0.2.1
-python-saharaclient>=0.7.3
+python-saharaclient>=0.7.5
 python-swiftclient>=2.2.0
-testresources>=0.2.4
 testrepository>=0.0.18
 oslo.config>=1.4.0  # Apache-2.0
 six>=1.7.0
 iso8601>=0.1.9
 fixtures>=0.3.14
 testscenarios>=0.4
+tempest-lib
diff --git a/tempest/api/compute/admin/test_flavors.py b/tempest/api/compute/admin/test_flavors.py
index d365f3a..3307159 100644
--- a/tempest/api/compute/admin/test_flavors.py
+++ b/tempest/api/compute/admin/test_flavors.py
@@ -296,7 +296,7 @@
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
         new_flavor_id = data_utils.rand_int_id(start=1000)
 
-        ram = " 1024 "
+        ram = "1024"
         resp, flavor = self.client.create_flavor(flavor_name,
                                                  ram, self.vcpus,
                                                  self.disk,
diff --git a/tempest/api/compute/admin/test_flavors_negative.py b/tempest/api/compute/admin/test_flavors_negative.py
index 3389aee..5bc3d10 100644
--- a/tempest/api/compute/admin/test_flavors_negative.py
+++ b/tempest/api/compute/admin/test_flavors_negative.py
@@ -58,7 +58,7 @@
         resp, flavor = self.client.create_flavor(flavor_name,
                                                  self.ram,
                                                  self.vcpus, self.disk,
-                                                 '',
+                                                 None,
                                                  ephemeral=self.ephemeral,
                                                  swap=self.swap,
                                                  rxtx=self.rxtx)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 6507ce1..2f53a0b 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -72,6 +72,8 @@
             cls.quotas_client = cls.os.quotas_client
             # NOTE(mriedem): os-quota-class-sets is v2 API only
             cls.quota_classes_client = cls.os.quota_classes_client
+            # NOTE(mriedem): os-networks is v2 API only
+            cls.networks_client = cls.os.networks_client
             cls.limits_client = cls.os.limits_client
             cls.volumes_extensions_client = cls.os.volumes_extensions_client
             cls.volumes_client = cls.os.volumes_client
diff --git a/tempest/api/compute/servers/test_delete_server.py b/tempest/api/compute/servers/test_delete_server.py
index 6a5da58..55931a4 100644
--- a/tempest/api/compute/servers/test_delete_server.py
+++ b/tempest/api/compute/servers/test_delete_server.py
@@ -116,6 +116,7 @@
         self.assertEqual('204', resp['status'])
         self.client.wait_for_server_termination(server['id'])
 
+    @test.services('volume')
     @test.attr(type='gate')
     def test_delete_server_while_in_attached_volume(self):
         # Delete a server while a volume is attached to it
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index 6c29f51..a494896 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -14,11 +14,8 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class ServerAddressesTestJSON(base.BaseV2ComputeTest):
 
@@ -31,8 +28,6 @@
 
         resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.skip_because(bug="1210483",
-                       condition=CONF.service_available.neutron)
     @test.attr(type='smoke')
     @test.services('network')
     def test_list_server_addresses(self):
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index a984ade..5986f41 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -45,12 +45,6 @@
                                                              cls.sg_desc)
         cls.sg_id = cls.sg['id']
 
-        # Create a volume and wait for it to become ready for attach
-        resp, cls.volume = cls.volumes_extensions_client.create_volume(
-            1, display_name=data_utils.rand_name(cls.__name__ + '_volume'))
-        cls.volumes_extensions_client.wait_for_volume_status(
-            cls.volume['id'], 'available')
-
         # Server for positive tests
         resp, server = cls.create_test_server(wait_until='BUILD')
         cls.server_id = server['id']
@@ -64,8 +58,6 @@
     def resource_cleanup(cls):
         # Deleting the floating IP which is created in this method
         cls.floating_ips_client.delete_floating_ip(cls.floating_ip_id)
-        if getattr(cls, 'volume', None):
-            cls.delete_volume(cls.volume['id'])
         resp, cls.sg = cls.security_groups_client.delete_security_group(
             cls.sg_id)
         super(ServerRescueTestJSON, cls).resource_cleanup()
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index 0d29968..de43164 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -35,12 +35,6 @@
         super(ServerRescueNegativeTestJSON, cls).resource_setup()
         cls.device = CONF.compute.volume_device_name
 
-        # Create a volume and wait for it to become ready for attach
-        resp, cls.volume = cls.volumes_extensions_client.create_volume(
-            1, display_name=data_utils.rand_name(cls.__name__ + '_volume'))
-        cls.volumes_extensions_client.wait_for_volume_status(
-            cls.volume['id'], 'available')
-
         # Server for negative tests
         resp, server = cls.create_test_server(wait_until='BUILD')
         resp, resc_server = cls.create_test_server(wait_until='ACTIVE')
@@ -54,11 +48,14 @@
         cls.servers_client.wait_for_server_status(cls.rescue_id, 'RESCUE')
         cls.servers_client.wait_for_server_status(cls.server_id, 'ACTIVE')
 
-    @classmethod
-    def resource_cleanup(cls):
-        if getattr(cls, 'volume', None):
-            cls.delete_volume(cls.volume['id'])
-        super(ServerRescueNegativeTestJSON, cls).resource_cleanup()
+    def _create_volume(self):
+        resp, volume = self.volumes_extensions_client.create_volume(
+            1, display_name=data_utils.rand_name(
+                self.__class__.__name__ + '_volume'))
+        self.addCleanup(self.delete_volume, volume['id'])
+        self.volumes_extensions_client.wait_for_volume_status(
+            volume['id'], 'available')
+        return volume
 
     def _detach(self, server_id, volume_id):
         self.servers_client.detach_volume(server_id, volume_id)
@@ -108,8 +105,11 @@
                           self.rescue_id,
                           self.image_ref_alt)
 
+    @test.services('volume')
     @test.attr(type=['negative', 'gate'])
     def test_rescued_vm_attach_volume(self):
+        volume = self._create_volume()
+
         # Rescue the server
         self.servers_client.rescue_server(self.server_id,
                                           adminPass=self.password)
@@ -120,31 +120,34 @@
         self.assertRaises(exceptions.Conflict,
                           self.servers_client.attach_volume,
                           self.server_id,
-                          self.volume['id'],
+                          volume['id'],
                           device='/dev/%s' % self.device)
 
+    @test.services('volume')
     @test.attr(type=['negative', 'gate'])
     def test_rescued_vm_detach_volume(self):
+        volume = self._create_volume()
+
         # Attach the volume to the server
         self.servers_client.attach_volume(self.server_id,
-                                          self.volume['id'],
+                                          volume['id'],
                                           device='/dev/%s' % self.device)
         self.volumes_extensions_client.wait_for_volume_status(
-            self.volume['id'], 'in-use')
+            volume['id'], 'in-use')
 
         # Rescue the server
         self.servers_client.rescue_server(self.server_id,
                                           adminPass=self.password)
         self.servers_client.wait_for_server_status(self.server_id, 'RESCUE')
         # addCleanup is a LIFO queue
-        self.addCleanup(self._detach, self.server_id, self.volume['id'])
+        self.addCleanup(self._detach, self.server_id, volume['id'])
         self.addCleanup(self._unrescue, self.server_id)
 
         # Detach the volume from the server expecting failure
         self.assertRaises(exceptions.Conflict,
                           self.servers_client.detach_volume,
                           self.server_id,
-                          self.volume['id'])
+                          volume['id'])
 
 
 class ServerRescueNegativeTestXML(ServerRescueNegativeTestJSON):
diff --git a/tempest/api/compute/servers/test_servers_negative_new.py b/tempest/api/compute/servers/test_servers_negative_new.py
deleted file mode 100644
index 7fc2d4f..0000000
--- a/tempest/api/compute/servers/test_servers_negative_new.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2014 Red Hat, Inc & Deutsche Telekom AG
-# 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.api_schema.request.compute.v2 import servers
-from tempest import test
-
-
-load_tests = test.NegativeAutoTest.load_tests
-
-
-@test.SimpleNegativeAutoTest
-class GetConsoleOutputNegativeTestJSON(base.BaseV2ComputeTest,
-                                       test.NegativeAutoTest):
-    _service = 'compute'
-    _schema = servers.get_console_output
-
-    @classmethod
-    def resource_setup(cls):
-        super(GetConsoleOutputNegativeTestJSON, cls).resource_setup()
-        _resp, server = cls.create_test_server()
-        cls.set_resource("server", server['id'])
diff --git a/tempest/api/compute/test_networks.py b/tempest/api/compute/test_networks.py
new file mode 100644
index 0000000..86779b3
--- /dev/null
+++ b/tempest/api/compute/test_networks.py
@@ -0,0 +1,33 @@
+# Copyright 2014 IBM Corp.
+#
+#    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 import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class NetworksTestJSON(base.BaseV2ComputeTest):
+    @classmethod
+    def resource_setup(cls):
+        if CONF.service_available.neutron:
+            raise cls.skipException('nova-network is not available.')
+        super(NetworksTestJSON, cls).resource_setup()
+        cls.client = cls.os.networks_client
+
+    @test.attr(type='gate')
+    def test_list_networks(self):
+        _, networks = self.client.list_networks()
+        self.assertNotEmpty(networks, "No networks found.")
diff --git a/tempest/api/compute/v3/servers/test_server_addresses.py b/tempest/api/compute/v3/servers/test_server_addresses.py
index 0590146..7b41d71 100644
--- a/tempest/api/compute/v3/servers/test_server_addresses.py
+++ b/tempest/api/compute/v3/servers/test_server_addresses.py
@@ -14,11 +14,8 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest import config
 from tempest import test
 
-CONF = config.CONF
-
 
 class ServerAddressesV3Test(base.BaseV3ComputeTest):
 
@@ -31,8 +28,6 @@
 
         resp, cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.skip_because(bug="1210483",
-                       condition=CONF.service_available.neutron)
     @test.attr(type='smoke')
     def test_list_server_addresses(self):
         # All public and private addresses for
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 484c34d..75f9795 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -27,9 +27,7 @@
 
     def __init__(self, *args, **kwargs):
         super(AttachVolumeTestJSON, self).__init__(*args, **kwargs)
-        self.server = None
-        self.volume = None
-        self.attached = False
+        self.attachment = None
 
     @classmethod
     def resource_setup(cls):
@@ -41,13 +39,15 @@
             raise cls.skipException(skip_msg)
 
     def _detach(self, server_id, volume_id):
-        if self.attached:
+        if self.attachment:
             self.servers_client.detach_volume(server_id, volume_id)
             self.volumes_client.wait_for_volume_status(volume_id, 'available')
 
     def _delete_volume(self):
+        # Delete the created Volumes
         if self.volume:
             self.volumes_client.delete_volume(self.volume['id'])
+            self.volumes_client.wait_for_resource_deletion(self.volume['id'])
             self.volume = None
 
     def _create_and_attach(self):
@@ -57,8 +57,8 @@
                                                  adminPass=admin_pass)
 
         # Record addresses so that we can ssh later
-        _, self.server['addresses'] = \
-            self.servers_client.list_addresses(self.server['id'])
+        _, self.server['addresses'] = (
+            self.servers_client.list_addresses(self.server['id']))
 
         # Create a volume and wait for it to become ready
         _, self.volume = self.volumes_client.create_volume(
@@ -68,12 +68,12 @@
                                                    'available')
 
         # Attach the volume to the server
-        self.servers_client.attach_volume(self.server['id'],
-                                          self.volume['id'],
-                                          device='/dev/%s' % self.device)
+        _, self.attachment = self.servers_client.attach_volume(
+            self.server['id'],
+            self.volume['id'],
+            device='/dev/%s' % self.device)
         self.volumes_client.wait_for_volume_status(self.volume['id'], 'in-use')
 
-        self.attached = True
         self.addCleanup(self._detach, self.server['id'], self.volume['id'])
 
     @testtools.skipUnless(CONF.compute.run_ssh, 'SSH required for this test')
@@ -97,8 +97,7 @@
         self.assertIn(self.device, partitions)
 
         self._detach(self.server['id'], self.volume['id'])
-        self.attached = False
-
+        self.attachment = None
         self.servers_client.stop(self.server['id'])
         self.servers_client.wait_for_server_status(self.server['id'],
                                                    'SHUTOFF')
@@ -112,6 +111,25 @@
         partitions = linux_client.get_partitions()
         self.assertNotIn(self.device, partitions)
 
+    @test.skip_because(bug="1323591", interface="xml")
+    @test.attr(type='gate')
+    def test_list_get_volume_attachments(self):
+        # Create Server, Volume and attach that Volume to Server
+        self._create_and_attach()
+        # List Volume attachment of the server
+        _, body = self.servers_client.list_volume_attachments(
+            self.server['id'])
+        self.assertEqual(1, len(body))
+        self.assertIn(self.attachment, body)
+
+        # Get Volume attachment of the server
+        _, body = self.servers_client.get_volume_attachment(
+            self.server['id'],
+            self.attachment['id'])
+        self.assertEqual(self.server['id'], body['serverId'])
+        self.assertEqual(self.volume['id'], body['volumeId'])
+        self.assertEqual(self.attachment['id'], body['id'])
+
 
 class AttachVolumeTestXML(AttachVolumeTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 1e4973b..244323e 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -31,6 +31,9 @@
     @classmethod
     def resource_setup(cls):
         super(BaseIdentityAdminTest, cls).resource_setup()
+        if getattr(cls, '_interface', None) == 'xml':
+            if not CONF.identity_feature_enabled.xml_api:
+                raise cls.skipException('XML API is not enabled')
         cls.os_adm = clients.AdminManager(interface=cls._interface)
         cls.os = clients.Manager(interface=cls._interface)
 
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index 2e58dae..5e6d8f3 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -84,6 +84,41 @@
         self.assertEqual(self.network['id'], show_net['id'])
         self.assertFalse(show_net['router:external'])
 
+    def test_delete_external_networks_with_floating_ip(self):
+        """Verifies external network can be deleted while still holding
+        (unassociated) floating IPs
+
+        """
+        # Set cls.client to admin to use base.create_subnet()
+        client = self.admin_client
+        _, body = client.create_network(**{'router:external': True})
+        external_network = body['network']
+        self.addCleanup(self._try_delete_resource,
+                        client.delete_network,
+                        external_network['id'])
+        subnet = self.create_subnet(external_network, client=client)
+        _, body = client.create_floatingip(
+            floating_network_id=external_network['id'])
+        created_floating_ip = body['floatingip']
+        self.addCleanup(self._try_delete_resource,
+                        client.delete_floatingip,
+                        created_floating_ip['id'])
+        _, floatingip_list = client.list_floatingips(
+            network=external_network['id'])
+        self.assertIn(created_floating_ip['id'],
+                      (f['id'] for f in floatingip_list['floatingips']))
+        client.delete_network(external_network['id'])
+        # Verifies floating ip is deleted
+        _, floatingip_list = client.list_floatingips()
+        self.assertNotIn(created_floating_ip['id'],
+                         (f['id'] for f in floatingip_list['floatingips']))
+        # Verifies subnet is deleted
+        _, subnet_list = client.list_subnets()
+        self.assertNotIn(subnet['id'],
+                         (s['id'] for s in subnet_list))
+        # Removes subnet from the cleanup list
+        self.subnets.remove(subnet)
+
 
 class ExternalNetworksTestXML(ExternalNetworksTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index c6480a1..4b5f107 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -65,6 +65,8 @@
         if getattr(cls, '_interface', None) == 'xml':
             if not CONF.network_feature_enabled.xml_api:
                 raise cls.skipException('XML API is not enabled')
+        if cls._ip_version == 6 and not CONF.network_feature_enabled.ipv6:
+            raise cls.skipException("IPv6 Tests are disabled.")
 
         os = cls.get_client_manager()
 
@@ -93,58 +95,95 @@
         if CONF.service_available.neutron:
             # Clean up ipsec policies
             for ipsecpolicy in cls.ipsecpolicies:
-                cls.client.delete_ipsecpolicy(ipsecpolicy['id'])
+                cls._try_delete_resource(cls.client.delete_ipsecpolicy,
+                                         ipsecpolicy['id'])
             # Clean up firewall policies
             for fw_policy in cls.fw_policies:
-                cls.client.delete_firewall_policy(fw_policy['id'])
+                cls._try_delete_resource(cls.client.delete_firewall_policy,
+                                         fw_policy['id'])
             # Clean up firewall rules
             for fw_rule in cls.fw_rules:
-                cls.client.delete_firewall_rule(fw_rule['id'])
+                cls._try_delete_resource(cls.client.delete_firewall_rule,
+                                         fw_rule['id'])
             # Clean up ike policies
             for ikepolicy in cls.ikepolicies:
-                cls.client.delete_ikepolicy(ikepolicy['id'])
+                cls._try_delete_resource(cls.client.delete_ikepolicy,
+                                         ikepolicy['id'])
             # Clean up vpn services
             for vpnservice in cls.vpnservices:
-                cls.client.delete_vpnservice(vpnservice['id'])
+                cls._try_delete_resource(cls.client.delete_vpnservice,
+                                         vpnservice['id'])
             # Clean up floating IPs
             for floating_ip in cls.floating_ips:
-                cls.client.delete_floatingip(floating_ip['id'])
+                cls._try_delete_resource(cls.client.delete_floatingip,
+                                         floating_ip['id'])
             # Clean up routers
             for router in cls.routers:
-                cls.delete_router(router)
+                cls._try_delete_resource(cls.delete_router,
+                                         router)
 
             # Clean up health monitors
             for health_monitor in cls.health_monitors:
-                cls.client.delete_health_monitor(health_monitor['id'])
+                cls._try_delete_resource(cls.client.delete_health_monitor,
+                                         health_monitor['id'])
             # Clean up members
             for member in cls.members:
-                cls.client.delete_member(member['id'])
+                cls._try_delete_resource(cls.client.delete_member,
+                                         member['id'])
             # Clean up vips
             for vip in cls.vips:
-                cls.client.delete_vip(vip['id'])
+                cls._try_delete_resource(cls.client.delete_vip,
+                                         vip['id'])
             # Clean up pools
             for pool in cls.pools:
-                cls.client.delete_pool(pool['id'])
+                cls._try_delete_resource(cls.client.delete_pool,
+                                         pool['id'])
             # Clean up metering label rules
             for metering_label_rule in cls.metering_label_rules:
-                cls.admin_client.delete_metering_label_rule(
+                cls._try_delete_resource(
+                    cls.admin_client.delete_metering_label_rule,
                     metering_label_rule['id'])
             # Clean up metering labels
             for metering_label in cls.metering_labels:
-                cls.admin_client.delete_metering_label(metering_label['id'])
+                cls._try_delete_resource(
+                    cls.admin_client.delete_metering_label,
+                    metering_label['id'])
             # Clean up ports
             for port in cls.ports:
-                cls.client.delete_port(port['id'])
+                cls._try_delete_resource(cls.client.delete_port,
+                                         port['id'])
             # Clean up subnets
             for subnet in cls.subnets:
-                cls.client.delete_subnet(subnet['id'])
+                cls._try_delete_resource(cls.client.delete_subnet,
+                                         subnet['id'])
             # Clean up networks
             for network in cls.networks:
-                cls.client.delete_network(network['id'])
+                cls._try_delete_resource(cls.client.delete_network,
+                                         network['id'])
             cls.clear_isolated_creds()
         super(BaseNetworkTest, cls).resource_cleanup()
 
     @classmethod
+    def _try_delete_resource(self, delete_callable, *args, **kwargs):
+        """Cleanup resources in case of test-failure
+
+        Some resources are explicitly deleted by the test.
+        If the test failed to delete a resource, this method will execute
+        the appropriate delete methods. Otherwise, the method ignores NotFound
+        exceptions thrown for resources that were correctly deleted by the
+        test.
+
+        :param delete_callable: delete method
+        :param args: arguments for delete method
+        :param kwargs: keyword arguments for delete method
+        """
+        try:
+            delete_callable(*args, **kwargs)
+        # if resource is not found, this means it was deleted in the test
+        except exceptions.NotFound:
+            pass
+
+    @classmethod
     def create_network(cls, network_name=None):
         """Wrapper utility that returns a test network."""
         network_name = network_name or data_utils.rand_name('test-network-')
@@ -155,33 +194,40 @@
         return network
 
     @classmethod
-    def create_subnet(cls, network, gateway=None, cidr=None, mask_bits=None,
-                      **kwargs):
+    def create_subnet(cls, network, gateway='', cidr=None, mask_bits=None,
+                      ip_version=None, client=None, **kwargs):
         """Wrapper utility that returns a test subnet."""
+
+        # allow tests to use admin client
+        if not client:
+            client = cls.client
+
         # The cidr and mask_bits depend on the ip version.
-        if cls._ip_version == 4:
+        ip_version = ip_version if ip_version is not None else cls._ip_version
+        gateway_not_set = gateway == ''
+        if ip_version == 4:
             cidr = cidr or netaddr.IPNetwork(CONF.network.tenant_network_cidr)
             mask_bits = mask_bits or CONF.network.tenant_network_mask_bits
-        elif cls._ip_version == 6:
+        elif ip_version == 6:
             cidr = (
                 cidr or netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr))
             mask_bits = mask_bits or CONF.network.tenant_network_v6_mask_bits
         # Find a cidr that is not in use yet and create a subnet with it
         for subnet_cidr in cidr.subnet(mask_bits):
-            if not gateway:
-                gateway = str(netaddr.IPAddress(subnet_cidr) + 1)
+            if gateway_not_set:
+                gateway_ip = str(netaddr.IPAddress(subnet_cidr) + 1)
+            else:
+                gateway_ip = gateway
             try:
-                resp, body = cls.client.create_subnet(
+                resp, body = client.create_subnet(
                     network_id=network['id'],
                     cidr=str(subnet_cidr),
-                    ip_version=cls._ip_version,
-                    gateway_ip=gateway,
+                    ip_version=ip_version,
+                    gateway_ip=gateway_ip,
                     **kwargs)
                 break
             except exceptions.BadRequest as e:
                 is_overlapping_cidr = 'overlaps with another subnet' in str(e)
-                # Unset gateway value if there is an overlapping subnet
-                gateway = None
                 if not is_overlapping_cidr:
                     raise
         else:
@@ -269,9 +315,11 @@
         return vip
 
     @classmethod
-    def create_member(cls, protocol_port, pool):
+    def create_member(cls, protocol_port, pool, ip_version=None):
         """Wrapper utility that returns a test member."""
-        resp, body = cls.client.create_member(address="10.0.9.46",
+        ip_version = ip_version if ip_version is not None else cls._ip_version
+        member_address = "fd00::abcd" if ip_version == 6 else "10.0.9.46"
+        resp, body = cls.client.create_member(address=member_address,
                                               protocol_port=protocol_port,
                                               pool_id=pool['id'])
         member = body['member']
diff --git a/tempest/api/network/test_allowed_address_pair.py b/tempest/api/network/test_allowed_address_pair.py
index c085c39..a1166c8 100644
--- a/tempest/api/network/test_allowed_address_pair.py
+++ b/tempest/api/network/test_allowed_address_pair.py
@@ -13,9 +13,14 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import netaddr
+
 from tempest.api.network import base
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class AllowedAddressPairTestJSON(base.BaseNetworkTest):
     _interface = 'json'
@@ -68,22 +73,50 @@
         self._confirm_allowed_address_pair(port[0], self.ip_address)
 
     @test.attr(type='smoke')
-    def test_update_port_with_address_pair(self):
+    def _update_port_with_address(self, address, mac_address=None, **kwargs):
         # Create a port without allowed address pair
         _, body = self.client.create_port(network_id=self.network['id'])
         port_id = body['port']['id']
         self.addCleanup(self.client.delete_port, port_id)
-
-        # Confirm  port is created
-        _, body = self.client.show_port(port_id)
+        if mac_address is None:
+            mac_address = self.mac_address
 
         # Update allowed address pair attribute of port
-        allowed_address_pairs = [{'ip_address': self.ip_address,
-                                  'mac_address': self.mac_address}]
+        allowed_address_pairs = [{'ip_address': address,
+                                  'mac_address': mac_address}]
+        if kwargs:
+            allowed_address_pairs.append(kwargs['allowed_address_pairs'])
         _, body = self.client.update_port(
             port_id, allowed_address_pairs=allowed_address_pairs)
-        newport = body['port']
-        self._confirm_allowed_address_pair(newport, self.ip_address)
+        allowed_address_pair = body['port']['allowed_address_pairs']
+        self.assertEqual(allowed_address_pair, allowed_address_pairs)
+
+    @test.attr(type='smoke')
+    def test_update_port_with_address_pair(self):
+        # Update port with allowed address pair
+        self._update_port_with_address(self.ip_address)
+
+    @test.attr(type='smoke')
+    def test_update_port_with_cidr_address_pair(self):
+        # Update allowed address pair with cidr
+        cidr = str(netaddr.IPNetwork(CONF.network.tenant_network_cidr))
+        self._update_port_with_address(cidr)
+
+    @test.attr(type='smoke')
+    def test_update_port_with_multiple_ip_mac_address_pair(self):
+        # Create an ip _address and mac_address through port create
+        _, resp = self.client.create_port(network_id=self.network['id'])
+        newportid = resp['port']['id']
+        self.addCleanup(self.client.delete_port, newportid)
+        ipaddress = resp['port']['fixed_ips'][0]['ip_address']
+        macaddress = resp['port']['mac_address']
+
+        # Update allowed address pair port with multiple ip and  mac
+        allowed_address_pairs = {'ip_address': ipaddress,
+                                 'mac_address': macaddress}
+        self._update_port_with_address(
+            self.ip_address, self.mac_address,
+            allowed_address_pairs=allowed_address_pairs)
 
     def _confirm_allowed_address_pair(self, port, ip):
         msg = 'Port allowed address pairs should not be empty'
@@ -94,5 +127,9 @@
         self.assertEqual(mac_address, self.mac_address)
 
 
+class AllowedAddressPairIpV6TestJSON(AllowedAddressPairTestJSON):
+    _ip_version = 6
+
+
 class AllowedAddressPairTestXML(AllowedAddressPairTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/network/test_extra_dhcp_options.py b/tempest/api/network/test_extra_dhcp_options.py
index 86da9b7..6d083b3 100644
--- a/tempest/api/network/test_extra_dhcp_options.py
+++ b/tempest/api/network/test_extra_dhcp_options.py
@@ -44,17 +44,22 @@
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
         cls.port = cls.create_port(cls.network)
+        cls.ip_tftp = ('123.123.123.123' if cls._ip_version == 4
+                       else '2015::dead')
+        cls.ip_server = ('123.123.123.45' if cls._ip_version == 4
+                         else '2015::badd')
+        cls.extra_dhcp_opts = [
+            {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
+            {'opt_value': cls.ip_tftp, 'opt_name': 'tftp-server'},
+            {'opt_value': cls.ip_server, 'opt_name': 'server-ip-address'}
+        ]
 
     @test.attr(type='smoke')
     def test_create_list_port_with_extra_dhcp_options(self):
         # Create a port with Extra DHCP Options
-        extra_dhcp_opts = [
-            {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
-            {'opt_value': '123.123.123.123', 'opt_name': 'tftp-server'},
-            {'opt_value': '123.123.123.45', 'opt_name': 'server-ip-address'}
-        ]
-        _, body = self.client.create_port(network_id=self.network['id'],
-                                          extra_dhcp_opts=extra_dhcp_opts)
+        _, body = self.client.create_port(
+            network_id=self.network['id'],
+            extra_dhcp_opts=self.extra_dhcp_opts)
         port_id = body['port']['id']
         self.addCleanup(self.client.delete_port, port_id)
 
@@ -63,23 +68,19 @@
         ports = body['ports']
         port = [p for p in ports if p['id'] == port_id]
         self.assertTrue(port)
-        self._confirm_extra_dhcp_options(port[0], extra_dhcp_opts)
+        self._confirm_extra_dhcp_options(port[0], self.extra_dhcp_opts)
 
     @test.attr(type='smoke')
     def test_update_show_port_with_extra_dhcp_options(self):
         # Update port with extra dhcp options
-        extra_dhcp_opts = [
-            {'opt_value': 'pxelinux.0', 'opt_name': 'bootfile-name'},
-            {'opt_value': '123.123.123.123', 'opt_name': 'tftp-server'},
-            {'opt_value': '123.123.123.45', 'opt_name': 'server-ip-address'}
-        ]
         name = data_utils.rand_name('new-port-name')
-        _, body = self.client.update_port(self.port['id'], name=name,
-                                          extra_dhcp_opts=extra_dhcp_opts)
-
+        _, body = self.client.update_port(
+            self.port['id'],
+            name=name,
+            extra_dhcp_opts=self.extra_dhcp_opts)
         # Confirm extra dhcp options were added to the port
         _, body = self.client.show_port(self.port['id'])
-        self._confirm_extra_dhcp_options(body['port'], extra_dhcp_opts)
+        self._confirm_extra_dhcp_options(body['port'], self.extra_dhcp_opts)
 
     def _confirm_extra_dhcp_options(self, port, extra_dhcp_opts):
         retrieved = port['extra_dhcp_opts']
@@ -92,3 +93,7 @@
             else:
                 self.fail('Extra DHCP option not found in port %s' %
                           str(retrieved_option))
+
+
+class ExtraDHCPOptionsIpV6TestJSON(ExtraDHCPOptionsTestJSON):
+    _ip_version = 6
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index baa8cad..8b8e3b1 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -55,7 +55,9 @@
                                  protocol_port=80,
                                  subnet=cls.subnet,
                                  pool=cls.pool)
-        cls.member = cls.create_member(80, cls.pool)
+        cls.member = cls.create_member(80, cls.pool, cls._ip_version)
+        cls.member_address = ("10.0.9.47" if cls._ip_version == 4
+                              else "2015::beef")
         cls.health_monitor = cls.create_health_monitor(delay=4,
                                                        max_retries=3,
                                                        Type="TCP",
@@ -213,13 +215,14 @@
     def test_list_members_with_filters(self):
         attr_exceptions = ['status', 'status_description']
         self._check_list_with_filter('member', attr_exceptions,
-                                     address="10.0.9.47", protocol_port=80,
+                                     address=self.member_address,
+                                     protocol_port=80,
                                      pool_id=self.pool['id'])
 
     @test.attr(type='smoke')
     def test_create_update_delete_member(self):
         # Creates a member
-        _, body = self.client.create_member(address="10.0.9.47",
+        _, body = self.client.create_member(address=self.member_address,
                                             protocol_port=80,
                                             pool_id=self.pool['id'])
         member = body['member']
@@ -419,5 +422,9 @@
         self.assertEqual(2, member['weight'])
 
 
+class LoadBalancerIpV6TestJSON(LoadBalancerTestJSON):
+    _ip_version = 6
+
+
 class LoadBalancerTestXML(LoadBalancerTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/network/test_metering_extensions.py b/tempest/api/network/test_metering_extensions.py
index 2cfb841..07ebd8c 100644
--- a/tempest/api/network/test_metering_extensions.py
+++ b/tempest/api/network/test_metering_extensions.py
@@ -43,7 +43,8 @@
         description = "metering label created by tempest"
         name = data_utils.rand_name("metering-label")
         cls.metering_label = cls.create_metering_label(name, description)
-        remote_ip_prefix = "10.0.0.0/24"
+        remote_ip_prefix = ("10.0.0.0/24" if cls._ip_version == 4
+                            else "fd02::/64")
         direction = "ingress"
         cls.metering_label_rule = cls.create_metering_label_rule(
             remote_ip_prefix, direction,
@@ -112,8 +113,10 @@
     @test.attr(type='smoke')
     def test_create_delete_metering_label_rule_with_filters(self):
         # Creates a rule
+        remote_ip_prefix = ("10.0.1.0/24" if self._ip_version == 4
+                            else "fd03::/64")
         _, body = (self.admin_client.create_metering_label_rule(
-                   remote_ip_prefix="10.0.1.0/24",
+                   remote_ip_prefix=remote_ip_prefix,
                    direction="ingress",
                    metering_label_id=self.metering_label['id']))
         metering_label_rule = body['metering_label_rule']
@@ -142,5 +145,9 @@
         self.assertFalse(metering_label_rule['excluded'])
 
 
+class MeteringIpV6JSON(MeteringJSON):
+    _ip_version = 6
+
+
 class MeteringXML(MeteringJSON):
     interface = 'xml'
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 986a2c8..be23a82 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -12,6 +12,7 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
+import itertools
 
 import netaddr
 import testtools
@@ -42,6 +43,7 @@
         network update
         subnet update
         delete a network also deletes its subnets
+        list external networks
 
         All subnet tests are run once with ipv4 and once with ipv6.
 
@@ -280,6 +282,10 @@
         self.subnets.pop()
 
     @test.attr(type='smoke')
+    def test_create_delete_subnet_without_gateway(self):
+        self._create_verify_delete_subnet()
+
+    @test.attr(type='smoke')
     def test_create_delete_subnet_with_gw(self):
         self._create_verify_delete_subnet(
             **self.subnet_dict(['gateway']))
@@ -341,6 +347,28 @@
             enable_dhcp=True,
             **self.subnet_dict(['gateway', 'host_routes', 'dns_nameservers']))
 
+    @test.attr(type='smoke')
+    def test_external_network_visibility(self):
+        """Verifies user can see external networks but not subnets."""
+        _, body = self.client.list_networks(**{'router:external': True})
+        networks = [network['id'] for network in body['networks']]
+        self.assertNotEmpty(networks, "No external networks found")
+
+        nonexternal = [net for net in body['networks'] if
+                       not net['router:external']]
+        self.assertEmpty(nonexternal, "Found non-external networks"
+                                      " in filtered list (%s)." % nonexternal)
+        self.assertIn(CONF.network.public_network_id, networks)
+
+        subnets_iter = (network['subnets'] for network in body['networks'])
+        # subnets_iter is a list (iterator) of lists. This flattens it to a
+        # list of UUIDs
+        public_subnets_iter = itertools.chain(*subnets_iter)
+        _, body = self.client.list_subnets()
+        subnets = [sub['id'] for sub in body['subnets']
+                   if sub['id'] in public_subnets_iter]
+        self.assertEmpty(subnets, "Public subnets visible")
+
 
 class NetworksTestXML(NetworksTestJSON):
     _interface = 'xml'
@@ -474,13 +502,6 @@
 class NetworksIpV6TestJSON(NetworksTestJSON):
     _ip_version = 6
 
-    @classmethod
-    def resource_setup(cls):
-        if not CONF.network_feature_enabled.ipv6:
-            skip_msg = "IPv6 Tests are disabled."
-            raise cls.skipException(skip_msg)
-        super(NetworksIpV6TestJSON, cls).resource_setup()
-
     @test.attr(type='smoke')
     def test_create_delete_subnet_with_gw(self):
         net = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
@@ -492,7 +513,7 @@
         self.assertEqual(subnet['gateway_ip'], gateway)
 
     @test.attr(type='smoke')
-    def test_create_delete_subnet_without_gw(self):
+    def test_create_delete_subnet_with_default_gw(self):
         net = netaddr.IPNetwork(CONF.network.tenant_network_v6_cidr)
         gateway_ip = str(netaddr.IPAddress(net.first + 1))
         name = data_utils.rand_name('network-')
@@ -501,16 +522,62 @@
         # Verifies Subnet GW in IPv6
         self.assertEqual(subnet['gateway_ip'], gateway_ip)
 
+    @test.attr(type='smoke')
+    def test_create_list_subnet_with_no_gw64_one_network(self):
+        name = data_utils.rand_name('network-')
+        network = self.create_network(name)
+        ipv6_gateway = self.subnet_dict(['gateway'])['gateway']
+        subnet1 = self.create_subnet(network,
+                                     ip_version=6,
+                                     gateway=ipv6_gateway)
+        self.assertEqual(netaddr.IPNetwork(subnet1['cidr']).version, 6,
+                         'The created subnet is not IPv6')
+        subnet2 = self.create_subnet(network,
+                                     gateway=None,
+                                     ip_version=4)
+        self.assertEqual(netaddr.IPNetwork(subnet2['cidr']).version, 4,
+                         'The created subnet is not IPv4')
+        # Verifies Subnet GW is set in IPv6
+        self.assertEqual(subnet1['gateway_ip'], ipv6_gateway)
+        # Verifies Subnet GW is None in IPv4
+        self.assertEqual(subnet2['gateway_ip'], None)
+        # Verifies all 2 subnets in the same network
+        _, body = self.client.list_subnets()
+        subnets = [sub['id'] for sub in body['subnets']
+                   if sub['network_id'] == network['id']]
+        test_subnet_ids = [sub['id'] for sub in (subnet1, subnet2)]
+        self.assertItemsEqual(subnets,
+                              test_subnet_ids,
+                              'Subnet are not in the same network')
+
     @testtools.skipUnless(CONF.network_feature_enabled.ipv6_subnet_attributes,
                           "IPv6 extended attributes for subnets not "
                           "available")
     @test.attr(type='smoke')
-    def test_create_delete_subnet_with_v6_attributes(self):
+    def test_create_delete_subnet_with_v6_attributes_stateful(self):
         self._create_verify_delete_subnet(
             gateway=self._subnet_data[self._ip_version]['gateway'],
+            ipv6_ra_mode='dhcpv6-stateful',
+            ipv6_address_mode='dhcpv6-stateful')
+
+    @testtools.skipUnless(CONF.network_feature_enabled.ipv6_subnet_attributes,
+                          "IPv6 extended attributes for subnets not "
+                          "available")
+    @test.attr(type='smoke')
+    def test_create_delete_subnet_with_v6_attributes_slaac(self):
+        self._create_verify_delete_subnet(
             ipv6_ra_mode='slaac',
             ipv6_address_mode='slaac')
 
+    @testtools.skipUnless(CONF.network_feature_enabled.ipv6_subnet_attributes,
+                          "IPv6 extended attributes for subnets not "
+                          "available")
+    @test.attr(type='smoke')
+    def test_create_delete_subnet_with_v6_attributes_stateless(self):
+        self._create_verify_delete_subnet(
+            ipv6_ra_mode='dhcpv6-stateless',
+            ipv6_address_mode='dhcpv6-stateless')
+
 
 class NetworksIpV6TestXML(NetworksIpV6TestJSON):
     _interface = 'xml'
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index d6db64d..7c5bdfe 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -276,13 +276,6 @@
     _tenant_network_cidr = CONF.network.tenant_network_v6_cidr
     _tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
 
-    @classmethod
-    def resource_setup(cls):
-        super(PortsIpV6TestJSON, cls).resource_setup()
-        if not CONF.network_feature_enabled.ipv6:
-            skip_msg = "IPv6 Tests are disabled."
-            raise cls.skipException(skip_msg)
-
 
 class PortsIpV6TestXML(PortsIpV6TestJSON):
     _interface = 'xml'
@@ -293,13 +286,6 @@
     _tenant_network_cidr = CONF.network.tenant_network_v6_cidr
     _tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
 
-    @classmethod
-    def resource_setup(cls):
-        if not CONF.network_feature_enabled.ipv6:
-            skip_msg = "IPv6 Tests are disabled."
-            raise cls.skipException(skip_msg)
-        super(PortsAdminExtendedAttrsIpV6TestJSON, cls).resource_setup()
-
 
 class PortsAdminExtendedAttrsIpV6TestXML(PortsAdminExtendedAttrsIpV6TestJSON):
     _interface = 'xml'
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index f3f25ac..2b4e60a 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -35,6 +35,9 @@
             raise cls.skipException(msg)
         admin_manager = clients.AdminManager()
         cls.identity_admin_client = admin_manager.identity_client
+        cls.tenant_cidr = (CONF.network.tenant_network_cidr
+                           if cls._ip_version == 4 else
+                           CONF.network.tenant_network_v6_cidr)
 
     def _cleanup_router(self, router):
         self.delete_router(router)
@@ -319,7 +322,7 @@
         network02 = self.create_network(
             network_name=data_utils.rand_name('router-network02-'))
         subnet01 = self.create_subnet(network01)
-        sub02_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr).next()
+        sub02_cidr = netaddr.IPNetwork(self.tenant_cidr).next()
         subnet02 = self.create_subnet(network02, cidr=sub02_cidr)
         router = self._create_router(data_utils.rand_name('router-'))
         interface01 = self._add_router_interface_with_subnet_id(router['id'],
@@ -337,3 +340,7 @@
         self.assertEqual(router_id, interface_port['device_id'])
         self.assertEqual(subnet_id,
                          interface_port['fixed_ips'][0]['subnet_id'])
+
+
+class RoutersIpV6Test(RoutersTest):
+    _ip_version = 6
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 4c226af..88aa3c9 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -36,6 +36,9 @@
         cls.router = cls.create_router(data_utils.rand_name('router-'))
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
+        cls.tenant_cidr = (CONF.network.tenant_network_cidr
+                           if cls._ip_version == 4 else
+                           CONF.network.tenant_network_v6_cidr)
 
     @test.attr(type=['negative', 'smoke'])
     def test_router_add_gateway_invalid_network_returns_404(self):
@@ -49,7 +52,7 @@
     def test_router_add_gateway_net_not_external_returns_400(self):
         alt_network = self.create_network(
             network_name=data_utils.rand_name('router-negative-'))
-        sub_cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr).next()
+        sub_cidr = netaddr.IPNetwork(self.tenant_cidr).next()
         self.create_subnet(alt_network, cidr=sub_cidr)
         self.assertRaises(exceptions.BadRequest,
                           self.client.update_router,
@@ -79,3 +82,7 @@
         self.assertRaises(exceptions.Conflict,
                           self.client.delete_router,
                           self.router['id'])
+
+
+class RoutersNegativeIpV6Test(RoutersNegativeTest):
+    _ip_version = 6
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index e20b58e..47f2b52 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -221,13 +221,6 @@
     _ip_version = 6
     _tenant_network_cidr = CONF.network.tenant_network_v6_cidr
 
-    @classmethod
-    def resource_setup(cls):
-        if not CONF.network_feature_enabled.ipv6:
-            skip_msg = "IPv6 Tests are disabled."
-            raise cls.skipException(skip_msg)
-        super(SecGroupIPv6Test, cls).resource_setup()
-
 
 class SecGroupIPv6TestXML(SecGroupIPv6Test):
     _interface = 'xml'
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index 97e4cb7..42f7f71 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -197,13 +197,6 @@
     _ip_version = 6
     _tenant_network_cidr = CONF.network.tenant_network_v6_cidr
 
-    @classmethod
-    def resource_setup(cls):
-        if not CONF.network_feature_enabled.ipv6:
-            skip_msg = "IPv6 Tests are disabled."
-            raise cls.skipException(skip_msg)
-        super(NegativeSecGroupIPv6Test, cls).resource_setup()
-
 
 class NegativeSecGroupIPv6TestXML(NegativeSecGroupIPv6Test):
     _interface = 'xml'
diff --git a/tempest/api/network/test_vpnaas_extensions.py b/tempest/api/network/test_vpnaas_extensions.py
index c61bf41..96b9804 100644
--- a/tempest/api/network/test_vpnaas_extensions.py
+++ b/tempest/api/network/test_vpnaas_extensions.py
@@ -39,6 +39,7 @@
             msg = "vpnaas extension not enabled."
             raise cls.skipException(msg)
         super(VPNaaSTestJSON, cls).resource_setup()
+        cls.ext_net_id = CONF.network.public_network_id
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
         cls.router = cls.create_router(
@@ -121,17 +122,21 @@
         tenant_id = self._get_tenant_id()
 
         # Create vpn service for the newly created tenant
+        network2 = self.create_network()
+        subnet2 = self.create_subnet(network2)
+        router2 = self.create_router(data_utils.rand_name('router-'),
+                                     external_network_id=self.ext_net_id)
+        self.create_router_interface(router2['id'], subnet2['id'])
         name = data_utils.rand_name('vpn-service')
         _, body = self.admin_client.create_vpnservice(
-            subnet_id=self.subnet['id'],
-            router_id=self.router['id'],
+            subnet_id=subnet2['id'],
+            router_id=router2['id'],
             name=name,
             admin_state_up=True,
             tenant_id=tenant_id)
         vpnservice = body['vpnservice']
         self.assertIsNotNone(vpnservice['id'])
         self.addCleanup(self.admin_client.delete_vpnservice, vpnservice['id'])
-
         # Assert that created vpnservice is found in API list call
         _, body = self.client.list_vpnservices()
         vpn_services = [vs['id'] for vs in body['vpnservices']]
@@ -167,9 +172,14 @@
     @test.attr(type='smoke')
     def test_create_update_delete_vpn_service(self):
         # Creates a VPN service and sets up deletion
-        name = data_utils.rand_name('vpn-service')
-        _, body = self.client.create_vpnservice(subnet_id=self.subnet['id'],
-                                                router_id=self.router['id'],
+        network1 = self.create_network()
+        subnet1 = self.create_subnet(network1)
+        router1 = self.create_router(data_utils.rand_name('router-'),
+                                     external_network_id=self.ext_net_id)
+        self.create_router_interface(router1['id'], subnet1['id'])
+        name = data_utils.rand_name('vpn-service1')
+        _, body = self.client.create_vpnservice(subnet_id=subnet1['id'],
+                                                router_id=router1['id'],
                                                 name=name,
                                                 admin_state_up=True)
         vpnservice = body['vpnservice']
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index 743f1aa..31a80cf 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -74,8 +74,6 @@
 
         self.containers.append(container_name)
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
-
         # When uploading an archived file with the bulk operation, the response
         # does not contain 'content-length' header. This is the special case,
         # therefore the existence of response headers is checked without
@@ -91,7 +89,6 @@
         param = {'format': 'json'}
         resp, body = self.account_client.list_account_containers(param)
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'GET')
 
         self.assertIn(container_name, [b['name'] for b in body])
@@ -100,7 +97,6 @@
         resp, contents_list = self.container_client.list_container_contents(
             container_name, param)
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
 
         self.assertIn(object_name, [c['name'] for c in contents_list])
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 97e9195..e75e971 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -83,7 +83,6 @@
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
 
-        self.assertEqual(resp["status"], "201")
         self.assertHeaders(resp, 'Object', 'PUT')
 
     @test.attr(type=["smoke"])
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index a0436ee..2bc4f59 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -67,7 +67,6 @@
 
         resp, container_list = \
             os_test_user.account_client.list_account_containers()
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
 
         # When sending a request to an account which has not received a PUT
         # container request, the response does not contain 'accept-ranges'
@@ -93,7 +92,6 @@
         params = {'format': 'json'}
         resp, container_list = self.account_client.list_account_containers(
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertIsNotNone(container_list)
         self.assertTrue([c['name'] for c in container_list])
@@ -106,7 +104,6 @@
         params = {'format': 'xml'}
         resp, container_list = self.account_client.list_account_containers(
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertIsNotNone(container_list)
         self.assertEqual(container_list.tag, 'account')
@@ -123,7 +120,6 @@
     def test_list_extensions(self):
         resp, extensions = self.account_client.list_extensions()
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertThat(resp, custom_matchers.AreAllWellFormatted())
 
     @test.attr(type='smoke')
@@ -182,7 +178,6 @@
                   'end_marker': self.containers[self.containers_count - 1]}
         resp, container_list = self.account_client.list_account_containers(
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list), self.containers_count - 2)
 
@@ -208,7 +203,6 @@
                   'end_marker': self.containers[self.containers_count / 2]}
         resp, container_list = self.account_client.list_account_containers(
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list),
                          min(limit, self.containers_count / 2))
@@ -222,7 +216,6 @@
                   'end_marker': self.containers[self.containers_count - 1]}
         resp, container_list = self.account_client.list_account_containers(
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list),
                          min(limit, self.containers_count - 2))
@@ -237,7 +230,6 @@
         resp, _ = self.account_client.create_account_metadata(metadata)
 
         resp, _ = self.account_client.list_account_metadata()
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'HEAD')
         self.assertIn('x-account-meta-test-account-meta1', resp)
         self.assertIn('x-account-meta-test-account-meta2', resp)
@@ -247,7 +239,6 @@
     def test_list_no_account_metadata(self):
         # list no account metadata
         resp, _ = self.account_client.list_account_metadata()
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'HEAD')
         self.assertNotIn('x-account-meta-', str(resp))
 
@@ -256,7 +247,6 @@
         # add metadata to account
         metadata = {'test-account-meta1': 'Meta1'}
         resp, _ = self.account_client.create_account_metadata(metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, body = self.account_client.list_account_metadata()
@@ -272,7 +262,6 @@
         metadata = {'test-account-meta1': 'Meta1'}
         self.account_client.create_account_metadata(metadata)
         resp, _ = self.account_client.delete_account_metadata(metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
@@ -284,7 +273,6 @@
         # registered at a server
         metadata = {'test-account-meta1': ''}
         resp, _ = self.account_client.create_account_metadata(metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
@@ -298,7 +286,6 @@
         self.account_client.create_account_metadata(metadata_1)
         metadata_2 = {'test-account-meta1': ''}
         resp, _ = self.account_client.delete_account_metadata(metadata_2)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
@@ -313,7 +300,6 @@
         resp, body = self.account_client.create_and_delete_account_metadata(
             metadata_2,
             metadata_1)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Account', 'POST')
 
         resp, _ = self.account_client.list_account_metadata()
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index e816a9f..2244900 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -45,13 +45,11 @@
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'POST')
         # create object
         object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, 'data')
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
         # Trying to read the object with rights
         self.custom_object_client.auth_provider.set_alt_auth_data(
@@ -60,7 +58,6 @@
         )
         resp, _ = self.custom_object_client.get_object(
             self.container_name, object_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
 
     @test.attr(type='smoke')
@@ -72,7 +69,6 @@
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'POST')
         # Trying to write the object with rights
         self.custom_object_client.auth_provider.set_alt_auth_data(
@@ -83,5 +79,4 @@
         resp, _ = self.custom_object_client.create_object(
             self.container_name,
             object_name, 'data')
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'PUT')
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 9b49db3..fed4549 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -88,7 +88,6 @@
         object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(
             self.container_name, object_name, 'data')
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
         # trying to get object with non authorized user token
         self.custom_object_client.auth_provider.set_alt_auth_data(
@@ -106,7 +105,6 @@
         object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(
             self.container_name, object_name, 'data')
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
         # trying to delete object with non-authorized user token
         self.custom_object_client.auth_provider.set_alt_auth_data(
@@ -125,13 +123,11 @@
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'POST')
         # create object
         object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, 'data')
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
         # Trying to read the object without rights
         self.custom_object_client.auth_provider.set_alt_auth_data(
@@ -150,7 +146,6 @@
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'POST')
         # Trying to write the object without rights
         self.custom_object_client.auth_provider.set_alt_auth_data(
@@ -173,7 +168,6 @@
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'POST')
         # Trying to write the object without write rights
         self.custom_object_client.auth_provider.set_alt_auth_data(
@@ -196,13 +190,11 @@
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'POST')
         # create object
         object_name = data_utils.rand_name(name='Object')
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, 'data')
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
         # Trying to delete the object without write rights
         self.custom_object_client.auth_provider.set_alt_auth_data(
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index 59b84d9..46944ed 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -61,7 +61,6 @@
 
         resp, _ = self.object_client.create_object(
             self.container_name, object_name, data)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'PUT')
 
         nafter = self._get_bytes_used()
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 8689d10..fe06fd0 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -51,7 +51,6 @@
         container_name = data_utils.rand_name(name='TestContainer')
         resp, body = self.container_client.create_container(container_name)
         self.containers.append(container_name)
-        self.assertIn(resp['status'], ('202', '201'))
         self.assertHeaders(resp, 'Container', 'PUT')
 
     @test.attr(type='smoke')
@@ -62,7 +61,6 @@
         self.containers.append(container_name)
 
         resp, _ = self.container_client.create_container(container_name)
-        self.assertIn(resp['status'], ('202', '201'))
         self.assertHeaders(resp, 'Container', 'PUT')
 
     @test.attr(type='smoke')
@@ -74,7 +72,6 @@
             container_name,
             metadata=metadata)
         self.containers.append(container_name)
-        self.assertIn(resp['status'], ('201', '202'))
         self.assertHeaders(resp, 'Container', 'PUT')
 
         resp, _ = self.container_client.list_container_metadata(
@@ -93,7 +90,6 @@
             container_name,
             metadata=metadata)
         self.containers.append(container_name)
-        self.assertIn(resp['status'], ('201', '202'))
         self.assertHeaders(resp, 'Container', 'PUT')
 
         resp, _ = self.container_client.list_container_metadata(
@@ -116,7 +112,6 @@
         resp, _ = self.container_client.create_container(
             container_name,
             remove_metadata=metadata_2)
-        self.assertIn(resp['status'], ('201', '202'))
         self.assertHeaders(resp, 'Container', 'PUT')
 
         resp, _ = self.container_client.list_container_metadata(
@@ -135,7 +130,6 @@
         resp, _ = self.container_client.create_container(
             container_name,
             remove_metadata=metadata)
-        self.assertIn(resp['status'], ('201', '202'))
         self.assertHeaders(resp, 'Container', 'PUT')
 
         resp, _ = self.container_client.list_container_metadata(
@@ -146,11 +140,9 @@
     def test_delete_container(self):
         # create a container
         container_name = self._create_container()
-        # delete container
+        # delete container, success asserted within
         resp, _ = self.container_client.delete_container(container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'DELETE')
-
         self.containers.remove(container_name)
 
     @test.attr(type='smoke')
@@ -161,7 +153,6 @@
 
         resp, object_list = self.container_client.list_container_contents(
             container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
@@ -172,7 +163,6 @@
 
         resp, object_list = self.container_client.list_container_contents(
             container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual('', object_list.strip('\n'))
 
@@ -187,7 +177,6 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name,
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name.split('/')[0], object_list.strip('/\n'))
 
@@ -201,7 +190,6 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name,
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
@@ -215,7 +203,6 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name,
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
 
         self.assertIsNotNone(object_list)
@@ -235,7 +222,6 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name,
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
 
         self.assertIsNotNone(object_list)
@@ -260,7 +246,6 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name,
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
@@ -274,7 +259,6 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name,
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
@@ -289,7 +273,6 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name,
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
@@ -304,7 +287,6 @@
         resp, object_list = self.container_client.list_container_contents(
             container_name,
             params=params)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
@@ -320,7 +302,6 @@
 
         resp, _ = self.container_client.list_container_metadata(
             container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'HEAD')
         self.assertIn('x-container-meta-name', resp)
         self.assertEqual(resp['x-container-meta-name'], metadata['name'])
@@ -332,7 +313,6 @@
 
         resp, _ = self.container_client.list_container_metadata(
             container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'HEAD')
         self.assertNotIn('x-container-meta-', str(resp))
 
@@ -350,7 +330,6 @@
             container_name,
             metadata=metadata_2,
             remove_metadata=metadata_1)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'POST')
 
         resp, _ = self.container_client.list_container_metadata(
@@ -369,7 +348,6 @@
         resp, _ = self.container_client.update_container_metadata(
             container_name,
             metadata=metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'POST')
 
         resp, _ = self.container_client.list_container_metadata(
@@ -390,7 +368,6 @@
         resp, _ = self.container_client.delete_container_metadata(
             container_name,
             metadata=metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'POST')
 
         resp, _ = self.container_client.list_container_metadata(
@@ -406,7 +383,6 @@
         resp, _ = self.container_client.update_container_metadata(
             container_name,
             metadata=metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'POST')
 
         resp, _ = self.container_client.list_container_metadata(
@@ -426,7 +402,6 @@
         resp, _ = self.container_client.delete_container_metadata(
             container_name,
             metadata=metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'POST')
 
         resp, _ = self.container_client.list_container_metadata(container_name)
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index 966a08d..5c4e0bf 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -67,7 +67,6 @@
         # we should retrieve the self.object_name file
         resp, body = self.custom_account_client.request("GET",
                                                         self.container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         # This request is equivalent to GET object
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, self.object_data)
@@ -92,7 +91,6 @@
         # we should retrieve a listing of objects
         resp, body = self.custom_account_client.request("GET",
                                                         self.container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         # The target of the request is not any Swift resource. Therefore, the
         # existence of response header is checked without a custom matcher.
         self.assertIn('content-length', resp)
@@ -131,7 +129,6 @@
         # we should retrieve a listing of objects
         resp, body = self.custom_account_client.request("GET",
                                                         self.container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertIn(self.object_name, body)
         css = '<link rel="stylesheet" type="text/css" href="listings.css" />'
         self.assertIn(css, body)
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index aebcb5c..a50e392 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -90,12 +90,10 @@
                        (client_base_url, str(cont[1]))}
             resp, body = \
                 cont_client[0].put(str(cont[0]), body=None, headers=headers)
-            self.assertIn(int(resp['status']), test.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.assertIn(int(resp['status']), test.HTTP_SUCCESS)
             self.objects.append(object_name)
 
         # wait until container contents list is not empty
@@ -108,7 +106,6 @@
                     cont_client[client_index].\
                     list_container_contents(self.containers[client_index],
                                             params=params)
-                self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
                 object_lists.append(dict(
                     (obj['name'], obj) for obj in object_list))
             # check that containers are not empty and have equal keys()
@@ -128,5 +125,4 @@
         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']), test.HTTP_SUCCESS)
                 self.assertEqual(object_content, obj_name[::-1])
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index f6d1fb9..66e8176 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -43,7 +43,6 @@
     def test_get_crossdomain_policy(self):
         resp, body = self.account_client.get("crossdomain.xml", {})
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertTrue(body.startswith(self.xml_start) and
                         body.endswith(self.xml_end))
 
diff --git a/tempest/api/object_storage/test_healthcheck.py b/tempest/api/object_storage/test_healthcheck.py
index a1138e6..53c0347 100644
--- a/tempest/api/object_storage/test_healthcheck.py
+++ b/tempest/api/object_storage/test_healthcheck.py
@@ -36,9 +36,6 @@
 
         resp, _ = self.account_client.get("healthcheck", {})
 
-        # The status is expected to be 200
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
-
         # The target of the request is not any Swift resource. Therefore, the
         # existence of response header is checked without a custom matcher.
         self.assertIn('content-length', resp)
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index 8cec2fc..5fa209d 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -51,7 +51,6 @@
         resp, _ = \
             self.object_client.list_object_metadata(self.container_name,
                                                     self.object_name)
-        self.assertEqual(resp['status'], '200')
         self.assertHeaders(resp, 'Object', 'HEAD')
         self.assertIn('x-delete-at', resp)
         # we want to ensure that we will sleep long enough for things to
@@ -60,7 +59,6 @@
 
         resp, body = self.object_client.get_object(self.container_name,
                                                    self.object_name)
-        self.assertEqual(resp['status'], '200')
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertIn('x-delete-at', resp)
 
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index 05c8ff2..7a9fcf6 100644
--- a/tempest/api/object_storage/test_object_formpost.py
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -117,12 +117,10 @@
         url = "%s/%s" % (self.container_name, self.object_name)
 
         resp, body = self.object_client.post(url, body, headers=headers)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, "Object", "POST")
 
         # Ensure object is available
         resp, body = self.object_client.get("%s/%s%s" % (
             self.container_name, self.object_name, "testfile"))
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, "Object", "GET")
         self.assertEqual(body, "hello world")
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 56ab1fb..f78220c 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -60,7 +60,6 @@
         for i in six.moves.xrange(segments):
             resp, _ = self.object_client.create_object_segments(
                 self.container_name, object_name, i, data_segments[i])
-            self.assertEqual(resp['status'], '201')
 
         return object_name, data_segments
 
@@ -97,7 +96,6 @@
         data = data_utils.arbitrary_string()
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # check uploaded content
@@ -117,7 +115,6 @@
             object_name,
             data,
             metadata=metadata)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         resp, body = self.object_client.get_object(
@@ -144,7 +141,6 @@
             object_name,
             data,
             metadata=metadata)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # download compressed object
@@ -168,7 +164,6 @@
             object_name,
             data,
             metadata=metadata)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # check uploaded content
@@ -212,7 +207,6 @@
             name=object_name,
             contents=StringIO.StringIO(data),
             chunk_size=512)
-        self.assertEqual(status, 201)
         self.assertHeaders(resp_headers, 'Object', 'PUT')
 
         # check uploaded content
@@ -239,7 +233,6 @@
             object_name,
             '',
             metadata=metadata_2)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         resp, body = self.object_client.get_object(self.container_name,
@@ -258,7 +251,6 @@
             object_name,
             data,
             metadata=metadata)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         resp, body = self.object_client.get_object(self.container_name,
@@ -278,7 +270,6 @@
             object_name,
             data,
             metadata=metadata)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         resp, body = self.object_client.get_object(self.container_name,
@@ -303,7 +294,6 @@
             object_name,
             data,
             metadata=metadata_remove)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         resp, body = self.object_client.get_object(self.container_name,
@@ -327,7 +317,6 @@
             object_name,
             data,
             metadata=metadata_remove)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         resp, body = self.object_client.get_object(self.container_name,
@@ -345,7 +334,6 @@
         # delete object
         resp, _ = self.object_client.delete_object(self.container_name,
                                                    object_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'DELETE')
 
     @test.attr(type='smoke')
@@ -359,7 +347,6 @@
             object_name,
             metadata,
             metadata_prefix='')
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'POST')
 
         resp, _ = self.object_client.list_object_metadata(
@@ -384,7 +371,6 @@
             object_name,
             update_metadata,
             metadata_prefix='')
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'POST')
 
         resp, _ = self.object_client.list_object_metadata(
@@ -410,7 +396,6 @@
             object_name,
             update_metadata,
             metadata_prefix='')
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'POST')
 
         resp, _ = self.object_client.list_object_metadata(
@@ -439,7 +424,6 @@
             object_name,
             update_metadata,
             metadata_prefix='')
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'POST')
 
         resp, _ = self.object_client.list_object_metadata(
@@ -458,7 +442,6 @@
             object_name,
             update_metadata,
             metadata_prefix='')
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'POST')
 
         resp, _ = self.object_client.list_object_metadata(
@@ -484,7 +467,6 @@
             object_name,
             update_metadata,
             metadata_prefix='')
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'POST')
 
         resp, _ = self.object_client.list_object_metadata(
@@ -506,7 +488,6 @@
         resp, _ = self.object_client.list_object_metadata(
             self.container_name,
             object_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'HEAD')
         self.assertIn('x-object-meta-test-meta', resp)
         self.assertEqual(resp['x-object-meta-test-meta'], 'Meta')
@@ -519,7 +500,6 @@
         resp, _ = self.object_client.list_object_metadata(
             self.container_name,
             object_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'HEAD')
         self.assertNotIn('x-object-meta-', str(resp))
 
@@ -542,7 +522,6 @@
         resp, _ = self.object_client.list_object_metadata(
             self.container_name,
             object_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
 
         # Check only the existence of common headers with custom matcher
         self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
@@ -573,7 +552,6 @@
         # get object
         resp, body = self.object_client.get_object(self.container_name,
                                                    object_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
 
         self.assertEqual(body, data)
@@ -592,7 +570,6 @@
             self.container_name,
             object_name,
             metadata=None)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertIn('x-object-meta-test-meta', resp)
         self.assertEqual(resp['x-object-meta-test-meta'], 'Meta')
@@ -613,7 +590,6 @@
             self.container_name,
             object_name,
             metadata=metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data[rand_num - 3: rand_num])
 
@@ -637,7 +613,6 @@
             self.container_name,
             object_name,
             metadata=None)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
 
         # Check only the existence of common headers with custom matcher
         self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
@@ -678,7 +653,6 @@
             self.container_name,
             object_name,
             metadata=list_metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
@@ -699,7 +673,6 @@
             self.container_name,
             object_name,
             metadata=list_metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
@@ -721,7 +694,6 @@
             self.container_name,
             object_name,
             metadata=list_metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
@@ -737,7 +709,6 @@
             self.container_name,
             object_name,
             metadata=list_metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
@@ -751,7 +722,6 @@
             self.container_name,
             object_name,
             metadata=list_metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
@@ -774,7 +744,6 @@
         # copy source object to destination
         resp, _ = self.object_client.copy_object_in_same_container(
             self.container_name, src_object_name, dst_object_name)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # check data
@@ -796,7 +765,6 @@
         self.assertNotEqual(resp_tmp['content-type'], metadata['content-type'])
         resp, _ = self.object_client.copy_object_in_same_container(
             self.container_name, object_name, object_name, metadata)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # check the content type
@@ -822,7 +790,6 @@
         resp, _ = self.object_client.copy_object_2d_way(self.container_name,
                                                         src_object_name,
                                                         dst_object_name)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'COPY')
         self.assertEqual(
             resp['x-copied-from'],
@@ -855,14 +822,12 @@
         resp, _ = self.object_client.update_object_metadata(src_container_name,
                                                             object_name,
                                                             orig_metadata)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'POST')
 
         # copy object from source container to destination container
         resp, _ = self.object_client.copy_object_across_containers(
             src_container_name, object_name, dst_container_name,
             object_name)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # check if object is present in destination container
@@ -884,7 +849,6 @@
         dst_object_name, resp = self._copy_object_2d(src_object_name,
                                                      metadata)
 
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'COPY')
 
         self.assertNotIn('x-object-meta-src', resp)
@@ -904,7 +868,6 @@
         metadata = {'x-object-meta-test': ''}
         dst_obj_name, resp = self._copy_object_2d(src_obj_name, metadata)
 
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'COPY')
 
         expected = {'x-object-meta-test': '',
@@ -927,7 +890,6 @@
         metadata = {'x-object-meta-test': 'value'}
         dst_obj_name, resp = self._copy_object_2d(src_obj_name, metadata)
 
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'COPY')
 
         expected = {'x-object-meta-test': 'value',
@@ -951,7 +913,6 @@
         for i in six.moves.xrange(segments):
             resp, _ = self.object_client.create_object_segments(
                 self.container_name, object_name, i, data_segments[i])
-            self.assertEqual(resp['status'], '201')
         # creating a manifest file
         metadata = {'X-Object-Manifest': '%s/%s/'
                     % (self.container_name, object_name)}
@@ -1012,7 +973,6 @@
         md5 = hashlib.md5(local_data).hexdigest()
         headers = {'If-None-Match': md5}
         resp, body = self.object_client.get(url, headers=headers)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
 
 
@@ -1035,7 +995,6 @@
         cont_headers = {'X-Container-Read': '.r:*,.rlistings'}
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers, metadata_prefix='')
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'POST')
 
         # create object
@@ -1044,13 +1003,11 @@
                                            base_text=object_name)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # list container metadata
         resp_meta, _ = self.container_client.list_container_metadata(
             self.container_name)
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'HEAD')
 
         self.assertIn('x-container-read', resp_meta)
@@ -1075,7 +1032,6 @@
         resp_meta, body = self.container_client.update_container_metadata(
             self.container_name, metadata=cont_headers,
             metadata_prefix='')
-        self.assertIn(int(resp_meta['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp_meta, 'Container', 'POST')
 
         # create object
@@ -1084,13 +1040,11 @@
                                            base_text=object_name)
         resp, _ = self.object_client.create_object(self.container_name,
                                                    object_name, data)
-        self.assertEqual(resp['status'], '201')
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # list container metadata
         resp, _ = self.container_client.list_container_metadata(
             self.container_name)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Container', 'HEAD')
 
         self.assertIn('x-container-read', resp)
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 159ad5c..6622349 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -120,7 +120,6 @@
                                    manifest,
                                    params)
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self._assertHeadersSLO(resp, 'PUT')
 
     @test.attr(type='gate')
@@ -132,7 +131,6 @@
             self.container_name,
             object_name)
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self._assertHeadersSLO(resp, 'HEAD')
 
     @test.attr(type='gate')
@@ -144,7 +142,6 @@
             self.container_name,
             object_name)
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self._assertHeadersSLO(resp, 'GET')
 
         sum_data = self.content + self.content
@@ -161,8 +158,6 @@
             object_name,
             params=params_del)
 
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
-
         # When deleting SLO using multipart manifest, the response contains
         # not 'content-length' but 'transfer-encoding' header. This is the
         # special case, therefore the existence of response headers is checked
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index e70bd9a..dd4fd17 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -105,13 +105,11 @@
 
         # trying to get object using temp url within expiry time
         resp, body = self.object_client.get(url)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, self.content)
 
         # Testing a HEAD on this Temp URL
         resp, body = self.object_client.head(url)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'HEAD')
 
     @test.attr(type='gate')
@@ -136,7 +134,6 @@
                                  self.object_name, "GET",
                                  expires, key2)
         resp, body = self.object_client.get(url)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertEqual(body, self.content)
 
     @test.attr(type='gate')
@@ -153,12 +150,10 @@
 
         # trying to put random data in the object using temp url
         resp, body = self.object_client.put(url, new_data, None)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'PUT')
 
         # Testing a HEAD on this Temp URL
         resp, body = self.object_client.head(url)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'HEAD')
 
         # Validate that the content of the object has been modified
@@ -181,7 +176,6 @@
 
         # Testing a HEAD on this Temp URL
         resp, body = self.object_client.head(url)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'HEAD')
 
     @test.attr(type='gate')
@@ -196,7 +190,6 @@
 
         # trying to get object using temp url within expiry time
         resp, body = self.object_client.get(url)
-        self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, self.content)
         self.assertEqual(resp['content-disposition'], 'inline')
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index 5fe4fc8..da40e5a 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -36,7 +36,6 @@
 
     def assertContainer(self, container, count, byte, versioned):
         resp, _ = self.container_client.list_container_metadata(container)
-        self.assertEqual(resp['status'], ('204'))
         self.assertHeaders(resp, 'Container', 'HEAD')
         header_value = resp.get('x-container-object-count', 'Missing Header')
         self.assertEqual(header_value, count)
@@ -55,7 +54,6 @@
         resp, body = self.container_client.create_container(
             vers_container_name)
         self.containers.append(vers_container_name)
-        self.assertIn(resp['status'], ('202', '201'))
         self.assertHeaders(resp, 'Container', 'PUT')
         self.assertContainer(vers_container_name, '0', '0', 'Missing Header')
 
@@ -66,7 +64,6 @@
             metadata=headers,
             metadata_prefix='')
         self.containers.append(base_container_name)
-        self.assertIn(resp['status'], ('202', '201'))
         self.assertHeaders(resp, 'Container', 'PUT')
         self.assertContainer(base_container_name, '0', '0',
                              vers_container_name)
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 042cde9..9e24993 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -66,13 +66,14 @@
 
         params = {self.name_field: vol_name, 'volume_type': type_name}
 
-        _, self.volume = self.volume_client.create_volume(size=1, **params)
+        _, self.volume = self.admin_volume_client.create_volume(size=1,
+                                                                **params)
         if with_prefix:
             self.volume_id_list_with_prefix.append(self.volume['id'])
         else:
             self.volume_id_list_without_prefix.append(
                 self.volume['id'])
-        self.volume_client.wait_for_volume_status(
+        self.admin_volume_client.wait_for_volume_status(
             self.volume['id'], 'available')
 
     @classmethod
@@ -80,13 +81,13 @@
         # volumes deletion
         vid_prefix = getattr(cls, 'volume_id_list_with_prefix', [])
         for volume_id in vid_prefix:
-            cls.volume_client.delete_volume(volume_id)
-            cls.volume_client.wait_for_resource_deletion(volume_id)
+            cls.admin_volume_client.delete_volume(volume_id)
+            cls.admin_volume_client.wait_for_resource_deletion(volume_id)
 
         vid_no_pre = getattr(cls, 'volume_id_list_without_prefix', [])
         for volume_id in vid_no_pre:
-            cls.volume_client.delete_volume(volume_id)
-            cls.volume_client.wait_for_resource_deletion(volume_id)
+            cls.admin_volume_client.delete_volume(volume_id)
+            cls.admin_volume_client.wait_for_resource_deletion(volume_id)
 
         # volume types deletion
         volume_type_id_list = getattr(cls, 'volume_type_id_list', [])
@@ -130,7 +131,7 @@
         # the multi backend feature has been enabled
         # if multi-backend is enabled: os-vol-attr:host should be like:
         # host@backend_name
-        _, volume = self.volume_client.get_volume(volume_id)
+        _, volume = self.admin_volume_client.get_volume(volume_id)
 
         volume1_host = volume['os-vol-host-attr:host']
         msg = ("multi-backend reporting incorrect values for volume %s" %
@@ -141,10 +142,10 @@
         # this test checks that the two volumes created at setUp don't
         # belong to the same backend (if they are, than the
         # volume backend distinction is not working properly)
-        _, volume = self.volume_client.get_volume(volume1_id)
+        _, volume = self.admin_volume_client.get_volume(volume1_id)
         volume1_host = volume['os-vol-host-attr:host']
 
-        _, volume = self.volume_client.get_volume(volume2_id)
+        _, volume = self.admin_volume_client.get_volume(volume2_id)
         volume2_host = volume['os-vol-host-attr:host']
 
         msg = ("volumes %s and %s were created in the same backend" %
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index 720734b..02a2526 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -18,29 +18,28 @@
 from tempest import test
 
 
-class SnapshotsActionsTest(base.BaseVolumeV1AdminTest):
+class SnapshotsActionsV2Test(base.BaseVolumeAdminTest):
     _interface = "json"
 
     @classmethod
     def resource_setup(cls):
-        super(SnapshotsActionsTest, cls).resource_setup()
+        super(SnapshotsActionsV2Test, cls).resource_setup()
         cls.client = cls.snapshots_client
 
-        # Create admin volume client
-        cls.admin_snapshots_client = cls.os_adm.snapshots_client
-
         # Create a test shared volume for tests
         vol_name = data_utils.rand_name(cls.__name__ + '-Volume-')
+        cls.name_field = cls.special_fields['name_field']
+        params = {cls.name_field: vol_name}
         _, cls.volume = \
-            cls.volumes_client.create_volume(size=1, display_name=vol_name)
+            cls.volumes_client.create_volume(size=1, **params)
         cls.volumes_client.wait_for_volume_status(cls.volume['id'],
                                                   'available')
 
         # Create a test shared snapshot for tests
         snap_name = data_utils.rand_name(cls.__name__ + '-Snapshot-')
+        params = {cls.name_field: snap_name}
         _, cls.snapshot = \
-            cls.client.create_snapshot(cls.volume['id'],
-                                       display_name=snap_name)
+            cls.client.create_snapshot(cls.volume['id'], **params)
         cls.client.wait_for_snapshot_status(cls.snapshot['id'],
                                             'available')
 
@@ -54,7 +53,7 @@
         cls.volumes_client.delete_volume(cls.volume['id'])
         cls.volumes_client.wait_for_resource_deletion(cls.volume['id'])
 
-        super(SnapshotsActionsTest, cls).resource_cleanup()
+        super(SnapshotsActionsV2Test, cls).resource_cleanup()
 
     def tearDown(self):
         # Set snapshot's status to available after test
@@ -62,7 +61,7 @@
         snapshot_id = self.snapshot['id']
         self.admin_snapshots_client.reset_snapshot_status(snapshot_id,
                                                           status)
-        super(SnapshotsActionsTest, self).tearDown()
+        super(SnapshotsActionsV2Test, self).tearDown()
 
     def _create_reset_and_force_delete_temp_snapshot(self, status=None):
         # Create snapshot, reset snapshot status,
@@ -127,7 +126,11 @@
         self._create_reset_and_force_delete_temp_snapshot('error_deleting')
 
 
-class SnapshotsActionsTestXML(SnapshotsActionsTest):
+class SnapshotsActionsV1Test(SnapshotsActionsV2Test):
+    _api_version = 1
+
+
+class SnapshotsActionsV1TestXML(SnapshotsActionsV1Test):
     _interface = "xml"
 
     def _get_progress_alias(self):
diff --git a/tempest/api/volume/admin/test_volume_hosts.py b/tempest/api/volume/admin/test_volume_hosts.py
index 017363d..c92a60c 100644
--- a/tempest/api/volume/admin/test_volume_hosts.py
+++ b/tempest/api/volume/admin/test_volume_hosts.py
@@ -17,7 +17,7 @@
 from tempest import test
 
 
-class VolumeHostsAdminTestsJSON(base.BaseVolumeV1AdminTest):
+class VolumeHostsAdminV2TestsJSON(base.BaseVolumeAdminTest):
     _interface = "json"
 
     @test.attr(type='gate')
@@ -27,5 +27,9 @@
                         "response of list hosts is: % s" % hosts)
 
 
-class VolumeHostsAdminTestsXML(VolumeHostsAdminTestsJSON):
+class VolumeHostsAdminV1TestsJSON(VolumeHostsAdminV2TestsJSON):
+    _api_version = 1
+
+
+class VolumeHostsAdminV1TestsXML(VolumeHostsAdminV1TestsJSON):
     _interface = 'xml'
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index ece4299..6e45b0f 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -29,7 +29,6 @@
     @classmethod
     def resource_setup(cls):
         super(VolumeQuotasAdminTestJSON, cls).resource_setup()
-        cls.admin_volume_client = cls.os_adm.volumes_client
         cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
 
     @test.attr(type='gate')
@@ -72,7 +71,7 @@
     @test.attr(type='gate')
     def test_show_quota_usage(self):
         _, quota_usage = self.quotas_client.get_quota_usage(
-            self.os_adm.credentials.tenant_name)
+            self.os_adm.credentials.tenant_id)
         for key in QUOTA_KEYS:
             self.assertIn(key, quota_usage)
             for usage_key in QUOTA_USAGE_KEYS:
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index a0792f1..a481224 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -21,7 +21,7 @@
 CONF = config.CONF
 
 
-class VolumeTypesTest(base.BaseVolumeV1AdminTest):
+class VolumeTypesV2Test(base.BaseVolumeAdminTest):
     _interface = "json"
 
     def _delete_volume(self, volume_id):
@@ -43,6 +43,7 @@
         volume = {}
         vol_name = data_utils.rand_name("volume-")
         vol_type_name = data_utils.rand_name("volume-type-")
+        self.name_field = self.special_fields['name_field']
         proto = CONF.volume.storage_protocol
         vendor = CONF.volume.vendor_name
         extra_specs = {"storage_protocol": proto,
@@ -54,21 +55,20 @@
         self.assertIn('id', body)
         self.addCleanup(self._delete_volume_type, body['id'])
         self.assertIn('name', body)
+        params = {self.name_field: vol_name, 'volume_type': vol_type_name}
         _, volume = self.volumes_client.create_volume(
-            size=1, display_name=vol_name,
-            volume_type=vol_type_name)
+            size=1, **params)
         self.assertIn('id', volume)
         self.addCleanup(self._delete_volume, volume['id'])
-        self.assertIn('display_name', volume)
-        self.assertEqual(volume['display_name'], vol_name,
+        self.assertIn(self.name_field, volume)
+        self.assertEqual(volume[self.name_field], vol_name,
                          "The created volume name is not equal "
                          "to the requested name")
         self.assertTrue(volume['id'] is not None,
                         "Field volume id is empty or not found.")
-        self.volumes_client.wait_for_volume_status(volume['id'],
-                                                   'available')
+        self.volumes_client.wait_for_volume_status(volume['id'], 'available')
         _, fetched_volume = self.volumes_client.get_volume(volume['id'])
-        self.assertEqual(vol_name, fetched_volume['display_name'],
+        self.assertEqual(vol_name, fetched_volume[self.name_field],
                          'The fetched Volume is different '
                          'from the created Volume')
         self.assertEqual(volume['id'], fetched_volume['id'],
@@ -154,3 +154,7 @@
             self.volume_types_client.get_encryption_type(
                 encryption_type['volume_type_id']))
         self.assertEmpty(deleted_encryption_type)
+
+
+class VolumeTypesV1Test(VolumeTypesV2Test):
+    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs.py b/tempest/api/volume/admin/test_volume_types_extra_specs.py
index a154821..3b9f6bb 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs.py
@@ -18,12 +18,12 @@
 from tempest import test
 
 
-class VolumeTypesExtraSpecsTest(base.BaseVolumeV1AdminTest):
+class VolumeTypesExtraSpecsV2Test(base.BaseVolumeAdminTest):
     _interface = "json"
 
     @classmethod
     def resource_setup(cls):
-        super(VolumeTypesExtraSpecsTest, cls).resource_setup()
+        super(VolumeTypesExtraSpecsV2Test, cls).resource_setup()
         vol_type_name = data_utils.rand_name('Volume-type-')
         _, cls.volume_type = cls.volume_types_client.create_volume_type(
             vol_type_name)
@@ -31,7 +31,7 @@
     @classmethod
     def resource_cleanup(cls):
         cls.volume_types_client.delete_volume_type(cls.volume_type['id'])
-        super(VolumeTypesExtraSpecsTest, cls).resource_cleanup()
+        super(VolumeTypesExtraSpecsV2Test, cls).resource_cleanup()
 
     @test.attr(type='smoke')
     def test_volume_type_extra_specs_list(self):
@@ -83,3 +83,7 @@
         self.volume_types_client.delete_volume_type_extra_specs(
             self.volume_type['id'],
             extra_specs.keys()[0])
+
+
+class VolumeTypesExtraSpecsV1Test(VolumeTypesExtraSpecsV2Test):
+    _api_version = 1
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index 8734b16..e474aa0 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -21,12 +21,12 @@
 from tempest import test
 
 
-class ExtraSpecsNegativeTest(base.BaseVolumeV1AdminTest):
+class ExtraSpecsNegativeV2Test(base.BaseVolumeAdminTest):
     _interface = 'json'
 
     @classmethod
     def resource_setup(cls):
-        super(ExtraSpecsNegativeTest, cls).resource_setup()
+        super(ExtraSpecsNegativeV2Test, cls).resource_setup()
         vol_type_name = data_utils.rand_name('Volume-type-')
         cls.extra_specs = {"spec1": "val1"}
         _, cls.volume_type = cls.volume_types_client.create_volume_type(
@@ -36,7 +36,7 @@
     @classmethod
     def resource_cleanup(cls):
         cls.volume_types_client.delete_volume_type(cls.volume_type['id'])
-        super(ExtraSpecsNegativeTest, cls).resource_cleanup()
+        super(ExtraSpecsNegativeV2Test, cls).resource_cleanup()
 
     @test.attr(type='gate')
     def test_update_no_body(self):
@@ -140,5 +140,9 @@
             self.volume_type['id'], str(uuid.uuid4()))
 
 
-class ExtraSpecsNegativeTestXML(ExtraSpecsNegativeTest):
+class ExtraSpecsNegativeV1Test(ExtraSpecsNegativeV2Test):
+    _api_version = 1
+
+
+class ExtraSpecsNegativeV1TestXML(ExtraSpecsNegativeV1Test):
     _interface = 'xml'
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index a4d6431..9c9913f 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -20,16 +20,18 @@
 from tempest import test
 
 
-class VolumeTypesNegativeTest(base.BaseVolumeV1AdminTest):
+class VolumeTypesNegativeV2Test(base.BaseVolumeAdminTest):
     _interface = 'json'
 
     @test.attr(type='gate')
     def test_create_with_nonexistent_volume_type(self):
         # Should not be able to create volume with nonexistent volume_type.
+        self.name_field = self.special_fields['name_field']
+        params = {self.name_field: str(uuid.uuid4()),
+                  'volume_type': str(uuid.uuid4())}
         self.assertRaises(exceptions.NotFound,
                           self.volumes_client.create_volume, size=1,
-                          display_name=str(uuid.uuid4()),
-                          volume_type=str(uuid.uuid4()))
+                          **params)
 
     @test.attr(type='gate')
     def test_create_with_empty_name(self):
@@ -52,5 +54,9 @@
                           str(uuid.uuid4()))
 
 
-class VolumesTypesNegativeTestXML(VolumeTypesNegativeTest):
+class VolumeTypesNegativeV1Test(VolumeTypesNegativeV2Test):
+    _api_version = 1
+
+
+class VolumeTypesNegativeV1TestXML(VolumeTypesNegativeV1Test):
     _interface = 'xml'
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index f85718b..1c3e04a 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -18,22 +18,21 @@
 from tempest import test
 
 
-class VolumesActionsTest(base.BaseVolumeV1AdminTest):
+class VolumesActionsV2Test(base.BaseVolumeAdminTest):
     _interface = "json"
 
     @classmethod
     def resource_setup(cls):
-        super(VolumesActionsTest, cls).resource_setup()
+        super(VolumesActionsV2Test, cls).resource_setup()
         cls.client = cls.volumes_client
 
-        # Create admin volume client
-        cls.admin_volume_client = cls.os_adm.volumes_client
-
         # Create a test shared volume for tests
         vol_name = utils.rand_name(cls.__name__ + '-Volume-')
+        cls.name_field = cls.special_fields['name_field']
+        params = {cls.name_field: vol_name}
 
         _, cls.volume = cls.client.create_volume(size=1,
-                                                 display_name=vol_name)
+                                                 **params)
         cls.client.wait_for_volume_status(cls.volume['id'], 'available')
 
     @classmethod
@@ -42,7 +41,7 @@
         cls.client.delete_volume(cls.volume['id'])
         cls.client.wait_for_resource_deletion(cls.volume['id'])
 
-        super(VolumesActionsTest, cls).resource_cleanup()
+        super(VolumesActionsV2Test, cls).resource_cleanup()
 
     def _reset_volume_status(self, volume_id, status):
         # Reset the volume status
@@ -53,13 +52,14 @@
     def tearDown(self):
         # Set volume's status to available after test
         self._reset_volume_status(self.volume['id'], 'available')
-        super(VolumesActionsTest, self).tearDown()
+        super(VolumesActionsV2Test, self).tearDown()
 
     def _create_temp_volume(self):
         # Create a temp volume for force delete tests
         vol_name = utils.rand_name('Volume')
+        params = {self.name_field: vol_name}
         _, temp_volume = self.client.create_volume(size=1,
-                                                   display_name=vol_name)
+                                                   **params)
         self.client.wait_for_volume_status(temp_volume['id'], 'available')
 
         return temp_volume
@@ -95,5 +95,9 @@
         self._create_reset_and_force_delete_temp_volume('error')
 
 
-class VolumesActionsTestXML(VolumesActionsTest):
+class VolumesActionsV1Test(VolumesActionsV2Test):
+    _api_version = 1
+
+
+class VolumesActionsV1TestXML(VolumesActionsV1Test):
     _interface = "xml"
diff --git a/tempest/api/volume/admin/test_volumes_backup.py b/tempest/api/volume/admin/test_volumes_backup.py
index 8b90b07..bf014a8 100644
--- a/tempest/api/volume/admin/test_volumes_backup.py
+++ b/tempest/api/volume/admin/test_volumes_backup.py
@@ -33,7 +33,6 @@
         if not CONF.volume_feature_enabled.backup:
             raise cls.skipException("Cinder backup feature disabled")
 
-        cls.volumes_adm_client = cls.os_adm.volumes_client
         cls.backups_adm_client = cls.os_adm.backups_client
         cls.volume = cls.create_volume()
 
@@ -47,8 +46,8 @@
         self.addCleanup(self.backups_adm_client.delete_backup,
                         backup['id'])
         self.assertEqual(backup_name, backup['name'])
-        self.volumes_adm_client.wait_for_volume_status(self.volume['id'],
-                                                       'available')
+        self.admin_volume_client.wait_for_volume_status(
+            self.volume['id'], 'available')
         self.backups_adm_client.wait_for_backup_status(backup['id'],
                                                        'available')
 
@@ -65,10 +64,10 @@
         _, restore = self.backups_adm_client.restore_backup(backup['id'])
 
         # Delete backup
-        self.addCleanup(self.volumes_adm_client.delete_volume,
+        self.addCleanup(self.admin_volume_client.delete_volume,
                         restore['volume_id'])
         self.assertEqual(backup['id'], restore['backup_id'])
         self.backups_adm_client.wait_for_backup_status(backup['id'],
                                                        'available')
-        self.volumes_adm_client.wait_for_volume_status(restore['volume_id'],
-                                                       'available')
+        self.admin_volume_client.wait_for_volume_status(
+            restore['volume_id'], 'available')
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index d78ddb6..f9f03ac 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -165,7 +165,6 @@
 
         cls.qos_specs = []
 
-        cls.hosts_client = cls.os_adm.volume_hosts_client
         cls.quotas_client = cls.os_adm.volume_quotas_client
 
         if cls._api_version == 1:
@@ -174,14 +173,18 @@
                 raise cls.skipException(msg)
             cls.volume_qos_client = cls.os_adm.volume_qos_client
             cls.volume_types_client = cls.os_adm.volume_types_client
-            cls.volume_client = cls.os_adm.volumes_client
+            cls.admin_volume_client = cls.os_adm.volumes_client
+            cls.hosts_client = cls.os_adm.volume_hosts_client
+            cls.admin_snapshots_client = cls.os_adm.snapshots_client
         elif cls._api_version == 2:
             if not CONF.volume_feature_enabled.api_v2:
                 msg = "Volume API v2 is disabled"
                 raise cls.skipException(msg)
             cls.volume_qos_client = cls.os_adm.volume_qos_v2_client
             cls.volume_types_client = cls.os_adm.volume_types_v2_client
-            cls.volume_client = cls.os_adm.volumes_v2_client
+            cls.admin_volume_client = cls.os_adm.volumes_v2_client
+            cls.hosts_client = cls.os_adm.volume_hosts_v2_client
+            cls.admin_snapshots_client = cls.os_adm.snapshots_v2_client
 
     @classmethod
     def resource_cleanup(cls):
diff --git a/tempest/api_schema/response/compute/availability_zone.py b/tempest/api_schema/response/compute/availability_zone.py
index c1abc64..ab3e2ea 100644
--- a/tempest/api_schema/response/compute/availability_zone.py
+++ b/tempest/api_schema/response/compute/availability_zone.py
@@ -27,7 +27,7 @@
                     'properties': {
                         'available': {'type': 'boolean'},
                         'active': {'type': 'boolean'},
-                        'updated_at': {'type': 'string'}
+                        'updated_at': {'type': ['string', 'null']}
                     },
                     'required': ['available', 'active', 'updated_at']
                 }
diff --git a/tempest/api_schema/response/compute/services.py b/tempest/api_schema/response/compute/services.py
index eaba129..fc42b89 100644
--- a/tempest/api_schema/response/compute/services.py
+++ b/tempest/api_schema/response/compute/services.py
@@ -28,7 +28,7 @@
                         'state': {'type': 'string'},
                         'binary': {'type': 'string'},
                         'status': {'type': 'string'},
-                        'updated_at': {'type': 'string'},
+                        'updated_at': {'type': ['string', 'null']},
                         'disabled_reason': {'type': ['string', 'null']}
                     },
                     'required': ['id', 'zone', 'host', 'state', 'binary',
diff --git a/tempest/api_schema/response/compute/v2/servers.py b/tempest/api_schema/response/compute/v2/servers.py
index 5fc2008..09abaed 100644
--- a/tempest/api_schema/response/compute/v2/servers.py
+++ b/tempest/api_schema/response/compute/v2/servers.py
@@ -117,21 +117,23 @@
     }
 }
 
+common_attach_volume_info = {
+    'type': 'object',
+    'properties': {
+        'id': {'type': 'string'},
+        'device': {'type': 'string'},
+        'volumeId': {'type': 'string'},
+        'serverId': {'type': ['integer', 'string']}
+    },
+    'required': ['id', 'device', 'volumeId', 'serverId']
+}
+
 attach_volume = {
     'status_code': [200],
     'response_body': {
         'type': 'object',
         'properties': {
-            'volumeAttachment': {
-                'type': 'object',
-                'properties': {
-                    'id': {'type': 'string'},
-                    'device': {'type': 'string'},
-                    'volumeId': {'type': 'string'},
-                    'serverId': {'type': ['integer', 'string']}
-                },
-                'required': ['id', 'device', 'volumeId', 'serverId']
-            }
+            'volumeAttachment': common_attach_volume_info
         },
         'required': ['volumeAttachment']
     }
@@ -141,6 +143,27 @@
     'status_code': [202]
 }
 
+get_volume_attachment = copy.deepcopy(attach_volume)
+get_volume_attachment['response_body']['properties'][
+    'volumeAttachment']['properties'].update({'serverId': {'type': 'string'}})
+
+list_volume_attachments = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'volumeAttachments': {
+                'type': 'array',
+                'items': common_attach_volume_info
+            }
+        },
+        'required': ['volumeAttachments']
+    }
+}
+list_volume_attachments['response_body']['properties'][
+    'volumeAttachments']['items']['properties'].update(
+    {'serverId': {'type': 'string'}})
+
 set_get_server_metadata_item = {
     'status_code': [200],
     'response_body': {
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index ca6d7fe..4782129 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -14,46 +14,21 @@
 #    under the License.
 
 import functools
-import os
-import shlex
-import subprocess
 
+from tempest_lib.cli import base
+from tempest_lib.cli import output_parser
 import testtools
 
-import tempest.cli.output_parser
+from tempest.common import credentials
 from tempest import config
 from tempest import exceptions
-from tempest.openstack.common import log as logging
 from tempest.openstack.common import versionutils
-import tempest.test
+from tempest import test
 
 
-LOG = logging.getLogger(__name__)
-
 CONF = config.CONF
 
 
-def execute(cmd, action, flags='', params='', fail_ok=False,
-            merge_stderr=False):
-    """Executes specified command for the given action."""
-    cmd = ' '.join([os.path.join(CONF.cli.cli_dir, cmd),
-                    flags, action, params])
-    LOG.info("running: '%s'" % cmd)
-    cmd = shlex.split(cmd.encode('utf-8'))
-    result = ''
-    result_err = ''
-    stdout = subprocess.PIPE
-    stderr = subprocess.STDOUT if merge_stderr else subprocess.PIPE
-    proc = subprocess.Popen(cmd, stdout=stdout, stderr=stderr)
-    result, result_err = proc.communicate()
-    if not fail_ok and proc.returncode != 0:
-        raise exceptions.CommandFailed(proc.returncode,
-                                       cmd,
-                                       result,
-                                       result_err)
-    return result
-
-
 def check_client_version(client, version):
     """Checks if the client's version is compatible with the given version
 
@@ -62,8 +37,8 @@
     @return: True if the client version is compatible with the given version
              parameter, False otherwise.
     """
-    current_version = execute(client, '', params='--version',
-                              merge_stderr=True)
+    current_version = base.execute(client, '', params='--version',
+                                   merge_stderr=True, cli_dir=CONF.cli.cli_dir)
 
     if not current_version.strip():
         raise exceptions.TempestException('"%s --version" output was empty' %
@@ -92,100 +67,52 @@
     return decorator
 
 
-class ClientTestBase(tempest.test.BaseTestCase):
+class ClientTestBase(test.BaseTestCase):
     @classmethod
     def resource_setup(cls):
         if not CONF.cli.enabled:
             msg = "cli testing disabled"
             raise cls.skipException(msg)
         super(ClientTestBase, cls).resource_setup()
+        cls.cred_prov = credentials.get_isolated_credentials(cls.__name__)
+        cls.creds = cls.cred_prov.get_admin_creds()
 
-    def __init__(self, *args, **kwargs):
-        self.parser = tempest.cli.output_parser
-        super(ClientTestBase, self).__init__(*args, **kwargs)
+    def _get_clients(self):
+        clients = base.CLIClient(self.creds.username,
+                                 self.creds.password,
+                                 self.creds.tenant_name,
+                                 CONF.identity.uri, CONF.cli.cli_dir)
+        return clients
 
-    def nova(self, action, flags='', params='', admin=True, fail_ok=False):
-        """Executes nova command for the given action."""
-        flags += ' --endpoint-type %s' % CONF.compute.endpoint_type
-        return self.cmd_with_auth(
-            'nova', action, flags, params, admin, fail_ok)
-
-    def nova_manage(self, action, flags='', params='', fail_ok=False,
-                    merge_stderr=False):
-        """Executes nova-manage command for the given action."""
-        return execute(
-            'nova-manage', action, flags, params, fail_ok, merge_stderr)
-
-    def keystone(self, action, flags='', params='', admin=True, fail_ok=False):
-        """Executes keystone command for the given action."""
-        return self.cmd_with_auth(
-            'keystone', action, flags, params, admin, fail_ok)
-
-    def glance(self, action, flags='', params='', admin=True, fail_ok=False):
-        """Executes glance command for the given action."""
-        flags += ' --os-endpoint-type %s' % CONF.image.endpoint_type
-        return self.cmd_with_auth(
-            'glance', action, flags, params, admin, fail_ok)
-
-    def ceilometer(self, action, flags='', params='', admin=True,
-                   fail_ok=False):
-        """Executes ceilometer command for the given action."""
-        flags += ' --os-endpoint-type %s' % CONF.telemetry.endpoint_type
-        return self.cmd_with_auth(
-            'ceilometer', action, flags, params, admin, fail_ok)
-
-    def heat(self, action, flags='', params='', admin=True,
-             fail_ok=False):
-        """Executes heat command for the given action."""
-        flags += ' --os-endpoint-type %s' % CONF.orchestration.endpoint_type
-        return self.cmd_with_auth(
-            'heat', action, flags, params, admin, fail_ok)
-
-    def cinder(self, action, flags='', params='', admin=True, fail_ok=False):
-        """Executes cinder command for the given action."""
-        flags += ' --endpoint-type %s' % CONF.volume.endpoint_type
-        return self.cmd_with_auth(
-            'cinder', action, flags, params, admin, fail_ok)
-
-    def swift(self, action, flags='', params='', admin=True, fail_ok=False):
-        """Executes swift command for the given action."""
-        flags += ' --os-endpoint-type %s' % CONF.object_storage.endpoint_type
-        return self.cmd_with_auth(
-            'swift', action, flags, params, admin, fail_ok)
-
-    def neutron(self, action, flags='', params='', admin=True, fail_ok=False):
-        """Executes neutron command for the given action."""
-        flags += ' --endpoint-type %s' % CONF.network.endpoint_type
-        return self.cmd_with_auth(
-            'neutron', action, flags, params, admin, fail_ok)
-
-    def sahara(self, action, flags='', params='', admin=True,
-               fail_ok=False, merge_stderr=True):
-        """Executes sahara command for the given action."""
-        flags += ' --endpoint-type %s' % CONF.data_processing.endpoint_type
-        return self.cmd_with_auth(
-            'sahara', action, flags, params, admin, fail_ok, merge_stderr)
-
-    def cmd_with_auth(self, cmd, action, flags='', params='',
-                      admin=True, fail_ok=False, merge_stderr=False):
-        """Executes given command with auth attributes appended."""
-        # TODO(jogo) make admin=False work
-        creds = ('--os-username %s --os-tenant-name %s --os-password %s '
-                 '--os-auth-url %s' %
-                 (CONF.identity.admin_username,
-                  CONF.identity.admin_tenant_name,
-                  CONF.identity.admin_password,
-                  CONF.identity.uri))
-        flags = creds + ' ' + flags
-        return execute(cmd, action, flags, params, fail_ok, merge_stderr)
+    # TODO(mtreinish): The following code is basically copied from tempest-lib.
+    # The base cli test class in tempest-lib 0.0.1 doesn't work as a mixin like
+    # is needed here. The code below should be removed when tempest-lib
+    # provides a way to provide this functionality
+    def setUp(self):
+        super(ClientTestBase, self).setUp()
+        self.clients = self._get_clients()
+        self.parser = output_parser
 
     def assertTableStruct(self, items, field_names):
-        """Verify that all items has keys listed in field_names."""
+        """Verify that all items has keys listed in field_names.
+
+        :param items: items to assert are field names in the output table
+        :type items: list
+        :param field_names: field names from the output table of the cmd
+        :type field_names: list
+        """
         for item in items:
             for field in field_names:
                 self.assertIn(field, item)
 
     def assertFirstLineStartsWith(self, lines, beginning):
+        """Verify that the first line starts with a string
+
+        :param lines: strings for each line of output
+        :type lines: list
+        :param beginning: verify this is at the beginning of the first line
+        :type beginning: string
+        """
         self.assertTrue(lines[0].startswith(beginning),
                         msg=('Beginning of first line has invalid content: %s'
                              % lines[:3]))
diff --git a/tempest/cli/output_parser.py b/tempest/cli/output_parser.py
deleted file mode 100644
index 80234a3..0000000
--- a/tempest/cli/output_parser.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Copyright 2013 OpenStack Foundation
-# 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.
-
-"""Collection of utilities for parsing CLI clients output."""
-
-import re
-
-from tempest import exceptions
-from tempest.openstack.common import log as logging
-
-
-LOG = logging.getLogger(__name__)
-
-
-delimiter_line = re.compile('^\+\-[\+\-]+\-\+$')
-
-
-def details_multiple(output_lines, with_label=False):
-    """Return list of dicts with item details from cli output tables.
-
-    If with_label is True, key '__label' is added to each items dict.
-    For more about 'label' see OutputParser.tables().
-    """
-    items = []
-    tables_ = tables(output_lines)
-    for table_ in tables_:
-        if 'Property' not in table_['headers'] \
-           or 'Value' not in table_['headers']:
-            raise exceptions.InvalidStructure()
-        item = {}
-        for value in table_['values']:
-            item[value[0]] = value[1]
-        if with_label:
-            item['__label'] = table_['label']
-        items.append(item)
-    return items
-
-
-def details(output_lines, with_label=False):
-    """Return dict with details of first item (table) found in output."""
-    items = details_multiple(output_lines, with_label)
-    return items[0]
-
-
-def listing(output_lines):
-    """Return list of dicts with basic item info parsed from cli output.
-    """
-
-    items = []
-    table_ = table(output_lines)
-    for row in table_['values']:
-        item = {}
-        for col_idx, col_key in enumerate(table_['headers']):
-            item[col_key] = row[col_idx]
-        items.append(item)
-    return items
-
-
-def tables(output_lines):
-    """Find all ascii-tables in output and parse them.
-
-    Return list of tables parsed from cli output as dicts.
-    (see OutputParser.table())
-
-    And, if found, label key (separated line preceding the table)
-    is added to each tables dict.
-    """
-    tables_ = []
-
-    table_ = []
-    label = None
-
-    start = False
-    header = False
-
-    if not isinstance(output_lines, list):
-        output_lines = output_lines.split('\n')
-
-    for line in output_lines:
-        if delimiter_line.match(line):
-            if not start:
-                start = True
-            elif not header:
-                # we are after head area
-                header = True
-            else:
-                # table ends here
-                start = header = None
-                table_.append(line)
-
-                parsed = table(table_)
-                parsed['label'] = label
-                tables_.append(parsed)
-
-                table_ = []
-                label = None
-                continue
-        if start:
-            table_.append(line)
-        else:
-            if label is None:
-                label = line
-            else:
-                LOG.warn('Invalid line between tables: %s' % line)
-    if len(table_) > 0:
-        LOG.warn('Missing end of table')
-
-    return tables_
-
-
-def table(output_lines):
-    """Parse single table from cli output.
-
-    Return dict with list of column names in 'headers' key and
-    rows in 'values' key.
-    """
-    table_ = {'headers': [], 'values': []}
-    columns = None
-
-    if not isinstance(output_lines, list):
-        output_lines = output_lines.split('\n')
-
-    if not output_lines[-1]:
-        # skip last line if empty (just newline at the end)
-        output_lines = output_lines[:-1]
-
-    for line in output_lines:
-        if delimiter_line.match(line):
-            columns = _table_columns(line)
-            continue
-        if '|' not in line:
-            LOG.warn('skipping invalid table line: %s' % line)
-            continue
-        row = []
-        for col in columns:
-            row.append(line[col[0]:col[1]].strip())
-        if table_['headers']:
-            table_['values'].append(row)
-        else:
-            table_['headers'] = row
-
-    return table_
-
-
-def _table_columns(first_table_row):
-    """Find column ranges in output line.
-
-    Return list of tuples (start,end) for each column
-    detected by plus (+) characters in delimiter line.
-    """
-    positions = []
-    start = 1  # there is '+' at 0
-    while start < len(first_table_row):
-        end = first_table_row.find('+', start)
-        if end == -1:
-            break
-        positions.append((start, end))
-        start = end + 1
-    return positions
diff --git a/tempest/cli/simple_read_only/compute/test_nova.py b/tempest/cli/simple_read_only/compute/test_nova.py
index 6e5e077..4fe4982 100644
--- a/tempest/cli/simple_read_only/compute/test_nova.py
+++ b/tempest/cli/simple_read_only/compute/test_nova.py
@@ -13,11 +13,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import exceptions
 import testtools
 
 from tempest import cli
 from tempest import config
-from tempest import exceptions
 from tempest.openstack.common import log as logging
 import tempest.test
 
@@ -47,6 +47,11 @@
             raise cls.skipException(msg)
         super(SimpleReadOnlyNovaClientTest, cls).resource_setup()
 
+    def nova(self, *args, **kwargs):
+        return self.clients.nova(*args,
+                                 endpoint_type=CONF.compute.endpoint_type,
+                                 **kwargs)
+
     def test_admin_fake_action(self):
         self.assertRaises(exceptions.CommandFailed,
                           self.nova,
diff --git a/tempest/cli/simple_read_only/compute/test_nova_manage.py b/tempest/cli/simple_read_only/compute/test_nova_manage.py
index cff543f..34ec671 100644
--- a/tempest/cli/simple_read_only/compute/test_nova_manage.py
+++ b/tempest/cli/simple_read_only/compute/test_nova_manage.py
@@ -13,9 +13,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from tempest_lib import exceptions
+
 from tempest import cli
 from tempest import config
-from tempest import exceptions
 from tempest.openstack.common import log as logging
 
 
@@ -46,6 +47,9 @@
             raise cls.skipException(msg)
         super(SimpleReadOnlyNovaManageTest, cls).resource_setup()
 
+    def nova_manage(self, *args, **kwargs):
+        return self.clients.nova_manage(*args, **kwargs)
+
     def test_admin_fake_action(self):
         self.assertRaises(exceptions.CommandFailed,
                           self.nova_manage,
diff --git a/tempest/cli/simple_read_only/data_processing/test_sahara.py b/tempest/cli/simple_read_only/data_processing/test_sahara.py
index 751a4ad..1f2403c 100644
--- a/tempest/cli/simple_read_only/data_processing/test_sahara.py
+++ b/tempest/cli/simple_read_only/data_processing/test_sahara.py
@@ -15,9 +15,10 @@
 import logging
 import re
 
+from tempest_lib import exceptions
+
 from tempest import cli
 from tempest import config
-from tempest import exceptions
 from tempest import test
 
 CONF = config.CONF
@@ -40,6 +41,10 @@
             raise cls.skipException(msg)
         super(SimpleReadOnlySaharaClientTest, cls).resource_setup()
 
+    def sahara(self, *args, **kwargs):
+        return self.clients.sahara(
+            *args, endpoint_type=CONF.data_processing.endpoint_type, **kwargs)
+
     @test.attr(type='negative')
     def test_sahara_fake_action(self):
         self.assertRaises(exceptions.CommandFailed,
diff --git a/tempest/cli/simple_read_only/identity/test_keystone.py b/tempest/cli/simple_read_only/identity/test_keystone.py
index 9218fcd..1fc7908 100644
--- a/tempest/cli/simple_read_only/identity/test_keystone.py
+++ b/tempest/cli/simple_read_only/identity/test_keystone.py
@@ -15,9 +15,10 @@
 
 import re
 
+from tempest_lib import exceptions
+
 from tempest import cli
 from tempest import config
-from tempest import exceptions
 from tempest.openstack.common import log as logging
 
 CONF = config.CONF
@@ -34,6 +35,9 @@
     their own. They only verify the structure of output if present.
     """
 
+    def keystone(self, *args, **kwargs):
+        return self.clients.keystone(*args, **kwargs)
+
     def test_admin_fake_action(self):
         self.assertRaises(exceptions.CommandFailed,
                           self.keystone,
diff --git a/tempest/cli/simple_read_only/image/test_glance.py b/tempest/cli/simple_read_only/image/test_glance.py
index a9cbadb..03e00d7 100644
--- a/tempest/cli/simple_read_only/image/test_glance.py
+++ b/tempest/cli/simple_read_only/image/test_glance.py
@@ -15,9 +15,10 @@
 
 import re
 
+from tempest_lib import exceptions
+
 from tempest import cli
 from tempest import config
-from tempest import exceptions
 from tempest.openstack.common import log as logging
 
 CONF = config.CONF
@@ -40,6 +41,11 @@
             raise cls.skipException(msg)
         super(SimpleReadOnlyGlanceClientTest, cls).resource_setup()
 
+    def glance(self, *args, **kwargs):
+        return self.clients.glance(*args,
+                                   endpoint_type=CONF.image.endpoint_type,
+                                   **kwargs)
+
     def test_glance_fake_action(self):
         self.assertRaises(exceptions.CommandFailed,
                           self.glance,
diff --git a/tempest/cli/simple_read_only/network/test_neutron.py b/tempest/cli/simple_read_only/network/test_neutron.py
index f9f8906..6090882 100644
--- a/tempest/cli/simple_read_only/network/test_neutron.py
+++ b/tempest/cli/simple_read_only/network/test_neutron.py
@@ -15,9 +15,10 @@
 
 import re
 
+from tempest_lib import exceptions
+
 from tempest import cli
 from tempest import config
-from tempest import exceptions
 from tempest.openstack.common import log as logging
 from tempest import test
 
@@ -41,6 +42,11 @@
             raise cls.skipException(msg)
         super(SimpleReadOnlyNeutronClientTest, cls).resource_setup()
 
+    def neutron(self, *args, **kwargs):
+        return self.clients.neutron(*args,
+                                    endpoint_type=CONF.network.endpoint_type,
+                                    **kwargs)
+
     @test.attr(type='smoke')
     def test_neutron_fake_action(self):
         self.assertRaises(exceptions.CommandFailed,
@@ -156,6 +162,42 @@
                                              'allocation_pools'])
 
     @test.attr(type='smoke')
+    @test.requires_ext(extension='vpnaas', service='network')
+    def test_neutron_vpn_ikepolicy_list(self):
+        ikepolicy = self.parser.listing(self.neutron('vpn-ikepolicy-list'))
+        self.assertTableStruct(ikepolicy, ['id', 'name',
+                                           'auth_algorithm',
+                                           'encryption_algorithm',
+                                           'ike_version', 'pfs'])
+
+    @test.attr(type='smoke')
+    @test.requires_ext(extension='vpnaas', service='network')
+    def test_neutron_vpn_ipsecpolicy_list(self):
+        ipsecpolicy = self.parser.listing(self.neutron('vpn-ipsecpolicy-list'))
+        self.assertTableStruct(ipsecpolicy, ['id', 'name',
+                                             'auth_algorithm',
+                                             'encryption_algorithm',
+                                             'pfs'])
+
+    @test.attr(type='smoke')
+    @test.requires_ext(extension='vpnaas', service='network')
+    def test_neutron_vpn_service_list(self):
+        vpn_list = self.parser.listing(self.neutron('vpn-service-list'))
+        self.assertTableStruct(vpn_list, ['id', 'name',
+                                          'router_id', 'status'])
+
+    @test.attr(type='smoke')
+    @test.requires_ext(extension='vpnaas', service='network')
+    def test_neutron_ipsec_site_connection_list(self):
+        ipsec_site = self.parser.listing(self.neutron
+                                         ('ipsec-site-connection-list'))
+        self.assertTableStruct(ipsec_site, ['id', 'name',
+                                            'peer_address',
+                                            'peer_cidrs',
+                                            'route_mode',
+                                            'auth_mode', 'status'])
+
+    @test.attr(type='smoke')
     def test_neutron_help(self):
         help_text = self.neutron('help')
         lines = help_text.split('\n')
diff --git a/tempest/cli/simple_read_only/object_storage/test_swift.py b/tempest/cli/simple_read_only/object_storage/test_swift.py
index a162660..40c4c15 100644
--- a/tempest/cli/simple_read_only/object_storage/test_swift.py
+++ b/tempest/cli/simple_read_only/object_storage/test_swift.py
@@ -15,9 +15,10 @@
 
 import re
 
+from tempest_lib import exceptions
+
 from tempest import cli
 from tempest import config
-from tempest import exceptions
 
 CONF = config.CONF
 
@@ -37,6 +38,10 @@
             raise cls.skipException(msg)
         super(SimpleReadOnlySwiftClientTest, cls).resource_setup()
 
+    def swift(self, *args, **kwargs):
+        return self.clients.swift(
+            *args, endpoint_type=CONF.object_storage.endpoint_type, **kwargs)
+
     def test_swift_fake_action(self):
         self.assertRaises(exceptions.CommandFailed,
                           self.swift,
diff --git a/tempest/cli/simple_read_only/orchestration/test_heat.py b/tempest/cli/simple_read_only/orchestration/test_heat.py
index 7d7f8c9..d3a9b01 100644
--- a/tempest/cli/simple_read_only/orchestration/test_heat.py
+++ b/tempest/cli/simple_read_only/orchestration/test_heat.py
@@ -42,6 +42,10 @@
             os.path.dirname(os.path.realpath(__file__))),
             'heat_templates/heat_minimal.yaml')
 
+    def heat(self, *args, **kwargs):
+        return self.clients.heat(
+            *args, endpoint_type=CONF.orchestration.endpoint_type, **kwargs)
+
     def test_heat_stack_list(self):
         self.heat('stack-list')
 
diff --git a/tempest/cli/simple_read_only/telemetry/test_ceilometer.py b/tempest/cli/simple_read_only/telemetry/test_ceilometer.py
index 45b793b..f9bf8b2 100644
--- a/tempest/cli/simple_read_only/telemetry/test_ceilometer.py
+++ b/tempest/cli/simple_read_only/telemetry/test_ceilometer.py
@@ -39,6 +39,10 @@
             raise cls.skipException(msg)
         super(SimpleReadOnlyCeilometerClientTest, cls).resource_setup()
 
+    def ceilometer(self, *args, **kwargs):
+        return self.clients.ceilometer(
+            *args, endpoint_type=CONF.telemetry.endpoint_type, **kwargs)
+
     def test_ceilometer_meter_list(self):
         self.ceilometer('meter-list')
 
diff --git a/tempest/cli/simple_read_only/volume/test_cinder.py b/tempest/cli/simple_read_only/volume/test_cinder.py
index 45f6c41..c2e0a42 100644
--- a/tempest/cli/simple_read_only/volume/test_cinder.py
+++ b/tempest/cli/simple_read_only/volume/test_cinder.py
@@ -16,11 +16,13 @@
 import logging
 import re
 
+from tempest_lib import exceptions
 import testtools
 
 from tempest import cli
+from tempest import clients
 from tempest import config
-from tempest import exceptions
+
 
 CONF = config.CONF
 LOG = logging.getLogger(__name__)
@@ -40,6 +42,14 @@
             msg = ("%s skipped as Cinder is not available" % cls.__name__)
             raise cls.skipException(msg)
         super(SimpleReadOnlyCinderClientTest, cls).resource_setup()
+        id_cl = clients.AdminManager().identity_client
+        tenant = id_cl.get_tenant_by_name(CONF.identity.admin_tenant_name)
+        cls.admin_tenant_id = tenant['id']
+
+    def cinder(self, *args, **kwargs):
+        return self.clients.cinder(*args,
+                                   endpoint_type=CONF.volume.endpoint_type,
+                                   **kwargs)
 
     def test_cinder_fake_action(self):
         self.assertRaises(exceptions.CommandFailed,
@@ -81,15 +91,13 @@
     def test_cinder_quota_defaults(self):
         """This CLI can accept and string as param."""
         roles = self.parser.listing(self.cinder('quota-defaults',
-                                                params=CONF.identity.
-                                                admin_tenant_name))
+                                                params=self.admin_tenant_id))
         self.assertTableStruct(roles, ['Property', 'Value'])
 
     def test_cinder_quota_show(self):
         """This CLI can accept and string as param."""
         roles = self.parser.listing(self.cinder('quota-show',
-                                                params=CONF.identity.
-                                                admin_tenant_name))
+                                                params=self.admin_tenant_id))
         self.assertTableStruct(roles, ['Property', 'Value'])
 
     def test_cinder_rate_limits(self):
@@ -131,8 +139,7 @@
     def test_cinder_service_list(self):
         service_list = self.parser.listing(self.cinder('service-list'))
         self.assertTableStruct(service_list, ['Binary', 'Host', 'Zone',
-                                              'Status', 'State', 'Updated_at',
-                                              'Disabled Reason'])
+                                              'Status', 'State', 'Updated_at'])
 
     def test_cinder_transfer_list(self):
         transfer_list = self.parser.listing(self.cinder('transfer-list'))
diff --git a/tempest/clients.py b/tempest/clients.py
index 19b4e11..9546502 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -181,6 +181,8 @@
 from tempest.services.volume.json.qos_client import QosSpecsClientJSON
 from tempest.services.volume.json.snapshots_client import SnapshotsClientJSON
 from tempest.services.volume.json.volumes_client import VolumesClientJSON
+from tempest.services.volume.v2.json.admin.volume_hosts_client import \
+    VolumeHostsV2ClientJSON
 from tempest.services.volume.v2.json.admin.volume_types_client import \
     VolumeTypesV2ClientJSON
 from tempest.services.volume.v2.json.availability_zone_client import \
@@ -230,164 +232,19 @@
         # super cares for credentials validation
         super(Manager, self).__init__(credentials=credentials)
 
+        self._set_compute_clients(self.interface)
+        self._set_identity_clients(self.interface)
+        self._set_volume_clients(self.interface)
+
         if self.interface == 'xml':
-            self.certificates_client = CertificatesClientXML(
-                self.auth_provider)
-            self.servers_client = ServersClientXML(self.auth_provider)
-            self.limits_client = LimitsClientXML(self.auth_provider)
-            self.images_client = ImagesClientXML(self.auth_provider)
-            self.keypairs_client = KeyPairsClientXML(self.auth_provider)
-            self.quotas_client = QuotasClientXML(self.auth_provider)
-            self.quota_classes_client = QuotaClassesClientXML(
-                self.auth_provider)
-            self.flavors_client = FlavorsClientXML(self.auth_provider)
-            self.extensions_client = ExtensionsClientXML(self.auth_provider)
-            self.volumes_extensions_client = VolumesExtensionsClientXML(
-                self.auth_provider)
-            self.floating_ips_client = FloatingIPsClientXML(
-                self.auth_provider)
-            self.backups_client = BackupsClientXML(self.auth_provider)
-            self.snapshots_client = SnapshotsClientXML(self.auth_provider)
-            self.snapshots_v2_client = SnapshotsV2ClientXML(self.auth_provider)
-            self.volumes_client = VolumesClientXML(self.auth_provider)
-            self.volumes_v2_client = VolumesV2ClientXML(self.auth_provider)
-            self.volume_types_client = VolumeTypesClientXML(
-                self.auth_provider)
-            self.identity_client = IdentityClientXML(self.auth_provider)
-            self.identity_v3_client = IdentityV3ClientXML(
-                self.auth_provider)
-            self.security_groups_client = SecurityGroupsClientXML(
-                self.auth_provider)
-            self.interfaces_client = InterfacesClientXML(self.auth_provider)
-            self.endpoints_client = EndPointClientXML(self.auth_provider)
-            self.fixed_ips_client = FixedIPsClientXML(self.auth_provider)
-            self.availability_zone_client = AvailabilityZoneClientXML(
-                self.auth_provider)
-            self.service_client = ServiceClientXML(self.auth_provider)
-            self.volume_services_client = VolumesServicesClientXML(
-                self.auth_provider)
-            self.aggregates_client = AggregatesClientXML(self.auth_provider)
-            self.services_client = ServicesClientXML(self.auth_provider)
-            self.tenant_usages_client = TenantUsagesClientXML(
-                self.auth_provider)
-            self.policy_client = PolicyClientXML(self.auth_provider)
-            self.region_client = RegionClientXML(self.auth_provider)
-            self.hosts_client = HostsClientXML(self.auth_provider)
-            self.hypervisor_client = HypervisorClientXML(self.auth_provider)
             self.network_client = NetworkClientXML(self.auth_provider)
-            self.credentials_client = CredentialsClientXML(
-                self.auth_provider)
-            self.instance_usages_audit_log_client = \
-                InstanceUsagesAuditLogClientXML(self.auth_provider)
-            self.volume_hosts_client = VolumeHostsClientXML(
-                self.auth_provider)
-            self.volume_quotas_client = VolumeQuotasClientXML(
-                self.auth_provider)
-            self.volumes_extension_client = VolumeExtensionClientXML(
-                self.auth_provider)
-            self.volumes_v2_extension_client = VolumeV2ExtensionClientXML(
-                self.auth_provider)
             if CONF.service_available.ceilometer:
                 self.telemetry_client = TelemetryClientXML(
                     self.auth_provider)
-            self.token_client = TokenClientXML()
-            self.token_v3_client = V3TokenClientXML()
-            self.volume_availability_zone_client = \
-                VolumeAvailabilityZoneClientXML(self.auth_provider)
-            self.volume_v2_availability_zone_client = \
-                VolumeV2AvailabilityZoneClientXML(self.auth_provider)
 
         elif self.interface == 'json':
-            self.certificates_client = CertificatesClientJSON(
-                self.auth_provider)
-            self.certificates_v3_client = CertificatesV3ClientJSON(
-                self.auth_provider)
             self.baremetal_client = BaremetalClientJSON(self.auth_provider)
-            self.servers_client = ServersClientJSON(self.auth_provider)
-            self.servers_v3_client = ServersV3ClientJSON(self.auth_provider)
-            self.limits_client = LimitsClientJSON(self.auth_provider)
-            self.images_client = ImagesClientJSON(self.auth_provider)
-            self.keypairs_v3_client = KeyPairsV3ClientJSON(
-                self.auth_provider)
-            self.keypairs_client = KeyPairsClientJSON(self.auth_provider)
-            self.keypairs_v3_client = KeyPairsV3ClientJSON(
-                self.auth_provider)
-            self.quotas_client = QuotasClientJSON(self.auth_provider)
-            self.quota_classes_client = QuotaClassesClientJSON(
-                self.auth_provider)
-            self.quotas_v3_client = QuotasV3ClientJSON(self.auth_provider)
-            self.flavors_client = FlavorsClientJSON(self.auth_provider)
-            self.flavors_v3_client = FlavorsV3ClientJSON(self.auth_provider)
-            self.extensions_v3_client = ExtensionsV3ClientJSON(
-                self.auth_provider)
-            self.extensions_client = ExtensionsClientJSON(
-                self.auth_provider)
-            self.volumes_extensions_client = VolumesExtensionsClientJSON(
-                self.auth_provider)
-            self.floating_ips_client = FloatingIPsClientJSON(
-                self.auth_provider)
-            self.backups_client = BackupsClientJSON(self.auth_provider)
-            self.snapshots_client = SnapshotsClientJSON(self.auth_provider)
-            self.snapshots_v2_client = SnapshotsV2ClientJSON(
-                self.auth_provider)
-            self.volumes_client = VolumesClientJSON(self.auth_provider)
-            self.volumes_v2_client = VolumesV2ClientJSON(self.auth_provider)
-            self.volume_types_client = VolumeTypesClientJSON(
-                self.auth_provider)
-            self.volume_types_v2_client = VolumeTypesV2ClientJSON(
-                self.auth_provider)
-            self.identity_client = IdentityClientJSON(self.auth_provider)
-            self.identity_v3_client = IdentityV3ClientJSON(
-                self.auth_provider)
-            self.security_groups_client = SecurityGroupsClientJSON(
-                self.auth_provider)
-            self.interfaces_v3_client = InterfacesV3ClientJSON(
-                self.auth_provider)
-            self.interfaces_client = InterfacesClientJSON(
-                self.auth_provider)
-            self.endpoints_client = EndPointClientJSON(self.auth_provider)
-            self.fixed_ips_client = FixedIPsClientJSON(self.auth_provider)
-            self.availability_zone_v3_client = AvailabilityZoneV3ClientJSON(
-                self.auth_provider)
-            self.availability_zone_client = AvailabilityZoneClientJSON(
-                self.auth_provider)
-            self.services_v3_client = ServicesV3ClientJSON(
-                self.auth_provider)
-            self.service_client = ServiceClientJSON(self.auth_provider)
-            self.volume_services_client = VolumesServicesClientJSON(
-                self.auth_provider)
-            self.agents_v3_client = AgentsV3ClientJSON(self.auth_provider)
-            self.aggregates_v3_client = AggregatesV3ClientJSON(
-                self.auth_provider)
-            self.aggregates_client = AggregatesClientJSON(
-                self.auth_provider)
-            self.services_client = ServicesClientJSON(self.auth_provider)
-            self.tenant_usages_client = TenantUsagesClientJSON(
-                self.auth_provider)
-            self.version_v3_client = VersionV3ClientJSON(self.auth_provider)
-            self.migrations_v3_client = MigrationsV3ClientJSON(
-                self.auth_provider)
-            self.policy_client = PolicyClientJSON(self.auth_provider)
-            self.region_client = RegionClientJSON(self.auth_provider)
-            self.hosts_client = HostsClientJSON(self.auth_provider)
-            self.hypervisor_v3_client = HypervisorV3ClientJSON(
-                self.auth_provider)
-            self.hypervisor_client = HypervisorClientJSON(
-                self.auth_provider)
             self.network_client = NetworkClientJSON(self.auth_provider)
-            self.credentials_client = CredentialsClientJSON(
-                self.auth_provider)
-            self.instance_usages_audit_log_client = \
-                InstanceUsagesAuditLogClientJSON(self.auth_provider)
-            self.volume_hosts_client = VolumeHostsClientJSON(
-                self.auth_provider)
-            self.volume_quotas_client = VolumeQuotasClientJSON(
-                self.auth_provider)
-            self.volumes_extension_client = VolumeExtensionClientJSON(
-                self.auth_provider)
-            self.volumes_v2_extension_client = VolumeV2ExtensionClientJSON(
-                self.auth_provider)
-            self.hosts_v3_client = HostsV3ClientJSON(self.auth_provider)
             self.database_flavors_client = DatabaseFlavorsClientJSON(
                 self.auth_provider)
             self.database_versions_client = DatabaseVersionsClientJSON(
@@ -396,15 +253,9 @@
             if CONF.service_available.ceilometer:
                 self.telemetry_client = TelemetryClientJSON(
                     self.auth_provider)
-            self.token_client = TokenClientJSON()
-            self.token_v3_client = V3TokenClientJSON()
             self.negative_client = rest_client.NegativeRestClient(
                 self.auth_provider)
             self.negative_client.service = service
-            self.volume_availability_zone_client = \
-                VolumeAvailabilityZoneClientJSON(self.auth_provider)
-            self.volume_v2_availability_zone_client = \
-                VolumeV2AvailabilityZoneClientJSON(self.auth_provider)
 
         else:
             msg = "Unsupported interface type `%s'" % interface
@@ -418,7 +269,6 @@
 
         # common clients
         self.account_client = AccountClient(self.auth_provider)
-        self.agents_client = AgentsClientJSON(self.auth_provider)
         if CONF.service_available.glance:
             self.image_client = ImageClientJSON(self.auth_provider)
             self.image_client_v2 = ImageClientV2JSON(self.auth_provider)
@@ -434,10 +284,128 @@
             AccountClientCustomizedHeader(self.auth_provider)
         self.data_processing_client = DataProcessingClient(
             self.auth_provider)
+
+    def _set_compute_clients(self, type):
+        if type == 'json':
+            self._set_compute_json_clients()
+        else:
+            self._set_compute_xml_clients()
+
+        # Common compute clients
+        self.agents_client = AgentsClientJSON(self.auth_provider)
+        self.networks_client = NetworksClientJSON(self.auth_provider)
         self.migrations_client = MigrationsClientJSON(self.auth_provider)
         self.security_group_default_rules_client = (
             SecurityGroupDefaultRulesClientJSON(self.auth_provider))
-        self.networks_client = NetworksClientJSON(self.auth_provider)
+
+    def _set_compute_xml_clients(self):
+        self.certificates_client = CertificatesClientXML(self.auth_provider)
+        self.servers_client = ServersClientXML(self.auth_provider)
+        self.limits_client = LimitsClientXML(self.auth_provider)
+        self.images_client = ImagesClientXML(self.auth_provider)
+        self.keypairs_client = KeyPairsClientXML(self.auth_provider)
+        self.quotas_client = QuotasClientXML(self.auth_provider)
+        self.quota_classes_client = QuotaClassesClientXML(self.auth_provider)
+        self.flavors_client = FlavorsClientXML(self.auth_provider)
+        self.extensions_client = ExtensionsClientXML(self.auth_provider)
+        self.volumes_extensions_client = VolumesExtensionsClientXML(
+            self.auth_provider)
+        self.floating_ips_client = FloatingIPsClientXML(self.auth_provider)
+        self.security_groups_client = SecurityGroupsClientXML(
+            self.auth_provider)
+        self.interfaces_client = InterfacesClientXML(self.auth_provider)
+        self.fixed_ips_client = FixedIPsClientXML(self.auth_provider)
+        self.availability_zone_client = AvailabilityZoneClientXML(
+            self.auth_provider)
+        self.aggregates_client = AggregatesClientXML(self.auth_provider)
+        self.services_client = ServicesClientXML(self.auth_provider)
+        self.tenant_usages_client = TenantUsagesClientXML(self.auth_provider)
+        self.hosts_client = HostsClientXML(self.auth_provider)
+        self.hypervisor_client = HypervisorClientXML(self.auth_provider)
+        self.instance_usages_audit_log_client = \
+            InstanceUsagesAuditLogClientXML(self.auth_provider)
+
+    def _set_compute_json_clients(self):
+        self.certificates_client = CertificatesClientJSON(self.auth_provider)
+        self.certificates_v3_client = CertificatesV3ClientJSON(
+            self.auth_provider)
+        self.servers_client = ServersClientJSON(self.auth_provider)
+        self.servers_v3_client = ServersV3ClientJSON(self.auth_provider)
+        self.limits_client = LimitsClientJSON(self.auth_provider)
+        self.images_client = ImagesClientJSON(self.auth_provider)
+        self.keypairs_client = KeyPairsClientJSON(self.auth_provider)
+        self.keypairs_v3_client = KeyPairsV3ClientJSON(self.auth_provider)
+        self.quotas_client = QuotasClientJSON(self.auth_provider)
+        self.quota_classes_client = QuotaClassesClientJSON(self.auth_provider)
+        self.quotas_v3_client = QuotasV3ClientJSON(self.auth_provider)
+        self.flavors_client = FlavorsClientJSON(self.auth_provider)
+        self.flavors_v3_client = FlavorsV3ClientJSON(self.auth_provider)
+        self.extensions_client = ExtensionsClientJSON(self.auth_provider)
+        self.extensions_v3_client = ExtensionsV3ClientJSON(self.auth_provider)
+        self.volumes_extensions_client = VolumesExtensionsClientJSON(
+            self.auth_provider)
+        self.floating_ips_client = FloatingIPsClientJSON(self.auth_provider)
+        self.security_groups_client = SecurityGroupsClientJSON(
+            self.auth_provider)
+        self.interfaces_client = InterfacesClientJSON(self.auth_provider)
+        self.interfaces_v3_client = InterfacesV3ClientJSON(self.auth_provider)
+        self.fixed_ips_client = FixedIPsClientJSON(self.auth_provider)
+        self.availability_zone_client = AvailabilityZoneClientJSON(
+            self.auth_provider)
+        self.availability_zone_v3_client = AvailabilityZoneV3ClientJSON(
+            self.auth_provider)
+        self.services_v3_client = ServicesV3ClientJSON(self.auth_provider)
+        self.agents_v3_client = AgentsV3ClientJSON(self.auth_provider)
+        self.aggregates_client = AggregatesClientJSON(self.auth_provider)
+        self.aggregates_v3_client = AggregatesV3ClientJSON(self.auth_provider)
+        self.services_client = ServicesClientJSON(self.auth_provider)
+        self.tenant_usages_client = TenantUsagesClientJSON(self.auth_provider)
+        self.version_v3_client = VersionV3ClientJSON(self.auth_provider)
+        self.migrations_v3_client = MigrationsV3ClientJSON(self.auth_provider)
+        self.hosts_client = HostsClientJSON(self.auth_provider)
+        self.hosts_v3_client = HostsV3ClientJSON(self.auth_provider)
+        self.hypervisor_client = HypervisorClientJSON(self.auth_provider)
+        self.hypervisor_v3_client = HypervisorV3ClientJSON(self.auth_provider)
+        self.instance_usages_audit_log_client = \
+            InstanceUsagesAuditLogClientJSON(self.auth_provider)
+
+    def _set_identity_clients(self, type):
+        if type == 'json':
+            self._set_identity_json_clients()
+        else:
+            self._set_identity_xml_clients()
+
+    def _set_identity_xml_clients(self):
+        self.identity_client = IdentityClientXML(self.auth_provider)
+        self.identity_v3_client = IdentityV3ClientXML(self.auth_provider)
+        self.endpoints_client = EndPointClientXML(self.auth_provider)
+        self.service_client = ServiceClientXML(self.auth_provider)
+        self.policy_client = PolicyClientXML(self.auth_provider)
+        self.region_client = RegionClientXML(self.auth_provider)
+        self.token_client = TokenClientXML()
+        if CONF.identity_feature_enabled.api_v3:
+            self.token_v3_client = V3TokenClientXML()
+        self.credentials_client = CredentialsClientXML(self.auth_provider)
+
+    def _set_identity_json_clients(self):
+        self.identity_client = IdentityClientJSON(self.auth_provider)
+        self.identity_v3_client = IdentityV3ClientJSON(self.auth_provider)
+        self.endpoints_client = EndPointClientJSON(self.auth_provider)
+        self.service_client = ServiceClientJSON(self.auth_provider)
+        self.policy_client = PolicyClientJSON(self.auth_provider)
+        self.region_client = RegionClientJSON(self.auth_provider)
+        self.token_client = TokenClientJSON()
+        if CONF.identity_feature_enabled.api_v3:
+            self.token_v3_client = V3TokenClientJSON()
+        self.credentials_client = CredentialsClientJSON(self.auth_provider)
+
+    def _set_volume_clients(self, type):
+        if type == 'json':
+            self._set_volume_json_clients()
+        else:
+            self._set_volume_xml_clients()
+
+        # Common volume clients
         # NOTE : As XML clients are not implemented for Qos-specs.
         # So, setting the qos_client here. Once client are implemented,
         # qos_client would be moved to its respective if/else.
@@ -446,6 +414,50 @@
         self.volume_qos_v2_client = QosSpecsV2ClientJSON(
             self.auth_provider)
 
+    def _set_volume_xml_clients(self):
+        self.backups_client = BackupsClientXML(self.auth_provider)
+        self.snapshots_client = SnapshotsClientXML(self.auth_provider)
+        self.snapshots_v2_client = SnapshotsV2ClientXML(self.auth_provider)
+        self.volumes_client = VolumesClientXML(self.auth_provider)
+        self.volumes_v2_client = VolumesV2ClientXML(self.auth_provider)
+        self.volume_types_client = VolumeTypesClientXML(self.auth_provider)
+        self.volume_services_client = VolumesServicesClientXML(
+            self.auth_provider)
+        self.volume_hosts_client = VolumeHostsClientXML(self.auth_provider)
+        self.volume_quotas_client = VolumeQuotasClientXML(self.auth_provider)
+        self.volumes_extension_client = VolumeExtensionClientXML(
+            self.auth_provider)
+        self.volumes_v2_extension_client = VolumeV2ExtensionClientXML(
+            self.auth_provider)
+        self.volume_availability_zone_client = \
+            VolumeAvailabilityZoneClientXML(self.auth_provider)
+        self.volume_v2_availability_zone_client = \
+            VolumeV2AvailabilityZoneClientXML(self.auth_provider)
+
+    def _set_volume_json_clients(self):
+        self.backups_client = BackupsClientJSON(self.auth_provider)
+        self.snapshots_client = SnapshotsClientJSON(self.auth_provider)
+        self.snapshots_v2_client = SnapshotsV2ClientJSON(self.auth_provider)
+        self.volumes_client = VolumesClientJSON(self.auth_provider)
+        self.volumes_v2_client = VolumesV2ClientJSON(self.auth_provider)
+        self.volume_types_client = VolumeTypesClientJSON(self.auth_provider)
+        self.volume_services_client = VolumesServicesClientJSON(
+            self.auth_provider)
+        self.volume_hosts_client = VolumeHostsClientJSON(self.auth_provider)
+        self.volume_hosts_v2_client = VolumeHostsV2ClientJSON(
+            self.auth_provider)
+        self.volume_quotas_client = VolumeQuotasClientJSON(self.auth_provider)
+        self.volumes_extension_client = VolumeExtensionClientJSON(
+            self.auth_provider)
+        self.volumes_v2_extension_client = VolumeV2ExtensionClientJSON(
+            self.auth_provider)
+        self.volume_availability_zone_client = \
+            VolumeAvailabilityZoneClientJSON(self.auth_provider)
+        self.volume_v2_availability_zone_client = \
+            VolumeV2AvailabilityZoneClientJSON(self.auth_provider)
+        self.volume_types_v2_client = VolumeTypesV2ClientJSON(
+            self.auth_provider)
+
 
 class AdminManager(Manager):
 
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 0adc7e0..6879db9 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -26,6 +26,7 @@
 import sys
 import unittest
 
+import netaddr
 import yaml
 
 import tempest.auth
@@ -34,14 +35,17 @@
 from tempest.openstack.common import log as logging
 from tempest.openstack.common import timeutils
 from tempest.services.compute.json import flavors_client
+from tempest.services.compute.json import security_groups_client
 from tempest.services.compute.json import servers_client
 from tempest.services.identity.json import identity_client
 from tempest.services.image.v2.json import image_client
+from tempest.services.network.json import network_client
 from tempest.services.object_storage import container_client
 from tempest.services.object_storage import object_client
 from tempest.services.telemetry.json import telemetry_client
 from tempest.services.volume.json import volumes_client
 
+CONF = config.CONF
 OPTS = {}
 USERS = {}
 RES = collections.defaultdict(list)
@@ -69,7 +73,9 @@
         self.images = image_client.ImageClientV2JSON(_auth)
         self.flavors = flavors_client.FlavorsClientJSON(_auth)
         self.telemetry = telemetry_client.TelemetryClientJSON(_auth)
+        self.secgroups = security_groups_client.SecurityGroupsClientJSON(_auth)
         self.volumes = volumes_client.VolumesClientJSON(_auth)
+        self.networks = network_client.NetworkClientJSON(_auth)
 
 
 def load_resources(fname):
@@ -90,6 +96,10 @@
     else:
         LOG.error("%s not found in USERS: %s" % (name, USERS))
 
+
+def resp_ok(response):
+    return 200 >= int(response['status']) < 300
+
 ###################
 #
 # TENANTS
@@ -212,12 +222,36 @@
     def runTest(self, *args):
         pass
 
+    def _ping_ip(self, ip_addr, count, namespace=None):
+        if namespace is None:
+            ping_cmd = "ping -c1 " + ip_addr
+        else:
+            ping_cmd = "sudo ip netns exec %s ping -c1 %s" % (namespace,
+                                                              ip_addr)
+        for current in range(count):
+            return_code = os.system(ping_cmd)
+            if return_code is 0:
+                break
+        self.assertNotEqual(current, count - 1,
+                            "Server is not pingable at %s" % ip_addr)
+
     def check(self):
         self.check_users()
         self.check_objects()
         self.check_servers()
         self.check_volumes()
         self.check_telemetry()
+        self.check_secgroups()
+
+        # validate neutron is enabled and ironic disabled:
+        # Tenant network isolation is not supported when using ironic.
+        # "admin" has set up a neutron flat network environment within a shared
+        # fixed network for all tenants to use.
+        # In this case, network/subnet/router creation can be skipped and the
+        # server booted the same as nova network.
+        if (CONF.service_available.neutron and
+                not CONF.baremetal.driver_enabled):
+            self.check_networking()
 
     def check_users(self):
         """Check that the users we expect to exist, do.
@@ -264,15 +298,32 @@
                 "Couldn't find expected server %s" % server['name'])
 
             r, found = client.servers.get_server(found['id'])
-            # get the ipv4 address
-            addr = found['addresses']['private'][0]['addr']
-            for count in range(60):
-                return_code = os.system("ping -c1 " + addr)
-                if return_code is 0:
-                    break
-            self.assertNotEqual(count, 59,
-                                "Server %s is not pingable at %s" % (
-                                    server['name'], addr))
+            # validate neutron is enabled and ironic disabled:
+            if (CONF.service_available.neutron and
+                    not CONF.baremetal.driver_enabled):
+                for network_name, body in found['addresses'].items():
+                    for addr in body:
+                        ip = addr['addr']
+                        if addr.get('OS-EXT-IPS:type', 'fixed') == 'fixed':
+                            namespace = _get_router_namespace(client,
+                                                              network_name)
+                            self._ping_ip(ip, 60, namespace)
+                        else:
+                            self._ping_ip(ip, 60)
+            else:
+                addr = found['addresses']['private'][0]['addr']
+                self._ping_ip(addr, 60)
+
+    def check_secgroups(self):
+        """Check that the security groups are still existing."""
+        LOG.info("Checking security groups")
+        for secgroup in self.res['secgroups']:
+            client = client_for_user(secgroup['owner'])
+            found = _get_resource_by_name(client.secgroups, 'security_groups',
+                                          secgroup['name'])
+            self.assertIsNotNone(
+                found,
+                "Couldn't find expected secgroup %s" % secgroup['name'])
 
     def check_telemetry(self):
         """Check that ceilometer provides a sane sample.
@@ -334,6 +385,17 @@
                 'timestamp should come before start of second javelin run'
             )
 
+    def check_networking(self):
+        """Check that the networks are still there."""
+        for res_type in ('networks', 'subnets', 'routers'):
+            for res in self.res[res_type]:
+                client = client_for_user(res['owner'])
+                found = _get_resource_by_name(client.networks, res_type,
+                                              res['name'])
+                self.assertIsNotNone(
+                    found,
+                    "Couldn't find expected resource %s" % res['name'])
+
 
 #######################
 #
@@ -440,6 +502,147 @@
 
 #######################
 #
+# NETWORKS
+#
+#######################
+
+def _get_router_namespace(client, network):
+    network_id = _get_resource_by_name(client.networks,
+                                       'networks', network)['id']
+    resp, n_body = client.networks.list_routers()
+    if not resp_ok(resp):
+        raise ValueError("unable to routers list: [%s] %s" % (resp, n_body))
+    for router in n_body['routers']:
+        router_id = router['id']
+        resp, r_body = client.networks.list_router_interfaces(router_id)
+        if not resp_ok(resp):
+            raise ValueError("unable to router interfaces list: [%s] %s" %
+                             (resp, r_body))
+        for port in r_body['ports']:
+            if port['network_id'] == network_id:
+                return "qrouter-%s" % router_id
+
+
+def _get_resource_by_name(client, resource, name):
+    get_resources = getattr(client, 'list_%s' % resource)
+    if get_resources is None:
+        raise AttributeError("client doesn't have method list_%s" % resource)
+    r, body = get_resources()
+    if not resp_ok(r):
+        raise ValueError("unable to list %s: [%s] %s" % (resource, r, body))
+    if isinstance(body, dict):
+        body = body[resource]
+    for res in body:
+        if name == res['name']:
+            return res
+    raise ValueError('%s not found in %s resources' % (name, resource))
+
+
+def create_networks(networks):
+    LOG.info("Creating networks")
+    for network in networks:
+        client = client_for_user(network['owner'])
+
+        # only create a network if the name isn't here
+        r, body = client.networks.list_networks()
+        if any(item['name'] == network['name'] for item in body['networks']):
+            LOG.warning("Dupplicated network name: %s" % network['name'])
+            continue
+
+        client.networks.create_network(name=network['name'])
+
+
+def destroy_networks(networks):
+    LOG.info("Destroying subnets")
+    for network in networks:
+        client = client_for_user(network['owner'])
+        network_id = _get_resource_by_name(client.networks, 'networks',
+                                           network['name'])['id']
+        client.networks.delete_network(network_id)
+
+
+def create_subnets(subnets):
+    LOG.info("Creating subnets")
+    for subnet in subnets:
+        client = client_for_user(subnet['owner'])
+
+        network = _get_resource_by_name(client.networks, 'networks',
+                                        subnet['network'])
+        ip_version = netaddr.IPNetwork(subnet['range']).version
+        # ensure we don't overlap with another subnet in the network
+        try:
+            client.networks.create_subnet(network_id=network['id'],
+                                          cidr=subnet['range'],
+                                          name=subnet['name'],
+                                          ip_version=ip_version)
+        except exceptions.BadRequest as e:
+            is_overlapping_cidr = 'overlaps with another subnet' in str(e)
+            if not is_overlapping_cidr:
+                raise
+
+
+def destroy_subnets(subnets):
+    LOG.info("Destroying subnets")
+    for subnet in subnets:
+        client = client_for_user(subnet['owner'])
+        subnet_id = _get_resource_by_name(client.networks,
+                                          'subnets', subnet['name'])['id']
+        client.networks.delete_subnet(subnet_id)
+
+
+def create_routers(routers):
+    LOG.info("Creating routers")
+    for router in routers:
+        client = client_for_user(router['owner'])
+
+        # only create a router if the name isn't here
+        r, body = client.networks.list_routers()
+        if any(item['name'] == router['name'] for item in body['routers']):
+            LOG.warning("Dupplicated router name: %s" % router['name'])
+            continue
+
+        client.networks.create_router(router['name'])
+
+
+def destroy_routers(routers):
+    LOG.info("Destroying routers")
+    for router in routers:
+        client = client_for_user(router['owner'])
+        router_id = _get_resource_by_name(client.networks,
+                                          'routers', router['name'])['id']
+        for subnet in router['subnet']:
+            subnet_id = _get_resource_by_name(client.networks,
+                                              'subnets', subnet)['id']
+            client.networks.remove_router_interface_with_subnet_id(router_id,
+                                                                   subnet_id)
+        client.networks.delete_router(router_id)
+
+
+def add_router_interface(routers):
+    for router in routers:
+        client = client_for_user(router['owner'])
+        router_id = _get_resource_by_name(client.networks,
+                                          'routers', router['name'])['id']
+
+        for subnet in router['subnet']:
+            subnet_id = _get_resource_by_name(client.networks,
+                                              'subnets', subnet)['id']
+            # connect routers to their subnets
+            client.networks.add_router_interface_with_subnet_id(router_id,
+                                                                subnet_id)
+        # connect routers to exteral network if set to "gateway"
+        if router['gateway']:
+            if CONF.network.public_network_id:
+                ext_net = CONF.network.public_network_id
+                client.networks._update_router(
+                    router_id, set_enable_snat=True,
+                    external_gateway_info={"network_id": ext_net})
+            else:
+                raise ValueError('public_network_id is not configured.')
+
+
+#######################
+#
 # SERVERS
 #
 #######################
@@ -473,10 +676,21 @@
 
         image_id = _get_image_by_name(client, server['image'])['id']
         flavor_id = _get_flavor_by_name(client, server['flavor'])['id']
-        resp, body = client.servers.create_server(server['name'], image_id,
-                                                  flavor_id)
+        # validate neutron is enabled and ironic disabled
+        kwargs = dict()
+        if (CONF.service_available.neutron and
+                not CONF.baremetal.driver_enabled and server.get('networks')):
+            get_net_id = lambda x: (_get_resource_by_name(
+                client.networks, 'networks', x)['id'])
+            kwargs['networks'] = [{'uuid': get_net_id(network)}
+                                  for network in server['networks']]
+        resp, body = client.servers.create_server(
+            server['name'], image_id, flavor_id, **kwargs)
         server_id = body['id']
         client.servers.wait_for_server_status(server_id, 'ACTIVE')
+        # create to security group(s) after server spawning
+        for secgroup in server['secgroups']:
+            client.servers.add_security_group(server_id, secgroup)
 
 
 def destroy_servers(servers):
@@ -496,6 +710,44 @@
                                                    ignore_error=True)
 
 
+def create_secgroups(secgroups):
+    LOG.info("Creating security groups")
+    for secgroup in secgroups:
+        client = client_for_user(secgroup['owner'])
+
+        # only create a security group if the name isn't here
+        # i.e. a security group may be used by another server
+        # only create a router if the name isn't here
+        r, body = client.secgroups.list_security_groups()
+        if any(item['name'] == secgroup['name'] for item in body):
+            LOG.warning("Security group '%s' already exists" %
+                        secgroup['name'])
+            continue
+
+        resp, body = client.secgroups.create_security_group(
+            secgroup['name'], secgroup['description'])
+        if not resp_ok(resp):
+            raise ValueError("Failed to create security group: [%s] %s" %
+                             (resp, body))
+        secgroup_id = body['id']
+        # for each security group, create the rules
+        for rule in secgroup['rules']:
+            ip_proto, from_port, to_port, cidr = rule.split()
+            client.secgroups.create_security_group_rule(
+                secgroup_id, ip_proto, from_port, to_port, cidr=cidr)
+
+
+def destroy_secgroups(secgroups):
+    LOG.info("Destroying security groups")
+    for secgroup in secgroups:
+        client = client_for_user(secgroup['owner'])
+        sg_id = _get_resource_by_name(client.secgroups,
+                                      'security_groups',
+                                      secgroup['name'])
+        # sg rules are deleted automatically
+        client.secgroups.delete_security_group(sg_id['id'])
+
+
 #######################
 #
 # VOLUMES
@@ -563,6 +815,15 @@
     # next create resources in a well known order
     create_objects(RES['objects'])
     create_images(RES['images'])
+
+    # validate neutron is enabled and ironic is disabled
+    if CONF.service_available.neutron and not CONF.baremetal.driver_enabled:
+        create_networks(RES['networks'])
+        create_subnets(RES['subnets'])
+        create_routers(RES['routers'])
+        add_router_interface(RES['routers'])
+
+    create_secgroups(RES['secgroups'])
     create_servers(RES['servers'])
     create_volumes(RES['volumes'])
     attach_volumes(RES['volumes'])
@@ -575,6 +836,11 @@
     destroy_images(RES['images'])
     destroy_objects(RES['objects'])
     destroy_volumes(RES['volumes'])
+    if CONF.service_available.neutron and not CONF.baremetal.driver_enabled:
+        destroy_routers(RES['routers'])
+        destroy_subnets(RES['subnets'])
+        destroy_networks(RES['networks'])
+    destroy_secgroups(RES['secgroups'])
     destroy_users(RES['users'])
     destroy_tenants(RES['tenants'])
     LOG.warn("Destroy mode incomplete")
diff --git a/tempest/cmd/resources.yaml b/tempest/cmd/resources.yaml
index 2d5e686..2d6664c 100644
--- a/tempest/cmd/resources.yaml
+++ b/tempest/cmd/resources.yaml
@@ -17,11 +17,17 @@
     tenant: discuss
 
 secgroups:
-  - angon:
+  - name: angon
     owner: javelin
+    description: angon
     rules:
       - 'icmp -1 -1 0.0.0.0/0'
       - 'tcp 22 22 0.0.0.0/0'
+  - name: baobab
+    owner: javelin
+    description: baobab
+    rules:
+      - 'tcp 80 80 0.0.0.0/0'
 
 # resources that we want to create
 images:
@@ -43,15 +49,45 @@
     owner: javelin
     gb: 2
     device: /dev/vdb
+networks:
+  - name: world1
+    owner: javelin
+  - name: world2
+    owner: javelin
+subnets:
+  - name: subnet1
+    range: 10.1.0.0/24
+    network: world1
+    owner: javelin
+  - name: subnet2
+    range: 192.168.1.0/24
+    network: world2
+    owner: javelin
+routers:
+  - name: connector
+    owner: javelin
+    gateway: true
+    subnet:
+      - subnet1
+      - subnet2
 servers:
   - name: peltast
     owner: javelin
     flavor: m1.small
     image: javelin_cirros
+    networks:
+      - world1
+    secgroups:
+      - angon
+      - baobab
   - name: hoplite
     owner: javelin
     flavor: m1.medium
     image: javelin_cirros
+    networks:
+      - world2
+    secgroups:
+      - angon
 objects:
   - container: jc1
     name: javelin1
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index c290dad..6f2e1bd 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -42,7 +42,7 @@
 
 
 # convert a structure into a string safely
-def safe_body(body, maxlen=2048):
+def safe_body(body, maxlen=4096):
     try:
         text = six.text_type(body)
     except UnicodeDecodeError:
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 89904b2..6a238d0 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -91,7 +91,7 @@
         return self.exec_command(cmd)
 
     def get_mac_address(self):
-        cmd = "/sbin/ifconfig | awk '/HWaddr/ {print $5}'"
+        cmd = "/bin/ip addr | awk '/ether/ {print $2}'"
         return self.exec_command(cmd)
 
     def get_ip_list(self):
diff --git a/tempest/config.py b/tempest/config.py
index 6e8238a..63a7226 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -143,6 +143,9 @@
     cfg.BoolOpt('api_v3',
                 default=True,
                 help='Is the v3 identity API enabled'),
+    cfg.BoolOpt('xml_api',
+                default=False,
+                help='If false, skip all identity api tests with xml'),
 ]
 
 compute_group = cfg.OptGroup(name='compute',
@@ -312,7 +315,7 @@
                 default=True,
                 help="Does the test environment support suspend/resume?"),
     cfg.BoolOpt('live_migration',
-                default=False,
+                default=True,
                 help="Does the test environment support live migration "
                      "available?"),
     cfg.BoolOpt('block_migration_for_live_migration',
@@ -449,7 +452,9 @@
     cfg.StrOpt('public_router_id',
                default="",
                help="Id of the public router that provides external "
-                    "connectivity"),
+                    "connectivity. This should only be used when Neutron's "
+                    "'allow_overlapping_ips' is set to 'False' in "
+                    "neutron.conf. usually not needed past 'Grizzly' release"),
     cfg.IntOpt('build_timeout',
                default=300,
                help="Timeout in seconds to wait for network operation to "
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 990a392..ea4365e 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -411,9 +411,8 @@
 
     def nova_volume_attach(self):
         # TODO(andreaf) Device should be here CONF.compute.volume_device_name
-        _, volume_attachment = self.servers_client.attach_volume(
+        _, volume = self.servers_client.attach_volume(
             self.server['id'], self.volume['id'], '/dev/vdb')
-        volume = volume_attachment['volumeAttachment']
         self.assertEqual(self.volume['id'], volume['id'])
         self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
         # Refresh the volume after the attachment
@@ -476,9 +475,9 @@
 
     @classmethod
     def resource_setup(cls):
+        cls.check_preconditions()
         super(NetworkScenarioTest, cls).resource_setup()
         cls.tenant_id = cls.manager.identity_client.tenant_id
-        cls.check_preconditions()
 
     def _create_network(self, client=None, tenant_id=None,
                         namestart='network-smoke-'):
@@ -1023,12 +1022,11 @@
 class BaremetalScenarioTest(ScenarioTest):
     @classmethod
     def resource_setup(cls):
-        super(BaremetalScenarioTest, cls).resource_setup()
-
         if (not CONF.service_available.ironic or
            not CONF.baremetal.driver_enabled):
             msg = 'Ironic not available or Ironic compute driver not enabled'
             raise cls.skipException(msg)
+        super(BaremetalScenarioTest, cls).resource_setup()
 
         # use an admin client manager for baremetal client
         manager = clients.Manager(
@@ -1202,9 +1200,9 @@
 
     @classmethod
     def resource_setup(cls):
-        super(OrchestrationScenarioTest, cls).resource_setup()
         if not CONF.service_available.heat:
             raise cls.skipException("Heat support is required")
+        super(OrchestrationScenarioTest, cls).resource_setup()
 
     @classmethod
     def credentials(cls):
@@ -1247,12 +1245,12 @@
 
     @classmethod
     def resource_setup(cls):
-        cls.set_network_resources()
-        super(SwiftScenarioTest, cls).resource_setup()
         if not CONF.service_available.swift:
             skip_msg = ("%s skipped as swift is not available" %
                         cls.__name__)
             raise cls.skipException(skip_msg)
+        cls.set_network_resources()
+        super(SwiftScenarioTest, cls).resource_setup()
         # Clients for Swift
         cls.account_client = cls.manager.account_client
         cls.container_client = cls.manager.container_client
@@ -1270,6 +1268,9 @@
         # look for the container to assure it is created
         self.list_and_check_container_objects(name)
         LOG.debug('Container %s created' % (name))
+        self.addCleanup(self.delete_wrapper,
+                        self.container_client.delete_container,
+                        name)
         return name
 
     def delete_container(self, container_name):
@@ -1280,6 +1281,10 @@
         obj_name = obj_name or data_utils.rand_name('swift-scenario-object')
         obj_data = data_utils.arbitrary_string()
         self.object_client.create_object(container_name, obj_name, obj_data)
+        self.addCleanup(self.delete_wrapper,
+                        self.object_client.delete_object,
+                        container_name,
+                        obj_name)
         return obj_name, obj_data
 
     def delete_object(self, container_name, filename):
diff --git a/tempest/scenario/orchestration/test_server_cfn_init.py b/tempest/scenario/orchestration/test_server_cfn_init.py
index 791c564..ddfabe4 100644
--- a/tempest/scenario/orchestration/test_server_cfn_init.py
+++ b/tempest/scenario/orchestration/test_server_cfn_init.py
@@ -129,6 +129,7 @@
                 raise e
 
     @test.attr(type='slow')
+    @test.skip_because(bug='1374175')
     @test.services('orchestration', 'compute')
     def test_server_cfn_init(self):
         self.assign_keypair()
diff --git a/tempest/scenario/test_baremetal_basic_ops.py b/tempest/scenario/test_baremetal_basic_ops.py
index 35571c6..ea10140 100644
--- a/tempest/scenario/test_baremetal_basic_ops.py
+++ b/tempest/scenario/test_baremetal_basic_ops.py
@@ -132,7 +132,6 @@
         # We expect the ephemeral partition to be mounted on /mnt and to have
         # the same size as our flavor definition.
         eph_size = self.get_flavor_ephemeral_size()
-        self.assertIsNotNone(eph_size)
         if eph_size > 0:
             preserve_ephemeral = True
 
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index f218fb2..875a1d9 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -35,11 +35,10 @@
 
     @classmethod
     def resource_setup(cls):
-        cls.set_network_resources()
-        super(TestDashboardBasicOps, cls).resource_setup()
-
         if not CONF.service_available.horizon:
             raise cls.skipException("Horizon support is required")
+        cls.set_network_resources()
+        super(TestDashboardBasicOps, cls).resource_setup()
 
     def check_login_page(self):
         response = urllib2.urlopen(CONF.dashboard.dashboard_url)
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 8a8e387..ead021e 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -16,6 +16,7 @@
 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
 from tempest.scenario import manager
 from tempest import test
@@ -77,9 +78,8 @@
 
     def nova_volume_attach(self):
         volume_device_path = '/dev/' + CONF.compute.volume_device_name
-        _, volume_attachment = self.servers_client.attach_volume(
+        _, volume = self.servers_client.attach_volume(
             self.server['id'], self.volume['id'], volume_device_path)
-        volume = volume_attachment['volumeAttachment']
         self.assertEqual(self.volume['id'], volume['id'])
         self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
         # Refresh the volume after the attachment
@@ -130,6 +130,17 @@
         self.addCleanup(self.servers_client.remove_security_group,
                         self.server['id'], secgroup['name'])
 
+        def wait_for_secgroup_add():
+            _, body = self.servers_client.get_server(self.server['id'])
+            return {'name': secgroup['name']} in body['security_groups']
+
+        if not test.call_until_true(wait_for_secgroup_add,
+                                    CONF.compute.build_timeout,
+                                    CONF.compute.build_interval):
+            msg = ('Timed out waiting for adding security group %s to server '
+                   '%s' % (secgroup['id'], self.server['id']))
+            raise exceptions.TimeoutException(msg)
+
     @test.services('compute', 'volume', 'image', 'network')
     def test_minimum_basic_scenario(self):
         self.glance_image_create()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index ac4f004..e3f87e9 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -89,13 +89,13 @@
 
     @classmethod
     def resource_setup(cls):
-        # Create no network resources for these tests.
-        cls.set_network_resources()
-        super(TestNetworkBasicOps, cls).resource_setup()
         for ext in ['router', 'security-group']:
             if not test.is_extension_enabled(ext, 'network'):
                 msg = "%s extension not enabled." % ext
                 raise cls.skipException(msg)
+        # Create no network resources for these tests.
+        cls.set_network_resources()
+        super(TestNetworkBasicOps, cls).resource_setup()
 
     def setUp(self):
         super(TestNetworkBasicOps, self).setUp()
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 6c36034..6ea3253 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -120,16 +120,6 @@
             cls.enabled = False
             raise cls.skipException(msg)
         super(TestSecurityGroupsBasicOps, cls).check_preconditions()
-        # need alt_creds here to check preconditions
-        cls.alt_creds = cls.alt_credentials()
-        cls.alt_manager = clients.Manager(cls.alt_creds)
-        # Credentials from the manager are filled with both IDs and Names
-        cls.alt_creds = cls.alt_manager.credentials
-        if (cls.alt_creds is None) or \
-                (cls.tenant_id is cls.alt_creds.tenant_id):
-            msg = 'No alt_tenant defined'
-            cls.enabled = False
-            raise cls.skipException(msg)
         if not (CONF.network.tenant_networks_reachable or
                 CONF.network.public_network_id):
             msg = ('Either tenant_networks_reachable must be "true", or '
@@ -144,6 +134,13 @@
         super(TestSecurityGroupsBasicOps, cls).resource_setup()
         # TODO(mnewby) Consider looking up entities as needed instead
         # of storing them as collections on the class.
+
+        # get credentials for secondary tenant
+        cls.alt_creds = cls.isolated_creds.get_alt_creds()
+        cls.alt_manager = clients.Manager(cls.alt_creds)
+        # Credentials from the manager are filled with both IDs and Names
+        cls.alt_creds = cls.alt_manager.credentials
+
         cls.floating_ips = {}
         cls.tenants = {}
         creds = cls.credentials()
@@ -437,6 +434,8 @@
     @test.attr(type='smoke')
     @test.services('compute', 'network')
     def test_cross_tenant_traffic(self):
+        if not self.isolated_creds.is_multi_tenant():
+            raise self.skipException("No secondary tenant defined")
         try:
             # deploy new tenant
             self._deploy_tenant(self.alt_tenant)
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index c53e22b..d10fcce 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -36,12 +36,11 @@
 
     @classmethod
     def resource_setup(cls):
-        cls.set_network_resources()
-        super(TestServerAdvancedOps, cls).resource_setup()
-
         if CONF.compute.flavor_ref_alt == CONF.compute.flavor_ref:
             msg = "Skipping test - flavor_ref and flavor_ref_alt are identical"
             raise cls.skipException(msg)
+        cls.set_network_resources()
+        super(TestServerAdvancedOps, cls).resource_setup()
 
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 8ea2814..e30c824 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -52,10 +52,9 @@
 
     @classmethod
     def resource_setup(cls):
-        super(TestStampPattern, cls).resource_setup()
-
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
+        super(TestStampPattern, cls).resource_setup()
 
     def _wait_for_volume_snapshot_status(self, volume_snapshot, status):
         self.snapshots_client.wait_for_snapshot_status(volume_snapshot['id'],
@@ -115,7 +114,6 @@
         # TODO(andreaf) we should use device from config instead if vdb
         _, attached_volume = self.servers_client.attach_volume(
             server['id'], volume['id'], device='/dev/vdb')
-        attached_volume = attached_volume['volumeAttachment']
         self.assertEqual(volume['id'], attached_volume['id'])
         self._wait_for_volume_status(attached_volume, 'in-use')
 
diff --git a/tempest/scenario/test_swift_basic_ops.py b/tempest/scenario/test_swift_basic_ops.py
index 9e0fee0..fcb9505 100644
--- a/tempest/scenario/test_swift_basic_ops.py
+++ b/tempest/scenario/test_swift_basic_ops.py
@@ -44,9 +44,12 @@
         self.get_swift_stat()
         container_name = self.create_container()
         obj_name, obj_data = self.upload_object_to_container(container_name)
-        self.list_and_check_container_objects(container_name, [obj_name])
+        self.list_and_check_container_objects(container_name,
+                                              present_obj=[obj_name])
         self.download_and_verify(container_name, obj_name, obj_data)
         self.delete_object(container_name, obj_name)
+        self.list_and_check_container_objects(container_name,
+                                              not_present_obj=[obj_name])
         self.delete_container(container_name)
 
     @test.services('object_storage')
@@ -68,5 +71,3 @@
         self.change_container_acl(container_name, '.r:*')
         resp, _ = http_client.request(obj_url, 'GET')
         self.assertEqual(resp.status, 200)
-        self.delete_object(container_name, obj_name)
-        self.delete_container(container_name)
diff --git a/tempest/scenario/test_swift_telemetry_middleware.py b/tempest/scenario/test_swift_telemetry_middleware.py
new file mode 100644
index 0000000..e8eb45c
--- /dev/null
+++ b/tempest/scenario/test_swift_telemetry_middleware.py
@@ -0,0 +1,103 @@
+#
+# Copyright 2014 Red Hat
+#
+# Author: Chris Dent <chdent@redhat.com>
+# 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 import config
+from tempest.openstack.common import log as logging
+from tempest.scenario import manager
+from tempest import test
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+# Loop for up to 120 seconds waiting on notifications
+# NOTE(chdent): The choice of 120 seconds is fairly
+# arbitrary: Long enough to give the notifications the
+# chance to travel across a highly latent bus but not
+# so long as to allow excessive latency to never be visible.
+# TODO(chdent): Ideally this value would come from configuration.
+NOTIFICATIONS_WAIT = 120
+NOTIFICATIONS_SLEEP = 1
+
+
+class TestSwiftTelemetry(manager.SwiftScenarioTest):
+    """
+    Test that swift uses the ceilometer middleware.
+     * create container.
+     * upload a file to the created container.
+     * retrieve the file from the created container.
+     * wait for notifications from ceilometer.
+    """
+
+    @classmethod
+    def resource_setup(cls):
+        if not CONF.service_available.ceilometer:
+            skip_msg = ("%s skipped as ceilometer is not available" %
+                        cls.__name__)
+            raise cls.skipException(skip_msg)
+        elif CONF.telemetry.too_slow_to_test:
+            skip_msg = "Ceilometer feature for fast work mysql is disabled"
+            raise cls.skipException(skip_msg)
+        super(TestSwiftTelemetry, cls).resource_setup()
+        cls.telemetry_client = cls.manager.telemetry_client
+
+    def _confirm_notifications(self, container_name, obj_name):
+        """
+        Loop seeking for appropriate notifications about the containers
+        and objects sent to swift.
+        """
+
+        def _check_samples():
+            """
+            Return True only if we have notifications about some
+            containers and some objects and the notifications are about
+            the expected containers and objects.
+            Otherwise returning False will case _check_samples to be
+            called again.
+            """
+            _, results = self.telemetry_client.list_samples(
+                'storage.api.request')
+            LOG.debug('got samples %s', results)
+
+            # Extract container info from samples.
+            containers = [sample['resource_metadata']['container']
+                          for sample in results
+                          if sample['resource_metadata']['container']
+                          != 'None']
+            # Extract object info from samples.
+            objects = [sample['resource_metadata']['object']
+                       for sample in results
+                       if sample['resource_metadata']['object'] != 'None']
+
+            return (containers
+                    and objects
+                    and container_name in containers
+                    and obj_name in objects)
+
+        self.assertTrue(test.call_until_true(_check_samples,
+                                             NOTIFICATIONS_WAIT,
+                                             NOTIFICATIONS_SLEEP),
+                        'Correct notifications were not received after '
+                        '%s seconds.' % NOTIFICATIONS_WAIT)
+
+    @test.services('object_storage', 'telemetry')
+    def test_swift_middleware_notifies(self):
+        container_name = self.create_container()
+        obj_name, _ = self.upload_object_to_container(container_name)
+        self._confirm_notifications(container_name, obj_name)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index a20db5c..62876c4 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -37,10 +37,9 @@
     """
     @classmethod
     def resource_setup(cls):
-        super(TestVolumeBootPattern, cls).resource_setup()
-
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
+        super(TestVolumeBootPattern, cls).resource_setup()
 
     def _create_volume_from_image(self):
         img_uuid = CONF.compute.image_ref
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index c20f20c..e6624a3 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -25,6 +25,7 @@
 from tempest import clients
 from tempest.common.utils import misc
 from tempest import config
+from tempest import exceptions
 
 CONF = config.CONF
 
@@ -151,9 +152,12 @@
         loader, standard_tests, pattern = args
     else:
         standard_tests, module, loader = args
-    scenario_utils = InputScenarioUtils()
-    scenario_flavor = scenario_utils.scenario_flavors
-    scenario_image = scenario_utils.scenario_images
+    try:
+        scenario_utils = InputScenarioUtils()
+        scenario_flavor = scenario_utils.scenario_flavors
+        scenario_image = scenario_utils.scenario_images
+    except exceptions.InvalidConfiguration:
+        return standard_tests
     for test in testtools.iterate_tests(standard_tests):
         setattr(test, 'scenarios', testscenarios.multiply_scenarios(
             scenario_image,
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 947ba7a..4268b1a 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -369,7 +369,7 @@
                                post_body)
         body = json.loads(body)
         self.validate_response(schema.attach_volume, resp, body)
-        return resp, body
+        return resp, body['volumeAttachment']
 
     def detach_volume(self, server_id, volume_id):
         """Detaches a volume from a server instance."""
@@ -378,6 +378,22 @@
         self.validate_response(schema.detach_volume, resp, body)
         return resp, body
 
+    def get_volume_attachment(self, server_id, attach_id):
+        """Return details about the given volume attachment."""
+        resp, body = self.get('servers/%s/os-volume_attachments/%s' % (
+            str(server_id), attach_id))
+        body = json.loads(body)
+        self.validate_response(schema.get_volume_attachment, resp, body)
+        return resp, body['volumeAttachment']
+
+    def list_volume_attachments(self, server_id):
+        """Returns the list of volume attachments for a given instance."""
+        resp, body = self.get('servers/%s/os-volume_attachments' % (
+            str(server_id)))
+        body = json.loads(body)
+        self.validate_response(schema.list_volume_attachments, resp, body)
+        return resp, body['volumeAttachments']
+
     def add_security_group(self, server_id, name):
         """Adds a security group to the server."""
         return self.action(server_id, 'addSecurityGroup', None, name=name)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 78ed56f..46475f0 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -85,8 +85,14 @@
         update_body['admin_state_up'] = kwargs.get(
             'admin_state_up', body['router']['admin_state_up'])
         cur_gw_info = body['router']['external_gateway_info']
-        if cur_gw_info and not set_enable_snat:
-            cur_gw_info.pop('enable_snat', None)
+        if cur_gw_info:
+            # TODO(kevinbenton): setting the external gateway info is not
+            # allowed for a regular tenant. If the ability to update is also
+            # merged, a test case for this will need to be added similar to
+            # the SNAT case.
+            cur_gw_info.pop('external_fixed_ips', None)
+            if not set_enable_snat:
+                cur_gw_info.pop('enable_snat', None)
         update_body['external_gateway_info'] = kwargs.get(
             'external_gateway_info', body['router']['external_gateway_info'])
         update_body = dict(router=update_body)
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index 4dc588f..4417e3b 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -52,6 +52,7 @@
             headers[remove_metadata_prefix + key] = remove_metadata[key]
 
         resp, body = self.put(url, data, headers)
+        self.expected_success(200, resp.status)
         return resp, body
 
     def delete_account(self, data=None, params=None):
@@ -61,6 +62,7 @@
             url = '?%s%s' % (url, urllib.urlencode(params))
 
         resp, body = self.delete(url, headers={}, body=data)
+        self.expected_success(200, resp.status)
         return resp, body
 
     def list_account_metadata(self):
@@ -69,6 +71,7 @@
         Returns all account metadata headers
         """
         resp, body = self.head('')
+        self.expected_success(204, resp.status)
         return resp, body
 
     def create_account_metadata(self, metadata,
@@ -85,6 +88,7 @@
             url = '?%s%s' % (url, urllib.urlencode(params))
 
         resp, body = self.post(url, headers=headers, body=data)
+        self.expected_success([200, 204], resp.status)
         return resp, body
 
     def delete_account_metadata(self, metadata,
@@ -97,6 +101,7 @@
         for item in metadata:
             headers[metadata_prefix + item] = metadata[item]
         resp, body = self.post('', headers=headers, body=None)
+        self.expected_success(204, resp.status)
         return resp, body
 
     def create_and_delete_account_metadata(
@@ -115,6 +120,7 @@
             headers[delete_metadata_prefix + key] = delete_metadata[key]
 
         resp, body = self.post('', headers=headers, body=None)
+        self.expected_success(204, resp.status)
         return resp, body
 
     def list_account_containers(self, params=None):
@@ -147,6 +153,7 @@
             body = etree.fromstring(body)
         else:
             body = body.strip().splitlines()
+        self.expected_success([200, 204], resp.status)
         return resp, body
 
     def list_extensions(self):
@@ -156,6 +163,7 @@
         finally:
             self.reset_path()
         body = json.loads(body)
+        self.expected_success(200, resp.status)
         return resp, body
 
 
@@ -222,7 +230,7 @@
 
         url = '?format=%s' % self.format
         if params:
-            url += '&%s' + urllib.urlencode(params)
+            url += '&%s' % urllib.urlencode(params)
 
         headers = {}
         if metadata:
@@ -230,4 +238,5 @@
                 headers[str(key)] = metadata[key]
 
         resp, body = self.get(url, headers=headers)
+        self.expected_success(200, resp.status)
         return resp, body
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index ffc1326..182c4d0 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -53,12 +53,14 @@
                 headers[remove_metadata_prefix + key] = remove_metadata[key]
 
         resp, body = self.put(url, body=None, headers=headers)
+        self.expected_success([201, 202], resp.status)
         return resp, body
 
     def delete_container(self, container_name):
         """Deletes the container (if it's empty)."""
         url = str(container_name)
         resp, body = self.delete(url)
+        self.expected_success(204, resp.status)
         return resp, body
 
     def update_container_metadata(
@@ -79,6 +81,7 @@
                 headers[remove_metadata_prefix + key] = remove_metadata[key]
 
         resp, body = self.post(url, body=None, headers=headers)
+        self.expected_success(204, resp.status)
         return resp, body
 
     def delete_container_metadata(self, container_name, metadata,
@@ -92,6 +95,7 @@
                 headers[metadata_prefix + item] = metadata[item]
 
         resp, body = self.post(url, body=None, headers=headers)
+        self.expected_success(204, resp.status)
         return resp, body
 
     def list_container_metadata(self, container_name):
@@ -100,6 +104,7 @@
         """
         url = str(container_name)
         resp, body = self.head(url)
+        self.expected_success(204, resp.status)
         return resp, body
 
     def list_all_container_objects(self, container, params=None):
@@ -121,6 +126,7 @@
         resp, objlist = self.list_container_contents(
             container,
             params={'limit': limit, 'format': 'json'})
+        self.expected_success(200, resp.status)
         return objlist
         """tmp = []
         for obj in objlist:
@@ -186,4 +192,5 @@
             body = json.loads(body)
         elif params and params.get('format') == 'xml':
             body = etree.fromstring(body)
+        self.expected_success([200, 204], resp.status)
         return resp, body
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index b2f8205..2231407 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -46,11 +46,14 @@
             url += '?%s' % urllib.urlencode(params)
 
         resp, body = self.put(url, data, headers)
+        self.expected_success(201, resp.status)
         return resp, body
 
     def update_object(self, container, object_name, data):
         """Upload data to replace current storage object."""
-        return self.create_object(container, object_name, data)
+        resp, body = self.create_object(container, object_name, data)
+        self.expected_success(201, resp.status)
+        return resp, body
 
     def delete_object(self, container, object_name, params=None):
         """Delete storage object."""
@@ -58,6 +61,7 @@
         if params:
             url += '?%s' % urllib.urlencode(params)
         resp, body = self.delete(url, headers={})
+        self.expected_success([200, 204], resp.status)
         return resp, body
 
     def update_object_metadata(self, container, object_name, metadata,
@@ -70,6 +74,7 @@
 
         url = "%s/%s" % (str(container), str(object_name))
         resp, body = self.post(url, None, headers=headers)
+        self.expected_success(202, resp.status)
         return resp, body
 
     def list_object_metadata(self, container, object_name):
@@ -77,6 +82,7 @@
 
         url = "%s/%s" % (str(container), str(object_name))
         resp, body = self.head(url)
+        self.expected_success(200, resp.status)
         return resp, body
 
     def get_object(self, container, object_name, metadata=None):
@@ -89,6 +95,7 @@
 
         url = "{0}/{1}".format(container, object_name)
         resp, body = self.get(url, headers=headers)
+        self.expected_success([200, 206], resp.status)
         return resp, body
 
     def copy_object_in_same_container(self, container, src_object_name,
@@ -105,6 +112,7 @@
                 headers[str(key)] = metadata[key]
 
         resp, body = self.put(url, None, headers=headers)
+        self.expected_success(201, resp.status)
         return resp, body
 
     def copy_object_across_containers(self, src_container, src_object_name,
@@ -122,6 +130,7 @@
                 headers[str(key)] = metadata[key]
 
         resp, body = self.put(url, None, headers=headers)
+        self.expected_success(201, resp.status)
         return resp, body
 
     def copy_object_2d_way(self, container, src_object_name, dest_object_name,
@@ -137,12 +146,14 @@
                 headers[str(key)] = metadata[key]
 
         resp, body = self.copy(url, headers=headers)
+        self.expected_success(201, resp.status)
         return resp, body
 
     def create_object_segments(self, container, object_name, segment, data):
         """Creates object segments."""
         url = "{0}/{1}/{2}".format(container, object_name, segment)
         resp, body = self.put(url, data)
+        self.expected_success(201, resp.status)
         return resp, body
 
     def put_object_with_chunk(self, container, name, contents, chunk_size):
@@ -167,7 +178,7 @@
             resp_headers[header.lower()] = value
 
         self._error_checker('PUT', None, headers, contents, resp, body)
-
+        self.expected_success(201, resp.status)
         return resp.status, resp.reason, resp_headers
 
 
@@ -220,6 +231,7 @@
 
         url = "{0}/{1}".format(container, object_name)
         resp, body = self.get(url, headers=headers)
+        self.expected_success(200, resp.status)
         return resp, body
 
     def create_object(self, container, object_name, data, metadata=None):
@@ -234,6 +246,7 @@
             headers['content-length'] = '0'
         url = "%s/%s" % (str(container), str(object_name))
         resp, body = self.put(url, data, headers=headers)
+        self.expected_success(201, resp.status)
         return resp, body
 
     def delete_object(self, container, object_name, metadata=None):
@@ -246,6 +259,7 @@
 
         url = "%s/%s" % (str(container), str(object_name))
         resp, body = self.delete(url, headers=headers)
+        self.expected_success(200, resp.status)
         return resp, body
 
     def create_object_continue(self, container, object_name,
diff --git a/tempest/services/volume/json/admin/volume_hosts_client.py b/tempest/services/volume/json/admin/volume_hosts_client.py
index b3a22b5..10cb0be 100644
--- a/tempest/services/volume/json/admin/volume_hosts_client.py
+++ b/tempest/services/volume/json/admin/volume_hosts_client.py
@@ -22,13 +22,13 @@
 CONF = config.CONF
 
 
-class VolumeHostsClientJSON(rest_client.RestClient):
+class BaseVolumeHostsClientJSON(rest_client.RestClient):
     """
     Client class to send CRUD Volume Hosts API requests to a Cinder endpoint
     """
 
     def __init__(self, auth_provider):
-        super(VolumeHostsClientJSON, self).__init__(auth_provider)
+        super(BaseVolumeHostsClientJSON, self).__init__(auth_provider)
 
         self.service = CONF.volume.catalog_type
         self.build_interval = CONF.volume.build_interval
@@ -45,3 +45,9 @@
         body = json.loads(body)
         self.expected_success(200, resp.status)
         return resp, body['hosts']
+
+
+class VolumeHostsClientJSON(BaseVolumeHostsClientJSON):
+    """
+    Client class to send CRUD Volume Host API V1 requests to a Cinder endpoint
+    """
diff --git a/tempest/services/volume/v2/json/admin/volume_hosts_client.py b/tempest/services/volume/v2/json/admin/volume_hosts_client.py
new file mode 100644
index 0000000..d631570
--- /dev/null
+++ b/tempest/services/volume/v2/json/admin/volume_hosts_client.py
@@ -0,0 +1,28 @@
+# Copyright 2014 OpenStack Foundation
+# 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.services.volume.json.admin import volume_hosts_client
+
+
+class VolumeHostsV2ClientJSON(volume_hosts_client.BaseVolumeHostsClientJSON):
+    """
+    Client class to send CRUD Volume V2 API requests to a Cinder endpoint
+    """
+
+    def __init__(self, auth_provider):
+        super(VolumeHostsV2ClientJSON, self).__init__(auth_provider)
+
+        self.api_version = "v2"
diff --git a/tempest/services/volume/xml/admin/volume_hosts_client.py b/tempest/services/volume/xml/admin/volume_hosts_client.py
index 98a7c58..583b2c5 100644
--- a/tempest/services/volume/xml/admin/volume_hosts_client.py
+++ b/tempest/services/volume/xml/admin/volume_hosts_client.py
@@ -24,14 +24,14 @@
 CONF = config.CONF
 
 
-class VolumeHostsClientXML(rest_client.RestClient):
+class BaseVolumeHostsClientXML(rest_client.RestClient):
     """
     Client class to send CRUD Volume Hosts API requests to a Cinder endpoint
     """
     TYPE = "xml"
 
     def __init__(self, auth_provider):
-        super(VolumeHostsClientXML, self).__init__(auth_provider)
+        super(BaseVolumeHostsClientXML, self).__init__(auth_provider)
         self.service = CONF.volume.catalog_type
         self.build_interval = CONF.compute.build_interval
         self.build_timeout = CONF.compute.build_timeout
@@ -72,3 +72,9 @@
         self.expected_success(200, resp.status)
         body = self._parse_array(etree.fromstring(body))
         return resp, body
+
+
+class VolumeHostsClientXML(BaseVolumeHostsClientXML):
+    """
+    Client class to send CRUD Volume Host API V1 requests to a Cinder endpoint
+    """
diff --git a/tempest/services/volume/xml/admin/volume_types_client.py b/tempest/services/volume/xml/admin/volume_types_client.py
index 2464016..03d39a8 100644
--- a/tempest/services/volume/xml/admin/volume_types_client.py
+++ b/tempest/services/volume/xml/admin/volume_types_client.py
@@ -25,14 +25,14 @@
 CONF = config.CONF
 
 
-class VolumeTypesClientXML(rest_client.RestClient):
+class BaseVolumeTypesClientXML(rest_client.RestClient):
     """
     Client class to send CRUD Volume Types API requests to a Cinder endpoint
     """
     TYPE = "xml"
 
     def __init__(self, auth_provider):
-        super(VolumeTypesClientXML, self).__init__(auth_provider)
+        super(BaseVolumeTypesClientXML, self).__init__(auth_provider)
         self.service = CONF.volume.catalog_type
         self.build_interval = CONF.compute.build_interval
         self.build_timeout = CONF.compute.build_timeout
@@ -210,3 +210,9 @@
     def resource_type(self):
         """Returns the primary type of resource this client works with."""
         return 'volume-type'
+
+
+class VolumeTypesClientXML(BaseVolumeTypesClientXML):
+    """
+    Client class to send CRUD Volume Type API V1 requests to a Cinder endpoint
+    """
diff --git a/tempest/test.py b/tempest/test.py
index 1c6265d..14cf3bb 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -24,7 +24,6 @@
 import uuid
 
 import fixtures
-import testresources
 import testscenarios
 import testtools
 
@@ -222,23 +221,9 @@
 
 atexit.register(validate_tearDownClass)
 
-if sys.version_info >= (2, 7):
-    class BaseDeps(testtools.TestCase,
-                   testtools.testcase.WithAttributes,
-                   testresources.ResourcedTestCase):
-        pass
-else:
-    # Define asserts for py26
-    import unittest2
 
-    class BaseDeps(testtools.TestCase,
-                   testtools.testcase.WithAttributes,
-                   testresources.ResourcedTestCase,
-                   unittest2.TestCase):
-        pass
-
-
-class BaseTestCase(BaseDeps):
+class BaseTestCase(testtools.testcase.WithAttributes,
+                   testtools.TestCase):
 
     setUpClassCalled = False
     _service = None
@@ -342,10 +327,12 @@
         """
         force_tenant_isolation = getattr(cls, 'force_tenant_isolation', None)
 
-        cls.isolated_creds = credentials.get_isolated_credentials(
-            name=cls.__name__, network_resources=cls.network_resources,
-            force_tenant_isolation=force_tenant_isolation,
-        )
+        if (not hasattr(cls, 'isolated_creds') or
+            not cls.isolated_creds.name == cls.__name__):
+            cls.isolated_creds = credentials.get_isolated_credentials(
+                name=cls.__name__, network_resources=cls.network_resources,
+                force_tenant_isolation=force_tenant_isolation,
+            )
 
         creds = cls.isolated_creds.get_primary_creds()
         params = dict(credentials=creds, service=cls._service)
diff --git a/tempest/tests/cli/test_cli.py b/tempest/tests/cli/test_cli.py
index 1fd5ccb..8f18dfc 100644
--- a/tempest/tests/cli/test_cli.py
+++ b/tempest/tests/cli/test_cli.py
@@ -13,17 +13,25 @@
 #    under the License.
 
 import mock
+from tempest_lib.cli import base as cli_base
 import testtools
 
 from tempest import cli
+from tempest import config
 from tempest import exceptions
 from tempest.tests import base
+from tempest.tests import fake_config
 
 
 class TestMinClientVersion(base.TestCase):
     """Tests for the min_client_version decorator.
     """
 
+    def setUp(self):
+        super(TestMinClientVersion, self).setUp()
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+
     def _test_min_version(self, required, installed, expect_skip):
 
         @cli.min_client_version(client='nova', version=required)
@@ -33,7 +41,7 @@
                 # expected so we need to fail.
                 self.fail('Should not have gotten past the decorator.')
 
-        with mock.patch.object(cli, 'execute',
+        with mock.patch.object(cli_base, 'execute',
                                return_value=installed) as mock_cmd:
             if expect_skip:
                 self.assertRaises(testtools.TestCase.skipException, fake,
@@ -41,6 +49,7 @@
             else:
                 fake(self, expect_skip)
             mock_cmd.assert_called_once_with('nova', '', params='--version',
+                                             cli_dir='/usr/local/bin',
                                              merge_stderr=True)
 
     def test_min_client_version(self):
@@ -52,7 +61,7 @@
         for case in cases:
             self._test_min_version(*case)
 
-    @mock.patch.object(cli, 'execute', return_value=' ')
+    @mock.patch.object(cli_base, 'execute', return_value=' ')
     def test_check_client_version_empty_output(self, mock_execute):
         # Tests that an exception is raised if the command output is empty.
         self.assertRaises(exceptions.TempestException,
diff --git a/tempest/tests/cli/test_command_failed.py b/tempest/tests/cli/test_command_failed.py
deleted file mode 100644
index 36a4fc8..0000000
--- a/tempest/tests/cli/test_command_failed.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#    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 import exceptions
-from tempest.tests import base
-
-
-class TestOutputParser(base.TestCase):
-
-    def test_command_failed_exception(self):
-        returncode = 1
-        cmd = "foo"
-        stdout = "output"
-        stderr = "error"
-        try:
-            raise exceptions.CommandFailed(returncode, cmd, stdout, stderr)
-        except exceptions.CommandFailed as e:
-            self.assertIn(str(returncode), str(e))
-            self.assertIn(cmd, str(e))
-            self.assertIn(stdout, str(e))
-            self.assertIn(stderr, str(e))
diff --git a/tempest/tests/cli/test_output_parser.py b/tempest/tests/cli/test_output_parser.py
deleted file mode 100644
index 7ad270c..0000000
--- a/tempest/tests/cli/test_output_parser.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# Copyright 2014 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.cli import output_parser
-from tempest import exceptions
-from tempest.tests import base
-
-
-class TestOutputParser(base.TestCase):
-    OUTPUT_LINES = """
-+----+------+---------+
-| ID | Name | Status  |
-+----+------+---------+
-| 11 | foo  | BUILD   |
-| 21 | bar  | ERROR   |
-| 31 | bee  | None    |
-+----+------+---------+
-"""
-    OUTPUT_LINES2 = """
-+----+-------+---------+
-| ID | Name2 | Status2 |
-+----+-------+---------+
-| 41 | aaa   | SSSSS   |
-| 51 | bbb   | TTTTT   |
-| 61 | ccc   | AAAAA   |
-+----+-------+---------+
-"""
-
-    EXPECTED_TABLE = {'headers': ['ID', 'Name', 'Status'],
-                      'values': [['11', 'foo', 'BUILD'],
-                                 ['21', 'bar', 'ERROR'],
-                                 ['31', 'bee', 'None']]}
-    EXPECTED_TABLE2 = {'headers': ['ID', 'Name2', 'Status2'],
-                       'values': [['41', 'aaa', 'SSSSS'],
-                                  ['51', 'bbb', 'TTTTT'],
-                                  ['61', 'ccc', 'AAAAA']]}
-
-    def test_table_with_normal_values(self):
-        actual = output_parser.table(self.OUTPUT_LINES)
-        self.assertIsInstance(actual, dict)
-        self.assertEqual(self.EXPECTED_TABLE, actual)
-
-    def test_table_with_list(self):
-        output_lines = self.OUTPUT_LINES.split('\n')
-        actual = output_parser.table(output_lines)
-        self.assertIsInstance(actual, dict)
-        self.assertEqual(self.EXPECTED_TABLE, actual)
-
-    def test_table_with_invalid_line(self):
-        output_lines = self.OUTPUT_LINES + "aaaa"
-        actual = output_parser.table(output_lines)
-        self.assertIsInstance(actual, dict)
-        self.assertEqual(self.EXPECTED_TABLE, actual)
-
-    def test_tables_with_normal_values(self):
-        output_lines = 'test' + self.OUTPUT_LINES +\
-                       'test2' + self.OUTPUT_LINES2
-        expected = [{'headers': self.EXPECTED_TABLE['headers'],
-                     'label': 'test',
-                     'values': self.EXPECTED_TABLE['values']},
-                    {'headers': self.EXPECTED_TABLE2['headers'],
-                     'label': 'test2',
-                     'values': self.EXPECTED_TABLE2['values']}]
-        actual = output_parser.tables(output_lines)
-        self.assertIsInstance(actual, list)
-        self.assertEqual(expected, actual)
-
-    def test_tables_with_invalid_values(self):
-        output_lines = 'test' + self.OUTPUT_LINES +\
-                       'test2' + self.OUTPUT_LINES2 + '\n'
-        expected = [{'headers': self.EXPECTED_TABLE['headers'],
-                     'label': 'test',
-                     'values': self.EXPECTED_TABLE['values']},
-                    {'headers': self.EXPECTED_TABLE2['headers'],
-                     'label': 'test2',
-                     'values': self.EXPECTED_TABLE2['values']}]
-        actual = output_parser.tables(output_lines)
-        self.assertIsInstance(actual, list)
-        self.assertEqual(expected, actual)
-
-    def test_tables_with_invalid_line(self):
-        output_lines = 'test' + self.OUTPUT_LINES +\
-                       'test2' + self.OUTPUT_LINES2 +\
-                       '+----+-------+---------+'
-        expected = [{'headers': self.EXPECTED_TABLE['headers'],
-                     'label': 'test',
-                     'values': self.EXPECTED_TABLE['values']},
-                    {'headers': self.EXPECTED_TABLE2['headers'],
-                     'label': 'test2',
-                     'values': self.EXPECTED_TABLE2['values']}]
-
-        actual = output_parser.tables(output_lines)
-        self.assertIsInstance(actual, list)
-        self.assertEqual(expected, actual)
-
-    LISTING_OUTPUT = """
-+----+
-| ID |
-+----+
-| 11 |
-| 21 |
-| 31 |
-+----+
-"""
-
-    def test_listing(self):
-        expected = [{'ID': '11'}, {'ID': '21'}, {'ID': '31'}]
-        actual = output_parser.listing(self.LISTING_OUTPUT)
-        self.assertIsInstance(actual, list)
-        self.assertEqual(expected, actual)
-
-    def test_details_multiple_with_invalid_line(self):
-        self.assertRaises(exceptions.InvalidStructure,
-                          output_parser.details_multiple,
-                          self.OUTPUT_LINES)
-
-    DETAILS_LINES1 = """First Table
-+----------+--------+
-| Property | Value  |
-+----------+--------+
-| foo      | BUILD  |
-| bar      | ERROR  |
-| bee      | None   |
-+----------+--------+
-"""
-    DETAILS_LINES2 = """Second Table
-+----------+--------+
-| Property | Value  |
-+----------+--------+
-| aaa      | VVVVV  |
-| bbb      | WWWWW  |
-| ccc      | XXXXX  |
-+----------+--------+
-"""
-
-    def test_details_with_normal_line_label_false(self):
-        expected = {'foo': 'BUILD', 'bar': 'ERROR', 'bee': 'None'}
-        actual = output_parser.details(self.DETAILS_LINES1)
-        self.assertEqual(expected, actual)
-
-    def test_details_with_normal_line_label_true(self):
-        expected = {'__label': 'First Table',
-                    'foo': 'BUILD', 'bar': 'ERROR', 'bee': 'None'}
-        actual = output_parser.details(self.DETAILS_LINES1, with_label=True)
-        self.assertEqual(expected, actual)
-
-    def test_details_multiple_with_normal_line_label_false(self):
-        expected = [{'foo': 'BUILD', 'bar': 'ERROR', 'bee': 'None'},
-                    {'aaa': 'VVVVV', 'bbb': 'WWWWW', 'ccc': 'XXXXX'}]
-        actual = output_parser.details_multiple(self.DETAILS_LINES1 +
-                                                self.DETAILS_LINES2)
-        self.assertIsInstance(actual, list)
-        self.assertEqual(expected, actual)
-
-    def test_details_multiple_with_normal_line_label_true(self):
-        expected = [{'__label': 'First Table',
-                     'foo': 'BUILD', 'bar': 'ERROR', 'bee': 'None'},
-                    {'__label': 'Second Table',
-                     'aaa': 'VVVVV', 'bbb': 'WWWWW', 'ccc': 'XXXXX'}]
-        actual = output_parser.details_multiple(self.DETAILS_LINES1 +
-                                                self.DETAILS_LINES2,
-                                                with_label=True)
-        self.assertIsInstance(actual, list)
-        self.assertEqual(expected, actual)
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index 0db4cfa..e8650c5 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -117,7 +117,7 @@
 
         self.assertEqual(self.conn.get_mac_address(), macs)
         self._assert_exec_called_with(
-            "/sbin/ifconfig | awk '/HWaddr/ {print $5}'")
+            "/bin/ip addr | awk '/ether/ {print $2}'")
 
     def test_get_ip_list(self):
         ips = """1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue
diff --git a/tempest/tests/stress/test_stress.py b/tempest/tests/stress/test_stress.py
index 5a93472..9c3533d 100644
--- a/tempest/tests/stress/test_stress.py
+++ b/tempest/tests/stress/test_stress.py
@@ -16,7 +16,8 @@
 import shlex
 import subprocess
 
-import tempest.exceptions as exceptions
+from tempest_lib import exceptions
+
 from tempest.openstack.common import log as logging
 from tempest.tests import base
 
diff --git a/tempest/tests/test_list_tests.py b/tempest/tests/test_list_tests.py
index 157fc5f..efdb413 100644
--- a/tempest/tests/test_list_tests.py
+++ b/tempest/tests/test_list_tests.py
@@ -12,6 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import os
 import re
 import subprocess
 
@@ -20,16 +21,23 @@
 
 class TestTestList(base.TestCase):
 
-    def test_no_import_errors(self):
+    def test_testr_list_tests_no_errors(self):
+        # Remove unit test discover path from env to test tempest tests
+        test_env = os.environ.copy()
+        test_env.pop('OS_TEST_PATH')
         import_failures = []
-        p = subprocess.Popen(['testr', 'list-tests'], stdout=subprocess.PIPE)
-        ids = p.stdout.read()
+        p = subprocess.Popen(['testr', 'list-tests'], stdout=subprocess.PIPE,
+                             env=test_env)
+        ids, err = p.communicate()
+        self.assertEqual(0, p.returncode,
+                         "test discovery failed, one or more files cause an "
+                         "error on import")
         ids = ids.split('\n')
         for test_id in ids:
             if re.match('(\w+\.){3}\w+', test_id):
                 if not test_id.startswith('tempest.'):
-                    fail_id = test_id.split('unittest.loader.ModuleImport'
-                                            'Failure.')[1]
+                    parts = test_id.partition('tempest')
+                    fail_id = parts[1] + parts[2]
                     import_failures.append(fail_id)
         error_message = ("The following tests have import failures and aren't"
                          " being run with test filters %s" % import_failures)
diff --git a/tempest/tests/test_wrappers.py b/tempest/tests/test_wrappers.py
index 0fd41f9..ae7860d 100644
--- a/tempest/tests/test_wrappers.py
+++ b/tempest/tests/test_wrappers.py
@@ -34,7 +34,6 @@
         # Setup Test files
         self.testr_conf_file = os.path.join(self.directory, '.testr.conf')
         self.setup_cfg_file = os.path.join(self.directory, 'setup.cfg')
-        self.subunit_trace = os.path.join(self.directory, 'subunit-trace.py')
         self.passing_file = os.path.join(self.test_dir, 'test_passing.py')
         self.failing_file = os.path.join(self.test_dir, 'test_failing.py')
         self.init_file = os.path.join(self.test_dir, '__init__.py')
@@ -45,7 +44,6 @@
         shutil.copy('setup.py', self.setup_py)
         shutil.copy('tempest/tests/files/setup.cfg', self.setup_cfg_file)
         shutil.copy('tempest/tests/files/__init__.py', self.init_file)
-        shutil.copy('tools/subunit-trace.py', self.subunit_trace)
         # copy over the pretty_tox scripts
         shutil.copy('tools/pretty_tox.sh',
                     os.path.join(self.directory, 'pretty_tox.sh'))
diff --git a/test-requirements.txt b/test-requirements.txt
index ba70259..6eefeee 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -3,11 +3,11 @@
 # process, which may cause wedges in the gate later.
 hacking>=0.9.2,<0.10
 # needed for doc build
-sphinx>=1.1.2,!=1.2.0,<1.3
+sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
 python-subunit>=0.0.18
 oslosphinx>=2.2.0  # Apache-2.0
 mox>=0.5.3
 mock>=1.0
 coverage>=3.6
-oslotest>=1.1.0  # Apache-2.0
-stevedore>=1.0.0  # Apache-2.0
+oslotest>=1.2.0  # Apache-2.0
+stevedore>=1.1.0  # Apache-2.0
diff --git a/tools/check_logs.py b/tools/check_logs.py
index 7cf9d85..c8d3a1a 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -31,7 +31,7 @@
 is_grenade = os.environ.get('DEVSTACK_GATE_GRENADE') is not None
 dump_all_errors = True
 
-# As logs are made clean, add to this set
+# As logs are made clean, remove from this set
 allowed_dirty = set([
     'c-api',
     'ceilometer-acentral',
diff --git a/tools/pretty_tox.sh b/tools/pretty_tox.sh
index 0a04ce6..ff554c5 100755
--- a/tools/pretty_tox.sh
+++ b/tools/pretty_tox.sh
@@ -3,4 +3,4 @@
 set -o pipefail
 
 TESTRARGS=$1
-python setup.py testr --slowest --testr-args="--subunit $TESTRARGS" | $(dirname $0)/subunit-trace.py --no-failure-debug -f
+python setup.py testr --slowest --testr-args="--subunit $TESTRARGS" | subunit-trace --no-failure-debug -f
diff --git a/tools/pretty_tox_serial.sh b/tools/pretty_tox_serial.sh
index db70890..e0fca0f 100755
--- a/tools/pretty_tox_serial.sh
+++ b/tools/pretty_tox_serial.sh
@@ -7,7 +7,7 @@
 if [ ! -d .testrepository ]; then
     testr init
 fi
-testr run --subunit $TESTRARGS | $(dirname $0)/subunit-trace.py -f -n
+testr run --subunit $TESTRARGS | subunit-trace -f -n
 retval=$?
 testr slowest
 
diff --git a/tools/subunit-trace.py b/tools/subunit-trace.py
deleted file mode 100755
index 57e58f2..0000000
--- a/tools/subunit-trace.py
+++ /dev/null
@@ -1,247 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright 2014 Hewlett-Packard Development Company, L.P.
-# Copyright 2014 Samsung Electronics
-# 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.
-
-"""Trace a subunit stream in reasonable detail and high accuracy."""
-
-import argparse
-import functools
-import re
-import sys
-
-import subunit
-import testtools
-
-DAY_SECONDS = 60 * 60 * 24
-FAILS = []
-RESULTS = {}
-
-
-def cleanup_test_name(name, strip_tags=True, strip_scenarios=False):
-    """Clean up the test name for display.
-
-    By default we strip out the tags in the test because they don't help us
-    in identifying the test that is run to it's result.
-
-    Make it possible to strip out the testscenarios information (not to
-    be confused with tempest scenarios) however that's often needed to
-    indentify generated negative tests.
-    """
-    if strip_tags:
-        tags_start = name.find('[')
-        tags_end = name.find(']')
-        if tags_start > 0 and tags_end > tags_start:
-            newname = name[:tags_start]
-            newname += name[tags_end + 1:]
-            name = newname
-
-    if strip_scenarios:
-        tags_start = name.find('(')
-        tags_end = name.find(')')
-        if tags_start > 0 and tags_end > tags_start:
-            newname = name[:tags_start]
-            newname += name[tags_end + 1:]
-            name = newname
-
-    return name
-
-
-def get_duration(timestamps):
-    start, end = timestamps
-    if not start or not end:
-        duration = ''
-    else:
-        delta = end - start
-        duration = '%d.%06ds' % (
-            delta.days * DAY_SECONDS + delta.seconds, delta.microseconds)
-    return duration
-
-
-def find_worker(test):
-    for tag in test['tags']:
-        if tag.startswith('worker-'):
-            return int(tag[7:])
-    return 'NaN'
-
-
-# Print out stdout/stderr if it exists, always
-def print_attachments(stream, test, all_channels=False):
-    """Print out subunit attachments.
-
-    Print out subunit attachments that contain content. This
-    runs in 2 modes, one for successes where we print out just stdout
-    and stderr, and an override that dumps all the attachments.
-    """
-    channels = ('stdout', 'stderr')
-    for name, detail in test['details'].items():
-        # NOTE(sdague): the subunit names are a little crazy, and actually
-        # are in the form pythonlogging:'' (with the colon and quotes)
-        name = name.split(':')[0]
-        if detail.content_type.type == 'test':
-            detail.content_type.type = 'text'
-        if (all_channels or name in channels) and detail.as_text():
-            title = "Captured %s:" % name
-            stream.write("\n%s\n%s\n" % (title, ('~' * len(title))))
-            # indent attachment lines 4 spaces to make them visually
-            # offset
-            for line in detail.as_text().split('\n'):
-                stream.write("    %s\n" % line)
-
-
-def show_outcome(stream, test, print_failures=False):
-    global RESULTS
-    status = test['status']
-    # TODO(sdague): ask lifeless why on this?
-    if status == 'exists':
-        return
-
-    worker = find_worker(test)
-    name = cleanup_test_name(test['id'])
-    duration = get_duration(test['timestamps'])
-
-    if worker not in RESULTS:
-        RESULTS[worker] = []
-    RESULTS[worker].append(test)
-
-    # don't count the end of the return code as a fail
-    if name == 'process-returncode':
-        return
-
-    if status == 'success':
-        stream.write('{%s} %s [%s] ... ok\n' % (
-            worker, name, duration))
-        print_attachments(stream, test)
-    elif status == 'fail':
-        FAILS.append(test)
-        stream.write('{%s} %s [%s] ... FAILED\n' % (
-            worker, name, duration))
-        if not print_failures:
-            print_attachments(stream, test, all_channels=True)
-    elif status == 'skip':
-        stream.write('{%s} %s ... SKIPPED: %s\n' % (
-            worker, name, test['details']['reason'].as_text()))
-    else:
-        stream.write('{%s} %s [%s] ... %s\n' % (
-            worker, name, duration, test['status']))
-        if not print_failures:
-            print_attachments(stream, test, all_channels=True)
-
-    stream.flush()
-
-
-def print_fails(stream):
-    """Print summary failure report.
-
-    Currently unused, however there remains debate on inline vs. at end
-    reporting, so leave the utility function for later use.
-    """
-    if not FAILS:
-        return
-    stream.write("\n==============================\n")
-    stream.write("Failed %s tests - output below:" % len(FAILS))
-    stream.write("\n==============================\n")
-    for f in FAILS:
-        stream.write("\n%s\n" % f['id'])
-        stream.write("%s\n" % ('-' * len(f['id'])))
-        print_attachments(stream, f, all_channels=True)
-    stream.write('\n')
-
-
-def count_tests(key, value):
-    count = 0
-    for k, v in RESULTS.items():
-        for item in v:
-            if key in item:
-                if re.search(value, item[key]):
-                    count += 1
-    return count
-
-
-def run_time():
-    runtime = 0.0
-    for k, v in RESULTS.items():
-        for test in v:
-            runtime += float(get_duration(test['timestamps']).strip('s'))
-    return runtime
-
-
-def worker_stats(worker):
-    tests = RESULTS[worker]
-    num_tests = len(tests)
-    delta = tests[-1]['timestamps'][1] - tests[0]['timestamps'][0]
-    return num_tests, delta
-
-
-def print_summary(stream):
-    stream.write("\n======\nTotals\n======\n")
-    stream.write("Run: %s in %s sec.\n" % (count_tests('status', '.*'),
-                                           run_time()))
-    stream.write(" - Passed: %s\n" % count_tests('status', 'success'))
-    stream.write(" - Skipped: %s\n" % count_tests('status', 'skip'))
-    stream.write(" - Failed: %s\n" % count_tests('status', 'fail'))
-
-    # we could have no results, especially as we filter out the process-codes
-    if RESULTS:
-        stream.write("\n==============\nWorker Balance\n==============\n")
-
-        for w in range(max(RESULTS.keys()) + 1):
-            if w not in RESULTS:
-                stream.write(
-                    " - WARNING: missing Worker %s! "
-                    "Race in testr accounting.\n" % w)
-            else:
-                num, time = worker_stats(w)
-                stream.write(" - Worker %s (%s tests) => %ss\n" %
-                             (w, num, time))
-
-
-def parse_args():
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--no-failure-debug', '-n', action='store_true',
-                        dest='print_failures', help='Disable printing failure '
-                        'debug information in realtime')
-    parser.add_argument('--fails', '-f', action='store_true',
-                        dest='post_fails', help='Print failure debug '
-                        'information after the stream is proccesed')
-    return parser.parse_args()
-
-
-def main():
-    args = parse_args()
-    stream = subunit.ByteStreamToStreamResult(
-        sys.stdin, non_subunit_name='stdout')
-    outcomes = testtools.StreamToDict(
-        functools.partial(show_outcome, sys.stdout,
-                          print_failures=args.print_failures))
-    summary = testtools.StreamSummary()
-    result = testtools.CopyStreamResult([outcomes, summary])
-    result.startTestRun()
-    try:
-        stream.run(result)
-    finally:
-        result.stopTestRun()
-    if count_tests('status', '.*') == 0:
-        print("The test run didn't actually run any tests")
-        return 1
-    if args.post_fails:
-        print_fails(sys.stdout)
-    print_summary(sys.stdout)
-    return (0 if summary.wasSuccessful() else 1)
-
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/tox.ini b/tox.ini
index e575b4f..f75e868 100644
--- a/tox.ini
+++ b/tox.ini
@@ -28,7 +28,9 @@
 
 [testenv:all]
 sitepackages = {[tempestenv]sitepackages}
+# 'all' includes slow tests
 setenv = {[tempestenv]setenv}
+         OS_TEST_TIMEOUT=1200
 deps = {[tempestenv]deps}
 commands =
   bash tools/pretty_tox.sh '{posargs}'
@@ -89,7 +91,7 @@
 setenv = {[tempestenv]setenv}
 deps = {[tempestenv]deps}
 commands =
-    run-tempest-stress '{posargs}'
+    run-tempest-stress {posargs}
 
 [testenv:venv]
 commands = {posargs}