Merge "Add config options for XML support in Keystone"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index a6dd0af..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
diff --git a/requirements.txt b/requirements.txt
index a856d09..1e4c40b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -20,7 +20,6 @@
 python-ironicclient>=0.2.1
 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
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/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/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 7ba68f7..cd04ef7 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -93,58 +93,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-')
@@ -156,8 +193,13 @@
 
     @classmethod
     def create_subnet(cls, network, gateway='', cidr=None, mask_bits=None,
-                      ip_version=None, **kwargs):
+                      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.
         ip_version = ip_version if ip_version is not None else cls._ip_version
         gateway_not_set = gateway == ''
@@ -175,7 +217,7 @@
             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=ip_version,
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 1189c8f..6e45b0f 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -71,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_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_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index 3857fdb..1c3e04a 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -18,19 +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 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
@@ -39,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
@@ -50,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
@@ -92,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/base.py b/tempest/api/volume/base.py
index 8170cbf..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:
@@ -175,6 +174,8 @@
             cls.volume_qos_client = cls.os_adm.volume_qos_client
             cls.volume_types_client = cls.os_adm.volume_types_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"
@@ -182,6 +183,8 @@
             cls.volume_qos_client = cls.os_adm.volume_qos_v2_client
             cls.volume_types_client = cls.os_adm.volume_types_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/cli/__init__.py b/tempest/cli/__init__.py
index 8dd2df2..4782129 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -16,6 +16,7 @@
 import functools
 
 from tempest_lib.cli import base
+from tempest_lib.cli import output_parser
 import testtools
 
 from tempest.common import credentials
@@ -66,7 +67,7 @@
     return decorator
 
 
-class ClientTestBase(base.ClientTestBase, test.BaseTestCase):
+class ClientTestBase(test.BaseTestCase):
     @classmethod
     def resource_setup(cls):
         if not CONF.cli.enabled:
@@ -82,3 +83,36 @@
                                  self.creds.tenant_name,
                                  CONF.identity.uri, CONF.cli.cli_dir)
         return clients
+
+    # 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.
+
+        :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/simple_read_only/volume/test_cinder.py b/tempest/cli/simple_read_only/volume/test_cinder.py
index 102f199..c2e0a42 100644
--- a/tempest/cli/simple_read_only/volume/test_cinder.py
+++ b/tempest/cli/simple_read_only/volume/test_cinder.py
@@ -20,6 +20,7 @@
 import testtools
 
 from tempest import cli
+from tempest import clients
 from tempest import config
 
 
@@ -41,6 +42,9 @@
             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,
@@ -87,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):
diff --git a/tempest/clients.py b/tempest/clients.py
index 328ad08..8f7fc4f 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 \
@@ -231,78 +233,38 @@
         super(Manager, self).__init__(credentials=credentials)
 
         self._set_compute_clients(self.interface)
+        self._set_volume_clients(self.interface)
 
         if self.interface == 'xml':
-            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.endpoints_client = EndPointClientXML(self.auth_provider)
             self.service_client = ServiceClientXML(self.auth_provider)
-            self.volume_services_client = VolumesServicesClientXML(
-                self.auth_provider)
             self.policy_client = PolicyClientXML(self.auth_provider)
             self.region_client = RegionClientXML(self.auth_provider)
             self.network_client = NetworkClientXML(self.auth_provider)
             self.credentials_client = CredentialsClientXML(
                 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()
             if CONF.identity_feature_enabled.api_v3:
                 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.baremetal_client = BaremetalClientJSON(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.endpoints_client = EndPointClientJSON(self.auth_provider)
             self.service_client = ServiceClientJSON(self.auth_provider)
-            self.volume_services_client = VolumesServicesClientJSON(
-                self.auth_provider)
             self.policy_client = PolicyClientJSON(self.auth_provider)
             self.region_client = RegionClientJSON(self.auth_provider)
             self.network_client = NetworkClientJSON(self.auth_provider)
             self.credentials_client = CredentialsClientJSON(
                 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.database_flavors_client = DatabaseFlavorsClientJSON(
                 self.auth_provider)
@@ -318,10 +280,6 @@
             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
@@ -335,7 +293,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)
@@ -351,17 +308,6 @@
             AccountClientCustomizedHeader(self.auth_provider)
         self.data_processing_client = DataProcessingClient(
             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)
-        # 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.
-        # Bug : 1312553
-        self.volume_qos_client = QosSpecsClientJSON(self.auth_provider)
-        self.volume_qos_v2_client = QosSpecsV2ClientJSON(
-            self.auth_provider)
 
     def _set_compute_clients(self, type):
         if type == 'json':
@@ -369,6 +315,13 @@
         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))
+
     def _set_compute_xml_clients(self):
         self.certificates_client = CertificatesClientXML(self.auth_provider)
         self.servers_client = ServersClientXML(self.auth_provider)
@@ -440,6 +393,65 @@
         self.instance_usages_audit_log_client = \
             InstanceUsagesAuditLogClientJSON(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.
+        # Bug : 1312553
+        self.volume_qos_client = QosSpecsClientJSON(self.auth_provider)
+        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/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/config.py b/tempest/config.py
index 77e8fff..63a7226 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -315,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',
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/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 a23e173..4417e3b 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -230,7 +230,7 @@
 
         url = '?format=%s' % self.format
         if params:
-            url += '&%s' + urllib.urlencode(params)
+            url += '&%s' % urllib.urlencode(params)
 
         headers = {}
         if metadata:
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/test.py b/tempest/test.py
index db8736e..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