Merge "Object storage tests to use default auth_provider"
diff --git a/.gitignore b/.gitignore
index 0f4880f..8d2b281 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@
 dist
 build
 .testrepository
+.coverage
+cover/
diff --git a/etc/schemas/compute/admin/flavor_create.json b/etc/schemas/compute/admin/flavor_create.json
new file mode 100644
index 0000000..0a3e7b3
--- /dev/null
+++ b/etc/schemas/compute/admin/flavor_create.json
@@ -0,0 +1,20 @@
+{
+    "name": "flavor-create",
+    "http-method": "POST",
+    "admin_client": true,
+    "url": "flavors",
+    "default_result_code": 400,
+    "json-schema": {
+        "type": "object",
+        "properties": {
+            "name": { "type": "string"},
+            "ram": { "type": "integer", "minimum": 1},
+            "vcpus": { "type": "integer", "minimum": 1},
+            "disk": { "type": "integer"},
+            "id": { "type": "integer"},
+            "swap": { "type": "integer"},
+            "rxtx_factor": { "type": "integer"},
+            "OS-FLV-EXT-DATA:ephemeral": { "type": "integer"}
+        }
+    }
+}
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index eb2340a..8ab3505 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -128,6 +128,9 @@
 # AWS Access Key (string value)
 #aws_access=<None>
 
+# AWS Zone for EC2 tests (string value)
+#aws_zone=nova
+
 # S3 Materials Path (string value)
 #s3_materials_path=/opt/stack/devstack/files/images/s3-materials/cirros-0.3.0
 
@@ -307,14 +310,14 @@
 
 # Administrative Username to use for Nova API requests.
 # (string value)
-#username=admin
+#username=<None>
 
 # Administrative Tenant name to use for Nova API requests.
 # (string value)
-#tenant_name=admin
+#tenant_name=<None>
 
 # API key to use when authenticating as admin. (string value)
-#password=pass
+#password=<None>
 
 
 [compute-feature-enabled]
@@ -341,9 +344,6 @@
 # password? (boolean value)
 #change_password=false
 
-# Does the test environment support snapshots? (boolean value)
-#create_image=false
-
 # Does the test environment support resizing? (boolean value)
 #resize=false
 
@@ -451,16 +451,16 @@
 #endpoint_type=publicURL
 
 # Username to use for Nova API requests. (string value)
-#username=demo
+#username=<None>
 
 # Tenant name to use for Nova API requests. (string value)
-#tenant_name=demo
+#tenant_name=<None>
 
 # Role required to administrate keystone. (string value)
 #admin_role=admin
 
 # API key to use when authenticating. (string value)
-#password=pass
+#password=<None>
 
 # Username of alternate user to use for Nova API requests.
 # (string value)
@@ -476,14 +476,14 @@
 
 # Administrative Username to use for Keystone API requests.
 # (string value)
-#admin_username=admin
+#admin_username=<None>
 
 # Administrative Tenant name to use for Keystone API requests.
 # (string value)
-#admin_tenant_name=admin
+#admin_tenant_name=<None>
 
 # API key to use when authenticating as admin. (string value)
-#admin_password=pass
+#admin_password=<None>
 
 
 [identity-feature-enabled]
@@ -617,6 +617,14 @@
 # (string value)
 #public_router_id=
 
+# Timeout in seconds to wait for network operation to
+# complete. (integer value)
+#build_timeout=300
+
+# Time in seconds between network operation status checks.
+# (integer value)
+#build_interval=10
+
 
 [network-feature-enabled]
 
@@ -722,6 +730,16 @@
 #max_template_size=524288
 
 
+[queuing]
+
+#
+# Options defined in tempest.config
+#
+
+# Catalog type of the Queuing service. (string value)
+#catalog_type=queuing
+
+
 [scenario]
 
 #
@@ -789,9 +807,9 @@
 # value)
 #horizon=true
 
-# Whether or not Savanna is expected to be available (boolean
+# Whether or not Sahara is expected to be available (boolean
 # value)
-#savanna=false
+#sahara=false
 
 # Whether or not Ironic is expected to be available (boolean
 # value)
@@ -801,6 +819,10 @@
 # value)
 #trove=false
 
+# Whether or not Marconi is expected to be available (boolean
+# value)
+#marconi=false
+
 
 [stress]
 
diff --git a/requirements.txt b/requirements.txt
index 48d1b12..434e12e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -20,6 +20,6 @@
 testrepository>=0.0.18
 oslo.config>=1.2.0
 six>=1.5.2
-iso8601>=0.1.8
+iso8601>=0.1.9
 fixtures>=0.3.14
 testscenarios>=0.4
diff --git a/tempest/api/compute/admin/test_flavors_negative.py b/tempest/api/compute/admin/test_flavors_negative.py
index 49d49ef..b882ff4 100644
--- a/tempest/api/compute/admin/test_flavors_negative.py
+++ b/tempest/api/compute/admin/test_flavors_negative.py
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testscenarios
 import uuid
 
 from tempest.api.compute import base
@@ -20,6 +21,8 @@
 from tempest import exceptions
 from tempest import test
 
+load_tests = testscenarios.load_tests_apply_scenarios
+
 
 class FlavorsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
 
@@ -44,11 +47,6 @@
         cls.swap = 1024
         cls.rxtx = 2
 
-    def flavor_clean_up(self, flavor_id):
-        resp, body = self.client.delete_flavor(flavor_id)
-        self.assertEqual(resp.status, 202)
-        self.client.wait_for_resource_deletion(flavor_id)
-
     @test.attr(type=['negative', 'gate'])
     def test_get_flavor_details_for_deleted_flavor(self):
         # Delete a flavor and ensure it is not listed
@@ -85,13 +83,6 @@
         self.assertTrue(flag)
 
     @test.attr(type=['negative', 'gate'])
-    def test_invalid_is_public_string(self):
-        # the 'is_public' parameter can be 'none/true/false' if it exists
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.list_flavors_with_detail,
-                          {'is_public': 'invalid'})
-
-    @test.attr(type=['negative', 'gate'])
     def test_create_flavor_as_user(self):
         # only admin user can create a flavor
         flavor_name = data_utils.rand_name(self.flavor_name_prefix)
@@ -110,231 +101,16 @@
                           self.user_client.delete_flavor,
                           self.flavor_ref_alt)
 
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_using_invalid_ram(self):
-        # the 'ram' attribute must be positive integer
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = str(uuid.uuid4())
 
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          flavor_name, -1, self.vcpus,
-                          self.disk, new_flavor_id)
+class FlavorCreateNegativeTestJSON(base.BaseV2ComputeAdminTest,
+                                   test.NegativeAutoTest):
+    _interface = 'json'
+    _service = 'compute'
+    _schema_file = 'compute/admin/flavor_create.json'
+
+    scenarios = test.NegativeAutoTest.generate_scenario(_schema_file)
 
     @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_using_invalid_vcpus(self):
-        # the 'vcpu' attribute must be positive integer
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          flavor_name, self.ram, -1,
-                          self.disk, new_flavor_id)
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_name_length_less_than_1(self):
-        # ensure name length >= 1
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          '',
-                          self.ram, self.vcpus,
-                          self.disk,
-                          new_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=self.rxtx,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_name_length_exceeds_255(self):
-        # ensure name do not exceed 255 characters
-        new_flavor_name = 'a' * 256
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          new_flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          new_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=self.rxtx,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_invalid_name(self):
-        # the regex of flavor_name is '^[\w\.\- ]*$'
-        invalid_flavor_name = data_utils.rand_name('invalid-!@#$%-')
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          invalid_flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          new_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=self.rxtx,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_invalid_flavor_id(self):
-        # the regex of flavor_id is '^[\w\.\- ]*$', and it cannot contain
-        # leading and/or trailing whitespace
-        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        invalid_flavor_id = '!@#$%'
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          new_flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          invalid_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=self.rxtx,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_id_length_exceeds_255(self):
-        # the length of flavor_id should not exceed 255 characters
-        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        invalid_flavor_id = 'a' * 256
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          new_flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          invalid_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=self.rxtx,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_invalid_root_gb(self):
-        # root_gb attribute should be non-negative ( >= 0) integer
-        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          new_flavor_name,
-                          self.ram, self.vcpus,
-                          -1,
-                          new_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=self.rxtx,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_invalid_ephemeral_gb(self):
-        # ephemeral_gb attribute should be non-negative ( >= 0) integer
-        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          new_flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          new_flavor_id,
-                          ephemeral=-1,
-                          swap=self.swap,
-                          rxtx=self.rxtx,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_invalid_swap(self):
-        # swap attribute should be non-negative ( >= 0) integer
-        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          new_flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          new_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=-1,
-                          rxtx=self.rxtx,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_invalid_rxtx_factor(self):
-        # rxtx_factor attribute should be a positive float
-        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          new_flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          new_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=-1.5,
-                          is_public='False')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_with_invalid_is_public(self):
-        # is_public attribute should be boolean
-        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.BadRequest,
-                          self.client.create_flavor,
-                          new_flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          new_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=self.rxtx,
-                          is_public='Invalid')
-
-    @test.attr(type=['negative', 'gate'])
-    def test_create_flavor_already_exists(self):
-        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
-        new_flavor_id = str(uuid.uuid4())
-
-        resp, flavor = self.client.create_flavor(flavor_name,
-                                                 self.ram, self.vcpus,
-                                                 self.disk,
-                                                 new_flavor_id,
-                                                 ephemeral=self.ephemeral,
-                                                 swap=self.swap,
-                                                 rxtx=self.rxtx)
-        self.assertEqual(200, resp.status)
-        self.addCleanup(self.flavor_clean_up, flavor['id'])
-
-        self.assertRaises(exceptions.Conflict,
-                          self.client.create_flavor,
-                          flavor_name,
-                          self.ram, self.vcpus,
-                          self.disk,
-                          new_flavor_id,
-                          ephemeral=self.ephemeral,
-                          swap=self.swap,
-                          rxtx=self.rxtx)
-
-    @test.attr(type=['negative', 'gate'])
-    def test_delete_nonexistent_flavor(self):
-        nonexistent_flavor_id = str(uuid.uuid4())
-
-        self.assertRaises(exceptions.NotFound,
-                          self.client.delete_flavor,
-                          nonexistent_flavor_id)
-
-
-class FlavorsAdminNegativeTestXML(FlavorsAdminNegativeTestJSON):
-    _interface = 'xml'
+    def test_create_flavor(self):
+        # flavor details are not returned for non-existent flavors
+        self.execute(self._schema_file)
diff --git a/tempest/api/compute/admin/test_flavors_negative_xml.py b/tempest/api/compute/admin/test_flavors_negative_xml.py
new file mode 100644
index 0000000..a06b0e6
--- /dev/null
+++ b/tempest/api/compute/admin/test_flavors_negative_xml.py
@@ -0,0 +1,268 @@
+# Copyright 2012 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import uuid
+
+from tempest.api.compute.admin import test_flavors_negative
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class FlavorsAdminNegativeTestXML(test_flavors_negative.
+                                  FlavorsAdminNegativeTestJSON):
+
+    """
+    Tests Flavors API Create and Delete that require admin privileges
+    """
+
+    _interface = 'xml'
+
+    def flavor_clean_up(self, flavor_id):
+        resp, body = self.client.delete_flavor(flavor_id)
+        self.assertEqual(resp.status, 202)
+        self.client.wait_for_resource_deletion(flavor_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_invalid_is_public_string(self):
+        # the 'is_public' parameter can be 'none/true/false' if it exists
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.list_flavors_with_detail,
+                          {'is_public': 'invalid'})
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_using_invalid_ram(self):
+        # the 'ram' attribute must be positive integer
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          flavor_name, -1, self.vcpus,
+                          self.disk, new_flavor_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_using_invalid_vcpus(self):
+        # the 'vcpu' attribute must be positive integer
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          flavor_name, self.ram, -1,
+                          self.disk, new_flavor_id)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_name_length_less_than_1(self):
+        # ensure name length >= 1
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          '',
+                          self.ram, self.vcpus,
+                          self.disk,
+                          new_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=self.rxtx,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_name_length_exceeds_255(self):
+        # ensure name do not exceed 255 characters
+        new_flavor_name = 'a' * 256
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          new_flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          new_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=self.rxtx,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_invalid_name(self):
+        # the regex of flavor_name is '^[\w\.\- ]*$'
+        invalid_flavor_name = data_utils.rand_name('invalid-!@#$%-')
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          invalid_flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          new_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=self.rxtx,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_invalid_flavor_id(self):
+        # the regex of flavor_id is '^[\w\.\- ]*$', and it cannot contain
+        # leading and/or trailing whitespace
+        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        invalid_flavor_id = '!@#$%'
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          new_flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          invalid_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=self.rxtx,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_id_length_exceeds_255(self):
+        # the length of flavor_id should not exceed 255 characters
+        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        invalid_flavor_id = 'a' * 256
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          new_flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          invalid_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=self.rxtx,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_invalid_root_gb(self):
+        # root_gb attribute should be non-negative ( >= 0) integer
+        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          new_flavor_name,
+                          self.ram, self.vcpus,
+                          -1,
+                          new_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=self.rxtx,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_invalid_ephemeral_gb(self):
+        # ephemeral_gb attribute should be non-negative ( >= 0) integer
+        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          new_flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          new_flavor_id,
+                          ephemeral=-1,
+                          swap=self.swap,
+                          rxtx=self.rxtx,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_invalid_swap(self):
+        # swap attribute should be non-negative ( >= 0) integer
+        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          new_flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          new_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=-1,
+                          rxtx=self.rxtx,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_invalid_rxtx_factor(self):
+        # rxtx_factor attribute should be a positive float
+        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          new_flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          new_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=-1.5,
+                          is_public='False')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_with_invalid_is_public(self):
+        # is_public attribute should be boolean
+        new_flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.BadRequest,
+                          self.client.create_flavor,
+                          new_flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          new_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=self.rxtx,
+                          is_public='Invalid')
+
+    @test.attr(type=['negative', 'gate'])
+    def test_create_flavor_already_exists(self):
+        flavor_name = data_utils.rand_name(self.flavor_name_prefix)
+        new_flavor_id = str(uuid.uuid4())
+
+        resp, flavor = self.client.create_flavor(flavor_name,
+                                                 self.ram, self.vcpus,
+                                                 self.disk,
+                                                 new_flavor_id,
+                                                 ephemeral=self.ephemeral,
+                                                 swap=self.swap,
+                                                 rxtx=self.rxtx)
+        self.assertEqual(200, resp.status)
+        self.addCleanup(self.flavor_clean_up, flavor['id'])
+
+        self.assertRaises(exceptions.Conflict,
+                          self.client.create_flavor,
+                          flavor_name,
+                          self.ram, self.vcpus,
+                          self.disk,
+                          new_flavor_id,
+                          ephemeral=self.ephemeral,
+                          swap=self.swap,
+                          rxtx=self.rxtx)
+
+    @test.attr(type=['negative', 'gate'])
+    def test_delete_nonexistent_flavor(self):
+        nonexistent_flavor_id = str(uuid.uuid4())
+
+        self.assertRaises(exceptions.NotFound,
+                          self.client.delete_flavor,
+                          nonexistent_flavor_id)
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py
index 32c8656..055a177 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py
@@ -14,10 +14,10 @@
 #    under the License.
 
 import datetime
+import urllib
 
 from tempest.api.compute import base
 from tempest import test
-import urllib
 
 
 class InstanceUsageAuditLogTestJSON(base.BaseV2ComputeAdminTest):
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
index fe4a184..6a5fc96 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
@@ -14,11 +14,11 @@
 #    under the License.
 
 import datetime
+import urllib
 
 from tempest.api.compute import base
 from tempest import exceptions
 from tempest import test
-import urllib
 
 
 class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest):
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 5af091e..09c7274 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -92,6 +92,29 @@
         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('ram_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)
+        ram_default = quota_set_default['ram']
+
+        resp, body = self.adm_client.update_quota_set(tenant_id, ram='5120')
+        self.assertEqual(200, resp.status)
+
+        resp, body = self.adm_client.delete_quota_set(tenant_id)
+        self.assertEqual(202, 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'])
+
 
 class QuotasAdminTestXML(QuotasAdminTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/admin/test_services.py b/tempest/api/compute/admin/test_services.py
index ca79e6b..2feb825 100644
--- a/tempest/api/compute/admin/test_services.py
+++ b/tempest/api/compute/admin/test_services.py
@@ -52,6 +52,7 @@
         services_on_host = [service for service in services if
                             service['host'] == host_name]
         params = {'host': host_name}
+
         resp, services = self.client.list_services(params)
 
         # we could have a periodic job checkin between the 2 service
@@ -69,6 +70,7 @@
         host_name = services[0]['host']
         binary_name = services[0]['binary']
         params = {'host': host_name, 'binary': binary_name}
+
         resp, services = self.client.list_services(params)
         self.assertEqual(200, resp.status)
         self.assertEqual(1, len(services))
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage.py b/tempest/api/compute/admin/test_simple_tenant_usage.py
index cc8641f..33cd6f3 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage.py
@@ -14,10 +14,10 @@
 #    under the License.
 
 import datetime
+import time
 
 from tempest.api.compute import base
 from tempest import test
-import time
 
 
 class TenantUsagesTestJSON(base.BaseV2ComputeAdminTest):
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 398297d..abd36a6 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -411,3 +411,4 @@
         cls.aggregates_admin_client = cls.os_adm.aggregates_v3_client
         cls.hosts_admin_client = cls.os_adm.hosts_v3_client
         cls.quotas_admin_client = cls.os_adm.quotas_v3_client
+        cls.agents_admin_client = cls.os_adm.agents_v3_client
diff --git a/tempest/api/compute/certificates/test_certificates.py b/tempest/api/compute/certificates/test_certificates.py
index 01fdc7c..5299d13 100644
--- a/tempest/api/compute/certificates/test_certificates.py
+++ b/tempest/api/compute/certificates/test_certificates.py
@@ -14,12 +14,12 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.test import attr
+from tempest import test
 
 
 class CertificatesTestJSON(base.BaseV2ComputeTest):
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_and_get_root_certificate(self):
         # create certificates
         resp, create_body = self.certificates_client.create_certificate()
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index 98a8e29..6e202f6 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.test import attr
+from tempest import test
 
 
 class FlavorsTestJSON(base.BaseV2ComputeTest):
@@ -24,7 +24,7 @@
         super(FlavorsTestJSON, cls).setUpClass()
         cls.client = cls.flavors_client
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_list_flavors(self):
         # List of all flavors should contain the expected flavor
         resp, flavors = self.client.list_flavors()
@@ -33,34 +33,34 @@
                              'name': flavor['name']}
         self.assertIn(flavor_min_detail, flavors)
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_list_flavors_with_detail(self):
         # Detailed list of all flavors should contain the expected flavor
         resp, flavors = self.client.list_flavors_with_detail()
         resp, flavor = self.client.get_flavor_details(self.flavor_ref)
         self.assertIn(flavor, flavors)
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_get_flavor(self):
         # The expected flavor details should be returned
         resp, flavor = self.client.get_flavor_details(self.flavor_ref)
         self.assertEqual(self.flavor_ref, flavor['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_flavors_limit_results(self):
         # Only the expected number of flavors should be returned
         params = {'limit': 1}
         resp, flavors = self.client.list_flavors(params)
         self.assertEqual(1, len(flavors))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_flavors_detailed_limit_results(self):
         # Only the expected number of flavors (detailed) should be returned
         params = {'limit': 1}
         resp, flavors = self.client.list_flavors_with_detail(params)
         self.assertEqual(1, len(flavors))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_flavors_using_marker(self):
         # The list of flavors should start from the provided marker
         resp, flavors = self.client.list_flavors()
@@ -71,7 +71,7 @@
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]),
                          'The list of flavors did not start after the marker.')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_flavors_detailed_using_marker(self):
         # The list of flavors should start from the provided marker
         resp, flavors = self.client.list_flavors_with_detail()
@@ -82,7 +82,7 @@
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]),
                          'The list of flavors did not start after the marker.')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_flavors_detailed_filter_by_min_disk(self):
         # The detailed list of flavors should be filtered by disk space
         resp, flavors = self.client.list_flavors_with_detail()
@@ -93,7 +93,7 @@
         resp, flavors = self.client.list_flavors_with_detail(params)
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_flavors_detailed_filter_by_min_ram(self):
         # The detailed list of flavors should be filtered by RAM
         resp, flavors = self.client.list_flavors_with_detail()
@@ -104,7 +104,7 @@
         resp, flavors = self.client.list_flavors_with_detail(params)
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_flavors_filter_by_min_disk(self):
         # The list of flavors should be filtered by disk space
         resp, flavors = self.client.list_flavors_with_detail()
@@ -115,7 +115,7 @@
         resp, flavors = self.client.list_flavors(params)
         self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_flavors_filter_by_min_ram(self):
         # The list of flavors should be filtered by RAM
         resp, flavors = self.client.list_flavors_with_detail()
diff --git a/tempest/api/compute/flavors/test_flavors_negative_xml.py b/tempest/api/compute/flavors/test_flavors_negative_xml.py
index c93c7c9..bf73c0e 100644
--- a/tempest/api/compute/flavors/test_flavors_negative_xml.py
+++ b/tempest/api/compute/flavors/test_flavors_negative_xml.py
@@ -17,7 +17,7 @@
 
 from tempest.api.compute import base
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class FlavorsNegativeTestXML(base.BaseV2ComputeTest):
@@ -28,19 +28,19 @@
         super(FlavorsNegativeTestXML, cls).setUpClass()
         cls.client = cls.flavors_client
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_invalid_minRam_filter(self):
         self.assertRaises(exceptions.BadRequest,
                           self.client.list_flavors_with_detail,
                           {'minRam': 'invalid'})
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_invalid_minDisk_filter(self):
         self.assertRaises(exceptions.BadRequest,
                           self.client.list_flavors_with_detail,
                           {'minDisk': 'invalid'})
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_non_existent_flavor_id(self):
         # flavor details are not returned for non-existent flavors
         nonexistent_flavor_id = str(uuid.uuid4())
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index c0f7af0..abd8a4c 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -24,10 +24,11 @@
     floating_ip = None
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(FloatingIPsTestJSON, cls).setUpClass()
         cls.client = cls.floating_ips_client
-        #cls.servers_client = cls.servers_client
+        cls.floating_ip_id = None
 
         # Server creation
         resp, server = cls.create_test_server(wait_until='ACTIVE')
@@ -40,7 +41,8 @@
     @classmethod
     def tearDownClass(cls):
         # Deleting the floating IP which is created in this method
-        resp, body = cls.client.delete_floating_ip(cls.floating_ip_id)
+        if cls.floating_ip_id:
+            resp, body = cls.client.delete_floating_ip(cls.floating_ip_id)
         super(FloatingIPsTestJSON, cls).tearDownClass()
 
     @test.attr(type='gate')
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index 0c3663e..9fc43e2 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -19,7 +19,7 @@
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -47,7 +47,7 @@
             if cls.non_exist_id not in cls.floating_ip_ids:
                 break
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_allocate_floating_ip_from_nonexistent_pool(self):
         # Negative test:Allocation of a new floating IP from a nonexistent_pool
         # to a project should fail
@@ -55,7 +55,7 @@
                           self.client.create_floating_ip,
                           "non_exist_pool")
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_delete_nonexistent_floating_ip(self):
         # Negative test:Deletion of a nonexistent floating IP
         # from project should fail
@@ -64,7 +64,7 @@
         self.assertRaises(exceptions.NotFound, self.client.delete_floating_ip,
                           self.non_exist_id)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_associate_nonexistent_floating_ip(self):
         # Negative test:Association of a non existent floating IP
         # to specific server should fail
@@ -73,7 +73,7 @@
                           self.client.associate_floating_ip_to_server,
                           "0.0.0.0", self.server_id)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_dissociate_nonexistent_floating_ip(self):
         # Negative test:Dissociation of a non existent floating IP should fail
         # Dissociating non existent floating IP
@@ -81,7 +81,7 @@
                           self.client.disassociate_floating_ip_from_server,
                           "0.0.0.0", self.server_id)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_associate_ip_to_server_without_passing_floating_ip(self):
         # Negative test:Association of empty floating IP to specific server
         # should raise NotFound exception
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index d69e33c..94dcf61 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.test import attr
+from tempest import test
 
 
 class FloatingIPDetailsTestJSON(base.BaseV2ComputeTest):
@@ -36,7 +36,7 @@
             cls.client.delete_floating_ip(cls.floating_ip_id[i])
         super(FloatingIPDetailsTestJSON, cls).tearDownClass()
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_floating_ips(self):
         # Positive test:Should return the list of floating IPs
         resp, body = self.client.list_floating_ips()
@@ -47,7 +47,7 @@
         for i in range(3):
             self.assertIn(self.floating_ip[i], floating_ips)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_floating_ip_details(self):
         # Positive test:Should be able to GET the details of floatingIP
         # Creating a floating IP for which details are to be checked
@@ -69,7 +69,7 @@
                          body['fixed_ip'])
         self.assertEqual(floating_ip_id, body['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_floating_ip_pools(self):
         # Positive test:Should return the list of floating IP Pools
         resp, floating_ip_pools = self.client.list_floating_ip_pools()
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index 5701be8..8cb2f08 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -19,7 +19,7 @@
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -31,7 +31,7 @@
         super(FloatingIPDetailsNegativeTestJSON, cls).setUpClass()
         cls.client = cls.floating_ips_client
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_get_nonexistent_floating_ip_details(self):
         # Negative test:Should not be able to GET the details
         # of non-existent floating IP
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index ad211ce..91eb4c5 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -16,7 +16,7 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import config
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -24,14 +24,15 @@
 class ImagesMetadataTestJSON(base.BaseV2ComputeTest):
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(ImagesMetadataTestJSON, cls).setUpClass()
         if not CONF.service_available.glance:
             skip_msg = ("%s skipped as glance is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
 
-        cls.servers_client = cls.servers_client
         cls.client = cls.images_client
+        cls.image_id = None
 
         resp, server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
@@ -45,7 +46,8 @@
 
     @classmethod
     def tearDownClass(cls):
-        cls.client.delete_image(cls.image_id)
+        if cls.image_id:
+            cls.client.delete_image(cls.image_id)
         super(ImagesMetadataTestJSON, cls).tearDownClass()
 
     def setUp(self):
@@ -54,14 +56,14 @@
         resp, _ = self.client.set_image_metadata(self.image_id, meta)
         self.assertEqual(resp.status, 200)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_image_metadata(self):
         # All metadata key/value pairs for an image should be returned
         resp, resp_metadata = self.client.list_image_metadata(self.image_id)
         expected = {'key1': 'value1', 'key2': 'value2'}
         self.assertEqual(expected, resp_metadata)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_set_image_metadata(self):
         # The metadata for the image should match the new values
         req_metadata = {'meta2': 'value2', 'meta3': 'value3'}
@@ -71,7 +73,7 @@
         resp, resp_metadata = self.client.list_image_metadata(self.image_id)
         self.assertEqual(req_metadata, resp_metadata)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_image_metadata(self):
         # The metadata for the image should match the updated values
         req_metadata = {'key1': 'alt1', 'key3': 'value3'}
@@ -82,14 +84,14 @@
         expected = {'key1': 'alt1', 'key2': 'value2', 'key3': 'value3'}
         self.assertEqual(expected, resp_metadata)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_image_metadata_item(self):
         # The value for a specific metadata key should be returned
         resp, meta = self.client.get_image_metadata_item(self.image_id,
                                                          'key2')
         self.assertEqual('value2', meta['key2'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_set_image_metadata_item(self):
         # The value provided for the given meta item should be set for
         # the image
@@ -100,7 +102,7 @@
         expected = {'key1': 'alt', 'key2': 'value2'}
         self.assertEqual(expected, resp_metadata)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_image_metadata_item(self):
         # The metadata value/key pair should be deleted from the image
         resp, body = self.client.delete_image_metadata_item(self.image_id,
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 7776c57..15bb66a 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -16,7 +16,7 @@
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class ImagesMetadataTestJSON(base.BaseV2ComputeTest):
@@ -26,14 +26,14 @@
         super(ImagesMetadataTestJSON, cls).setUpClass()
         cls.client = cls.images_client
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_list_nonexistent_image_metadata(self):
         # Negative test: List on nonexistent image
         # metadata should not happen
         self.assertRaises(exceptions.NotFound, self.client.list_image_metadata,
                           data_utils.rand_uuid())
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_update_nonexistent_image_metadata(self):
         # Negative test:An update should not happen for a non-existent image
         meta = {'key1': 'alt1', 'key2': 'alt2'}
@@ -41,21 +41,21 @@
                           self.client.update_image_metadata,
                           data_utils.rand_uuid(), meta)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_get_nonexistent_image_metadata_item(self):
         # Negative test: Get on non-existent image should not happen
         self.assertRaises(exceptions.NotFound,
                           self.client.get_image_metadata_item,
                           data_utils.rand_uuid(), 'key2')
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_set_nonexistent_image_metadata(self):
         # Negative test: Metadata should not be set to a non-existent image
         meta = {'key1': 'alt1', 'key2': 'alt2'}
         self.assertRaises(exceptions.NotFound, self.client.set_image_metadata,
                           data_utils.rand_uuid(), meta)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_set_nonexistent_image_metadata_item(self):
         # Negative test: Metadata item should not be set to a
         # nonexistent image
@@ -65,7 +65,7 @@
                           data_utils.rand_uuid(), 'key1',
                           meta)
 
-    @attr(type=['negative', 'gate'])
+    @test.attr(type=['negative', 'gate'])
     def test_delete_nonexistent_image_metadata_item(self):
         # Negative test: Shouldn't be able to delete metadata
         # item from non-existent image
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index b152c3c..d2fd970 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
@@ -61,8 +60,6 @@
         resp, flavor = self.flavors_client.get_flavor_details(flavor_id)
         return flavor['disk']
 
-    @testtools.skipUnless(CONF.compute_feature_enabled.create_image,
-                          'Environment unable to create images.')
     @test.attr(type='smoke')
     def test_create_delete_image(self):
 
diff --git a/tempest/api/compute/images/test_list_images.py b/tempest/api/compute/images/test_list_images.py
index 4074a7a..eba331f 100644
--- a/tempest/api/compute/images/test_list_images.py
+++ b/tempest/api/compute/images/test_list_images.py
@@ -15,7 +15,7 @@
 
 from tempest.api.compute import base
 from tempest import config
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -30,20 +30,20 @@
             raise cls.skipException(skip_msg)
         cls.client = cls.images_client
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_get_image(self):
         # Returns the correct details for a single image
         resp, image = self.client.get_image(self.image_ref)
         self.assertEqual(self.image_ref, image['id'])
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_list_images(self):
         # The list of all images should contain the image
         resp, images = self.client.list_images()
         found = any([i for i in images if i['id'] == self.image_ref])
         self.assertTrue(found)
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_list_images_with_detail(self):
         # Detailed list of all images should contain the expected images
         resp, images = self.client.list_images_with_detail()
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index a21c411..f6eed00 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -16,7 +16,7 @@
 from tempest.api.compute import base
 from tempest import config
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 import time
 
@@ -106,7 +106,7 @@
 
         self.assertEqual(sorted(list1), sorted(list2))
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_create_list_show_delete_interfaces(self):
         server, ifs = self._create_server_get_interfaces()
         interface_count = len(ifs)
@@ -127,7 +127,7 @@
         _ifs = self._test_delete_interface(server, ifs)
         self.assertEqual(len(ifs) - 1, len(_ifs))
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_add_remove_fixed_ip(self):
         # Add and Remove the fixed IP to server.
         server, ifs = self._create_server_get_interfaces()
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index ddf37ce..778294e 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -186,8 +186,7 @@
 
         admin_pass = self.image_ssh_password
 
-        resp, server_no_eph_disk = (self.
-                                    create_test_server(
+        resp, server_no_eph_disk = (self.create_test_server(
                                     wait_until='ACTIVE',
                                     adminPass=admin_pass,
                                     flavor=flavor_no_eph_disk_id))
diff --git a/tempest/api/compute/servers/test_disk_config.py b/tempest/api/compute/servers/test_disk_config.py
index 75a1234..332358c 100644
--- a/tempest/api/compute/servers/test_disk_config.py
+++ b/tempest/api/compute/servers/test_disk_config.py
@@ -17,7 +17,7 @@
 
 from tempest.api.compute import base
 from tempest import config
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -44,7 +44,7 @@
             resp, server = self.client.get_server(server['id'])
             self.assertEqual(disk_config, server['OS-DCF:diskConfig'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_rebuild_server_with_manual_disk_config(self):
         # A server should be rebuilt using the manual disk config option
         self._update_server_with_disk_config(disk_config='AUTO')
@@ -60,7 +60,7 @@
         resp, server = self.client.get_server(server['id'])
         self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_rebuild_server_with_auto_disk_config(self):
         # A server should be rebuilt using the auto disk config option
         self._update_server_with_disk_config(disk_config='MANUAL')
@@ -86,7 +86,7 @@
 
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_resize_server_from_manual_to_auto(self):
         # A server should be resized from manual to auto disk config
         self._update_server_with_disk_config(disk_config='MANUAL')
@@ -103,7 +103,7 @@
 
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_resize_server_from_auto_to_manual(self):
         # A server should be resized from auto to manual disk config
         self._update_server_with_disk_config(disk_config='AUTO')
@@ -118,7 +118,7 @@
         resp, server = self.client.get_server(self.server_id)
         self.assertEqual('MANUAL', server['OS-DCF:diskConfig'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_server_from_auto_to_manual(self):
         # A server should be updated from auto to manual disk config
         self._update_server_with_disk_config(disk_config='AUTO')
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 837114c..f0913f1 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -26,6 +26,7 @@
 class ListServerFiltersTestJSON(base.BaseV2ComputeTest):
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(ListServerFiltersTestJSON, cls).setUpClass()
         cls.client = cls.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 26c5887..c825fb9 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -19,7 +19,7 @@
 
 from tempest.api.compute import base
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
@@ -51,7 +51,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 +63,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 +72,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 +81,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 +90,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,7 +99,7 @@
         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})
@@ -107,26 +107,26 @@
         # when _interface='xml', one element for servers_links in servers
         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()}
@@ -139,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'}
@@ -153,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/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index bde0f57..21465d8 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -17,6 +17,7 @@
 import time
 
 import testtools
+import urlparse
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
@@ -382,6 +383,11 @@
             self.client.wait_for_server_status(self.server_id,
                                                'SHELVED')
 
+            resp, server = self.client.shelve_offload_server(self.server_id)
+            self.assertEqual(202, resp.status)
+            self.client.wait_for_server_status(self.server_id,
+                                               'SHELVED_OFFLOADED')
+
         resp, server = self.client.get_server(self.server_id)
         image_name = server['name'] + '-shelved'
         params = {'name': image_name}
@@ -422,6 +428,29 @@
         self.assertEqual(202, resp.status)
         self.servers_client.wait_for_server_status(self.server_id, 'ACTIVE')
 
+    def _validate_url(self, url):
+        valid_scheme = ['http', 'https']
+        parsed_url = urlparse.urlparse(url)
+        self.assertNotEqual('None', parsed_url.port)
+        self.assertNotEqual('None', parsed_url.hostname)
+        self.assertIn(parsed_url.scheme, valid_scheme)
+
+    @testtools.skipUnless(CONF.compute_feature_enabled.vnc_console,
+                          'VNC Console feature is disabled.')
+    @test.attr(type='gate')
+    def test_get_vnc_console(self):
+        # Get the VNC console of type 'novnc' and 'xvpvnc'
+        console_types = ['novnc', 'xvpvnc']
+        for console_type in console_types:
+            resp, body = self.servers_client.get_vnc_console(self.server_id,
+                                                             console_type)
+            self.assertEqual(
+                200, resp.status,
+                "Failed to get Console Type: %s" % (console_types))
+            self.assertEqual(console_type, body['type'])
+            self.assertNotEqual('', body['url'])
+            self._validate_url(body['url'])
+
 
 class ServerActionsTestXML(ServerActionsTestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/servers/test_server_password.py b/tempest/api/compute/servers/test_server_password.py
index ad78f65..50c881a 100644
--- a/tempest/api/compute/servers/test_server_password.py
+++ b/tempest/api/compute/servers/test_server_password.py
@@ -15,7 +15,7 @@
 
 
 from tempest.api.compute import base
-from tempest.test import attr
+from tempest import test
 
 
 class ServerPasswordTestJSON(base.BaseV2ComputeTest):
@@ -26,12 +26,12 @@
         cls.client = cls.servers_client
         resp, cls.server = cls.create_test_server(wait_until="ACTIVE")
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_server_password(self):
         resp, body = self.client.get_password(self.server['id'])
         self.assertEqual(200, resp.status)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_server_password(self):
         resp, body = self.client.delete_password(self.server['id'])
         self.assertEqual(204, resp.status)
diff --git a/tempest/api/compute/servers/test_server_personality.py b/tempest/api/compute/servers/test_server_personality.py
index b581faf..b7e4e38 100644
--- a/tempest/api/compute/servers/test_server_personality.py
+++ b/tempest/api/compute/servers/test_server_personality.py
@@ -17,7 +17,7 @@
 
 from tempest.api.compute import base
 from tempest import exceptions
-from tempest.test import attr
+from tempest import test
 
 
 class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
@@ -28,7 +28,7 @@
         cls.client = cls.servers_client
         cls.user_client = cls.limits_client
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_personality_files_exceed_limit(self):
         # Server creation should fail if greater than the maximum allowed
         # number of files are injected into the server.
@@ -43,7 +43,7 @@
         self.assertRaises(exceptions.OverLimit, self.create_test_server,
                           personality=personality)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_can_create_server_with_max_number_personality_files(self):
         # Server should be created successfully if maximum allowed number of
         # files is injected into the server during creation.
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index 277f28f..e027567 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -45,6 +45,11 @@
             cls.rescue_id, adminPass=rescue_password)
         cls.servers_client.wait_for_server_status(cls.rescue_id, 'RESCUE')
 
+    @classmethod
+    def tearDownClass(cls):
+        cls.delete_volume(cls.volume['id'])
+        super(ServerRescueNegativeTestJSON, cls).tearDownClass()
+
     def _detach(self, server_id, volume_id):
         self.servers_client.detach_volume(server_id, volume_id)
         self.volumes_extensions_client.wait_for_volume_status(volume_id,
diff --git a/tempest/api/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index 9674463..40b97d7 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -15,7 +15,7 @@
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
 
 
 class ServersTestJSON(base.BaseV2ComputeTest):
@@ -29,7 +29,7 @@
         self.clear_servers()
         super(ServersTestJSON, self).tearDown()
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_server_with_admin_password(self):
         # If an admin password is provided on server creation, the server's
         # root password should be set to that password.
@@ -38,7 +38,7 @@
         # Verify the password is set correctly in the response
         self.assertEqual('testpassword', server['adminPass'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_with_existing_server_name(self):
         # Creating a server with a name that already exists is allowed
 
@@ -57,7 +57,7 @@
         name2 = server['name']
         self.assertEqual(name1, name2)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_specify_keypair(self):
         # Specify a keypair while creating a server
 
@@ -70,7 +70,7 @@
         resp, server = self.client.get_server(server['id'])
         self.assertEqual(key_name, server['key_name'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_server_name(self):
         # The server name should be changed to the the provided value
         resp, server = self.create_test_server(wait_until='ACTIVE')
@@ -85,7 +85,7 @@
         resp, server = self.client.get_server(server['id'])
         self.assertEqual('newname', server['name'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_access_server_address(self):
         # The server's access addresses should reflect the provided values
         resp, server = self.create_test_server(wait_until='ACTIVE')
@@ -102,7 +102,7 @@
         self.assertEqual('1.1.1.1', server['accessIPv4'])
         self.assertEqual('::babe:202:202', server['accessIPv6'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_server_with_ipv6_addr_only(self):
         # Create a server without an IPv4 address(only IPv6 address).
         resp, server = self.create_test_server(accessIPv6='2001:2001::3')
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index fd73cc5..7f909d7 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -19,7 +19,7 @@
 from tempest import config
 from tempest import exceptions
 from tempest.openstack.common import log as logging
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -89,31 +89,31 @@
             cls.security_client.delete_security_group(cls.security_group['id'])
         super(AuthorizationTestJSON, cls).tearDownClass()
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_server_for_alt_account_fails(self):
         # A GET request for a server on another user's account should fail
         self.assertRaises(exceptions.NotFound, self.alt_client.get_server,
                           self.server['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_server_for_alt_account_fails(self):
         # A DELETE request for another user's server should fail
         self.assertRaises(exceptions.NotFound, self.alt_client.delete_server,
                           self.server['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_update_server_for_alt_account_fails(self):
         # An update server request for another user's server should fail
         self.assertRaises(exceptions.NotFound, self.alt_client.update_server,
                           self.server['id'], name='test')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_server_addresses_for_alt_account_fails(self):
         # A list addresses request for another user's server should fail
         self.assertRaises(exceptions.NotFound, self.alt_client.list_addresses,
                           self.server['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_server_addresses_by_network_for_alt_account_fails(self):
         # A list address/network request for another user's server should fail
         server_id = self.server['id']
@@ -121,7 +121,7 @@
                           self.alt_client.list_addresses_by_network, server_id,
                           'public')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_list_servers_with_alternate_tenant(self):
         # A list on servers from one tenant should not
         # show on alternate tenant
@@ -131,44 +131,44 @@
         alt_server_ids = [s['id'] for s in body['servers']]
         self.assertNotIn(self.server['id'], alt_server_ids)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_change_password_for_alt_account_fails(self):
         # A change password request for another user's server should fail
         self.assertRaises(exceptions.NotFound, self.alt_client.change_password,
                           self.server['id'], 'newpass')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_reboot_server_for_alt_account_fails(self):
         # A reboot request for another user's server should fail
         self.assertRaises(exceptions.NotFound, self.alt_client.reboot,
                           self.server['id'], 'HARD')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_rebuild_server_for_alt_account_fails(self):
         # A rebuild request for another user's server should fail
         self.assertRaises(exceptions.NotFound, self.alt_client.rebuild,
                           self.server['id'], self.image_ref_alt)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_resize_server_for_alt_account_fails(self):
         # A resize request for another user's server should fail
         self.assertRaises(exceptions.NotFound, self.alt_client.resize,
                           self.server['id'], self.flavor_ref_alt)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_image_for_alt_account_fails(self):
         # A create image request for another user's server should fail
         self.assertRaises(exceptions.NotFound,
                           self.alt_images_client.create_image,
                           self.server['id'], 'testImage')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_server_with_unauthorized_image(self):
         # Server creation with another user's image should fail
         self.assertRaises(exceptions.BadRequest, self.alt_client.create_server,
                           'test', self.image['id'], self.flavor_ref)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_server_fails_when_tenant_incorrect(self):
         # A create server request should fail if the tenant id does not match
         # the current user
@@ -181,7 +181,7 @@
                           self.alt_client.create_server, 'test',
                           self.image['id'], self.flavor_ref)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_keypair_in_analt_user_tenant(self):
         # A create keypair request should fail if the tenant id does not match
         # the current user
@@ -204,34 +204,34 @@
                 LOG.error("Create keypair request should not happen "
                           "if the tenant id does not match the current user")
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_keypair_of_alt_account_fails(self):
         # A GET request for another user's keypair should fail
         self.assertRaises(exceptions.NotFound,
                           self.alt_keypairs_client.get_keypair,
                           self.keypairname)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_keypair_of_alt_account_fails(self):
         # A DELETE request for another user's keypair should fail
         self.assertRaises(exceptions.NotFound,
                           self.alt_keypairs_client.delete_keypair,
                           self.keypairname)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_image_for_alt_account_fails(self):
         # A GET request for an image on another user's account should fail
         self.assertRaises(exceptions.NotFound,
                           self.alt_images_client.get_image, self.image['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_image_for_alt_account_fails(self):
         # A DELETE request for another user's image should fail
         self.assertRaises(exceptions.NotFound,
                           self.alt_images_client.delete_image,
                           self.image['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_security_group_in_analt_user_tenant(self):
         # A create security group request should fail if the tenant id does not
         # match the current user
@@ -256,21 +256,21 @@
                 LOG.error("Create Security Group request should not happen if"
                           "the tenant id does not match the current user")
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_security_group_of_alt_account_fails(self):
         # A GET request for another user's security group should fail
         self.assertRaises(exceptions.NotFound,
                           self.alt_security_client.get_security_group,
                           self.security_group['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_security_group_of_alt_account_fails(self):
         # A DELETE request for another user's security group should fail
         self.assertRaises(exceptions.NotFound,
                           self.alt_security_client.delete_security_group,
                           self.security_group['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_create_security_group_rule_in_analt_user_tenant(self):
         # A create security group rule request should fail if the tenant id
         # does not match the current user
@@ -300,7 +300,7 @@
                           "happen if the tenant id does not match the"
                           " current user")
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_security_group_rule_of_alt_account_fails(self):
         # A DELETE request for another user's security group rule
         # should fail
@@ -308,7 +308,7 @@
                           self.alt_security_client.delete_security_group_rule,
                           self.rule['id'])
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_set_metadata_of_alt_account_server_fails(self):
         # A set metadata for another user's server should fail
         req_metadata = {'meta1': 'data1', 'meta2': 'data2'}
@@ -317,7 +317,7 @@
                           self.server['id'],
                           req_metadata)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_set_metadata_of_alt_account_image_fails(self):
         # A set metadata for another user's image should fail
         req_metadata = {'meta1': 'value1', 'meta2': 'value2'}
@@ -325,7 +325,7 @@
                           self.alt_images_client.set_image_metadata,
                           self.image['id'], req_metadata)
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_metadata_of_alt_account_server_fails(self):
         # A get metadata for another user's server should fail
         req_metadata = {'meta1': 'data1'}
@@ -336,7 +336,7 @@
                           self.alt_client.get_server_metadata_item,
                           self.server['id'], 'meta1')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_metadata_of_alt_account_image_fails(self):
         # A get metadata for another user's image should fail
         req_metadata = {'meta1': 'value1'}
@@ -348,7 +348,7 @@
                           self.alt_images_client.get_image_metadata_item,
                           self.image['id'], 'meta1')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_metadata_of_alt_account_server_fails(self):
         # A delete metadata for another user's server should fail
         req_metadata = {'meta1': 'data1'}
@@ -359,7 +359,7 @@
                           self.alt_client.delete_server_metadata_item,
                           self.server['id'], 'meta1')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_delete_metadata_of_alt_account_image_fails(self):
         # A delete metadata for another user's image should fail
         req_metadata = {'meta1': 'data1'}
@@ -371,7 +371,7 @@
                           self.alt_images_client.delete_image_metadata_item,
                           self.image['id'], 'meta1')
 
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_get_console_output_of_alt_account_server_fails(self):
         # A Get Console Output for another user's server should fail
         self.assertRaises(exceptions.NotFound,
diff --git a/tempest/api/compute/test_live_block_migration.py b/tempest/api/compute/test_live_block_migration.py
index 1319f68..93ff4b0 100644
--- a/tempest/api/compute/test_live_block_migration.py
+++ b/tempest/api/compute/test_live_block_migration.py
@@ -18,7 +18,7 @@
 
 from tempest.api.compute import base
 from tempest import config
-from tempest.test import attr
+from tempest import test
 
 CONF = config.CONF
 
@@ -85,7 +85,7 @@
 
     @testtools.skipIf(not CONF.compute_feature_enabled.live_migration,
                       'Live migration not available')
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_live_block_migration(self):
         # Live block migrate an instance to another host
         if len(self._get_compute_hostnames()) < 2:
@@ -105,7 +105,7 @@
     @testtools.skipIf(not CONF.compute_feature_enabled.
                       block_migrate_cinder_iscsi,
                       'Block Live migration not configured for iSCSI')
-    @attr(type='gate')
+    @test.attr(type='gate')
     def test_iscsi_volume(self):
         # Live block migrate an instance to another host
         if len(self._get_compute_hostnames()) < 2:
diff --git a/tempest/api/compute/test_quotas.py b/tempest/api/compute/test_quotas.py
index b97ab2c..230d433 100644
--- a/tempest/api/compute/test_quotas.py
+++ b/tempest/api/compute/test_quotas.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.test import attr
+from tempest import test
 
 
 class QuotasTestJSON(base.BaseV2ComputeTest):
@@ -35,7 +35,7 @@
                                      'instances', 'security_group_rules',
                                      'cores', 'security_groups'))
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_get_quotas(self):
         # User can get the quota set for it's tenant
         expected_quota_set = self.default_quota_set | set(['id'])
@@ -45,7 +45,7 @@
                          sorted(quota_set.keys()))
         self.assertEqual(quota_set['id'], self.tenant_id)
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_get_default_quotas(self):
         # User can get the default quota set for it's tenant
         expected_quota_set = self.default_quota_set | set(['id'])
@@ -55,7 +55,7 @@
                          sorted(quota_set.keys()))
         self.assertEqual(quota_set['id'], self.tenant_id)
 
-    @attr(type='smoke')
+    @test.attr(type='smoke')
     def test_compare_tenant_quotas_with_default_quotas(self):
         # Tenants are created with the default quota values
         resp, defualt_quota_set = \
diff --git a/tempest/api/compute/v3/admin/test_agents.py b/tempest/api/compute/v3/admin/test_agents.py
new file mode 100644
index 0000000..9d01b71
--- /dev/null
+++ b/tempest/api/compute/v3/admin/test_agents.py
@@ -0,0 +1,91 @@
+# 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.api.compute import base
+from tempest import test
+
+
+class AgentsAdminV3Test(base.BaseV3ComputeAdminTest):
+
+    """
+    Tests Agents API that require admin privileges
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        super(AgentsAdminV3Test, cls).setUpClass()
+        cls.client = cls.agents_admin_client
+
+    @test.attr(type='gate')
+    def test_create_update_list_delete_agents(self):
+
+        """
+        1. Create 2 agents.
+        2. Update one of the agents.
+        3. List all agent builds.
+        4. List the agent builds by the filter.
+        5. Delete agents.
+        """
+        params_kvm = expected_kvm = {'hypervisor': 'kvm',
+                                     'os': 'win',
+                                     'architecture': 'x86',
+                                     'version': '7.0',
+                                     'url': 'xxx://xxxx/xxx/xxx',
+                                     'md5hash': ("""add6bb58e139be103324d04d"""
+                                                 """82d8f545""")}
+
+        resp, agent_kvm = self.client.create_agent(**params_kvm)
+        self.assertEqual(201, resp.status)
+        for expected_item, value in expected_kvm.items():
+            self.assertEqual(value, agent_kvm[expected_item])
+
+        params_xen = expected_xen = {'hypervisor': 'xen',
+                                     'os': 'linux',
+                                     'architecture': 'x86',
+                                     'version': '7.0',
+                                     'url': 'xxx://xxxx/xxx/xxx1',
+                                     'md5hash': """add6bb58e139be103324d04d8"""
+                                                """2d8f546"""}
+
+        resp, agent_xen = self.client.create_agent(**params_xen)
+        self.assertEqual(201, resp.status)
+
+        for expected_item, value in expected_xen.items():
+            self.assertEqual(value, agent_xen[expected_item])
+
+        params_kvm_new = expected_kvm_new = {'version': '8.0',
+                                             'url': 'xxx://xxxx/xxx/xxx2',
+                                             'md5hash': """add6bb58e139be103"""
+                                                        """324d04d82d8f547"""}
+
+        resp, resp_agent_kvm = self.client.update_agent(agent_kvm['agent_id'],
+                                                        **params_kvm_new)
+        self.assertEqual(200, resp.status)
+        for expected_item, value in expected_kvm_new.items():
+            self.assertEqual(value, resp_agent_kvm[expected_item])
+
+        resp, agents = self.client.list_agents()
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(agents) > 1)
+
+        params_filter = {'hypervisor': 'kvm'}
+        resp, agent = self.client.list_agents(params_filter)
+        self.assertEqual(200, resp.status)
+        self.assertTrue(len(agent) > 0)
+        self.assertEqual('kvm', agent[0]['hypervisor'])
+
+        resp, _ = self.client.delete_agent(agent_kvm['agent_id'])
+        self.assertEqual(204, resp.status)
+        resp, _ = self.client.delete_agent(agent_xen['agent_id'])
+        self.assertEqual(204, resp.status)
diff --git a/tempest/api/compute/v3/admin/test_quotas.py b/tempest/api/compute/v3/admin/test_quotas.py
index 0c138bb..917c115 100644
--- a/tempest/api/compute/v3/admin/test_quotas.py
+++ b/tempest/api/compute/v3/admin/test_quotas.py
@@ -56,7 +56,7 @@
     def test_get_quota_set_detail(self):
         # Admin can get the detail of resource quota set for a tenant
         expected_quota_set = self.default_quota_set | set(['id'])
-        expected_detail = {'reserved', 'limit', 'in_use'}
+        expected_detail = ['reserved', 'limit', 'in_use']
         resp, quota_set = self.adm_client.get_quota_set_detail(
             self.demo_tenant_id)
         self.assertEqual(200, resp.status)
@@ -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_services.py b/tempest/api/compute/v3/admin/test_services.py
index 914a2a4..b367dad 100644
--- a/tempest/api/compute/v3/admin/test_services.py
+++ b/tempest/api/compute/v3/admin/test_services.py
@@ -48,10 +48,12 @@
     @attr(type='gate')
     def test_get_service_by_host_name(self):
         resp, services = self.client.list_services()
+        self.assertEqual(200, resp.status)
         host_name = services[0]['host']
         services_on_host = [service for service in services if
                             service['host'] == host_name]
         params = {'host': host_name}
+
         resp, services = self.client.list_services(params)
 
         # we could have a periodic job checkin between the 2 service
@@ -69,6 +71,7 @@
         host_name = services[0]['host']
         binary_name = services[0]['binary']
         params = {'host': host_name, 'binary': binary_name}
+
         resp, services = self.client.list_services(params)
         self.assertEqual(200, resp.status)
         self.assertEqual(1, len(services))
diff --git a/tempest/api/compute/v3/images/test_images_negative.py b/tempest/api/compute/v3/images/test_images_negative.py
index c38373f..0705bdc 100644
--- a/tempest/api/compute/v3/images/test_images_negative.py
+++ b/tempest/api/compute/v3/images/test_images_negative.py
@@ -35,7 +35,7 @@
         resp, body = self.servers_client.create_image(server_id, name, meta)
         image_id = data_utils.parse_image_id(resp['location'])
         self.addCleanup(self.client.delete_image, image_id)
-        self.client.wait_for_image_status(image_id, 'ACTIVE')
+        self.client.wait_for_image_status(image_id, 'active')
         return resp, body
 
     @test.attr(type=['negative', 'gate'])
diff --git a/tempest/api/compute/v3/images/test_images_oneserver.py b/tempest/api/compute/v3/images/test_images_oneserver.py
index 48a885e..3aab1e1 100644
--- a/tempest/api/compute/v3/images/test_images_oneserver.py
+++ b/tempest/api/compute/v3/images/test_images_oneserver.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import testtools
 
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
@@ -61,8 +60,6 @@
         resp, flavor = self.flavors_client.get_flavor_details(flavor_id)
         return flavor['disk']
 
-    @testtools.skipUnless(CONF.compute_feature_enabled.create_image,
-                          'Environment unable to create images.')
     @test.attr(type='smoke')
     def test_create_delete_image(self):
 
@@ -73,26 +70,26 @@
                                                       name, meta)
         self.assertEqual(202, resp.status)
         image_id = data_utils.parse_image_id(resp['location'])
-        self.client.wait_for_image_status(image_id, 'ACTIVE')
+        self.client.wait_for_image_status(image_id, 'active')
 
         # Verify the image was created correctly
-        resp, image = self.client.get_image(image_id)
+        resp, image = self.client.get_image_meta(image_id)
         self.assertEqual(name, image['name'])
-        self.assertEqual('test', image['metadata']['image_type'])
+        self.assertEqual('test', image['properties']['image_type'])
 
-        resp, original_image = self.client.get_image(self.image_ref)
+        resp, original_image = self.client.get_image_meta(self.image_ref)
 
         # Verify minRAM is the same as the original image
-        self.assertEqual(image['minRam'], original_image['minRam'])
+        self.assertEqual(image['min_ram'], original_image['min_ram'])
 
         # Verify minDisk is the same as the original image or the flavor size
         flavor_disk_size = self._get_default_flavor_disk_size(self.flavor_ref)
-        self.assertIn(str(image['minDisk']),
-                      (str(original_image['minDisk']), str(flavor_disk_size)))
+        self.assertIn(str(image['min_disk']),
+                      (str(original_image['min_disk']), str(flavor_disk_size)))
 
         # Verify the image was deleted correctly
         resp, body = self.client.delete_image(image_id)
-        self.assertEqual('204', resp['status'])
+        self.assertEqual('200', resp['status'])
         self.client.wait_for_resource_deletion(image_id)
 
     @test.attr(type=['gate'])
diff --git a/tempest/api/compute/v3/servers/test_create_server.py b/tempest/api/compute/v3/servers/test_create_server.py
index a212ca5..7e9aaf2 100644
--- a/tempest/api/compute/v3/servers/test_create_server.py
+++ b/tempest/api/compute/v3/servers/test_create_server.py
@@ -195,8 +195,7 @@
 
         admin_pass = self.image_ssh_password
 
-        resp, server_no_eph_disk = (self.
-                                    create_test_server(
+        resp, server_no_eph_disk = (self.create_test_server(
                                     wait_until='ACTIVE',
                                     adminPass=admin_pass,
                                     flavor=flavor_no_eph_disk_id))
diff --git a/tempest/api/compute/v3/servers/test_list_server_filters.py b/tempest/api/compute/v3/servers/test_list_server_filters.py
index ec31e8e..2cb176c 100644
--- a/tempest/api/compute/v3/servers/test_list_server_filters.py
+++ b/tempest/api/compute/v3/servers/test_list_server_filters.py
@@ -26,6 +26,7 @@
 class ListServerFiltersV3Test(base.BaseV3ComputeTest):
 
     @classmethod
+    @test.safe_setup
     def setUpClass(cls):
         super(ListServerFiltersV3Test, cls).setUpClass()
         cls.client = cls.servers_client
diff --git a/tempest/api/compute/v3/servers/test_server_actions.py b/tempest/api/compute/v3/servers/test_server_actions.py
index 406c45a..555d028 100644
--- a/tempest/api/compute/v3/servers/test_server_actions.py
+++ b/tempest/api/compute/v3/servers/test_server_actions.py
@@ -372,6 +372,11 @@
             self.client.wait_for_server_status(self.server_id,
                                                'SHELVED')
 
+            resp, server = self.client.shelve_offload_server(self.server_id)
+            self.assertEqual(202, resp.status)
+            self.client.wait_for_server_status(self.server_id,
+                                               'SHELVED_OFFLOADED')
+
         resp, server = self.client.get_server(self.server_id)
         image_name = server['name'] + '-shelved'
         resp, images = self.images_client.image_list(name=image_name)
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index 5b272ef..73ad22b 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -27,8 +27,8 @@
     def setUpClass(cls):
         super(BaseDataProcessingTest, cls).setUpClass()
         os = cls.get_client_manager()
-        if not CONF.service_available.savanna:
-            raise cls.skipException("Savanna support is required")
+        if not CONF.service_available.sahara:
+            raise cls.skipException("Sahara support is required")
         cls.client = os.data_processing_client
 
         # set some constants
diff --git a/tempest/api/data_processing/test_node_group_templates.py b/tempest/api/data_processing/test_node_group_templates.py
index ff4fa6a..a64c345 100644
--- a/tempest/api/data_processing/test_node_group_templates.py
+++ b/tempest/api/data_processing/test_node_group_templates.py
@@ -28,7 +28,7 @@
 
         if template_name is None:
             # generate random name if it's not specified
-            template_name = data_utils.rand_name('savanna')
+            template_name = data_utils.rand_name('sahara')
 
         # create simple node group template
         resp, body, template_id = self.create_node_group_template(
diff --git a/tempest/api/identity/admin/test_tokens.py b/tempest/api/identity/admin/test_tokens.py
index 239433b..533f374 100644
--- a/tempest/api/identity/admin/test_tokens.py
+++ b/tempest/api/identity/admin/test_tokens.py
@@ -22,7 +22,7 @@
     _interface = 'json'
 
     @attr(type='gate')
-    def test_create_delete_token(self):
+    def test_create_get_delete_token(self):
         # get a token by username and password
         user_name = data_utils.rand_name(name='user-')
         user_password = data_utils.rand_name(name='pass-')
@@ -43,8 +43,16 @@
         self.assertEqual(rsp['status'], '200')
         self.assertEqual(body['token']['tenant']['name'],
                          tenant['name'])
-        # then delete the token
+        # Perform GET Token
         token_id = body['token']['id']
+        resp, token_details = self.client.get_token(token_id)
+        self.assertEqual(resp['status'], '200')
+        self.assertEqual(token_id, token_details['token']['id'])
+        self.assertEqual(user['id'], token_details['user']['id'])
+        self.assertEqual(user_name, token_details['user']['name'])
+        self.assertEqual(tenant['name'],
+                         token_details['token']['tenant']['name'])
+        # then delete the token
         resp, body = self.client.delete_token(token_id)
         self.assertEqual(resp['status'], '204')
 
diff --git a/tempest/api/identity/admin/test_users_negative.py b/tempest/api/identity/admin/test_users_negative.py
index 1188325..4e8ebe5 100644
--- a/tempest/api/identity/admin/test_users_negative.py
+++ b/tempest/api/identity/admin/test_users_negative.py
@@ -13,11 +13,12 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import uuid
+
 from tempest.api.identity import base
 from tempest.common.utils import data_utils
 from tempest import exceptions
 from tempest.test import attr
-import uuid
 
 
 class UsersNegativeTestJSON(base.BaseIdentityV2AdminTest):
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/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index ce11911..abde8f7 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -101,6 +101,7 @@
                                               disk_format='iso',
                                               visibility='public')
         self.assertEqual(201, resp.status)
+        self.addCleanup(self.client.delete_image, body['id'])
         self.assertEqual('queued', body['status'])
         image_id = body['id']
 
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index eb397ba..f4050c5 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -76,11 +76,8 @@
         resp, body = self.admin_client.remove_router_from_l3_agent(
             self.agent['id'], router['router']['id'])
         self.assertEqual('204', resp['status'])
-        resp, body = self.admin_client.list_l3_agents_hosting_router(
-            router['router']['id'])
-        for agent in body['agents']:
-            l3_agent_ids.append(agent['id'])
-        self.assertNotIn(self.agent['id'], l3_agent_ids)
+        # NOTE(afazekas): The deletion not asserted, because neutron
+        # is not forbidden to reschedule the router to the same agent
 
 
 class L3AgentSchedulerTestXML(L3AgentSchedulerTestJSON):
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 93335e7..231c4bf 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -242,14 +242,20 @@
     @classmethod
     def create_member(cls, protocol_port, pool):
         """Wrapper utility that returns a test member."""
-        resp, body = cls.client.create_member("10.0.9.46",
-                                              protocol_port,
-                                              pool['id'])
+        resp, body = cls.client.create_member(address="10.0.9.46",
+                                              protocol_port=protocol_port,
+                                              pool_id=pool['id'])
         member = body['member']
         cls.members.append(member)
         return member
 
     @classmethod
+    def update_member(cls, admin_state_up):
+        resp, body = cls.client.update_member(admin_state_up=admin_state_up)
+        member = body['member']
+        return member
+
+    @classmethod
     def create_health_monitor(cls, delay, max_retries, Type, timeout):
         """Wrapper utility that returns a test health monitor."""
         resp, body = cls.client.create_health_monitor(delay=delay,
diff --git a/tempest/api/network/test_load_balancer.py b/tempest/api/network/test_load_balancer.py
index 03e095d..695dbf8 100644
--- a/tempest/api/network/test_load_balancer.py
+++ b/tempest/api/network/test_load_balancer.py
@@ -61,19 +61,50 @@
                                                        Type="TCP",
                                                        timeout=1)
 
+    def _check_list_with_filter(self, obj_name, attr_exceptions, **kwargs):
+        create_obj = getattr(self.client, 'create_' + obj_name)
+        delete_obj = getattr(self.client, 'delete_' + obj_name)
+        list_objs = getattr(self.client, 'list_' + obj_name + 's')
+
+        resp, body = create_obj(**kwargs)
+        self.assertEqual('201', resp['status'])
+        obj = body[obj_name]
+        self.addCleanup(delete_obj, obj['id'])
+        for key, value in obj.iteritems():
+            # It is not relevant to filter by all arguments. That is why
+            # there is a list of attr to except
+            if key not in attr_exceptions:
+                resp, body = list_objs(**{key: value})
+                self.assertEqual('200', resp['status'])
+                objs = [v[key] for v in body[obj_name + 's']]
+                self.assertIn(value, objs)
+
     @test.attr(type='smoke')
     def test_list_vips(self):
         # Verify the vIP exists in the list of all vIPs
         resp, body = self.client.list_vips()
         self.assertEqual('200', resp['status'])
         vips = body['vips']
-        found = None
-        for n in vips:
-            if (n['id'] == self.vip['id']):
-                found = n['id']
-        msg = "vIPs list doesn't contain created vip"
-        self.assertIsNotNone(found, msg)
+        self.assertIn(self.vip['id'], [v['id'] for v in vips])
 
+    @test.attr(type='smoke')
+    def test_list_vips_with_filter(self):
+        name = data_utils.rand_name('vip-')
+        resp, body = self.client.create_pool(
+            name=data_utils.rand_name("pool-"), lb_method="ROUND_ROBIN",
+            protocol="HTTPS", subnet_id=self.subnet['id'])
+        self.assertEqual('201', resp['status'])
+        pool = body['pool']
+        self.addCleanup(self.client.delete_pool, pool['id'])
+        attr_exceptions = ['status', 'session_persistence',
+                           'status_description']
+        self._check_list_with_filter(
+            'vip', attr_exceptions, name=name, protocol="HTTPS",
+            protocol_port=81, subnet_id=self.subnet['id'], pool_id=pool['id'],
+            description=data_utils.rand_name('description-'),
+            admin_state_up=False)
+
+    @test.attr(type='smoke')
     def test_create_update_delete_pool_vip(self):
         # Creates a vip
         name = data_utils.rand_name('vip-')
@@ -100,6 +131,7 @@
         # Verification of vip delete
         resp, body = self.client.delete_vip(vip['id'])
         self.assertEqual('204', resp['status'])
+        self.client.wait_for_resource_deletion('vip', vip['id'])
         # Verification of pool update
         new_name = "New_pool"
         resp, body = self.client.update_pool(pool['id'],
@@ -117,17 +149,30 @@
         resp, body = self.client.show_vip(self.vip['id'])
         self.assertEqual('200', resp['status'])
         vip = body['vip']
-        self.assertEqual(self.vip['id'], vip['id'])
-        self.assertEqual(self.vip['name'], vip['name'])
+        for key, value in vip.iteritems():
+            # 'status' should not be confirmed in api tests
+            if key != 'status':
+                self.assertEqual(self.vip[key], value)
 
     @test.attr(type='smoke')
     def test_show_pool(self):
-        # Verifies the details of a pool
-        resp, body = self.client.show_pool(self.pool['id'])
-        self.assertEqual('200', resp['status'])
+        # Here we need to new pool without any dependence with vips
+        resp, body = self.client.create_pool(
+            name=data_utils.rand_name("pool-"),
+            lb_method='ROUND_ROBIN',
+            protocol='HTTP',
+            subnet_id=self.subnet['id'])
+        self.assertEqual('201', resp['status'])
         pool = body['pool']
-        self.assertEqual(self.pool['id'], pool['id'])
-        self.assertEqual(self.pool['name'], pool['name'])
+        self.addCleanup(self.client.delete_pool, pool['id'])
+        # Verifies the details of a pool
+        resp, body = self.client.show_pool(pool['id'])
+        self.assertEqual('200', resp['status'])
+        shown_pool = body['pool']
+        for key, value in pool.iteritems():
+            # 'status' should not be confirmed in api tests
+            if key != 'status':
+                self.assertEqual(value, shown_pool[key])
 
     @test.attr(type='smoke')
     def test_list_pools(self):
@@ -138,6 +183,17 @@
         self.assertIn(self.pool['id'], [p['id'] for p in pools])
 
     @test.attr(type='smoke')
+    def test_list_pools_with_filters(self):
+        attr_exceptions = ['status', 'vip_id', 'members', 'provider',
+                           'status_description']
+        self._check_list_with_filter(
+            'pool', attr_exceptions, name=data_utils.rand_name("pool-"),
+            lb_method="ROUND_ROBIN", protocol="HTTPS",
+            subnet_id=self.subnet['id'],
+            description=data_utils.rand_name('description-'),
+            admin_state_up=False)
+
+    @test.attr(type='smoke')
     def test_list_members(self):
         # Verify the member exists in the list of all members
         resp, body = self.client.list_members()
@@ -146,14 +202,23 @@
         self.assertIn(self.member['id'], [m['id'] for m in members])
 
     @test.attr(type='smoke')
+    def test_list_members_with_filters(self):
+        attr_exceptions = ['status', 'status_description']
+        self._check_list_with_filter('member', attr_exceptions,
+                                     address="10.0.9.47", protocol_port=80,
+                                     pool_id=self.pool['id'])
+
+    @test.attr(type='smoke')
     def test_create_update_delete_member(self):
         # Creates a member
-        resp, body = self.client.create_member("10.0.9.47", 80,
-                                               self.pool['id'])
+        resp, body = self.client.create_member(address="10.0.9.47",
+                                               protocol_port=80,
+                                               pool_id=self.pool['id'])
         self.assertEqual('201', resp['status'])
         member = body['member']
         # Verification of member update
-        resp, body = self.client.update_member(False, member['id'])
+        resp, body = self.client.update_member(member['id'],
+                                               admin_state_up=False)
         self.assertEqual('200', resp['status'])
         updated_member = body['member']
         self.assertFalse(updated_member['admin_state_up'])
@@ -167,9 +232,10 @@
         resp, body = self.client.show_member(self.member['id'])
         self.assertEqual('200', resp['status'])
         member = body['member']
-        self.assertEqual(self.member['id'], member['id'])
-        self.assertEqual(self.member['admin_state_up'],
-                         member['admin_state_up'])
+        for key, value in member.iteritems():
+             # 'status' should not be confirmed in api tests
+            if key != 'status':
+                self.assertEqual(self.member[key], value)
 
     @test.attr(type='smoke')
     def test_list_health_monitors(self):
@@ -181,6 +247,13 @@
                       [h['id'] for h in health_monitors])
 
     @test.attr(type='smoke')
+    def test_list_health_monitors_with_filters(self):
+        attr_exceptions = ['status', 'status_description', 'pools']
+        self._check_list_with_filter('health_monitor', attr_exceptions,
+                                     delay=5, max_retries=4, type="TCP",
+                                     timeout=2)
+
+    @test.attr(type='smoke')
     def test_create_update_delete_health_monitor(self):
         # Creates a health_monitor
         resp, body = self.client.create_health_monitor(delay=4,
@@ -206,9 +279,10 @@
         resp, body = self.client.show_health_monitor(self.health_monitor['id'])
         self.assertEqual('200', resp['status'])
         health_monitor = body['health_monitor']
-        self.assertEqual(self.health_monitor['id'], health_monitor['id'])
-        self.assertEqual(self.health_monitor['admin_state_up'],
-                         health_monitor['admin_state_up'])
+        for key, value in health_monitor.iteritems():
+             # 'status' should not be confirmed in api tests
+            if key != 'status':
+                self.assertEqual(self.health_monitor[key], value)
 
     @test.attr(type='smoke')
     def test_associate_disassociate_health_monitor_with_pool(self):
@@ -216,10 +290,26 @@
         resp, body = (self.client.associate_health_monitor_with_pool
                      (self.health_monitor['id'], self.pool['id']))
         self.assertEqual('201', resp['status'])
+        resp, body = self.client.show_health_monitor(
+            self.health_monitor['id'])
+        health_monitor = body['health_monitor']
+        resp, body = self.client.show_pool(self.pool['id'])
+        pool = body['pool']
+        self.assertIn(pool['id'],
+                      [p['pool_id'] for p in health_monitor['pools']])
+        self.assertIn(health_monitor['id'], pool['health_monitors'])
         # Verify that a health monitor can be disassociated from a pool
         resp, body = (self.client.disassociate_health_monitor_with_pool
                      (self.health_monitor['id'], self.pool['id']))
         self.assertEqual('204', resp['status'])
+        resp, body = self.client.show_pool(self.pool['id'])
+        pool = body['pool']
+        resp, body = self.client.show_health_monitor(
+            self.health_monitor['id'])
+        health_monitor = body['health_monitor']
+        self.assertNotIn(health_monitor['id'], pool['health_monitors'])
+        self.assertNotIn(pool['id'],
+                         [p['pool_id'] for p in health_monitor['pools']])
 
     @test.attr(type='smoke')
     def test_get_lb_pool_stats(self):
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 1155257..70fb00a 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -67,17 +67,16 @@
         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):
-        # Creates a network
+        # Create a network
         name = data_utils.rand_name('network-')
         resp, body = self.client.create_network(name=name)
         self.assertEqual('201', resp['status'])
         network = body['network']
         net_id = network['id']
-        # Verification of network update
+        # Verify network update
         new_name = "New_network"
         resp, body = self.client.update_network(net_id, name=new_name)
         self.assertEqual('200', resp['status'])
@@ -86,13 +85,12 @@
         # Find a cidr that is not in use yet and create a subnet with it
         subnet = self.create_subnet(network)
         subnet_id = subnet['id']
-        # Verification of subnet update
-        new_subnet = "New_subnet"
-        resp, body = self.client.update_subnet(subnet_id,
-                                               name=new_subnet)
+        # Verify subnet update
+        new_name = "New_subnet"
+        resp, body = self.client.update_subnet(subnet_id, name=new_name)
         self.assertEqual('200', resp['status'])
         updated_subnet = body['subnet']
-        self.assertEqual(updated_subnet['name'], new_subnet)
+        self.assertEqual(updated_subnet['name'], new_name)
         # Delete subnet and network
         resp, body = self.client.delete_subnet(subnet_id)
         self.assertEqual('204', resp['status'])
@@ -103,191 +101,87 @@
 
     @attr(type='smoke')
     def test_show_network(self):
-        # Verifies the details of a network
+        # Verify the details of a network
         resp, body = self.client.show_network(self.network['id'])
         self.assertEqual('200', resp['status'])
         network = body['network']
-        self.assertEqual(self.network['id'], network['id'])
-        self.assertEqual(self.name, network['name'])
+        for key in ['id', 'name']:
+            self.assertEqual(network[key], self.network[key])
 
     @attr(type='smoke')
     def test_show_network_fields(self):
-        # Verifies showing some fields of a network works
+        # Verify specific fields of a network
         field_list = [('fields', 'id'), ('fields', 'name'), ]
         resp, body = self.client.show_network(self.network['id'],
                                               field_list=field_list)
         self.assertEqual('200', resp['status'])
         network = body['network']
-        self.assertEqual(len(network), 2)
-        self.assertEqual(self.network['id'], network['id'])
-        self.assertEqual(self.name, network['name'])
+        self.assertEqual(len(network), len(field_list))
+        for label, field_name in field_list:
+            self.assertEqual(network[field_name], self.network[field_name])
 
     @attr(type='smoke')
     def test_list_networks(self):
         # Verify the network exists in the list of all networks
         resp, body = self.client.list_networks()
         self.assertEqual('200', resp['status'])
-        networks = body['networks']
-        found = None
-        for n in networks:
-            if (n['id'] == self.network['id']):
-                found = n['id']
-        msg = "Network list doesn't contain created network"
-        self.assertIsNotNone(found, msg)
+        networks = [network['id'] for network in body['networks']
+                    if network['id'] == self.network['id']]
+        self.assertNotEmpty(networks, "Created network not found in the list")
 
     @attr(type='smoke')
     def test_list_networks_fields(self):
-        # Verify listing some fields of the networks
+        # Verify specific fields of the networks
         resp, body = self.client.list_networks(fields='id')
         self.assertEqual('200', resp['status'])
         networks = body['networks']
-        found = None
-        for n in networks:
-            self.assertEqual(len(n), 1)
-            self.assertIn('id', n)
-            if (n['id'] == self.network['id']):
-                found = n['id']
-        self.assertIsNotNone(found,
-                             "Created network id not found in the list")
+        self.assertNotEmpty(networks, "Network list returned is empty")
+        for network in networks:
+            self.assertEqual(len(network), 1)
+            self.assertIn('id', network)
 
     @attr(type='smoke')
     def test_show_subnet(self):
-        # Verifies the details of a subnet
+        # Verify the details of a subnet
         resp, body = self.client.show_subnet(self.subnet['id'])
         self.assertEqual('200', resp['status'])
         subnet = body['subnet']
-        self.assertEqual(self.subnet['id'], subnet['id'])
-        self.assertEqual(self.cidr, subnet['cidr'])
+        self.assertNotEmpty(subnet, "Subnet returned has no fields")
+        for key in ['id', 'cidr']:
+            self.assertIn(key, subnet)
+            self.assertEqual(subnet[key], self.subnet[key])
 
     @attr(type='smoke')
     def test_show_subnet_fields(self):
-        # Verifies showing some fields of a subnet works
+        # Verify specific fields of a subnet
         field_list = [('fields', 'id'), ('fields', 'cidr'), ]
         resp, body = self.client.show_subnet(self.subnet['id'],
                                              field_list=field_list)
         self.assertEqual('200', resp['status'])
         subnet = body['subnet']
-        self.assertEqual(len(subnet), 2)
-        self.assertEqual(self.subnet['id'], subnet['id'])
-        self.assertEqual(self.cidr, subnet['cidr'])
+        self.assertEqual(len(subnet), len(field_list))
+        for label, field_name in field_list:
+            self.assertEqual(subnet[field_name], self.subnet[field_name])
 
     @attr(type='smoke')
     def test_list_subnets(self):
         # Verify the subnet exists in the list of all subnets
         resp, body = self.client.list_subnets()
         self.assertEqual('200', resp['status'])
-        subnets = body['subnets']
-        found = None
-        for n in subnets:
-            if (n['id'] == self.subnet['id']):
-                found = n['id']
-        msg = "Subnet list doesn't contain created subnet"
-        self.assertIsNotNone(found, msg)
+        subnets = [subnet['id'] for subnet in body['subnets']
+                   if subnet['id'] == self.subnet['id']]
+        self.assertNotEmpty(subnets, "Created subnet not found in the list")
 
     @attr(type='smoke')
     def test_list_subnets_fields(self):
-        # Verify listing some fields of the subnets
+        # Verify specific fields of subnets
         resp, body = self.client.list_subnets(fields='id')
         self.assertEqual('200', resp['status'])
         subnets = body['subnets']
-        found = None
-        for n in subnets:
-            self.assertEqual(len(n), 1)
-            self.assertIn('id', n)
-            if (n['id'] == self.subnet['id']):
-                found = n['id']
-        self.assertIsNotNone(found,
-                             "Created subnet id not found in the list")
-
-    @attr(type='smoke')
-    def test_create_update_delete_port(self):
-        # Verify that successful port creation, update & deletion
-        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'])
-        # Verification of port update
-        new_port = "New_Port"
-        resp, body = self.client.update_port(
-            port['id'],
-            name=new_port,
-            admin_state_up=False)
-        self.assertEqual('200', resp['status'])
-        updated_port = body['port']
-        self.assertEqual(updated_port['name'], new_port)
-        self.assertFalse(updated_port['admin_state_up'])
-        # Verification of port delete
-        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.assertEqual(self.port['id'], port['id'])
-
-    @attr(type='smoke')
-    def test_show_port_fields(self):
-        # Verifies showing fields of a port works
-        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), 1)
-        self.assertEqual(self.port['id'], port['id'])
-
-    @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_list = body['ports']
-        found = None
-        for n in ports_list:
-            if (n['id'] == self.port['id']):
-                found = n['id']
-        self.assertIsNotNone(found, "Port list doesn't contain created port")
-
-    @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'])
-        # Verify if only corresponding port is listed and assert router_id
-        self.assertEqual(len(port_list['ports']), 1)
-        self.assertEqual(port['port']['id'], port_list['ports'][0]['id'])
-        self.assertEqual(router['id'], port_list['ports'][0]['device_id'])
-
-    @attr(type='smoke')
-    def test_list_ports_fields(self):
-        # Verify listing some fields of the ports
-        resp, body = self.client.list_ports(fields='id')
-        self.assertEqual('200', resp['status'])
-        ports_list = body['ports']
-        found = None
-        for n in ports_list:
-            self.assertEqual(len(n), 1)
-            self.assertIn('id', n)
-            if (n['id'] == self.port['id']):
-                found = n['id']
-        self.assertIsNotNone(found,
-                             "Created port id not found in the list")
+        self.assertNotEmpty(subnets, "Subnet list returned is empty")
+        for subnet in subnets:
+            self.assertEqual(len(subnet), 1)
+            self.assertIn('id', subnet)
 
 
 class NetworksTestXML(NetworksTestJSON):
@@ -328,9 +222,7 @@
             self.assertEqual(204, resp.status)
         # Asserting that the networks are not found in the list after deletion
         resp, body = self.client.list_networks()
-        networks_list = list()
-        for network in body['networks']:
-            networks_list.append(network['id'])
+        networks_list = [network['id'] for network in body['networks']]
         for n in created_networks:
             self.assertNotIn(n['id'], networks_list)
 
@@ -340,9 +232,7 @@
             self.assertEqual(204, resp.status)
         # Asserting that the subnets are not found in the list after deletion
         resp, body = self.client.list_subnets()
-        subnets_list = list()
-        for subnet in body['subnets']:
-            subnets_list.append(subnet['id'])
+        subnets_list = [subnet['id'] for subnet in body['subnets']]
         for n in created_subnets:
             self.assertNotIn(n['id'], subnets_list)
 
@@ -352,9 +242,7 @@
             self.assertEqual(204, resp.status)
         # Asserting that the ports are not found in the list after deletion
         resp, body = self.client.list_ports()
-        ports_list = list()
-        for port in body['ports']:
-            ports_list.append(port['id'])
+        ports_list = [port['id'] for port in body['ports']]
         for n in created_ports:
             self.assertNotIn(n['id'], ports_list)
 
@@ -369,9 +257,7 @@
         self.addCleanup(self._delete_networks, created_networks)
         # Asserting that the networks are found in the list after creation
         resp, body = self.client.list_networks()
-        networks_list = list()
-        for network in body['networks']:
-            networks_list.append(network['id'])
+        networks_list = [network['id'] for network in body['networks']]
         for n in created_networks:
             self.assertIsNotNone(n['id'])
             self.assertIn(n['id'], networks_list)
@@ -381,14 +267,10 @@
         # Creates 2 subnets in one request
         cidr = netaddr.IPNetwork(CONF.network.tenant_network_cidr)
         mask_bits = CONF.network.tenant_network_mask_bits
-        cidrs = []
-        for subnet_cidr in cidr.subnet(mask_bits):
-            cidrs.append(subnet_cidr)
-        names = []
+        cidrs = [subnet_cidr for subnet_cidr in cidr.subnet(mask_bits)]
         networks = [self.network1['id'], self.network2['id']]
-        for i in range(len(networks)):
-            names.append(data_utils.rand_name('subnet-'))
-        subnet_list = []
+        names = [data_utils.rand_name('subnet-') for i in range(len(networks))]
+        subnets_list = []
         # TODO(raies): "for IPv6, version list [4, 6] will be used.
         # and cidr for IPv6 will be of IPv6"
         ip_version = [4, 4]
@@ -399,17 +281,15 @@
                 'name': names[i],
                 'ip_version': ip_version[i]
             }
-            subnet_list.append(p1)
-        del subnet_list[1]['name']
-        resp, body = self.client.create_bulk_subnet(subnet_list)
+            subnets_list.append(p1)
+        del subnets_list[1]['name']
+        resp, body = self.client.create_bulk_subnet(subnets_list)
         created_subnets = body['subnets']
         self.addCleanup(self._delete_subnets, created_subnets)
         self.assertEqual('201', resp['status'])
         # Asserting that the subnets are found in the list after creation
         resp, body = self.client.list_subnets()
-        subnets_list = list()
-        for subnet in body['subnets']:
-            subnets_list.append(subnet['id'])
+        subnets_list = [subnet['id'] for subnet in body['subnets']]
         for n in created_subnets:
             self.assertIsNotNone(n['id'])
             self.assertIn(n['id'], subnets_list)
@@ -417,10 +297,8 @@
     @attr(type='smoke')
     def test_bulk_create_delete_port(self):
         # Creates 2 ports in one request
-        names = []
         networks = [self.network1['id'], self.network2['id']]
-        for i in range(len(networks)):
-            names.append(data_utils.rand_name('port-'))
+        names = [data_utils.rand_name('port-') for i in range(len(networks))]
         port_list = []
         state = [True, False]
         for i in range(len(names)):
@@ -437,9 +315,7 @@
         self.assertEqual('201', resp['status'])
         # Asserting that the ports are found in the list after creation
         resp, body = self.client.list_ports()
-        ports_list = list()
-        for port in body['ports']:
-            ports_list.append(port['id'])
+        ports_list = [port['id'] for port in body['ports']]
         for n in created_ports:
             self.assertIsNotNone(n['id'])
             self.assertIn(n['id'], ports_list)
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/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
new file mode 100644
index 0000000..9d3bf13
--- /dev/null
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -0,0 +1,181 @@
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+
+import logging
+
+from tempest.api.orchestration import base
+from tempest.common.utils import data_utils
+from tempest.test import attr
+
+
+LOG = logging.getLogger(__name__)
+
+
+class NovaKeyPairResourcesYAMLTest(base.BaseOrchestrationTest):
+    _interface = 'json'
+    template = """
+heat_template_version: 2013-05-23
+
+description: >
+  Template which creates two key pairs.
+
+parameters:
+  KeyPairName1:
+    type: string
+    default: testkey
+
+  KeyPairName2:
+    type: string
+    default: testkey2
+
+resources:
+  KeyPairSavePrivate:
+    type: OS::Nova::KeyPair
+    properties:
+      name: { get_param: KeyPairName1 }
+      save_private_key: true
+
+  KeyPairDontSavePrivate:
+    type: OS::Nova::KeyPair
+    properties:
+      name: { get_param: KeyPairName2 }
+      save_private_key: false
+
+outputs:
+  KeyPair_PublicKey:
+    description: Public Key of generated keypair
+    value: { get_attr: [KeyPairSavePrivate, public_key] }
+
+  KeyPair_PrivateKey:
+    description: Private Key of generated keypair
+    value: { get_attr: [KeyPairSavePrivate, private_key] }
+
+  KeyPairDontSavePrivate_PublicKey:
+    description: Public Key of generated keypair
+    value: { get_attr: [KeyPairDontSavePrivate, public_key] }
+
+  KeyPairDontSavePrivate_PrivateKey:
+    description: Private Key of generated keypair
+    value: { get_attr: [KeyPairDontSavePrivate, private_key] }
+"""
+
+    @classmethod
+    def setUpClass(cls):
+        super(NovaKeyPairResourcesYAMLTest, cls).setUpClass()
+        cls.client = cls.orchestration_client
+        cls.stack_name = data_utils.rand_name('heat')
+
+        # create the stack, avoid any duplicated key.
+        cls.stack_identifier = cls.create_stack(
+            cls.stack_name,
+            cls.template,
+            parameters={
+                'KeyPairName1': cls.stack_name + '_1',
+                'KeyPairName2': cls.stack_name + '_2'
+            })
+
+        cls.stack_id = cls.stack_identifier.split('/')[1]
+        cls.client.wait_for_stack_status(cls.stack_id, 'CREATE_COMPLETE')
+        _, resources = cls.client.list_resources(cls.stack_identifier)
+        cls.test_resources = {}
+        for resource in resources:
+            cls.test_resources[resource['logical_resource_id']] = resource
+
+    @attr(type='slow')
+    def test_created_resources(self):
+        """Verifies created keypair resource."""
+        resources = [('KeyPairSavePrivate', 'OS::Nova::KeyPair'),
+                     ('KeyPairDontSavePrivate', 'OS::Nova::KeyPair')]
+
+        for resource_name, resource_type in resources:
+            resource = self.test_resources.get(resource_name, None)
+            self.assertIsInstance(resource, dict)
+            self.assertEqual(resource_name, resource['logical_resource_id'])
+            self.assertEqual(resource_type, resource['resource_type'])
+            self.assertEqual('CREATE_COMPLETE', resource['resource_status'])
+
+    @attr(type='slow')
+    def test_stack_keypairs_output(self):
+        resp, stack = self.client.get_stack(self.stack_name)
+        self.assertEqual('200', resp['status'])
+        self.assertIsInstance(stack, dict)
+
+        output_map = {}
+        for outputs in stack['outputs']:
+            output_map[outputs['output_key']] = outputs['output_value']
+        #Test that first key generated public and private keys
+        self.assertTrue('KeyPair_PublicKey' in output_map)
+        self.assertTrue("Generated by" in output_map['KeyPair_PublicKey'])
+        self.assertTrue('KeyPair_PrivateKey' in output_map)
+        self.assertTrue('-----BEGIN' in output_map['KeyPair_PrivateKey'])
+        #Test that second key generated public key, and private key is not
+        #in the output due to save_private_key = false
+        self.assertTrue('KeyPairDontSavePrivate_PublicKey' in output_map)
+        self.assertTrue('Generated by' in
+                        output_map['KeyPairDontSavePrivate_PublicKey'])
+        self.assertTrue(u'KeyPairDontSavePrivate_PrivateKey' in output_map)
+        private_key = output_map['KeyPairDontSavePrivate_PrivateKey']
+        self.assertTrue(len(private_key) == 0)
+
+
+class NovaKeyPairResourcesAWSTest(NovaKeyPairResourcesYAMLTest):
+    template = """
+{
+  "AWSTemplateFormatVersion" : "2010-09-09",
+  "Description" : "Template which create two key pairs.",
+  "Parameters" : {
+    "KeyPairName1": {
+      "Type": "String",
+      "Default": "testkey1"
+      },
+    "KeyPairName2": {
+      "Type": "String",
+      "Default": "testkey2"
+      }
+   },
+   "Resources" : {
+     "KeyPairSavePrivate": {
+       "Type": "OS::Nova::KeyPair",
+       "Properties": {
+         "name" : { "Ref" : "KeyPairName1" },
+         "save_private_key": true
+       }
+     },
+     "KeyPairDontSavePrivate": {
+       "Type": "OS::Nova::KeyPair",
+       "Properties": {
+         "name" : { "Ref" : "KeyPairName2" },
+         "save_private_key": false
+      }
+     }
+  },
+ "Outputs": {
+   "KeyPair_PublicKey": {
+     "Description": "Public Key of generated keypair.",
+     "Value": { "Fn::GetAtt" : ["KeyPairSavePrivate", "public_key"] }
+    },
+   "KeyPair_PrivateKey": {
+     "Description": "Private Key of generated keypair.",
+     "Value": { "Fn::GetAtt" : ["KeyPairSavePrivate", "private_key"] }
+   },
+   "KeyPairDontSavePrivate_PublicKey": {
+     "Description": "Public Key of generated keypair.",
+     "Value": { "Fn::GetAtt" : ["KeyPairDontSavePrivate", "public_key"] }
+   },
+  "KeyPairDontSavePrivate_PrivateKey": {
+     "Description": "Private Key of generated keypair.",
+     "Value": { "Fn::GetAtt" : ["KeyPairDontSavePrivate", "private_key"] }
+   }
+  }
+}
+"""
diff --git a/tempest/api/orchestration/stacks/test_server_cfn_init.py b/tempest/api/orchestration/stacks/test_server_cfn_init.py
index 7e8bc2d..95deaf5 100644
--- a/tempest/api/orchestration/stacks/test_server_cfn_init.py
+++ b/tempest/api/orchestration/stacks/test_server_cfn_init.py
@@ -17,6 +17,7 @@
 from tempest.common.utils import data_utils
 from tempest.common.utils.linux import remote_client
 from tempest import config
+from tempest import exceptions
 from tempest.openstack.common import log as logging
 from tempest import test
 
@@ -66,18 +67,13 @@
               content: smoke test complete
             /etc/cfn/cfn-credentials:
               content:
-                Fn::Join:
-                - ''
-                - - AWSAccessKeyId=
-                  - {Ref: SmokeKeys}
-                  - '
-
-                    '
-                  - AWSSecretKey=
-                  - Fn::GetAtt: [SmokeKeys, SecretAccessKey]
-                  - '
-
-                    '
+                Fn::Replace:
+                - SmokeKeys: {Ref: SmokeKeys}
+                  SecretAccessKey:
+                    'Fn::GetAtt': [SmokeKeys, SecretAccessKey]
+                - |
+                  AWSAccessKeyId=SmokeKeys
+                  AWSSecretKey=SecretAccessKey
               mode: '000400'
               owner: root
               group: root
@@ -90,19 +86,13 @@
       networks:
       - uuid: {Ref: network}
       user_data:
-        Fn::Base64:
-          Fn::Join:
-          - ''
-          - - |-
-                #!/bin/bash -v
-                /opt/aws/bin/cfn-init
-            - |-
-                || error_exit ''Failed to run cfn-init''
-                /opt/aws/bin/cfn-signal -e 0 --data "`cat /tmp/smoke-status`" '
-            - {Ref: WaitHandle}
-            - '''
-
-              '
+        Fn::Replace:
+        - WaitHandle: {Ref: WaitHandle}
+        - |
+          #!/bin/bash -v
+          /opt/aws/bin/cfn-init
+          /opt/aws/bin/cfn-signal -e 0 --data "`cat /tmp/smoke-status`" \
+              "WaitHandle"
   WaitHandle:
     Type: AWS::CloudFormation::WaitConditionHandle
   WaitCondition:
@@ -172,9 +162,32 @@
         linux_client.validate_authentication()
 
     @test.attr(type='slow')
-    def test_stack_wait_condition_data(self):
-
+    def test_all_resources_created(self):
         sid = self.stack_identifier
+        self.client.wait_for_resource_status(
+            sid, 'WaitHandle', 'CREATE_COMPLETE')
+        self.client.wait_for_resource_status(
+            sid, 'SmokeSecurityGroup', 'CREATE_COMPLETE')
+        self.client.wait_for_resource_status(
+            sid, 'SmokeKeys', 'CREATE_COMPLETE')
+        self.client.wait_for_resource_status(
+            sid, 'CfnUser', 'CREATE_COMPLETE')
+        self.client.wait_for_resource_status(
+            sid, 'SmokeServer', 'CREATE_COMPLETE')
+        try:
+            self.client.wait_for_resource_status(
+                sid, 'WaitCondition', 'CREATE_COMPLETE')
+        except exceptions.TimeoutException as e:
+            # attempt to log the server console to help with debugging
+            # the cause of the server not signalling the waitcondition
+            # to heat.
+            resp, body = self.client.get_resource(sid, 'SmokeServer')
+            server_id = body['physical_resource_id']
+            LOG.debug('Console output for %s', server_id)
+            resp, output = self.servers_client.get_console_output(
+                server_id, None)
+            LOG.debug(output)
+            raise e
 
         # wait for create to complete.
         self.client.wait_for_stack_status(sid, 'CREATE_COMPLETE')
diff --git a/tempest/api/queuing/__init__.py b/tempest/api/queuing/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/queuing/__init__.py
diff --git a/tempest/api/queuing/base.py b/tempest/api/queuing/base.py
new file mode 100644
index 0000000..5656850
--- /dev/null
+++ b/tempest/api/queuing/base.py
@@ -0,0 +1,49 @@
+# Copyright (c) 2014 Rackspace, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from tempest import config
+from tempest.openstack.common import log as logging
+from tempest import test
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+
+class BaseQueuingTest(test.BaseTestCase):
+
+    """
+    Base class for the Queuing tests that use the Tempest Marconi REST client
+
+    It is assumed that the following option is defined in the
+    [service_available] section of etc/tempest.conf
+
+        queuing as True
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        super(BaseQueuingTest, cls).setUpClass()
+        if not CONF.service_available.marconi:
+            raise cls.skipException("Marconi support is required")
+        os = cls.get_client_manager()
+        cls.queuing_cfg = CONF.queuing
+        cls.client = os.queuing_client
+
+    @classmethod
+    def create_queue(cls, queue_name):
+        """Wrapper utility that returns a test queue."""
+        resp, body = cls.client.create_queue(queue_name)
+        return resp, body
diff --git a/tempest/api/queuing/test_queues.py b/tempest/api/queuing/test_queues.py
new file mode 100644
index 0000000..6934b46
--- /dev/null
+++ b/tempest/api/queuing/test_queues.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2014 Rackspace, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+
+from tempest.api.queuing import base
+from tempest.common.utils import data_utils
+from tempest import test
+
+
+LOG = logging.getLogger(__name__)
+
+
+class TestQueues(base.BaseQueuingTest):
+
+    @test.attr(type='smoke')
+    def test_create_queue(self):
+        # Create Queue
+        queue_name = data_utils.rand_name('test-')
+        resp, body = self.create_queue(queue_name)
+
+        self.addCleanup(self.client.delete_queue, queue_name)
+
+        self.assertEqual('201', resp['status'])
+        self.assertEqual('', body)
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 31f6730..742f7e1 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -23,6 +23,7 @@
 
 class VolumeQuotasAdminTestJSON(base.BaseVolumeV1AdminTest):
     _interface = "json"
+    force_tenant_isolation = True
 
     @classmethod
     def setUpClass(cls):
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 175da01..be5d76b 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -124,8 +124,8 @@
         resp, new_volume = \
             self.client.create_volume(size=1,
                                       display_description=new_v_desc,
-                                      availability_zone=volume[
-                                      'availability_zone'])
+                                      availability_zone=
+                                      volume['availability_zone'])
         self.assertEqual(200, resp.status)
         self.assertIn('id', new_volume)
         self.addCleanup(self._delete_volume, new_volume['id'])
@@ -133,8 +133,8 @@
         resp, update_volume = \
             self.client.update_volume(new_volume['id'],
                                       display_name=volume['display_name'],
-                                      display_description=volume[
-                                      'display_description'])
+                                      display_description=
+                                      volume['display_description'])
         self.assertEqual(200, resp.status)
 
         # NOTE(jdg): Revert back to strict true/false checking
diff --git a/tempest/api/volume/v2/test_volumes_list.py b/tempest/api/volume/v2/test_volumes_list.py
index 0e91371..fff40ed 100644
--- a/tempest/api/volume/v2/test_volumes_list.py
+++ b/tempest/api/volume/v2/test_volumes_list.py
@@ -116,8 +116,8 @@
                           ('details' if with_detail else '', key)
                     if key == 'metadata':
                         self.assertThat(volume[key].items(),
-                                        matchers.ContainsAll(params[key]
-                                        .items()), msg)
+                                        matchers.ContainsAll(
+                                            params[key].items()), msg)
                     else:
                         self.assertEqual(params[key], volume[key], msg)
 
diff --git a/tempest/api_schema/__init__.py b/tempest/api_schema/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/__init__.py
diff --git a/tempest/api_schema/compute/__init__.py b/tempest/api_schema/compute/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/compute/__init__.py
diff --git a/tempest/api_schema/compute/services.py b/tempest/api_schema/compute/services.py
new file mode 100644
index 0000000..4793f5a
--- /dev/null
+++ b/tempest/api_schema/compute/services.py
@@ -0,0 +1,44 @@
+# 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_services = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'services': {
+                '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']},
+                        'zone': {'type': 'string'},
+                        'host': {'type': 'string'},
+                        'state': {'type': 'string'},
+                        'binary': {'type': 'string'},
+                        'status': {'type': 'string'},
+                        'updated_at': {'type': 'string'},
+                        'disabled_reason': {'type': ['string', 'null']}
+                    },
+                    'required': ['id', 'zone', 'host', 'state', 'binary',
+                                 'status', 'updated_at', 'disabled_reason']
+                }
+            }
+        },
+        'required': ['services']
+    }
+}
diff --git a/tempest/api_schema/compute/v2/__init__.py b/tempest/api_schema/compute/v2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api_schema/compute/v2/__init__.py
diff --git a/tempest/api_schema/compute/v2/volumes.py b/tempest/api_schema/compute/v2/volumes.py
new file mode 100644
index 0000000..16ed7c2
--- /dev/null
+++ b/tempest/api_schema/compute/v2/volumes.py
@@ -0,0 +1,56 @@
+# 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_volume = {
+    'status_code': [200],
+    'response_body': {
+        'type': 'object',
+        'properties': {
+            'volume': {
+                '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']},
+                    'status': {'type': 'string'},
+                    'displayName': {'type': ['string', 'null']},
+                    'availabilityZone': {'type': 'string'},
+                    'createdAt': {'type': 'string'},
+                    'displayDescription': {'type': ['string', 'null']},
+                    'volumeType': {'type': 'string'},
+                    'snapshotId': {'type': ['string', 'null']},
+                    'metadata': {'type': 'object'},
+                    'size': {'type': 'integer'},
+                    'attachments': {
+                        'type': 'array',
+                        'items': {
+                            'type': 'object',
+                            'properties': {
+                                'id': {'type': ['integer', 'string']},
+                                'device': {'type': 'string'},
+                                'volumeId': {'type': ['integer', 'string']},
+                                'serverId': {'type': ['integer', 'string']}
+                            }
+                        }
+                    }
+                },
+                'required': ['id', 'status', 'displayName', 'availabilityZone',
+                             'createdAt', 'displayDescription', 'volumeType',
+                             'snapshotId', 'metadata', 'size', 'attachments']
+            }
+        },
+        'required': ['volume']
+    }
+}
diff --git a/tempest/cli/__init__.py b/tempest/cli/__init__.py
index 8c4ec45..810e6b2 100644
--- a/tempest/cli/__init__.py
+++ b/tempest/cli/__init__.py
@@ -83,9 +83,10 @@
         return self.cmd_with_auth(
             'neutron', action, flags, params, admin, fail_ok)
 
-    def savanna(self, action, flags='', params='', admin=True, fail_ok=False):
-        """Executes savanna command for the given action."""
+    def sahara(self, action, flags='', params='', admin=True, fail_ok=False):
+        """Executes sahara command for the given action."""
         return self.cmd_with_auth(
+            # TODO (slukjanov): replace with sahara when new client released
             'savanna', action, flags, params, admin, fail_ok)
 
     def cmd_with_auth(self, cmd, action, flags='', params='',
diff --git a/tempest/cli/simple_read_only/test_savanna.py b/tempest/cli/simple_read_only/test_sahara.py
similarity index 61%
rename from tempest/cli/simple_read_only/test_savanna.py
rename to tempest/cli/simple_read_only/test_sahara.py
index 1e30978..cd819a4 100644
--- a/tempest/cli/simple_read_only/test_savanna.py
+++ b/tempest/cli/simple_read_only/test_sahara.py
@@ -25,8 +25,8 @@
 LOG = logging.getLogger(__name__)
 
 
-class SimpleReadOnlySavannaClientTest(cli.ClientTestBase):
-    """Basic, read-only tests for Savanna CLI client.
+class SimpleReadOnlySaharaClientTest(cli.ClientTestBase):
+    """Basic, read-only tests for Sahara CLI client.
 
     Checks return values and output of read-only commands.
     These tests do not presume any content, nor do they create
@@ -35,36 +35,36 @@
 
     @classmethod
     def setUpClass(cls):
-        if not CONF.service_available.savanna:
-            msg = "Skipping all Savanna cli tests because it is not available"
+        if not CONF.service_available.sahara:
+            msg = "Skipping all Sahara cli tests because it is not available"
             raise cls.skipException(msg)
-        super(SimpleReadOnlySavannaClientTest, cls).setUpClass()
+        super(SimpleReadOnlySaharaClientTest, cls).setUpClass()
 
     @test.attr(type='negative')
-    def test_savanna_fake_action(self):
+    def test_sahara_fake_action(self):
         self.assertRaises(subprocess.CalledProcessError,
-                          self.savanna,
+                          self.sahara,
                           'this-does-not-exist')
 
-    def test_savanna_plugins_list(self):
-        plugins = self.parser.listing(self.savanna('plugin-list'))
+    def test_sahara_plugins_list(self):
+        plugins = self.parser.listing(self.sahara('plugin-list'))
         self.assertTableStruct(plugins, ['name', 'versions', 'title'])
 
-    def test_savanna_plugins_show(self):
-        plugin = self.parser.listing(self.savanna('plugin-show',
-                                                  params='--name vanilla'))
+    def test_sahara_plugins_show(self):
+        plugin = self.parser.listing(self.sahara('plugin-show',
+                                                 params='--name vanilla'))
         self.assertTableStruct(plugin, ['Property', 'Value'])
 
-    def test_savanna_node_group_template_list(self):
-        plugins = self.parser.listing(self.savanna('node-group-template-list'))
+    def test_sahara_node_group_template_list(self):
+        plugins = self.parser.listing(self.sahara('node-group-template-list'))
         self.assertTableStruct(plugins, ['name', 'id', 'plugin_name',
                                          'node_processes', 'description'])
 
-    def test_savanna_cluster_template_list(self):
-        plugins = self.parser.listing(self.savanna('cluster-template-list'))
+    def test_sahara_cluster_template_list(self):
+        plugins = self.parser.listing(self.sahara('cluster-template-list'))
         self.assertTableStruct(plugins, ['name', 'id', 'plugin_name',
                                          'node_groups', 'description'])
 
-    def test_savanna_cluster_list(self):
-        plugins = self.parser.listing(self.savanna('cluster-list'))
+    def test_sahara_cluster_list(self):
+        plugins = self.parser.listing(self.sahara('cluster-list'))
         self.assertTableStruct(plugins, ['name', 'id', 'status', 'node_count'])
diff --git a/tempest/clients.py b/tempest/clients.py
index 5999ed6..7ebd983 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -61,6 +61,7 @@
     TenantUsagesClientJSON
 from tempest.services.compute.json.volumes_extensions_client import \
     VolumesExtensionsClientJSON
+from tempest.services.compute.v3.json.agents_client import AgentsV3ClientJSON
 from tempest.services.compute.v3.json.aggregates_client import \
     AggregatesV3ClientJSON
 from tempest.services.compute.v3.json.availability_zone_client import \
@@ -152,6 +153,7 @@
     ObjectClientCustomizedHeader
 from tempest.services.orchestration.json.orchestration_client import \
     OrchestrationClient
+from tempest.services.queuing.json.queuing_client import QueuingClientJSON
 from tempest.services.telemetry.json.telemetry_client import \
     TelemetryClientJSON
 from tempest.services.telemetry.xml.telemetry_client import \
@@ -314,6 +316,7 @@
             self.services_v3_client = ServicesV3ClientJSON(
                 self.auth_provider)
             self.service_client = ServiceClientJSON(self.auth_provider)
+            self.agents_v3_client = AgentsV3ClientJSON(self.auth_provider)
             self.aggregates_v3_client = AggregatesV3ClientJSON(
                 self.auth_provider)
             self.aggregates_client = AggregatesClientJSON(
@@ -342,6 +345,7 @@
             self.hosts_v3_client = HostsV3ClientJSON(self.auth_provider)
             self.database_flavors_client = DatabaseFlavorsClientJSON(
                 self.auth_provider)
+            self.queuing_client = QueuingClientJSON(self.auth_provider)
             if CONF.service_available.ceilometer:
                 self.telemetry_client = TelemetryClientJSON(
                     self.auth_provider)
diff --git a/tempest/common/commands.py b/tempest/common/commands.py
index 6405eaa..c31a038 100644
--- a/tempest/common/commands.py
+++ b/tempest/common/commands.py
@@ -73,3 +73,7 @@
 
 def iptables_ns(ns, table):
     return ip_ns_exec(ns, "iptables -v -S -t " + table)
+
+
+def ovs_db_dump():
+    return sudo_cmd_call("ovsdb-client dump")
diff --git a/tempest/common/debug.py b/tempest/common/debug.py
index 8325d4d..6a496c2 100644
--- a/tempest/common/debug.py
+++ b/tempest/common/debug.py
@@ -38,3 +38,15 @@
         for table in ['filter', 'nat', 'mangle']:
             LOG.info('ns(%s) table(%s):\n%s', ns, table,
                      commands.iptables_ns(ns, table))
+
+
+def log_ovs_db():
+    if not CONF.debug.enable or not CONF.service_available.neutron:
+        return
+    db_dump = commands.ovs_db_dump()
+    LOG.info("OVS DB:\n" + db_dump)
+
+
+def log_net_debug():
+    log_ip_ns()
+    log_ovs_db()
diff --git a/tempest/common/generator/base_generator.py b/tempest/common/generator/base_generator.py
index 35f8158..7e7a2d6 100644
--- a/tempest/common/generator/base_generator.py
+++ b/tempest/common/generator/base_generator.py
@@ -59,7 +59,9 @@
                 "enum": ["GET", "PUT", "HEAD",
                          "POST", "PATCH", "DELETE", 'COPY']
             },
+            "admin_client": {"type": "boolean"},
             "url": {"type": "string"},
+            "default_result_code": {"type": "integer"},
             "json-schema": jsonschema._utils.load_schema("draft4"),
             "resources": {
                 "type": "array",
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index ac8b14f..c54a8e8 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -456,7 +456,8 @@
             port
             for port in self.ports
             if (port['network_id'] == network_id and
-                port['device_owner'] != 'network:router_interface')
+                port['device_owner'] != 'network:router_interface' and
+                port['device_owner'] != 'network:dhcp')
         ]
         for port in ports_to_delete:
             try:
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 36ddb40..88dbe58 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -21,6 +21,8 @@
 import re
 import time
 
+import jsonschema
+
 from tempest.common import http
 from tempest import config
 from tempest import exceptions
@@ -502,6 +504,31 @@
                    % self.__class__.__name__)
         raise NotImplementedError(message)
 
+    @classmethod
+    def validate_response(cls, schema, resp, body):
+        # Only check the response if the status code is a success code
+        # TODO(cyeoh): Eventually we should be able to verify that a failure
+        # code if it exists is something that we expect. This is explicitly
+        # declared in the V3 API and so we should be able to export this in
+        # the response schema. For now we'll ignore it.
+        if str(resp.status).startswith('2'):
+            response_code = schema['status_code']
+            if resp.status not in response_code:
+                msg = ("The status code(%s) is different than the expected "
+                       "one(%s)") % (resp.status, response_code)
+                raise exceptions.InvalidHttpSuccessCode(msg)
+            response_schema = schema.get('response_body')
+            if response_schema:
+                try:
+                    jsonschema.validate(body, response_schema)
+                except jsonschema.ValidationError as ex:
+                    msg = ("HTTP response body is invalid (%s)") % ex
+                    raise exceptions.InvalidHTTPResponseBody(msg)
+            else:
+                if body:
+                    msg = ("HTTP response body should not exist (%s)") % body
+                    raise exceptions.InvalidHTTPResponseBody(msg)
+
 
 class NegativeRestClient(RestClient):
     """
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 8420ad0..00e5e0d 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -43,6 +43,9 @@
                                      ssh_timeout, pkey=pkey,
                                      channel_timeout=ssh_channel_timeout)
 
+    def exec_command(self, cmd):
+        return self.ssh_client.exec_command(cmd)
+
     def validate_authentication(self):
         """Validate ssh connection and authentication
            This method raises an Exception when the validation fails.
@@ -51,33 +54,33 @@
 
     def hostname_equals_servername(self, expected_hostname):
         # Get host name using command "hostname"
-        actual_hostname = self.ssh_client.exec_command("hostname").rstrip()
+        actual_hostname = self.exec_command("hostname").rstrip()
         return expected_hostname == actual_hostname
 
     def get_files(self, path):
         # Return a list of comma separated files
         command = "ls -m " + path
-        return self.ssh_client.exec_command(command).rstrip('\n').split(', ')
+        return self.exec_command(command).rstrip('\n').split(', ')
 
     def get_ram_size_in_mb(self):
-        output = self.ssh_client.exec_command('free -m | grep Mem')
+        output = self.exec_command('free -m | grep Mem')
         if output:
             return output.split()[1]
 
     def get_number_of_vcpus(self):
         command = 'cat /proc/cpuinfo | grep processor | wc -l'
-        output = self.ssh_client.exec_command(command)
+        output = self.exec_command(command)
         return int(output)
 
     def get_partitions(self):
         # Return the contents of /proc/partitions
         command = 'cat /proc/partitions'
-        output = self.ssh_client.exec_command(command)
+        output = self.exec_command(command)
         return output
 
     def get_boot_time(self):
         cmd = 'cut -f1 -d. /proc/uptime'
-        boot_secs = self.ssh_client.exec_command(cmd)
+        boot_secs = self.exec_command(cmd)
         boot_time = time.time() - int(boot_secs)
         return time.localtime(boot_time)
 
@@ -85,27 +88,27 @@
         message = re.sub("([$\\`])", "\\\\\\\\\\1", message)
         # usually to /dev/ttyS0
         cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % message
-        return self.ssh_client.exec_command(cmd)
+        return self.exec_command(cmd)
 
     def ping_host(self, host):
         cmd = 'ping -c1 -w1 %s' % host
-        return self.ssh_client.exec_command(cmd)
+        return self.exec_command(cmd)
 
     def get_mac_address(self):
         cmd = "/sbin/ifconfig | awk '/HWaddr/ {print $5}'"
-        return self.ssh_client.exec_command(cmd)
+        return self.exec_command(cmd)
 
     def get_ip_list(self):
         cmd = "/bin/ip address"
-        return self.ssh_client.exec_command(cmd)
+        return self.exec_command(cmd)
 
     def assign_static_ip(self, nic, addr):
         cmd = "sudo /bin/ip addr add {ip}/{mask} dev {nic}".format(
             ip=addr, mask=CONF.network.tenant_network_mask_bits,
             nic=nic
         )
-        return self.ssh_client.exec_command(cmd)
+        return self.exec_command(cmd)
 
     def turn_nic_on(self, nic):
         cmd = "sudo /bin/ip link set {nic} up".format(nic=nic)
-        return self.ssh_client.exec_command(cmd)
+        return self.exec_command(cmd)
diff --git a/tempest/config.py b/tempest/config.py
index db81f6e..471a0de 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -60,16 +60,16 @@
                         'publicURL', 'adminURL', 'internalURL'],
                help="The endpoint type to use for the identity service."),
     cfg.StrOpt('username',
-               default='demo',
+               default=None,
                help="Username to use for Nova API requests."),
     cfg.StrOpt('tenant_name',
-               default='demo',
+               default=None,
                help="Tenant name to use for Nova API requests."),
     cfg.StrOpt('admin_role',
                default='admin',
                help="Role required to administrate keystone."),
     cfg.StrOpt('password',
-               default='pass',
+               default=None,
                help="API key to use when authenticating.",
                secret=True),
     cfg.StrOpt('alt_username',
@@ -85,15 +85,15 @@
                help="API key to use when authenticating as alternate user.",
                secret=True),
     cfg.StrOpt('admin_username',
-               default='admin',
+               default=None,
                help="Administrative Username to use for "
                     "Keystone API requests."),
     cfg.StrOpt('admin_tenant_name',
-               default='admin',
+               default=None,
                help="Administrative Tenant name to use for Keystone API "
                     "requests."),
     cfg.StrOpt('admin_password',
-               default='pass',
+               default=None,
                help="API key to use when authenticating as admin.",
                secret=True),
 ]
@@ -246,9 +246,6 @@
                 default=False,
                 help="Does the test environment support changing the admin "
                      "password?"),
-    cfg.BoolOpt('create_image',
-                default=False,
-                help="Does the test environment support snapshots?"),
     cfg.BoolOpt('resize',
                 default=False,
                 help="Does the test environment support resizing?"),
@@ -276,14 +273,14 @@
 
 ComputeAdminGroup = [
     cfg.StrOpt('username',
-               default='admin',
+               default=None,
                help="Administrative Username to use for Nova API requests."),
     cfg.StrOpt('tenant_name',
-               default='admin',
+               default=None,
                help="Administrative Tenant name to use for Nova API "
                     "requests."),
     cfg.StrOpt('password',
-               default='pass',
+               default=None,
                help="API key to use when authenticating as admin.",
                secret=True),
 ]
@@ -366,6 +363,14 @@
                default="",
                help="Id of the public router that provides external "
                     "connectivity"),
+    cfg.IntOpt('build_timeout',
+               default=300,
+               help="Timeout in seconds to wait for network operation to "
+                    "complete."),
+    cfg.IntOpt('build_interval',
+               default=10,
+               help="Time in seconds between network operation status "
+                    "checks."),
 ]
 
 network_feature_group = cfg.OptGroup(name='network-feature-enabled',
@@ -381,6 +386,15 @@
                      'entry all which indicates every extension is enabled'),
 ]
 
+queuing_group = cfg.OptGroup(name='queuing',
+                             title='Queuing Service')
+
+QueuingGroup = [
+    cfg.StrOpt('catalog_type',
+               default='queuing',
+               help='Catalog type of the Queuing service.'),
+]
+
 volume_group = cfg.OptGroup(name='volume',
                             title='Block Storage Options')
 
@@ -612,6 +626,9 @@
     cfg.StrOpt('aws_access',
                default=None,
                help="AWS Access Key"),
+    cfg.StrOpt('aws_zone',
+               default="nova",
+               help="AWS Zone for EC2 tests"),
     cfg.StrOpt('s3_materials_path',
                default="/opt/stack/devstack/files/images/"
                        "s3-materials/cirros-0.3.0",
@@ -744,15 +761,18 @@
     cfg.BoolOpt('horizon',
                 default=True,
                 help="Whether or not Horizon is expected to be available"),
-    cfg.BoolOpt('savanna',
+    cfg.BoolOpt('sahara',
                 default=False,
-                help="Whether or not Savanna is expected to be available"),
+                help="Whether or not Sahara is expected to be available"),
     cfg.BoolOpt('ironic',
                 default=False,
                 help="Whether or not Ironic is expected to be available"),
     cfg.BoolOpt('trove',
                 default=False,
                 help="Whether or not Trove is expected to be available"),
+    cfg.BoolOpt('marconi',
+                default=False,
+                help="Whether or not Marconi is expected to be available"),
 ]
 
 debug_group = cfg.OptGroup(name="debug",
@@ -842,6 +862,7 @@
     register_opt_group(cfg.CONF, network_group, NetworkGroup)
     register_opt_group(cfg.CONF, network_feature_group,
                        NetworkFeaturesGroup)
+    register_opt_group(cfg.CONF, queuing_group, QueuingGroup)
     register_opt_group(cfg.CONF, volume_group, VolumeGroup)
     register_opt_group(cfg.CONF, volume_feature_group,
                        VolumeFeaturesGroup)
@@ -893,6 +914,7 @@
             'object-storage-feature-enabled']
         self.database = cfg.CONF.database
         self.orchestration = cfg.CONF.orchestration
+        self.queuing = cfg.CONF.queuing
         self.telemetry = cfg.CONF.telemetry
         self.dashboard = cfg.CONF.dashboard
         self.data_processing = cfg.CONF.data_processing
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 39b7760..24d2677 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -97,7 +97,7 @@
         except Exception:
             LOG.exception('ssh to server failed')
             self._log_console_output()
-            debug.log_ip_ns()
+            debug.log_net_debug()
             raise
 
     def check_partitions(self):
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 489b271..d5ab3d3 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -172,7 +172,7 @@
         except Exception:
             LOG.exception('Tenant connectivity check failed')
             self._log_console_output(servers=self.servers.keys())
-            debug.log_ip_ns()
+            debug.log_net_debug()
             raise
 
     def _create_and_associate_floating_ips(self):
@@ -204,7 +204,7 @@
                 ex_msg += ": " + msg
             LOG.exception(ex_msg)
             self._log_console_output(servers=self.servers.keys())
-            debug.log_ip_ns()
+            debug.log_net_debug()
             raise
 
     def _disassociate_floating_ips(self):
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index d404dd1..b9ee040 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -343,7 +343,7 @@
                                                             should_succeed),
                             msg)
         except Exception:
-            debug.log_ip_ns()
+            debug.log_net_debug()
             raise
 
     def _test_in_tenant_block(self, tenant):
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index 37beb07..562020a 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -45,11 +45,10 @@
 
     def _ssh_to_server(self, server_or_ip):
         try:
-            linux_client = self.get_remote_client(server_or_ip)
+            return self.get_remote_client(server_or_ip)
         except Exception:
             LOG.exception()
             self._log_console_output()
-        return linux_client.ssh_client
 
     def _write_timestamp(self, server_or_ip):
         ssh_client = self._ssh_to_server(server_or_ip)
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 841f9e1..128ec17 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -72,8 +72,7 @@
         server.add_floating_ip(floating_ip)
 
     def _ssh_to_server(self, server_or_ip):
-        linux_client = self.get_remote_client(server_or_ip)
-        return linux_client.ssh_client
+        return self.get_remote_client(server_or_ip)
 
     def _create_volume_snapshot(self, volume):
         snapshot_name = data_utils.rand_name('scenario-snapshot-')
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 9a250d7..4046cbd 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -53,7 +53,7 @@
             'block_device_mapping': bd_map,
             'key_name': keypair.name
         }
-        return self.create_server(create_kwargs=create_kwargs)
+        return self.create_server(image='', create_kwargs=create_kwargs)
 
     def _create_snapshot_from_volume(self, vol_id):
         volume_snapshots = self.volume_client.volume_snapshots
@@ -101,14 +101,13 @@
             ip = server.networks[network_name_for_ssh][0]
 
         try:
-            client = self.get_remote_client(
+            return self.get_remote_client(
                 ip,
                 private_key=keypair.private_key)
         except Exception:
             LOG.exception('ssh to server failed')
             self._log_console_output()
             raise
-        return client.ssh_client
 
     def _get_content(self, ssh_client):
         return ssh_client.exec_command('cat /tmp/text')
diff --git a/tempest/services/botoclients.py b/tempest/services/botoclients.py
index b52d48c..7616a99 100644
--- a/tempest/services/botoclients.py
+++ b/tempest/services/botoclients.py
@@ -179,19 +179,6 @@
                            'revoke_security_group',
                            'revoke_security_group_egress'))
 
-    def get_good_zone(self):
-        """
-        :rtype: BaseString
-        :return: Returns with the first available zone name
-        """
-        for zone in self.get_all_zones():
-            # NOTE(afazekas): zone.region_name was None
-            if (zone.state == "available" and
-                zone.region.name == self.connection_data["region"].name):
-                return zone.name
-        else:
-            raise IndexError("Don't have a good zone")
-
 
 class ObjectClientS3(BotoClientBase):
 
diff --git a/tempest/services/compute/json/quotas_client.py b/tempest/services/compute/json/quotas_client.py
index 459ab6d..c1ac3db 100644
--- a/tempest/services/compute/json/quotas_client.py
+++ b/tempest/services/compute/json/quotas_client.py
@@ -100,3 +100,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/json/servers_client.py b/tempest/services/compute/json/servers_client.py
index 623bf42..ca0f114 100644
--- a/tempest/services/compute/json/servers_client.py
+++ b/tempest/services/compute/json/servers_client.py
@@ -382,6 +382,10 @@
         """Un-shelves the provided server."""
         return self.action(server_id, 'unshelve', None, **kwargs)
 
+    def shelve_offload_server(self, server_id, **kwargs):
+        """Shelve-offload the provided server."""
+        return self.action(server_id, 'shelveOffload', None, **kwargs)
+
     def get_console_output(self, server_id, length):
         return self.action(server_id, 'os-getConsoleOutput', 'output',
                            length=length)
@@ -436,3 +440,8 @@
     def inject_network_info(self, server_id, **kwargs):
         """Inject the Network Info into server"""
         return self.action(server_id, 'injectNetworkInfo', None, **kwargs)
+
+    def get_vnc_console(self, server_id, console_type):
+        """Get URL of VNC console."""
+        return self.action(server_id, "os-getVNCConsole",
+                           "console", type=console_type)
diff --git a/tempest/services/compute/json/services_client.py b/tempest/services/compute/json/services_client.py
index 1ab25ec..0f7d4cb 100644
--- a/tempest/services/compute/json/services_client.py
+++ b/tempest/services/compute/json/services_client.py
@@ -17,6 +17,7 @@
 import json
 import urllib
 
+from tempest.api_schema.compute import services as schema
 from tempest.common import rest_client
 from tempest import config
 
@@ -36,6 +37,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
+        self.validate_response(schema.list_services, resp, body)
         return resp, body['services']
 
     def enable_service(self, host_name, binary):
diff --git a/tempest/services/compute/json/volumes_extensions_client.py b/tempest/services/compute/json/volumes_extensions_client.py
index 5ef11ed..451dbac 100644
--- a/tempest/services/compute/json/volumes_extensions_client.py
+++ b/tempest/services/compute/json/volumes_extensions_client.py
@@ -17,6 +17,7 @@
 import time
 import urllib
 
+from tempest.api_schema.compute.v2 import volumes as schema
 from tempest.common import rest_client
 from tempest import config
 from tempest import exceptions
@@ -58,6 +59,7 @@
         url = "os-volumes/%s" % str(volume_id)
         resp, body = self.get(url)
         body = json.loads(body)
+        self.validate_response(schema.get_volume, resp, body)
         return resp, body['volume']
 
     def create_volume(self, size, **kwargs):
diff --git a/tempest/services/compute/v3/json/agents_client.py b/tempest/services/compute/v3/json/agents_client.py
new file mode 100644
index 0000000..6893af2
--- /dev/null
+++ b/tempest/services/compute/v3/json/agents_client.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.
+
+import json
+import urllib
+
+from tempest.common import rest_client
+from tempest import config
+
+CONF = config.CONF
+
+
+class AgentsV3ClientJSON(rest_client.RestClient):
+
+    def __init__(self, auth_provider):
+        super(AgentsV3ClientJSON, self).__init__(auth_provider)
+        self.service = CONF.compute.catalog_v3_type
+
+    def list_agents(self, params=None):
+        """List all agent builds."""
+        url = 'os-agents'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        return resp, self._parse_resp(body)
+
+    def create_agent(self, **kwargs):
+        """Create an agent build."""
+        post_body = json.dumps({'agent': kwargs})
+        resp, body = self.post('os-agents', post_body)
+        return resp, self._parse_resp(body)
+
+    def delete_agent(self, agent_id):
+        """Delete an existing agent build."""
+        return self.delete('os-agents/%s' % str(agent_id))
+
+    def update_agent(self, agent_id, **kwargs):
+        """Update an agent build."""
+        put_body = json.dumps({'agent': kwargs})
+        resp, body = self.put('os-agents/%s' % str(agent_id), put_body)
+        return resp, self._parse_resp(body)
diff --git a/tempest/services/compute/v3/json/quotas_client.py b/tempest/services/compute/v3/json/quotas_client.py
index 32e31a3..5bfe67e 100644
--- a/tempest/services/compute/v3/json/quotas_client.py
+++ b/tempest/services/compute/v3/json/quotas_client.py
@@ -96,3 +96,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 256a730..92eb09b 100644
--- a/tempest/services/compute/v3/json/servers_client.py
+++ b/tempest/services/compute/v3/json/servers_client.py
@@ -384,6 +384,10 @@
         """Un-shelves the provided server."""
         return self.action(server_id, 'unshelve', None, **kwargs)
 
+    def shelve_offload_server(self, server_id, **kwargs):
+        """Shelve-offload the provided server."""
+        return self.action(server_id, 'shelve_offload', None, **kwargs)
+
     def get_console_output(self, server_id, length):
         return self.action(server_id, 'get_console_output', 'output',
                            length=length)
diff --git a/tempest/services/compute/v3/json/services_client.py b/tempest/services/compute/v3/json/services_client.py
index b4e65a0..88c4d16 100644
--- a/tempest/services/compute/v3/json/services_client.py
+++ b/tempest/services/compute/v3/json/services_client.py
@@ -17,6 +17,7 @@
 import json
 import urllib
 
+from tempest.api_schema.compute import services as schema
 from tempest.common import rest_client
 from tempest import config
 
@@ -36,6 +37,7 @@
 
         resp, body = self.get(url)
         body = json.loads(body)
+        self.validate_response(schema.list_services, resp, body)
         return resp, body['services']
 
     def enable_service(self, host_name, binary):
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 b8b759f..85e481c 100644
--- a/tempest/services/compute/xml/quotas_client.py
+++ b/tempest/services/compute/xml/quotas_client.py
@@ -121,3 +121,7 @@
         body = xml_to_json(etree.fromstring(body))
         body = self._format_quota(body)
         return resp, body
+
+    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/xml/servers_client.py b/tempest/services/compute/xml/servers_client.py
index cd2cb06..1215b80 100644
--- a/tempest/services/compute/xml/servers_client.py
+++ b/tempest/services/compute/xml/servers_client.py
@@ -227,6 +227,10 @@
         """Un-shelves the provided server."""
         return self.action(server_id, 'unshelve', None, **kwargs)
 
+    def shelve_offload_server(self, server_id, **kwargs):
+        """Shelve-offload the provided server."""
+        return self.action(server_id, 'shelveOffload', None, **kwargs)
+
     def reset_state(self, server_id, state='error'):
         """Resets the state of a server to active/error."""
         return self.action(server_id, 'os-resetState', None, state=state)
@@ -641,3 +645,8 @@
     def inject_network_info(self, server_id, **kwargs):
         """Inject the Network Info into server"""
         return self.action(server_id, 'injectNetworkInfo', None, **kwargs)
+
+    def get_vnc_console(self, server_id, console_type):
+        """Get URL of VNC console."""
+        return self.action(server_id, "os-getVNCConsole",
+                           "console", type=console_type)
diff --git a/tempest/services/database/json/flavors_client.py b/tempest/services/database/json/flavors_client.py
index 1a8a4c1..2ec0405 100644
--- a/tempest/services/database/json/flavors_client.py
+++ b/tempest/services/database/json/flavors_client.py
@@ -13,9 +13,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import urllib
+
 from tempest.common import rest_client
 from tempest import config
-import urllib
 
 CONF = config.CONF
 
diff --git a/tempest/services/identity/json/identity_client.py b/tempest/services/identity/json/identity_client.py
index 349a9e9..9a31540 100644
--- a/tempest/services/identity/json/identity_client.py
+++ b/tempest/services/identity/json/identity_client.py
@@ -172,6 +172,11 @@
         resp, body = self.put('users/%s/enabled' % user_id, put_body)
         return resp, self._parse_resp(body)
 
+    def get_token(self, token_id):
+        """Get token details."""
+        resp, body = self.get("tokens/%s" % token_id)
+        return resp, self._parse_resp(body)
+
     def delete_token(self, token_id):
         """Delete a token."""
         return self.delete("tokens/%s" % token_id)
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/network/json/network_client.py b/tempest/services/network/json/network_client.py
index d8c0979..a804e8e 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -163,32 +163,6 @@
         body = json.loads(body)
         return resp, body
 
-    def create_member(self, address, protocol_port, pool_id):
-        post_body = {
-            "member": {
-                "protocol_port": protocol_port,
-                "pool_id": pool_id,
-                "address": address
-            }
-        }
-        body = json.dumps(post_body)
-        uri = '%s/lb/members' % (self.uri_prefix)
-        resp, body = self.post(uri, body)
-        body = json.loads(body)
-        return resp, body
-
-    def update_member(self, admin_state_up, member_id):
-        put_body = {
-            "member": {
-                "admin_state_up": admin_state_up
-            }
-        }
-        body = json.dumps(put_body)
-        uri = '%s/lb/members/%s' % (self.uri_prefix, member_id)
-        resp, body = self.put(uri, body)
-        body = json.loads(body)
-        return resp, body
-
     def associate_health_monitor_with_pool(self, health_monitor_id,
                                            pool_id):
         post_body = {
diff --git a/tempest/services/network/network_client_base.py b/tempest/services/network/network_client_base.py
index f1bf548..41a7aa4 100644
--- a/tempest/services/network/network_client_base.py
+++ b/tempest/services/network/network_client_base.py
@@ -10,9 +10,11 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import time
 import urllib
 
 from tempest import config
+from tempest import exceptions
 
 CONF = config.CONF
 
@@ -54,6 +56,8 @@
         self.rest_client.service = CONF.network.catalog_type
         self.version = '2.0'
         self.uri_prefix = "v%s" % (self.version)
+        self.build_timeout = CONF.network.build_timeout
+        self.build_interval = CONF.network.build_interval
 
     def get_rest_client(self, auth_provider):
         raise NotImplementedError
@@ -189,3 +193,23 @@
         resp, body = self.post(uri, body)
         body = {'ports': self.deserialize_list(body)}
         return resp, body
+
+    def wait_for_resource_deletion(self, resource_type, id):
+        """Waits for a resource to be deleted."""
+        start_time = int(time.time())
+        while True:
+            if self.is_resource_deleted(resource_type, id):
+                return
+            if int(time.time()) - start_time >= self.build_timeout:
+                raise exceptions.TimeoutException
+            time.sleep(self.build_interval)
+
+    def is_resource_deleted(self, resource_type, id):
+        method = 'show_' + resource_type
+        try:
+            getattr(self, method)(id)
+        except AttributeError:
+            raise Exception("Unknown resource type %s " % resource_type)
+        except exceptions.NotFound:
+            return True
+        return False
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index daa60da..2a5083c 100644
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -23,7 +23,8 @@
 
     # list of plurals used for xml serialization
     PLURALS = ['dns_nameservers', 'host_routes', 'allocation_pools',
-               'fixed_ips', 'extensions', 'extra_dhcp_opts']
+               'fixed_ips', 'extensions', 'extra_dhcp_opts', 'pools',
+               'health_monitors', 'vips']
 
     def get_rest_client(self, auth_provider):
         rc = rest_client.RestClient(auth_provider)
@@ -92,28 +93,6 @@
             root.add_attr('xmlns:%s' % element,
                           common.NEUTRON_NAMESPACES[element])
 
-    def create_member(self, address, protocol_port, pool_id):
-        uri = '%s/lb/members' % (self.uri_prefix)
-        post_body = common.Element("member")
-        p1 = common.Element("address", address)
-        p2 = common.Element("protocol_port", protocol_port)
-        p3 = common.Element("pool_id", pool_id)
-        post_body.append(p1)
-        post_body.append(p2)
-        post_body.append(p3)
-        resp, body = self.post(uri, str(common.Document(post_body)))
-        body = _root_tag_fetcher_and_xml_to_json_parse(body)
-        return resp, body
-
-    def update_member(self, admin_state_up, member_id):
-        uri = '%s/lb/members/%s' % (self.uri_prefix, str(member_id))
-        put_body = common.Element("member")
-        p2 = common.Element("admin_state_up", admin_state_up)
-        put_body.append(p2)
-        resp, body = self.put(uri, str(common.Document(put_body)))
-        body = _root_tag_fetcher_and_xml_to_json_parse(body)
-        return resp, body
-
     def associate_health_monitor_with_pool(self, health_monitor_id,
                                            pool_id):
         uri = '%s/lb/pools/%s/health_monitors' % (self.uri_prefix,
diff --git a/tempest/services/queuing/__init__.py b/tempest/services/queuing/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/queuing/__init__.py
diff --git a/tempest/services/queuing/json/__init__.py b/tempest/services/queuing/json/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/queuing/json/__init__.py
diff --git a/tempest/services/queuing/json/queuing_client.py b/tempest/services/queuing/json/queuing_client.py
new file mode 100644
index 0000000..4a0c495
--- /dev/null
+++ b/tempest/services/queuing/json/queuing_client.py
@@ -0,0 +1,58 @@
+# Copyright (c) 2014 Rackspace, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import json
+
+from tempest.common import rest_client
+from tempest import config
+
+CONF = config.CONF
+
+
+class QueuingClientJSON(rest_client.RestClient):
+
+    def __init__(self, auth_provider):
+        super(QueuingClientJSON, self).__init__(auth_provider)
+        self.service = CONF.queuing.catalog_type
+        self.version = '1'
+        self.uri_prefix = 'v{0}'.format(self.version)
+
+    def list_queues(self):
+        uri = '{0}/queues'.format(self.uri_prefix)
+        resp, body = self.get(uri)
+        body = json.loads(body)
+        return resp, body
+
+    def create_queue(self, queue_name):
+        uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
+        resp, body = self.put(uri, body=None)
+        return resp, body
+
+    def get_queue(self, queue_name):
+        uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
+        resp, body = self.get(uri)
+        body = json.loads(body)
+        return resp, body
+
+    def head_queue(self, queue_name):
+        uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
+        resp, body = self.head(uri)
+        body = json.loads(body)
+        return resp, body
+
+    def delete_queue(self, queue_name):
+        uri = '{0}/queues/{1}'.format(self.uri_prefix, queue_name)
+        resp = self.delete(uri)
+        return resp
diff --git a/tempest/stress/actions/ssh_floating.py b/tempest/stress/actions/ssh_floating.py
index a34a20d..c330165 100644
--- a/tempest/stress/actions/ssh_floating.py
+++ b/tempest/stress/actions/ssh_floating.py
@@ -69,7 +69,7 @@
         servers_client = self.manager.servers_client
         self.logger.info("creating %s" % name)
         vm_args = self.vm_extra_args.copy()
-        vm_args['security_groups'] = [{'name': self.sec_grp}]
+        vm_args['security_groups'] = [self.sec_grp]
         resp, server = servers_client.create_server(name, self.image,
                                                     self.flavor,
                                                     **vm_args)
@@ -90,16 +90,15 @@
         sec_grp_cli = self.manager.security_groups_client
         s_name = data_utils.rand_name('sec_grp-')
         s_description = data_utils.rand_name('desc-')
-        _, _sec_grp = sec_grp_cli.create_security_group(s_name,
-                                                        s_description)
-        self.sec_grp = _sec_grp['id']
+        _, self.sec_grp = sec_grp_cli.create_security_group(s_name,
+                                                            s_description)
         create_rule = sec_grp_cli.create_security_group_rule
-        create_rule(self.sec_grp, 'tcp', 22, 22)
-        create_rule(self.sec_grp, 'icmp', -1, -1)
+        create_rule(self.sec_grp['id'], 'tcp', 22, 22)
+        create_rule(self.sec_grp['id'], 'icmp', -1, -1)
 
     def _destroy_sec_grp(self):
         sec_grp_cli = self.manager.security_groups_client
-        sec_grp_cli.delete_security_group(self.sec_grp)
+        sec_grp_cli.delete_security_group(self.sec_grp['id'])
 
     def _create_floating_ip(self):
         floating_cli = self.manager.floating_ips_client
diff --git a/tempest/stress/cleanup.py b/tempest/stress/cleanup.py
index b46de35..2587331 100644
--- a/tempest/stress/cleanup.py
+++ b/tempest/stress/cleanup.py
@@ -45,6 +45,16 @@
         except Exception:
             pass
 
+    secgrp_client = admin_manager.security_groups_client
+    _, secgrp = secgrp_client.list_security_groups({"all_tenants": True})
+    secgrp_del = [grp for grp in secgrp if grp['name'] != 'default']
+    LOG.info("Cleanup::remove %s Security Group" % len(secgrp_del))
+    for g in secgrp_del:
+        try:
+            secgrp_client.delete_security_group(g['id'])
+        except Exception:
+            pass
+
     _, floating_ips = admin_manager.floating_ips_client.list_floating_ips()
     LOG.info("Cleanup::remove %s floating ips" % len(floating_ips))
     for f in floating_ips:
diff --git a/tempest/test.py b/tempest/test.py
index 2125047..75eb6be 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -26,6 +26,8 @@
 import testresources
 import testtools
 
+from oslo.config import cfg
+
 from tempest import clients
 import tempest.common.generator.valid_generator as valid
 from tempest.common import isolated_creds
@@ -64,6 +66,25 @@
     return decorator
 
 
+def safe_setup(f):
+    """A decorator used to wrap the setUpClass for cleaning up resources
+       when setUpClass failed.
+    """
+
+    def decorator(cls):
+            try:
+                f(cls)
+            except Exception as se:
+                LOG.exception("setUpClass failed: %s" % se)
+                try:
+                    cls.tearDownClass()
+                except Exception as te:
+                    LOG.exception("tearDownClass failed: %s" % te)
+                raise se
+
+    return decorator
+
+
 def services(*args, **kwargs):
     """A decorator used to set an attr for each service used in a test case
 
@@ -199,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)
 
@@ -353,6 +372,12 @@
                 'subnet': subnet,
                 'dhcp': dhcp}
 
+    def assertEmpty(self, list, msg=None):
+        self.assertTrue(len(list) == 0, msg)
+
+    def assertNotEmpty(self, list, msg=None):
+        self.assertTrue(len(list) > 0, msg)
+
 
 class NegativeAutoTest(BaseTestCase):
 
@@ -363,6 +388,9 @@
         super(NegativeAutoTest, cls).setUpClass()
         os = cls.get_client_manager()
         cls.client = os.negative_client
+        os_admin = clients.AdminManager(interface=cls._interface,
+                                        service=cls._service)
+        cls.admin_client = os_admin.negative_client
 
     @staticmethod
     def load_schema(file):
@@ -401,7 +429,17 @@
         """
         description = NegativeAutoTest.load_schema(description_file)
         LOG.debug(description)
-        generator = importutils.import_class(CONF.negative.test_generator)()
+
+        # NOTE(mkoderer): since this will be executed on import level the
+        # config doesn't have to be in place (e.g. for the pep8 job).
+        # In this case simply return.
+        try:
+            generator = importutils.import_class(
+                CONF.negative.test_generator)()
+        except cfg.ConfigFilesNotFoundError:
+            LOG.critical(
+                "Tempest config not found. Test scenarios aren't created")
+            return
         generator.validate_schema(description)
         schema = description.get("json-schema", None)
         resources = description.get("resources", [])
@@ -418,10 +456,13 @@
                                              "expected_result": expected_result
                                              }))
         if schema is not None:
-            for invalid in generator.generate(schema):
-                scenario_list.append((invalid[0],
-                                      {"schema": invalid[1],
-                                       "expected_result": invalid[2]}))
+            for name, schema, expected_result in generator.generate(schema):
+                if (expected_result is None and
+                    "default_result_code" in description):
+                    expected_result = description["default_result_code"]
+                scenario_list.append((name,
+                                      {"schema": schema,
+                                       "expected_result": expected_result}))
         LOG.debug(scenario_list)
         return scenario_list
 
@@ -470,8 +511,12 @@
         elif hasattr(self, "schema"):
             new_url, body = self._http_arguments(self.schema, url, method)
 
-        resp, resp_body = self.client.send_request(method, new_url,
-                                                   resources, body=body)
+        if "admin_client" in description and description["admin_client"]:
+            client = self.admin_client
+        else:
+            client = self.client
+        resp, resp_body = client.send_request(method, new_url,
+                                              resources, body=body)
         self._check_negative_response(resp.status, resp_body)
 
     def _http_arguments(self, json_dict, url, method):
diff --git a/tempest/tests/common/__init__.py b/tempest/tests/common/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/tests/common/__init__.py
diff --git a/tempest/tests/common/utils/__init__.py b/tempest/tests/common/utils/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/tests/common/utils/__init__.py
diff --git a/tempest/tests/common/utils/test_data_utils.py b/tempest/tests/common/utils/test_data_utils.py
new file mode 100644
index 0000000..7aafdb2
--- /dev/null
+++ b/tempest/tests/common/utils/test_data_utils.py
@@ -0,0 +1,77 @@
+# 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 data_utils
+from tempest.tests import base
+
+
+class TestDataUtils(base.TestCase):
+
+    def test_rand_uuid(self):
+        actual = data_utils.rand_uuid()
+        self.assertIsInstance(actual, str)
+        self.assertRegexpMatches(actual, "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]"
+                                         "{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
+        actual2 = data_utils.rand_uuid()
+        self.assertNotEqual(actual, actual2)
+
+    def test_rand_uuid_hex(self):
+        actual = data_utils.rand_uuid_hex()
+        self.assertIsInstance(actual, str)
+        self.assertRegexpMatches(actual, "^[0-9a-f]{32}$")
+
+        actual2 = data_utils.rand_uuid_hex()
+        self.assertNotEqual(actual, actual2)
+
+    def test_rand_name(self):
+        actual = data_utils.rand_name()
+        self.assertIsInstance(actual, str)
+        actual2 = data_utils.rand_name()
+        self.assertNotEqual(actual, actual2)
+
+        actual = data_utils.rand_name('foo')
+        self.assertTrue(actual.startswith('foo'))
+        actual2 = data_utils.rand_name('foo')
+        self.assertTrue(actual.startswith('foo'))
+        self.assertNotEqual(actual, actual2)
+
+    def test_rand_int(self):
+        actual = data_utils.rand_int_id()
+        self.assertIsInstance(actual, int)
+
+        actual2 = data_utils.rand_int_id()
+        self.assertNotEqual(actual, actual2)
+
+    def test_rand_mac_address(self):
+        actual = data_utils.rand_mac_address()
+        self.assertIsInstance(actual, str)
+        self.assertRegexpMatches(actual, "^([0-9a-f][0-9a-f]:){5}"
+                                         "[0-9a-f][0-9a-f]$")
+
+        actual2 = data_utils.rand_mac_address()
+        self.assertNotEqual(actual, actual2)
+
+    def test_parse_image_id(self):
+        actual = data_utils.parse_image_id("/foo/bar/deadbeaf")
+        self.assertEqual("deadbeaf", actual)
+
+    def test_arbitrary_string(self):
+        actual = data_utils.arbitrary_string()
+        self.assertEqual(actual, "test")
+        actual = data_utils.arbitrary_string(size=30, base_text="abc")
+        self.assertEqual(actual, "abc" * (30 / len("abc")))
+        actual = data_utils.arbitrary_string(size=5, base_text="deadbeaf")
+        self.assertEqual(actual, "deadb")
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..4c23fbd 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())
 
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/tempest/tests/test_waiters.py b/tempest/tests/test_waiters.py
new file mode 100644
index 0000000..1f9825e
--- /dev/null
+++ b/tempest/tests/test_waiters.py
@@ -0,0 +1,49 @@
+# 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 time
+
+import mock
+
+from tempest.common import waiters
+from tempest import exceptions
+from tempest.tests import base
+
+
+class TestImageWaiters(base.TestCase):
+    def setUp(self):
+        super(TestImageWaiters, self).setUp()
+        self.client = mock.MagicMock()
+        self.client.build_timeout = 1
+        self.client.build_interval = 1
+
+    def test_wait_for_image_status(self):
+        self.client.get_image.return_value = (None, {'status': 'active'})
+        start_time = int(time.time())
+        waiters.wait_for_image_status(self.client, 'fake_image_id', 'active')
+        end_time = int(time.time())
+        # Ensure waiter returns before build_timeout
+        self.assertTrue((end_time - start_time) < 10)
+
+    def test_wait_for_image_status_timeout(self):
+        self.client.get_image.return_value = (None, {'status': 'saving'})
+        self.assertRaises(exceptions.TimeoutException,
+                          waiters.wait_for_image_status,
+                          self.client, 'fake_image_id', 'active')
+
+    def test_wait_for_image_status_error_on_image_create(self):
+        self.client.get_image.return_value = (None, {'status': 'ERROR'})
+        self.assertRaises(exceptions.AddImageException,
+                          waiters.wait_for_image_status,
+                          self.client, 'fake_image_id', 'active')
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 10d421e..4c39f78 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -108,6 +108,9 @@
     CODE_RE = '.*'  # regexp makes sense in group match
 
     def match(self, exc):
+        """:returns: Retruns with an error string if not matches,
+               returns with None when matches.
+        """
         if not isinstance(exc, exception.BotoServerError):
             return "%r not an BotoServerError instance" % exc
         LOG.info("Status: %s , error_code: %s", exc.status, exc.error_code)
@@ -119,6 +122,7 @@
             return ("Error code (%s) does not match" +
                     "the expected re pattern \"%s\"") %\
                    (exc.error_code, self.CODE_RE)
+        return None
 
 
 class ClientError(BotoExceptionMatcher):
@@ -313,7 +317,7 @@
             except ValueError:
                 return "_GONE"
             except exception.EC2ResponseError as exc:
-                if colusure_matcher.match(exc):
+                if colusure_matcher.match(exc) is None:
                     return "_GONE"
                 else:
                     raise
@@ -449,7 +453,7 @@
                 return "_GONE"
             except exception.EC2ResponseError as exc:
                 if cls.ec2_error_code.\
-                        client.InvalidInstanceID.NotFound.match(exc):
+                        client.InvalidInstanceID.NotFound.match(exc) is None:
                     return "_GONE"
                 # NOTE(afazekas): incorrect code,
                 # but the resource must be destoreyd
diff --git a/tempest/thirdparty/boto/test_ec2_instance_run.py b/tempest/thirdparty/boto/test_ec2_instance_run.py
index bbfbb79..e6a1638 100644
--- a/tempest/thirdparty/boto/test_ec2_instance_run.py
+++ b/tempest/thirdparty/boto/test_ec2_instance_run.py
@@ -40,7 +40,7 @@
                                     ": requires ami/aki/ari manifest")))
         cls.s3_client = cls.os.s3_client
         cls.ec2_client = cls.os.ec2api_client
-        cls.zone = cls.ec2_client.get_good_zone()
+        cls.zone = CONF.boto.aws_zone
         cls.materials_path = CONF.boto.s3_materials_path
         ami_manifest = CONF.boto.ami_manifest
         aki_manifest = CONF.boto.aki_manifest
diff --git a/tempest/thirdparty/boto/test_ec2_volumes.py b/tempest/thirdparty/boto/test_ec2_volumes.py
index 6a771e5..12dea18 100644
--- a/tempest/thirdparty/boto/test_ec2_volumes.py
+++ b/tempest/thirdparty/boto/test_ec2_volumes.py
@@ -38,7 +38,7 @@
             raise cls.skipException(skip_msg)
 
         cls.client = cls.os.ec2api_client
-        cls.zone = cls.client.get_good_zone()
+        cls.zone = CONF.boto.aws_zone
 
     @test.attr(type='smoke')
     def test_create_get_delete(self):