Merge "Instance ID was corrected"
diff --git a/README.rst b/README.rst
index ba93712..94a5352 100644
--- a/README.rst
+++ b/README.rst
@@ -18,7 +18,7 @@
   incorrect assessment of their cloud. Explicit is always better.
 - Tempest uses OpenStack public interfaces. Tests in Tempest should
   only touch public interfaces, API calls (native or 3rd party),
-  public CLI or libraries.
+  or libraries.
 - Tempest should not touch private or implementation specific
   interfaces. This means not directly going to the database, not
   directly hitting the hypervisors, not testing extensions not
diff --git a/doc/source/field_guide/cli.rst b/doc/source/field_guide/cli.rst
deleted file mode 120000
index 13caef5..0000000
--- a/doc/source/field_guide/cli.rst
+++ /dev/null
@@ -1 +0,0 @@
-../../../tempest/cli/README.rst
\ No newline at end of file
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 2a72635..4418b9d 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -201,27 +201,6 @@
 #build_interval = 1
 
 
-[cli]
-
-#
-# From tempest.config
-#
-
-# enable cli tests (boolean value)
-#enabled = true
-
-# directory where python client binaries are located (string value)
-#cli_dir = /usr/local/bin
-
-# Whether the tempest run location has access to the *-manage
-# commands. In a pure blackbox environment it will not. (boolean
-# value)
-#has_manage = true
-
-# Number of seconds to wait on a CLI timeout (integer value)
-#timeout = 15
-
-
 [compute]
 
 #
@@ -396,6 +375,11 @@
 # https://bugs.launchpad.net/nova/+bug/1398999 (boolean value)
 #block_migrate_cinder_iscsi = false
 
+# Does the test system allow live-migration of paused instances? Note,
+# this is more than just the ANDing of paused and live_migrate, but
+# all 3 should be set to True to run those tests (boolean value)
+#live_migrate_paused_instances = false
+
 # Enable VNC console. This configuration value should be same as
 # [nova.vnc]->vnc_enabled in nova.conf (boolean value)
 #vnc_console = false
diff --git a/requirements.txt b/requirements.txt
index 174c7c8..3a32b69 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,10 +9,8 @@
 boto>=2.32.1
 paramiko>=1.13.0
 netaddr>=0.7.12
-python-glanceclient>=0.15.0
-python-cinderclient>=1.1.0
-python-heatclient>=0.3.0
 testrepository>=0.0.18
+pyOpenSSL>=0.11
 oslo.concurrency>=1.8.0,<1.9.0         # Apache-2.0
 oslo.config>=1.9.3,<1.10.0  # Apache-2.0
 oslo.i18n>=1.5.0,<1.6.0  # Apache-2.0
@@ -24,3 +22,4 @@
 fixtures>=0.3.14
 testscenarios>=0.4
 tempest-lib>=0.5.0
+PyYAML>=3.1.0
diff --git a/tempest/README.rst b/tempest/README.rst
index d28c3f9..fec2874 100644
--- a/tempest/README.rst
+++ b/tempest/README.rst
@@ -14,7 +14,6 @@
 
 | tempest/
 |    api/ - API tests
-|    cli/ - CLI tests
 |    scenario/ - complex scenario tests
 |    stress/ - stress tests
 |    thirdparty/ - 3rd party api tests
@@ -38,16 +37,6 @@
 frameworks.
 
 
-:ref:`cli_field_guide`
-----------------------
-
-CLI tests use the openstack CLI to interact with the OpenStack
-cloud. CLI testing in unit tests is somewhat difficult because unlike
-server testing, there is no access to server code to
-instantiate. Tempest seems like a logical place for this, as it
-prereqs having a running OpenStack cloud.
-
-
 :ref:`scenario_field_guide`
 ---------------------------
 
diff --git a/tempest/api/baremetal/admin/test_chassis.py b/tempest/api/baremetal/admin/test_chassis.py
index e9068f3..5ad05cc 100644
--- a/tempest/api/baremetal/admin/test_chassis.py
+++ b/tempest/api/baremetal/admin/test_chassis.py
@@ -11,6 +11,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
 from tempest_lib.common.utils import data_utils
 from tempest_lib import exceptions as lib_exc
 
@@ -28,7 +29,7 @@
 
     def _assertExpected(self, expected, actual):
         # Check if not expected keys/values exists in actual response body
-        for key, value in expected.iteritems():
+        for key, value in six.iteritems(expected):
             if key not in ('created_at', 'updated_at'):
                 self.assertIn(key, actual)
                 self.assertEqual(value, actual[key])
diff --git a/tempest/api/baremetal/admin/test_ports.py b/tempest/api/baremetal/admin/test_ports.py
index ee6bb9c..ece4471 100644
--- a/tempest/api/baremetal/admin/test_ports.py
+++ b/tempest/api/baremetal/admin/test_ports.py
@@ -10,6 +10,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
 from tempest_lib.common.utils import data_utils
 from tempest_lib import decorators
 from tempest_lib import exceptions as lib_exc
@@ -31,7 +32,7 @@
 
     def _assertExpected(self, expected, actual):
         # Check if not expected keys/values exists in actual response body
-        for key, value in expected.iteritems():
+        for key, value in six.iteritems(expected):
             if key not in ('created_at', 'updated_at'):
                 self.assertIn(key, actual)
                 self.assertEqual(value, actual[key])
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py
index 6634290..9da7901 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py
@@ -14,7 +14,8 @@
 #    under the License.
 
 import datetime
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.api.compute import base
 from tempest import test
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
index ec9ad19..97d665b 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 import datetime
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api.compute import base
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 8a92326..d3b1f5e 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -84,10 +84,15 @@
             self.volumes_client.wait_for_volume_status(volume_id, 'available')
         self.volumes_client.delete_volume(volume_id)
 
-    @test.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
-    @testtools.skipIf(not CONF.compute_feature_enabled.live_migration,
-                      'Live migration not available')
-    def test_live_block_migration(self):
+    def _test_live_block_migration(self, state='ACTIVE'):
+        """Tests live block migration between two hosts.
+
+        Requires CONF.compute_feature_enabled.live_migration to be True.
+
+        :param state: The vm_state the migrated server should be in before and
+                      after the live migration. Supported values are 'ACTIVE'
+                      and 'PAUSED'.
+        """
         # Live block migrate an instance to another host
         if len(self._get_compute_hostnames()) < 2:
             raise self.skipTest(
@@ -95,10 +100,33 @@
         server_id = self._get_an_active_server()
         actual_host = self._get_host_for_server(server_id)
         target_host = self._get_host_other_than(actual_host)
+
+        if state == 'PAUSED':
+            self.admin_servers_client.pause_server(server_id)
+            self.admin_servers_client.wait_for_server_status(server_id, state)
+
         self._migrate_server_to(server_id, target_host)
-        self.servers_client.wait_for_server_status(server_id, 'ACTIVE')
+        self.servers_client.wait_for_server_status(server_id, state)
         self.assertEqual(target_host, self._get_host_for_server(server_id))
 
+    @test.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
+    @testtools.skipUnless(CONF.compute_feature_enabled.live_migration,
+                          'Live migration not available')
+    def test_live_block_migration(self):
+        self._test_live_block_migration()
+
+    @test.idempotent_id('1e107f21-61b2-4988-8f22-b196e938ab88')
+    @testtools.skipUnless(CONF.compute_feature_enabled.live_migration,
+                          'Live migration not available')
+    @testtools.skipUnless(CONF.compute_feature_enabled.pause,
+                          'Pause is not available.')
+    @testtools.skipUnless(CONF.compute_feature_enabled
+                              .live_migrate_paused_instances,
+                          'Live migration of paused instances is not '
+                          'available.')
+    def test_live_block_migration_paused(self):
+        self._test_live_block_migration(state='PAUSED')
+
     @test.idempotent_id('e19c0cc6-6720-4ed8-be83-b6603ed5c812')
     @testtools.skipIf(not CONF.compute_feature_enabled.live_migration or not
                       CONF.compute_feature_enabled.
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index 0178c9e..fd4d902 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -21,7 +21,6 @@
 
 
 class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
-    force_tenant_isolation = True
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index d0dfc87..a17f581 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
+
 from tempest.api.compute import base
 from tempest import test
 
@@ -48,7 +50,7 @@
         # We do not know the exact network configuration, but an instance
         # should at least have a single public or private address
         self.assertTrue(len(addresses) >= 1)
-        for network_name, network_addresses in addresses.iteritems():
+        for network_name, network_addresses in six.iteritems(addresses):
             self.assertTrue(len(network_addresses) >= 1)
             for address in network_addresses:
                 self.assertTrue(address['addr'])
diff --git a/tempest/api/network/admin/test_quotas.py b/tempest/api/network/admin/test_quotas.py
index 86fbc54..46d6651 100644
--- a/tempest/api/network/admin/test_quotas.py
+++ b/tempest/api/network/admin/test_quotas.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
 from tempest_lib.common.utils import data_utils
 
 from tempest.api.network import base
@@ -62,7 +63,7 @@
         quota_set = self.admin_client.update_quotas(tenant_id,
                                                     **new_quotas)
         self.addCleanup(self.admin_client.reset_quotas, tenant_id)
-        for key, value in new_quotas.iteritems():
+        for key, value in six.iteritems(new_quotas):
             self.assertEqual(value, quota_set[key])
 
         # Confirm our tenant is listed among tenants with non default quotas
@@ -76,7 +77,7 @@
         # Confirm from API quotas were changed as requested for tenant
         quota_set = self.admin_client.show_quotas(tenant_id)
         quota_set = quota_set['quota']
-        for key, value in new_quotas.iteritems():
+        for key, value in six.iteritems(new_quotas):
             self.assertEqual(value, quota_set[key])
 
         # Reset quotas to default and confirm
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 253d779..ca08fbd 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -16,6 +16,7 @@
 import netaddr
 import random
 
+import six
 from tempest_lib.common.utils import data_utils
 from tempest_lib import exceptions as lib_exc
 
@@ -127,7 +128,7 @@
         ):
             kwargs = {'ipv6_ra_mode': ra_mode,
                       'ipv6_address_mode': add_mode}
-            kwargs = {k: v for k, v in kwargs.iteritems() if v}
+            kwargs = {k: v for k, v in six.iteritems(kwargs) if v}
             real_ip, eui_ip = self._get_ips_from_subnet(**kwargs)
             self._clean_network()
             self.assertEqual(eui_ip, real_ip,
@@ -203,8 +204,8 @@
                 real_ips = dict([(k['subnet_id'], k['ip_address'])
                                  for k in port['fixed_ips']])
                 real_dhcp_ip, real_eui_ip = [real_ips[sub['id']]
-                                             for sub in subnet_dhcp,
-                                             subnet_slaac]
+                                             for sub in [subnet_dhcp,
+                                             subnet_slaac]]
                 self.client.delete_port(port['id'])
                 self.ports.pop()
                 body = self.client.list_ports()
@@ -256,8 +257,8 @@
                 real_ips = dict([(k['subnet_id'], k['ip_address'])
                                  for k in port['fixed_ips']])
                 real_dhcp_ip, real_eui_ip = [real_ips[sub['id']]
-                                             for sub in subnet_dhcp,
-                                             subnet_slaac]
+                                             for sub in [subnet_dhcp,
+                                             subnet_slaac]]
                 self._clean_network()
                 self.assertTrue({real_eui_ip,
                                  real_dhcp_ip}.issubset([eui_ip] + dhcp_ip))
@@ -284,7 +285,7 @@
         ):
             kwargs = {'ipv6_ra_mode': ra_mode,
                       'ipv6_address_mode': add_mode}
-            kwargs = {k: v for k, v in kwargs.iteritems() if v}
+            kwargs = {k: v for k, v in six.iteritems(kwargs) if v}
             subnet = self.create_subnet(self.network, **kwargs)
             port = self.create_port(self.network)
             port_ip = next(iter(port['fixed_ips']), None)['ip_address']
@@ -311,7 +312,7 @@
         ):
             kwargs = {'ipv6_ra_mode': ra_mode,
                       'ipv6_address_mode': add_mode}
-            kwargs = {k: v for k, v in kwargs.iteritems() if v}
+            kwargs = {k: v for k, v in six.iteritems(kwargs) if v}
             subnet = self.create_subnet(self.network, **kwargs)
             ip_range = netaddr.IPRange(subnet["allocation_pools"][0]["start"],
                                        subnet["allocation_pools"][0]["end"])
@@ -389,7 +390,7 @@
         ):
             kwargs = {'ipv6_ra_mode': ra_mode,
                       'ipv6_address_mode': add_mode}
-            kwargs = {k: v for k, v in kwargs.iteritems() if v}
+            kwargs = {k: v for k, v in six.iteritems(kwargs) if v}
             subnet, port = self._create_subnet_router(kwargs)
             port_ip = next(iter(port['fixed_ips']), None)['ip_address']
             self._clean_network()
diff --git a/tempest/api/network/test_fwaas_extensions.py b/tempest/api/network/test_fwaas_extensions.py
index d007fb0..0622e87 100644
--- a/tempest/api/network/test_fwaas_extensions.py
+++ b/tempest/api/network/test_fwaas_extensions.py
@@ -12,6 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
 from tempest_lib.common.utils import data_utils
 from tempest_lib import exceptions as lib_exc
 
@@ -145,7 +146,7 @@
     def test_show_firewall_rule(self):
         # show a created firewall rule
         fw_rule = self.client.show_firewall_rule(self.fw_rule['id'])
-        for key, value in fw_rule['firewall_rule'].iteritems():
+        for key, value in six.iteritems(fw_rule['firewall_rule']):
             self.assertEqual(self.fw_rule[key], value)
 
     @test.idempotent_id('1086dd93-a4c0-4bbb-a1bd-6d4bc62c199f')
@@ -187,7 +188,7 @@
         # show a created firewall policy
         fw_policy = self.client.show_firewall_policy(self.fw_policy['id'])
         fw_policy = fw_policy['firewall_policy']
-        for key, value in fw_policy.iteritems():
+        for key, value in six.iteritems(fw_policy):
             self.assertEqual(self.fw_policy[key], value)
 
     @test.idempotent_id('02082a03-3cdd-4789-986a-1327dd80bfb7')
@@ -216,7 +217,7 @@
         firewall = self.client.show_firewall(firewall_id)
         firewall = firewall['firewall']
 
-        for key, value in firewall.iteritems():
+        for key, value in six.iteritems(firewall):
             if key == 'status':
                 continue
             self.assertEqual(created_firewall[key], value)
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index ace9f61..38a6fe9 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
 from tempest_lib.common.utils import data_utils
 from tempest_lib import decorators
 
@@ -75,7 +76,7 @@
         body = create_obj(**kwargs)
         obj = body[obj_name]
         self.addCleanup(delete_obj, obj['id'])
-        for key, value in obj.iteritems():
+        for key, value in six.iteritems(obj):
             # It is not relevant to filter by all arguments. That is why
             # there is a list of attr to except
             if key not in attr_exceptions:
@@ -168,7 +169,7 @@
         # Verifies the details of a vip
         body = self.client.show_vip(self.vip['id'])
         vip = body['vip']
-        for key, value in vip.iteritems():
+        for key, value in six.iteritems(vip):
             # 'status' should not be confirmed in api tests
             if key != 'status':
                 self.assertEqual(self.vip[key], value)
@@ -185,7 +186,7 @@
         # Verifies the details of a pool
         body = self.client.show_pool(pool['id'])
         shown_pool = body['pool']
-        for key, value in pool.iteritems():
+        for key, value in six.iteritems(pool):
             # 'status' should not be confirmed in api tests
             if key != 'status':
                 self.assertEqual(value, shown_pool[key])
@@ -243,7 +244,7 @@
         # Verifies the details of a member
         body = self.client.show_member(self.member['id'])
         member = body['member']
-        for key, value in member.iteritems():
+        for key, value in six.iteritems(member):
             # 'status' should not be confirmed in api tests
             if key != 'status':
                 self.assertEqual(self.member[key], value)
@@ -316,7 +317,7 @@
         # Verifies the details of a health_monitor
         body = self.client.show_health_monitor(self.health_monitor['id'])
         health_monitor = body['health_monitor']
-        for key, value in health_monitor.iteritems():
+        for key, value in six.iteritems(health_monitor):
             # 'status' should not be confirmed in api tests
             if key != 'status':
                 self.assertEqual(self.health_monitor[key], value)
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 97273a6..5e3e374 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -15,6 +15,7 @@
 import itertools
 
 import netaddr
+import six
 from tempest_lib.common.utils import data_utils
 from tempest_lib import exceptions as lib_exc
 
@@ -162,7 +163,7 @@
                                     **kwargs)
         compare_args_full = dict(gateway_ip=gateway, cidr=cidr,
                                  mask_bits=mask_bits, **kwargs)
-        compare_args = dict((k, v) for k, v in compare_args_full.iteritems()
+        compare_args = dict((k, v) for k, v in six.iteritems(compare_args_full)
                             if v is not None)
 
         if 'dns_nameservers' in set(subnet).intersection(compare_args):
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 4362926..35072b4 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 import netaddr
+import six
 from tempest_lib.common.utils import data_utils
 
 from tempest.api.network import base_routers as base
@@ -176,7 +177,7 @@
             self.assertIsNone(actual_ext_gw_info)
             return
         # Verify only keys passed in exp_ext_gw_info
-        for k, v in exp_ext_gw_info.iteritems():
+        for k, v in six.iteritems(exp_ext_gw_info):
             self.assertEqual(v, actual_ext_gw_info[k])
 
     def _verify_gateway_port(self, router_id):
diff --git a/tempest/api/network/test_vpnaas_extensions.py b/tempest/api/network/test_vpnaas_extensions.py
index 718168b..9fe2a56 100644
--- a/tempest/api/network/test_vpnaas_extensions.py
+++ b/tempest/api/network/test_vpnaas_extensions.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
 from tempest_lib.common.utils import data_utils
 from tempest_lib import exceptions as lib_exc
 
@@ -82,7 +83,7 @@
 
     def _assertExpected(self, expected, actual):
         # Check if not expected keys/values exists in actual response body
-        for key, value in expected.iteritems():
+        for key, value in six.iteritems(expected):
             self.assertIn(key, actual)
             self.assertEqual(value, actual[key])
 
@@ -245,7 +246,7 @@
         # Confirm that update was successful by verifying using 'show'
         body = self.client.show_ikepolicy(ikepolicy['id'])
         ike_policy = body['ikepolicy']
-        for key, value in new_ike.iteritems():
+        for key, value in six.iteritems(new_ike):
             self.assertIn(key, ike_policy)
             self.assertEqual(value, ike_policy[key])
 
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 77defd6..918bd5a 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -64,7 +64,6 @@
         for container_name in self.containers:
             self.assertIn(container_name, container_list)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('884ec421-fbad-4fcc-916b-0580f2699565')
     def test_list_no_containers(self):
         # List request to empty account
@@ -93,7 +92,6 @@
 
         self.assertEqual(len(container_list), 0)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('1c7efa35-e8a2-4b0b-b5ff-862c7fd83704')
     def test_list_containers_with_format_json(self):
         # list containers setting format parameter to 'json'
@@ -106,7 +104,6 @@
         self.assertTrue([c['count'] for c in container_list])
         self.assertTrue([c['bytes'] for c in container_list])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('4477b609-1ca6-4d4b-b25d-ad3f01086089')
     def test_list_containers_with_format_xml(self):
         # list containers setting format parameter to 'xml'
@@ -122,7 +119,6 @@
         self.assertEqual(container_list.find(".//count").tag, 'count')
         self.assertEqual(container_list.find(".//bytes").tag, 'bytes')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('6eb04a6a-4860-4e31-ba91-ea3347d76b58')
     @testtools.skipIf(
         not CONF.object_storage_feature_enabled.discoverability,
@@ -132,7 +128,6 @@
 
         self.assertThat(resp, custom_matchers.AreAllWellFormatted())
 
-    @test.attr(type='smoke')
     @test.idempotent_id('5cfa4ab2-4373-48dd-a41f-a532b12b08b2')
     def test_list_containers_with_limit(self):
         # list containers one of them, half of them then all of them
@@ -144,7 +139,6 @@
 
             self.assertEqual(len(container_list), limit)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('638f876d-6a43-482a-bbb3-0840bca101c6')
     def test_list_containers_with_marker(self):
         # list containers using marker param
@@ -165,7 +159,6 @@
 
         self.assertEqual(len(container_list), self.containers_count / 2 - 1)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('5ca164e4-7bde-43fa-bafb-913b53b9e786')
     def test_list_containers_with_end_marker(self):
         # list containers using end_marker param
@@ -184,7 +177,6 @@
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list), self.containers_count / 2)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('ac8502c2-d4e4-4f68-85a6-40befea2ef5e')
     def test_list_containers_with_marker_and_end_marker(self):
         # list containers combining marker and end_marker param
@@ -195,7 +187,6 @@
         self.assertHeaders(resp, 'Account', 'GET')
         self.assertEqual(len(container_list), self.containers_count - 2)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('f7064ae8-dbcc-48da-b594-82feef6ea5af')
     def test_list_containers_with_limit_and_marker(self):
         # list containers combining marker and limit param
@@ -210,7 +201,6 @@
 
             self.assertTrue(len(container_list) <= limit, str(container_list))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('888a3f0e-7214-4806-8e50-5e0c9a69bb5e')
     def test_list_containers_with_limit_and_end_marker(self):
         # list containers combining limit and end_marker param
@@ -223,7 +213,6 @@
         self.assertEqual(len(container_list),
                          min(limit, self.containers_count / 2))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('8cf98d9c-e3a0-4e44-971b-c87656fdddbd')
     def test_list_containers_with_limit_and_marker_and_end_marker(self):
         # list containers combining limit, marker and end_marker param
@@ -253,7 +242,6 @@
         self.assertIn('x-account-meta-test-account-meta2', resp)
         self.account_client.delete_account_metadata(metadata)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('b904c2e3-24c2-4dba-ad7d-04e90a761be5')
     def test_list_no_account_metadata(self):
         # list no account metadata
@@ -261,7 +249,6 @@
         self.assertHeaders(resp, 'Account', 'HEAD')
         self.assertNotIn('x-account-meta-', str(resp))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('e2a08b5f-3115-4768-a3ee-d4287acd6c08')
     def test_update_account_metadata_with_create_metadata(self):
         # add metadata to account
@@ -276,7 +263,6 @@
 
         self.account_client.delete_account_metadata(metadata)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('9f60348d-c46f-4465-ae06-d51dbd470953')
     def test_update_account_metadata_with_delete_matadata(self):
         # delete metadata from account
@@ -288,7 +274,6 @@
         resp, _ = self.account_client.list_account_metadata()
         self.assertNotIn('x-account-meta-test-account-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('64fd53f3-adbd-4639-af54-436e4982dbfb')
     def test_update_account_metadata_with_create_matadata_key(self):
         # if the value of metadata is not set, the metadata is not
@@ -300,7 +285,6 @@
         resp, _ = self.account_client.list_account_metadata()
         self.assertNotIn('x-account-meta-test-account-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('d4d884d3-4696-4b85-bc98-4f57c4dd2bf1')
     def test_update_account_metadata_with_delete_matadata_key(self):
         # Although the value of metadata is not set, the feature of
@@ -314,7 +298,6 @@
         resp, _ = self.account_client.list_account_metadata()
         self.assertNotIn('x-account-meta-test-account-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('8e5fc073-59b9-42ee-984a-29ed11b2c749')
     def test_update_account_metadata_with_create_and_delete_metadata(self):
         # Send a request adding and deleting metadata requests simultaneously
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index 73a976d..1003f82 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -46,7 +46,6 @@
         self.delete_containers([self.container_name])
         super(ObjectTestACLs, self).tearDown()
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a3270f3f-7640-4944-8448-c7ea783ea5b6')
     def test_read_object_with_rights(self):
         # attempt to read object using authorized user
@@ -72,7 +71,6 @@
             self.container_name, object_name)
         self.assertHeaders(resp, 'Object', 'GET')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('aa58bfa5-40d9-4bc3-82b4-d07f4a9e392a')
     def test_write_object_with_rights(self):
         # attempt to write object using authorized user
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index 9f2adfe..0f107f5 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -55,7 +55,6 @@
         self.containers.append(container_name)
         self.assertHeaders(resp, 'Container', 'PUT')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('49f866ed-d6af-4395-93e7-4187eb56d322')
     def test_create_container_overwrite(self):
         # overwrite container with the same name
@@ -66,7 +65,6 @@
         resp, _ = self.container_client.create_container(container_name)
         self.assertHeaders(resp, 'Container', 'PUT')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('c2ac4d59-d0f5-40d5-ba19-0635056d48cd')
     def test_create_container_with_metadata_key(self):
         # create container with the blank value of metadata
@@ -84,7 +82,6 @@
         # in the server
         self.assertNotIn('x-container-meta-test-container-meta', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('e1e8df32-7b22-44e1-aa08-ccfd8d446b58')
     def test_create_container_with_metadata_value(self):
         # create container with metadata value
@@ -103,7 +100,6 @@
         self.assertEqual(resp['x-container-meta-test-container-meta'],
                          metadata['test-container-meta'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('24d16451-1c0c-4e4f-b59c-9840a3aba40e')
     def test_create_container_with_remove_metadata_key(self):
         # create container with the blank value of remove metadata
@@ -124,7 +120,6 @@
             container_name)
         self.assertNotIn('x-container-meta-test-container-meta', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('8a21ebad-a5c7-4e29-b428-384edc8cd156')
     def test_create_container_with_remove_metadata_value(self):
         # create container with remove metadata
@@ -143,7 +138,6 @@
             container_name)
         self.assertNotIn('x-container-meta-test-container-meta', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('95d3a249-b702-4082-a2c4-14bb860cf06a')
     def test_delete_container(self):
         # create a container
@@ -165,7 +159,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('4646ac2d-9bfb-4c7d-a3c5-0f527402b3df')
     def test_list_container_contents_with_no_object(self):
         # get empty container contents list
@@ -176,7 +169,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual('', object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('fe323a32-57b9-4704-a996-2e68f83b09bc')
     def test_list_container_contents_with_delimiter(self):
         # get container contents list using delimiter param
@@ -191,7 +183,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name.split('/')[0], object_list.strip('/\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('55b4fa5c-e12e-4ca9-8fcf-a79afe118522')
     def test_list_container_contents_with_end_marker(self):
         # get container contents list using end_marker param
@@ -205,7 +196,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('196f5034-6ab0-4032-9da9-a937bbb9fba9')
     def test_list_container_contents_with_format_json(self):
         # get container contents list using format_json param
@@ -225,7 +215,6 @@
         self.assertTrue([c['content_type'] for c in object_list])
         self.assertTrue([c['last_modified'] for c in object_list])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('655a53ca-4d15-408c-a377-f4c6dbd0a1fa')
     def test_list_container_contents_with_format_xml(self):
         # get container contents list using format_xml param
@@ -250,7 +239,6 @@
         self.assertEqual(object_list.find(".//last_modified").tag,
                          'last_modified')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('297ec38b-2b61-4ff4-bcd1-7fa055e97b61')
     def test_list_container_contents_with_limit(self):
         # get container contents list using limit param
@@ -264,7 +252,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('c31ddc63-2a58-4f6b-b25c-94d2937e6867')
     def test_list_container_contents_with_marker(self):
         # get container contents list using marker param
@@ -278,7 +265,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('58ca6cc9-6af0-408d-aaec-2a6a7b2f0df9')
     def test_list_container_contents_with_path(self):
         # get container contents list using path param
@@ -293,7 +279,6 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual(object_name, object_list.strip('\n'))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('77e742c7-caf2-4ec9-8aa4-f7d509a3344c')
     def test_list_container_contents_with_prefix(self):
         # get container contents list using prefix param
@@ -325,7 +310,6 @@
         self.assertIn('x-container-meta-name', resp)
         self.assertEqual(resp['x-container-meta-name'], metadata['name'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a2faf936-6b13-4f8d-92a2-c2278355821e')
     def test_list_no_container_metadata(self):
         # HEAD container without metadata
@@ -336,7 +320,6 @@
         self.assertHeaders(resp, 'Container', 'HEAD')
         self.assertNotIn('x-container-meta-', str(resp))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('cf19bc0b-7e16-4a5a-aaed-cb0c2fe8deef')
     def test_update_container_metadata_with_create_and_delete_matadata(self):
         # Send one request of adding and deleting metadata
@@ -360,7 +343,6 @@
         self.assertEqual(resp['x-container-meta-test-container-meta2'],
                          metadata_2['test-container-meta2'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('2ae5f295-4bf1-4e04-bfad-21e54b62cec5')
     def test_update_container_metadata_with_create_metadata(self):
         # update container metadata using add metadata
@@ -378,7 +360,6 @@
         self.assertEqual(resp['x-container-meta-test-container-meta1'],
                          metadata['test-container-meta1'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('3a5ce7d4-6e4b-47d0-9d87-7cd42c325094')
     def test_update_container_metadata_with_delete_metadata(self):
         # update container metadata using delete metadata
@@ -397,7 +378,6 @@
             container_name)
         self.assertNotIn('x-container-meta-test-container-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('31f40a5f-6a52-4314-8794-cd89baed3040')
     def test_update_container_metadata_with_create_matadata_key(self):
         # update container metadata with a blenk value of metadata
@@ -413,7 +393,6 @@
             container_name)
         self.assertNotIn('x-container-meta-test-container-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a2e36378-6f1f-43f4-840a-ffd9cfd61914')
     def test_update_container_metadata_with_delete_metadata_key(self):
         # update container metadata with a blank value of matadata
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index 6acd0f2..8075e91 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -89,6 +89,7 @@
             for meta_key in not_in_meta:
                 self.assertNotIn('x-object-meta-' + meta_key, resp)
 
+    @test.attr(type='smoke')
     @test.idempotent_id('5b4ce26f-3545-46c9-a2ba-5754358a4c62')
     def test_create_object(self):
         # create object
@@ -385,7 +386,6 @@
             object_name)
         self.assertNotIn('x-object-meta-test-meta1', resp)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('f726174b-2ded-4708-bff7-729d12ce1f84')
     def test_update_object_metadata_with_create_and_remove_metadata(self):
         # creation and deletion of metadata with one request
@@ -413,7 +413,6 @@
         self.assertIn('x-object-meta-test-meta2', resp)
         self.assertEqual(resp['x-object-meta-test-meta2'], 'Meta2')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('08854588-6449-4bb7-8cca-f2e1040f5e6f')
     def test_update_object_metadata_with_x_object_manifest(self):
         # update object metadata with x_object_manifest
@@ -460,7 +459,6 @@
         self.assertIn('x-object-meta-test-meta', resp)
         self.assertEqual(resp['x-object-meta-test-meta'], '')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('9a88dca4-b684-425b-806f-306cd0e57e42')
     def test_update_object_metadata_with_x_remove_object_metakey(self):
         # update object metadata with a blank value of remove metadata
@@ -504,7 +502,6 @@
         self.assertIn('x-object-meta-test-meta', resp)
         self.assertEqual(resp['x-object-meta-test-meta'], 'Meta')
 
-    @test.attr(type='smoke')
     @test.idempotent_id('170fb90e-f5c3-4b1f-ae1b-a18810821172')
     def test_list_no_object_metadata(self):
         # get empty list of object metadata
@@ -516,7 +513,6 @@
         self.assertHeaders(resp, 'Object', 'HEAD')
         self.assertNotIn('x-object-meta-', str(resp))
 
-    @test.attr(type='smoke')
     @test.idempotent_id('23a3674c-d6de-46c3-86af-ff92bfc8a3da')
     def test_list_object_metadata_with_x_object_manifest(self):
         # get object metadata with x_object_manifest
@@ -571,7 +567,6 @@
 
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('005f9bf6-e06d-41ec-968e-96c78e0b1d82')
     def test_get_object_with_metadata(self):
         # get object with metadata
@@ -591,7 +586,6 @@
         self.assertEqual(resp['x-object-meta-test-meta'], 'Meta')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('05a1890e-7db9-4a6c-90a8-ce998a2bddfa')
     def test_get_object_with_range(self):
         # get object with range
@@ -610,7 +604,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data[rand_num - 3: rand_num])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('11b4515b-7ba7-4ca8-8838-357ded86fc10')
     def test_get_object_with_x_object_manifest(self):
         # get object with x_object_manifest
@@ -654,7 +647,6 @@
 
         self.assertEqual(''.join(data_segments), body)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('c05b4013-e4de-47af-be84-e598062b16fc')
     def test_get_object_with_if_match(self):
         # get object with if_match
@@ -675,7 +667,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('be133639-e5d2-4313-9b1f-2d59fc054a16')
     def test_get_object_with_if_modified_since(self):
         # get object with if_modified_since
@@ -718,7 +709,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('0aa1201c-10aa-467a-bee7-63cbdd463152')
     def test_get_object_with_if_unmodified_since(self):
         # get object with if_unmodified_since
@@ -734,7 +724,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('94587078-475f-48f9-a40f-389c246e31cd')
     def test_get_object_with_x_newest(self):
         # get object with x_newest
@@ -748,7 +737,6 @@
         self.assertHeaders(resp, 'Object', 'GET')
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('1a9ab572-1b66-4981-8c21-416e2a5e6011')
     def test_copy_object_in_same_container(self):
         # create source object
@@ -775,7 +763,6 @@
                                                    dst_object_name)
         self.assertEqual(body, src_data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('2248abba-415d-410b-9c30-22dff9cd6e67')
     def test_copy_object_to_itself(self):
         # change the content type of an existing object
@@ -797,7 +784,6 @@
                                                           object_name)
         self.assertEqual(resp['content-type'], metadata['content-type'])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('06f90388-2d0e-40aa-934c-e9a8833e958a')
     def test_copy_object_2d_way(self):
         # create source object
@@ -824,7 +810,6 @@
         # check data
         self._check_copied_obj(dst_object_name, src_data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('aa467252-44f3-472a-b5ae-5b57c3c9c147')
     def test_copy_object_across_containers(self):
         # create a container to use as  asource container
@@ -865,7 +850,6 @@
         self.assertIn(actual_meta_key, resp)
         self.assertEqual(resp[actual_meta_key], meta_value)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('5a9e2cc6-85b6-46fc-916d-0cbb7a88e5fd')
     def test_copy_object_with_x_fresh_metadata(self):
         # create source object
@@ -886,7 +870,6 @@
         # check that destination object does NOT have any object-meta
         self._check_copied_obj(dst_object_name, data, not_in_meta=["src"])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a28a8b99-e701-4d7e-9d84-3b66f121460b')
     def test_copy_object_with_x_object_metakey(self):
         # create source object
@@ -909,7 +892,6 @@
         # check destination object
         self._check_copied_obj(dst_obj_name, data, in_meta=["test", "src"])
 
-    @test.attr(type='smoke')
     @test.idempotent_id('edabedca-24c3-4322-9b70-d6d9f942a074')
     def test_copy_object_with_x_object_meta(self):
         # create source object
@@ -1029,7 +1011,6 @@
         self.delete_containers([self.container_name])
         super(PublicObjectTest, self).tearDown()
 
-    @test.attr(type='smoke')
     @test.idempotent_id('07c9cf95-c0d4-4b49-b9c8-0ef2c9b27193')
     def test_access_public_container_object_without_using_creds(self):
         # make container public-readable and access an object in it object
@@ -1068,7 +1049,6 @@
 
         self.assertEqual(body, data)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('54e2a2fe-42dc-491b-8270-8e4217dd4cdc')
     def test_access_public_object_with_another_user_creds(self):
         # make container public-readable and access an object in it using
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index cd2d3c3..923166a 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -45,7 +45,6 @@
         header_value = resp.get('x-versions-location', 'Missing Header')
         self.assertEqual(header_value, versioned)
 
-    @test.attr(type='smoke')
     @test.idempotent_id('a151e158-dcbf-4a1f-a1e7-46cd65895a6f')
     @testtools.skipIf(
         not CONF.object_storage_feature_enabled.object_versioning,
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 814b46d..24c7c63 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -12,6 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import six
 from tempest_lib.common.utils import data_utils
 
 from tempest.api.volume import base
@@ -57,7 +58,7 @@
             **new_quota_set)
 
         cleanup_quota_set = dict(
-            (k, v) for k, v in default_quota_set.iteritems()
+            (k, v) for k, v in six.iteritems(default_quota_set)
             if k in QUOTA_KEYS)
         self.addCleanup(self.quotas_client.update_quota_set,
                         self.demo_tenant_id, **cleanup_quota_set)
diff --git a/tempest/cli/README.rst b/tempest/cli/README.rst
deleted file mode 100644
index bc18084..0000000
--- a/tempest/cli/README.rst
+++ /dev/null
@@ -1,50 +0,0 @@
-.. _cli_field_guide:
-
-Tempest Field Guide to CLI tests
-================================
-
-
-What are these tests?
----------------------
-The cli tests test the various OpenStack command line interface tools
-to ensure that they minimally function. The current scope is read only
-operations on a cloud that are hard to test via unit tests.
-
-
-Why are these tests in tempest?
--------------------------------
-These tests exist here because it is extremely difficult to build a
-functional enough environment in the python-\*client unit tests to
-provide this kind of testing. Because we already put up a cloud in the
-gate with devstack + tempest it was decided it was better to have
-these as a side tree in tempest instead of another QA effort which
-would split review time.
-
-
-Scope of these tests
---------------------
-This should stay limited to the scope of testing the cli. Functional
-testing of the cloud should be elsewhere, this is about exercising the
-cli code.
-
-
-Example of a good test
-----------------------
-Tests should be isolated to a single command in one of the python
-clients.
-
-Tests should not modify the cloud.
-
-If a test is validating the cli for bad data, it should do it with
-assertRaises.
-
-A reasonable example of an existing test is as follows::
-
-    def test_admin_list(self):
-        self.nova('list')
-        self.nova('list', params='--all-tenants 1')
-        self.nova('list', params='--all-tenants 0')
-        self.assertRaises(subprocess.CalledProcessError,
-                          self.nova,
-                          'list',
-                          params='--all-tenants bad')
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
deleted file mode 100644
index 6733204..0000000
--- a/tempest/cli/__init__.py
+++ /dev/null
@@ -1,126 +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.
-
-import functools
-
-from tempest_lib.cli import base
-from tempest_lib.cli import output_parser
-import testtools
-
-from tempest.common import credentials
-from tempest import config
-from tempest import exceptions
-from tempest.openstack.common import versionutils
-from tempest import test
-
-
-CONF = config.CONF
-
-
-def check_client_version(client, version):
-    """Checks if the client's version is compatible with the given version
-
-    @param client: The client to check.
-    @param version: The version to compare against.
-    @return: True if the client version is compatible with the given version
-             parameter, False otherwise.
-    """
-    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' %
-                                          client)
-
-    return versionutils.is_compatible(version, current_version,
-                                      same_major=False)
-
-
-def min_client_version(*args, **kwargs):
-    """A decorator to skip tests if the client used isn't of the right version.
-
-    @param client: The client command to run. For python-novaclient, this is
-                   'nova', for python-cinderclient this is 'cinder', etc.
-    @param version: The minimum version required to run the CLI test.
-    """
-    def decorator(func):
-        @functools.wraps(func)
-        def wrapper(*func_args, **func_kwargs):
-            if not check_client_version(kwargs['client'], kwargs['version']):
-                msg = "requires %s client version >= %s" % (kwargs['client'],
-                                                            kwargs['version'])
-                raise testtools.TestCase.skipException(msg)
-            return func(*func_args, **func_kwargs)
-        return wrapper
-    return decorator
-
-
-class ClientTestBase(test.BaseTestCase):
-
-    @classmethod
-    def skip_checks(cls):
-        super(ClientTestBase, cls).skip_checks()
-        if not CONF.identity_feature_enabled.api_v2:
-            raise cls.skipException("CLI clients rely on identity v2 API, "
-                                    "which is configured as not available")
-
-    @classmethod
-    def resource_setup(cls):
-        if not CONF.cli.enabled:
-            msg = "cli testing disabled"
-            raise cls.skipException(msg)
-        super(ClientTestBase, cls).resource_setup()
-        cls.isolated_creds = credentials.get_isolated_credentials(cls.__name__)
-        cls.creds = cls.isolated_creds.get_admin_creds()
-
-    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
-
-    # 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/README.txt b/tempest/cli/simple_read_only/README.txt
deleted file mode 100644
index ca5fa2f..0000000
--- a/tempest/cli/simple_read_only/README.txt
+++ /dev/null
@@ -1 +0,0 @@
-This directory consists of simple read only python client tests.
diff --git a/tempest/cli/simple_read_only/__init__.py b/tempest/cli/simple_read_only/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/cli/simple_read_only/__init__.py
+++ /dev/null
diff --git a/tempest/cli/simple_read_only/heat_templates/heat_minimal.yaml b/tempest/cli/simple_read_only/heat_templates/heat_minimal.yaml
deleted file mode 100644
index 7dcda39..0000000
--- a/tempest/cli/simple_read_only/heat_templates/heat_minimal.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-HeatTemplateFormatVersion: '2012-12-12'
-Description: Minimal template to test validation
-Parameters:
-  InstanceImage:
-    Description: Glance image name
-    Type: String
-  InstanceType:
-    Description: Nova instance type
-    Type: String
-    Default: m1.small
-    AllowedValues: [m1.tiny, m1.small, m1.medium, m1.large, m1.nano, m1.xlarge, m1.micro]
-    ConstraintDescription: must be a valid nova instance type.
-Resources:
-    InstanceResource:
-        Type: OS::Nova::Server
-        Properties:
-          flavor: {Ref: InstanceType}
-          image: {Ref: InstanceImage}
diff --git a/tempest/cli/simple_read_only/heat_templates/heat_minimal_hot.yaml b/tempest/cli/simple_read_only/heat_templates/heat_minimal_hot.yaml
deleted file mode 100644
index 4657bfc..0000000
--- a/tempest/cli/simple_read_only/heat_templates/heat_minimal_hot.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
-heat_template_version: 2013-05-23
-description: A minimal HOT test template
-parameters:
-  instance_image:
-    description: Glance image name
-    type: string
-  instance_type:
-    description: Nova instance type
-    type: string
-    default: m1.small
-    constraints:
-        - allowed_values: [m1.small, m1.medium, m1.large]
-          description: instance_type must be one of m1.small, m1.medium or m1.large
-resources:
-    instance:
-        type: OS::Nova::Server
-        properties:
-            image: { get_param: instance_image }
-            flavor: { get_param: instance_type }
diff --git a/tempest/cli/simple_read_only/image/__init__.py b/tempest/cli/simple_read_only/image/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/cli/simple_read_only/image/__init__.py
+++ /dev/null
diff --git a/tempest/cli/simple_read_only/image/test_glance.py b/tempest/cli/simple_read_only/image/test_glance.py
deleted file mode 100644
index e38ca48..0000000
--- a/tempest/cli/simple_read_only/image/test_glance.py
+++ /dev/null
@@ -1,106 +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.
-
-import re
-
-from oslo_log import log as logging
-from tempest_lib import exceptions
-
-from tempest import cli
-from tempest import config
-from tempest import test
-
-CONF = config.CONF
-
-LOG = logging.getLogger(__name__)
-
-
-class SimpleReadOnlyGlanceClientTest(cli.ClientTestBase):
-    """Basic, read-only tests for Glance CLI client.
-
-    Checks return values and output of read-only commands.
-    These tests do not presume any content, nor do they create
-    their own. They only verify the structure of output if present.
-    """
-
-    @classmethod
-    def resource_setup(cls):
-        if not CONF.service_available.glance:
-            msg = ("%s skipped as Glance is not available" % cls.__name__)
-            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)
-
-    @test.idempotent_id('c6bd9bf9-717f-4458-8d74-05b682ea7adf')
-    def test_glance_fake_action(self):
-        self.assertRaises(exceptions.CommandFailed,
-                          self.glance,
-                          'this-does-not-exist')
-
-    @test.idempotent_id('72bcdaf3-11cd-48cb-bb8e-62b329acc1ef')
-    def test_glance_image_list(self):
-        out = self.glance('image-list')
-        endpoints = self.parser.listing(out)
-        self.assertTableStruct(endpoints, [
-            'ID', 'Name', 'Disk Format', 'Container Format',
-            'Size', 'Status'])
-
-    @test.idempotent_id('965d294c-8772-4899-ba33-26ee23406135')
-    def test_glance_member_list(self):
-        tenant_name = '--tenant-id %s' % CONF.identity.admin_tenant_name
-        out = self.glance('member-list',
-                          params=tenant_name)
-        endpoints = self.parser.listing(out)
-        self.assertTableStruct(endpoints,
-                               ['Image ID', 'Member ID', 'Can Share'])
-
-    @test.idempotent_id('43b80ee5-4297-47f3-ab4c-6f81b9c6edb3')
-    def test_glance_help(self):
-        help_text = self.glance('help')
-        lines = help_text.split('\n')
-        self.assertFirstLineStartsWith(lines, 'usage: glance')
-
-        commands = []
-        cmds_start = lines.index('Positional arguments:')
-        cmds_end = lines.index('Optional arguments:')
-        command_pattern = re.compile('^ {4}([a-z0-9\-\_]+)')
-        for line in lines[cmds_start:cmds_end]:
-            match = command_pattern.match(line)
-            if match:
-                commands.append(match.group(1))
-        commands = set(commands)
-        wanted_commands = set(('image-create', 'image-delete', 'help',
-                               'image-download', 'image-show', 'image-update',
-                               'member-create', 'member-delete',
-                               'member-list', 'image-list'))
-        self.assertFalse(wanted_commands - commands)
-
-    # Optional arguments:
-
-    @test.idempotent_id('3b2359ea-3719-4b47-81e5-44a042572b11')
-    def test_glance_version(self):
-        self.glance('', flags='--version')
-
-    @test.idempotent_id('1a52d3bd-3edf-4d67-b3da-999a5d9e0c5e')
-    def test_glance_debug_list(self):
-        self.glance('image-list', flags='--debug')
-
-    @test.idempotent_id('6f42b076-f9a7-4e2b-a729-579f53e7814e')
-    def test_glance_timeout(self):
-        self.glance('image-list', flags='--timeout %d' % CONF.cli.timeout)
diff --git a/tempest/cli/simple_read_only/orchestration/__init__.py b/tempest/cli/simple_read_only/orchestration/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/cli/simple_read_only/orchestration/__init__.py
+++ /dev/null
diff --git a/tempest/cli/simple_read_only/orchestration/test_heat.py b/tempest/cli/simple_read_only/orchestration/test_heat.py
deleted file mode 100644
index 8defe51..0000000
--- a/tempest/cli/simple_read_only/orchestration/test_heat.py
+++ /dev/null
@@ -1,117 +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.
-
-import json
-import os
-
-from oslo_log import log as logging
-import yaml
-
-import tempest.cli
-from tempest import config
-from tempest import test
-
-CONF = config.CONF
-
-LOG = logging.getLogger(__name__)
-
-
-class SimpleReadOnlyHeatClientTest(tempest.cli.ClientTestBase):
-    """Basic, read-only tests for Heat CLI client.
-
-    Basic smoke test for the heat CLI commands which do not require
-    creating or modifying stacks.
-    """
-
-    @classmethod
-    def resource_setup(cls):
-        if (not CONF.service_available.heat):
-            msg = ("Skipping all Heat cli tests because it is "
-                   "not available")
-            raise cls.skipException(msg)
-        super(SimpleReadOnlyHeatClientTest, cls).resource_setup()
-        cls.heat_template_path = os.path.join(os.path.dirname(
-            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)
-
-    @test.idempotent_id('0ae034bb-ce35-45e8-b7aa-3e339cd3140f')
-    def test_heat_stack_list(self):
-        self.heat('stack-list')
-
-    @test.idempotent_id('a360d069-7250-4aed-9721-0a6f2db7c3fa')
-    def test_heat_stack_list_debug(self):
-        self.heat('stack-list', flags='--debug')
-
-    @test.idempotent_id('e1b7c177-5ab4-4d3f-8a26-ea01ebbd2b8c')
-    def test_heat_resource_template_fmt_default(self):
-        ret = self.heat('resource-template OS::Nova::Server')
-        self.assertIn('Type: OS::Nova::Server', ret)
-
-    @test.idempotent_id('93f82f76-aab2-4910-9359-11cf48f2a46b')
-    def test_heat_resource_template_fmt_arg_short_yaml(self):
-        ret = self.heat('resource-template -F yaml OS::Nova::Server')
-        self.assertIn('Type: OS::Nova::Server', ret)
-        self.assertIsInstance(yaml.safe_load(ret), dict)
-
-    @test.idempotent_id('7356a98c-e14d-43f0-8c25-c9f7daa0aafa')
-    def test_heat_resource_template_fmt_arg_long_json(self):
-        ret = self.heat('resource-template --format json OS::Nova::Server')
-        self.assertIn('"Type": "OS::Nova::Server"', ret)
-        self.assertIsInstance(json.loads(ret), dict)
-
-    @test.idempotent_id('2fd99d20-beff-4667-b42e-de9095f671d7')
-    def test_heat_resource_type_list(self):
-        ret = self.heat('resource-type-list')
-        rsrc_types = self.parser.listing(ret)
-        self.assertTableStruct(rsrc_types, ['resource_type'])
-
-    @test.idempotent_id('62f60dbf-d139-4698-b230-a09fb531d643')
-    def test_heat_resource_type_show(self):
-        rsrc_schema = self.heat('resource-type-show OS::Nova::Server')
-        # resource-type-show returns a json resource schema
-        self.assertIsInstance(json.loads(rsrc_schema), dict)
-
-    @test.idempotent_id('6ca16ff7-9d5f-4448-a8c2-4cecc7b5ba3a')
-    def test_heat_template_validate_yaml(self):
-        ret = self.heat('template-validate -f %s' % self.heat_template_path)
-        # On success template-validate returns a json representation
-        # of the template parameters
-        self.assertIsInstance(json.loads(ret), dict)
-
-    @test.idempotent_id('35241014-16ea-4cb6-ad3e-4ee5f41446de')
-    def test_heat_template_validate_hot(self):
-        ret = self.heat('template-validate -f %s' % self.heat_template_path)
-        self.assertIsInstance(json.loads(ret), dict)
-
-    @test.idempotent_id('34d43e0a-36dc-4ea8-9b85-0189e3de89d8')
-    def test_heat_help(self):
-        self.heat('help')
-
-    @tempest.cli.min_client_version(client='heat', version='0.2.7')
-    @test.idempotent_id('c122c08b-839d-49d1-afd1-bc546b2d18d3')
-    def test_heat_bash_completion(self):
-        self.heat('bash-completion')
-
-    @test.idempotent_id('1b045e12-2fa0-4895-9282-00668428dfbe')
-    def test_heat_help_cmd(self):
-        # Check requesting help for a specific command works
-        help_text = self.heat('help resource-template')
-        lines = help_text.split('\n')
-        self.assertFirstLineStartsWith(lines, 'usage: heat resource-template')
-
-    @test.idempotent_id('c7837f8f-d0a8-47fd-b75b-14ba3e3fa9a2')
-    def test_heat_version(self):
-        self.heat('', flags='--version')
diff --git a/tempest/cli/simple_read_only/volume/__init__.py b/tempest/cli/simple_read_only/volume/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/cli/simple_read_only/volume/__init__.py
+++ /dev/null
diff --git a/tempest/cli/simple_read_only/volume/test_cinder.py b/tempest/cli/simple_read_only/volume/test_cinder.py
deleted file mode 100644
index cb29cc8..0000000
--- a/tempest/cli/simple_read_only/volume/test_cinder.py
+++ /dev/null
@@ -1,220 +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.
-
-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 test
-
-
-CONF = config.CONF
-LOG = logging.getLogger(__name__)
-
-
-class SimpleReadOnlyCinderClientTest(cli.ClientTestBase):
-    """Basic, read-only tests for Cinder CLI client.
-
-    Checks return values and output of read-only commands.
-    These tests do not presume any content, nor do they create
-    their own. They only verify the structure of output if present.
-    """
-
-    @classmethod
-    def resource_setup(cls):
-        if not CONF.service_available.cinder:
-            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)
-
-    @test.idempotent_id('229bc6dc-d804-4668-b753-b590caf63061')
-    def test_cinder_fake_action(self):
-        self.assertRaises(exceptions.CommandFailed,
-                          self.cinder,
-                          'this-does-not-exist')
-
-    @test.idempotent_id('77140216-14db-4fc5-a246-e2a587e9e99b')
-    def test_cinder_absolute_limit_list(self):
-        roles = self.parser.listing(self.cinder('absolute-limits'))
-        self.assertTableStruct(roles, ['Name', 'Value'])
-
-    @test.idempotent_id('2206b9ce-1a36-4a0a-a129-e5afc7cee1dd')
-    def test_cinder_backup_list(self):
-        backup_list = self.parser.listing(self.cinder('backup-list'))
-        self.assertTableStruct(backup_list, ['ID', 'Volume ID', 'Status',
-                                             'Name', 'Size', 'Object Count',
-                                             'Container'])
-
-    @test.idempotent_id('c7f50346-cd99-4e0b-953f-796ff5f47295')
-    def test_cinder_extra_specs_list(self):
-        extra_specs_list = self.parser.listing(self.cinder('extra-specs-list'))
-        self.assertTableStruct(extra_specs_list, ['ID', 'Name', 'extra_specs'])
-
-    @test.idempotent_id('9de694cb-b40b-442c-a30c-5f9873e144f7')
-    def test_cinder_volumes_list(self):
-        list = self.parser.listing(self.cinder('list'))
-        self.assertTableStruct(list, ['ID', 'Status', 'Name', 'Size',
-                                      'Volume Type', 'Bootable',
-                                      'Attached to'])
-        self.cinder('list', params='--all-tenants 1')
-        self.cinder('list', params='--all-tenants 0')
-        self.assertRaises(exceptions.CommandFailed,
-                          self.cinder,
-                          'list',
-                          params='--all-tenants bad')
-
-    @test.idempotent_id('56f7c15c-ee82-4f23-bbe8-ce99b66da493')
-    def test_cinder_quota_class_show(self):
-        """This CLI can accept and string as param."""
-        roles = self.parser.listing(self.cinder('quota-class-show',
-                                                params='abc'))
-        self.assertTableStruct(roles, ['Property', 'Value'])
-
-    @test.idempotent_id('a919a811-b7f0-47a7-b4e5-f3eb674dd200')
-    def test_cinder_quota_defaults(self):
-        """This CLI can accept and string as param."""
-        roles = self.parser.listing(self.cinder('quota-defaults',
-                                                params=self.admin_tenant_id))
-        self.assertTableStruct(roles, ['Property', 'Value'])
-
-    @test.idempotent_id('18166673-ffa8-4df3-b60c-6375532288bc')
-    def test_cinder_quota_show(self):
-        """This CLI can accept and string as param."""
-        roles = self.parser.listing(self.cinder('quota-show',
-                                                params=self.admin_tenant_id))
-        self.assertTableStruct(roles, ['Property', 'Value'])
-
-    @test.idempotent_id('b2c66ed9-ca96-4dc4-94cc-8083e664e516')
-    def test_cinder_rate_limits(self):
-        rate_limits = self.parser.listing(self.cinder('rate-limits'))
-        self.assertTableStruct(rate_limits, ['Verb', 'URI', 'Value', 'Remain',
-                                             'Unit', 'Next_Available'])
-
-    @test.idempotent_id('7a19955b-807c-481a-a2ee-9d76733eac28')
-    @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
-                          'Volume snapshot not available.')
-    def test_cinder_snapshot_list(self):
-        snapshot_list = self.parser.listing(self.cinder('snapshot-list'))
-        self.assertTableStruct(snapshot_list, ['ID', 'Volume ID', 'Status',
-                                               'Name', 'Size'])
-
-    @test.idempotent_id('6e54ecd9-7ba9-490d-8e3b-294b67139e73')
-    def test_cinder_type_list(self):
-        type_list = self.parser.listing(self.cinder('type-list'))
-        self.assertTableStruct(type_list, ['ID', 'Name'])
-
-    @test.idempotent_id('2c363583-24a0-4980-b9cb-b50c0d241e82')
-    def test_cinder_list_extensions(self):
-        roles = self.parser.listing(self.cinder('list-extensions'))
-        self.assertTableStruct(roles, ['Name', 'Summary', 'Alias', 'Updated'])
-
-    @test.idempotent_id('691bd6df-30ad-4be7-927b-a02d62aaa38a')
-    def test_cinder_credentials(self):
-        credentials = self.parser.listing(self.cinder('credentials'))
-        self.assertTableStruct(credentials, ['User Credentials', 'Value'])
-
-    @test.idempotent_id('5c6d71a3-4904-4a3a-aec9-7fd4aa830e95')
-    def test_cinder_availability_zone_list(self):
-        zone_list = self.parser.listing(self.cinder('availability-zone-list'))
-        self.assertTableStruct(zone_list, ['Name', 'Status'])
-
-    @test.idempotent_id('9b0fd5a6-f955-42b9-a42f-6f542a80b9a3')
-    def test_cinder_endpoints(self):
-        out = self.cinder('endpoints')
-        tables = self.parser.tables(out)
-        for table in tables:
-            headers = table['headers']
-            self.assertTrue(2 >= len(headers))
-            self.assertEqual('Value', headers[1])
-
-    @test.idempotent_id('301b5ae1-9591-4e9f-999c-d525a9bdf822')
-    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'])
-
-    @test.idempotent_id('7260ae52-b462-461e-9048-36d0bccf92c6')
-    def test_cinder_transfer_list(self):
-        transfer_list = self.parser.listing(self.cinder('transfer-list'))
-        self.assertTableStruct(transfer_list, ['ID', 'Volume ID', 'Name'])
-
-    @test.idempotent_id('0976dea8-14f3-45a9-8495-3617fc4fbb13')
-    def test_cinder_bash_completion(self):
-        self.cinder('bash-completion')
-
-    @test.idempotent_id('b7c00361-be80-4512-8735-5f98fc54f2a9')
-    def test_cinder_qos_list(self):
-        qos_list = self.parser.listing(self.cinder('qos-list'))
-        self.assertTableStruct(qos_list, ['ID', 'Name', 'Consumer', 'specs'])
-
-    @test.idempotent_id('2e92dc6e-22b5-4d94-abfc-b543b0c50a89')
-    def test_cinder_encryption_type_list(self):
-        encrypt_list = self.parser.listing(self.cinder('encryption-type-list'))
-        self.assertTableStruct(encrypt_list, ['Volume Type ID', 'Provider',
-                                              'Cipher', 'Key Size',
-                                              'Control Location'])
-
-    @test.idempotent_id('0ee6cb4c-8de6-4811-a7be-7f4bb75b80cc')
-    def test_admin_help(self):
-        help_text = self.cinder('help')
-        lines = help_text.split('\n')
-        self.assertFirstLineStartsWith(lines, 'usage: cinder')
-
-        commands = []
-        cmds_start = lines.index('Positional arguments:')
-        cmds_end = lines.index('Optional arguments:')
-        command_pattern = re.compile('^ {4}([a-z0-9\-\_]+)')
-        for line in lines[cmds_start:cmds_end]:
-            match = command_pattern.match(line)
-            if match:
-                commands.append(match.group(1))
-        commands = set(commands)
-        wanted_commands = set(('absolute-limits', 'list', 'help',
-                               'quota-show', 'type-list', 'snapshot-list'))
-        self.assertFalse(wanted_commands - commands)
-
-    # Optional arguments:
-
-    @test.idempotent_id('2fd6f530-183c-4bda-8918-1e59e36c26b9')
-    def test_cinder_version(self):
-        self.cinder('', flags='--version')
-
-    @test.idempotent_id('306bac51-c443-4426-a6cf-583a953fcd68')
-    def test_cinder_debug_list(self):
-        self.cinder('list', flags='--debug')
-
-    @test.idempotent_id('6d97fcd2-5dd1-429d-af70-030c949d86cd')
-    def test_cinder_retries_list(self):
-        self.cinder('list', flags='--retries 3')
-
-    @test.idempotent_id('95a2850c-35b4-4159-bb93-51647a5ad232')
-    def test_cinder_region_list(self):
-        region = CONF.volume.region
-        if not region:
-            region = CONF.identity.region
-        self.cinder('list', flags='--os-region-name ' + region)
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index b2311b0..4e2af76 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -114,6 +114,7 @@
 import netaddr
 from oslo_log import log as logging
 from oslo_utils import timeutils
+import six
 from tempest_lib import auth
 from tempest_lib import exceptions as lib_exc
 import yaml
@@ -416,7 +417,7 @@
         that things like tenantId didn't drift across versions.
         """
         LOG.info("checking users")
-        for name, user in self.users.iteritems():
+        for name, user in six.iteritems(self.users):
             client = keystone_admin()
             found = client.identity.get_user(user['id'])
             self.assertEqual(found['name'], user['name'])
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index f1965bc..70a8594 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -335,25 +335,28 @@
         CONF_PARSER.optionxform = str
         CONF_PARSER.readfp(conf_file)
     icreds = credentials.get_isolated_credentials('verify_tempest_config')
-    os = clients.Manager(icreds.get_primary_creds())
-    services = check_service_availability(os, update)
-    results = {}
-    for service in ['nova', 'cinder', 'neutron', 'swift']:
-        if service not in services:
-            continue
-        results = verify_extensions(os, service, results)
+    try:
+        os = clients.Manager(icreds.get_primary_creds())
+        services = check_service_availability(os, update)
+        results = {}
+        for service in ['nova', 'cinder', 'neutron', 'swift']:
+            if service not in services:
+                continue
+            results = verify_extensions(os, service, results)
 
-    # Verify API versions of all services in the keystone catalog and keystone
-    # itself.
-    services.append('keystone')
-    for service in services:
-        verify_api_versions(os, service, update)
+        # Verify API versions of all services in the keystone catalog and
+        # keystone itself.
+        services.append('keystone')
+        for service in services:
+            verify_api_versions(os, service, update)
 
-    display_results(results, update, replace)
-    if update:
-        conf_file.close()
-        CONF_PARSER.write(outfile)
-    outfile.close()
+        display_results(results, update, replace)
+        if update:
+            conf_file.close()
+            CONF_PARSER.write(outfile)
+        outfile.close()
+    finally:
+        icreds.clear_isolated_creds()
 
 
 if __name__ == "__main__":
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index 93c8bcf..650faf1 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -17,6 +17,7 @@
 
 from oslo_concurrency import lockutils
 from oslo_log import log as logging
+import six
 import yaml
 
 from tempest import clients
@@ -75,7 +76,7 @@
             if 'resources' in account:
                 resources = account.pop('resources')
             temp_hash = hashlib.md5()
-            temp_hash.update(str(account))
+            temp_hash.update(six.text_type(account).encode('utf-8'))
             temp_hash_key = temp_hash.hexdigest()
             hash_dict['creds'][temp_hash_key] = account
             for role in roles:
@@ -244,17 +245,19 @@
 
     def get_creds_by_roles(self, roles, force_new=False):
         roles = list(set(roles))
-        exist_creds = self.isolated_creds.get(str(roles), None)
+        exist_creds = self.isolated_creds.get(six.text_type(roles).encode(
+            'utf-8'), None)
         # The force kwarg is used to allocate an additional set of creds with
         # the same role list. The index used for the previously allocation
         # in the isolated_creds dict will be moved.
         if exist_creds and not force_new:
             return exist_creds
         elif exist_creds and force_new:
-            new_index = str(roles) + '-' + str(len(self.isolated_creds))
+            new_index = six.text_type(roles).encode('utf-8') + '-' + \
+                six.text_type(len(self.isolated_creds)).encode('utf-8')
             self.isolated_creds[new_index] = exist_creds
         net_creds = self._get_creds(roles=roles)
-        self.isolated_creds[str(roles)] = net_creds
+        self.isolated_creds[six.text_type(roles).encode('utf-8')] = net_creds
         return net_creds
 
     def clear_isolated_creds(self):
@@ -283,8 +286,11 @@
         net_clients = clients.Manager(credentials=credential)
         compute_network_client = net_clients.networks_client
         net_name = self.hash_dict['networks'].get(hash, None)
-        network = fixed_network.get_network_from_name(
-            net_name, compute_network_client)
+        try:
+            network = fixed_network.get_network_from_name(
+                net_name, compute_network_client)
+        except exceptions.InvalidConfiguration:
+            network = {}
         net_creds.set_resources(network=network)
         return net_creds
 
diff --git a/tempest/common/custom_matchers.py b/tempest/common/custom_matchers.py
index 298a94e..839088c 100644
--- a/tempest/common/custom_matchers.py
+++ b/tempest/common/custom_matchers.py
@@ -14,6 +14,7 @@
 
 import re
 
+import six
 from testtools import helpers
 
 
@@ -121,7 +122,7 @@
     """
 
     def match(self, actual):
-        for key, value in actual.iteritems():
+        for key, value in six.iteritems(actual):
             if key in ('content-length', 'x-account-bytes-used',
                        'x-account-container-count', 'x-account-object-count',
                        'x-container-bytes-used', 'x-container-object-count')\
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
index 1557474..2c6e334 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/common/fixed_network.py
@@ -17,6 +17,7 @@
 from tempest_lib import exceptions as lib_exc
 
 from tempest import config
+from tempest import exceptions
 
 CONF = config.CONF
 
@@ -29,51 +30,59 @@
     :param str name: the name of the network to use
     :param NetworksClientJSON compute_networks_client: The network client
         object to use for making the network lists api request
-    :return: The full dictionary for the network in question, unless the
-        network for the supplied name can not be found. In which case a dict
-        with just the name will be returned.
+    :return: The full dictionary for the network in question
     :rtype: dict
+    :raises InvalidConfiguration: If the name provided is invalid, the networks
+        list returns a 404, there are no found networks, or the found network
+        is invalid
     """
     caller = misc_utils.find_test_caller()
+
     if not name:
-        network = {'name': name}
+        raise exceptions.InvalidConfiguration()
+
+    try:
+        networks = compute_networks_client.list_networks(name=name)
+    except lib_exc.NotFound:
+        # In case of nova network, if the fixed_network_name is not
+        # owned by the tenant, and the network client is not an admin
+        # one, list_networks will not find it
+        msg = ('Unable to find network %s. '
+               'Starting instance without specifying a network.' %
+               name)
+        if caller:
+            msg = '(%s) %s' % (caller, msg)
+        LOG.info(msg)
+        raise exceptions.InvalidConfiguration()
+
+    # Check that a network exists, else raise an InvalidConfigurationException
+    if len(networks) == 1:
+        network = sorted(networks)[0]
+    elif len(networks) > 1:
+        msg = ("Network with name: %s had multiple matching networks in the "
+               "list response: %s\n Unable to specify a single network" % (
+                   name, networks))
+        if caller:
+            msg = '(%s) %s' % (caller, msg)
+        LOG.warn(msg)
+        raise exceptions.InvalidConfiguration()
     else:
-        try:
-            resp = compute_networks_client.list_networks(name=name)
-            if isinstance(resp, list):
-                networks = resp
-            elif isinstance(resp, dict):
-                networks = resp['networks']
-            else:
-                raise lib_exc.NotFound()
-            if len(networks) > 0:
-                network = networks[0]
-            else:
-                msg = "Network with name: %s not found" % name
-                if caller:
-                    LOG.warn('(%s) %s' % (caller, msg))
-                else:
-                    LOG.warn(msg)
-                raise lib_exc.NotFound()
-            # To be consistent with network isolation, add name is only
-            # label is available
-            name = network.get('name', network.get('label'))
-            if name:
-                network['name'] = name
-            else:
-                raise lib_exc.NotFound()
-        except lib_exc.NotFound:
-            # In case of nova network, if the fixed_network_name is not
-            # owned by the tenant, and the network client is not an admin
-            # one, list_networks will not find it
-            msg = ('Unable to find network %s. '
-                   'Starting instance without specifying a network.' %
-                   name)
-            if caller:
-                LOG.info('(%s) %s' % (caller, msg))
-            else:
-                LOG.info(msg)
-            network = {'name': name}
+        msg = "Network with name: %s not found" % name
+        if caller:
+            msg = '(%s) %s' % (caller, msg)
+        LOG.warn(msg)
+        raise exceptions.InvalidConfiguration()
+    # To be consistent between neutron and nova network always use name even
+    # if label is used in the api response. If neither is present than then
+    # the returned network is invalid.
+    name = network.get('name') or network.get('label')
+    if not name:
+        msg = "Network found from list doesn't contain a valid name or label"
+        if caller:
+            msg = '(%s) %s' % (caller, msg)
+        LOG.warn(msg)
+        raise exceptions.InvalidConfiguration()
+    network['name'] = name
     return network
 
 
@@ -97,16 +106,17 @@
             msg = ('No valid network provided or created, defaulting to '
                    'fixed_network_name')
             if caller:
-                LOG.debug('(%s) %s' % (caller, msg))
-            else:
-                LOG.debug(msg)
-            network = get_network_from_name(fixed_network_name,
-                                            compute_networks_client)
+                msg = '(%s) %s' % (caller, msg)
+            LOG.debug(msg)
+            try:
+                network = get_network_from_name(fixed_network_name,
+                                                compute_networks_client)
+            except exceptions.InvalidConfiguration:
+                network = {}
     msg = ('Found network %s available for tenant' % network)
     if caller:
-        LOG.info('(%s) %s' % (caller, msg))
-    else:
-        LOG.info(msg)
+        msg = '(%s) %s' % (caller, msg)
+    LOG.info(msg)
     return network
 
 
diff --git a/tempest/common/generator/base_generator.py b/tempest/common/generator/base_generator.py
index f81f405..3e09300 100644
--- a/tempest/common/generator/base_generator.py
+++ b/tempest/common/generator/base_generator.py
@@ -17,8 +17,8 @@
 import functools
 
 import jsonschema
-
 from oslo_log import log as logging
+import six
 
 LOG = logging.getLogger(__name__)
 
@@ -122,7 +122,7 @@
 
         if schema_type == 'object':
             properties = schema["properties"]
-            for attribute, definition in properties.iteritems():
+            for attribute, definition in six.iteritems(properties):
                 current_path = copy.copy(path)
                 if path is not None:
                     current_path.append(attribute)
diff --git a/tempest/common/generator/valid_generator.py b/tempest/common/generator/valid_generator.py
index 0c63bf5..2213b4a 100644
--- a/tempest/common/generator/valid_generator.py
+++ b/tempest/common/generator/valid_generator.py
@@ -14,6 +14,7 @@
 #    under the License.
 
 from oslo_log import log as logging
+import six
 
 import tempest.common.generator.base_generator as base
 
@@ -51,7 +52,7 @@
     @base.simple_generator
     def generate_valid_object(self, schema):
         obj = {}
-        for k, v in schema["properties"].iteritems():
+        for k, v in six.iteritems(schema["properties"]):
             obj[k] = self.generate_valid(v)
         return obj
 
diff --git a/tempest/common/ssh.py b/tempest/common/ssh.py
deleted file mode 100644
index d0e484c..0000000
--- a/tempest/common/ssh.py
+++ /dev/null
@@ -1,151 +0,0 @@
-# Copyright 2012 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.
-
-import select
-import socket
-import time
-import warnings
-
-from oslo_log import log as logging
-import six
-from six import moves
-
-from tempest import exceptions
-
-
-with warnings.catch_warnings():
-    warnings.simplefilter("ignore")
-    import paramiko
-
-
-LOG = logging.getLogger(__name__)
-
-
-class Client(object):
-
-    def __init__(self, host, username, password=None, timeout=300, pkey=None,
-                 channel_timeout=10, look_for_keys=False, key_filename=None):
-        self.host = host
-        self.username = username
-        self.password = password
-        if isinstance(pkey, six.string_types):
-            pkey = paramiko.RSAKey.from_private_key(
-                moves.cStringIO(str(pkey)))
-        self.pkey = pkey
-        self.look_for_keys = look_for_keys
-        self.key_filename = key_filename
-        self.timeout = int(timeout)
-        self.channel_timeout = float(channel_timeout)
-        self.buf_size = 1024
-
-    def _get_ssh_connection(self, sleep=1.5, backoff=1):
-        """Returns an ssh connection to the specified host."""
-        bsleep = sleep
-        ssh = paramiko.SSHClient()
-        ssh.set_missing_host_key_policy(
-            paramiko.AutoAddPolicy())
-        _start_time = time.time()
-        if self.pkey is not None:
-            LOG.info("Creating ssh connection to '%s' as '%s'"
-                     " with public key authentication",
-                     self.host, self.username)
-        else:
-            LOG.info("Creating ssh connection to '%s' as '%s'"
-                     " with password %s",
-                     self.host, self.username, str(self.password))
-        attempts = 0
-        while True:
-            try:
-                ssh.connect(self.host, username=self.username,
-                            password=self.password,
-                            look_for_keys=self.look_for_keys,
-                            key_filename=self.key_filename,
-                            timeout=self.channel_timeout, pkey=self.pkey)
-                LOG.info("ssh connection to %s@%s successfuly created",
-                         self.username, self.host)
-                return ssh
-            except (socket.error,
-                    paramiko.SSHException) as e:
-                if self._is_timed_out(_start_time):
-                    LOG.exception("Failed to establish authenticated ssh"
-                                  " connection to %s@%s after %d attempts",
-                                  self.username, self.host, attempts)
-                    raise exceptions.SSHTimeout(host=self.host,
-                                                user=self.username,
-                                                password=self.password)
-                bsleep += backoff
-                attempts += 1
-                LOG.warning("Failed to establish authenticated ssh"
-                            " connection to %s@%s (%s). Number attempts: %s."
-                            " Retry after %d seconds.",
-                            self.username, self.host, e, attempts, bsleep)
-                time.sleep(bsleep)
-
-    def _is_timed_out(self, start_time):
-        return (time.time() - self.timeout) > start_time
-
-    def exec_command(self, cmd):
-        """
-        Execute the specified command on the server.
-
-        Note that this method is reading whole command outputs to memory, thus
-        shouldn't be used for large outputs.
-
-        :returns: data read from standard output of the command.
-        :raises: SSHExecCommandFailed if command returns nonzero
-                 status. The exception contains command status stderr content.
-        """
-        ssh = self._get_ssh_connection()
-        transport = ssh.get_transport()
-        channel = transport.open_session()
-        channel.fileno()  # Register event pipe
-        channel.exec_command(cmd)
-        channel.shutdown_write()
-        out_data = []
-        err_data = []
-        poll = select.poll()
-        poll.register(channel, select.POLLIN)
-        start_time = time.time()
-
-        while True:
-            ready = poll.poll(self.channel_timeout)
-            if not any(ready):
-                if not self._is_timed_out(start_time):
-                    continue
-                raise exceptions.TimeoutException(
-                    "Command: '{0}' executed on host '{1}'.".format(
-                        cmd, self.host))
-            if not ready[0]:  # If there is nothing to read.
-                continue
-            out_chunk = err_chunk = None
-            if channel.recv_ready():
-                out_chunk = channel.recv(self.buf_size)
-                out_data += out_chunk,
-            if channel.recv_stderr_ready():
-                err_chunk = channel.recv_stderr(self.buf_size)
-                err_data += err_chunk,
-            if channel.closed and not err_chunk and not out_chunk:
-                break
-        exit_status = channel.recv_exit_status()
-        if 0 != exit_status:
-            raise exceptions.SSHExecCommandFailed(
-                command=cmd, exit_status=exit_status,
-                strerror=''.join(err_data))
-        return ''.join(out_data)
-
-    def test_connection_auth(self):
-        """Raises an exception when we can not connect to server via ssh."""
-        connection = self._get_ssh_connection()
-        connection.close()
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 29fb493..bedff1f 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -15,8 +15,8 @@
 import time
 
 import six
+from tempest_lib.common import ssh
 
-from tempest.common import ssh
 from tempest import config
 from tempest import exceptions
 
diff --git a/tempest/config.py b/tempest/config.py
index bcbe41f..a711b33 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -335,6 +335,13 @@
                 help="Does the test environment block migration support "
                 "cinder iSCSI volumes. Note, libvirt doesn't support this, "
                 "see https://bugs.launchpad.net/nova/+bug/1398999"),
+    # TODO(gilliard): Remove live_migrate_paused_instances at juno-eol.
+    cfg.BoolOpt('live_migrate_paused_instances',
+                default=False,
+                help="Does the test system allow live-migration of paused "
+                "instances? Note, this is more than just the ANDing of "
+                "paused and live_migrate, but all 3 should be set to True "
+                "to run those tests"),
     cfg.BoolOpt('vnc_console',
                 default=False,
                 help='Enable VNC console. This configuration value should '
@@ -1091,25 +1098,6 @@
                help="Timeout for unprovisioning an Ironic node.")
 ]
 
-cli_group = cfg.OptGroup(name='cli', title="cli Configuration Options")
-
-CLIGroup = [
-    cfg.BoolOpt('enabled',
-                default=True,
-                help="enable cli tests"),
-    cfg.StrOpt('cli_dir',
-               default='/usr/local/bin',
-               help="directory where python client binaries are located"),
-    cfg.BoolOpt('has_manage',
-                default=True,
-                help=("Whether the tempest run location has access to the "
-                      "*-manage commands. In a pure blackbox environment "
-                      "it will not.")),
-    cfg.IntOpt('timeout',
-               default=15,
-               help="Number of seconds to wait on a CLI timeout"),
-]
-
 negative_group = cfg.OptGroup(name='negative', title="Negative Test Options")
 
 NegativeGroup = [
@@ -1148,7 +1136,6 @@
     (debug_group, DebugGroup),
     (baremetal_group, BaremetalGroup),
     (input_scenario_group, InputScenarioGroup),
-    (cli_group, CLIGroup),
     (negative_group, NegativeGroup)
 ]
 
@@ -1212,7 +1199,6 @@
         self.debug = _CONF.debug
         self.baremetal = _CONF.baremetal
         self.input_scenario = _CONF['input-scenario']
-        self.cli = _CONF.cli
         self.negative = _CONF.negative
         _CONF.set_default('domain_name', self.identity.admin_domain_name,
                           group='identity')
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 09f7016..15617c6 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -128,17 +128,6 @@
     message = "Got identity error"
 
 
-class SSHTimeout(TempestException):
-    message = ("Connection to the %(host)s via SSH timed out.\n"
-               "User: %(user)s, Password: %(password)s")
-
-
-class SSHExecCommandFailed(TempestException):
-    """Raised when remotely executed command returns nonzero status."""
-    message = ("Command '%(command)s', exit status: %(exit_status)d, "
-               "Error:\n%(strerror)s")
-
-
 class ServerUnreachable(TempestException):
     message = "The server is not reachable via the configured network"
 
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 98bacf0..7e0c3b3 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -381,7 +381,7 @@
 
     def _log_net_info(self, exc):
         # network debug is called as part of ssh init
-        if not isinstance(exc, exceptions.SSHTimeout):
+        if not isinstance(exc, lib_exc.SSHTimeout):
             LOG.debug('Network information on a devstack host')
 
     def create_server_snapshot(self, server, name=None):
@@ -741,7 +741,7 @@
         # The target login is assumed to have been configured for
         # key-based authentication by cloud-init.
         try:
-            for net_name, ip_addresses in server['addresses'].iteritems():
+            for net_name, ip_addresses in six.iteritems(server['addresses']):
                 for ip_address in ip_addresses:
                     self.check_vm_connectivity(ip_address['addr'],
                                                username,
@@ -766,7 +766,7 @@
         def ping_remote():
             try:
                 source.ping_host(dest)
-            except exceptions.SSHExecCommandFailed:
+            except lib_exc.SSHExecCommandFailed:
                 LOG.warn('Failed to ping IP: %s via a ssh connection from: %s.'
                          % (dest, source.ssh_client.host))
                 return not should_succeed
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index 5aec01f..eb018eb 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -12,9 +12,9 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import HTMLParser
-import urllib
-import urllib2
+from six.moves import html_parser as HTMLParser
+from six.moves.urllib import parse
+from six.moves.urllib import request
 
 from tempest import config
 from tempest.scenario import manager
@@ -68,11 +68,11 @@
         super(TestDashboardBasicOps, cls).setup_credentials()
 
     def check_login_page(self):
-        response = urllib2.urlopen(CONF.dashboard.dashboard_url)
+        response = request.urlopen(CONF.dashboard.dashboard_url)
         self.assertIn("id_username", response.read())
 
     def user_login(self, username, password):
-        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
+        self.opener = request.build_opener(request.HTTPCookieProcessor())
         response = self.opener.open(CONF.dashboard.dashboard_url).read()
 
         # Grab the CSRF token and default region
@@ -80,14 +80,14 @@
         parser.feed(response)
 
         # Prepare login form request
-        req = urllib2.Request(CONF.dashboard.login_url)
+        req = request.Request(CONF.dashboard.login_url)
         req.add_header('Content-type', 'application/x-www-form-urlencoded')
         req.add_header('Referer', CONF.dashboard.dashboard_url)
         params = {'username': username,
                   'password': password,
                   'region': parser.region,
                   'csrfmiddlewaretoken': parser.csrf_token}
-        self.opener.open(req, urllib.urlencode(params))
+        self.opener.open(req, parse.urlencode(params))
 
     def check_home_page(self):
         response = self.opener.open(CONF.dashboard.dashboard_url)
diff --git a/tempest/scenario/test_load_balancer_basic.py b/tempest/scenario/test_load_balancer_basic.py
index 8f37d74..691c7c9 100644
--- a/tempest/scenario/test_load_balancer_basic.py
+++ b/tempest/scenario/test_load_balancer_basic.py
@@ -16,7 +16,9 @@
 
 import tempfile
 import time
-import urllib2
+
+import six
+from six.moves.urllib import request as urllib2
 
 from tempest.common import commands
 from tempest import config
@@ -158,7 +160,7 @@
         1. SSH to the instance
         2. Start two http backends listening on ports 80 and 88 respectively
         """
-        for server_id, ip in self.server_ips.iteritems():
+        for server_id, ip in six.iteritems(self.server_ips):
             private_key = self.servers_keypairs[server_id]['private_key']
             server_name = self.servers_client.get_server(server_id)['name']
             username = config.scenario.ssh_user
@@ -238,7 +240,7 @@
         but with different ports to listen on.
         """
 
-        for server_id, ip in self.server_fixed_ips.iteritems():
+        for server_id, ip in six.iteritems(self.server_fixed_ips):
             if len(self.server_fixed_ips) == 1:
                 member1 = self._create_member(address=ip,
                                               protocol_port=self.port1,
@@ -307,7 +309,7 @@
             except urllib2.HTTPError:
                 continue
         # Assert that each member of the pool gets balanced at least once
-        for member, counter in counters.iteritems():
+        for member, counter in six.iteritems(counters):
             self.assertGreater(counter, 0, 'Member %s never balanced' % member)
 
     @test.idempotent_id('c0c6f1ca-603b-4509-9c0f-2c63f0d838ee')
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 16ff848..6e67c4b 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -16,6 +16,7 @@
 import netaddr
 
 from oslo_log import log as logging
+import six
 
 from tempest import config
 from tempest.scenario import manager
@@ -93,7 +94,7 @@
 
     @staticmethod
     def define_server_ips(srv):
-        for net_name, nics in srv['addresses'].iteritems():
+        for net_name, nics in six.iteritems(srv['addresses']):
             for nic in nics:
                 if nic['version'] == 6:
                     srv['accessIPv6'] = nic['addr']
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 6c00d09..60eb1c3 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -23,7 +23,7 @@
 import testtools
 
 from tempest import clients
-from tempest.common import cred_provider
+from tempest.common import credentials
 from tempest import config
 from tempest import exceptions
 
@@ -41,7 +41,10 @@
         self.non_ssh_image_pattern = \
             CONF.input_scenario.non_ssh_image_regex
         # Setup clients
-        os = clients.Manager()
+        self.isolated_creds = credentials.get_isolated_credentials(
+            name='ScenarioImageUtils',
+            identity_version=CONF.identity.auth_version)
+        os = clients.Manager(self.isolated_creds.get_primary_creds())
         self.images_client = os.images_client
         self.flavors_client = os.flavors_client
 
@@ -100,8 +103,10 @@
                                             digit=string.digits)
 
     def __init__(self):
-        os = clients.Manager(
-            cred_provider.get_configured_credentials('user', fill_in=False))
+        self.isolated_creds = credentials.get_isolated_credentials(
+            name='InputScenarioUtils',
+            identity_version=CONF.identity.auth_version)
+        os = clients.Manager(self.isolated_creds.get_primary_creds())
         self.images_client = os.images_client
         self.flavors_client = os.flavors_client
         self.image_pattern = CONF.input_scenario.image_regex
@@ -162,7 +167,7 @@
         scenario_utils = InputScenarioUtils()
         scenario_flavor = scenario_utils.scenario_flavors
         scenario_image = scenario_utils.scenario_images
-    except exceptions.InvalidConfiguration:
+    except (exceptions.InvalidConfiguration, TypeError):
         return standard_tests
     for test in testtools.iterate_tests(standard_tests):
         setattr(test, 'scenarios', testscenarios.multiply_scenarios(
diff --git a/tempest/services/baremetal/base.py b/tempest/services/baremetal/base.py
index 4c6a5bf..1461198 100644
--- a/tempest/services/baremetal/base.py
+++ b/tempest/services/baremetal/base.py
@@ -12,9 +12,9 @@
 
 import functools
 import json
-import urllib
 
 import six
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/compute/json/agents_client.py b/tempest/services/compute/json/agents_client.py
index 403437d..c69e483 100644
--- a/tempest/services/compute/json/agents_client.py
+++ b/tempest/services/compute/json/agents_client.py
@@ -13,7 +13,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.api_schema.response.compute.v2_1 import agents as schema
 from tempest.common import service_client
diff --git a/tempest/services/compute/json/baremetal_nodes_client.py b/tempest/services/compute/json/baremetal_nodes_client.py
index e4a4e88..fa2d7f4 100644
--- a/tempest/services/compute/json/baremetal_nodes_client.py
+++ b/tempest/services/compute/json/baremetal_nodes_client.py
@@ -13,7 +13,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.api_schema.response.compute import baremetal_nodes as schema
 from tempest.common import service_client
diff --git a/tempest/services/compute/json/flavors_client.py b/tempest/services/compute/json/flavors_client.py
index 2de43cf..80cbe4d 100644
--- a/tempest/services/compute/json/flavors_client.py
+++ b/tempest/services/compute/json/flavors_client.py
@@ -14,7 +14,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.api_schema.response.compute import flavors_access as schema_access
 from tempest.api_schema.response.compute import flavors_extra_specs \
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 5bad527..9568a5e 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 import json
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api_schema.response.compute.v2_1 import floating_ips as schema
diff --git a/tempest/services/compute/json/hosts_client.py b/tempest/services/compute/json/hosts_client.py
index 088e695..287482f 100644
--- a/tempest/services/compute/json/hosts_client.py
+++ b/tempest/services/compute/json/hosts_client.py
@@ -13,7 +13,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.api_schema.response.compute.v2_1 import hosts as schema
 from tempest.common import service_client
diff --git a/tempest/services/compute/json/images_client.py b/tempest/services/compute/json/images_client.py
index 1223fef..5462efc 100644
--- a/tempest/services/compute/json/images_client.py
+++ b/tempest/services/compute/json/images_client.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 import json
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api_schema.response.compute.v2_1 import images as schema
diff --git a/tempest/services/compute/json/migrations_client.py b/tempest/services/compute/json/migrations_client.py
index a65b655..009992c 100644
--- a/tempest/services/compute/json/migrations_client.py
+++ b/tempest/services/compute/json/migrations_client.py
@@ -13,7 +13,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.api_schema.response.compute import migrations as schema
 from tempest.common import service_client
diff --git a/tempest/services/compute/json/security_groups_client.py b/tempest/services/compute/json/security_groups_client.py
index d8c8d63..2855e13 100644
--- a/tempest/services/compute/json/security_groups_client.py
+++ b/tempest/services/compute/json/security_groups_client.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 import json
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api_schema.response.compute.v2_1 import security_groups as schema
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index c9ba2c3..1af1b37 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -16,8 +16,8 @@
 
 import json
 import time
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api_schema.response.compute.v2_1 import servers as schema
diff --git a/tempest/services/compute/json/services_client.py b/tempest/services/compute/json/services_client.py
index fc2274d..e2d959b 100644
--- a/tempest/services/compute/json/services_client.py
+++ b/tempest/services/compute/json/services_client.py
@@ -15,7 +15,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.api_schema.response.compute import services as schema
 from tempest.common import service_client
diff --git a/tempest/services/compute/json/tenant_usages_client.py b/tempest/services/compute/json/tenant_usages_client.py
index ff6e7a2..b7e2b2a 100644
--- a/tempest/services/compute/json/tenant_usages_client.py
+++ b/tempest/services/compute/json/tenant_usages_client.py
@@ -14,7 +14,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.api_schema.response.compute.v2_1 import tenant_usages as schema
 from tempest.common import service_client
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index ba5921e..4d7a7aa 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -15,8 +15,8 @@
 
 import json
 import time
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.api_schema.response.compute.v2_1 import volumes as schema
diff --git a/tempest/services/database/json/limits_client.py b/tempest/services/database/json/limits_client.py
index ae758bc..f99ceaa 100644
--- a/tempest/services/database/json/limits_client.py
+++ b/tempest/services/database/json/limits_client.py
@@ -13,7 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import urllib
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/database/json/versions_client.py b/tempest/services/database/json/versions_client.py
index aa2fef7..0db9c6a 100644
--- a/tempest/services/database/json/versions_client.py
+++ b/tempest/services/database/json/versions_client.py
@@ -13,7 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import urllib
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index bc90fd1..f3d02a8 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -14,7 +14,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/identity/v3/json/region_client.py b/tempest/services/identity/v3/json/region_client.py
index faaf43c..02df354 100644
--- a/tempest/services/identity/v3/json/region_client.py
+++ b/tempest/services/identity/v3/json/region_client.py
@@ -14,7 +14,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/image/v1/json/image_client.py b/tempest/services/image/v1/json/image_client.py
index ec7900b..5e442fa 100644
--- a/tempest/services/image/v1/json/image_client.py
+++ b/tempest/services/image/v1/json/image_client.py
@@ -18,9 +18,10 @@
 import json
 import os
 import time
-import urllib
 
 from oslo_log import log as logging
+import six
+from six.moves.urllib import parse as urllib
 from tempest_lib.common.utils import misc as misc_utils
 from tempest_lib import exceptions as lib_exc
 
@@ -54,7 +55,7 @@
 
     def _image_meta_from_headers(self, headers):
         meta = {'properties': {}}
-        for key, value in headers.iteritems():
+        for key, value in six.iteritems(headers):
             if key.startswith('x-image-meta-property-'):
                 _key = key[22:]
                 meta['properties'][_key] = value
@@ -80,11 +81,11 @@
         copy_from = fields_copy.pop('copy_from', None)
         if copy_from is not None:
             headers['x-glance-api-copy-from'] = copy_from
-        for key, value in fields_copy.pop('properties', {}).iteritems():
+        for key, value in six.iteritems(fields_copy.pop('properties', {})):
             headers['x-image-meta-property-%s' % key] = str(value)
-        for key, value in fields_copy.pop('api', {}).iteritems():
+        for key, value in six.iteritems(fields_copy.pop('api', {})):
             headers['x-glance-api-property-%s' % key] = str(value)
-        for key, value in fields_copy.iteritems():
+        for key, value in six.iteritems(fields_copy):
             headers['x-image-meta-%s' % key] = str(value)
         return headers
 
diff --git a/tempest/services/image/v2/json/image_client.py b/tempest/services/image/v2/json/image_client.py
index 6b04144..aff8e85 100644
--- a/tempest/services/image/v2/json/image_client.py
+++ b/tempest/services/image/v2/json/image_client.py
@@ -14,9 +14,9 @@
 #    under the License.
 
 import json
-import urllib
 
 import jsonschema
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.common import glance_http
diff --git a/tempest/services/messaging/json/messaging_client.py b/tempest/services/messaging/json/messaging_client.py
index 483ba93..5f6c32a 100644
--- a/tempest/services/messaging/json/messaging_client.py
+++ b/tempest/services/messaging/json/messaging_client.py
@@ -14,9 +14,10 @@
 # limitations under the License.
 
 import json
-import urllib
 import uuid
 
+from six.moves.urllib import parse as urllib
+
 from tempest.api_schema.response.messaging.v1 import queues as queues_schema
 from tempest.common import service_client
 
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 53645a5..e93cc47 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -12,8 +12,8 @@
 
 import json
 import time
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib.common.utils import misc
 from tempest_lib import exceptions as lib_exc
 
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index af00eff..dece763 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -14,9 +14,10 @@
 #    under the License.
 
 import json
-import urllib
 from xml.etree import ElementTree as etree
 
+from six.moves.urllib import parse as urllib
+
 from tempest.common import service_client
 
 
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index ed74de4..8e225b0 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -14,9 +14,10 @@
 #    under the License.
 
 import json
-import urllib
 from xml.etree import ElementTree as etree
 
+from six.moves.urllib import parse as urllib
+
 from tempest.common import service_client
 
 
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index 3466c8a..2265587 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -13,8 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import urllib
-
+import six
 from six.moves import http_client as httplib
 from six.moves.urllib import parse as urlparse
 
@@ -36,7 +35,7 @@
                 headers[str(key)] = metadata[key]
         url = "%s/%s" % (str(container), str(object_name))
         if params:
-            url += '?%s' % urllib.urlencode(params)
+            url += '?%s' % urlparse.urlencode(params)
 
         resp, body = self.put(url, data, headers)
         self.expected_success(201, resp.status)
@@ -52,7 +51,7 @@
         """Delete storage object."""
         url = "%s/%s" % (str(container), str(object_name))
         if params:
-            url += '?%s' % urllib.urlencode(params)
+            url += '?%s' % urlparse.urlencode(params)
         resp, body = self.delete(url, headers={})
         self.expected_success([200, 204], resp.status)
         return resp, body
@@ -234,7 +233,7 @@
         headers = {}
     if hasattr(contents, 'read'):
         conn.putrequest('PUT', path)
-        for header, value in headers.iteritems():
+        for header, value in six.iteritems(headers):
             conn.putheader(header, value)
         if 'Content-Length' not in headers:
             if 'Transfer-Encoding' not in headers:
diff --git a/tempest/services/orchestration/json/orchestration_client.py b/tempest/services/orchestration/json/orchestration_client.py
index debf39b..4d443d3 100644
--- a/tempest/services/orchestration/json/orchestration_client.py
+++ b/tempest/services/orchestration/json/orchestration_client.py
@@ -16,8 +16,8 @@
 import json
 import re
 import time
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.common import service_client
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index 0c01908..554f574 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -13,9 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import urllib
-
 from oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/volume/json/admin/volume_hosts_client.py b/tempest/services/volume/json/admin/volume_hosts_client.py
index 1cd92b7..1dfabaf 100644
--- a/tempest/services/volume/json/admin/volume_hosts_client.py
+++ b/tempest/services/volume/json/admin/volume_hosts_client.py
@@ -14,7 +14,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/volume/json/admin/volume_quotas_client.py b/tempest/services/volume/json/admin/volume_quotas_client.py
index 5092afc..cbab3f0 100644
--- a/tempest/services/volume/json/admin/volume_quotas_client.py
+++ b/tempest/services/volume/json/admin/volume_quotas_client.py
@@ -12,9 +12,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import urllib
-
 from oslo_serialization import jsonutils
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/volume/json/admin/volume_services_client.py b/tempest/services/volume/json/admin/volume_services_client.py
index 1c4433f..94792e0 100644
--- a/tempest/services/volume/json/admin/volume_services_client.py
+++ b/tempest/services/volume/json/admin/volume_services_client.py
@@ -14,7 +14,8 @@
 #    under the License.
 
 import json
-import urllib
+
+from six.moves.urllib import parse as urllib
 
 from tempest.common import service_client
 
diff --git a/tempest/services/volume/json/admin/volume_types_client.py b/tempest/services/volume/json/admin/volume_types_client.py
index 9366984..2436d88 100644
--- a/tempest/services/volume/json/admin/volume_types_client.py
+++ b/tempest/services/volume/json/admin/volume_types_client.py
@@ -14,8 +14,8 @@
 #    under the License.
 
 import json
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.common import service_client
diff --git a/tempest/services/volume/json/snapshots_client.py b/tempest/services/volume/json/snapshots_client.py
index 2140c62..cfa02bd 100644
--- a/tempest/services/volume/json/snapshots_client.py
+++ b/tempest/services/volume/json/snapshots_client.py
@@ -12,9 +12,9 @@
 
 import json
 import time
-import urllib
 
 from oslo_log import log as logging
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.common import service_client
diff --git a/tempest/services/volume/json/volumes_client.py b/tempest/services/volume/json/volumes_client.py
index a82291a..9a08bbd 100644
--- a/tempest/services/volume/json/volumes_client.py
+++ b/tempest/services/volume/json/volumes_client.py
@@ -15,8 +15,8 @@
 
 import json
 import time
-import urllib
 
+from six.moves.urllib import parse as urllib
 from tempest_lib import exceptions as lib_exc
 
 from tempest.common import service_client
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 62e60d6..3f8e537 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -19,12 +19,13 @@
 
 from oslo_log import log as logging
 from oslo_utils import importutils
+import six
 from six import moves
+from tempest_lib.common import ssh
 from tempest_lib.common.utils import data_utils
 
 from tempest import clients
 from tempest.common import isolated_creds
-from tempest.common import ssh
 from tempest import config
 from tempest import exceptions
 from tempest.stress import cleanup
@@ -171,7 +172,7 @@
             test_run = test_obj(manager, max_runs, stop_on_error)
 
             kwargs = test.get('kwargs', {})
-            test_run.setUp(**dict(kwargs.iteritems()))
+            test_run.setUp(**dict(six.iteritems(kwargs)))
 
             LOG.debug("calling Target Object %s" %
                       test_run.__class__.__name__)
diff --git a/tempest/test_discover/test_discover.py b/tempest/test_discover/test_discover.py
index 3fbb8e1..4a4b43a 100644
--- a/tempest/test_discover/test_discover.py
+++ b/tempest/test_discover/test_discover.py
@@ -25,7 +25,7 @@
     suite = unittest.TestSuite()
     base_path = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
     base_path = os.path.split(base_path)[0]
-    for test_dir in ['./tempest/api', './tempest/cli', './tempest/scenario',
+    for test_dir in ['./tempest/api', './tempest/scenario',
                      './tempest/thirdparty']:
         if not pattern:
             suite.addTests(loader.discover(test_dir, top_level_dir=base_path))
diff --git a/tempest/tests/cli/__init__.py b/tempest/tests/cli/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/tests/cli/__init__.py
+++ /dev/null
diff --git a/tempest/tests/cli/test_cli.py b/tempest/tests/cli/test_cli.py
deleted file mode 100644
index 8f18dfc..0000000
--- a/tempest/tests/cli/test_cli.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# 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.
-
-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)
-        def fake(self, expect_skip):
-            if expect_skip:
-                # If we got here, the decorator didn't raise a skipException as
-                # expected so we need to fail.
-                self.fail('Should not have gotten past the decorator.')
-
-        with mock.patch.object(cli_base, 'execute',
-                               return_value=installed) as mock_cmd:
-            if expect_skip:
-                self.assertRaises(testtools.TestCase.skipException, fake,
-                                  self, expect_skip)
-            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):
-        # required, installed, expect_skip
-        cases = (('2.17.0', '2.17.0', False),
-                 ('2.17.0', '2.18.0', False),
-                 ('2.18.0', '2.17.0', True))
-
-        for case in cases:
-            self._test_min_version(*case)
-
-    @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,
-                          cli.check_client_version, 'nova', '2.18.0')
diff --git a/tempest/tests/common/test_accounts.py b/tempest/tests/common/test_accounts.py
index f357bf4..87c4bb3 100644
--- a/tempest/tests/common/test_accounts.py
+++ b/tempest/tests/common/test_accounts.py
@@ -20,6 +20,7 @@
 from oslo_concurrency import lockutils
 from oslo_config import cfg
 from oslotest import mockpatch
+import six
 from tempest_lib import auth
 from tempest_lib.services.identity.v2 import token_client
 
@@ -79,7 +80,7 @@
         hash_list = []
         for account in accounts_list:
             hash = hashlib.md5()
-            hash.update(str(account))
+            hash.update(six.text_type(account).encode('utf-8'))
             temp_hash = hash.hexdigest()
             hash_list.append(temp_hash)
         return hash_list
@@ -265,7 +266,7 @@
             'tempest.common.accounts.read_accounts_yaml',
             return_value=self.test_accounts))
         test_accounts_class = accounts.Accounts('v2', 'test_name')
-        hashes = test_accounts_class.hash_dict['creds'].keys()
+        hashes = list(test_accounts_class.hash_dict['creds'].keys())
         admin_hashes = test_accounts_class.hash_dict['roles'][
             cfg.CONF.identity.admin_role]
         temp_hash = hashes[0]
diff --git a/tempest/tests/negative/test_negative_generators.py b/tempest/tests/negative/test_negative_generators.py
index 2fa6933..78fd80d 100644
--- a/tempest/tests/negative/test_negative_generators.py
+++ b/tempest/tests/negative/test_negative_generators.py
@@ -17,6 +17,7 @@
 
 import jsonschema
 import mock
+import six
 
 from tempest.common.generator import base_generator
 from tempest.common.generator import negative_generator
@@ -101,11 +102,11 @@
 
     class fake_test_class(object):
         def __init__(self, scenario):
-            for k, v in scenario.iteritems():
+            for k, v in six.iteritems(scenario):
                 setattr(self, k, v)
 
     def _validate_result(self, valid_schema, invalid_schema):
-        for k, v in valid_schema.iteritems():
+        for k, v in six.iteritems(valid_schema):
             self.assertTrue(k in invalid_schema)
 
     def test_generator_mandatory_functions(self):
diff --git a/tempest/tests/test_ssh.py b/tempest/tests/test_ssh.py
deleted file mode 100644
index aaacaab..0000000
--- a/tempest/tests/test_ssh.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# Copyright 2014 OpenStack Foundation
-#
-#    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.
-
-import contextlib
-import socket
-import time
-
-import mock
-import testtools
-
-from tempest.common import ssh
-from tempest import exceptions
-from tempest.tests import base
-
-
-class TestSshClient(base.TestCase):
-
-    def test_pkey_calls_paramiko_RSAKey(self):
-        with contextlib.nested(
-            mock.patch('paramiko.RSAKey.from_private_key'),
-            mock.patch('six.moves.cStringIO')) as (rsa_mock, cs_mock):
-            cs_mock.return_value = mock.sentinel.csio
-            pkey = 'mykey'
-            ssh.Client('localhost', 'root', pkey=pkey)
-            rsa_mock.assert_called_once_with(mock.sentinel.csio)
-            cs_mock.assert_called_once_with('mykey')
-            rsa_mock.reset_mock()
-            cs_mock.reset_mock()
-            pkey = mock.sentinel.pkey
-            # Shouldn't call out to load a file from RSAKey, since
-            # a sentinel isn't a basestring...
-            ssh.Client('localhost', 'root', pkey=pkey)
-            self.assertEqual(0, rsa_mock.call_count)
-            self.assertEqual(0, cs_mock.call_count)
-
-    def _set_ssh_connection_mocks(self):
-        client_mock = mock.MagicMock()
-        client_mock.connect.return_value = True
-        return (self.patch('paramiko.SSHClient'),
-                self.patch('paramiko.AutoAddPolicy'),
-                client_mock)
-
-    def test_get_ssh_connection(self):
-        c_mock, aa_mock, client_mock = self._set_ssh_connection_mocks()
-        s_mock = self.patch('time.sleep')
-
-        c_mock.return_value = client_mock
-        aa_mock.return_value = mock.sentinel.aa
-
-        # Test normal case for successful connection on first try
-        client = ssh.Client('localhost', 'root', timeout=2)
-        client._get_ssh_connection(sleep=1)
-
-        aa_mock.assert_called_once_with()
-        client_mock.set_missing_host_key_policy.assert_called_once_with(
-            mock.sentinel.aa)
-        expected_connect = [mock.call(
-            'localhost',
-            username='root',
-            pkey=None,
-            key_filename=None,
-            look_for_keys=False,
-            timeout=10.0,
-            password=None
-        )]
-        self.assertEqual(expected_connect, client_mock.connect.mock_calls)
-        self.assertEqual(0, s_mock.call_count)
-
-    def test_get_ssh_connection_two_attemps(self):
-        c_mock, aa_mock, client_mock = self._set_ssh_connection_mocks()
-
-        c_mock.return_value = client_mock
-        client_mock.connect.side_effect = [
-            socket.error,
-            mock.MagicMock()
-        ]
-
-        client = ssh.Client('localhost', 'root', timeout=1)
-        start_time = int(time.time())
-        client._get_ssh_connection(sleep=1)
-        end_time = int(time.time())
-        self.assertLess((end_time - start_time), 4)
-        self.assertGreater((end_time - start_time), 1)
-
-    def test_get_ssh_connection_timeout(self):
-        c_mock, aa_mock, client_mock = self._set_ssh_connection_mocks()
-
-        c_mock.return_value = client_mock
-        client_mock.connect.side_effect = [
-            socket.error,
-            socket.error,
-            socket.error,
-        ]
-
-        client = ssh.Client('localhost', 'root', timeout=2)
-        start_time = int(time.time())
-        with testtools.ExpectedException(exceptions.SSHTimeout):
-            client._get_ssh_connection()
-        end_time = int(time.time())
-        self.assertLess((end_time - start_time), 5)
-        self.assertGreaterEqual((end_time - start_time), 2)
-
-    def test_exec_command(self):
-        gsc_mock = self.patch('tempest.common.ssh.Client._get_ssh_connection')
-        ito_mock = self.patch('tempest.common.ssh.Client._is_timed_out')
-        select_mock = self.patch('select.poll')
-
-        client_mock = mock.MagicMock()
-        tran_mock = mock.MagicMock()
-        chan_mock = mock.MagicMock()
-        poll_mock = mock.MagicMock()
-
-        def reset_mocks():
-            gsc_mock.reset_mock()
-            ito_mock.reset_mock()
-            select_mock.reset_mock()
-            poll_mock.reset_mock()
-            client_mock.reset_mock()
-            tran_mock.reset_mock()
-            chan_mock.reset_mock()
-
-        select_mock.return_value = poll_mock
-        gsc_mock.return_value = client_mock
-        ito_mock.return_value = True
-        client_mock.get_transport.return_value = tran_mock
-        tran_mock.open_session.return_value = chan_mock
-        poll_mock.poll.side_effect = [
-            [0, 0, 0]
-        ]
-
-        # Test for a timeout condition immediately raised
-        client = ssh.Client('localhost', 'root', timeout=2)
-        with testtools.ExpectedException(exceptions.TimeoutException):
-            client.exec_command("test")
-
-        chan_mock.fileno.assert_called_once_with()
-        chan_mock.exec_command.assert_called_once_with("test")
-        chan_mock.shutdown_write.assert_called_once_with()
-
-        SELECT_POLLIN = 1
-        poll_mock.register.assert_called_once_with(chan_mock, SELECT_POLLIN)
-        poll_mock.poll.assert_called_once_with(10)
-
-        # Test for proper reading of STDOUT and STDERROR and closing
-        # of all file descriptors.
-
-        reset_mocks()
-
-        select_mock.return_value = poll_mock
-        gsc_mock.return_value = client_mock
-        ito_mock.return_value = False
-        client_mock.get_transport.return_value = tran_mock
-        tran_mock.open_session.return_value = chan_mock
-        poll_mock.poll.side_effect = [
-            [1, 0, 0]
-        ]
-        closed_prop = mock.PropertyMock(return_value=True)
-        type(chan_mock).closed = closed_prop
-        chan_mock.recv_exit_status.return_value = 0
-        chan_mock.recv.return_value = ''
-        chan_mock.recv_stderr.return_value = ''
-
-        client = ssh.Client('localhost', 'root', timeout=2)
-        client.exec_command("test")
-
-        chan_mock.fileno.assert_called_once_with()
-        chan_mock.exec_command.assert_called_once_with("test")
-        chan_mock.shutdown_write.assert_called_once_with()
-
-        SELECT_POLLIN = 1
-        poll_mock.register.assert_called_once_with(chan_mock, SELECT_POLLIN)
-        poll_mock.poll.assert_called_once_with(10)
-        chan_mock.recv_ready.assert_called_once_with()
-        chan_mock.recv.assert_called_once_with(1024)
-        chan_mock.recv_stderr_ready.assert_called_once_with()
-        chan_mock.recv_stderr.assert_called_once_with(1024)
-        chan_mock.recv_exit_status.assert_called_once_with()
-        closed_prop.assert_called_once_with()
diff --git a/tox.ini b/tox.ini
index 2f0aa99..88d1302 100644
--- a/tox.ini
+++ b/tox.ini
@@ -47,7 +47,7 @@
 # See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610
 commands =
   find . -type f -name "*.pyc" -delete
-  bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
+  bash tools/pretty_tox.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
 
 [testenv:full-serial]
 sitepackages = {[tempestenv]sitepackages}
@@ -57,7 +57,7 @@
 # See the testrepostiory bug: https://bugs.launchpad.net/testrepository/+bug/1208610
 commands =
   find . -type f -name "*.pyc" -delete
-  bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty|cli)) {posargs}'
+  bash tools/pretty_tox_serial.sh '(?!.*\[.*\bslow\b.*\])(^tempest\.(api|scenario|thirdparty)) {posargs}'
 
 [testenv:heat-slow]
 sitepackages = {[tempestenv]sitepackages}