Merge "Verify the response attributes of 'list_hosts'"
diff --git a/.gitignore b/.gitignore
index 8d2b281..28a9b9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,5 +15,5 @@
 dist
 build
 .testrepository
-.coverage
+.coverage*
 cover/
diff --git a/etc/whitelist.yaml b/etc/whitelist.yaml
deleted file mode 100644
index 2d8b741..0000000
--- a/etc/whitelist.yaml
+++ /dev/null
@@ -1,233 +0,0 @@
-n-cpu:
-    - module: "nova.virt.libvirt.driver"
-      message: "During wait destroy, instance disappeared"
-    - module: "glanceclient.common.http"
-      message: "Request returned failure status"
-    - module: "nova.openstack.common.periodic_task"
-      message: "Error during ComputeManager\\.update_available_resource: \
-        'NoneType' object is not iterable"
-    - module: "nova.compute.manager"
-      message: "Possibly task preempted"
-    - module: "nova.openstack.common.rpc.amqp"
-      message: "Exception during message handling"
-    - module: "nova.network.api"
-      message: "Failed storing info cache"
-    - module: "nova.compute.manager"
-      message: "Error while trying to clean up image"
-    - module: "nova.virt.libvirt.driver"
-      message: "Error injecting data into image.*\\(Unexpected error while \
-        running command"
-    - module: "nova.compute.manager"
-      message: "Instance failed to spawn"
-    - module: "nova.compute.manager"
-      message: "Error: Unexpected error while running command"
-    - module: "nova.virt.libvirt.driver"
-      message: "Error from libvirt during destroy"
-    - module: "nova.virt.libvirt.vif"
-      message: "Failed while unplugging vif"
-    - module: "nova.openstack.common.loopingcal"
-      message: "in fixed duration looping call"
-    - module: "nova.virt.libvirt.driver"
-      message: "Getting disk size of instance"
-    - module: "nova.virt.libvirt.driver"
-      message: "No such file or directory: '/opt/stack/data/nova/instances"
-    - module: "nova.virt.libvirt.driver"
-      message: "Nova requires libvirt version 0\\.9\\.11 or greater"
-    - module: "nova.compute.manager"
-      message: "error during stop\\(\\) in sync_power_state"
-    - module: "nova.compute.manager"
-      message: "Instance failed network setup after 1 attempt"
-    - module: "nova.compute.manager"
-      message: "Periodic sync_power_state task had an error"
-    - module: "nova.virt.driver"
-      message: "Info cache for instance .* could not be found"
-
-g-api:
-    - module: "glance.store.sheepdog"
-      message: "Error in store configuration: Unexpected error while \
-        running command"
-    - module: "swiftclient"
-      message: "Container HEAD failed: .*404 Not Found"
-    - module: "glance.api.middleware.cache"
-      message: "however the registry did not contain metadata for that image"
-    - module: "oslo.messaging.notify._impl_messaging"
-      message: ".*"
-
-ceilometer-acompute:
-    - module: "ceilometer.compute.pollsters.disk"
-      message: "Unable to read from monitor: Connection reset by peer"
-    - module: "ceilometer.compute.pollsters.disk"
-      message: "Requested operation is not valid: domain is not running"
-    - module: "ceilometer.compute.pollsters.net"
-      message: "Requested operation is not valid: domain is not running"
-    - module: "ceilometer.compute.pollsters.disk"
-      message: "Domain not found: no domain with matching uuid"
-    - module: "ceilometer.compute.pollsters.net"
-      message: "Domain not found: no domain with matching uuid"
-    - module: "ceilometer.compute.pollsters.net"
-      message: "No module named libvirt"
-    - module: "ceilometer.compute.pollsters.net"
-      message: "Unable to write to monitor: Broken pipe"
-    - module: "ceilometer.compute.pollsters.cpu"
-      message: "Domain not found: no domain with matching uuid"
-    - module: "ceilometer.compute.pollsters.net"
-      message: ".*"
-    - module: "ceilometer.compute.pollsters.disk"
-      message: ".*"
-
-ceilometer-acentral:
-    - module: "ceilometer.central.manager"
-      message: "403 Forbidden"
-    - module: "ceilometer.central.manager"
-      message: "get_samples\\(\\) got an unexpected keyword argument 'resources'"
-
-ceilometer-alarm-evaluator:
-    - module: "ceilometer.alarm.service"
-      message: "alarm evaluation cycle failed"
-    - module: "ceilometer.alarm.evaluator.threshold"
-      message: ".*"
-
-ceilometer-api:
-    - module: "wsme.api"
-      message: ".*"
-
-h-api:
-    - module: "root"
-      message: "Returning 400 to user: The server could not comply with \
-        the request since it is either malformed or otherwise incorrect"
-    - module: "root"
-      message: "Unexpected error occurred serving API: Request limit \
-        exceeded: Template exceeds maximum allowed size"
-    - module: "root"
-      message: "Unexpected error occurred serving API: The Stack \
-        .*could not be found"
-
-h-eng:
-    - module: "heat.openstack.common.rpc.amqp"
-      message: "Exception during message handling"
-    - module: "heat.openstack.common.rpc.common"
-      message: "The Stack .* could not be found"
-
-n-api:
-    - module: "glanceclient.common.http"
-      message: "Request returned failure status"
-    - module: "nova.api.openstack"
-      message: "Caught error: Quota exceeded for"
-    - module: "nova.compute.api"
-      message: "ServerDiskConfigTest"
-    - module: "nova.compute.api"
-      message: "ServersTest"
-    - module: "nova.compute.api"
-      message: "\\{u'kernel_id'.*u'ramdisk_id':"
-    - module: "nova.api.openstack.wsgi"
-      message: "takes exactly 4 arguments"
-    - module: "nova.api.openstack"
-      message: "Caught error: Instance .* could not be found"
-    - module: "nova.api.metadata.handler"
-      message: "Failed to get metadata for instance id:"
-
-n-cond:
-    - module: "nova.notifications"
-      message: "Failed to send state update notification"
-    - module: "nova.openstack.common.rpc.amqp"
-      message: "Exception during message handling"
-    - module: "nova.openstack.common.rpc.common"
-      message: "but the actual state is deleting to caller"
-    - module: "nova.openstack.common.rpc.common"
-      message: "Traceback \\(most recent call last"
-    - module: "nova.openstack.common.threadgroup"
-      message: "Service with host .* topic conductor exists."
-
-n-sch:
-    - module: "nova.scheduler.filter_scheduler"
-      message: "Error from last host: "
-
-n-net:
-    - module: "nova.openstack.common.rpc.amqp"
-      message: "Exception during message handling"
-    - module: "nova.openstack.common.rpc.common"
-      message: "'NoneType' object has no attribute '__getitem__'"
-    - module: "nova.openstack.common.rpc.common"
-      message: "Instance .* could not be found"
-
-c-api:
-    - module: "cinder.api.middleware.fault"
-      message: "Caught error: Volume .* could not be found"
-    - module: "cinder.api.middleware.fault"
-      message: "Caught error: Snapshot .* could not be found"
-    - module: "cinder.api.openstack.wsgi"
-      message: "argument must be a string or a number, not 'NoneType'"
-    - module: "cinder.volume.api"
-      message: "Volume status must be available to reserve"
-
-c-vol:
-    - module: "cinder.brick.iscsi.iscsi"
-      message: "Failed to create iscsi target for volume id"
-    - module: "cinder.brick.local_dev.lvm"
-      message: "stat failed: No such file or directory"
-    - module: "cinder.brick.local_dev.lvm"
-      message: "LV stack-volumes.*in use: not deactivating"
-    - module: "cinder.brick.local_dev.lvm"
-      message: "Can't remove open logical volume"
-
-ceilometer-collector:
-    - module: "stevedore.extension"
-      message: ".*"
-    - module: "ceilometer.collector.dispatcher.database"
-      message: "duplicate key value violates unique constraint"
-    - module: "ceilometer.collector.dispatcher.database"
-      message: "Failed to record metering data: QueuePool limit"
-    - module: "ceilometer.dispatcher.database"
-      message: "\\(DataError\\) integer out of range"
-    - module: "ceilometer.collector.dispatcher.database"
-      message: "Failed to record metering data: .* integer out of range"
-    - module: "ceilometer.collector.dispatcher.database"
-      message: "Failed to record metering data: .* integer out of range"
-    - module: "ceilometer.openstack.common.db.sqlalchemy.session"
-      message: "DB exception wrapped"
-
-q-agt:
-    - module: "neutron.agent.linux.ovs_lib"
-      message: "Unable to execute.*Exception:"
-
-q-dhcp:
-    - module: "neutron.common.legacy"
-      message: "Skipping unknown group key: firewall_driver"
-    - module: "neutron.agent.dhcp_agent"
-      message: "Unable to enable dhcp"
-    - module: "neutron.agent.dhcp_agent"
-      message: "Network .* RPC info call failed"
-
-q-l3:
-    - module: "neutron.common.legacy"
-      message: "Skipping unknown group key: firewall_driver"
-    - module: "neutron.agent.l3_agent"
-      message: "Failed synchronizing routers"
-
-q-vpn:
-    - module: "neutron.common.legacy"
-      message: "Skipping unknown group key: firewall_driver"
-
-q-lbaas:
-    - module: "neutron.common.legacy"
-      message: "Skipping unknown group key: firewall_driver"
-    - module: "neutron.services.loadbalancer.drivers.haproxy.agent_manager"
-      message: "Error upating stats"
-    - module: "neutron.services.loadbalancer.drivers.haproxy.agent_manager"
-      message: "Unable to destroy device for pool"
-
-q-svc:
-    - module: "neutron.common.legacy"
-      message: "Skipping unknown group key: firewall_driver"
-    - module: "neutron.openstack.common.rpc.amqp"
-      message: "Exception during message handling"
-    - module: "neutron.openstack.common.rpc.common"
-      message: "(Network|Pool|Subnet|Agent|Port) .* could not be found"
-    - module: "neutron.api.v2.resource"
-      message: ".* failed"
-    - module: ".*"
-      message: ".*"
-
-s-proxy:
-    - module: "proxy-server"
-      message: "Timeout talking to memcached"
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 40a4df7..77431bb 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -27,6 +27,7 @@
     _host_key = 'OS-EXT-SRV-ATTR:host'
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(ServersAdminTestJSON, cls).setUpClass()
         cls.client = cls.os_adm.servers_client
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index c825fb9..768cc11 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -26,6 +26,7 @@
     force_tenant_isolation = True
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(ListServersNegativeTestJSON, cls).setUpClass()
         cls.client = cls.servers_client
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 48f2e14..093e9e2 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -21,6 +21,7 @@
 class ServerRescueTestJSON(base.BaseV2ComputeTest):
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         cls.set_network_resources(network=True, subnet=True, router=True)
         super(ServerRescueTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index e027567..ef45585 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -22,6 +22,7 @@
 class ServerRescueNegativeTestJSON(base.BaseV2ComputeTest):
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         cls.set_network_resources(network=True, subnet=True, router=True)
         super(ServerRescueNegativeTestJSON, cls).setUpClass()
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index 230d433..4db8c56 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -27,6 +27,9 @@
         resp, tenants = cls.admin_client.list_tenants()
         cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
                          cls.client.tenant_name][0]
+        resp, users = cls.admin_client.list_users_for_tenant(cls.tenant_id)
+        cls.user_id = [user['id'] for user in users if user['name'] ==
+                       cls.client.user][0]
         cls.default_quota_set = set(('injected_file_content_bytes',
                                      'metadata_items', 'injected_files',
                                      'ram', 'floating_ips',
@@ -45,6 +48,14 @@
                          sorted(quota_set.keys()))
         self.assertEqual(quota_set['id'], self.tenant_id)
 
+        # get the quota set using user id
+        resp, quota_set = self.client.get_quota_set(self.tenant_id,
+                                                    self.user_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(sorted(expected_quota_set),
+                         sorted(quota_set.keys()))
+        self.assertEqual(quota_set['id'], self.tenant_id)
+
     @test.attr(type='smoke')
     def test_get_default_quotas(self):
         # User can get the default quota set for it's tenant
diff --git a/tempest/api/compute/v3/admin/test_quotas.py b/tempest/api/compute/v3/admin/test_quotas.py
index 536891c..917c115 100644
--- a/tempest/api/compute/v3/admin/test_quotas.py
+++ b/tempest/api/compute/v3/admin/test_quotas.py
@@ -109,3 +109,26 @@
         resp, quota_set = self.adm_client.get_quota_set(tenant_id)
         self.assertEqual(200, resp.status)
         self.assertEqual(quota_set['ram'], 5120)
+
+    @test.attr(type='gate')
+    def test_delete_quota(self):
+        # Admin can delete the resource quota set for a tenant
+        tenant_name = data_utils.rand_name('cpu_quota_tenant_')
+        tenant_desc = tenant_name + '-desc'
+        identity_client = self.os_adm.identity_client
+        _, tenant = identity_client.create_tenant(name=tenant_name,
+                                                  description=tenant_desc)
+        tenant_id = tenant['id']
+        self.addCleanup(identity_client.delete_tenant, tenant_id)
+        resp, quota_set_default = self.adm_client.get_quota_set(tenant_id)
+        self.assertEqual(200, resp.status)
+        ram_default = quota_set_default['ram']
+
+        self.adm_client.update_quota_set(tenant_id, ram='5120')
+        self.assertEqual(200, resp.status)
+        resp, _ = self.adm_client.delete_quota_set(tenant_id)
+        self.assertEqual(204, resp.status)
+
+        resp, quota_set_new = self.adm_client.get_quota_set(tenant_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(ram_default, quota_set_new['ram'])
diff --git a/tempest/api/compute/v3/admin/test_servers.py b/tempest/api/compute/v3/admin/test_servers.py
index fb8afe4..579a535 100644
--- a/tempest/api/compute/v3/admin/test_servers.py
+++ b/tempest/api/compute/v3/admin/test_servers.py
@@ -27,6 +27,7 @@
     _host_key = 'os-extended-server-attributes:host'
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(ServersAdminV3Test, cls).setUpClass()
         cls.client = cls.servers_admin_client
diff --git a/tempest/api/compute/v3/servers/test_create_server.py b/tempest/api/compute/v3/servers/test_create_server.py
index 7e9aaf2..14a4338 100644
--- a/tempest/api/compute/v3/servers/test_create_server.py
+++ b/tempest/api/compute/v3/servers/test_create_server.py
@@ -92,14 +92,6 @@
 
     @testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
     @test.attr(type='gate')
-    def test_can_log_into_created_server(self):
-        # Check that the user can authenticate with the generated password
-        linux_client = remote_client.RemoteClient(self.server,
-                                                  self.ssh_user, self.password)
-        self.assertTrue(linux_client.can_authenticate())
-
-    @testtools.skipIf(not run_ssh, 'Instance validation tests are disabled.')
-    @test.attr(type='gate')
     def test_verify_created_server_vcpus(self):
         # Verify that the number of vcpus reported by the instance matches
         # the amount stated by the flavor
diff --git a/tempest/api/compute/v3/servers/test_list_servers_negative.py b/tempest/api/compute/v3/servers/test_list_servers_negative.py
index 92f44fe..9cbc4e0 100644
--- a/tempest/api/compute/v3/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/v3/servers/test_list_servers_negative.py
@@ -19,13 +19,14 @@
 
 from tempest.api.compute import base
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class ListServersNegativeV3Test(base.BaseV3ComputeTest):
     force_tenant_isolation = True
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(ListServersNegativeV3Test, cls).setUpClass()
         cls.client = cls.servers_client
@@ -51,7 +52,7 @@
                                                ignore_error=True)
         cls.deleted_fixtures.append(srv)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_with_a_deleted_server(self):
         # Verify deleted servers do not show by default in list servers
         # List servers and verify server not returned
@@ -63,7 +64,7 @@
         self.assertEqual('200', resp['status'])
         self.assertEqual([], actual)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_non_existing_image(self):
         # Listing servers for a non existing image returns empty list
         non_existing_image = '1234abcd-zzz0-aaa9-ppp3-0987654abcde'
@@ -72,7 +73,7 @@
         self.assertEqual('200', resp['status'])
         self.assertEqual([], servers)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_non_existing_flavor(self):
         # Listing servers by non existing flavor returns empty list
         non_existing_flavor = 1234
@@ -81,7 +82,7 @@
         self.assertEqual('200', resp['status'])
         self.assertEqual([], servers)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_non_existing_server_name(self):
         # Listing servers for a non existent server name returns empty list
         non_existing_name = 'junk_server_1234'
@@ -90,7 +91,7 @@
         self.assertEqual('200', resp['status'])
         self.assertEqual([], servers)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_status_non_existing(self):
         # Return an empty list when invalid status is specified
         non_existing_status = 'BALONEY'
@@ -99,33 +100,33 @@
         self.assertEqual('200', resp['status'])
         self.assertEqual([], servers)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_by_limits(self):
         # List servers by specifying limits
         resp, body = self.client.list_servers({'limit': 1})
         self.assertEqual('200', resp['status'])
         self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_limits_greater_than_actual_count(self):
         # List servers by specifying a greater value for limit
         resp, body = self.client.list_servers({'limit': 100})
         self.assertEqual('200', resp['status'])
         self.assertEqual(len(self.existing_fixtures), len(body['servers']))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_limits_pass_string(self):
         # Return an error if a string value is passed for limit
         self.assertRaises(exceptions.BadRequest, self.client.list_servers,
                           {'limit': 'testing'})
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_limits_pass_negative_value(self):
         # Return an error if a negative value for limit is passed
         self.assertRaises(exceptions.BadRequest, self.client.list_servers,
                           {'limit': -1})
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_by_changes_since(self):
         # Servers are listed by specifying changes-since date
         changes_since = {'changes_since': self.start_time.isoformat()}
@@ -138,13 +139,13 @@
                          "Number of servers %d is wrong in %s" %
                          (num_expected, body['servers']))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_changes_since_invalid_date(self):
         # Return an error when invalid date format is passed
         self.assertRaises(exceptions.BadRequest, self.client.list_servers,
                           {'changes_since': '2011/01/01'})
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_by_changes_since_future_date(self):
         # Return an empty list when a date in the future is passed
         changes_since = {'changes_since': '2051-01-01T12:34:00Z'}
@@ -152,7 +153,7 @@
         self.assertEqual('200', resp['status'])
         self.assertEqual(0, len(body['servers']))
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_servers_detail_server_is_deleted(self):
         # Server details are not listed for a deleted server
         deleted_ids = [s['id'] for s in self.deleted_fixtures]
diff --git a/tempest/api/compute/v3/servers/test_server_rescue_negative.py b/tempest/api/compute/v3/servers/test_server_rescue_negative.py
index 6e09376..6bb441c 100644
--- a/tempest/api/compute/v3/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/v3/servers/test_server_rescue_negative.py
@@ -22,6 +22,7 @@
 class ServerRescueNegativeV3Test(base.BaseV3ComputeTest):
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(ServerRescueNegativeV3Test, cls).setUpClass()
         cls.device = 'vdf'
diff --git a/tempest/api/compute/v3/test_quotas.py b/tempest/api/compute/v3/test_quotas.py
index b53d9be..3fe62e9 100644
--- a/tempest/api/compute/v3/test_quotas.py
+++ b/tempest/api/compute/v3/test_quotas.py
@@ -27,6 +27,9 @@
         resp, tenants = cls.admin_client.list_tenants()
         cls.tenant_id = [tnt['id'] for tnt in tenants if tnt['name'] ==
                          cls.client.tenant_name][0]
+        resp, users = cls.admin_client.list_users_for_tenant(cls.tenant_id)
+        cls.user_id = [user['id'] for user in users if user['name'] ==
+                       cls.client.user][0]
         cls.default_quota_set = set(('metadata_items',
                                      'ram', 'floating_ips',
                                      'fixed_ips', 'key_pairs',
@@ -43,6 +46,14 @@
                          sorted(quota_set.keys()))
         self.assertEqual(quota_set['id'], self.tenant_id)
 
+        # get the quota set using user id
+        resp, quota_set = self.client.get_quota_set(self.tenant_id,
+                                                    self.user_id)
+        self.assertEqual(200, resp.status)
+        self.assertEqual(sorted(expected_quota_set),
+                         sorted(quota_set.keys()))
+        self.assertEqual(quota_set['id'], self.tenant_id)
+
     @test.attr(type='smoke')
     def test_get_default_quotas(self):
         # User can get the default quota set for it's tenant
diff --git a/tempest/api/identity/admin/test_tokens.py b/tempest/api/identity/admin/test_tokens.py
index 533f374..c931bcf 100644
--- a/tempest/api/identity/admin/test_tokens.py
+++ b/tempest/api/identity/admin/test_tokens.py
@@ -56,6 +56,49 @@
         resp, body = self.client.delete_token(token_id)
         self.assertEqual(resp['status'], '204')
 
+    @attr(type='gate')
+    def test_rescope_token(self):
+        """An unscoped token can be requested, that token can be used to
+           request a scoped token.
+        """
+
+        # Create a user.
+        user_name = data_utils.rand_name(name='user-')
+        user_password = data_utils.rand_name(name='pass-')
+        tenant_id = None  # No default tenant so will get unscoped token.
+        email = ''
+        resp, user = self.client.create_user(user_name, user_password,
+                                             tenant_id, email)
+        self.assertEqual(200, resp.status)
+        self.data.users.append(user)
+
+        # Create a tenant.
+        tenant_name = data_utils.rand_name(name='tenant-')
+        resp, tenant = self.client.create_tenant(tenant_name)
+        self.assertEqual(200, resp.status)
+        self.data.tenants.append(tenant)
+
+        # Create a role
+        role_name = data_utils.rand_name(name='role-')
+        resp, role = self.client.create_role(role_name)
+        self.assertEqual(200, resp.status)
+        self.data.roles.append(role)
+
+        # Grant the user the role on the tenant.
+        resp, _ = self.client.assign_user_role(tenant['id'], user['id'],
+                                               role['id'])
+        self.assertEqual(200, resp.status)
+
+        # Get an unscoped token.
+        rsp, body = self.token_client.auth(user_name, user_password)
+        self.assertEqual(200, resp.status)
+
+        token_id = body['token']['id']
+
+        # Use the unscoped token to get a scoped token.
+        rsp, body = self.token_client.auth_token(token_id, tenant=tenant_name)
+        self.assertEqual(200, resp.status)
+
 
 class TokensTestXML(TokensTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 05b704f..0e4d66b 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -102,6 +102,7 @@
             self.client.create_endpoint(self.service_id, interface1,
                                         url1, region=region1,
                                         enabled=True)
+        self.addCleanup(self.client.delete_endpoint, endpoint_for_update['id'])
         # Creating service so as update endpoint with new service ID
         s_name = data_utils.rand_name('service-')
         s_type = data_utils.rand_name('type--')
@@ -126,7 +127,6 @@
         self.assertEqual(url2, endpoint['url'])
         self.assertEqual(region2, endpoint['region'])
         self.assertEqual('false', str(endpoint['enabled']).lower())
-        self.addCleanup(self.client.delete_endpoint, endpoint_for_update['id'])
 
 
 class EndPointsTestXML(EndPointsTestJSON):
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
new file mode 100644
index 0000000..28615a4
--- /dev/null
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -0,0 +1,94 @@
+
+# Copyright 2013 IBM Corp.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+
+from tempest.api.identity import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest.test import attr
+
+
+class EndpointsNegativeTestJSON(base.BaseIdentityV3AdminTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(EndpointsNegativeTestJSON, cls).setUpClass()
+        cls.identity_client = cls.client
+        cls.client = cls.endpoints_client
+        cls.service_ids = list()
+        s_name = data_utils.rand_name('service-')
+        s_type = data_utils.rand_name('type--')
+        s_description = data_utils.rand_name('description-')
+        resp, cls.service_data = (
+            cls.service_client.create_service(s_name, s_type,
+                                              description=s_description))
+        cls.service_id = cls.service_data['id']
+        cls.service_ids.append(cls.service_id)
+
+    @classmethod
+    def tearDownClass(cls):
+        for s in cls.service_ids:
+            cls.service_client.delete_service(s)
+        super(EndpointsNegativeTestJSON, cls).tearDownClass()
+
+    @attr(type=['negative', 'gate'])
+    def test_create_with_enabled_False(self):
+        # Enabled should be a boolean, not a string like 'False'
+        interface = 'public'
+        url = data_utils.rand_name('url')
+        region = data_utils.rand_name('region')
+        self.assertRaises(exceptions.BadRequest, self.client.create_endpoint,
+                          self.service_id, interface, url, region=region,
+                          force_enabled='False')
+
+    @attr(type=['negative', 'gate'])
+    def test_create_with_enabled_True(self):
+        # Enabled should be a boolean, not a string like 'True'
+        interface = 'public'
+        url = data_utils.rand_name('url')
+        region = data_utils.rand_name('region')
+        self.assertRaises(exceptions.BadRequest, self.client.create_endpoint,
+                          self.service_id, interface, url, region=region,
+                          force_enabled='True')
+
+    def _assert_update_raises_bad_request(self, enabled):
+
+        # Create an endpoint
+        region1 = data_utils.rand_name('region')
+        url1 = data_utils.rand_name('url')
+        interface1 = 'public'
+        resp, endpoint_for_update = (
+            self.client.create_endpoint(self.service_id, interface1,
+                                        url1, region=region1, enabled=True))
+        self.addCleanup(self.client.delete_endpoint, endpoint_for_update['id'])
+
+        self.assertRaises(exceptions.BadRequest, self.client.update_endpoint,
+                          endpoint_for_update['id'], force_enabled=enabled)
+
+    @attr(type=['negative', 'gate'])
+    def test_update_with_enabled_False(self):
+        # Enabled should be a boolean, not a string like 'False'
+        self._assert_update_raises_bad_request('False')
+
+    @attr(type=['negative', 'gate'])
+    def test_update_with_enabled_True(self):
+        # Enabled should be a boolean, not a string like 'True'
+        self._assert_update_raises_bad_request('True')
+
+
+class EndpointsNegativeTestXML(EndpointsNegativeTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/network/admin/test_dhcp_agent_scheduler.py b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
index ecd992a..0e601d1 100644
--- a/tempest/api/network/admin/test_dhcp_agent_scheduler.py
+++ b/tempest/api/network/admin/test_dhcp_agent_scheduler.py
@@ -26,7 +26,7 @@
             msg = "dhcp_agent_scheduler extension not enabled."
             raise cls.skipException(msg)
         # Create a network and make sure it will be hosted by a
-        # dhcp agent.
+        # dhcp agent: this is done by creating a regular port
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
         cls.cidr = cls.subnet['cidr']
@@ -60,6 +60,9 @@
 
     @test.attr(type='smoke')
     def test_remove_network_from_dhcp_agent(self):
+        # The agent is now bound to the network, we can free the port
+        self.client.delete_port(self.port['id'])
+        self.ports.remove(self.port)
         resp, body = self.admin_client.list_dhcp_agent_hosting_network(
             self.network['id'])
         agents = body['agents']
diff --git a/tempest/api/network/admin/test_load_balancer_admin_actions.py b/tempest/api/network/admin/test_load_balancer_admin_actions.py
new file mode 100644
index 0000000..34a8e32
--- /dev/null
+++ b/tempest/api/network/admin/test_load_balancer_admin_actions.py
@@ -0,0 +1,94 @@
+# Copyright 2014 Mirantis.inc
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.network import base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+class LoadBalancerAdminTestJSON(base.BaseAdminNetworkTest):
+    _interface = 'json'
+
+    """
+    Test admin actions for load balancer.
+
+    Create VIP for another tenant
+    Create health monitor for another tenant
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        super(LoadBalancerAdminTestJSON, cls).setUpClass()
+        if not test.is_extension_enabled('lbaas', 'network'):
+            msg = "lbaas extension not enabled."
+            raise cls.skipException(msg)
+        cls.force_tenant_isolation = True
+        manager = cls.get_client_manager()
+        cls.client = manager.network_client
+        username, tenant_name, passwd = cls.isolated_creds.get_primary_creds()
+        cls.tenant_id = cls.os_adm.identity_client.get_tenant_by_name(
+            tenant_name)['id']
+        cls.network = cls.create_network()
+        cls.subnet = cls.create_subnet(cls.network)
+
+    @test.attr(type='smoke')
+    def test_create_vip_as_admin_for_another_tenant(self):
+        name = data_utils.rand_name('vip-')
+        resp, body = self.admin_client.create_pool(
+            name=data_utils.rand_name('pool-'), lb_method="ROUND_ROBIN",
+            protocol="HTTP", subnet_id=self.subnet['id'],
+            tenant_id=self.tenant_id)
+        self.assertEqual('201', resp['status'])
+        pool = body['pool']
+        self.addCleanup(self.admin_client.delete_pool, pool['id'])
+        resp, body = self.admin_client.create_vip(name=name,
+                                                  protocol="HTTP",
+                                                  protocol_port=80,
+                                                  subnet_id=self.subnet['id'],
+                                                  pool_id=pool['id'],
+                                                  tenant_id=self.tenant_id)
+        self.assertEqual('201', resp['status'])
+        vip = body['vip']
+        self.addCleanup(self.admin_client.delete_vip, vip['id'])
+        self.assertIsNotNone(vip['id'])
+        self.assertEqual(self.tenant_id, vip['tenant_id'])
+        resp, body = self.client.show_vip(vip['id'])
+        self.assertEqual('200', resp['status'])
+        show_vip = body['vip']
+        self.assertEqual(vip['id'], show_vip['id'])
+        self.assertEqual(vip['name'], show_vip['name'])
+
+    @test.attr(type='smoke')
+    def test_create_health_monitor_as_admin_for_another_tenant(self):
+        resp, body = (
+            self.admin_client.create_health_monitor(delay=4,
+                                                    max_retries=3,
+                                                    type="TCP",
+                                                    timeout=1,
+                                                    tenant_id=self.tenant_id))
+        self.assertEqual('201', resp['status'])
+        health_monitor = body['health_monitor']
+        self.addCleanup(self.admin_client.delete_health_monitor,
+                        health_monitor['id'])
+        self.assertIsNotNone(health_monitor['id'])
+        self.assertEqual(self.tenant_id, health_monitor['tenant_id'])
+        resp, body = self.client.show_health_monitor(health_monitor['id'])
+        self.assertEqual('200', resp['status'])
+        show_health_monitor = body['health_monitor']
+        self.assertEqual(health_monitor['id'], show_health_monitor['id'])
+
+
+class LoadBalancerAdminTestXML(LoadBalancerAdminTestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index 695dbf8..792d61d 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -108,6 +108,7 @@
     def test_create_update_delete_pool_vip(self):
         # Creates a vip
         name = data_utils.rand_name('vip-')
+        address = self.subnet['allocation_pools'][0]['end']
         resp, body = self.client.create_pool(
             name=data_utils.rand_name("pool-"),
             lb_method='ROUND_ROBIN',
@@ -118,16 +119,36 @@
                                             protocol="HTTP",
                                             protocol_port=80,
                                             subnet_id=self.subnet['id'],
-                                            pool_id=pool['id'])
+                                            pool_id=pool['id'],
+                                            address=address)
         self.assertEqual('201', resp['status'])
         vip = body['vip']
         vip_id = vip['id']
+        # Confirm VIP's address correctness with a show
+        resp, body = self.client.show_vip(vip_id)
+        self.assertEqual('200', resp['status'])
+        vip = body['vip']
+        self.assertEqual(address, vip['address'])
         # Verification of vip update
         new_name = "New_vip"
-        resp, body = self.client.update_vip(vip_id, name=new_name)
+        new_description = "New description"
+        persistence_type = "HTTP_COOKIE"
+        update_data = {"session_persistence": {
+            "type": persistence_type}}
+        resp, body = self.client.update_vip(vip_id,
+                                            name=new_name,
+                                            description=new_description,
+                                            connection_limit=10,
+                                            admin_state_up=False,
+                                            **update_data)
         self.assertEqual('200', resp['status'])
         updated_vip = body['vip']
-        self.assertEqual(updated_vip['name'], new_name)
+        self.assertEqual(new_name, updated_vip['name'])
+        self.assertEqual(new_description, updated_vip['description'])
+        self.assertEqual(10, updated_vip['connection_limit'])
+        self.assertFalse(updated_vip['admin_state_up'])
+        self.assertEqual(persistence_type,
+                         updated_vip['session_persistence']['type'])
         # Verification of vip delete
         resp, body = self.client.delete_vip(vip['id'])
         self.assertEqual('204', resp['status'])
@@ -274,6 +295,40 @@
         self.assertEqual('204', resp['status'])
 
     @test.attr(type='smoke')
+    def test_create_health_monitor_http_type(self):
+        hm_type = "HTTP"
+        resp, body = self.client.create_health_monitor(delay=4,
+                                                       max_retries=3,
+                                                       type=hm_type,
+                                                       timeout=1)
+        self.assertEqual('201', resp['status'])
+        health_monitor = body['health_monitor']
+        self.addCleanup(self.client.delete_health_monitor,
+                        health_monitor['id'])
+        self.assertEqual(hm_type, health_monitor['type'])
+
+    @test.attr(type='smoke')
+    def test_update_health_monitor_http_method(self):
+        resp, body = self.client.create_health_monitor(delay=4,
+                                                       max_retries=3,
+                                                       type="HTTP",
+                                                       timeout=1)
+        self.assertEqual('201', resp['status'])
+        health_monitor = body['health_monitor']
+        self.addCleanup(self.client.delete_health_monitor,
+                        health_monitor['id'])
+        resp, body = (self.client.update_health_monitor
+                     (health_monitor['id'],
+                      http_method="POST",
+                      url_path="/home/user",
+                      expected_codes="290"))
+        self.assertEqual('200', resp['status'])
+        updated_health_monitor = body['health_monitor']
+        self.assertEqual("POST", updated_health_monitor['http_method'])
+        self.assertEqual("/home/user", updated_health_monitor['url_path'])
+        self.assertEqual("290", updated_health_monitor['expected_codes'])
+
+    @test.attr(type='smoke')
     def test_show_health_monitor(self):
         # Verifies the details of a health_monitor
         resp, body = self.client.show_health_monitor(self.health_monitor['id'])
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 88e7238..70fb00a 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -67,7 +67,6 @@
         cls.name = cls.network['name']
         cls.subnet = cls.create_subnet(cls.network)
         cls.cidr = cls.subnet['cidr']
-        cls.port = cls.create_port(cls.network)
 
     @attr(type='smoke')
     def test_create_update_delete_network_subnet(self):
@@ -184,90 +183,6 @@
             self.assertEqual(len(subnet), 1)
             self.assertIn('id', subnet)
 
-    @attr(type='smoke')
-    def test_create_update_delete_port(self):
-        # Verify port creation
-        resp, body = self.client.create_port(network_id=self.network['id'])
-        self.assertEqual('201', resp['status'])
-        port = body['port']
-        self.assertTrue(port['admin_state_up'])
-        # Verify port update
-        new_name = "New_Port"
-        resp, body = self.client.update_port(
-            port['id'],
-            name=new_name,
-            admin_state_up=False)
-        self.assertEqual('200', resp['status'])
-        updated_port = body['port']
-        self.assertEqual(updated_port['name'], new_name)
-        self.assertFalse(updated_port['admin_state_up'])
-        # Verify port deletion
-        resp, body = self.client.delete_port(port['id'])
-        self.assertEqual('204', resp['status'])
-
-    @attr(type='smoke')
-    def test_show_port(self):
-        # Verify the details of port
-        resp, body = self.client.show_port(self.port['id'])
-        self.assertEqual('200', resp['status'])
-        port = body['port']
-        self.assertIn('id', port)
-        self.assertEqual(port['id'], self.port['id'])
-
-    @attr(type='smoke')
-    def test_show_port_fields(self):
-        # Verify specific fields of a port
-        field_list = [('fields', 'id'), ]
-        resp, body = self.client.show_port(self.port['id'],
-                                           field_list=field_list)
-        self.assertEqual('200', resp['status'])
-        port = body['port']
-        self.assertEqual(len(port), len(field_list))
-        for label, field_name in field_list:
-            self.assertEqual(port[field_name], self.port[field_name])
-
-    @attr(type='smoke')
-    def test_list_ports(self):
-        # Verify the port exists in the list of all ports
-        resp, body = self.client.list_ports()
-        self.assertEqual('200', resp['status'])
-        ports = [port['id'] for port in body['ports']
-                 if port['id'] == self.port['id']]
-        self.assertNotEmpty(ports, "Created port not found in the list")
-
-    @attr(type='smoke')
-    def test_port_list_filter_by_router_id(self):
-        # Create a router
-        network = self.create_network()
-        self.create_subnet(network)
-        router = self.create_router(data_utils.rand_name('router-'))
-        resp, port = self.client.create_port(network_id=network['id'])
-        # Add router interface to port created above
-        resp, interface = self.client.add_router_interface_with_port_id(
-            router['id'], port['port']['id'])
-        self.addCleanup(self.client.remove_router_interface_with_port_id,
-                        router['id'], port['port']['id'])
-        # List ports filtered by router_id
-        resp, port_list = self.client.list_ports(
-            device_id=router['id'])
-        self.assertEqual('200', resp['status'])
-        ports = port_list['ports']
-        self.assertEqual(len(ports), 1)
-        self.assertEqual(ports[0]['id'], port['port']['id'])
-        self.assertEqual(ports[0]['device_id'], router['id'])
-
-    @attr(type='smoke')
-    def test_list_ports_fields(self):
-        # Verify specific fields of ports
-        resp, body = self.client.list_ports(fields='id')
-        self.assertEqual('200', resp['status'])
-        ports = body['ports']
-        self.assertNotEmpty(ports, "Port list returned is empty")
-        # Asserting the fields returned are correct
-        for port in ports:
-            self.assertEqual(len(port), 1)
-            self.assertIn('id', port)
-
 
 class NetworksTestXML(NetworksTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
new file mode 100644
index 0000000..fbb25a8
--- /dev/null
+++ b/tempest/api/network/test_ports.py
@@ -0,0 +1,249 @@
+# Copyright 2014 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import socket
+
+from tempest.api.network import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+class PortsTestJSON(base.BaseNetworkTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(PortsTestJSON, cls).setUpClass()
+        cls.network = cls.create_network()
+        cls.port = cls.create_port(cls.network)
+
+    def _delete_port(self, port_id):
+        resp, body = self.client.delete_port(port_id)
+        self.assertEqual('204', resp['status'])
+        resp, body = self.client.list_ports()
+        self.assertEqual('200', resp['status'])
+        ports_list = body['ports']
+        self.assertFalse(port_id in [n['id'] for n in ports_list])
+
+    @test.attr(type='smoke')
+    def test_create_update_delete_port(self):
+        # Verify port creation
+        resp, body = self.client.create_port(network_id=self.network['id'])
+        self.assertEqual('201', resp['status'])
+        port = body['port']
+        self.assertTrue(port['admin_state_up'])
+        # Verify port update
+        new_name = "New_Port"
+        resp, body = self.client.update_port(
+            port['id'],
+            name=new_name,
+            admin_state_up=False)
+        self.assertEqual('200', resp['status'])
+        updated_port = body['port']
+        self.assertEqual(updated_port['name'], new_name)
+        self.assertFalse(updated_port['admin_state_up'])
+        # Verify port deletion
+        resp, body = self.client.delete_port(port['id'])
+        self.assertEqual('204', resp['status'])
+
+    @test.attr(type='smoke')
+    def test_show_port(self):
+        # Verify the details of port
+        resp, body = self.client.show_port(self.port['id'])
+        self.assertEqual('200', resp['status'])
+        port = body['port']
+        self.assertIn('id', port)
+        self.assertEqual(port['id'], self.port['id'])
+        self.assertEqual(self.port['admin_state_up'], port['admin_state_up'])
+        self.assertEqual(self.port['device_id'], port['device_id'])
+        self.assertEqual(self.port['device_owner'], port['device_owner'])
+        self.assertEqual(self.port['mac_address'], port['mac_address'])
+        self.assertEqual(self.port['name'], port['name'])
+        self.assertEqual(self.port['security_groups'],
+                         port['security_groups'])
+        self.assertEqual(self.port['network_id'], port['network_id'])
+        self.assertEqual(self.port['security_groups'],
+                         port['security_groups'])
+
+    @test.attr(type='smoke')
+    def test_show_port_fields(self):
+        # Verify specific fields of a port
+        field_list = [('fields', 'id'), ]
+        resp, body = self.client.show_port(self.port['id'],
+                                           field_list=field_list)
+        self.assertEqual('200', resp['status'])
+        port = body['port']
+        self.assertEqual(len(port), len(field_list))
+        for label, field_name in field_list:
+            self.assertEqual(port[field_name], self.port[field_name])
+
+    @test.attr(type='smoke')
+    def test_list_ports(self):
+        # Verify the port exists in the list of all ports
+        resp, body = self.client.list_ports()
+        self.assertEqual('200', resp['status'])
+        ports = [port['id'] for port in body['ports']
+                 if port['id'] == self.port['id']]
+        self.assertNotEmpty(ports, "Created port not found in the list")
+
+    @test.attr(type='smoke')
+    def test_port_list_filter_by_router_id(self):
+        # Create a router
+        network = self.create_network()
+        self.create_subnet(network)
+        router = self.create_router(data_utils.rand_name('router-'))
+        resp, port = self.client.create_port(network_id=network['id'])
+        # Add router interface to port created above
+        resp, interface = self.client.add_router_interface_with_port_id(
+            router['id'], port['port']['id'])
+        self.addCleanup(self.client.remove_router_interface_with_port_id,
+                        router['id'], port['port']['id'])
+        # List ports filtered by router_id
+        resp, port_list = self.client.list_ports(
+            device_id=router['id'])
+        self.assertEqual('200', resp['status'])
+        ports = port_list['ports']
+        self.assertEqual(len(ports), 1)
+        self.assertEqual(ports[0]['id'], port['port']['id'])
+        self.assertEqual(ports[0]['device_id'], router['id'])
+
+    @test.attr(type='smoke')
+    def test_list_ports_fields(self):
+        # Verify specific fields of ports
+        resp, body = self.client.list_ports(fields='id')
+        self.assertEqual('200', resp['status'])
+        ports = body['ports']
+        self.assertNotEmpty(ports, "Port list returned is empty")
+        # Asserting the fields returned are correct
+        for port in ports:
+            self.assertEqual(len(port), 1)
+            self.assertIn('id', port)
+
+
+class PortsTestXML(PortsTestJSON):
+    _interface = 'xml'
+
+
+class PortsAdminExtendedAttrsTestJSON(base.BaseAdminNetworkTest):
+    _interface = 'json'
+
+    @classmethod
+    def setUpClass(cls):
+        super(PortsAdminExtendedAttrsTestJSON, cls).setUpClass()
+        cls.identity_client = cls._get_identity_admin_client()
+        cls.tenant = cls.identity_client.get_tenant_by_name(
+            CONF.identity.tenant_name)
+        cls.network = cls.create_network()
+        cls.host_id = socket.gethostname()
+
+    @test.attr(type='smoke')
+    def test_create_port_binding_ext_attr(self):
+        post_body = {"network_id": self.network['id'],
+                     "binding:host_id": self.host_id}
+        resp, body = self.admin_client.create_port(**post_body)
+        self.assertEqual('201', resp['status'])
+        port = body['port']
+        self.addCleanup(self.admin_client.delete_port, port['id'])
+        host_id = port['binding:host_id']
+        self.assertIsNotNone(host_id)
+        self.assertEqual(self.host_id, host_id)
+
+    @test.attr(type='smoke')
+    def test_update_port_binding_ext_attr(self):
+        post_body = {"network_id": self.network['id']}
+        resp, body = self.admin_client.create_port(**post_body)
+        self.assertEqual('201', resp['status'])
+        port = body['port']
+        self.addCleanup(self.admin_client.delete_port, port['id'])
+        update_body = {"binding:host_id": self.host_id}
+        resp, body = self.admin_client.update_port(port['id'], **update_body)
+        self.assertEqual('200', resp['status'])
+        updated_port = body['port']
+        host_id = updated_port['binding:host_id']
+        self.assertIsNotNone(host_id)
+        self.assertEqual(self.host_id, host_id)
+
+    @test.attr(type='smoke')
+    def test_list_ports_binding_ext_attr(self):
+        resp, body = self.admin_client.list_ports(
+            **{'tenant_id': self.tenant['id']})
+        self.assertEqual('200', resp['status'])
+        ports_list = body['ports']
+        for port in ports_list:
+            vif_type = port['binding:vif_type']
+            self.assertIsNotNone(vif_type)
+            vif_details = port['binding:vif_details']['port_filter']
+            self.assertIsNotNone(vif_details)
+
+    @test.attr(type='smoke')
+    def test_show_port_binding_ext_attr(self):
+        resp, body = self.admin_client.create_port(
+            network_id=self.network['id'])
+        self.assertEqual('201', resp['status'])
+        port = body['port']
+        self.addCleanup(self.admin_client.delete_port, port['id'])
+        resp, body = self.admin_client.show_port(port['id'])
+        self.assertEqual('200', resp['status'])
+        show_port = body['port']
+        self.assertEqual(port['binding:host_id'],
+                         show_port['binding:host_id'])
+        self.assertEqual(port['binding:vif_type'],
+                         show_port['binding:vif_type'])
+        self.assertEqual(port['binding:vif_details'],
+                         show_port['binding:vif_details'])
+
+
+class PortsAdminExtendedAttrsTestXML(PortsAdminExtendedAttrsTestJSON):
+    _interface = 'xml'
+
+
+class PortsIpV6TestJSON(PortsTestJSON):
+    _ip_version = 6
+    _tenant_network_cidr = CONF.network.tenant_network_v6_cidr
+    _tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
+
+    @classmethod
+    def setUpClass(cls):
+        super(PortsIpV6TestJSON, cls).setUpClass()
+        if not CONF.network_feature_enabled.ipv6:
+            cls.tearDownClass()
+            skip_msg = "IPv6 Tests are disabled."
+            raise cls.skipException(skip_msg)
+
+
+class PortsIpV6TestXML(PortsIpV6TestJSON):
+    _interface = 'xml'
+
+
+class PortsAdminExtendedAttrsIpV6TestJSON(PortsAdminExtendedAttrsTestJSON):
+    _ip_version = 6
+    _tenant_network_cidr = CONF.network.tenant_network_v6_cidr
+    _tenant_network_mask_bits = CONF.network.tenant_network_v6_mask_bits
+
+    @classmethod
+    def setUpClass(cls):
+        super(PortsAdminExtendedAttrsIpV6TestJSON, cls).setUpClass()
+        if not CONF.network_feature_enabled.ipv6:
+            cls.tearDownClass()
+            skip_msg = "IPv6 Tests are disabled."
+            raise cls.skipException(skip_msg)
+
+
+class PortsAdminExtendedAttrsIpV6TestXML(
+    PortsAdminExtendedAttrsIpV6TestJSON):
+    _interface = 'xml'
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index b14adc0..a3098a5 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -68,7 +68,7 @@
         # Retrieve a ResellerAdmin auth data and use it to set a quota
         # on the client's account
         cls.reselleradmin_auth_data = \
-            cls.os_reselleradmin.get_auth_provider().auth_data
+            cls.os_reselleradmin.auth_provider.auth_data
 
     def setUp(self):
         super(AccountQuotasTest, self).setUp()
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 402cd90..7648ea1 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -68,7 +68,7 @@
         # Retrieve a ResellerAdmin auth data and use it to set a quota
         # on the client's account
         cls.reselleradmin_auth_data = \
-            cls.os_reselleradmin.get_auth_provider().auth_data
+            cls.os_reselleradmin.auth_provider.auth_data
 
     def setUp(self):
         super(AccountQuotasNegativeTest, self).setUp()
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index ea93aa3..71eaab5 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -31,7 +31,7 @@
         test_os = clients.Manager(self.data.test_user,
                                   self.data.test_password,
                                   self.data.test_tenant)
-        test_auth_provider = test_os.get_auth_provider()
+        test_auth_provider = test_os.auth_provider
         # Get auth for the test user
         test_auth_provider.auth_data
 
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index 085ef51..c865ee1 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -27,7 +27,7 @@
         test_os = clients.Manager(cls.data.test_user,
                                   cls.data.test_password,
                                   cls.data.test_tenant)
-        cls.test_auth_data = test_os.get_auth_provider().auth_data
+        cls.test_auth_data = test_os.auth_provider.auth_data
 
     @classmethod
     def tearDownClass(cls):
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index a5a0950..547bf87 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -29,7 +29,7 @@
         test_os = clients.Manager(cls.data.test_user,
                                   cls.data.test_password,
                                   cls.data.test_tenant)
-        cls.test_auth_data = test_os.get_auth_provider().auth_data
+        cls.test_auth_data = test_os.auth_provider.auth_data
 
     @classmethod
     def tearDownClass(cls):
diff --git a/tempest/api/volume/admin/test_snapshots_actions.py b/tempest/api/volume/admin/test_snapshots_actions.py
index e140ad0..594c703 100644
--- a/tempest/api/volume/admin/test_snapshots_actions.py
+++ b/tempest/api/volume/admin/test_snapshots_actions.py
@@ -22,6 +22,7 @@
     _interface = "json"
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(SnapshotsActionsTest, cls).setUpClass()
         cls.client = cls.snapshots_client
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 742f7e1..cf308f5 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -65,7 +65,10 @@
         self.addCleanup(self.quotas_client.update_quota_set,
                         self.demo_tenant_id, **default_quota_set)
         self.assertEqual(200, resp.status)
-        self.assertEqual(new_quota_set, quota_set)
+        # test that the specific values we set are actually in
+        # the final result. There is nothing here that ensures there
+        # would be no other values in there.
+        self.assertDictContainsSubset(new_quota_set, quota_set)
 
     @test.attr(type='gate')
     def test_show_quota_usage(self):
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index 8183999..ee1d09a 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -116,3 +116,35 @@
         self.assertEqual(extra_specs, fetched_volume_type['extra_specs'],
                          'The fetched Volume_type is different '
                          'from the created Volume_type')
+
+    @test.attr(type='smoke')
+    def test_volume_type_encryption_create_get(self):
+        # Create/get encryption type.
+        provider = "LuksEncryptor"
+        control_location = "front-end"
+        name = data_utils.rand_name("volume-type-")
+        resp, body = self.client.create_volume_type(name)
+        self.assertEqual(200, resp.status)
+        self.addCleanup(self._delete_volume_type, body['id'])
+        resp, encryption_type = self.client.create_encryption_type(
+            body['id'], provider=provider,
+            control_location=control_location)
+        self.assertEqual(200, resp.status)
+        self.assertIn('volume_type_id', encryption_type)
+        self.assertEqual(provider, encryption_type['provider'],
+                         "The created encryption_type provider is not equal "
+                         "to the requested provider")
+        self.assertEqual(control_location, encryption_type['control_location'],
+                         "The created encryption_type control_location is not "
+                         "equal to the requested control_location")
+        resp, fetched_encryption_type = self.client.get_encryption_type(
+            encryption_type['volume_type_id'])
+        self.assertEqual(200, resp.status)
+        self.assertEqual(provider,
+                         fetched_encryption_type['provider'],
+                         'The fetched encryption_type provider is different '
+                         'from the created encryption_type')
+        self.assertEqual(control_location,
+                         fetched_encryption_type['control_location'],
+                         'The fetched encryption_type control_location is '
+                         'different from the created encryption_type')
diff --git a/tempest/api/volume/admin/test_volumes_actions.py b/tempest/api/volume/admin/test_volumes_actions.py
index aa00700..4496f18 100644
--- a/tempest/api/volume/admin/test_volumes_actions.py
+++ b/tempest/api/volume/admin/test_volumes_actions.py
@@ -22,6 +22,7 @@
     _interface = "json"
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(VolumesActionsTest, cls).setUpClass()
         cls.client = cls.volumes_client
diff --git a/tempest/api/volume/test_snapshot_metadata.py b/tempest/api/volume/test_snapshot_metadata.py
index 1493b37..d2c4ab7 100644
--- a/tempest/api/volume/test_snapshot_metadata.py
+++ b/tempest/api/volume/test_snapshot_metadata.py
@@ -21,6 +21,7 @@
     _interface = "json"
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(SnapshotMetadataTest, cls).setUpClass()
         cls.client = cls.snapshots_client
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index a22ad32..cfab0bd 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -25,6 +25,7 @@
     _interface = "json"
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(VolumesActionsTest, cls).setUpClass()
         cls.client = cls.volumes_client
@@ -44,7 +45,7 @@
     def tearDownClass(cls):
         # Delete the test instance
         cls.servers_client.delete_server(cls.server['id'])
-        cls.client.wait_for_resource_deletion(cls.server['id'])
+        cls.servers_client.wait_for_server_termination(cls.server['id'])
 
         super(VolumesActionsTest, cls).tearDownClass()
 
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 2701e84..84c9501 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -71,8 +71,8 @@
         resp, server = self.servers_client.create_server(server_name,
                                                          self.image_ref,
                                                          self.flavor_ref)
-        self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
         self.addCleanup(self.servers_client.delete_server, server['id'])
+        self.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
         mountpoint = '/dev/%s' % CONF.compute.volume_device_name
         resp, body = self.volumes_client.attach_volume(
             self.volume_origin['id'], server['id'], mountpoint)
diff --git a/tempest/api_schema/compute/v2/fixed_ips.py b/tempest/api_schema/compute/v2/fixed_ips.py
new file mode 100644
index 0000000..a6add04
--- /dev/null
+++ b/tempest/api_schema/compute/v2/fixed_ips.py
@@ -0,0 +1,36 @@
+# Copyright 2014 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+fixed_ips = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'fixed_ip': {
+                'type': 'object',
+                'properties': {
+                    'address': {
+                        'type': 'string',
+                        'format': 'ip-address'
+                    },
+                    'cidr': {'type': 'string'},
+                    'host': {'type': 'string'},
+                    'hostname': {'type': 'string'}
+                },
+                'required': ['address', 'cidr', 'host', 'hostname']
+            }
+        },
+        'required': ['fixed_ip']
+    }
+}
diff --git a/tempest/api_schema/compute/v2/floating_ips.py b/tempest/api_schema/compute/v2/floating_ips.py
new file mode 100644
index 0000000..61582ec
--- /dev/null
+++ b/tempest/api_schema/compute/v2/floating_ips.py
@@ -0,0 +1,46 @@
+# Copyright 2014 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+list_floating_ips = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'floating_ips': {
+                'type': 'array',
+                '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']},
+                        'pool': {'type': ['string', 'null']},
+                        'instance_id': {'type': ['integer', 'string', 'null']},
+                        'ip': {
+                            'type': 'string',
+                            'format': 'ip-address'
+                        },
+                        'fixed_ip': {
+                            'type': ['string', 'null'],
+                            'format': 'ip-address'
+                        }
+                    },
+                    'required': ['id', 'pool', 'instance_id', 'ip', 'fixed_ip']
+                }
+            }
+        },
+        'required': ['floating_ips']
+    }
+}
diff --git a/tempest/api_schema/compute/v2/limits.py b/tempest/api_schema/compute/v2/limits.py
new file mode 100644
index 0000000..b9857f1
--- /dev/null
+++ b/tempest/api_schema/compute/v2/limits.py
@@ -0,0 +1,94 @@
+# Copyright 2014 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+get_limit = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'limits': {
+                'type': 'object',
+                'properties': {
+                    'absolute': {
+                        'type': 'object',
+                        'properties': {
+                            'maxTotalRAMSize': {'type': 'integer'},
+                            'totalCoresUsed': {'type': 'integer'},
+                            'maxTotalInstances': {'type': 'integer'},
+                            'maxTotalFloatingIps': {'type': 'integer'},
+                            'totalSecurityGroupsUsed': {'type': 'integer'},
+                            'maxTotalCores': {'type': 'integer'},
+                            'totalFloatingIpsUsed': {'type': 'integer'},
+                            'maxSecurityGroups': {'type': 'integer'},
+                            'maxServerMeta': {'type': 'integer'},
+                            'maxPersonality': {'type': 'integer'},
+                            'maxImageMeta': {'type': 'integer'},
+                            'maxPersonalitySize': {'type': 'integer'},
+                            'maxSecurityGroupRules': {'type': 'integer'},
+                            'maxTotalKeypairs': {'type': 'integer'},
+                            'totalRAMUsed': {'type': 'integer'},
+                            'totalInstancesUsed': {'type': 'integer'}
+                        },
+                        'required': ['maxImageMeta',
+                                     'maxPersonality',
+                                     'maxPersonalitySize',
+                                     'maxSecurityGroupRules',
+                                     'maxSecurityGroups',
+                                     'maxServerMeta',
+                                     'maxTotalCores',
+                                     'maxTotalFloatingIps',
+                                     'maxTotalInstances',
+                                     'maxTotalKeypairs',
+                                     'maxTotalRAMSize',
+                                     'totalCoresUsed',
+                                     'totalFloatingIpsUsed',
+                                     'totalInstancesUsed',
+                                     'totalRAMUsed',
+                                     'totalSecurityGroupsUsed']
+                    },
+                    'rate': {
+                        'type': 'array',
+                        'items': {
+                            'type': 'object',
+                            'properties': {
+                                'limit': {
+                                    'type': 'array',
+                                    'items': {
+                                        'type': 'object',
+                                        'properties': {
+                                            'next-available':
+                                                {'type': 'string'},
+                                            'remaining':
+                                                {'type': 'integer'},
+                                            'unit':
+                                                {'type': 'string'},
+                                            'value':
+                                                {'type': 'integer'},
+                                            'verb':
+                                                {'type': 'string'}
+                                        }
+                                    }
+                                },
+                                'regex': {'type': 'string'},
+                                'uri': {'type': 'string'}
+                            }
+                        }
+                    }
+                },
+                'required': ['absolute', 'rate']
+            }
+        },
+        'required': ['limits']
+    }
+}
diff --git a/tempest/api_schema/compute/v2/servers.py b/tempest/api_schema/compute/v2/servers.py
new file mode 100644
index 0000000..7f06ca6
--- /dev/null
+++ b/tempest/api_schema/compute/v2/servers.py
@@ -0,0 +1,53 @@
+# Copyright 2014 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+create_server = {
+    'status_code': [202],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'server': {
+                'type': 'object',
+                'properties': {
+                    # NOTE: Now the type of 'id' is uuid, but here allows
+                    # 'integer' also because old OpenStack uses 'integer'
+                    # as a server id.
+                    'id': {'type': ['integer', 'string']},
+                    'security_groups': {'type': 'array'},
+                    'links': {
+                        'type': 'array',
+                        'items': {
+                            'type': 'object',
+                            'properties': {
+                                'href': {
+                                    'type': 'string',
+                                    'format': 'uri'
+                                },
+                                'rel': {'type': 'string'}
+                            },
+                            'required': ['href', 'rel']
+                        }
+                    },
+                    'adminPass': {'type': 'string'},
+                    'OS-DCF:diskConfig': {'type': 'string'}
+                },
+                # NOTE: OS-DCF:diskConfig is API extension, and some
+                # environments return a response without the attribute.
+                # So it is not 'required'.
+                'required': ['id', 'security_groups', 'links', 'adminPass']
+            }
+        },
+        'required': ['server']
+    }
+}
diff --git a/tempest/api_schema/compute/v3/__init__.py b/tempest/api_schema/compute/v3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/compute/v3/__init__.py
diff --git a/tempest/api_schema/compute/v3/servers.py b/tempest/api_schema/compute/v3/servers.py
new file mode 100644
index 0000000..e69b25f
--- /dev/null
+++ b/tempest/api_schema/compute/v3/servers.py
@@ -0,0 +1,55 @@
+# Copyright 2014 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+create_server = {
+    'status_code': [202],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'server': {
+                'type': 'object',
+                'properties': {
+                    # NOTE: Now the type of 'id' is uuid, but here allows
+                    # 'integer' also because old OpenStack uses 'integer'
+                    # as a server id.
+                    'id': {'type': ['integer', 'string']},
+                    'os-security-groups:security_groups': {'type': 'array'},
+                    'links': {
+                        'type': 'array',
+                        'items': {
+                            'type': 'object',
+                            'properties': {
+                                'href': {
+                                    'type': 'string',
+                                    'format': 'uri'
+                                },
+                                'rel': {'type': 'string'}
+                            },
+                            'required': ['href', 'rel']
+                        }
+                    },
+                    'admin_password': {'type': 'string'},
+                    'os-access-ips:access_ip_v4': {'type': 'string'},
+                    'os-access-ips:access_ip_v6': {'type': 'string'}
+                },
+                # NOTE: os-access-ips:access_ip_v4/v6 are API extension,
+                # and some environments return a response without these
+                # attributes. So they are not 'required'.
+                'required': ['id', 'os-security-groups:security_groups',
+                             'links', 'admin_password']
+            }
+        },
+        'required': ['server']
+    }
+}
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index 810e6b2..932b151 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -42,6 +42,7 @@
 
     def nova(self, action, flags='', params='', admin=True, fail_ok=False):
         """Executes nova command for the given action."""
+        flags += ' --endpoint-type %s' % CONF.compute.endpoint_type
         return self.cmd_with_auth(
             'nova', action, flags, params, admin, fail_ok)
 
@@ -58,33 +59,39 @@
 
     def glance(self, action, flags='', params='', admin=True, fail_ok=False):
         """Executes glance command for the given action."""
+        flags += ' --os-endpoint-type %s' % CONF.image.endpoint_type
         return self.cmd_with_auth(
             'glance', action, flags, params, admin, fail_ok)
 
     def ceilometer(self, action, flags='', params='', admin=True,
                    fail_ok=False):
         """Executes ceilometer command for the given action."""
+        flags += ' --os-endpoint-type %s' % CONF.telemetry.endpoint_type
         return self.cmd_with_auth(
             'ceilometer', action, flags, params, admin, fail_ok)
 
     def heat(self, action, flags='', params='', admin=True,
              fail_ok=False):
         """Executes heat command for the given action."""
+        flags += ' --os-endpoint-type %s' % CONF.orchestration.endpoint_type
         return self.cmd_with_auth(
             'heat', action, flags, params, admin, fail_ok)
 
     def cinder(self, action, flags='', params='', admin=True, fail_ok=False):
         """Executes cinder command for the given action."""
+        flags += ' --endpoint-type %s' % CONF.volume.endpoint_type
         return self.cmd_with_auth(
             'cinder', action, flags, params, admin, fail_ok)
 
     def neutron(self, action, flags='', params='', admin=True, fail_ok=False):
         """Executes neutron command for the given action."""
+        flags += ' --endpoint-type %s' % CONF.network.endpoint_type
         return self.cmd_with_auth(
             'neutron', action, flags, params, admin, fail_ok)
 
     def sahara(self, action, flags='', params='', admin=True, fail_ok=False):
         """Executes sahara command for the given action."""
+        flags += ' --endpoint-type %s' % CONF.data_processing.endpoint_type
         return self.cmd_with_auth(
             # TODO (slukjanov): replace with sahara when new client released
             'savanna', action, flags, params, admin, fail_ok)
@@ -94,7 +101,7 @@
         """Executes given command with auth attributes appended."""
         # TODO(jogo) make admin=False work
         creds = ('--os-username %s --os-tenant-name %s --os-password %s '
-                 '--os-auth-url %s ' %
+                 '--os-auth-url %s' %
                  (CONF.identity.admin_username,
                   CONF.identity.admin_tenant_name,
                   CONF.identity.admin_password,
diff --git a/tempest/cli/simple_read_only/test_ceilometer.py b/tempest/cli/simple_read_only/test_ceilometer.py
index 0b6ae22..1d2822d 100644
--- a/tempest/cli/simple_read_only/test_ceilometer.py
+++ b/tempest/cli/simple_read_only/test_ceilometer.py
@@ -16,6 +16,7 @@
 from tempest import cli
 from tempest import config
 from tempest.openstack.common import log as logging
+from tempest import test
 
 CONF = config.CONF
 
@@ -41,6 +42,7 @@
     def test_ceilometer_meter_list(self):
         self.ceilometer('meter-list')
 
+    @test.attr(type='slow')
     def test_ceilometer_resource_list(self):
         self.ceilometer('resource-list')
 
diff --git a/tempest/exceptions/__init__.py b/tempest/exceptions/__init__.py
index 06dee71..485f532 100644
--- a/tempest/exceptions/__init__.py
+++ b/tempest/exceptions/__init__.py
@@ -20,6 +20,10 @@
     message = "Invalid Configuration"
 
 
+class InvalidCredentials(base.TempestException):
+    message = "Invalid Credentials"
+
+
 class InvalidHttpSuccessCode(base.RestClientException):
     message = "The success code is different than the expected one"
 
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index 55be60a..7f39905 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -15,7 +15,9 @@
 import re
 
 
-PYTHON_CLIENTS = ['cinder', 'glance', 'keystone', 'nova', 'swift', 'neutron']
+PYTHON_CLIENTS = ['cinder', 'glance', 'keystone', 'nova', 'swift', 'neutron',
+                  'trove', 'ironic', 'savanna', 'heat', 'ceilometer',
+                  'marconi']
 
 PYTHON_CLIENT_RE = re.compile('import (%s)client' % '|'.join(PYTHON_CLIENTS))
 TEST_DEFINITION = re.compile(r'^\s*def test.*')
diff --git a/tempest/manager.py b/tempest/manager.py
index 708447e..63235db 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -75,13 +75,12 @@
             tenant_name=CONF.identity.tenant_name
         )
 
-    def get_auth_provider(self, credentials=None):
-        auth_params = dict(client_type=getattr(self, 'client_type', None),
-                           interface=getattr(self, 'interface', None))
+    def get_auth_provider(self, credentials):
+        if credentials is None:
+            raise exceptions.InvalidCredentials(
+                'Credentials must be specified')
         auth_provider_class = self.get_auth_provider_class(self.auth_version)
-        # If invalid / incomplete credentials are provided, use default ones
-        if credentials is None or \
-                not auth_provider_class.check_credentials(credentials):
-            credentials = self.credentials
-        auth_params['credentials'] = credentials
-        return auth_provider_class(**auth_params)
+        return auth_provider_class(
+            client_type=getattr(self, 'client_type', None),
+            interface=getattr(self, 'interface', None),
+            credentials=credentials)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 4046cbd..e89ea70 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -169,3 +169,15 @@
         # deletion operations to succeed
         self._stop_instances([instance_2nd, instance_from_snapshot])
         self._detach_volumes([volume_origin, volume])
+
+
+class TestVolumeBootPatternV2(TestVolumeBootPattern):
+    def _boot_instance_from_volume(self, vol_id, keypair):
+        bdms = [{'uuid': vol_id, 'source_type': 'volume',
+                 'destination_type': 'volume', 'boot_index': 0,
+                 'delete_on_termination': False}]
+        create_kwargs = {
+            'block_device_mapping_v2': bdms,
+            'key_name': keypair.name
+        }
+        return self.create_server(image='', create_kwargs=create_kwargs)
diff --git a/tempest/services/compute/json/fixed_ips_client.py b/tempest/services/compute/json/fixed_ips_client.py
index 8b2c6c9..5fdd564 100644
--- a/tempest/services/compute/json/fixed_ips_client.py
+++ b/tempest/services/compute/json/fixed_ips_client.py
@@ -15,6 +15,7 @@
 
 import json
 
+from tempest.api_schema.compute.v2 import fixed_ips as schema
 from tempest.common import rest_client
 from tempest import config
 
@@ -31,6 +32,7 @@
         url = "os-fixed-ips/%s" % (fixed_ip)
         resp, body = self.get(url)
         body = json.loads(body)
+        self.validate_response(schema.fixed_ips, resp, body)
         return resp, body['fixed_ip']
 
     def reserve_fixed_ip(self, ip, body):
diff --git a/tempest/services/compute/json/floating_ips_client.py b/tempest/services/compute/json/floating_ips_client.py
index 42487c3..2a7e25a 100644
--- a/tempest/services/compute/json/floating_ips_client.py
+++ b/tempest/services/compute/json/floating_ips_client.py
@@ -16,6 +16,7 @@
 import json
 import urllib
 
+from tempest.api_schema.compute.v2 import floating_ips as schema
 from tempest.common import rest_client
 from tempest import config
 from tempest import exceptions
@@ -36,6 +37,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
+        self.validate_response(schema.list_floating_ips, resp, body)
         return resp, body['floating_ips']
 
     def get_floating_ip_details(self, floating_ip_id):
diff --git a/tempest/services/compute/json/limits_client.py b/tempest/services/compute/json/limits_client.py
index 1493718..e503bef 100644
--- a/tempest/services/compute/json/limits_client.py
+++ b/tempest/services/compute/json/limits_client.py
@@ -15,6 +15,7 @@
 
 import json
 
+from tempest.api_schema.compute.v2 import limits as schema
 from tempest.common import rest_client
 from tempest import config
 
@@ -30,11 +31,13 @@
     def get_absolute_limits(self):
         resp, body = self.get("limits")
         body = json.loads(body)
+        self.validate_response(schema.get_limit, resp, body)
         return resp, body['limits']['absolute']
 
     def get_specific_absolute_limit(self, absolute_limit):
         resp, body = self.get("limits")
         body = json.loads(body)
+        self.validate_response(schema.get_limit, resp, body)
         if absolute_limit not in body['limits']['absolute']:
             return None
         else:
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
index c1ac3db..2fae927 100644
--- a/tempest/services/compute/json/quotas_client.py
+++ b/tempest/services/compute/json/quotas_client.py
@@ -27,10 +27,12 @@
         super(QuotasClientJSON, self).__init__(auth_provider)
         self.service = CONF.compute.catalog_type
 
-    def get_quota_set(self, tenant_id):
+    def get_quota_set(self, tenant_id, user_id=None):
         """List the quota set for a tenant."""
 
         url = 'os-quota-sets/%s' % str(tenant_id)
+        if user_id:
+            url += '?user_id=%s' % str(user_id)
         resp, body = self.get(url)
         body = json.loads(body)
         return resp, body['quota_set']
diff --git a/tempest/services/compute/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index ca0f114..4eba2b4 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -18,6 +18,7 @@
 import time
 import urllib
 
+from tempest.api_schema.compute.v2 import servers as schema
 from tempest.common import rest_client
 from tempest.common import waiters
 from tempest import config
@@ -85,6 +86,7 @@
         # with return reservation id set True
         if 'reservation_id' in body:
             return resp, body
+        self.validate_response(schema.create_server, resp, body)
         return resp, body['server']
 
     def update_server(self, server_id, name=None, meta=None, accessIPv4=None,
diff --git a/tempest/services/compute/v3/json/quotas_client.py b/tempest/services/compute/v3/json/quotas_client.py
index 32e31a3..ed92aae 100644
--- a/tempest/services/compute/v3/json/quotas_client.py
+++ b/tempest/services/compute/v3/json/quotas_client.py
@@ -27,10 +27,12 @@
         super(QuotasV3ClientJSON, self).__init__(auth_provider)
         self.service = CONF.compute.catalog_v3_type
 
-    def get_quota_set(self, tenant_id):
+    def get_quota_set(self, tenant_id, user_id=None):
         """List the quota set for a tenant."""
 
         url = 'os-quota-sets/%s' % str(tenant_id)
+        if user_id:
+            url += '?user_id=%s' % str(user_id)
         resp, body = self.get(url)
         body = json.loads(body)
         return resp, body['quota_set']
@@ -96,3 +98,7 @@
 
         body = json.loads(body)
         return resp, body['quota_set']
+
+    def delete_quota_set(self, tenant_id):
+        """Delete the tenant's quota set."""
+        return self.delete('os-quota-sets/%s' % str(tenant_id))
diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py
index 92eb09b..6f492d0 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -19,6 +19,7 @@
 import time
 import urllib
 
+from tempest.api_schema.compute.v3 import servers as schema
 from tempest.common import rest_client
 from tempest.common import waiters
 from tempest import config
@@ -91,6 +92,7 @@
         # with return reservation id set True
         if 'servers_reservation' in body:
             return resp, body['servers_reservation']
+        self.validate_response(schema.create_server, resp, body)
         return resp, body['server']
 
     def update_server(self, server_id, name=None, meta=None, access_ip_v4=None,
diff --git a/tempest/services/compute/xml/common.py b/tempest/services/compute/xml/common.py
index b29b932..b1bf789 100644
--- a/tempest/services/compute/xml/common.py
+++ b/tempest/services/compute/xml/common.py
@@ -19,6 +19,7 @@
 XMLNS_V3 = "http://docs.openstack.org/compute/api/v1.1"
 
 NEUTRON_NAMESPACES = {
+    'binding': "http://docs.openstack.org/ext/binding/api/v1.0",
     'router': "http://docs.openstack.org/ext/neutron/router/api/v1.0",
     'provider': 'http://docs.openstack.org/ext/provider/api/v1.0',
 }
diff --git a/tempest/services/compute/xml/quotas_client.py b/tempest/services/compute/xml/quotas_client.py
index 85e481c..911c476 100644
--- a/tempest/services/compute/xml/quotas_client.py
+++ b/tempest/services/compute/xml/quotas_client.py
@@ -44,10 +44,12 @@
 
         return quota
 
-    def get_quota_set(self, tenant_id):
+    def get_quota_set(self, tenant_id, user_id=None):
         """List the quota set for a tenant."""
 
         url = 'os-quota-sets/%s' % str(tenant_id)
+        if user_id:
+            url += '?user_id=%s' % str(user_id)
         resp, body = self.get(url)
         body = xml_to_json(etree.fromstring(body))
         body = self._format_quota(body)
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/json/identity_client.py
index 9a31540..99b4036 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/json/identity_client.py
@@ -134,9 +134,10 @@
         post_body = {
             'name': name,
             'password': password,
-            'tenantId': tenant_id,
             'email': email
         }
+        if tenant_id is not None:
+            post_body['tenantId'] = tenant_id
         if kwargs.get('enabled') is not None:
             post_body['enabled'] = kwargs.get('enabled')
         post_body = json.dumps({'user': post_body})
@@ -233,16 +234,36 @@
 
         self.auth_url = auth_url
 
-    def auth(self, user, password, tenant):
+    def auth(self, user, password, tenant=None):
         creds = {
             'auth': {
                 'passwordCredentials': {
                     'username': user,
                     'password': password,
                 },
-                'tenantName': tenant,
             }
         }
+
+        if tenant:
+            creds['auth']['tenantName'] = tenant
+
+        body = json.dumps(creds)
+        resp, body = self.post(self.auth_url, body=body)
+
+        return resp, body['access']
+
+    def auth_token(self, token_id, tenant=None):
+        creds = {
+            'auth': {
+                'token': {
+                    'id': token_id,
+                },
+            }
+        }
+
+        if tenant:
+            creds['auth']['tenantName'] = tenant
+
         body = json.dumps(creds)
         resp, body = self.post(self.auth_url, body=body)
 
diff --git a/tempest/services/identity/v3/json/endpoints_client.py b/tempest/services/identity/v3/json/endpoints_client.py
index c3c1e15..f7a894b 100644
--- a/tempest/services/identity/v3/json/endpoints_client.py
+++ b/tempest/services/identity/v3/json/endpoints_client.py
@@ -36,9 +36,17 @@
         return resp, body['endpoints']
 
     def create_endpoint(self, service_id, interface, url, **kwargs):
-        """Create endpoint."""
+        """Create endpoint.
+
+        Normally this function wouldn't allow setting values that are not
+        allowed for 'enabled'. Use `force_enabled` to set a non-boolean.
+
+        """
         region = kwargs.get('region', None)
-        enabled = kwargs.get('enabled', None)
+        if 'force_enabled' in kwargs:
+            enabled = kwargs.get('force_enabled', None)
+        else:
+            enabled = kwargs.get('enabled', None)
         post_body = {
             'service_id': service_id,
             'interface': interface,
@@ -52,8 +60,13 @@
         return resp, body['endpoint']
 
     def update_endpoint(self, endpoint_id, service_id=None, interface=None,
-                        url=None, region=None, enabled=None):
-        """Updates an endpoint with given parameters."""
+                        url=None, region=None, enabled=None, **kwargs):
+        """Updates an endpoint with given parameters.
+
+        Normally this function wouldn't allow setting values that are not
+        allowed for 'enabled'. Use `force_enabled` to set a non-boolean.
+
+        """
         post_body = {}
         if service_id is not None:
             post_body['service_id'] = service_id
@@ -63,7 +76,9 @@
             post_body['url'] = url
         if region is not None:
             post_body['region'] = region
-        if enabled is not None:
+        if 'force_enabled' in kwargs:
+            post_body['enabled'] = kwargs['force_enabled']
+        elif enabled is not None:
             post_body['enabled'] = enabled
         post_body = json.dumps({'endpoint': post_body})
         resp, body = self.patch('endpoints/%s' % endpoint_id, post_body)
diff --git a/tempest/services/identity/v3/xml/endpoints_client.py b/tempest/services/identity/v3/xml/endpoints_client.py
index cc9aa65..a1f9811 100644
--- a/tempest/services/identity/v3/xml/endpoints_client.py
+++ b/tempest/services/identity/v3/xml/endpoints_client.py
@@ -62,11 +62,19 @@
         return resp, body
 
     def create_endpoint(self, service_id, interface, url, **kwargs):
-        """Create endpoint."""
+        """Create endpoint.
+
+        Normally this function wouldn't allow setting values that are not
+        allowed for 'enabled'. Use `force_enabled` to set a non-boolean.
+
+        """
         region = kwargs.get('region', None)
-        enabled = kwargs.get('enabled', None)
-        if enabled is not None:
-            enabled = str(enabled).lower()
+        if 'force_enabled' in kwargs:
+            enabled = kwargs['force_enabled']
+        else:
+            enabled = kwargs.get('enabled', None)
+            if enabled is not None:
+                enabled = str(enabled).lower()
         create_endpoint = common.Element("endpoint",
                                          xmlns=XMLNS,
                                          service_id=service_id,
@@ -79,8 +87,13 @@
         return resp, body
 
     def update_endpoint(self, endpoint_id, service_id=None, interface=None,
-                        url=None, region=None, enabled=None):
-        """Updates an endpoint with given parameters."""
+                        url=None, region=None, enabled=None, **kwargs):
+        """Updates an endpoint with given parameters.
+
+        Normally this function wouldn't allow setting values that are not
+        allowed for 'enabled'. Use `force_enabled` to set a non-boolean.
+
+        """
         doc = common.Document()
         endpoint = common.Element("endpoint")
         doc.append(endpoint)
@@ -93,8 +106,12 @@
             endpoint.add_attr("url", url)
         if region:
             endpoint.add_attr("region", region)
-        if enabled is not None:
+
+        if 'force_enabled' in kwargs:
+            endpoint.add_attr("enabled", kwargs['force_enabled'])
+        elif enabled is not None:
             endpoint.add_attr("enabled", str(enabled).lower())
+
         resp, body = self.patch('endpoints/%s' % str(endpoint_id), str(doc))
         body = self._parse_body(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 50403fb..c5bf310 100644
--- a/tempest/services/identity/xml/identity_client.py
+++ b/tempest/services/identity/xml/identity_client.py
@@ -75,8 +75,9 @@
                                   xmlns=XMLNS,
                                   name=name,
                                   password=password,
-                                  tenantId=tenant_id,
                                   email=email)
+        if tenant_id:
+            create_user.add_attr('tenantId', tenant_id)
         if 'enabled' in kwargs:
             create_user.add_attr('enabled', str(kwargs['enabled']).lower())
 
@@ -116,11 +117,24 @@
 class TokenClientXML(identity_client.TokenClientJSON):
     TYPE = "xml"
 
-    def auth(self, user, password, tenant):
-        passwordCreds = xml.Element("passwordCredentials",
+    def auth(self, user, password, tenant=None):
+        passwordCreds = xml.Element('passwordCredentials',
                                     username=user,
                                     password=password)
-        auth = xml.Element("auth", tenantName=tenant)
+        auth_kwargs = {}
+        if tenant:
+            auth_kwargs['tenantName'] = tenant
+        auth = xml.Element('auth', **auth_kwargs)
         auth.append(passwordCreds)
         resp, body = self.post(self.auth_url, body=str(xml.Document(auth)))
         return resp, body['access']
+
+    def auth_token(self, token_id, tenant=None):
+        tokenCreds = xml.Element('token', id=token_id)
+        auth_kwargs = {}
+        if tenant:
+            auth_kwargs['tenantName'] = tenant
+        auth = xml.Element('auth', **auth_kwargs)
+        auth.append(tokenCreds)
+        resp, body = self.post(self.auth_url, body=str(xml.Document(auth)))
+        return resp, body['access']
diff --git a/tempest/services/volume/json/admin/volume_types_client.py b/tempest/services/volume/json/admin/volume_types_client.py
index 5554362..c9c0582 100644
--- a/tempest/services/volume/json/admin/volume_types_client.py
+++ b/tempest/services/volume/json/admin/volume_types_client.py
@@ -122,3 +122,31 @@
         resp, body = self.put(url, put_body)
         body = json.loads(body)
         return resp, body
+
+    def get_encryption_type(self, vol_type_id):
+        """
+        Get the volume encryption type for the specified volume type.
+        vol_type_id: Id of volume_type.
+        """
+        url = "/types/%s/encryption" % str(vol_type_id)
+        resp, body = self.get(url)
+        body = json.loads(body)
+        return resp, body
+
+    def create_encryption_type(self, vol_type_id, **kwargs):
+        """
+        Create a new encryption type for the specified volume type.
+
+        vol_type_id: Id of volume_type.
+        provider: Class providing encryption support.
+        cipher: Encryption algorithm/mode to use.
+        key_size: Size of the encryption key, in bits.
+        control_location: Notional service where encryption is performed.
+        """
+        url = "/types/%s/encryption" % str(vol_type_id)
+        post_body = {}
+        post_body.update(kwargs)
+        post_body = json.dumps({'encryption': post_body})
+        resp, body = self.post(url, post_body)
+        body = json.loads(body)
+        return resp, body['encryption']
diff --git a/tempest/test.py b/tempest/test.py
index 6290761..75eb6be 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -220,13 +220,11 @@
 
 def validate_tearDownClass():
     if at_exit_set:
-        raise RuntimeError("tearDownClass does not call the super's "
-                           "tearDownClass in these classes: "
-                           + str(at_exit_set) + "\n"
-                           "If you see the exception, with another "
-                           "exception please do not report this one! "
-                           "If you are changing tempest code, make sure you "
-                           "are calling the super class's tearDownClass!")
+        LOG.error(
+            "tearDownClass does not call the super's "
+            "tearDownClass in these classes: \n"
+            + str(at_exit_set))
+
 
 atexit.register(validate_tearDownClass)
 
diff --git a/tempest/tests/common/utils/test_misc.py b/tempest/tests/common/utils/test_misc.py
new file mode 100644
index 0000000..b8c6184
--- /dev/null
+++ b/tempest/tests/common/utils/test_misc.py
@@ -0,0 +1,52 @@
+# Copyright 2014 NEC Corporation.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+
+from tempest.common.utils import misc
+from tempest.tests import base
+
+
+@misc.singleton
+class TestFoo(object):
+
+    count = 0
+
+    def increment(self):
+        self.count += 1
+        return self.count
+
+
+@misc.singleton
+class TestBar(object):
+
+    count = 0
+
+    def increment(self):
+        self.count += 1
+        return self.count
+
+
+class TestMisc(base.TestCase):
+
+    def test_singleton(self):
+        test = TestFoo()
+        self.assertEqual(0, test.count)
+        self.assertEqual(1, test.increment())
+        test2 = TestFoo()
+        self.assertEqual(1, test.count)
+        self.assertEqual(1, test2.count)
+        self.assertEqual(test, test2)
+        test3 = TestBar()
+        self.assertNotEqual(test, test3)
diff --git a/tempest/tests/fake_config.py b/tempest/tests/fake_config.py
index e941606..8a8ebb0 100644
--- a/tempest/tests/fake_config.py
+++ b/tempest/tests/fake_config.py
@@ -12,49 +12,33 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from oslo.config import cfg
 
-class FakeConfig(object):
+from tempest import config
+from tempest.openstack.common.fixture import config as conf_fixture
 
-    class fake_compute(object):
-        build_interval = 10
-        build_timeout = 10
 
-    class fake_identity(object):
-        disable_ssl_certificate_validation = True
-        catalog_type = 'identity'
-        uri = 'http://fake_uri.com/auth'
-        uri_v3 = 'http://fake_uri_v3.com/auth'
+class ConfigFixture(conf_fixture.Config):
 
-    class fake_default_feature_enabled(object):
-        api_extensions = ['all']
+    def __init__(self):
+        config.register_opts()
+        super(ConfigFixture, self).__init__()
 
-    class fake_compute_feature_enabled(fake_default_feature_enabled):
-        api_v3_extensions = ['all']
+    def setUp(self):
+        super(ConfigFixture, self).setUp()
+        self.conf.set_default('build_interval', 10, group='compute')
+        self.conf.set_default('build_timeout', 10, group='compute')
+        self.conf.set_default('disable_ssl_certificate_validation', True,
+                              group='identity')
+        self.conf.set_default('uri', 'http://fake_uri.com/auth',
+                              group='identity')
+        self.conf.set_default('uri_v3', 'http://fake_uri_v3.com/auth',
+                              group='identity')
+        self.conf.set_default('neutron', True, group='service_available')
+        self.conf.set_default('heat', True, group='service_available')
 
-    class fake_object_storage_discoverable_apis(object):
-        discoverable_apis = ['all']
 
-    class fake_service_available(object):
-        nova = True
-        glance = True
-        cinder = True
-        heat = True
-        neutron = True
-        swift = True
-        horizon = True
-
-    class fake_negative(object):
-        test_generator = 'tempest.common.' \
-            'generator.negative_generator.NegativeTestGenerator'
-
-    compute_feature_enabled = fake_compute_feature_enabled()
-    volume_feature_enabled = fake_default_feature_enabled()
-    network_feature_enabled = fake_default_feature_enabled()
-    object_storage_feature_enabled = fake_object_storage_discoverable_apis()
-
-    service_available = fake_service_available()
-
-    compute = fake_compute()
-    identity = fake_identity()
-
-    negative = fake_negative()
+class FakePrivate(config.TempestConfigPrivate):
+    def __init__(self):
+        cfg.CONF([], default_config_files=[])
+        self._set_attrs()
diff --git a/tempest/tests/negative/test_negative_auto_test.py b/tempest/tests/negative/test_negative_auto_test.py
index 27ddc95..7a1909a 100644
--- a/tempest/tests/negative/test_negative_auto_test.py
+++ b/tempest/tests/negative/test_negative_auto_test.py
@@ -15,6 +15,7 @@
 
 import mock
 
+from tempest import config
 import tempest.test as test
 from tempest.tests import base
 from tempest.tests import fake_config
@@ -38,7 +39,8 @@
 
     def setUp(self):
         super(TestNegativeAutoTest, self).setUp()
-        self.stubs.Set(test, 'CONF', fake_config.FakeConfig)
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
 
     def _check_prop_entries(self, result, entry):
         entries = [a for a in result if entry in a[0]]
diff --git a/tempest/tests/test_auth.py b/tempest/tests/test_auth.py
index df04d65..b6e15bd 100644
--- a/tempest/tests/test_auth.py
+++ b/tempest/tests/test_auth.py
@@ -42,7 +42,8 @@
 
     def setUp(self):
         super(BaseAuthTestsSetUp, self).setUp()
-        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakeConfig)
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
         self.fake_http = fake_http.fake_httplib2(return_type=200)
         self.stubs.Set(http.ClosingHttp, 'request', self.fake_http.request)
         self.auth_provider = self._auth(self.credentials)
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index aa3c8fc..ebf0ca0 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -15,6 +15,9 @@
 
 import testtools
 
+from oslo.config import cfg
+
+from tempest import config
 from tempest import exceptions
 from tempest.openstack.common.fixture import mockpatch
 from tempest import test
@@ -25,7 +28,8 @@
 class BaseDecoratorsTest(base.TestCase):
     def setUp(self):
         super(BaseDecoratorsTest, self).setUp()
-        self.stubs.Set(test, 'CONF', fake_config.FakeConfig)
+        self.config_fixture = self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
 
 
 class TestAttrDecorator(BaseDecoratorsTest):
@@ -191,10 +195,8 @@
 class TestRequiresExtDecorator(BaseDecoratorsTest):
     def setUp(self):
         super(TestRequiresExtDecorator, self).setUp()
-        self.fixture = self.useFixture(mockpatch.PatchObject(
-                                       test.CONF.compute_feature_enabled,
-                                       'api_extensions',
-                                       new=['enabled_ext', 'another_ext']))
+        cfg.CONF.set_default('api_extensions', ['enabled_ext', 'another_ext'],
+                             'compute-feature-enabled')
 
     def _test_requires_ext_helper(self, expected_to_skip=True,
                                   **decorator_args):
@@ -220,7 +222,7 @@
 
     def test_requires_ext_decorator_with_all_ext_enabled(self):
         # disable fixture so the default (all) is used.
-        self.fixture.cleanUp()
+        self.config_fixture.cleanUp()
         self._test_requires_ext_helper(expected_to_skip=False,
                                        extension='random_ext',
                                        service='compute')
diff --git a/tempest/tests/test_rest_client.py b/tempest/tests/test_rest_client.py
index 827b5c9..da9ab72 100644
--- a/tempest/tests/test_rest_client.py
+++ b/tempest/tests/test_rest_client.py
@@ -35,7 +35,8 @@
 
     def setUp(self):
         super(BaseRestClientTestClass, self).setUp()
-        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakeConfig)
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
         self.rest_client = rest_client.RestClient(
             fake_auth_provider.FakeAuthProvider())
         self.stubs.Set(httplib2.Http, 'request', self.fake_http.request)
@@ -254,7 +255,8 @@
 
     def setUp(self):
         super(TestRestClientErrorCheckerJSON, self).setUp()
-        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakeConfig)
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
         self.rest_client = rest_client.RestClient(
             fake_auth_provider.FakeAuthProvider())
 
@@ -341,3 +343,44 @@
         self.assertRaises(exceptions.InvalidContentType,
                           self.rest_client._error_checker,
                           **self.set_data("405", enc="fake_enc"))
+
+
+class TestRestClientUtils(BaseRestClientTestClass):
+
+    def _is_resource_deleted(self, resource_id):
+        if not isinstance(self.retry_pass, int):
+            return False
+        if self.retry_count >= self.retry_pass:
+            return True
+        self.retry_count = self.retry_count + 1
+        return False
+
+    def setUp(self):
+        self.fake_http = fake_http.fake_httplib2()
+        super(TestRestClientUtils, self).setUp()
+        self.retry_count = 0
+        self.retry_pass = None
+        self.original_deleted_method = self.rest_client.is_resource_deleted
+        self.rest_client.is_resource_deleted = self._is_resource_deleted
+
+    def test_wait_for_resource_deletion(self):
+        self.retry_pass = 2
+        # Ensure timeout long enough for loop execution to hit retry count
+        self.rest_client.build_timeout = 500
+        sleep_mock = self.patch('time.sleep')
+        self.rest_client.wait_for_resource_deletion('1234')
+        self.assertEqual(len(sleep_mock.mock_calls), 2)
+
+    def test_wait_for_resource_deletion_not_deleted(self):
+        self.patch('time.sleep')
+        # Set timeout to be very quick to force exception faster
+        self.rest_client.build_timeout = 1
+        self.assertRaises(exceptions.TimeoutException,
+                          self.rest_client.wait_for_resource_deletion,
+                          '1234')
+
+    def test_wait_for_deletion_with_unimplemented_deleted_method(self):
+        self.rest_client.is_resource_deleted = self.original_deleted_method
+        self.assertRaises(NotImplementedError,
+                          self.rest_client.wait_for_resource_deletion,
+                          '1234')
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
new file mode 100644
index 0000000..2e50cfd
--- /dev/null
+++ b/tempest/tests/test_tenant_isolation.py
@@ -0,0 +1,336 @@
+# 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 keystoneclient.v2_0.client as keystoneclient
+from mock import patch
+import neutronclient.v2_0.client as neutronclient
+from oslo.config import cfg
+
+from tempest.common import isolated_creds
+from tempest import config
+from tempest.openstack.common.fixture import mockpatch
+from tempest.services.identity.json import identity_client as json_iden_client
+from tempest.services.identity.xml import identity_client as xml_iden_client
+from tempest.services.network.json import network_client as json_network_client
+from tempest.services.network.xml import network_client as xml_network_client
+from tempest.tests import base
+from tempest.tests import fake_config
+
+
+class TestTenantIsolation(base.TestCase):
+
+    def setUp(self):
+        super(TestTenantIsolation, self).setUp()
+        self.useFixture(fake_config.ConfigFixture())
+        self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
+
+    def test_tempest_client(self):
+        iso_creds = isolated_creds.IsolatedCreds('test class')
+        self.assertTrue(isinstance(iso_creds.identity_admin_client,
+                                   json_iden_client.IdentityClientJSON))
+        self.assertTrue(isinstance(iso_creds.network_admin_client,
+                                   json_network_client.NetworkClientJSON))
+
+    def test_official_client(self):
+        self.useFixture(mockpatch.PatchObject(keystoneclient.Client,
+                                              'authenticate'))
+        iso_creds = isolated_creds.IsolatedCreds('test class',
+                                                 tempest_client=False)
+        self.assertTrue(isinstance(iso_creds.identity_admin_client,
+                                   keystoneclient.Client))
+        self.assertTrue(isinstance(iso_creds.network_admin_client,
+                                   neutronclient.Client))
+
+    def test_tempest_client_xml(self):
+        iso_creds = isolated_creds.IsolatedCreds('test class', interface='xml')
+        self.assertEqual(iso_creds.interface, 'xml')
+        self.assertTrue(isinstance(iso_creds.identity_admin_client,
+                                   xml_iden_client.IdentityClientXML))
+        self.assertTrue(isinstance(iso_creds.network_admin_client,
+                                   xml_network_client.NetworkClientXML))
+
+    def _mock_user_create(self, id, name):
+        user_fix = self.useFixture(mockpatch.PatchObject(
+            json_iden_client.IdentityClientJSON,
+            'create_user',
+            return_value=({'status': 200},
+                          {'id': id, 'name': name})))
+        return user_fix
+
+    def _mock_tenant_create(self, id, name):
+        tenant_fix = self.useFixture(mockpatch.PatchObject(
+            json_iden_client.IdentityClientJSON,
+            'create_tenant',
+            return_value=({'status': 200},
+                          {'id': id, 'name': name})))
+        return tenant_fix
+
+    def _mock_network_create(self, iso_creds, id, name):
+        net_fix = self.useFixture(mockpatch.PatchObject(
+            iso_creds.network_admin_client,
+            'create_network',
+            return_value=({'status': 200},
+                          {'network': {'id': id, 'name': name}})))
+        return net_fix
+
+    def _mock_subnet_create(self, iso_creds, id, name):
+        subnet_fix = self.useFixture(mockpatch.PatchObject(
+            iso_creds.network_admin_client,
+            'create_subnet',
+            return_value=({'status': 200},
+                          {'subnet': {'id': id, 'name': name}})))
+        return subnet_fix
+
+    def _mock_router_create(self, id, name):
+        router_fix = self.useFixture(mockpatch.PatchObject(
+            json_network_client.NetworkClientJSON,
+            'create_router',
+            return_value=({'status': 200},
+                          {'router': {'id': id, 'name': name}})))
+        return router_fix
+
+    @patch('tempest.common.rest_client.RestClient')
+    def test_primary_creds(self, MockRestClient):
+        cfg.CONF.set_default('neutron', False, 'service_available')
+        iso_creds = isolated_creds.IsolatedCreds('test class',
+                                                 password='fake_password')
+        self._mock_tenant_create('1234', 'fake_prim_tenant')
+        self._mock_user_create('1234', 'fake_prim_user')
+        username, tenant_name, password = iso_creds.get_primary_creds()
+        self.assertEqual(username, 'fake_prim_user')
+        self.assertEqual(tenant_name, 'fake_prim_tenant')
+        # Verify helper methods
+        tenant = iso_creds.get_primary_tenant()
+        user = iso_creds.get_primary_user()
+        self.assertEqual(tenant['id'], '1234')
+        self.assertEqual(user['id'], '1234')
+
+    @patch('tempest.common.rest_client.RestClient')
+    def test_admin_creds(self, MockRestClient):
+        cfg.CONF.set_default('neutron', False, 'service_available')
+        iso_creds = isolated_creds.IsolatedCreds('test class',
+                                                 password='fake_password')
+        self._mock_user_create('1234', 'fake_admin_user')
+        self._mock_tenant_create('1234', 'fake_admin_tenant')
+        self.useFixture(mockpatch.PatchObject(
+            json_iden_client.IdentityClientJSON,
+            'list_roles',
+            return_value=({'status': 200},
+                          [{'id': '1234', 'name': 'admin'}])))
+
+        user_mock = patch.object(json_iden_client.IdentityClientJSON,
+                                 'assign_user_role')
+        user_mock.start()
+        self.addCleanup(user_mock.stop)
+        with patch.object(json_iden_client.IdentityClientJSON,
+                          'assign_user_role') as user_mock:
+            username, tenant_name, password = iso_creds.get_admin_creds()
+        user_mock.assert_called_once_with('1234', '1234', '1234')
+        self.assertEqual(username, 'fake_admin_user')
+        self.assertEqual(tenant_name, 'fake_admin_tenant')
+        # Verify helper methods
+        tenant = iso_creds.get_admin_tenant()
+        user = iso_creds.get_admin_user()
+        self.assertEqual(tenant['id'], '1234')
+        self.assertEqual(user['id'], '1234')
+
+    @patch('tempest.common.rest_client.RestClient')
+    def test_all_cred_cleanup(self, MockRestClient):
+        cfg.CONF.set_default('neutron', False, 'service_available')
+        iso_creds = isolated_creds.IsolatedCreds('test class',
+                                                 password='fake_password')
+        tenant_fix = self._mock_tenant_create('1234', 'fake_prim_tenant')
+        user_fix = self._mock_user_create('1234', 'fake_prim_user')
+        username, tenant_name, password = iso_creds.get_primary_creds()
+        tenant_fix.cleanUp()
+        user_fix.cleanUp()
+        tenant_fix = self._mock_tenant_create('12345', 'fake_alt_tenant')
+        user_fix = self._mock_user_create('12345', 'fake_alt_user')
+        alt_username, alt_tenant, alt_password = iso_creds.get_alt_creds()
+        tenant_fix.cleanUp()
+        user_fix.cleanUp()
+        tenant_fix = self._mock_tenant_create('123456', 'fake_admin_tenant')
+        user_fix = self._mock_user_create('123456', 'fake_admin_user')
+        self.useFixture(mockpatch.PatchObject(
+            json_iden_client.IdentityClientJSON,
+            'list_roles',
+            return_value=({'status': 200},
+                          [{'id': '123456', 'name': 'admin'}])))
+        with patch.object(json_iden_client.IdentityClientJSON,
+                          'assign_user_role'):
+            admin_username, admin_tenant, admin_pass = \
+                iso_creds.get_admin_creds()
+        user_mock = self.patch(
+            'tempest.services.identity.json.identity_client.'
+            'IdentityClientJSON.delete_user')
+        tenant_mock = self.patch(
+            'tempest.services.identity.json.identity_client.'
+            'IdentityClientJSON.delete_tenant')
+        iso_creds.clear_isolated_creds()
+        # Verify user delete calls
+        calls = user_mock.mock_calls
+        self.assertEqual(len(calls), 3)
+        args = map(lambda x: x[1][0], calls)
+        self.assertIn('1234', args)
+        self.assertIn('12345', args)
+        self.assertIn('123456', args)
+        # Verify tenant delete calls
+        calls = tenant_mock.mock_calls
+        self.assertEqual(len(calls), 3)
+        args = map(lambda x: x[1][0], calls)
+        self.assertIn('1234', args)
+        self.assertIn('12345', args)
+        self.assertIn('123456', args)
+
+    @patch('tempest.common.rest_client.RestClient')
+    def test_alt_creds(self, MockRestClient):
+        cfg.CONF.set_default('neutron', False, 'service_available')
+        iso_creds = isolated_creds.IsolatedCreds('test class',
+                                                 password='fake_password')
+        self._mock_user_create('1234', 'fake_alt_user')
+        self._mock_tenant_create('1234', 'fake_alt_tenant')
+        username, tenant_name, password = iso_creds.get_alt_creds()
+        self.assertEqual(username, 'fake_alt_user')
+        self.assertEqual(tenant_name, 'fake_alt_tenant')
+        # Verify helper methods
+        tenant = iso_creds.get_alt_tenant()
+        user = iso_creds.get_alt_user()
+        self.assertEqual(tenant['id'], '1234')
+        self.assertEqual(user['id'], '1234')
+
+    @patch('tempest.common.rest_client.RestClient')
+    def test_network_creation(self, MockRestClient):
+        iso_creds = isolated_creds.IsolatedCreds('test class',
+                                                 password='fake_password')
+        self._mock_user_create('1234', 'fake_prim_user')
+        self._mock_tenant_create('1234', 'fake_prim_tenant')
+        self._mock_network_create(iso_creds, '1234', 'fake_net')
+        self._mock_subnet_create(iso_creds, '1234', 'fake_subnet')
+        self._mock_router_create('1234', 'fake_router')
+        router_interface_mock = self.patch(
+            'tempest.services.network.json.network_client.NetworkClientJSON.'
+            'add_router_interface_with_subnet_id')
+        username, tenant_name, password = iso_creds.get_primary_creds()
+        router_interface_mock.called_once_with('1234', '1234')
+        network = iso_creds.get_primary_network()
+        subnet = iso_creds.get_primary_subnet()
+        router = iso_creds.get_primary_router()
+        self.assertEqual(network['id'], '1234')
+        self.assertEqual(network['name'], 'fake_net')
+        self.assertEqual(subnet['id'], '1234')
+        self.assertEqual(subnet['name'], 'fake_subnet')
+        self.assertEqual(router['id'], '1234')
+        self.assertEqual(router['name'], 'fake_router')
+
+    @patch('tempest.common.rest_client.RestClient')
+    def test_network_cleanup(self, MockRestClient):
+        iso_creds = isolated_creds.IsolatedCreds('test class',
+                                                 password='fake_password')
+        # Create primary tenant and network
+        user_fix = self._mock_user_create('1234', 'fake_prim_user')
+        tenant_fix = self._mock_tenant_create('1234', 'fake_prim_tenant')
+        net_fix = self._mock_network_create(iso_creds, '1234', 'fake_net')
+        subnet_fix = self._mock_subnet_create(iso_creds, '1234', 'fake_subnet')
+        router_fix = self._mock_router_create('1234', 'fake_router')
+        router_interface_mock = self.patch(
+            'tempest.services.network.json.network_client.NetworkClientJSON.'
+            'add_router_interface_with_subnet_id')
+        username, tenant_name, password = iso_creds.get_primary_creds()
+        router_interface_mock.called_once_with('1234', '1234')
+        router_interface_mock.reset_mock()
+        tenant_fix.cleanUp()
+        user_fix.cleanUp()
+        net_fix.cleanUp()
+        subnet_fix.cleanUp()
+        router_fix.cleanUp()
+        # Create alternate tenant and network
+        user_fix = self._mock_user_create('12345', 'fake_alt_user')
+        tenant_fix = self._mock_tenant_create('12345', 'fake_alt_tenant')
+        net_fix = self._mock_network_create(iso_creds, '12345', 'fake_alt_net')
+        subnet_fix = self._mock_subnet_create(iso_creds, '12345',
+                                              'fake_alt_subnet')
+        router_fix = self._mock_router_create('12345', 'fake_alt_router')
+        alt_username, alt_tenant_name, password = iso_creds.get_alt_creds()
+        router_interface_mock.called_once_with('12345', '12345')
+        router_interface_mock.reset_mock()
+        tenant_fix.cleanUp()
+        user_fix.cleanUp()
+        net_fix.cleanUp()
+        subnet_fix.cleanUp()
+        router_fix.cleanUp()
+        # Create admin tenant and networks
+        user_fix = self._mock_user_create('123456', 'fake_admin_user')
+        tenant_fix = self._mock_tenant_create('123456', 'fake_admin_tenant')
+        net_fix = self._mock_network_create(iso_creds, '123456',
+                                            'fake_admin_net')
+        subnet_fix = self._mock_subnet_create(iso_creds, '123456',
+                                              'fake_admin_subnet')
+        router_fix = self._mock_router_create('123456', 'fake_admin_router')
+        self.useFixture(mockpatch.PatchObject(
+            json_iden_client.IdentityClientJSON,
+            'list_roles',
+            return_value=({'status': 200},
+                          [{'id': '123456', 'name': 'admin'}])))
+        with patch.object(json_iden_client.IdentityClientJSON,
+                          'assign_user_role'):
+            admin_user, admin_tenant, password = iso_creds.get_admin_creds()
+        self.patch('tempest.services.identity.json.identity_client.'
+                   'IdentityClientJSON.delete_user')
+        self.patch('tempest.services.identity.json.identity_client.'
+                   'IdentityClientJSON.delete_tenant')
+        net = patch.object(iso_creds.network_admin_client,
+                           'delete_network')
+        net_mock = net.start()
+        subnet = patch.object(iso_creds.network_admin_client,
+                              'delete_subnet')
+        subnet_mock = subnet.start()
+        router = patch.object(iso_creds.network_admin_client,
+                              'delete_router')
+        router_mock = router.start()
+        remove_router_interface_mock = self.patch(
+            'tempest.services.network.json.network_client.NetworkClientJSON.'
+            'remove_router_interface_with_subnet_id')
+        port_list_mock = patch.object(iso_creds.network_admin_client,
+                                      'list_ports', return_value=(
+                                      {'status': 200}, {'ports': []}))
+        port_list_mock.start()
+        iso_creds.clear_isolated_creds()
+        # Verify remove router interface calls
+        calls = remove_router_interface_mock.mock_calls
+        self.assertEqual(len(calls), 3)
+        args = map(lambda x: x[1], calls)
+        self.assertIn(('1234', '1234'), args)
+        self.assertIn(('12345', '12345'), args)
+        self.assertIn(('123456', '123456'), args)
+        # Verify network delete calls
+        calls = net_mock.mock_calls
+        self.assertEqual(len(calls), 3)
+        args = map(lambda x: x[1][0], calls)
+        self.assertIn('1234', args)
+        self.assertIn('12345', args)
+        self.assertIn('123456', args)
+        # Verify subnet delete calls
+        calls = subnet_mock.mock_calls
+        self.assertEqual(len(calls), 3)
+        args = map(lambda x: x[1][0], calls)
+        self.assertIn('1234', args)
+        self.assertIn('12345', args)
+        self.assertIn('123456', args)
+        # Verify router delete calls
+        calls = router_mock.mock_calls
+        self.assertEqual(len(calls), 3)
+        args = map(lambda x: x[1][0], calls)
+        self.assertIn('1234', args)
+        self.assertIn('12345', args)
+        self.assertIn('123456', args)
diff --git a/tools/check_logs.py b/tools/check_logs.py
index edf95a1..e28c230 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -30,9 +30,30 @@
 dump_all_errors = True
 
 # As logs are made clean, add to this set
-must_be_clean = set(['c-sch', 'g-reg', 'ceilometer-alarm-notifier',
-                     'ceilometer-collector', 'horizon', 'n-crt', 'n-obj',
-                     'q-vpn'])
+allowed_dirty = set([
+    'c-api',
+    'ceilometer-acentral',
+    'ceilometer-acompute',
+    'ceilometer-alarm-evaluator',
+    'ceilometer-anotification',
+    'ceilometer-api',
+    'c-vol',
+    'g-api',
+    'h-api',
+    'h-eng',
+    'ir-cond',
+    'n-api',
+    'n-cpu',
+    'n-net',
+    'n-sch',
+    'q-agt',
+    'q-dhcp',
+    'q-lbaas',
+    'q-meta',
+    'q-metering',
+    'q-svc',
+    'q-vpn',
+    's-proxy'])
 
 
 def process_files(file_specs, url_specs, whitelists):
@@ -69,12 +90,12 @@
                     break
             if not whitelisted or dump_all_errors:
                 if print_log_name:
-                    print("Log File: %s" % name)
+                    print("Log File Has Errors: %s" % name)
                     print_log_name = False
                 if not whitelisted:
                     had_errors = True
                     print("*** Not Whitelisted ***"),
-                print(line)
+                print(line.rstrip())
     return had_errors
 
 
@@ -135,8 +156,8 @@
         return 0
     failed = False
     for log in logs_with_errors:
-        if log in must_be_clean:
-            print("FAILED: %s" % log)
+        if log not in allowed_dirty:
+            print("Log: %s not allowed to have ERRORS or TRACES" % log)
             failed = True
     if failed:
         return 1
diff --git a/tools/verify_tempest_config.py b/tools/verify_tempest_config.py
index 4be812c..79e1fe3 100755
--- a/tools/verify_tempest_config.py
+++ b/tools/verify_tempest_config.py
@@ -63,6 +63,7 @@
         'nova_v3': os.extensions_v3_client,
         'cinder': os.volumes_extension_client,
         'neutron': os.network_client,
+        'swift': os.account_client,
     }
     if service not in extensions_client:
         print('No tempest extensions client for %s' % service)
@@ -76,6 +77,7 @@
         'nova_v3': CONF.compute_feature_enabled.api_v3_extensions,
         'cinder': CONF.volume_feature_enabled.api_extensions,
         'neutron': CONF.network_feature_enabled.api_extensions,
+        'swift': CONF.object_storage_feature_enabled.discoverable_apis,
     }
     if service not in extensions_options:
         print('No supported extensions list option for %s' % service)
@@ -93,6 +95,10 @@
         # instead of name.
         if service == 'neutron':
             extensions = map(lambda x: x['alias'], resp['extensions'])
+        elif service == 'swift':
+            # Remove Swift general information from extensions list
+            resp.pop('swift')
+            extensions = resp.keys()
         else:
             extensions = map(lambda x: x['name'], resp['extensions'])
 
@@ -142,7 +148,7 @@
     print('Running config verification...')
     os = clients.ComputeAdminManager(interface='json')
     results = {}
-    for service in ['nova', 'nova_v3', 'cinder', 'neutron']:
+    for service in ['nova', 'nova_v3', 'cinder', 'neutron', 'swift']:
         # TODO(mtreinish) make this a keystone endpoint check for available
         # services
         if not check_service_availability(service):