Merge "Support lack of ephemeral volumes for baremetal"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index ef56ab3..3b0b834 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -747,10 +747,10 @@
 
 # The cidr block to allocate tenant ipv6 subnets from (string
 # value)
-#tenant_network_v6_cidr=2003::/64
+#tenant_network_v6_cidr=2003::/48
 
 # The mask bits for tenant ipv6 subnets (integer value)
-#tenant_network_v6_mask_bits=96
+#tenant_network_v6_mask_bits=64
 
 # Whether tenant network connectivity should be evaluated
 # directly (boolean value)
@@ -843,6 +843,15 @@
 # expected to be enabled (list value)
 #discoverable_apis=all
 
+# Execute (old style) container-sync tests (boolean value)
+#container_sync=true
+
+# Execute object-versioning tests (boolean value)
+#object_versioning=true
+
+# Execute discoverability tests (boolean value)
+#discoverability=true
+
 
 [orchestration]
 
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index d27d78b..93ed7ae 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -57,9 +57,9 @@
         resp, quota_set = self.adm_client.get_default_quota_set(
             self.demo_tenant_id)
         self.assertEqual(200, resp.status)
-        self.assertEqual(sorted(expected_quota_set),
-                         sorted(quota_set.keys()))
         self.assertEqual(quota_set['id'], self.demo_tenant_id)
+        for quota in expected_quota_set:
+            self.assertIn(quota, quota_set.keys())
 
     @test.attr(type='gate')
     def test_update_all_quota_resources_for_tenant(self):
@@ -79,10 +79,18 @@
             **new_quota_set)
 
         default_quota_set.pop('id')
+        # NOTE(PhilDay) The following is safe as we're not updating these
+        # two quota values yet.  Once the Nova change to add these is merged
+        # and the client updated to support them this can be removed
+        if 'server_groups' in default_quota_set:
+            default_quota_set.pop('server_groups')
+        if 'server_group_members' in default_quota_set:
+            default_quota_set.pop('server_group_members')
         self.addCleanup(self.adm_client.update_quota_set,
                         self.demo_tenant_id, **default_quota_set)
         self.assertEqual(200, resp.status)
-        self.assertEqual(new_quota_set, quota_set)
+        for quota in new_quota_set:
+            self.assertIn(quota, quota_set.keys())
 
     # TODO(afazekas): merge these test cases
     @test.attr(type='gate')
diff --git a/tempest/api/identity/admin/test_tokens.py b/tempest/api/identity/admin/test_tokens.py
index e1db008..2c5fb74 100644
--- a/tempest/api/identity/admin/test_tokens.py
+++ b/tempest/api/identity/admin/test_tokens.py
@@ -35,10 +35,9 @@
                                           tenant['id'], '')
         self.data.users.append(user)
         # then get a token for the user
-        rsp, body = self.token_client.auth(user_name,
-                                           user_password,
-                                           tenant['name'])
-        self.assertEqual(rsp['status'], '200')
+        _, body = self.token_client.auth(user_name,
+                                         user_password,
+                                         tenant['name'])
         self.assertEqual(body['token']['tenant']['name'],
                          tenant['name'])
         # Perform GET Token
@@ -89,15 +88,13 @@
                                      role['id'])
 
         # Get an unscoped token.
-        resp, body = self.token_client.auth(user_name, user_password)
-        self.assertEqual(200, resp.status)
+        _, body = self.token_client.auth(user_name, user_password)
 
         token_id = body['token']['id']
 
         # Use the unscoped token to get a token scoped to tenant1
-        resp, body = self.token_client.auth_token(token_id,
-                                                  tenant=tenant1_name)
-        self.assertEqual(200, resp.status)
+        _, body = self.token_client.auth_token(token_id,
+                                               tenant=tenant1_name)
 
         scoped_token_id = body['token']['id']
 
@@ -105,9 +102,8 @@
         self.client.delete_token(scoped_token_id)
 
         # Use the unscoped token to get a token scoped to tenant2
-        resp, body = self.token_client.auth_token(token_id,
-                                                  tenant=tenant2_name)
-        self.assertEqual(200, resp.status)
+        _, body = self.token_client.auth_token(token_id,
+                                               tenant=tenant2_name)
 
 
 class TokensTestXML(TokensTestJSON):
diff --git a/tempest/api/identity/admin/test_users.py b/tempest/api/identity/admin/test_users.py
index 5838da3..d3ac6dd 100644
--- a/tempest/api/identity/admin/test_users.py
+++ b/tempest/api/identity/admin/test_users.py
@@ -97,10 +97,9 @@
         self.token_client.auth(self.data.test_user, self.data.test_password,
                                self.data.test_tenant)
         # Re-auth
-        resp, body = self.token_client.auth(self.data.test_user,
-                                            self.data.test_password,
-                                            self.data.test_tenant)
-        self.assertEqual('200', resp['status'])
+        self.token_client.auth(self.data.test_user,
+                               self.data.test_password,
+                               self.data.test_tenant)
 
     @test.attr(type='gate')
     def test_authentication_request_without_token(self):
@@ -113,10 +112,9 @@
         # Delete the token from database
         self.client.delete_token(token)
         # Re-auth
-        resp, body = self.token_client.auth(self.data.test_user,
-                                            self.data.test_password,
-                                            self.data.test_tenant)
-        self.assertEqual('200', resp['status'])
+        self.token_client.auth(self.data.test_user,
+                               self.data.test_password,
+                               self.data.test_tenant)
         self.client.auth_provider.clear_auth()
 
     @test.attr(type='smoke')
@@ -205,9 +203,8 @@
 
         # Validate the updated password
         # Get a token
-        resp, body = self.token_client.auth(self.data.test_user, new_pass,
-                                            self.data.test_tenant)
-        self.assertEqual('200', resp['status'])
+        _, body = self.token_client.auth(self.data.test_user, new_pass,
+                                         self.data.test_tenant)
         self.assertTrue('id' in body['token'])
 
 
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 2e732fe..1f7cf48 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -141,11 +141,10 @@
         self.client.add_group_user(self.group_body['id'], self.user_body['id'])
         self.addCleanup(self.client.delete_group_user,
                         self.group_body['id'], self.user_body['id'])
-        resp, body = self.token.auth(self.user_body['id'], self.u_password,
-                                     self.project['name'],
-                                     domain=self.domain['name'])
+        _, body = self.token.auth(self.user_body['id'], self.u_password,
+                                  self.project['name'],
+                                  domain=self.domain['name'])
         roles = body['token']['roles']
-        self.assertEqual(resp['status'], '201')
         self.assertEqual(len(roles), 1)
         self.assertEqual(roles[0]['id'], self.role['id'])
         # Revoke role to group on project
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index f6078da..7e21cc3 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -13,41 +13,84 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
+from tempest import exceptions
 from tempest import test
 
 
 class ServicesTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
-    @test.attr(type='gate')
-    def test_update_service(self):
-        # Update description attribute of service
-        name = data_utils.rand_name('service-')
-        serv_type = data_utils.rand_name('type--')
-        desc = data_utils.rand_name('description-')
-        _, body = self.service_client.create_service(name, serv_type,
-                                                     description=desc)
-        # Deleting the service created in this method
-        self.addCleanup(self.service_client.delete_service, body['id'])
+    def _del_service(self, service_id):
+        # Used for deleting the services created in this class
+        self.service_client.delete_service(service_id)
+        # Checking whether service is deleted successfully
+        self.assertRaises(exceptions.NotFound, self.service_client.get_service,
+                          service_id)
 
-        s_id = body['id']
-        resp1_desc = body['description']
+    @test.attr(type='smoke')
+    def test_create_update_get_service(self):
+        # Creating a Service
+        name = data_utils.rand_name('service')
+        serv_type = data_utils.rand_name('type')
+        desc = data_utils.rand_name('description')
+        _, create_service = self.service_client.create_service(
+            serv_type, name=name, description=desc)
+        self.addCleanup(self._del_service, create_service['id'])
+        self.assertIsNotNone(create_service['id'])
 
-        s_desc2 = data_utils.rand_name('desc2-')
-        _, body = self.service_client.update_service(
+        # Verifying response body of create service
+        expected_data = {'name': name, 'type': serv_type, 'description': desc}
+        self.assertDictContainsSubset(expected_data, create_service)
+
+        # Update description
+        s_id = create_service['id']
+        resp1_desc = create_service['description']
+        s_desc2 = data_utils.rand_name('desc2')
+        _, update_service = self.service_client.update_service(
             s_id, description=s_desc2)
-        resp2_desc = body['description']
+        resp2_desc = update_service['description']
+
         self.assertNotEqual(resp1_desc, resp2_desc)
 
         # Get service
-        _, body = self.service_client.get_service(s_id)
-        resp3_desc = body['description']
+        _, fetched_service = self.service_client.get_service(s_id)
+        resp3_desc = fetched_service['description']
 
-        self.assertNotEqual(resp1_desc, resp3_desc)
         self.assertEqual(resp2_desc, resp3_desc)
+        self.assertDictContainsSubset(update_service, fetched_service)
+
+    @test.attr(type='smoke')
+    def test_create_service_without_description(self):
+        # Create a service only with name and type
+        name = data_utils.rand_name('service')
+        serv_type = data_utils.rand_name('type')
+        _, service = self.service_client.create_service(
+            serv_type, name=name)
+        self.addCleanup(self.service_client.delete_service, service['id'])
+        self.assertIn('id', service)
+        expected_data = {'name': name, 'type': serv_type}
+        self.assertDictContainsSubset(expected_data, service)
+
+    @test.attr(type='smoke')
+    def test_list_services(self):
+        # Create, List, Verify and Delete Services
+        service_ids = list()
+        for _ in range(3):
+            name = data_utils.rand_name('service')
+            serv_type = data_utils.rand_name('type')
+            _, create_service = self.service_client.create_service(
+                serv_type, name=name)
+            self.addCleanup(self.service_client.delete_service,
+                            create_service['id'])
+            service_ids.append(create_service['id'])
+
+        # List and Verify Services
+        _, services = self.service_client.list_services()
+        fetched_ids = [service['id'] for service in services]
+        found = [s for s in fetched_ids if s in service_ids]
+        self.assertEqual(len(found), len(service_ids))
 
 
 class ServicesTestXML(ServicesTestJSON):
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index bd08614..68d61f6 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -35,8 +35,7 @@
             email=u_email)
         self.addCleanup(self.client.delete_user, user['id'])
         # Perform Authentication
-        resp, body = self.token.auth(user['id'], u_password)
-        self.assertEqual(201, resp.status)
+        resp, _ = self.token.auth(user['id'], u_password)
         subject_token = resp['x-subject-token']
         # Perform GET Token
         _, token_details = self.client.get_token(subject_token)
@@ -89,7 +88,6 @@
         # Get an unscoped token.
         resp, token_auth = self.token.auth(user=user['id'],
                                            password=user_password)
-        self.assertEqual(201, resp.status)
 
         token_id = resp['x-subject-token']
         orig_expires_at = token_auth['token']['expires_at']
@@ -114,7 +112,6 @@
                                            tenant=project1_name,
                                            domain='Default')
         token1_id = resp['x-subject-token']
-        self.assertEqual(201, resp.status)
 
         self.assertEqual(orig_expires_at, token_auth['token']['expires_at'],
                          'Expiration time should match original token')
@@ -141,10 +138,9 @@
         self.client.delete_token(token1_id)
 
         # Now get another scoped token using the unscoped token.
-        resp, token_auth = self.token.auth(token=token_id,
-                                           tenant=project2_name,
-                                           domain='Default')
-        self.assertEqual(201, resp.status)
+        _, token_auth = self.token.auth(token=token_id,
+                                        tenant=project2_name,
+                                        domain='Default')
 
         self.assertEqual(project2['id'],
                          token_auth['token']['project']['id'])
diff --git a/tempest/api/identity/admin/v3/test_users.py b/tempest/api/identity/admin/v3/test_users.py
index 3c25819..898bcd0 100644
--- a/tempest/api/identity/admin/v3/test_users.py
+++ b/tempest/api/identity/admin/v3/test_users.py
@@ -77,8 +77,7 @@
         new_password = data_utils.rand_name('pass1')
         self.client.update_user_password(user['id'], new_password,
                                          original_password)
-        resp, body = self.token.auth(user['id'], new_password)
-        self.assertEqual(201, resp.status)
+        resp, _ = self.token.auth(user['id'], new_password)
         subject_token = resp['x-subject-token']
         # Perform GET Token to verify and confirm password is updated
         _, token_details = self.client.get_token(subject_token)
diff --git a/tempest/api/network/test_fwaas_extensions.py b/tempest/api/network/test_fwaas_extensions.py
index 6eec79e..9300c5e 100644
--- a/tempest/api/network/test_fwaas_extensions.py
+++ b/tempest/api/network/test_fwaas_extensions.py
@@ -72,15 +72,18 @@
 
         self.client.wait_for_resource_deletion('firewall', fw_id)
 
-    def _wait_for_active(self, fw_id):
+    def _wait_until_ready(self, fw_id):
+        target_states = ('ACTIVE', 'CREATED')
+
         def _wait():
             _, firewall = self.client.show_firewall(fw_id)
             firewall = firewall['firewall']
-            return firewall['status'] == 'ACTIVE'
+            return firewall['status'] in target_states
 
         if not test.call_until_true(_wait, CONF.network.build_timeout,
                                     CONF.network.build_interval):
-            m = 'Timed out waiting for firewall %s to become ACTIVE.' % fw_id
+            m = ("Timed out waiting for firewall %s to reach %s state(s)" %
+                 (fw_id, target_states))
             raise exceptions.TimeoutException(m)
 
     @test.attr(type='smoke')
@@ -190,7 +193,8 @@
         firewall_id = created_firewall['id']
         self.addCleanup(self._try_delete_firewall, firewall_id)
 
-        self._wait_for_active(firewall_id)
+        # Wait for the firewall resource to become ready
+        self._wait_until_ready(firewall_id)
 
         # show a created firewall
         _, firewall = self.client.show_firewall(firewall_id)
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index c6fe817..26f6b8f 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -129,6 +129,7 @@
         for port in ports:
             self.assertEqual(sorted(fields), sorted(port.keys()))
 
+    @test.skip_because(bug="1364166")
     @test.attr(type='smoke')
     def test_update_port_with_second_ip(self):
         # Create a network with two subnets
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index ccc0067..a143659 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -69,10 +69,11 @@
         cls.object_client_alt.auth_provider.clear_auth()
         cls.container_client_alt.auth_provider.clear_auth()
 
-        cls.data = base.DataGenerator(cls.identity_admin_client)
+        cls.data = SwiftDataGenerator(cls.identity_admin_client)
 
     @classmethod
     def tearDownClass(cls):
+        cls.data.teardown_all()
         cls.isolated_creds.clear_isolated_creds()
         super(BaseObjectTest, cls).tearDownClass()
 
@@ -116,3 +117,28 @@
         self.assertThat(resp, custom_matchers.ExistsAllResponseHeaders(
                         target, method))
         self.assertThat(resp, custom_matchers.AreAllWellFormatted())
+
+
+class SwiftDataGenerator(base.DataGenerator):
+
+    def setup_test_user(self, reseller=False):
+        super(SwiftDataGenerator, self).setup_test_user()
+        if reseller:
+            role_name = CONF.object_storage.reseller_admin_role
+        else:
+            role_name = CONF.object_storage.operator_role
+        role_id = self._get_role_id(role_name)
+        self._assign_role(role_id)
+
+    def _get_role_id(self, role_name):
+        try:
+            _, roles = self.client.list_roles()
+            return next(r['id'] for r in roles if r['name'] == role_name)
+        except StopIteration:
+            msg = "Role name '%s' is not found" % role_name
+            raise exceptions.NotFound(msg)
+
+    def _assign_role(self, role_id):
+        self.client.assign_user_role(self.tenant['id'],
+                                     self.user['id'],
+                                     role_id)
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 19e3068..c1eb897 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -18,7 +18,6 @@
 from tempest import clients
 from tempest.common.utils import data_utils
 from tempest import config
-from tempest import exceptions
 from tempest import test
 
 CONF = config.CONF
@@ -33,32 +32,10 @@
         cls.container_name = data_utils.rand_name(name="TestContainer")
         cls.container_client.create_container(cls.container_name)
 
-        cls.data.setup_test_user()
+        cls.data.setup_test_user(reseller=True)
 
         cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
 
-        # Retrieve the ResellerAdmin role id
-        reseller_role_id = None
-        try:
-            _, roles = cls.os_admin.identity_client.list_roles()
-            reseller_role_id = next(r['id'] for r in roles if r['name']
-                                    == CONF.object_storage.reseller_admin_role)
-        except StopIteration:
-            msg = "No ResellerAdmin role found"
-            raise exceptions.NotFound(msg)
-
-        # Retrieve the ResellerAdmin user id
-        reseller_user_id = cls.data.test_credentials.user_id
-
-        # Retrieve the ResellerAdmin tenant id
-        reseller_tenant_id = cls.data.test_credentials.tenant_id
-
-        # Assign the newly created user the appropriate ResellerAdmin role
-        cls.os_admin.identity_client.assign_user_role(
-            reseller_tenant_id,
-            reseller_user_id,
-            reseller_role_id)
-
         # Retrieve a ResellerAdmin auth data and use it to set a quota
         # on the client's account
         cls.reselleradmin_auth_data = \
@@ -97,7 +74,6 @@
     def tearDownClass(cls):
         if hasattr(cls, "container_name"):
             cls.delete_containers([cls.container_name])
-        cls.data.teardown_all()
         super(AccountQuotasTest, cls).tearDownClass()
 
     @test.attr(type="smoke")
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 6afd381..7324c2e 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -33,32 +33,10 @@
         cls.container_name = data_utils.rand_name(name="TestContainer")
         cls.container_client.create_container(cls.container_name)
 
-        cls.data.setup_test_user()
+        cls.data.setup_test_user(reseller=True)
 
         cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
 
-        # Retrieve the ResellerAdmin role id
-        reseller_role_id = None
-        try:
-            _, roles = cls.os_admin.identity_client.list_roles()
-            reseller_role_id = next(r['id'] for r in roles if r['name']
-                                    == CONF.object_storage.reseller_admin_role)
-        except StopIteration:
-            msg = "No ResellerAdmin role found"
-            raise exceptions.NotFound(msg)
-
-        # Retrieve the ResellerAdmin tenant id
-        reseller_user_id = cls.data.test_credentials.user_id
-
-        # Retrieve the ResellerAdmin tenant id
-        reseller_tenant_id = cls.data.test_credentials.tenant_id
-
-        # Assign the newly created user the appropriate ResellerAdmin role
-        cls.os_admin.identity_client.assign_user_role(
-            reseller_tenant_id,
-            reseller_user_id,
-            reseller_role_id)
-
         # Retrieve a ResellerAdmin auth data and use it to set a quota
         # on the client's account
         cls.reselleradmin_auth_data = \
@@ -96,7 +74,6 @@
     def tearDownClass(cls):
         if hasattr(cls, "container_name"):
             cls.delete_containers([cls.container_name])
-        cls.data.teardown_all()
         super(AccountQuotasNegativeTest, cls).tearDownClass()
 
     @test.attr(type=["negative", "smoke"])
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index d615374..69cba1e 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -14,15 +14,14 @@
 #    under the License.
 
 import random
-
 from six import moves
+import testtools
 
 from tempest.api.object_storage import base
 from tempest import clients
 from tempest.common import custom_matchers
 from tempest.common.utils import data_utils
 from tempest import config
-from tempest import exceptions
 from tempest import test
 
 CONF = config.CONF
@@ -45,7 +44,6 @@
     @classmethod
     def tearDownClass(cls):
         cls.delete_containers(cls.containers)
-        cls.data.teardown_all()
         super(AccountTest, cls).tearDownClass()
 
     @test.attr(type='smoke')
@@ -66,35 +64,7 @@
         # the base user of this instance.
         self.data.setup_test_user()
 
-        os_test_user = clients.Manager(
-            self.data.test_credentials)
-
-        # Retrieve the id of an operator role of object storage
-        test_role_id = None
-        swift_role = CONF.object_storage.operator_role
-        try:
-            _, roles = self.os_admin.identity_client.list_roles()
-            test_role_id = next(r['id'] for r in roles if r['name']
-                                == swift_role)
-        except StopIteration:
-            msg = "%s role found" % swift_role
-            raise exceptions.NotFound(msg)
-
-        # Retrieve the test_user id
-        _, users = self.os_admin.identity_client.get_users()
-        test_user_id = next(usr['id'] for usr in users if usr['name']
-                            == self.data.test_user)
-
-        # Retrieve the test_tenant id
-        _, tenants = self.os_admin.identity_client.list_tenants()
-        test_tenant_id = next(tnt['id'] for tnt in tenants if tnt['name']
-                              == self.data.test_tenant)
-
-        # Assign the newly created user the appropriate operator role
-        self.os_admin.identity_client.assign_user_role(
-            test_tenant_id,
-            test_user_id,
-            test_role_id)
+        os_test_user = clients.Manager(self.data.test_credentials)
 
         resp, container_list = \
             os_test_user.account_client.list_account_containers()
@@ -148,6 +118,9 @@
         self.assertEqual(container_list.find(".//bytes").tag, 'bytes')
 
     @test.attr(type='smoke')
+    @testtools.skipIf(
+        not CONF.object_storage_feature_enabled.discoverability,
+        'Discoverability function is disabled')
     def test_list_extensions(self):
         resp, extensions = self.account_client.list_extensions()
 
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index 490672d..e4c46e2 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -47,5 +47,3 @@
         self.assertRaises(exceptions.Unauthorized,
                           self.custom_account_client.list_account_containers,
                           params=params)
-        # delete the user which was created
-        self.data.teardown_all()
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index fc51504..a7d45be 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -27,11 +27,6 @@
         test_os = clients.Manager(cls.data.test_credentials)
         cls.test_auth_data = test_os.auth_provider.auth_data
 
-    @classmethod
-    def tearDownClass(cls):
-        cls.data.teardown_all()
-        super(ObjectTestACLs, cls).tearDownClass()
-
     def setUp(self):
         super(ObjectTestACLs, self).setUp()
         self.container_name = data_utils.rand_name(name='TestContainer')
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index ca53876..1a21ecc 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -29,11 +29,6 @@
         test_os = clients.Manager(cls.data.test_credentials)
         cls.test_auth_data = test_os.auth_provider.auth_data
 
-    @classmethod
-    def tearDownClass(cls):
-        cls.data.teardown_all()
-        super(ObjectACLsNegativeTest, cls).tearDownClass()
-
     def setUp(self):
         super(ObjectACLsNegativeTest, self).setUp()
         self.container_name = data_utils.rand_name(name='TestContainer')
diff --git a/tempest/api/object_storage/test_container_staticweb.py b/tempest/api/object_storage/test_container_staticweb.py
index 581c6d9..28bde24 100644
--- a/tempest/api/object_storage/test_container_staticweb.py
+++ b/tempest/api/object_storage/test_container_staticweb.py
@@ -48,7 +48,6 @@
     def tearDownClass(cls):
         if hasattr(cls, "container_name"):
             cls.delete_containers([cls.container_name])
-        cls.data.teardown_all()
         super(StaticWebTest, cls).tearDownClass()
 
     @test.requires_ext(extension='staticweb', service='object')
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 5f46d01..3e6d58c 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
 import time
 import urlparse
 
@@ -68,6 +69,9 @@
 
     @test.attr(type='slow')
     @test.skip_because(bug='1317133')
+    @testtools.skipIf(
+        not CONF.object_storage_feature_enabled.container_sync,
+        'Old-style container sync function is disabled')
     def test_container_synchronization(self):
         # container to container synchronization
         # to allow/accept sync requests to/from other accounts
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index d1541b9..ad7e068 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -15,7 +15,6 @@
 # under the License.
 
 from tempest.api.object_storage import base
-from tempest import clients
 from tempest.common import custom_matchers
 from tempest import test
 
@@ -25,11 +24,6 @@
     @classmethod
     def setUpClass(cls):
         super(CrossdomainTest, cls).setUpClass()
-        # creates a test user. The test user will set its base_url to the Swift
-        # endpoint and test the healthcheck feature.
-        cls.data.setup_test_user()
-
-        cls.os_test_user = clients.Manager(cls.data.test_credentials)
 
         cls.xml_start = '<?xml version="1.0"?>\n' \
                         '<!DOCTYPE cross-domain-policy SYSTEM ' \
@@ -38,29 +32,16 @@
 
         cls.xml_end = "</cross-domain-policy>"
 
-    @classmethod
-    def tearDownClass(cls):
-        cls.data.teardown_all()
-        super(CrossdomainTest, cls).tearDownClass()
-
     def setUp(self):
         super(CrossdomainTest, self).setUp()
 
-        client = self.os_test_user.account_client
         # Turning http://.../v1/foobar into http://.../
-        client.skip_path()
-
-    def tearDown(self):
-        # clear the base_url for subsequent requests
-        self.os_test_user.account_client.reset_path()
-
-        super(CrossdomainTest, self).tearDown()
+        self.account_client.skip_path()
 
     @test.attr('gate')
     @test.requires_ext(extension='crossdomain', service='object')
     def test_get_crossdomain_policy(self):
-        resp, body = self.os_test_user.account_client.get("crossdomain.xml",
-                                                          {})
+        resp, body = self.account_client.get("crossdomain.xml", {})
 
         self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self.assertTrue(body.startswith(self.xml_start) and
diff --git a/tempest/api/object_storage/test_object_formpost.py b/tempest/api/object_storage/test_object_formpost.py
index dc5585e..a0fb708 100644
--- a/tempest/api/object_storage/test_object_formpost.py
+++ b/tempest/api/object_storage/test_object_formpost.py
@@ -59,7 +59,6 @@
     def tearDownClass(cls):
         cls.account_client.delete_account_metadata(metadata=cls.metadata)
         cls.delete_containers(cls.containers)
-        cls.data.teardown_all()
         super(ObjectFormPostTest, cls).tearDownClass()
 
     def get_multipart_form(self, expires=600):
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index 878bf6d..103bc8e 100644
--- a/tempest/api/object_storage/test_object_formpost_negative.py
+++ b/tempest/api/object_storage/test_object_formpost_negative.py
@@ -59,7 +59,6 @@
     def tearDownClass(cls):
         cls.account_client.delete_account_metadata(metadata=cls.metadata)
         cls.delete_containers(cls.containers)
-        cls.data.teardown_all()
         super(ObjectFormPostNegativeTest, cls).tearDownClass()
 
     def get_multipart_form(self, expires=600):
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 0443a80..159ad5c 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -59,23 +59,23 @@
         object_name_base_1 = object_name + '_01'
         object_name_base_2 = object_name + '_02'
         data_size = MIN_SEGMENT_SIZE
-        self.data = data_utils.arbitrary_string(data_size)
+        self.content = data_utils.arbitrary_string(data_size)
         self._create_object(self.container_name,
                             object_name_base_1,
-                            self.data)
+                            self.content)
         self._create_object(self.container_name,
                             object_name_base_2,
-                            self.data)
+                            self.content)
 
         path_object_1 = '/%s/%s' % (self.container_name,
                                     object_name_base_1)
         path_object_2 = '/%s/%s' % (self.container_name,
                                     object_name_base_2)
         data_manifest = [{'path': path_object_1,
-                          'etag': hashlib.md5(self.data).hexdigest(),
+                          'etag': hashlib.md5(self.content).hexdigest(),
                           'size_bytes': data_size},
                          {'path': path_object_2,
-                          'etag': hashlib.md5(self.data).hexdigest(),
+                          'etag': hashlib.md5(self.content).hexdigest(),
                           'size_bytes': data_size}]
 
         return json.dumps(data_manifest)
@@ -147,7 +147,7 @@
         self.assertIn(int(resp['status']), test.HTTP_SUCCESS)
         self._assertHeadersSLO(resp, 'GET')
 
-        sum_data = self.data + self.data
+        sum_data = self.content + self.content
         self.assertEqual(body, sum_data)
 
     @test.attr(type='gate')
diff --git a/tempest/api/object_storage/test_object_temp_url.py b/tempest/api/object_storage/test_object_temp_url.py
index 264a18a..f5ebce7 100644
--- a/tempest/api/object_storage/test_object_temp_url.py
+++ b/tempest/api/object_storage/test_object_temp_url.py
@@ -59,8 +59,6 @@
 
         cls.delete_containers(cls.containers)
 
-        # delete the user setup created
-        cls.data.teardown_all()
         super(ObjectTempUrlTest, cls).tearDownClass()
 
     def setUp(self):
diff --git a/tempest/api/object_storage/test_object_temp_url_negative.py b/tempest/api/object_storage/test_object_temp_url_negative.py
index 7d26433..28173fe 100644
--- a/tempest/api/object_storage/test_object_temp_url_negative.py
+++ b/tempest/api/object_storage/test_object_temp_url_negative.py
@@ -53,8 +53,6 @@
 
         cls.delete_containers(cls.containers)
 
-        # delete the user setup created
-        cls.data.teardown_all()
         super(ObjectTempUrlNegativeTest, cls).tearDownClass()
 
     def setUp(self):
@@ -69,10 +67,10 @@
 
         # create object
         self.object_name = data_utils.rand_name(name='ObjectTemp')
-        self.data = data_utils.arbitrary_string(size=len(self.object_name),
-                                                base_text=self.object_name)
+        self.content = data_utils.arbitrary_string(size=len(self.object_name),
+                                                   base_text=self.object_name)
         self.object_client.create_object(self.container_name,
-                                         self.object_name, self.data)
+                                         self.object_name, self.content)
 
     def _get_expiry_date(self, expiration_time=1000):
         return int(time.time() + expiration_time)
diff --git a/tempest/api/object_storage/test_object_version.py b/tempest/api/object_storage/test_object_version.py
index 8d2ff9b..971449d 100644
--- a/tempest/api/object_storage/test_object_version.py
+++ b/tempest/api/object_storage/test_object_version.py
@@ -13,10 +13,15 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.object_storage import base
 from tempest.common.utils import data_utils
+from tempest import config
 from tempest import test
 
+CONF = config.CONF
+
 
 class ContainerTest(base.BaseObjectTest):
     @classmethod
@@ -41,6 +46,9 @@
         self.assertEqual(header_value, versioned)
 
     @test.attr(type='smoke')
+    @testtools.skipIf(
+        not CONF.object_storage_feature_enabled.object_versioning,
+        'Object-versioning is disabled')
     def test_versioned_container(self):
         # create container
         vers_container_name = data_utils.rand_name(name='TestVersionContainer')
diff --git a/tempest/api/orchestration/stacks/test_update.py b/tempest/api/orchestration/stacks/test_update.py
index 791a19b..98761ac 100644
--- a/tempest/api/orchestration/stacks/test_update.py
+++ b/tempest/api/orchestration/stacks/test_update.py
@@ -61,7 +61,6 @@
                          self.list_resources(stack_identifier))
 
     @test.attr(type='gate')
-    @test.skip_because(bug='1308682')
     def test_stack_update_add_remove(self):
         stack_name = data_utils.rand_name('heat')
         stack_identifier = self.create_stack(stack_name, self.template)
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index f3b1ad5..769f5e0 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -67,13 +67,13 @@
 
         _, self.volume = self.volume_client.create_volume(
             size=1, display_name=vol_name, volume_type=type_name)
-        self.volume_client.wait_for_volume_status(
-            self.volume['id'], 'available')
         if with_prefix:
             self.volume_id_list_with_prefix.append(self.volume['id'])
         else:
             self.volume_id_list_without_prefix.append(
                 self.volume['id'])
+        self.volume_client.wait_for_volume_status(
+            self.volume['id'], 'available')
 
     @classmethod
     def tearDownClass(cls):
diff --git a/tempest/api_schema/response/compute/v2/hypervisors.py b/tempest/api_schema/response/compute/v2/hypervisors.py
index 1878881..cbb7698 100644
--- a/tempest/api_schema/response/compute/v2/hypervisors.py
+++ b/tempest/api_schema/response/compute/v2/hypervisors.py
@@ -26,11 +26,7 @@
         'items': {
             'type': 'object',
             'properties': {
-                # NOTE: Now the type of 'id' is integer,
-                # but here allows 'string' also because we
-                # will be able to change it to 'uuid' in
-                # the future.
-                'id': {'type': ['integer', 'string']},
+                'uuid': {'type': 'string'},
                 'name': {'type': 'string'}
             }
         }
diff --git a/tempest/cli/simple_read_only/orchestration/test_heat.py b/tempest/cli/simple_read_only/orchestration/test_heat.py
index 8e413a9..019818b 100644
--- a/tempest/cli/simple_read_only/orchestration/test_heat.py
+++ b/tempest/cli/simple_read_only/orchestration/test_heat.py
@@ -56,7 +56,7 @@
 
     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.assertIn('"Type": "OS::Nova::Server"', ret)
         self.assertIsInstance(json.loads(ret), dict)
 
     def test_heat_resource_type_list(self):
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 436162e..3f8db3d 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -21,7 +21,6 @@
 
 import argparse
 import datetime
-import logging
 import os
 import sys
 import unittest
@@ -31,6 +30,7 @@
 import tempest.auth
 from tempest import config
 from tempest import exceptions
+from tempest.openstack.common import log as logging
 from tempest.openstack.common import timeutils
 from tempest.services.compute.json import flavors_client
 from tempest.services.compute.json import servers_client
@@ -362,7 +362,7 @@
     for obj in objects:
         client = client_for_user(obj['owner'])
         r, body = client.objects.delete_object(obj['container'], obj['name'])
-        if not (200 >= int(r['status']) < 299):
+        if not (200 <= int(r['status']) < 299):
             raise ValueError("unable to destroy object: [%s] %s" % (r, body))
 
 
@@ -564,7 +564,6 @@
     destroy_servers(RES['servers'])
     destroy_images(RES['images'])
     destroy_objects(RES['objects'])
-    destroy_servers(RES['servers'])
     destroy_volumes(RES['volumes'])
     destroy_users(RES['users'])
     destroy_tenants(RES['tenants'])
@@ -617,21 +616,10 @@
         config.CONF.set_config_path(OPTS.config_file)
 
 
-def setup_logging(debug=True):
+def setup_logging():
     global LOG
+    logging.setup(__name__)
     LOG = logging.getLogger(__name__)
-    if debug:
-        LOG.setLevel(logging.DEBUG)
-    else:
-        LOG.setLevel(logging.INFO)
-
-    ch = logging.StreamHandler(sys.stdout)
-    ch.setLevel(logging.DEBUG)
-    formatter = logging.Formatter(
-        datefmt='%Y-%m-%d %H:%M:%S',
-        fmt='%(asctime)s.%(msecs).03d - %(levelname)s - %(message)s')
-    ch.setFormatter(formatter)
-    LOG.addHandler(ch)
 
 
 def main():
diff --git a/tempest/common/accounts.py b/tempest/common/accounts.py
index b31c19a..c491169 100644
--- a/tempest/common/accounts.py
+++ b/tempest/common/accounts.py
@@ -127,3 +127,44 @@
         msg = ('If admin credentials are available tenant_isolation should be'
                ' used instead')
         raise NotImplementedError(msg)
+
+
+class NotLockingAccounts(Accounts):
+    """Credentials provider which always returns the first and second
+    configured accounts as primary and alt users.
+    This credential provider can be used in case of serial test execution
+    to preserve the current behaviour of the serial tempest run.
+    """
+
+    def get_creds(self, id):
+        try:
+            # No need to sort the dict as within the same python process
+            # the HASH seed won't change, so subsequent calls to keys()
+            # will return the same result
+            _hash = self.hash_dict.keys()[id]
+        except IndexError:
+            msg = 'Insufficient number of users provided'
+            raise exceptions.InvalidConfiguration(msg)
+        return self.hash_dict[_hash]
+
+    def get_primary_creds(self):
+        if self.isolated_creds.get('primary'):
+            return self.isolated_creds.get('primary')
+        creds = self.get_creds(0)
+        primary_credential = auth.get_credentials(**creds)
+        self.isolated_creds['primary'] = primary_credential
+        return primary_credential
+
+    def get_alt_creds(self):
+        if self.isolated_creds.get('alt'):
+            return self.isolated_creds.get('alt')
+        creds = self.get_creds(1)
+        alt_credential = auth.get_credentials(**creds)
+        self.isolated_creds['alt'] = alt_credential
+        return alt_credential
+
+    def clear_isolated_creds(self):
+        self.isolated_creds = {}
+
+    def get_admin_creds(self):
+        return auth.get_default_credentials("identity_admin", fill_in=False)
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index dca1f86..02c50e4 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -134,6 +134,8 @@
             self.identity_admin_client.users.delete(user)
 
     def _delete_tenant(self, tenant):
+        if CONF.service_available.neutron:
+            self._cleanup_default_secgroup(tenant)
         if self.tempest_client:
             self.identity_admin_client.delete_tenant(tenant)
         else:
@@ -376,6 +378,22 @@
             LOG.warn('network with name: %s not found for delete' %
                      network_name)
 
+    def _cleanup_default_secgroup(self, tenant):
+        net_client = self.network_admin_client
+        if self.tempest_client:
+            resp, resp_body = net_client.list_security_groups(tenant_id=tenant,
+                                                              name="default")
+        else:
+            resp_body = net_client.list_security_groups(tenant_id=tenant,
+                                                        name="default")
+        secgroups_to_delete = resp_body['security_groups']
+        for secgroup in secgroups_to_delete:
+            try:
+                net_client.delete_security_group(secgroup['id'])
+            except exceptions.NotFound:
+                LOG.warn('Security group %s, id %s not found for clean-up' %
+                         (secgroup['name'], secgroup['id']))
+
     def _clear_isolated_net_resources(self):
         net_client = self.network_admin_client
         for cred in self.isolated_net_resources:
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 132d0a6..e584cbf 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -552,7 +552,13 @@
             if self.is_resource_deleted(id):
                 return
             if int(time.time()) - start_time >= self.build_timeout:
-                raise exceptions.TimeoutException
+                message = ('Failed to delete resource %(id)s within the '
+                           'required time (%(timeout)s s).' %
+                           {'id': id, 'timeout': self.build_timeout})
+                caller = misc_utils.find_test_caller()
+                if caller:
+                    message = '(%s) %s' % (caller, message)
+                raise exceptions.TimeoutException(message)
             time.sleep(self.build_interval)
 
     def is_resource_deleted(self, id):
diff --git a/tempest/config.py b/tempest/config.py
index 93d4874..d3449a7 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -419,10 +419,10 @@
                default=28,
                help="The mask bits for tenant ipv4 subnets"),
     cfg.StrOpt('tenant_network_v6_cidr',
-               default="2003::/64",
+               default="2003::/48",
                help="The cidr block to allocate tenant ipv6 subnets from"),
     cfg.IntOpt('tenant_network_v6_mask_bits',
-               default=96,
+               default=64,
                help="The mask bits for tenant ipv6 subnets"),
     cfg.BoolOpt('tenant_networks_reachable',
                 default=False,
@@ -622,6 +622,15 @@
                 help="A list of the enabled optional discoverable apis. "
                      "A single entry, all, indicates that all of these "
                      "features are expected to be enabled"),
+    cfg.BoolOpt('container_sync',
+                default=True,
+                help="Execute (old style) container-sync tests"),
+    cfg.BoolOpt('object_versioning',
+                default=True,
+                help="Execute object-versioning tests"),
+    cfg.BoolOpt('discoverability',
+                default=True,
+                help="Execute discoverability tests"),
 ]
 
 database_group = cfg.OptGroup(name='database',
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index cabefc8..66043d3 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -271,14 +271,18 @@
         _, volume = self.volumes_client.create_volume(
             size=size, display_name=name, snapshot_id=snapshot_id,
             imageRef=imageRef, volume_type=volume_type)
+
         if wait_on_delete:
             self.addCleanup(self.volumes_client.wait_for_resource_deletion,
                             volume['id'])
-        self.addCleanup_with_wait(
-            waiter_callable=self.volumes_client.wait_for_resource_deletion,
-            thing_id=volume['id'], thing_id_param='id',
-            cleanup_callable=self.delete_wrapper,
-            cleanup_args=[self.volumes_client.delete_volume, volume['id']])
+            self.addCleanup(self.delete_wrapper,
+                            self.volumes_client.delete_volume, volume['id'])
+        else:
+            self.addCleanup_with_wait(
+                waiter_callable=self.volumes_client.wait_for_resource_deletion,
+                thing_id=volume['id'], thing_id_param='id',
+                cleanup_callable=self.delete_wrapper,
+                cleanup_args=[self.volumes_client.delete_volume, volume['id']])
 
         self.assertEqual(name, volume['display_name'])
         self.volumes_client.wait_for_volume_status(volume['id'], 'available')
@@ -446,6 +450,24 @@
                   image_name, server['name'])
         return snapshot_image
 
+    def nova_volume_attach(self):
+        # TODO(andreaf) Device should be here CONF.compute.volume_device_name
+        _, volume_attachment = self.servers_client.attach_volume(
+            self.server['id'], self.volume['id'], '/dev/vdb')
+        volume = volume_attachment['volumeAttachment']
+        self.assertEqual(self.volume['id'], volume['id'])
+        self.volumes_client.wait_for_volume_status(volume['id'], 'in-use')
+        # Refresh the volume after the attachment
+        _, self.volume = self.volumes_client.get_volume(volume['id'])
+
+    def nova_volume_detach(self):
+        self.servers_client.detach_volume(self.server['id'], self.volume['id'])
+        self.volumes_client.wait_for_volume_status(self.volume['id'],
+                                                   'available')
+
+        _, volume = self.volumes_client.get_volume(self.volume['id'])
+        self.assertEqual('available', volume['status'])
+
 
 # TODO(yfried): change this class name to NetworkScenarioTest once client
 # migration is complete
@@ -1620,7 +1642,7 @@
             timeout=CONF.baremetal.unprovision_timeout)
 
 
-class EncryptionScenarioTest(OfficialClientTest):
+class EncryptionScenarioTest(ScenarioTest):
     """
     Base class for encryption scenario tests
     """
@@ -1628,11 +1650,7 @@
     @classmethod
     def setUpClass(cls):
         super(EncryptionScenarioTest, cls).setUpClass()
-
-        # use admin credentials to create encrypted volume types
-        admin_creds = cls.admin_credentials()
-        manager = clients.OfficialClientManager(credentials=admin_creds)
-        cls.admin_volume_client = manager.volume_client
+        cls.admin_volume_types_client = cls.admin_manager.volume_types_client
 
     def _wait_for_volume_status(self, status):
         self.status_timeout(
@@ -1640,53 +1658,35 @@
 
     def nova_boot(self):
         self.keypair = self.create_keypair()
-        create_kwargs = {'key_name': self.keypair.name}
-        self.server = self.create_server(self.compute_client,
-                                         image=self.image,
+        create_kwargs = {'key_name': self.keypair['name']}
+        self.server = self.create_server(image=self.image,
                                          create_kwargs=create_kwargs)
 
     def create_volume_type(self, client=None, name=None):
         if not client:
-            client = self.admin_volume_client
+            client = self.admin_volume_types_client
         if not name:
             name = 'generic'
         randomized_name = data_utils.rand_name('scenario-type-' + name + '-')
         LOG.debug("Creating a volume type: %s", randomized_name)
-        volume_type = client.volume_types.create(randomized_name)
-        self.addCleanup(client.volume_types.delete, volume_type.id)
-        return volume_type
+        _, body = client.create_volume_type(
+            randomized_name)
+        self.assertIn('id', body)
+        self.addCleanup(client.delete_volume_type, body['id'])
+        return body
 
     def create_encryption_type(self, client=None, type_id=None, provider=None,
                                key_size=None, cipher=None,
                                control_location=None):
         if not client:
-            client = self.admin_volume_client
+            client = self.admin_volume_types_client
         if not type_id:
             volume_type = self.create_volume_type()
-            type_id = volume_type.id
+            type_id = volume_type['id']
         LOG.debug("Creating an encryption type for volume type: %s", type_id)
-        client.volume_encryption_types.create(type_id,
-                                              {'provider': provider,
-                                               'key_size': key_size,
-                                               'cipher': cipher,
-                                               'control_location':
-                                               control_location})
-
-    def nova_volume_attach(self):
-        attach_volume_client = self.compute_client.volumes.create_server_volume
-        volume = attach_volume_client(self.server.id,
-                                      self.volume.id,
-                                      '/dev/vdb')
-        self.assertEqual(self.volume.id, volume.id)
-        self._wait_for_volume_status('in-use')
-
-    def nova_volume_detach(self):
-        detach_volume_client = self.compute_client.volumes.delete_server_volume
-        detach_volume_client(self.server.id, self.volume.id)
-        self._wait_for_volume_status('available')
-
-        volume = self.volume_client.volumes.get(self.volume.id)
-        self.assertEqual('available', volume.status)
+        client.create_encryption_type(
+            type_id, provider=provider, key_size=key_size, cipher=cipher,
+            control_location=control_location)
 
 
 class NetworkScenarioTest(OfficialClientTest):
diff --git a/tempest/scenario/test_dashboard_basic_ops.py b/tempest/scenario/test_dashboard_basic_ops.py
index 4fcc70a..72cc8b0 100644
--- a/tempest/scenario/test_dashboard_basic_ops.py
+++ b/tempest/scenario/test_dashboard_basic_ops.py
@@ -69,6 +69,7 @@
         response = self.opener.open(CONF.dashboard.dashboard_url)
         self.assertIn('Overview', response.read())
 
+    @test.skip_because(bug="1345955")
     @test.services('dashboard')
     def test_basic_scenario(self):
         self.check_login_page()
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index 366cd93..ac2ef8a 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -37,12 +37,12 @@
 
     def create_encrypted_volume(self, encryption_provider):
         volume_type = self.create_volume_type(name='luks')
-        self.create_encryption_type(type_id=volume_type.id,
+        self.create_encryption_type(type_id=volume_type['id'],
                                     provider=encryption_provider,
                                     key_size=512,
                                     cipher='aes-xts-plain64',
                                     control_location='front-end')
-        self.volume = self.create_volume(volume_type=volume_type.name)
+        self.volume = self.create_volume(volume_type=volume_type['name'])
 
     def attach_detach_volume(self):
         self.nova_volume_attach()
diff --git a/tempest/scenario/test_large_ops.py b/tempest/scenario/test_large_ops.py
index 15cf13b..a7ea70f 100644
--- a/tempest/scenario/test_large_ops.py
+++ b/tempest/scenario/test_large_ops.py
@@ -25,7 +25,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class TestLargeOpsScenario(manager.NetworkScenarioTest):
+class TestLargeOpsScenario(manager.ScenarioTest):
 
     """
     Test large operations.
@@ -44,29 +44,34 @@
 
     def _wait_for_server_status(self, status):
         for server in self.servers:
-            self.status_timeout(
-                self.compute_client.servers, server.id, status)
+            self.servers_client.wait_for_server_status(server['id'], status)
 
     def nova_boot(self):
         name = data_utils.rand_name('scenario-server-')
-        client = self.compute_client
         flavor_id = CONF.compute.flavor_ref
-        secgroup = self._create_security_group_nova()
-        self.servers = client.servers.create(
-            name=name, image=self.image,
-            flavor=flavor_id,
+        secgroup = self._create_security_group()
+        self.servers_client.create_server(
+            name,
+            self.image,
+            flavor_id,
             min_count=CONF.scenario.large_ops_number,
-            security_groups=[secgroup.name])
+            security_groups=[secgroup])
         # needed because of bug 1199788
-        self.servers = [x for x in client.servers.list() if name in x.name]
+        params = {'name': name}
+        _, server_list = self.servers_client.list_servers(params)
+        self.servers = server_list['servers']
         for server in self.servers:
             # after deleting all servers - wait for all servers to clear
             # before cleanup continues
-            self.addCleanup(self.delete_timeout,
-                            self.compute_client.servers,
-                            server.id)
+            self.addCleanup(self.servers_client.wait_for_server_termination,
+                            server['id'])
         for server in self.servers:
-            self.addCleanup_with_wait(self.compute_client.servers, server.id)
+            self.addCleanup_with_wait(
+                waiter_callable=(self.servers_client.
+                                 wait_for_server_termination),
+                thing_id=server['id'], thing_id_param='server_id',
+                cleanup_callable=self.delete_wrapper,
+                cleanup_args=[self.servers_client.delete_server, server['id']])
         self._wait_for_server_status('ACTIVE')
 
     def _large_ops_scenario(self):
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 47f2f1a..c145551 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -25,7 +25,7 @@
 LOG = logging.getLogger(__name__)
 
 
-class TestNetworkAdvancedServerOps(manager.NetworkScenarioTest):
+class TestNetworkAdvancedServerOps(manager.NeutronScenarioTest):
 
     """
     This test case checks VM connectivity after some advanced
@@ -40,9 +40,8 @@
     """
 
     @classmethod
-    def setUpClass(cls):
-        super(TestNetworkAdvancedServerOps, cls).setUpClass()
-        cls.check_preconditions()
+    def check_preconditions(cls):
+        super(TestNetworkAdvancedServerOps, cls).check_preconditions()
         if not (CONF.network.tenant_networks_reachable
                 or CONF.network.public_network_id):
             msg = ('Either tenant_networks_reachable must be "true", or '
@@ -50,20 +49,23 @@
             cls.enabled = False
             raise cls.skipException(msg)
 
-    def _setup_network_and_servers(self):
-        key_name = data_utils.rand_name('keypair-smoke-')
-        self.keypair = self.create_keypair(name=key_name)
-        security_group =\
-            self._create_security_group_neutron(tenant_id=self.tenant_id)
-        network, subnet, router = self.create_networks(self.tenant_id)
+    @classmethod
+    def setUpClass(cls):
+        # Create no network resources for these tests.
+        cls.set_network_resources()
+        super(TestNetworkAdvancedServerOps, cls).setUpClass()
 
+    def _setup_network_and_servers(self):
+        self.keypair = self.create_keypair()
+        security_group = self._create_security_group()
+        network, subnet, router = self.create_networks()
         public_network_id = CONF.network.public_network_id
         create_kwargs = {
             'nics': [
                 {'net-id': network.id},
             ],
-            'key_name': self.keypair.name,
-            'security_groups': [security_group.name],
+            'key_name': self.keypair['name'],
+            'security_groups': [security_group],
         }
         server_name = data_utils.rand_name('server-smoke')
         self.server = self.create_server(name=server_name,
@@ -76,9 +78,10 @@
 
     def _check_network_connectivity(self, should_connect=True):
         username = CONF.compute.image_ssh_user
-        private_key = self.keypair.private_key
+        private_key = self.keypair['private_key']
         self._check_tenant_network_connectivity(
-            self.server, username, private_key, should_connect=should_connect,
+            self.server, username, private_key,
+            should_connect=should_connect,
             servers_for_debug=[self.server])
         floating_ip = self.floating_ip.floating_ip_address
         self._check_public_network_connectivity(floating_ip, username,
@@ -86,31 +89,31 @@
                                                 servers=[self.server])
 
     def _wait_server_status_and_check_network_connectivity(self):
-        self.status_timeout(self.compute_client.servers, self.server.id,
-                            'ACTIVE')
+        self.servers_client.wait_for_server_status(self.server['id'], 'ACTIVE')
         self._check_network_connectivity()
 
     @test.services('compute', 'network')
     def test_server_connectivity_stop_start(self):
         self._setup_network_and_servers()
-        self.server.stop()
-        self.status_timeout(self.compute_client.servers, self.server.id,
-                            'SHUTOFF')
+        self.servers_client.stop(self.server['id'])
+        self.servers_client.wait_for_server_status(self.server['id'],
+                                                   'SHUTOFF')
         self._check_network_connectivity(should_connect=False)
-        self.server.start()
+        self.servers_client.start(self.server['id'])
         self._wait_server_status_and_check_network_connectivity()
 
     @test.services('compute', 'network')
     def test_server_connectivity_reboot(self):
         self._setup_network_and_servers()
-        self.server.reboot()
+        self.servers_client.reboot(self.server['id'], reboot_type='SOFT')
         self._wait_server_status_and_check_network_connectivity()
 
     @test.services('compute', 'network')
     def test_server_connectivity_rebuild(self):
         self._setup_network_and_servers()
         image_ref_alt = CONF.compute.image_ref_alt
-        self.server.rebuild(image_ref_alt)
+        self.servers_client.rebuild(self.server['id'],
+                                    image_ref=image_ref_alt)
         self._wait_server_status_and_check_network_connectivity()
 
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
@@ -118,11 +121,10 @@
     @test.services('compute', 'network')
     def test_server_connectivity_pause_unpause(self):
         self._setup_network_and_servers()
-        self.server.pause()
-        self.status_timeout(self.compute_client.servers, self.server.id,
-                            'PAUSED')
+        self.servers_client.pause_server(self.server['id'])
+        self.servers_client.wait_for_server_status(self.server['id'], 'PAUSED')
         self._check_network_connectivity(should_connect=False)
-        self.server.unpause()
+        self.servers_client.unpause_server(self.server['id'])
         self._wait_server_status_and_check_network_connectivity()
 
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
@@ -130,11 +132,11 @@
     @test.services('compute', 'network')
     def test_server_connectivity_suspend_resume(self):
         self._setup_network_and_servers()
-        self.server.suspend()
-        self.status_timeout(self.compute_client.servers, self.server.id,
-                            'SUSPENDED')
+        self.servers_client.suspend_server(self.server['id'])
+        self.servers_client.wait_for_server_status(self.server['id'],
+                                                   'SUSPENDED')
         self._check_network_connectivity(should_connect=False)
-        self.server.resume()
+        self.servers_client.resume_server(self.server['id'])
         self._wait_server_status_and_check_network_connectivity()
 
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
@@ -146,9 +148,8 @@
             msg = "Skipping test - flavor_ref and flavor_ref_alt are identical"
             raise self.skipException(msg)
         self._setup_network_and_servers()
-        resize_flavor = CONF.compute.flavor_ref_alt
-        self.server.resize(resize_flavor)
-        self.status_timeout(self.compute_client.servers, self.server.id,
-                            'VERIFY_RESIZE')
-        self.server.confirm_resize()
+        self.servers_client.resize(self.server['id'], flavor_ref=resize_flavor)
+        self.servers_client.wait_for_server_status(self.server['id'],
+                                                   'VERIFY_RESIZE')
+        self.servers_client.confirm_resize(self.server['id'])
         self._wait_server_status_and_check_network_connectivity()
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/json/identity_client.py
index ac65f81..e76c1bd 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/json/identity_client.py
@@ -309,6 +309,7 @@
 
         body = json.dumps(creds)
         resp, body = self.post(self.auth_url, body=body)
+        self.expected_success(200, resp.status)
 
         return resp, body['access']
 
@@ -326,6 +327,7 @@
 
         body = json.dumps(creds)
         resp, body = self.post(self.auth_url, body=body)
+        self.expected_success(200, resp.status)
 
         return resp, body['access']
 
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index 0522f37..df424ca 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -588,6 +588,7 @@
 
         body = json.dumps(creds)
         resp, body = self.post(self.auth_url, body=body)
+        self.expected_success(201, resp.status)
         return resp, body
 
     def request(self, method, url, extra_headers=False, headers=None,
diff --git a/tempest/services/identity/v3/json/service_client.py b/tempest/services/identity/v3/json/service_client.py
index 82e8aad..8e89957 100644
--- a/tempest/services/identity/v3/json/service_client.py
+++ b/tempest/services/identity/v3/json/service_client.py
@@ -57,10 +57,10 @@
     def create_service(self, serv_type, name=None, description=None,
                        enabled=True):
         body_dict = {
-            "name": name,
+            'name': name,
             'type': serv_type,
             'enabled': enabled,
-            "description": description,
+            'description': description,
         }
         body = json.dumps({'service': body_dict})
         resp, body = self.post("services", body)
@@ -73,3 +73,9 @@
         resp, body = self.delete(url)
         self.expected_success(204, resp.status)
         return resp, body
+
+    def list_services(self):
+        resp, body = self.get('services')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return resp, body['services']
diff --git a/tempest/services/identity/v3/xml/identity_client.py b/tempest/services/identity/v3/xml/identity_client.py
index 5b761b3..5c43692 100644
--- a/tempest/services/identity/v3/xml/identity_client.py
+++ b/tempest/services/identity/v3/xml/identity_client.py
@@ -590,6 +590,7 @@
             auth.append(scope)
 
         resp, body = self.post(self.auth_url, body=str(common.Document(auth)))
+        self.expected_success(201, resp.status)
         return resp, body
 
     def request(self, method, url, extra_headers=False, headers=None,
diff --git a/tempest/services/identity/v3/xml/service_client.py b/tempest/services/identity/v3/xml/service_client.py
index 3beeb89..14adfac 100644
--- a/tempest/services/identity/v3/xml/service_client.py
+++ b/tempest/services/identity/v3/xml/service_client.py
@@ -37,6 +37,14 @@
         data = common.xml_to_json(body)
         return data
 
+    def _parse_array(self, node):
+        array = []
+        for child in node.getchildren():
+            tag_list = child.tag.split('}', 1)
+            if tag_list[1] == "service":
+                array.append(common.xml_to_json(child))
+        return array
+
     def update_service(self, service_id, **kwargs):
         """Updates a service_id."""
         resp, body = self.get_service(service_id)
@@ -79,3 +87,9 @@
         resp, body = self.delete(url)
         self.expected_success(204, resp.status)
         return resp, body
+
+    def list_services(self):
+        resp, body = self.get('services')
+        self.expected_success(200, resp.status)
+        body = self._parse_array(etree.fromstring(body))
+        return resp, body
diff --git a/tempest/services/identity/xml/identity_client.py b/tempest/services/identity/xml/identity_client.py
index 4ada46c..eaf9390 100644
--- a/tempest/services/identity/xml/identity_client.py
+++ b/tempest/services/identity/xml/identity_client.py
@@ -157,6 +157,7 @@
         auth = xml.Element('auth', **auth_kwargs)
         auth.append(passwordCreds)
         resp, body = self.post(self.auth_url, body=str(xml.Document(auth)))
+        self.expected_success(200, resp.status)
         return resp, body['access']
 
     def auth_token(self, token_id, tenant=None):
@@ -167,4 +168,5 @@
         auth = xml.Element('auth', **auth_kwargs)
         auth.append(tokenCreds)
         resp, body = self.post(self.auth_url, body=str(xml.Document(auth)))
+        self.expected_success(200, resp.status)
         return resp, body['access']
diff --git a/tempest/test.py b/tempest/test.py
index f34933e..d2b32d4 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -76,7 +76,10 @@
                 f(cls)
             except Exception as se:
                 etype, value, trace = sys.exc_info()
-                LOG.exception("setUpClass failed: %s" % se)
+                if etype is cls.skipException:
+                    LOG.info("setUpClass skipped: %s:" % se)
+                else:
+                    LOG.exception("setUpClass failed: %s" % se)
                 try:
                     cls.tearDownClass()
                 except Exception as te:
@@ -89,12 +92,7 @@
     return decorator
 
 
-def services(*args, **kwargs):
-    """A decorator used to set an attr for each service used in a test case
-
-    This decorator applies a testtools attr for each service that gets
-    exercised by a test case.
-    """
+def get_service_list():
     service_list = {
         'compute': CONF.service_available.nova,
         'image': CONF.service_available.glance,
@@ -110,16 +108,29 @@
         'telemetry': CONF.service_available.ceilometer,
         'data_processing': CONF.service_available.sahara
     }
+    return service_list
 
+
+def services(*args, **kwargs):
+    """A decorator used to set an attr for each service used in a test case
+
+    This decorator applies a testtools attr for each service that gets
+    exercised by a test case.
+    """
     def decorator(f):
+        services = ['compute', 'image', 'baremetal', 'volume', 'orchestration',
+                    'network', 'identity', 'object_storage', 'dashboard',
+                    'ceilometer', 'data_processing']
         for service in args:
-            if service not in service_list:
-                raise exceptions.InvalidServiceTag('%s is not a valid service'
-                                                   % service)
+            if service not in services:
+                raise exceptions.InvalidServiceTag('%s is not a valid '
+                                                   'service' % service)
         attr(type=list(args))(f)
 
         @functools.wraps(f)
         def wrapper(self, *func_args, **func_kwargs):
+            service_list = get_service_list()
+
             for service in args:
                 if not service_list[service]:
                     msg = 'Skipped because the %s service is not available' % (
diff --git a/tempest/tests/common/test_accounts.py b/tempest/tests/common/test_accounts.py
index feafbf5..a0b3496 100644
--- a/tempest/tests/common/test_accounts.py
+++ b/tempest/tests/common/test_accounts.py
@@ -197,3 +197,36 @@
             return_value=self.test_accounts))
         test_accounts_class = accounts.Accounts('test_name')
         self.assertFalse(test_accounts_class.is_multi_user())
+
+
+class TestNotLockingAccount(base.TestCase):
+
+    def setUp(self):
+        super(TestNotLockingAccount, self).setUp()
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+        self.temp_dir = tempfile.mkdtemp()
+        cfg.CONF.set_default('lock_path', self.temp_dir)
+        self.addCleanup(os.rmdir, self.temp_dir)
+        self.test_accounts = [
+            {'username': 'test_user1', 'tenant_name': 'test_tenant1',
+             'password': 'p'},
+            {'username': 'test_user2', 'tenant_name': 'test_tenant2',
+             'password': 'p'},
+            {'username': 'test_user3', 'tenant_name': 'test_tenant3',
+             'password': 'p'},
+        ]
+        self.useFixture(mockpatch.Patch(
+            'tempest.common.accounts.read_accounts_yaml',
+            return_value=self.test_accounts))
+        cfg.CONF.set_default('test_accounts_file', '', group='auth')
+
+    def test_get_creds(self):
+        test_accounts_class = accounts.NotLockingAccounts('test_name')
+        for i in xrange(len(self.test_accounts)):
+            creds = test_accounts_class.get_creds(i)
+            msg = "Empty credentials returned for ID %s" % str(i)
+            self.assertIsNotNone(creds, msg)
+        self.assertRaises(exceptions.InvalidConfiguration,
+                          test_accounts_class.get_creds,
+                          id=len(self.test_accounts))
\ No newline at end of file
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index eddbb1d..48c523e 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -272,6 +272,13 @@
 
     @mock.patch('tempest.common.rest_client.RestClient')
     def test_network_cleanup(self, MockRestClient):
+        def side_effect(**args):
+            return ({'status': 200},
+                    {"security_groups": [{"tenant_id": args['tenant_id'],
+                                          "name": args['name'],
+                                          "description": args['name'],
+                                          "security_group_rules": [],
+                                          "id": "sg-%s" % args['tenant_id']}]})
         iso_creds = isolated_creds.IsolatedCreds('test class',
                                                  password='fake_password')
         # Create primary tenant and network
@@ -341,7 +348,23 @@
                                            return_value=return_values)
 
         port_list_mock.start()
+        secgroup_list_mock = mock.patch.object(iso_creds.network_admin_client,
+                                               'list_security_groups',
+                                               side_effect=side_effect)
+        secgroup_list_mock.start()
+
+        return_values = (fake_http.fake_httplib({}, status=204), {})
+        remove_secgroup_mock = self.patch(
+            'tempest.services.network.network_client_base.'
+            'NetworkClientBase.delete', return_value=return_values)
         iso_creds.clear_isolated_creds()
+        # Verify default security group delete
+        calls = remove_secgroup_mock.mock_calls
+        self.assertEqual(len(calls), 3)
+        args = map(lambda x: x[1][0], calls)
+        self.assertIn('v2.0/security-groups/sg-1234', args)
+        self.assertIn('v2.0/security-groups/sg-12345', args)
+        self.assertIn('v2.0/security-groups/sg-123456', args)
         # Verify remove router interface calls
         calls = remove_router_interface_mock.mock_calls
         self.assertEqual(len(calls), 3)
diff --git a/tempest/tests/test_wrappers.py b/tempest/tests/test_wrappers.py
index bba4012..3f4ac7d 100644
--- a/tempest/tests/test_wrappers.py
+++ b/tempest/tests/test_wrappers.py
@@ -69,14 +69,14 @@
 
         self.assertEqual(
             p.returncode, expected,
-            "Stdout: %s; Stderr: %s" % (p.stdout, p.stderr))
+            "Stdout: %s; Stderr: %s" % (p.stdout.read(), p.stderr.read()))
 
     def test_pretty_tox(self):
         # Git init is required for the pbr testr command. pbr requires a git
         # version or an sdist to work. so make the test directory a git repo
         # too.
         subprocess.call(['git', 'init'], stderr=DEVNULL)
-        self.assertRunExit('pretty_tox.sh tests.passing', 0)
+        self.assertRunExit('pretty_tox.sh passing', 0)
 
     def test_pretty_tox_fails(self):
         # Git init is required for the pbr testr command. pbr requires a git
@@ -86,7 +86,7 @@
         self.assertRunExit('pretty_tox.sh', 1)
 
     def test_pretty_tox_serial(self):
-        self.assertRunExit('pretty_tox_serial.sh tests.passing', 0)
+        self.assertRunExit('pretty_tox_serial.sh passing', 0)
 
     def test_pretty_tox_serial_fails(self):
         self.assertRunExit('pretty_tox_serial.sh', 1)
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index 2c68d6b..c0d3f7a 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -13,8 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from boto import exception
-
 from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
 from tempest import config
@@ -82,6 +80,13 @@
                 raise exceptions.EC2RegisterImageException(
                     image_id=image["image_id"])
 
+    def _terminate_reservation(self, reservation, rcuk):
+        for instance in reservation.instances:
+            instance.terminate()
+        for instance in reservation.instances:
+            self.assertInstanceStateWait(instance, '_GONE')
+        self.cancelResourceCleanUp(rcuk)
+
     def test_run_idempotent_instances(self):
         # EC2 run instances idempotently
 
@@ -96,11 +101,6 @@
                                            reservation)
             return (reservation, rcuk)
 
-        def _terminate_reservation(reservation, rcuk):
-            for instance in reservation.instances:
-                instance.terminate()
-            self.cancelResourceCleanUp(rcuk)
-
         reservation_1, rcuk_1 = _run_instance('token_1')
         reservation_2, rcuk_2 = _run_instance('token_2')
         reservation_1a, rcuk_1a = _run_instance('token_1')
@@ -116,8 +116,8 @@
         # handled by rcuk1
         self.cancelResourceCleanUp(rcuk_1a)
 
-        _terminate_reservation(reservation_1, rcuk_1)
-        _terminate_reservation(reservation_2, rcuk_2)
+        self._terminate_reservation(reservation_1, rcuk_1)
+        self._terminate_reservation(reservation_2, rcuk_2)
 
     def test_run_stop_terminate_instance(self):
         # EC2 run, stop and terminate instance
@@ -139,9 +139,7 @@
             if instance.state != "stopped":
                 self.assertInstanceStateWait(instance, "stopped")
 
-        for instance in reservation.instances:
-            instance.terminate()
-        self.cancelResourceCleanUp(rcuk)
+        self._terminate_reservation(reservation, rcuk)
 
     def test_run_stop_terminate_instance_with_tags(self):
         # EC2 run, stop and terminate instance with tags
@@ -188,9 +186,7 @@
             if instance.state != "stopped":
                 self.assertInstanceStateWait(instance, "stopped")
 
-        for instance in reservation.instances:
-            instance.terminate()
-        self.cancelResourceCleanUp(rcuk)
+        self._terminate_reservation(reservation, rcuk)
 
     def test_run_terminate_instance(self):
         # EC2 run, terminate immediately
@@ -202,18 +198,7 @@
 
         for instance in reservation.instances:
             instance.terminate()
-        try:
-            instance.update(validate=True)
-        except ValueError:
-            pass
-        except exception.EC2ResponseError as exc:
-            if self.ec2_error_code.\
-                client.InvalidInstanceID.NotFound.match(exc) is None:
-                pass
-            else:
-                raise
-        else:
-            self.assertNotEqual(instance.state, "running")
+        self.assertInstanceStateWait(instance, '_GONE')
 
     def test_compute_with_volumes(self):
         # EC2 1. integration test (not strict)
diff --git a/tools/subunit-trace.py b/tools/subunit-trace.py
index 8ad59bb..57e58f2 100755
--- a/tools/subunit-trace.py
+++ b/tools/subunit-trace.py
@@ -23,7 +23,6 @@
 import re
 import sys
 
-import mimeparse
 import subunit
 import testtools
 
@@ -32,55 +31,6 @@
 RESULTS = {}
 
 
-class Starts(testtools.StreamResult):
-
-    def __init__(self, output):
-        super(Starts, self).__init__()
-        self._output = output
-
-    def startTestRun(self):
-        self._neednewline = False
-        self._emitted = set()
-
-    def status(self, test_id=None, test_status=None, test_tags=None,
-               runnable=True, file_name=None, file_bytes=None, eof=False,
-               mime_type=None, route_code=None, timestamp=None):
-        super(Starts, self).status(
-            test_id, test_status,
-            test_tags=test_tags, runnable=runnable, file_name=file_name,
-            file_bytes=file_bytes, eof=eof, mime_type=mime_type,
-            route_code=route_code, timestamp=timestamp)
-        if not test_id:
-            if not file_bytes:
-                return
-            if not mime_type or mime_type == 'test/plain;charset=utf8':
-                mime_type = 'text/plain; charset=utf-8'
-            primary, sub, parameters = mimeparse.parse_mime_type(mime_type)
-            content_type = testtools.content_type.ContentType(
-                primary, sub, parameters)
-            content = testtools.content.Content(
-                content_type, lambda: [file_bytes])
-            text = content.as_text()
-            if text and text[-1] not in '\r\n':
-                self._neednewline = True
-            self._output.write(text)
-        elif test_status == 'inprogress' and test_id not in self._emitted:
-            if self._neednewline:
-                self._neednewline = False
-                self._output.write('\n')
-            worker = ''
-            for tag in test_tags or ():
-                if tag.startswith('worker-'):
-                    worker = '(' + tag[7:] + ') '
-            if timestamp:
-                timestr = timestamp.isoformat()
-            else:
-                timestr = ''
-                self._output.write('%s: %s%s [start]\n' %
-                                   (timestr, worker, test_id))
-            self._emitted.add(test_id)
-
-
 def cleanup_test_name(name, strip_tags=True, strip_scenarios=False):
     """Clean up the test name for display.
 
@@ -274,17 +224,19 @@
     args = parse_args()
     stream = subunit.ByteStreamToStreamResult(
         sys.stdin, non_subunit_name='stdout')
-    starts = Starts(sys.stdout)
     outcomes = testtools.StreamToDict(
         functools.partial(show_outcome, sys.stdout,
                           print_failures=args.print_failures))
     summary = testtools.StreamSummary()
-    result = testtools.CopyStreamResult([starts, outcomes, summary])
+    result = testtools.CopyStreamResult([outcomes, summary])
     result.startTestRun()
     try:
         stream.run(result)
     finally:
         result.stopTestRun()
+    if count_tests('status', '.*') == 0:
+        print("The test run didn't actually run any tests")
+        return 1
     if args.post_fails:
         print_fails(sys.stdout)
     print_summary(sys.stdout)
diff --git a/tox.ini b/tox.ini
index a071d4b..6ec0b2c 100644
--- a/tox.ini
+++ b/tox.ini
@@ -29,6 +29,8 @@
 setenv = OS_TEST_PATH=./tempest/tests
          PYTHONHASHSEED=0
 commands = python setup.py testr --coverage --testr-arg='tempest\.tests {posargs}'
+deps = -r{toxinidir}/requirements.txt
+       -r{toxinidir}/test-requirements.txt
 
 [testenv:all]
 sitepackages = True