Merge "Fix broken api urls in TypesClient"
diff --git a/HACKING.rst b/HACKING.rst
index c0a857c..dbb758b 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -22,6 +22,7 @@
 - [T112] Check that tempest.lib should not import local tempest code
 - [T113] Check that tests use data_utils.rand_uuid() instead of uuid.uuid4()
 - [T114] Check that tempest.lib does not use tempest config
+- [T115] Check that admin tests should exist under admin path
 - [N322] Method's default argument shouldn't be mutable
 
 Test Data/Configuration
@@ -232,9 +233,9 @@
   and xml version of the same test class there could still be a race between
   methods.
 
-- The rand_name() function from tempest.common.utils.data_utils should be used
-  anywhere a resource is created with a name. Static naming should be avoided
-  to prevent resource conflicts.
+- The rand_name() function from tempest.lib.common.utils.data_utils should be
+  used anywhere a resource is created with a name. Static naming should be
+  avoided to prevent resource conflicts.
 
 - If the execution of a set of tests is required to be serialized then locking
   can be used to perform this. See AggregatesAdminTest in
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 2314222..4accd94 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -52,8 +52,7 @@
  #. ``uri_v3``
 
 The ``auth_version`` option is used to tell Tempest whether it should be using
-keystone's v2 or v3 api for communicating with keystone. (except for the
-identity api tests which will test a specific version) The two uri options are
+keystone's v2 or v3 api for communicating with keystone. The two uri options are
 used to tell Tempest the url of the keystone endpoint. The ``uri`` option is
 used for keystone v2 request and ``uri_v3`` is used for keystone v3. You want to
 ensure that which ever version you set for ``auth_version`` has its uri option
diff --git a/releasenotes/notes/add-floating-ip-config-option-e5774bf77702ce9f.yaml b/releasenotes/notes/add-floating-ip-config-option-e5774bf77702ce9f.yaml
new file mode 100644
index 0000000..8221d78
--- /dev/null
+++ b/releasenotes/notes/add-floating-ip-config-option-e5774bf77702ce9f.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - A new config option in the network-feature-enabled section, floating_ips,
+    to specify whether floating ips are available in the cloud under test. By
+    default this is set to True.
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions.py b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
index 2769245..faa7b5d 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions.py
@@ -30,6 +30,12 @@
     floating_ip = None
 
     @classmethod
+    def skip_checks(cls):
+        super(FloatingIPsTestJSON, cls).skip_checks()
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
+
+    @classmethod
     def setup_clients(cls):
         super(FloatingIPsTestJSON, cls).setup_clients()
         cls.client = cls.floating_ips_client
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index 96983b0..483bd95 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -28,6 +28,12 @@
 class FloatingIPsNegativeTestJSON(base.BaseFloatingIPsTest):
 
     @classmethod
+    def skip_checks(cls):
+        super(FloatingIPsNegativeTestJSON, cls).skip_checks()
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
+
+    @classmethod
     def setup_clients(cls):
         super(FloatingIPsNegativeTestJSON, cls).setup_clients()
         cls.client = cls.floating_ips_client
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index 71f5f13..74d2dc4 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -24,6 +24,12 @@
 class FloatingIPDetailsTestJSON(base.BaseV2ComputeTest):
 
     @classmethod
+    def skip_checks(cls):
+        super(FloatingIPDetailsTestJSON, cls).skip_checks()
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
+
+    @classmethod
     def setup_clients(cls):
         super(FloatingIPDetailsTestJSON, cls).setup_clients()
         cls.client = cls.floating_ips_client
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index 9d70bf7..b5bbb8c 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -26,6 +26,12 @@
 class FloatingIPDetailsNegativeTestJSON(base.BaseV2ComputeTest):
 
     @classmethod
+    def skip_checks(cls):
+        super(FloatingIPDetailsNegativeTestJSON, cls).skip_checks()
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
+
+    @classmethod
     def setup_clients(cls):
         super(FloatingIPDetailsNegativeTestJSON, cls).setup_clients()
         cls.client = cls.floating_ips_client
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 76b9c44..6f072b2 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -531,6 +531,10 @@
         self.client.unshelve_server(self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
 
+        images = self.compute_images_client.list_images(**params)['images']
+        msg = ('After unshelve, shelved image is not deleted.')
+        self.assertEmpty(images, msg)
+
     @decorators.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560')
     def test_stop_start_server(self):
         self.client.stop_server(self.server_id)
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 83151b3..b0ef3bc 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -65,6 +65,8 @@
     @decorators.idempotent_id('4842e0cf-e87d-4d9d-b61f-f4791da3cacc')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
+    @testtools.skipUnless(CONF.network_feature_enabled.floating_ips,
+                          "Floating ips are not available")
     def test_rescued_vm_associate_dissociate_floating_ip(self):
         # Association of floating IP to a rescued vm
         floating_ip_body = self.floating_ips_client.create_floating_ip(
diff --git a/tempest/api/identity/admin/v3/test_oauth_consumers.py b/tempest/api/identity/admin/v3/test_oauth_consumers.py
index f06fb8f..970ead3 100644
--- a/tempest/api/identity/admin/v3/test_oauth_consumers.py
+++ b/tempest/api/identity/admin/v3/test_oauth_consumers.py
@@ -14,7 +14,7 @@
 #    under the License.
 
 from tempest.api.identity import base
-from tempest.common.utils import data_utils
+from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as exceptions
diff --git a/tempest/api/identity/admin/v3/test_tokens.py b/tempest/api/identity/admin/v3/test_tokens.py
index 8c5e63b..1acc67d 100644
--- a/tempest/api/identity/admin/v3/test_tokens.py
+++ b/tempest/api/identity/admin/v3/test_tokens.py
@@ -145,7 +145,7 @@
 
     @decorators.idempotent_id('08ed85ce-2ba8-4864-b442-bcc61f16ae89')
     def test_get_available_project_scopes(self):
-        manager_project_id = self.manager.credentials.project_id
+        manager_project_id = self.os_primary.credentials.project_id
         admin_user_id = self.os_admin.credentials.user_id
         admin_role_id = self.get_role_by_name(CONF.identity.admin_role)['id']
 
diff --git a/tempest/api/network/admin/test_external_network_extension.py b/tempest/api/network/admin/test_external_network_extension.py
index c83dd7f..4d41e33 100644
--- a/tempest/api/network/admin/test_external_network_extension.py
+++ b/tempest/api/network/admin/test_external_network_extension.py
@@ -10,11 +10,16 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import testtools
+
 from tempest.api.network import base
+from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 
+CONF = config.CONF
+
 
 class ExternalNetworksTestJSON(base.BaseAdminNetworkTest):
 
@@ -91,6 +96,8 @@
         self.assertFalse(show_net['router:external'])
 
     @decorators.idempotent_id('82068503-2cf2-4ed4-b3be-ecb89432e4bb')
+    @testtools.skipUnless(CONF.network_feature_enabled.floating_ips,
+                          'Floating ips are not availabled')
     def test_delete_external_networks_with_floating_ip(self):
         # Verifies external network can be deleted while still holding
         # (unassociated) floating IPs
diff --git a/tempest/api/network/admin/test_floating_ips_admin_actions.py b/tempest/api/network/admin/test_floating_ips_admin_actions.py
index 11f520a..7ee819e 100644
--- a/tempest/api/network/admin/test_floating_ips_admin_actions.py
+++ b/tempest/api/network/admin/test_floating_ips_admin_actions.py
@@ -34,6 +34,8 @@
         if not CONF.network.public_network_id:
             msg = "The public_network_id option must be specified."
             raise cls.skipException(msg)
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
 
     @classmethod
     def setup_clients(cls):
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index f0f92ac..c799b15 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -49,6 +49,8 @@
         if not CONF.network.public_network_id:
             msg = "The public_network_id option must be specified."
             raise cls.skipException(msg)
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index f5830ab..5ca17fe 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -40,6 +40,8 @@
         if not CONF.network.public_network_id:
             msg = "The public_network_id option must be specified."
             raise cls.skipException(msg)
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/volume/admin/test_volume_quota_classes.py b/tempest/api/volume/admin/test_volume_quota_classes.py
index b8a61fd..f551575 100644
--- a/tempest/api/volume/admin/test_volume_quota_classes.py
+++ b/tempest/api/volume/admin/test_volume_quota_classes.py
@@ -13,6 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import random
+
 from oslo_log import log as logging
 from testtools import matchers
 
@@ -53,31 +55,41 @@
         LOG.debug("Get the current default quota class values")
         body = self.admin_quota_classes_client.show_quota_class_set(
             'default')['quota_class_set']
-        body.pop('id')
 
-        # Restore the defaults when the test is done
-        self.addCleanup(self._restore_default_quotas, body.copy())
+        # Note(jeremyZ) Only include specified quota keys to avoid the conflict
+        # that other tests may create/delete volume types or update volume
+        # type's default quotas in concurrency running.
+        update_kwargs = {key: body[key] for key in body if key in QUOTA_KEYS}
 
-        # Increment some of the values for updating the default quota class.
-        # For safety, only items with value >= 0 will be updated, and items
-        # with value < 0 (-1 means unlimited) will be ignored.
-        for quota, default in body.items():
+        # Restore the defaults when the test is done.
+        self.addCleanup(self._restore_default_quotas, update_kwargs.copy())
+
+        # Note(jeremyZ) Increment some of the values for updating the default
+        # quota class. For safety, only items with value >= 0 will be updated,
+        # and items with value < 0 (-1 means unlimited) will be ignored.
+        for quota, default in update_kwargs.items():
             if default >= 0:
-                body[quota] = default + 1
+                update_kwargs[quota] = default + 1
+
+        # Create a volume type for updating default quotas class.
+        volume_type_name = self.create_volume_type()['name']
+        for key in ['volumes', 'snapshots', 'gigabytes']:
+            update_kwargs['%s_%s' % (key, volume_type_name)] = \
+                random.randint(1, 10)
 
         LOG.debug("Update limits for the default quota class set")
         update_body = self.admin_quota_classes_client.update_quota_class_set(
-            'default', **body)['quota_class_set']
+            'default', **update_kwargs)['quota_class_set']
         self.assertThat(update_body.items(),
-                        matchers.ContainsAll(body.items()))
+                        matchers.ContainsAll(update_kwargs.items()))
 
-        # Verify current project's default quotas
+        # Verify current project's default quotas.
         default_quotas = self.admin_quotas_client.show_default_quota_set(
             self.os_admin.credentials.tenant_id)['quota_set']
         self.assertThat(default_quotas.items(),
-                        matchers.ContainsAll(body.items()))
+                        matchers.ContainsAll(update_kwargs.items()))
 
-        # Verify a new project's default quotas
+        # Verify a new project's default quotas.
         project_name = data_utils.rand_name('quota_class_tenant')
         description = data_utils.rand_name('desc_')
         project_id = self.identity_utils.create_project(
@@ -86,4 +98,4 @@
         default_quotas = self.admin_quotas_client.show_default_quota_set(
             project_id)['quota_set']
         self.assertThat(default_quotas.items(),
-                        matchers.ContainsAll(body.items()))
+                        matchers.ContainsAll(update_kwargs.items()))
diff --git a/tempest/api/volume/test_volume_absolute_limits.py b/tempest/api/volume/test_volume_absolute_limits.py
index 870b9f0..4018468 100644
--- a/tempest/api/volume/test_volume_absolute_limits.py
+++ b/tempest/api/volume/test_volume_absolute_limits.py
@@ -24,7 +24,7 @@
 # NOTE(zhufl): This inherits from BaseVolumeAdminTest because
 # it requires force_tenant_isolation=True, which need admin
 # credentials to create non-admin users for the tests.
-class AbsoluteLimitsTests(base.BaseVolumeAdminTest):
+class AbsoluteLimitsTests(base.BaseVolumeAdminTest):  # noqa
 
     # avoid existing volumes of pre-defined tenant
     force_tenant_isolation = True
diff --git a/tempest/config.py b/tempest/config.py
index a2e0877..989d53a 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -647,6 +647,9 @@
     cfg.BoolOpt('port_security',
                 default=False,
                 help="Does the test environment support port security?"),
+    cfg.BoolOpt('floating_ips',
+                default=True,
+                help='Does the test environment support floating_ips')
 ]
 
 validation_group = cfg.OptGroup(name='validation',
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index 4123ae5..067da09 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -273,6 +273,27 @@
         yield(0, msg)
 
 
+def dont_put_admin_tests_on_nonadmin_path(logical_line, physical_line,
+                                          filename):
+    """Check admin tests should exist under admin path
+
+    T115
+    """
+
+    if 'tempest/api/' not in filename:
+        return
+
+    if pep8.noqa(physical_line):
+        return
+
+    if not re.match('class .*Test.*\(.*Admin.*\):', logical_line):
+        return
+
+    if not re.match('.\/tempest\/api\/.*\/admin\/.*', filename):
+        msg = 'T115: All admin tests should exist under admin path.'
+        yield(0, msg)
+
+
 def factory(register):
     register(import_no_clients_in_api_and_scenario_tests)
     register(scenario_tests_need_service_tags)
@@ -287,3 +308,4 @@
     register(dont_import_local_tempest_into_lib)
     register(dont_use_config_in_tempest_lib)
     register(use_rand_uuid_instead_of_uuid4)
+    register(dont_put_admin_tests_on_nonadmin_path)
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index 657c0c1..d4ec6ad 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -84,10 +84,6 @@
         ssh.set_missing_host_key_policy(
             paramiko.AutoAddPolicy())
         _start_time = time.time()
-        if self.proxy_client is not None:
-            proxy_chan = self._get_proxy_channel()
-        else:
-            proxy_chan = None
         if self.pkey is not None:
             LOG.info("Creating ssh connection to '%s:%d' as '%s'"
                      " with public key authentication",
@@ -98,6 +94,10 @@
                      self.host, self.port, self.username, str(self.password))
         attempts = 0
         while True:
+            if self.proxy_client is not None:
+                proxy_chan = self._get_proxy_channel()
+            else:
+                proxy_chan = None
             try:
                 ssh.connect(self.host, port=self.port, username=self.username,
                             password=self.password,
diff --git a/tempest/lib/services/identity/v3/services_client.py b/tempest/lib/services/identity/v3/services_client.py
index 17b0f24..7bbe850 100644
--- a/tempest/lib/services/identity/v3/services_client.py
+++ b/tempest/lib/services/identity/v3/services_client.py
@@ -76,7 +76,7 @@
         url = 'services'
         if params:
             url += '?%s' % urllib.urlencode(params)
-        resp, body = self.get('services')
+        resp, body = self.get(url)
         self.expected_success(200, resp.status)
         body = json.loads(body)
         return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 2e55c2e..a486a29 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -47,40 +47,40 @@
     def setup_clients(cls):
         super(ScenarioTest, cls).setup_clients()
         # Clients (in alphabetical order)
-        cls.flavors_client = cls.manager.flavors_client
+        cls.flavors_client = cls.os_primary.flavors_client
         cls.compute_floating_ips_client = (
-            cls.manager.compute_floating_ips_client)
+            cls.os_primary.compute_floating_ips_client)
         if CONF.service_available.glance:
             # Check if glance v1 is available to determine which client to use.
             if CONF.image_feature_enabled.api_v1:
-                cls.image_client = cls.manager.image_client
+                cls.image_client = cls.os_primary.image_client
             elif CONF.image_feature_enabled.api_v2:
-                cls.image_client = cls.manager.image_client_v2
+                cls.image_client = cls.os_primary.image_client_v2
             else:
                 raise lib_exc.InvalidConfiguration(
                     'Either api_v1 or api_v2 must be True in '
                     '[image-feature-enabled].')
         # Compute image client
-        cls.compute_images_client = cls.manager.compute_images_client
-        cls.keypairs_client = cls.manager.keypairs_client
+        cls.compute_images_client = cls.os_primary.compute_images_client
+        cls.keypairs_client = cls.os_primary.keypairs_client
         # Nova security groups client
         cls.compute_security_groups_client = (
-            cls.manager.compute_security_groups_client)
+            cls.os_primary.compute_security_groups_client)
         cls.compute_security_group_rules_client = (
-            cls.manager.compute_security_group_rules_client)
-        cls.servers_client = cls.manager.servers_client
-        cls.interface_client = cls.manager.interfaces_client
+            cls.os_primary.compute_security_group_rules_client)
+        cls.servers_client = cls.os_primary.servers_client
+        cls.interface_client = cls.os_primary.interfaces_client
         # Neutron network client
-        cls.networks_client = cls.manager.networks_client
-        cls.ports_client = cls.manager.ports_client
-        cls.routers_client = cls.manager.routers_client
-        cls.subnets_client = cls.manager.subnets_client
-        cls.floating_ips_client = cls.manager.floating_ips_client
-        cls.security_groups_client = cls.manager.security_groups_client
+        cls.networks_client = cls.os_primary.networks_client
+        cls.ports_client = cls.os_primary.ports_client
+        cls.routers_client = cls.os_primary.routers_client
+        cls.subnets_client = cls.os_primary.subnets_client
+        cls.floating_ips_client = cls.os_primary.floating_ips_client
+        cls.security_groups_client = cls.os_primary.security_groups_client
         cls.security_group_rules_client = (
-            cls.manager.security_group_rules_client)
-        cls.volumes_client = cls.manager.volumes_v2_client
-        cls.snapshots_client = cls.manager.snapshots_v2_client
+            cls.os_primary.security_group_rules_client)
+        cls.volumes_client = cls.os_primary.volumes_v2_client
+        cls.snapshots_client = cls.os_primary.snapshots_v2_client
 
     # ## Test functions library
     #
@@ -133,7 +133,7 @@
 
         # Needed for the cross_tenant_traffic test:
         if clients is None:
-            clients = self.manager
+            clients = self.os_primary
 
         if name is None:
             name = data_utils.rand_name(self.__class__.__name__ + "-server")
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 5fee801..eae1056 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -103,6 +103,8 @@
     @decorators.idempotent_id('bdbb5441-9204-419d-a225-b4fdbfb1a1a8')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
+    @testtools.skipUnless(CONF.network_feature_enabled.floating_ips,
+                          'Floating ips are not available')
     @test.services('compute', 'volume', 'image', 'network')
     def test_minimum_basic_scenario(self):
         image = self.glance_image_create()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index c2fc1a7..ec6d362 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -48,6 +48,8 @@
             msg = ('Either project_networks_reachable must be "true", or '
                    'public_network_id must be defined.')
             raise cls.skipException(msg)
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
 
     @classmethod
     def setup_credentials(cls):
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index d2907a0..c76c082 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -90,6 +90,8 @@
             if not test.is_extension_enabled(ext, 'network'):
                 msg = "%s extension not enabled." % ext
                 raise cls.skipException(msg)
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
 
     @classmethod
     def setup_credentials(cls):
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index c581812..3504a44 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -51,6 +51,8 @@
         if CONF.network.shared_physical_network:
             msg = 'Deployment uses a shared physical network'
             raise cls.skipException(msg)
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
 
     @classmethod
     def setup_credentials(cls):
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 413f315..41c60f1 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -148,6 +148,8 @@
             msg = ('Deployment uses a shared physical network, security '
                    'groups not supported')
             raise cls.skipException(msg)
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
 
     @classmethod
     def setup_credentials(cls):
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 2be9e06..77563b3 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -43,6 +43,12 @@
      * Terminate the instance
     """
 
+    @classmethod
+    def skip_checks(cls):
+        super(TestServerBasicOps, cls).skip_checks()
+        if not CONF.network_feature_enabled.floating_ips:
+            raise cls.skipException("Floating ips are not available")
+
     def setUp(self):
         super(TestServerBasicOps, self).setUp()
         self.run_ssh = CONF.validation.run_validation
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index 15f57d4..552ab27 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -13,7 +13,6 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions
@@ -35,15 +34,6 @@
             raise cls.skipException(
                 "Less than 2 compute nodes, skipping multinode tests.")
 
-    @classmethod
-    def setup_clients(cls):
-        super(TestServerMultinode, cls).setup_clients()
-        # Use admin client by default
-        cls.manager = cls.os_admin
-        # this is needed so that we can use the availability_zone:host
-        # scheduler hint, which is admin_only by default
-        cls.servers_client = cls.os_admin.servers_client
-
     @decorators.idempotent_id('9cecbe35-b9d4-48da-a37e-7ce70aa43d30')
     @decorators.attr(type='smoke')
     @test.services('compute', 'network')
@@ -74,9 +64,13 @@
         for host in hosts[:CONF.compute.min_compute_nodes]:
             # by getting to active state here, this means this has
             # landed on the host in question.
+            # in order to use the availability_zone:host scheduler hint,
+            # admin client is need here.
             inst = self.create_server(
+                clients=self.os_admin,
                 availability_zone='%(zone)s:%(host_name)s' % host)
-            server = self.servers_client.show_server(inst['id'])['server']
+            server = self.os_admin.servers_client.show_server(
+                inst['id'])['server']
             # ensure server is located on the requested host
             self.assertEqual(host['host_name'], server['OS-EXT-SRV-ATTR:host'])
             servers.append(server)