Merge "Add namespace properties client and tests"
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index 3c4e313..85aa301 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -40,6 +40,13 @@
                  for host in hosts_all if host['service'] == 'compute'])
         cls.host = hosts[0]
 
+    def _create_test_aggregate(self):
+        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
+        aggregate = (self.client.create_aggregate(name=aggregate_name)
+                     ['aggregate'])
+        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        return aggregate
+
     @test.attr(type=['negative'])
     @test.idempotent_id('86a1cb14-da37-4a70-b056-903fd56dfe29')
     def test_aggregate_create_as_user(self):
@@ -70,24 +77,16 @@
     @test.idempotent_id('9c23a291-b0b1-487b-b464-132e061151b3')
     def test_aggregate_create_with_existent_aggregate_name(self):
         # creating an aggregate with existent aggregate name is forbidden
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = self.client.create_aggregate(name=aggregate_name)
-        self.addCleanup(self.client.delete_aggregate,
-                        aggregate['aggregate']['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.Conflict,
                           self.client.create_aggregate,
-                          name=aggregate_name)
+                          name=aggregate['name'])
 
     @test.attr(type=['negative'])
     @test.idempotent_id('cd6de795-c15d-45f1-8d9e-813c6bb72a3d')
     def test_aggregate_delete_as_user(self):
         # Regular user is not allowed to delete an aggregate.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.Forbidden,
                           self.user_client.delete_aggregate,
                           aggregate['id'])
@@ -103,11 +102,7 @@
     @test.idempotent_id('557cad12-34c9-4ff4-95f0-22f0dfbaf7dc')
     def test_aggregate_get_details_as_user(self):
         # Regular user is not allowed to get aggregate details.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.Forbidden,
                           self.user_client.show_aggregate,
                           aggregate['id'])
@@ -136,12 +131,7 @@
             non_exist_host = data_utils.rand_name('nonexist_host')
             if non_exist_host not in hosts:
                 break
-
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.NotFound, self.client.add_host,
                           aggregate['id'], host=non_exist_host)
 
@@ -149,11 +139,7 @@
     @test.idempotent_id('7324c334-bd13-4c93-8521-5877322c3d51')
     def test_aggregate_add_host_as_user(self):
         # Regular user is not allowed to add a host to an aggregate.
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
-
+        aggregate = self._create_test_aggregate()
         self.assertRaises(lib_exc.Forbidden,
                           self.user_client.add_host,
                           aggregate['id'], host=self.host)
@@ -162,10 +148,7 @@
     @test.idempotent_id('19dd44e1-c435-4ee1-a402-88c4f90b5950')
     def test_aggregate_add_existent_host(self):
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate()
 
         self.client.add_host(aggregate['id'], host=self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'],
@@ -179,10 +162,8 @@
     def test_aggregate_remove_host_as_user(self):
         # Regular user is not allowed to remove a host from an aggregate.
         self.useFixture(fixtures.LockFixture('availability_zone'))
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate()
+
         self.client.add_host(aggregate['id'], host=self.host)
         self.addCleanup(self.client.remove_host, aggregate['id'],
                         host=self.host)
@@ -194,11 +175,7 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('95d6a6fa-8da9-4426-84d0-eec0329f2e4d')
     def test_aggregate_remove_nonexistent_host(self):
-        non_exist_host = data_utils.rand_name('nonexist_host')
-        aggregate_name = data_utils.rand_name(self.aggregate_name_prefix)
-        aggregate = (self.client.create_aggregate(name=aggregate_name)
-                     ['aggregate'])
-        self.addCleanup(self.client.delete_aggregate, aggregate['id'])
+        aggregate = self._create_test_aggregate()
 
         self.assertRaises(lib_exc.NotFound, self.client.remove_host,
-                          aggregate['id'], host=non_exist_host)
+                          aggregate['id'], host='nonexist_host')
diff --git a/tempest/api/compute/admin/test_auto_allocate_network.py b/tempest/api/compute/admin/test_auto_allocate_network.py
index ee8ed14..4eb3376 100644
--- a/tempest/api/compute/admin/test_auto_allocate_network.py
+++ b/tempest/api/compute/admin/test_auto_allocate_network.py
@@ -66,7 +66,6 @@
     @classmethod
     def setup_clients(cls):
         super(AutoAllocateNetworkTest, cls).setup_clients()
-        cls.servers_client = cls.servers_client
         cls.networks_client = cls.os.networks_client
         cls.routers_client = cls.os.routers_client
         cls.subnets_client = cls.os.subnets_client
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index b0ab9be..7eb4bbf 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -102,11 +102,10 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('440b9f3f-3c7f-4293-a106-0ceda350f8de')
     def test_flavor_unset_nonexistent_key(self):
-        nonexistent_key = data_utils.rand_name('flavor_key')
         self.assertRaises(lib_exc.NotFound,
                           self.client.unset_flavor_extra_spec,
                           self.flavor['id'],
-                          nonexistent_key)
+                          'nonexistent_key')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('329a7be3-54b2-48be-8052-bf2ce4afd898')
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
index e207aed..a4695b0 100644
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -17,6 +17,7 @@
 
 from tempest.api.compute import base
 from tempest import config
+from tempest.lib.common.utils import test_utils
 from tempest.lib import exceptions
 from tempest import test
 
@@ -54,12 +55,6 @@
                 raise exceptions.InvalidConfiguration(msg)
         return
 
-    def _delete_floating_ips_bulk(self, ip_range):
-        try:
-            self.client.delete_floating_ips_bulk(ip_range)
-        except Exception:
-            pass
-
     @test.idempotent_id('2c8f145f-8012-4cb8-ac7e-95a587f0e4ab')
     @test.services('network')
     def test_create_list_delete_floating_ips_bulk(self):
@@ -73,7 +68,8 @@
                                                      pool,
                                                      interface)
                 ['floating_ips_bulk_create'])
-        self.addCleanup(self._delete_floating_ips_bulk, self.ip_range)
+        self.addCleanup(test_utils.call_and_ignore_notfound_exc,
+                        self.client.delete_floating_ips_bulk, self.ip_range)
         self.assertEqual(self.ip_range, body['ip_range'])
         ips_list = self.client.list_floating_ips_bulk()['floating_ip_info']
         self.assertNotEqual(0, len(ips_list))
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index c270829..3821b22 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -13,7 +13,6 @@
 #    under the License.
 
 from tempest.api.compute import base
-from tempest.common.utils import data_utils
 from tempest.lib import exceptions as lib_exc
 from tempest import test
 
@@ -27,11 +26,13 @@
         cls.client = cls.os_adm.hosts_client
         cls.non_admin_client = cls.os.hosts_client
 
-    def _get_host_name(self):
-        hosts = self.client.list_hosts()['hosts']
-        self.assertGreaterEqual(len(hosts), 1)
-        hostname = hosts[0]['host_name']
-        return hostname
+    @classmethod
+    def resource_setup(cls):
+        super(HostsAdminNegativeTestJSON, cls).resource_setup()
+        hosts = cls.client.list_hosts()['hosts']
+        if not hosts:
+            raise lib_exc.NotFound("no host found")
+        cls.hostname = hosts[0]['host_name']
 
     @test.attr(type=['negative'])
     @test.idempotent_id('dd032027-0210-4d9c-860e-69b1b8deed5f')
@@ -42,27 +43,22 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('e75b0a1a-041f-47a1-8b4a-b72a6ff36d3f')
     def test_show_host_detail_with_nonexistent_hostname(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
         self.assertRaises(lib_exc.NotFound,
-                          self.client.show_host, nonexitent_hostname)
+                          self.client.show_host, 'nonexistent_hostname')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('19ebe09c-bfd4-4b7c-81a2-e2e0710f59cc')
     def test_show_host_detail_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.show_host,
-                          hostname)
+                          self.hostname)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('e40c72b1-0239-4ed6-ba21-81a184df1f7c')
     def test_update_host_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.update_host,
-                          hostname,
+                          self.hostname,
                           status='enable',
                           maintenance_mode='enable')
 
@@ -70,11 +66,9 @@
     @test.idempotent_id('fbe2bf3e-3246-4a95-a59f-94e4e298ec77')
     def test_update_host_with_invalid_status(self):
         # 'status' can only be 'enable' or 'disable'
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.BadRequest,
                           self.client.update_host,
-                          hostname,
+                          self.hostname,
                           status='invalid',
                           maintenance_mode='enable')
 
@@ -82,11 +76,9 @@
     @test.idempotent_id('ab1e230e-5e22-41a9-8699-82b9947915d4')
     def test_update_host_with_invalid_maintenance_mode(self):
         # 'maintenance_mode' can only be 'enable' or 'disable'
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.BadRequest,
                           self.client.update_host,
-                          hostname,
+                          self.hostname,
                           status='enable',
                           maintenance_mode='invalid')
 
@@ -94,73 +86,57 @@
     @test.idempotent_id('0cd85f75-6992-4a4a-b1bd-d11e37fd0eee')
     def test_update_host_without_param(self):
         # 'status' or 'maintenance_mode' needed for host update
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.BadRequest,
                           self.client.update_host,
-                          hostname)
+                          self.hostname)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('23c92146-2100-4d68-b2d6-c7ade970c9c1')
     def test_update_nonexistent_host(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
-
         self.assertRaises(lib_exc.NotFound,
                           self.client.update_host,
-                          nonexitent_hostname,
+                          'nonexistent_hostname',
                           status='enable',
                           maintenance_mode='enable')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('0d981ac3-4320-4898-b674-82b61fbb60e4')
     def test_startup_nonexistent_host(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
-
         self.assertRaises(lib_exc.NotFound,
                           self.client.startup_host,
-                          nonexitent_hostname)
+                          'nonexistent_hostname')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('9f4ebb7e-b2ae-4e5b-a38f-0fd1bb0ddfca')
     def test_startup_host_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.startup_host,
-                          hostname)
+                          self.hostname)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('9e637444-29cf-4244-88c8-831ae82c31b6')
     def test_shutdown_nonexistent_host(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
-
         self.assertRaises(lib_exc.NotFound,
                           self.client.shutdown_host,
-                          nonexitent_hostname)
+                          'nonexistent_hostname')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('a803529c-7e3f-4d3c-a7d6-8e1c203d27f6')
     def test_shutdown_host_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.shutdown_host,
-                          hostname)
+                          self.hostname)
 
     @test.attr(type=['negative'])
     @test.idempotent_id('f86bfd7b-0b13-4849-ae29-0322e83ee58b')
     def test_reboot_nonexistent_host(self):
-        nonexitent_hostname = data_utils.rand_name('rand_hostname')
-
         self.assertRaises(lib_exc.NotFound,
                           self.client.reboot_host,
-                          nonexitent_hostname)
+                          'nonexistent_hostname')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('02d79bb9-eb57-4612-abf6-2cb38897d2f8')
     def test_reboot_host_with_non_admin_user(self):
-        hostname = self._get_host_name()
-
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.reboot_host,
-                          hostname)
+                          self.hostname)
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index 220ea39..0f35e14 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.py
@@ -122,12 +122,10 @@
     @test.attr(type=['negative'])
     @test.idempotent_id('19a45cc1-1000-4055-b6d2-28e8b2ec4faa')
     def test_search_nonexistent_hypervisor(self):
-        nonexistent_hypervisor_name = data_utils.rand_name('test_hypervisor')
-
         self.assertRaises(
             lib_exc.NotFound,
             self.client.search_hypervisor,
-            nonexistent_hypervisor_name)
+            'nonexistent_hypervisor_name')
 
     @test.attr(type=['negative'])
     @test.idempotent_id('5b6a6c79-5dc1-4fa5-9c58-9c8085948e74')
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 7d97ce2..ce0adb4 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -74,7 +74,8 @@
                          'ram': 10240, 'floating_ips': 20, 'fixed_ips': 10,
                          'key_pairs': 200, 'injected_file_path_bytes': 512,
                          'instances': 20, 'security_group_rules': 20,
-                         'cores': 2, 'security_groups': 20}
+                         'cores': 2, 'security_groups': 20,
+                         'server_groups': 20, 'server_group_members': 20}
         # Update limits for all quota resources
         quota_set = self.adm_client.update_quota_set(
             self.demo_tenant_id,
@@ -82,13 +83,6 @@
             **new_quota_set)['quota_set']
 
         default_quota_set.pop('id')
-        # NOTE(PhilDay) The following is safe as we're not updating these
-        # two quota values yet.  Once the Nova change to add these is merged
-        # and the client updated to support them this can be removed
-        if 'server_groups' in default_quota_set:
-            default_quota_set.pop('server_groups')
-        if 'server_group_members' in default_quota_set:
-            default_quota_set.pop('server_group_members')
         self.addCleanup(self.adm_client.update_quota_set,
                         self.demo_tenant_id, **default_quota_set)
         for quota in new_quota_set:
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index d6aba5b..015e14d 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -40,6 +40,17 @@
         # tenant most of them should be skipped if we can't do that
         cls.demo_tenant_id = cls.client.tenant_id
 
+    def _update_quota(self, quota_item, quota_value):
+        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
+                     ['quota_set'])
+        default_quota_value = quota_set[quota_item]
+
+        self.adm_client.update_quota_set(self.demo_tenant_id,
+                                         force=True,
+                                         **{quota_item: quota_value})
+        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
+                        **{quota_item: default_quota_value})
+
     @test.attr(type=['negative'])
     @test.idempotent_id('733abfe8-166e-47bb-8363-23dbd7ff3476')
     def test_update_quota_normal_user(self):
@@ -54,17 +65,7 @@
     @test.idempotent_id('91058876-9947-4807-9f22-f6eb17140d9b')
     def test_create_server_when_cpu_quota_is_full(self):
         # Disallow server creation when tenant's vcpu quota is full
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_vcpu_quota = quota_set['cores']
-        vcpu_quota = 0  # Set the quota to zero to conserve resources
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         cores=vcpu_quota)
-
-        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
-                        cores=default_vcpu_quota)
+        self._update_quota('cores', 0)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
@@ -72,17 +73,7 @@
     @test.idempotent_id('6fdd7012-584d-4327-a61c-49122e0d5864')
     def test_create_server_when_memory_quota_is_full(self):
         # Disallow server creation when tenant's memory quota is full
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_mem_quota = quota_set['ram']
-        mem_quota = 0  # Set the quota to zero to conserve resources
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         ram=mem_quota)
-
-        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
-                        ram=default_mem_quota)
+        self._update_quota('ram', 0)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
@@ -90,16 +81,7 @@
     @test.idempotent_id('7c6be468-0274-449a-81c3-ac1c32ee0161')
     def test_create_server_when_instances_quota_is_full(self):
         # Once instances quota limit is reached, disallow server creation
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_instances_quota = quota_set['instances']
-        instances_quota = 0  # Set quota to zero to disallow server creation
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         instances=instances_quota)
-        self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
-                        instances=default_instances_quota)
+        self._update_quota('instances', 0)
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
@@ -109,22 +91,10 @@
     @test.services('network')
     def test_security_groups_exceed_limit(self):
         # Negative test: Creation Security Groups over limit should FAIL
-
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_sg_quota = quota_set['security_groups']
-
         # Set the quota to number of used security groups
         sg_quota = self.limits_client.show_limits()['limits']['absolute'][
             'totalSecurityGroupsUsed']
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         security_groups=sg_quota)
-
-        self.addCleanup(self.adm_client.update_quota_set,
-                        self.demo_tenant_id,
-                        security_groups=default_sg_quota)
+        self._update_quota('security_groups', sg_quota)
 
         # Check we cannot create anymore
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
@@ -141,19 +111,7 @@
     def test_security_groups_rules_exceed_limit(self):
         # Negative test: Creation of Security Group Rules should FAIL
         # when we reach limit maxSecurityGroupRules
-
-        quota_set = (self.adm_client.show_quota_set(self.demo_tenant_id)
-                     ['quota_set'])
-        default_sg_rules_quota = quota_set['security_group_rules']
-        sg_rules_quota = 0  # Set the quota to zero to conserve resources
-
-        self.adm_client.update_quota_set(self.demo_tenant_id,
-                                         force=True,
-                                         security_group_rules=sg_rules_quota)
-
-        self.addCleanup(self.adm_client.update_quota_set,
-                        self.demo_tenant_id,
-                        security_group_rules=default_sg_rules_quota)
+        self._update_quota('security_group_rules', 0)
 
         s_name = data_utils.rand_name('securitygroup')
         s_description = data_utils.rand_name('description')
diff --git a/tempest/api/compute/images/test_images.py b/tempest/api/compute/images/test_images.py
index 154d717..a06f4a7 100644
--- a/tempest/api/compute/images/test_images.py
+++ b/tempest/api/compute/images/test_images.py
@@ -38,7 +38,6 @@
     def setup_clients(cls):
         super(ImagesTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
-        cls.servers_client = cls.servers_client
 
     @test.idempotent_id('aa06b52b-2db5-4807-b218-9441f75d74e3')
     def test_delete_saving_image(self):
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 8db094d..7035401 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -39,7 +39,6 @@
     def setup_clients(cls):
         super(ImagesNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
-        cls.servers_client = cls.servers_client
 
     @test.attr(type=['negative'])
     @test.idempotent_id('6cd5a89d-5b47-46a7-93bc-3916f0d84973')
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index fc6a20f..8342a3e 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -50,30 +50,6 @@
         cls.subnets_client = cls.os.subnets_client
         cls.ports_client = cls.os.ports_client
 
-    def wait_for_interface_status(self, server, port_id, status):
-        """Waits for an interface to reach a given status."""
-        body = (self.interfaces_client.show_interface(server, port_id)
-                ['interfaceAttachment'])
-        interface_status = body['port_state']
-        start = int(time.time())
-
-        while(interface_status != status):
-            time.sleep(self.build_interval)
-            body = (self.interfaces_client.show_interface(server, port_id)
-                    ['interfaceAttachment'])
-            interface_status = body['port_state']
-
-            timed_out = int(time.time()) - start >= self.build_timeout
-
-            if interface_status != status and timed_out:
-                message = ('Interface %s failed to reach %s status '
-                           '(current %s) within the required time (%s s).' %
-                           (port_id, status, interface_status,
-                            self.build_timeout))
-                raise lib_exc.TimeoutException(message)
-
-        return body
-
     # TODO(mriedem): move this into a common waiters utility module
     def wait_for_port_detach(self, port_id):
         """Waits for the port's device_id to be unset.
@@ -118,16 +94,16 @@
         server = self.create_test_server(wait_until='ACTIVE')
         ifs = (self.interfaces_client.list_interfaces(server['id'])
                ['interfaceAttachments'])
-        body = self.wait_for_interface_status(
-            server['id'], ifs[0]['port_id'], 'ACTIVE')
+        body = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], ifs[0]['port_id'], 'ACTIVE')
         ifs[0]['port_state'] = body['port_state']
         return server, ifs
 
     def _test_create_interface(self, server):
         iface = (self.interfaces_client.create_interface(server['id'])
                  ['interfaceAttachment'])
-        iface = self.wait_for_interface_status(
-            server['id'], iface['port_id'], 'ACTIVE')
+        iface = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface)
         return iface
 
@@ -135,8 +111,8 @@
         network_id = ifs[0]['net_id']
         iface = self.interfaces_client.create_interface(
             server['id'], net_id=network_id)['interfaceAttachment']
-        iface = self.wait_for_interface_status(
-            server['id'], iface['port_id'], 'ACTIVE')
+        iface = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface, network_id=network_id)
         return iface
 
@@ -147,8 +123,8 @@
         self.addCleanup(self.ports_client.delete_port, port_id)
         iface = self.interfaces_client.create_interface(
             server['id'], port_id=port_id)['interfaceAttachment']
-        iface = self.wait_for_interface_status(
-            server['id'], iface['port_id'], 'ACTIVE')
+        iface = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface, port_id=port_id)
         return iface
 
@@ -166,8 +142,8 @@
             server['id'], net_id=network_id,
             fixed_ips=fixed_ips)['interfaceAttachment']
         self.addCleanup(self.ports_client.delete_port, iface['port_id'])
-        iface = self.wait_for_interface_status(
-            server['id'], iface['port_id'], 'ACTIVE')
+        iface = waiters.wait_for_interface_status(
+            self.interfaces_client, server['id'], iface['port_id'], 'ACTIVE')
         self._check_interface(iface, fixed_ip=ip_list[0])
         return iface
 
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 50910ec..0a94d5e 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -13,8 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import logging
-
+from oslo_log import log as logging
 from six.moves.urllib import parse as urlparse
 import testtools
 
diff --git a/tempest/api/compute/servers/test_server_metadata.py b/tempest/api/compute/servers/test_server_metadata.py
index cb66e81..847b7a1 100644
--- a/tempest/api/compute/servers/test_server_metadata.py
+++ b/tempest/api/compute/servers/test_server_metadata.py
@@ -23,7 +23,6 @@
     def setup_clients(cls):
         super(ServerMetadataTestJSON, cls).setup_clients()
         cls.client = cls.servers_client
-        cls.quotas = cls.quotas_client
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index aae9101..62b8962 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -25,7 +25,6 @@
     def setup_clients(cls):
         super(ServerMetadataNegativeTestJSON, cls).setup_clients()
         cls.client = cls.servers_client
-        cls.quotas = cls.quotas_client
 
     @classmethod
     def resource_setup(cls):
@@ -134,7 +133,8 @@
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
         # will be raised while exceeding metadata items limit for
         # tenant.
-        quota_set = self.quotas.show_quota_set(self.tenant_id)['quota_set']
+        quota_set = self.quotas_client.show_quota_set(
+            self.tenant_id)['quota_set']
         quota_metadata = quota_set['metadata_items']
         if quota_metadata == -1:
             raise self.skipException("No limit for metadata_items")
diff --git a/tempest/api/compute/volumes/test_volume_snapshots.py b/tempest/api/compute/volumes/test_volume_snapshots.py
index 460c882..01718cc 100644
--- a/tempest/api/compute/volumes/test_volume_snapshots.py
+++ b/tempest/api/compute/volumes/test_volume_snapshots.py
@@ -13,6 +13,8 @@
 #    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
 from tempest.common import waiters
@@ -39,6 +41,8 @@
         cls.snapshots_client = cls.snapshots_extensions_client
 
     @test.idempotent_id('cd4ec87d-7825-450d-8040-6e2068f2da8f')
+    @testtools.skipUnless(CONF.volume_feature_enabled.snapshot,
+                          'Cinder volume snapshots are disabled')
     def test_volume_snapshot_create_get_list_delete(self):
         volume = self.create_volume()
         self.addCleanup(self.delete_volume, volume['id'])
diff --git a/tempest/api/compute/volumes/test_volumes_list.py b/tempest/api/compute/volumes/test_volumes_list.py
index c60fcca..7d76731 100644
--- a/tempest/api/compute/volumes/test_volumes_list.py
+++ b/tempest/api/compute/volumes/test_volumes_list.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from oslo_log import log as logging
+
 from tempest.api.compute import base
 from tempest.common.utils import data_utils
 from tempest.common import waiters
@@ -20,6 +22,7 @@
 from tempest import test
 
 CONF = config.CONF
+LOG = logging.getLogger(__name__)
 
 
 class VolumesTestJSON(base.BaseV2ComputeTest):
@@ -59,21 +62,16 @@
                 volume = cls.client.show_volume(volume['id'])['volume']
                 cls.volume_list.append(volume)
                 cls.volume_id_list.append(volume['id'])
-            except Exception:
+            except Exception as exc:
+                LOG.exception(exc)
                 if cls.volume_list:
                     # We could not create all the volumes, though we were able
                     # to create *some* of the volumes. This is typically
                     # because the backing file size of the volume group is
-                    # too small. So, here, we clean up whatever we did manage
-                    # to create and raise a SkipTest
+                    # too small.
                     for volume in cls.volume_list:
                         cls.delete_volume(volume['id'])
-                    msg = ("Failed to create ALL necessary volumes to run "
-                           "test. This typically means that the backing file "
-                           "size of the nova-volumes group is too small to "
-                           "create the 3 volumes needed by this test case")
-                    raise cls.skipException(msg)
-                raise
+                raise exc
 
     @classmethod
     def resource_cleanup(cls):
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index 5fe4cb3..c4041cb 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -66,7 +66,7 @@
 
     @test.attr(type=['negative'])
     @test.idempotent_id('131cb3a1-75cc-4d40-b4c3-1317f64719b0')
-    def test_create_volume_with_out_passing_size(self):
+    def test_create_volume_without_passing_size(self):
         # Negative: Should not be able to create volume without passing size
         # in request
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 5cf8084..42912f0 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -129,7 +129,6 @@
 
 
 class ListImagesTest(base.BaseV2ImageTest):
-    """Here we test the listing of image information"""
 
     @classmethod
     def resource_setup(cls):
@@ -157,23 +156,49 @@
         """
         size = random.randint(1024, 4096)
         image_file = six.BytesIO(data_utils.random_bytes(size))
+        tags = [data_utils.rand_name('tag'), data_utils.rand_name('tag')]
         image = cls.create_image(container_format=container_format,
                                  disk_format=disk_format,
-                                 visibility='private')
+                                 visibility='private',
+                                 tags=tags)
         cls.client.store_image_file(image['id'], data=image_file)
+        # Keep the data of one test image so it can be used to filter lists
+        cls.test_data = image
+        cls.test_data['size'] = size
 
         return image['id']
 
+
+class ListUserImagesTest(ListImagesTest):
+    """Here we test the listing of image information"""
+
     def _list_by_param_value_and_assert(self, params):
         """Perform list action with given params and validates result."""
-
+        # Retrieve the list of images that meet the filter
         images_list = self.client.list_images(params=params)['images']
         # Validating params of fetched images
+        msg = 'No images were found that met the filter criteria.'
+        self.assertNotEmpty(images_list, msg)
         for image in images_list:
             for key in params:
                 msg = "Failed to list images by %s" % key
                 self.assertEqual(params[key], image[key], msg)
 
+    def _list_sorted_by_image_size_and_assert(self, params, desc=False):
+        """Validate an image list that has been sorted by size
+
+        Perform list action with given params and validates the results are
+        sorted by image size in either ascending or descending order.
+        """
+        # Retrieve the list of images that meet the filter
+        images_list = self.client.list_images(params=params)['images']
+        # Validate that the list was fetched sorted accordingly
+        msg = 'No images were found that met the filter criteria.'
+        self.assertNotEmpty(images_list, msg)
+        sorted_list = [image['size'] for image in images_list]
+        msg = 'The list of images was not sorted correctly.'
+        self.assertEqual(sorted(sorted_list, reverse=desc), sorted_list, msg)
+
     @test.idempotent_id('1e341d7a-90a9-494c-b143-2cdf2aeb6aee')
     def test_list_no_params(self):
         # Simple test to see all fixture images returned
@@ -185,8 +210,8 @@
 
     @test.idempotent_id('9959ca1d-1aa7-4b7a-a1ea-0fff0499b37e')
     def test_list_images_param_container_format(self):
-        # Test to get all images with container_format='bare'
-        params = {"container_format": "bare"}
+        # Test to get all images with a specific container_format
+        params = {"container_format": self.test_data['container_format']}
         self._list_by_param_value_and_assert(params)
 
     @test.idempotent_id('4a4735a7-f22f-49b6-b0d9-66e1ef7453eb')
@@ -254,6 +279,37 @@
         params = {"owner": image['owner']}
         self._list_by_param_value_and_assert(params)
 
+    @test.idempotent_id('55c8f5f5-bfed-409d-a6d5-4caeda985d7b')
+    def test_list_images_param_name(self):
+        # Test to get images by name
+        params = {'name': self.test_data['name']}
+        self._list_by_param_value_and_assert(params)
+
+    @test.idempotent_id('aa8ac4df-cff9-418b-8d0f-dd9c67b072c9')
+    def test_list_images_param_tag(self):
+        # Test to get images matching a tag
+        params = {'tag': self.test_data['tags'][0]}
+        images_list = self.client.list_images(params=params)['images']
+        # Validating properties of fetched images
+        self.assertNotEmpty(images_list)
+        for image in images_list:
+            msg = ("The image {image_name} does not have the expected tag "
+                   "{expected_tag} among its tags: {observerd_tags}."
+                   .format(image_name=image['name'],
+                           expected_tag=self.test_data['tags'][0],
+                           observerd_tags=image['tags']))
+            self.assertIn(self.test_data['tags'][0], image['tags'], msg)
+
+    @test.idempotent_id('eeadce49-04e0-43b7-aec7-52535d903e7a')
+    def test_list_images_param_sort(self):
+        params = {'sort': 'size:desc'}
+        self._list_sorted_by_image_size_and_assert(params, desc=True)
+
+    @test.idempotent_id('9faaa0c2-c3a5-43e1-8f61-61c54b409a49')
+    def test_list_images_param_sort_key_dir(self):
+        params = {'sort_key': 'size', 'sort_dir': 'desc'}
+        self._list_sorted_by_image_size_and_assert(params, desc=True)
+
     @test.idempotent_id('622b925c-479f-4736-860d-adeaf13bc371')
     def test_get_image_schema(self):
         # Test to get image schema
@@ -267,3 +323,32 @@
         schema = "images"
         body = self.schemas_client.show_schema(schema)
         self.assertEqual("images", body['name'])
+
+
+class ListSharedImagesTest(ListImagesTest):
+    """Here we test the listing of a shared image information"""
+
+    credentials = ['primary', 'alt']
+
+    @classmethod
+    def setup_clients(cls):
+        super(ListSharedImagesTest, cls).setup_clients()
+        cls.image_member_client = cls.os.image_member_client_v2
+        cls.alt_img_client = cls.os_alt.image_client_v2
+
+    @test.idempotent_id('3fa50be4-8e38-4c02-a8db-7811bb780122')
+    def test_list_images_param_member_status(self):
+        # Share one of the images created with the alt user
+        self.image_member_client.create_image_member(
+            image_id=self.test_data['id'],
+            member=self.alt_img_client.tenant_id)
+        # Update the info on the test data so it remains accurate
+        self.test_data['updated_at'] = self.client.show_image(
+            self.test_data['id'])['updated_at']
+        # As an image consumer you need to provide the member_status parameter
+        # along with the visibility=shared parameter in order for it to show
+        # results
+        params = {'member_status': 'pending', 'visibility': 'shared'}
+        fetched_images = self.alt_img_client.list_images(params)['images']
+        self.assertEqual(1, len(fetched_images))
+        self.assertEqual(self.test_data['id'], fetched_images[0]['id'])
diff --git a/tempest/api/object_storage/test_container_services_negative.py b/tempest/api/object_storage/test_container_services_negative.py
index 7049db0..e6c53ec 100644
--- a/tempest/api/object_storage/test_container_services_negative.py
+++ b/tempest/api/object_storage/test_container_services_negative.py
@@ -92,47 +92,39 @@
     def test_get_metadata_headers_with_invalid_container_name(self):
         # Attempts to retrieve metadata headers with an invalid
         # container name.
-        invalid_name = data_utils.rand_name(name="TestInvalidContainer")
-
         self.assertRaises(exceptions.NotFound,
                           self.container_client.list_container_metadata,
-                          invalid_name)
+                          'invalid_container_name')
 
     @test.attr(type=["negative"])
     @test.idempotent_id('125a24fa-90a7-4cfc-b604-44e49d788390')
     def test_update_metadata_with_nonexistent_container_name(self):
         # Attempts to update metadata using a nonexistent container name.
-        nonexistent_name = data_utils.rand_name(
-            name="TestNonexistentContainer")
         metadata = {'animal': 'penguin'}
 
         self.assertRaises(exceptions.NotFound,
                           self.container_client.update_container_metadata,
-                          nonexistent_name, metadata)
+                          'nonexistent_container_name', metadata)
 
     @test.attr(type=["negative"])
     @test.idempotent_id('65387dbf-a0e2-4aac-9ddc-16eb3f1f69ba')
     def test_delete_with_nonexistent_container_name(self):
         # Attempts to delete metadata using a nonexistent container name.
-        nonexistent_name = data_utils.rand_name(
-            name="TestNonexistentContainer")
         metadata = {'animal': 'penguin'}
 
         self.assertRaises(exceptions.NotFound,
                           self.container_client.delete_container_metadata,
-                          nonexistent_name, metadata)
+                          'nonexistent_container_name', metadata)
 
     @test.attr(type=["negative"])
     @test.idempotent_id('14331d21-1e81-420a-beea-19cb5e5207f5')
     def test_list_all_container_objects_with_nonexistent_container(self):
         # Attempts to get a listing of all objects on a container
         # that doesn't exist.
-        nonexistent_name = data_utils.rand_name(
-            name="TestNonexistentContainer")
         params = {'limit': 9999, 'format': 'json'}
         self.assertRaises(exceptions.NotFound,
                           self.container_client.list_container_contents,
-                          nonexistent_name, params)
+                          'nonexistent_container_name', params)
 
     @test.attr(type=["negative"])
     @test.idempotent_id('86b2ab08-92d5-493d-acd2-85f0c848819e')
diff --git a/tempest/api/orchestration/stacks/test_neutron_resources.py b/tempest/api/orchestration/stacks/test_neutron_resources.py
index a3792b4..bffcb64 100644
--- a/tempest/api/orchestration/stacks/test_neutron_resources.py
+++ b/tempest/api/orchestration/stacks/test_neutron_resources.py
@@ -10,10 +10,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-
-import logging
-
 import netaddr
+from oslo_log import log as logging
 
 from tempest.api.orchestration import base
 from tempest.common.utils import data_utils
diff --git a/tempest/api/volume/admin/test_volume_types.py b/tempest/api/volume/admin/test_volume_types.py
index eb6500c..3098cab 100644
--- a/tempest/api/volume/admin/test_volume_types.py
+++ b/tempest/api/volume/admin/test_volume_types.py
@@ -51,8 +51,7 @@
                   'size': CONF.volume.volume_size}
 
         # Create volume
-        volume = self.volumes_client.create_volume(**params)['volume']
-        self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
+        volume = self.create_volume(**params)
         self.assertEqual(volume_types[0]['name'], volume["volume_type"])
         self.assertEqual(volume[self.name_field], vol_name,
                          "The created volume name is not equal "
diff --git a/tempest/api/volume/admin/v2/test_volume_type_access.py b/tempest/api/volume/admin/v2/test_volume_type_access.py
index 91ff5af..80dbf12 100644
--- a/tempest/api/volume/admin/v2/test_volume_type_access.py
+++ b/tempest/api/volume/admin/v2/test_volume_type_access.py
@@ -16,7 +16,6 @@
 import operator
 
 from tempest.api.volume import base
-from tempest.common import waiters
 from tempest import config
 from tempest.lib import exceptions as lib_exc
 from tempest import test
@@ -52,13 +51,7 @@
                         project=self.volumes_client.tenant_id)
 
         # Creating a volume from primary tenant
-        volume = self.volumes_client.create_volume(
-            volume_type=volume_type['id'],
-            size=CONF.volume.volume_size)['volume']
-        self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
-        waiters.wait_for_volume_status(self.volumes_client, volume['id'],
-                                       'available')
-
+        volume = self.create_volume(volume_type=volume_type['id'])
         # Validating the created volume is based on the volume type
         self.assertEqual(volume_type['name'], volume['volume_type'])
 
diff --git a/tempest/api/volume/admin/v3/test_user_messages.py b/tempest/api/volume/admin/v3/test_user_messages.py
index 39a5dfa..257a434 100755
--- a/tempest/api/volume/admin/v3/test_user_messages.py
+++ b/tempest/api/volume/admin/v3/test_user_messages.py
@@ -15,9 +15,7 @@
 
 from tempest.api.volume.v3 import base
 from tempest.common.utils import data_utils
-from tempest.common import waiters
 from tempest import config
-from tempest import exceptions
 from tempest import test
 
 CONF = config.CONF
@@ -47,21 +45,11 @@
                        'vendor_name': bad_vendor}
         vol_type_name = data_utils.rand_name(
             self.__class__.__name__ + '-volume-type')
-        bogus_type = self.admin_volume_types_client.create_volume_type(
-            name=vol_type_name,
-            extra_specs=extra_specs)['volume_type']
-        self.addCleanup(self.admin_volume_types_client.delete_volume_type,
-                        bogus_type['id'])
+        bogus_type = self.create_volume_type(
+            name=vol_type_name, extra_specs=extra_specs)
         params = {'volume_type': bogus_type['id'],
                   'size': CONF.volume.volume_size}
-        volume = self.volumes_client.create_volume(**params)['volume']
-        self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
-        try:
-            waiters.wait_for_volume_status(self.volumes_client, volume['id'],
-                                           'error')
-        except exceptions.VolumeBuildErrorException:
-            # Error state is expected and desired
-            pass
+        volume = self.create_volume(wait_until="error", **params)
         messages = self.messages_client.list_messages()['messages']
         message_id = None
         for message in messages:
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index b9aeb99..f32c84a 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -108,11 +108,20 @@
         super(BaseVolumeTest, cls).resource_cleanup()
 
     @classmethod
-    def create_volume(cls, **kwargs):
-        """Wrapper utility that returns a test volume."""
+    def create_volume(cls, wait_until='available', **kwargs):
+        """Wrapper utility that returns a test volume.
+
+           :param wait_until: wait till volume status.
+        """
         if 'size' not in kwargs:
             kwargs['size'] = CONF.volume.volume_size
 
+        if 'imageRef' in kwargs:
+            image = cls.compute_images_client.show_image(
+                kwargs['imageRef'])['image']
+            min_disk = image.get('minDisk')
+            kwargs['size'] = max(kwargs['size'], min_disk)
+
         name_field = cls.special_fields['name_field']
         if name_field not in kwargs:
             name = data_utils.rand_name(cls.__name__ + '-Volume')
@@ -120,8 +129,8 @@
 
         volume = cls.volumes_client.create_volume(**kwargs)['volume']
         cls.volumes.append(volume)
-        waiters.wait_for_volume_status(cls.volumes_client,
-                                       volume['id'], 'available')
+        waiters.wait_for_volume_status(cls.volumes_client, volume['id'],
+                                       wait_until)
         return volume
 
     @classmethod
@@ -148,6 +157,18 @@
         client.delete_volume(volume_id)
         client.wait_for_resource_deletion(volume_id)
 
+    def attach_volume(self, server_id, volume_id):
+        """Attachs a volume to a server"""
+        self.servers_client.attach_volume(
+            server_id, volumeId=volume_id,
+            device='/dev/%s' % CONF.compute.volume_device_name)
+        waiters.wait_for_volume_status(self.volumes_client,
+                                       volume_id, 'in-use')
+        self.addCleanup(waiters.wait_for_volume_status, self.volumes_client,
+                        volume_id, 'available')
+        self.addCleanup(self.servers_client.detach_volume, server_id,
+                        self.volume_origin['id'])
+
     @classmethod
     def clear_volumes(cls):
         for volume in cls.volumes:
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index fda0dda..6ed6b9c 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -62,7 +62,7 @@
 
     @test.attr(type=['negative'])
     @test.idempotent_id('9387686f-334f-4d31-a439-33494b9e2683')
-    def test_create_volume_with_out_passing_size(self):
+    def test_create_volume_without_passing_size(self):
         # Should not be able to create volume without passing size
         # in request
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
diff --git a/tempest/api/volume/test_volumes_snapshots.py b/tempest/api/volume/test_volumes_snapshots.py
index 3c05d3e..3c7a2c8 100644
--- a/tempest/api/volume/test_volumes_snapshots.py
+++ b/tempest/api/volume/test_volumes_snapshots.py
@@ -12,7 +12,6 @@
 
 from tempest.api.volume import base
 from tempest.common.utils import data_utils
-from tempest.common import waiters
 from tempest import config
 from tempest import test
 
@@ -46,21 +45,53 @@
         # Create a snapshot when volume status is in-use
         # Create a test instance
         server = self.create_server(wait_until='ACTIVE')
-        self.servers_client.attach_volume(
-            server['id'], volumeId=self.volume_origin['id'],
-            device='/dev/%s' % CONF.compute.volume_device_name)
-        waiters.wait_for_volume_status(self.volumes_client,
-                                       self.volume_origin['id'], 'in-use')
-        self.addCleanup(waiters.wait_for_volume_status, self.volumes_client,
-                        self.volume_origin['id'], 'available')
-        self.addCleanup(self.servers_client.detach_volume, server['id'],
-                        self.volume_origin['id'])
+        self.attach_volume(server['id'], self.volume_origin['id'])
+
         # Snapshot a volume even if it's attached to an instance
         snapshot = self.create_snapshot(self.volume_origin['id'],
                                         force=True)
         # Delete the snapshot
         self.cleanup_snapshot(snapshot)
 
+    @test.idempotent_id('8567b54c-4455-446d-a1cf-651ddeaa3ff2')
+    @test.services('compute')
+    def test_snapshot_delete_with_volume_in_use(self):
+        # Create a test instance
+        server = self.create_server(wait_until='ACTIVE')
+        self.attach_volume(server['id'], self.volume_origin['id'])
+
+        # Snapshot a volume attached to an instance
+        snapshot1 = self.create_snapshot(self.volume_origin['id'], force=True)
+        snapshot2 = self.create_snapshot(self.volume_origin['id'], force=True)
+        snapshot3 = self.create_snapshot(self.volume_origin['id'], force=True)
+
+        # Delete the snapshots. Some snapshot implementations can take
+        # different paths according to order they are deleted.
+        self.cleanup_snapshot(snapshot1)
+        self.cleanup_snapshot(snapshot3)
+        self.cleanup_snapshot(snapshot2)
+
+    @test.idempotent_id('5210a1de-85a0-11e6-bb21-641c676a5d61')
+    @test.services('compute')
+    def test_snapshot_create_offline_delete_online(self):
+
+        # Create a snapshot while it is not attached
+        snapshot1 = self.create_snapshot(self.volume_origin['id'])
+
+        # Create a server and attach it
+        server = self.create_server(wait_until='ACTIVE')
+        self.attach_volume(server['id'], self.volume_origin['id'])
+
+        # Now that the volume is attached, create another snapshots
+        snapshot2 = self.create_snapshot(self.volume_origin['id'], force=True)
+        snapshot3 = self.create_snapshot(self.volume_origin['id'], force=True)
+
+        # Delete the snapshots. Some snapshot implementations can take
+        # different paths according to order they are deleted.
+        self.cleanup_snapshot(snapshot3)
+        self.cleanup_snapshot(snapshot1)
+        self.cleanup_snapshot(snapshot2)
+
     @test.idempotent_id('2a8abbe4-d871-46db-b049-c41f5af8216e')
     def test_snapshot_create_get_list_update_delete(self):
         # Create a snapshot
diff --git a/tempest/api/volume/v3/base.py b/tempest/api/volume/v3/base.py
index e38f947..31fc1eb 100644
--- a/tempest/api/volume/v3/base.py
+++ b/tempest/api/volume/v3/base.py
@@ -52,7 +52,8 @@
             self.request_microversion))
 
 
-class VolumesV3AdminTest(VolumesV3Test):
+class VolumesV3AdminTest(VolumesV3Test,
+                         base.BaseVolumeAdminTest):
     """Base test case class for all v3 Volume Admin API tests."""
 
     credentials = ['primary', 'admin']
diff --git a/tempest/cmd/main.py b/tempest/cmd/main.py
index 641d11c..1090c41 100644
--- a/tempest/cmd/main.py
+++ b/tempest/cmd/main.py
@@ -11,11 +11,11 @@
 # License for the specific language governing permissions and limitations
 # under the License.
 
-import logging
 import sys
 
 from cliff import app
 from cliff import commandmanager
+from oslo_log import log as logging
 from pbr import version
 
 
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 92bce5f..981a922 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -176,7 +176,7 @@
         time.sleep(client.build_interval)
         body = client.show_volume(volume_id)['volume']
         volume_status = body['status']
-        if volume_status == 'error':
+        if volume_status == 'error' and status != 'error':
             raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
         if volume_status == 'error_restoring':
             raise exceptions.VolumeRestoreErrorException(volume_id=volume_id)
@@ -290,3 +290,28 @@
         if int(time.time()) - start_time >= client.build_timeout:
             raise lib_exc.TimeoutException
         time.sleep(client.build_interval)
+
+
+def wait_for_interface_status(client, server, port_id, status):
+    """Waits for an interface to reach a given status."""
+    body = (client.show_interface(server, port_id)
+            ['interfaceAttachment'])
+    interface_status = body['port_state']
+    start = int(time.time())
+
+    while(interface_status != status):
+        time.sleep(client.build_interval)
+        body = (client.show_interface(server, port_id)
+                ['interfaceAttachment'])
+        interface_status = body['port_state']
+
+        timed_out = int(time.time()) - start >= client.build_timeout
+
+        if interface_status != status and timed_out:
+            message = ('Interface %s failed to reach %s status '
+                       '(current %s) within the required time (%s s).' %
+                       (port_id, status, interface_status,
+                        client.build_timeout))
+            raise lib_exc.TimeoutException(message)
+
+    return body
diff --git a/tempest/lib/services/volume/v1/backups_client.py b/tempest/lib/services/volume/v1/backups_client.py
index 2728c67..8677913 100644
--- a/tempest/lib/services/volume/v1/backups_client.py
+++ b/tempest/lib/services/volume/v1/backups_client.py
@@ -26,8 +26,9 @@
     def create_backup(self, **kwargs):
         """Creates a backup of volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-backup
         """
         post_body = json.dumps({'backup': kwargs})
         resp, body = self.post('backups', post_body)
@@ -38,8 +39,9 @@
     def restore_backup(self, backup_id, **kwargs):
         """Restore volume from backup.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#restoreBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#restore-backup
         """
         post_body = json.dumps({'restore': kwargs})
         resp, body = self.post('backups/%s/restore' % (backup_id), post_body)
diff --git a/tempest/lib/services/volume/v1/qos_client.py b/tempest/lib/services/volume/v1/qos_client.py
index 65ae274..e247b7b 100644
--- a/tempest/lib/services/volume/v1/qos_client.py
+++ b/tempest/lib/services/volume/v1/qos_client.py
@@ -41,8 +41,9 @@
     def create_qos(self, **kwargs):
         """Create a QoS Specification.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createQoSSpec
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#create-qos-specification
         """
         post_body = json.dumps({'qos_specs': kwargs})
         resp, body = self.post('qos-specs', post_body)
@@ -76,8 +77,9 @@
     def set_qos_key(self, qos_id, **kwargs):
         """Set the specified keys/values of QoS specification.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#setQoSKey
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref/block-storage/v2/#set-keys-in-qos-specification
         """
         put_body = json.dumps({"qos_specs": kwargs})
         resp, body = self.put('qos-specs/%s' % qos_id, put_body)
diff --git a/tempest/lib/services/volume/v1/snapshots_client.py b/tempest/lib/services/volume/v1/snapshots_client.py
index 1881078..2cf1555 100644
--- a/tempest/lib/services/volume/v1/snapshots_client.py
+++ b/tempest/lib/services/volume/v1/snapshots_client.py
@@ -25,8 +25,9 @@
     def list_snapshots(self, detail=False, **params):
         """List all the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#listSnapshots
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#listSnapshots
         """
         url = 'snapshots'
         if detail:
@@ -42,8 +43,9 @@
     def show_snapshot(self, snapshot_id):
         """Returns the details of a single snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#showSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#showSnapshot
         """
         url = "snapshots/%s" % snapshot_id
         resp, body = self.get(url)
@@ -54,8 +56,9 @@
     def create_snapshot(self, **kwargs):
         """Creates a new snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#createSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#createSnapshot
         """
         post_body = json.dumps({'snapshot': kwargs})
         resp, body = self.post('snapshots', post_body)
@@ -66,8 +69,9 @@
     def delete_snapshot(self, snapshot_id):
         """Delete Snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#deleteSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#deleteSnapshot
         """
         resp, body = self.delete("snapshots/%s" % snapshot_id)
         self.expected_success(202, resp.status)
@@ -117,9 +121,9 @@
     def update_snapshot(self, snapshot_id, **kwargs):
         """Updates a snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#
-                              updateSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#updateSnapshotMetadata
         """
         put_body = json.dumps({'snapshot': kwargs})
         resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
@@ -130,9 +134,9 @@
     def show_snapshot_metadata(self, snapshot_id):
         """Get metadata of the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#
-                              showSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#showSnapshotMetadata
         """
         url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.get(url)
@@ -143,9 +147,9 @@
     def update_snapshot_metadata(self, snapshot_id, **kwargs):
         """Update metadata for the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#
-                              updateSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#updateSnapshotMetadata
         """
         put_body = json.dumps(kwargs)
         url = "snapshots/%s/metadata" % snapshot_id
diff --git a/tempest/lib/services/volume/v1/types_client.py b/tempest/lib/services/volume/v1/types_client.py
index dce728d..2b696e5 100644
--- a/tempest/lib/services/volume/v1/types_client.py
+++ b/tempest/lib/services/volume/v1/types_client.py
@@ -38,8 +38,9 @@
     def list_volume_types(self, **params):
         """List all the volume_types created.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#listVolumeTypes
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#listVolumeTypes
         """
         url = 'types'
         if params:
@@ -53,8 +54,9 @@
     def show_volume_type(self, volume_type_id):
         """Returns the details of a single volume_type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#showVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#showVolumeType
         """
         url = "types/%s" % volume_type_id
         resp, body = self.get(url)
@@ -65,8 +67,9 @@
     def create_volume_type(self, **kwargs):
         """Create volume type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#createVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#createVolumeType
         """
         post_body = json.dumps({'volume_type': kwargs})
         resp, body = self.post('types', post_body)
@@ -77,8 +80,9 @@
     def delete_volume_type(self, volume_type_id):
         """Deletes the Specified Volume_type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v1.html#deleteVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v1.html#deleteVolumeType
         """
         resp, body = self.delete("types/%s" % volume_type_id)
         self.expected_success(202, resp.status)
@@ -131,8 +135,9 @@
     def update_volume_type(self, volume_type_id, **kwargs):
         """Updates volume type name, description, and/or is_public.
 
-        Available params: see http://developer.openstack.org/
-        api-ref-blockstorage-v2.html#updateVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateVolumeType
         """
         put_body = json.dumps({'volume_type': kwargs})
         resp, body = self.put('types/%s' % volume_type_id, put_body)
@@ -148,9 +153,9 @@
         extra_spec_name: Name of the extra spec to be updated.
         extra_spec: A dictionary of with key as extra_spec_name and the
                      updated value.
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#
-                              updateVolumeTypeExtraSpecs
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateVolumeTypeExtraSpecs
         """
         url = "types/%s/extra_specs/%s" % (volume_type_id, extra_spec_name)
         put_body = json.dumps(extra_specs)
diff --git a/tempest/lib/services/volume/v1/volumes_client.py b/tempest/lib/services/volume/v1/volumes_client.py
index cc98c91..242befc 100644
--- a/tempest/lib/services/volume/v1/volumes_client.py
+++ b/tempest/lib/services/volume/v1/volumes_client.py
@@ -61,8 +61,9 @@
     def create_volume(self, **kwargs):
         """Creates a new Volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createVolume
         """
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('volumes', post_body)
@@ -73,8 +74,9 @@
     def update_volume(self, volume_id, **kwargs):
         """Updates the Specified Volume.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#updateVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateVolume
         """
         put_body = json.dumps({'volume': kwargs})
         resp, body = self.put('volumes/%s' % volume_id, put_body)
@@ -100,8 +102,9 @@
     def attach_volume(self, volume_id, **kwargs):
         """Attaches a volume to a given instance on a given mountpoint.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#attachVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#attachVolume
         """
         post_body = json.dumps({'os-attach': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -156,8 +159,9 @@
     def extend_volume(self, volume_id, **kwargs):
         """Extend a volume.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#extendVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#extendVolume
         """
         post_body = json.dumps({'os-extend': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -168,8 +172,9 @@
     def reset_volume_status(self, volume_id, **kwargs):
         """Reset the Specified Volume's Status.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#resetVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#resetVolume
         """
         post_body = json.dumps({'os-reset_status': kwargs})
         resp, body = self.post('volumes/%s/action' % volume_id, post_body)
@@ -179,8 +184,9 @@
     def create_volume_transfer(self, **kwargs):
         """Create a volume transfer.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#createVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createVolumeTransfer
         """
         post_body = json.dumps({'transfer': kwargs})
         resp, body = self.post('os-volume-transfer', post_body)
@@ -199,8 +205,9 @@
     def list_volume_transfers(self, **params):
         """List all the volume transfers created.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#listVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#listVolumeTransfer
         """
         url = 'os-volume-transfer'
         if params:
@@ -219,8 +226,9 @@
     def accept_volume_transfer(self, transfer_id, **kwargs):
         """Accept a volume transfer.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#acceptVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#acceptVolumeTransfer
         """
         url = 'os-volume-transfer/%s/accept' % transfer_id
         post_body = json.dumps({'accept': kwargs})
diff --git a/tempest/lib/services/volume/v2/backups_client.py b/tempest/lib/services/volume/v2/backups_client.py
index 61f865d..ab5eefd 100644
--- a/tempest/lib/services/volume/v2/backups_client.py
+++ b/tempest/lib/services/volume/v2/backups_client.py
@@ -26,8 +26,9 @@
     def create_backup(self, **kwargs):
         """Creates a backup of volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createBackup
         """
         post_body = json.dumps({'backup': kwargs})
         resp, body = self.post('backups', post_body)
@@ -38,8 +39,9 @@
     def restore_backup(self, backup_id, **kwargs):
         """Restore volume from backup.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#restoreBackup
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#restoreBackup
         """
         post_body = json.dumps({'restore': kwargs})
         resp, body = self.post('backups/%s/restore' % (backup_id), post_body)
diff --git a/tempest/lib/services/volume/v2/snapshots_client.py b/tempest/lib/services/volume/v2/snapshots_client.py
index c84e557..dd0f407 100644
--- a/tempest/lib/services/volume/v2/snapshots_client.py
+++ b/tempest/lib/services/volume/v2/snapshots_client.py
@@ -25,8 +25,9 @@
     def list_snapshots(self, detail=False, **params):
         """List all the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#listSnapshots
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#listSnapshots
         """
         url = 'snapshots'
         if detail:
@@ -42,8 +43,9 @@
     def show_snapshot(self, snapshot_id):
         """Returns the details of a single snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#showSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#showSnapshot
         """
         url = "snapshots/%s" % snapshot_id
         resp, body = self.get(url)
@@ -54,8 +56,9 @@
     def create_snapshot(self, **kwargs):
         """Creates a new snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createSnapshot
         """
         post_body = json.dumps({'snapshot': kwargs})
         resp, body = self.post('snapshots', post_body)
@@ -66,8 +69,9 @@
     def update_snapshot(self, snapshot_id, **kwargs):
         """Updates a snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#updateSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateSnapshot
         """
         put_body = json.dumps({'snapshot': kwargs})
         resp, body = self.put('snapshots/%s' % snapshot_id, put_body)
@@ -78,8 +82,9 @@
     def delete_snapshot(self, snapshot_id):
         """Delete Snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#deleteSnapshot
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#deleteSnapshot
         """
         resp, body = self.delete("snapshots/%s" % snapshot_id)
         self.expected_success(202, resp.status)
@@ -129,9 +134,9 @@
     def show_snapshot_metadata(self, snapshot_id):
         """Get metadata of the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#
-                              showSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#showSnapshotMetadata
         """
         url = "snapshots/%s/metadata" % snapshot_id
         resp, body = self.get(url)
@@ -142,9 +147,9 @@
     def update_snapshot_metadata(self, snapshot_id, **kwargs):
         """Update metadata for the snapshot.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#
-                              updateSnapshotMetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateSnapshotMetadata
         """
         put_body = json.dumps(kwargs)
         url = "snapshots/%s/metadata" % snapshot_id
diff --git a/tempest/lib/services/volume/v2/types_client.py b/tempest/lib/services/volume/v2/types_client.py
index d399e99..7a0d6d0 100644
--- a/tempest/lib/services/volume/v2/types_client.py
+++ b/tempest/lib/services/volume/v2/types_client.py
@@ -39,8 +39,9 @@
     def list_volume_types(self, **params):
         """List all the volume_types created.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#showVolumeTypes
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#showVolumeTypes
         """
         url = 'types'
         if params:
@@ -54,8 +55,9 @@
     def show_volume_type(self, volume_type_id):
         """Returns the details of a single volume_type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#showVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#showVolumeType
         """
         url = "types/%s" % volume_type_id
         resp, body = self.get(url)
@@ -66,8 +68,9 @@
     def create_volume_type(self, **kwargs):
         """Create volume type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createVolumeType
         """
         post_body = json.dumps({'volume_type': kwargs})
         resp, body = self.post('types', post_body)
@@ -78,8 +81,9 @@
     def delete_volume_type(self, volume_type_id):
         """Deletes the Specified Volume_type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#deleteVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#deleteVolumeType
         """
         resp, body = self.delete("types/%s" % volume_type_id)
         self.expected_success(202, resp.status)
@@ -132,8 +136,9 @@
     def update_volume_type(self, volume_type_id, **kwargs):
         """Updates volume type name, description, and/or is_public.
 
-        Available params: see http://developer.openstack.org/
-        api-ref-blockstorage-v2.html#updateVolumeType
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateVolumeType
         """
         put_body = json.dumps({'volume_type': kwargs})
         resp, body = self.put('types/%s' % volume_type_id, put_body)
@@ -149,9 +154,9 @@
         extra_spec_name: Name of the extra spec to be updated.
         extra_spec: A dictionary of with key as extra_spec_name and the
                      updated value.
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#
-                              updateVolumeTypeExtraSpecs
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateVolumeTypeExtraSpecs
         """
         url = "types/%s/extra_specs/%s" % (volume_type_id, extra_spec_name)
         put_body = json.dumps(extra_specs)
@@ -163,9 +168,9 @@
     def add_type_access(self, volume_type_id, **kwargs):
         """Adds volume type access for the given project.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html
-                              #createVolumeTypeAccessExt
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createVolumeTypeAccessExt
         """
         post_body = json.dumps({'addProjectAccess': kwargs})
         url = 'types/%s/action' % volume_type_id
@@ -176,9 +181,9 @@
     def remove_type_access(self, volume_type_id, **kwargs):
         """Removes volume type access for the given project.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html
-                              #removeVolumeTypeAccessExt
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#removeVolumeTypeAccessExt
         """
         post_body = json.dumps({'removeProjectAccess': kwargs})
         url = 'types/%s/action' % volume_type_id
@@ -189,9 +194,9 @@
     def list_type_access(self, volume_type_id):
         """Print access information about the given volume type.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#
-                              listVolumeTypeAccessExt
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#listVolumeTypeAccessExt
         """
         url = 'types/%s/os-volume-type-access' % volume_type_id
         resp, body = self.get(url)
diff --git a/tempest/lib/services/volume/v2/volumes_client.py b/tempest/lib/services/volume/v2/volumes_client.py
index b1930e1..1fb5727 100644
--- a/tempest/lib/services/volume/v2/volumes_client.py
+++ b/tempest/lib/services/volume/v2/volumes_client.py
@@ -62,8 +62,9 @@
     def create_volume(self, **kwargs):
         """Creates a new Volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html#createVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createVolume
         """
         post_body = json.dumps({'volume': kwargs})
         resp, body = self.post('volumes', post_body)
@@ -74,8 +75,9 @@
     def update_volume(self, volume_id, **kwargs):
         """Updates the Specified Volume.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#updateVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#updateVolume
         """
         put_body = json.dumps({'volume': kwargs})
         resp, body = self.put('volumes/%s' % volume_id, put_body)
@@ -101,8 +103,9 @@
     def attach_volume(self, volume_id, **kwargs):
         """Attaches a volume to a given instance on a given mountpoint.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#attachVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#attachVolume
         """
         post_body = json.dumps({'os-attach': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -157,8 +160,9 @@
     def extend_volume(self, volume_id, **kwargs):
         """Extend a volume.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#extendVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#extendVolume
         """
         post_body = json.dumps({'os-extend': kwargs})
         url = 'volumes/%s/action' % (volume_id)
@@ -169,8 +173,9 @@
     def reset_volume_status(self, volume_id, **kwargs):
         """Reset the Specified Volume's Status.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#resetVolume
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#resetVolume
         """
         post_body = json.dumps({'os-reset_status': kwargs})
         resp, body = self.post('volumes/%s/action' % volume_id, post_body)
@@ -180,8 +185,9 @@
     def create_volume_transfer(self, **kwargs):
         """Create a volume transfer.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#createVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#createVolumeTransfer
         """
         post_body = json.dumps({'transfer': kwargs})
         resp, body = self.post('os-volume-transfer', post_body)
@@ -200,8 +206,9 @@
     def list_volume_transfers(self, **params):
         """List all the volume transfers created.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#listVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#listVolumeTransfer
         """
         url = 'os-volume-transfer'
         if params:
@@ -220,8 +227,9 @@
     def accept_volume_transfer(self, transfer_id, **kwargs):
         """Accept a volume transfer.
 
-        Available params: see http://developer.openstack.org/
-                                api-ref-blockstorage-v2.html#acceptVolumeTransfer
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#acceptVolumeTransfer
         """
         url = 'os-volume-transfer/%s/accept' % transfer_id
         post_body = json.dumps({'accept': kwargs})
@@ -296,9 +304,9 @@
     def update_volume_image_metadata(self, volume_id, **kwargs):
         """Update image metadata for the volume.
 
-        Available params: see http://developer.openstack.org/
-                              api-ref-blockstorage-v2.html
-                              #setVolumeimagemetadata
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#setVolumeimagemetadata
         """
         post_body = json.dumps({'os-set_image_metadata': {'metadata': kwargs}})
         url = "volumes/%s/action" % (volume_id)
@@ -329,9 +337,9 @@
     def show_backend_capabilities(self, host):
         """Shows capabilities for a storage back end.
 
-         Output params: see http://developer.openstack.org/
-                            api-ref-blockstorage-v2.html
-                            #showBackendCapabilities
+        For a full list of available parameters, please refer to the official
+        API reference:
+        http://developer.openstack.org/api-ref-blockstorage-v2.html#showBackendCapabilities
         """
         url = 'capabilities/%s' % host
         resp, body = self.get(url)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 8b86267..73544d9 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -219,6 +219,10 @@
                       imageRef=None, volume_type=None):
         if size is None:
             size = CONF.volume.volume_size
+        if imageRef:
+            image = self.compute_images_client.show_image(imageRef)['image']
+            min_disk = image.get('minDisk')
+            size = max(size, min_disk)
         if name is None:
             name = data_utils.rand_name(self.__class__.__name__ + "-volume")
         kwargs = {'display_name': name,
diff --git a/tempest/tests/common/test_custom_matchers.py b/tempest/tests/common/test_custom_matchers.py
index 07867fc..1053d86 100644
--- a/tempest/tests/common/test_custom_matchers.py
+++ b/tempest/tests/common/test_custom_matchers.py
@@ -25,11 +25,11 @@
         matches = self.matches_matches
         mismatches = self.matches_mismatches
         for candidate in matches:
-            self.assertEqual(None, matcher.match(candidate))
+            self.assertIsNone(matcher.match(candidate))
         for candidate in mismatches:
             mismatch = matcher.match(candidate)
-            self.assertNotEqual(None, mismatch)
-            self.assertNotEqual(None, getattr(mismatch, 'describe', None))
+            self.assertIsNotNone(mismatch)
+            self.assertIsNotNone(getattr(mismatch, 'describe', None))
 
     def test__str__(self):
         # [(expected, object to __str__)].