Merge "Add os-tenant-networks test"
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 3ade411..949302f 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -816,7 +816,7 @@
 
 # Number of seconds to time on waiting for a container to container
 # synchronization complete. (integer value)
-#container_sync_timeout = 120
+#container_sync_timeout = 600
 
 # Number of seconds to wait while looping to check the status of a
 # container to container synchronization (integer value)
@@ -829,6 +829,16 @@
 # User role that has reseller admin (string value)
 #reseller_admin_role = ResellerAdmin
 
+# Name of sync realm. A sync realm is a set of clusters that have
+# agreed to allow container syncing with each other. Set the same
+# realm name as Swift's container-sync-realms.conf (string value)
+#realm_name = realm1
+
+# One name of cluster which is set in the realm whose name is set in
+# 'realm_name' item in this file. Set the same cluster name as Swift's
+# container-sync-realms.conf (string value)
+#cluster_name = name1
+
 
 [object-storage-feature-enabled]
 
diff --git a/requirements.txt b/requirements.txt
index 1ce2fc5..94c6fb0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,7 +6,7 @@
 httplib2>=0.7.5
 jsonschema>=2.0.0,<3.0.0
 testtools>=0.9.36,!=1.2.0
-boto>=2.32.1,<2.35.0
+boto>=2.32.1
 paramiko>=1.13.0
 netaddr>=0.7.12
 python-ceilometerclient>=1.0.6
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index e3477f1..5210077 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -79,6 +79,24 @@
         self.assertIn(self.s2_name, servers_name)
 
     @test.attr(type='gate')
+    def test_list_servers_by_admin_with_specified_tenant(self):
+        # In nova v2, tenant_id is ignored unless all_tenants is specified
+
+        # List the primary tenant but get nothing due to odd specified behavior
+        tenant_id = self.non_admin_client.tenant_id
+        params = {'tenant_id': tenant_id}
+        resp, body = self.client.list_servers_with_detail(params)
+        servers = body['servers']
+        self.assertEqual([], servers)
+
+        # List the admin tenant which has no servers
+        admin_tenant_id = self.client.tenant_id
+        params = {'all_tenants': '', 'tenant_id': admin_tenant_id}
+        resp, body = self.client.list_servers_with_detail(params)
+        servers = body['servers']
+        self.assertEqual([], servers)
+
+    @test.attr(type='gate')
     def test_list_servers_filter_by_exist_host(self):
         # Filter the list of servers by existent host
         name = data_utils.rand_name('server')
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index 1c4dc59..13ec045 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -173,12 +173,17 @@
 
         _, addresses = self.client.list_addresses(server_multi_nics['id'])
 
-        expected_addr = ['19.80.0.2', '19.86.0.2']
-
+        # We can't predict the ip addresses assigned to the server on networks.
+        # Sometimes the assigned addresses are ['19.80.0.2', '19.86.0.2'], at
+        # other times ['19.80.0.3', '19.86.0.3']. So we check if the first
+        # address is in first network, similarly second address is in second
+        # network.
         addr = [addresses[name_net1][0]['addr'],
                 addresses[name_net2][0]['addr']]
-
-        self.assertEqual(expected_addr, addr)
+        networks = [netaddr.IPNetwork('19.80.0.0/24'),
+                    netaddr.IPNetwork('19.86.0.0/24')]
+        for address, network in zip(addr, networks):
+            self.assertIn(address, network)
 
 
 class ServersWithSpecificFlavorTestJSON(base.BaseV2ComputeAdminTest):
diff --git a/tempest/api/compute/test_live_block_migration.py b/tempest/api/compute/test_live_block_migration.py
index e04439f..180dffd 100644
--- a/tempest/api/compute/test_live_block_migration.py
+++ b/tempest/api/compute/test_live_block_migration.py
@@ -115,8 +115,7 @@
         actual_host = self._get_host_for_server(server_id)
         target_host = self._get_host_other_than(actual_host)
 
-        resp, volume = self.volumes_client.create_volume(1,
-                                                         display_name='test')
+        volume = self.volumes_client.create_volume(1, display_name='test')
 
         self.volumes_client.wait_for_volume_status(volume['id'],
                                                    'available')
diff --git a/tempest/api/database/base.py b/tempest/api/database/base.py
index c9f16ca..dd4c684 100644
--- a/tempest/api/database/base.py
+++ b/tempest/api/database/base.py
@@ -41,4 +41,5 @@
         cls.os = os
         cls.database_flavors_client = cls.os.database_flavors_client
         cls.os_flavors_client = cls.os.flavors_client
+        cls.database_limits_client = cls.os.database_limits_client
         cls.database_versions_client = cls.os.database_versions_client
diff --git a/tempest/api/database/limits/__init__.py b/tempest/api/database/limits/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/database/limits/__init__.py
diff --git a/tempest/api/database/limits/test_limits.py b/tempest/api/database/limits/test_limits.py
new file mode 100644
index 0000000..30d0a77
--- /dev/null
+++ b/tempest/api/database/limits/test_limits.py
@@ -0,0 +1,45 @@
+# Copyright 2014 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.database import base
+from tempest import test
+
+
+class DatabaseLimitsTest(base.BaseDatabaseTest):
+    _interface = 'json'
+
+    @classmethod
+    def resource_setup(cls):
+        super(DatabaseLimitsTest, cls).resource_setup()
+        cls.client = cls.database_limits_client
+
+    @test.attr(type='smoke')
+    def test_absolute_limits(self):
+        # Test to verify if all absolute limit paramaters are
+        # present when verb is ABSOLUTE
+        _, limits = self.client.list_db_limits()
+        expected_abs_limits = ['max_backups', 'max_volumes',
+                               'max_instances', 'verb']
+        absolute_limit = [l for l in limits
+                          if l['verb'] == 'ABSOLUTE']
+        self.assertEqual(1, len(absolute_limit), "One ABSOLUTE limit "
+                         "verb is allowed. Fetched %s"
+                         % len(absolute_limit))
+        actual_abs_limits = absolute_limit[0].keys()
+        missing_abs_limit = set(expected_abs_limits) - set(actual_abs_limits)
+        self.assertEmpty(missing_abs_limit,
+                         "Failed to find the following absolute limit(s)"
+                         " in a fetched list: %s" %
+                         ', '.join(str(a) for a in missing_abs_limit))
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 64dba7d..d8c7063 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -91,3 +91,22 @@
         user_groups = self.client.list_user_groups(user['id'])
         self.assertEqual(sorted(groups), sorted(user_groups))
         self.assertEqual(2, len(user_groups))
+
+    @test.attr(type='smoke')
+    def test_list_groups(self):
+        # Test to list groups
+        group_ids = list()
+        fetched_ids = list()
+        for _ in range(3):
+            name = data_utils.rand_name('Group')
+            description = data_utils.rand_name('Description')
+            group = self.client.create_group(name,
+                                             description=description)
+            self.addCleanup(self.client.delete_group, group['id'])
+            group_ids.append(group['id'])
+        # List and Verify Groups
+        body = self.client.list_groups()
+        for g in body:
+            fetched_ids.append(g['id'])
+        missing_groups = [g for g in group_ids if g not in fetched_ids]
+        self.assertEqual([], missing_groups)
diff --git a/tempest/api/network/test_dhcp_ipv6.py b/tempest/api/network/test_dhcp_ipv6.py
index 6ce1216..1257699 100644
--- a/tempest/api/network/test_dhcp_ipv6.py
+++ b/tempest/api/network/test_dhcp_ipv6.py
@@ -327,12 +327,11 @@
                                    subnet["allocation_pools"][0]["end"])
         ip = netaddr.IPAddress(random.randrange(
             ip_range.last + 1, ip_range.last + 10)).format()
-        self.assertRaisesRegexp(exceptions.BadRequest,
-                                "not a valid IP for the defined subnet",
-                                self.create_port,
-                                self.network,
-                                fixed_ips=[{'subnet_id': subnet['id'],
-                                            'ip_address': ip}])
+        self.assertRaises(exceptions.BadRequest,
+                          self.create_port,
+                          self.network,
+                          fixed_ips=[{'subnet_id': subnet['id'],
+                                      'ip_address': ip}])
 
     def test_dhcp_stateful_fixedips_duplicate(self):
         """When port gets IP address from fixed IP range it
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index a50e392..7f8cb8b 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -44,10 +44,9 @@
         cls.local_ip = '127.0.0.1'
 
         # Must be configure according to container-sync interval
-        container_sync_timeout = \
-            int(CONF.object_storage.container_sync_timeout)
+        container_sync_timeout = CONF.object_storage.container_sync_timeout
         cls.container_sync_interval = \
-            int(CONF.object_storage.container_sync_interval)
+            CONF.object_storage.container_sync_interval
         cls.attempts = \
             int(container_sync_timeout / cls.container_sync_interval)
 
@@ -66,12 +65,7 @@
             cls.delete_containers(cls.containers, client[0], client[1])
         super(ContainerSyncTest, cls).resource_cleanup()
 
-    @test.attr(type='slow')
-    @test.skip_because(bug='1317133')
-    @testtools.skipIf(
-        not CONF.object_storage_feature_enabled.container_sync,
-        'Old-style container sync function is disabled')
-    def test_container_synchronization(self):
+    def _test_container_synchronization(self, make_headers):
         # container to container synchronization
         # to allow/accept sync requests to/from other accounts
 
@@ -79,15 +73,7 @@
         for cont in (self.containers, self.containers[::-1]):
             cont_client = [self.clients[c][0] for c in cont]
             obj_client = [self.clients[c][1] for c in cont]
-            # tell first container to synchronize to a second
-            client_proxy_ip = \
-                urlparse.urlparse(cont_client[1].base_url).netloc.split(':')[0]
-            client_base_url = \
-                cont_client[1].base_url.replace(client_proxy_ip,
-                                                self.local_ip)
-            headers = {'X-Container-Sync-Key': 'sync_key',
-                       'X-Container-Sync-To': "%s/%s" %
-                       (client_base_url, str(cont[1]))}
+            headers = make_headers(cont[1], cont_client[1])
             resp, body = \
                 cont_client[0].put(str(cont[0]), body=None, headers=headers)
             # create object in container
@@ -101,21 +87,19 @@
         params = {'format': 'json'}
         while self.attempts > 0:
             object_lists = []
-            for client_index in (0, 1):
-                resp, object_list = \
-                    cont_client[client_index].\
-                    list_container_contents(self.containers[client_index],
-                                            params=params)
+            for c_client, cont in zip(cont_client, self.containers):
+                resp, object_list = c_client.list_container_contents(
+                    cont, params=params)
                 object_lists.append(dict(
                     (obj['name'], obj) for obj in object_list))
             # check that containers are not empty and have equal keys()
             # or wait for next attempt
-            if not object_lists[0] or not object_lists[1] or \
-                    set(object_lists[0].keys()) != set(object_lists[1].keys()):
+            if object_lists[0] and object_lists[1] and \
+                    set(object_lists[0].keys()) == set(object_lists[1].keys()):
+                break
+            else:
                 time.sleep(self.container_sync_interval)
                 self.attempts -= 1
-            else:
-                break
 
         self.assertEqual(object_lists[0], object_lists[1],
                          'Different object lists in containers.')
@@ -126,3 +110,22 @@
             for obj_name in object_lists[0]:
                 resp, object_content = obj_client.get_object(cont, obj_name)
                 self.assertEqual(object_content, obj_name[::-1])
+
+    @test.attr(type='slow')
+    @test.skip_because(bug='1317133')
+    @testtools.skipIf(
+        not CONF.object_storage_feature_enabled.container_sync,
+        'Old-style container sync function is disabled')
+    def test_container_synchronization(self):
+        def make_headers(cont, cont_client):
+            # tell first container to synchronize to a second
+            client_proxy_ip = \
+                urlparse.urlparse(cont_client.base_url).netloc.split(':')[0]
+            client_base_url = \
+                cont_client.base_url.replace(client_proxy_ip,
+                                             self.local_ip)
+            headers = {'X-Container-Sync-Key': 'sync_key',
+                       'X-Container-Sync-To': "%s/%s" %
+                       (client_base_url, str(cont))}
+            return headers
+        self._test_container_synchronization(make_headers)
diff --git a/tempest/api/object_storage/test_container_sync_middleware.py b/tempest/api/object_storage/test_container_sync_middleware.py
new file mode 100644
index 0000000..41509a0
--- /dev/null
+++ b/tempest/api/object_storage/test_container_sync_middleware.py
@@ -0,0 +1,51 @@
+# Copyright(c)2015 NTT corp. All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.object_storage import test_container_sync
+from tempest import config
+from tempest import test
+
+CONF = config.CONF
+
+
+# This test can be quite long to run due to its
+# dependency on container-sync process running interval.
+# You can obviously reduce the container-sync interval in the
+# container-server configuration.
+
+
+class ContainerSyncMiddlewareTest(test_container_sync.ContainerSyncTest):
+
+    @classmethod
+    def resource_setup(cls):
+        super(ContainerSyncMiddlewareTest, cls).resource_setup()
+
+        # Set container-sync-realms.conf info
+        cls.realm_name = CONF.object_storage.realm_name
+        cls.key = 'sync_key'
+        cls.cluster_name = CONF.object_storage.cluster_name
+
+    @test.attr(type='slow')
+    @test.requires_ext(extension='container_sync', service='object')
+    def test_container_synchronization(self):
+        def make_headers(cont, cont_client):
+            # tell first container to synchronize to a second
+            account_name = cont_client.base_url.split('/')[-1]
+
+            headers = {'X-Container-Sync-Key': "%s" % (self.key),
+                       'X-Container-Sync-To': "//%s/%s/%s/%s" %
+                       (self.realm_name, self.cluster_name,
+                        str(account_name), str(cont))}
+            return headers
+        self._test_container_synchronization(make_headers)
diff --git a/tempest/cli/simple_read_only/compute/test_nova.py b/tempest/cli/simple_read_only/compute/test_nova.py
index 4fe4982..5efeb75 100644
--- a/tempest/cli/simple_read_only/compute/test_nova.py
+++ b/tempest/cli/simple_read_only/compute/test_nova.py
@@ -149,7 +149,7 @@
     def test_admin_secgroup_list_rules(self):
         self.nova('secgroup-list-rules')
 
-    @tempest.cli.min_client_version(client='nova', version='2.18')
+    @cli.min_client_version(client='nova', version='2.18')
     def test_admin_server_group_list(self):
         self.nova('server-group-list')
 
diff --git a/tempest/cli/simple_read_only/data_processing/test_sahara.py b/tempest/cli/simple_read_only/data_processing/test_sahara.py
index 1f2403c..c06c2c9 100644
--- a/tempest/cli/simple_read_only/data_processing/test_sahara.py
+++ b/tempest/cli/simple_read_only/data_processing/test_sahara.py
@@ -16,6 +16,7 @@
 import re
 
 from tempest_lib import exceptions
+import testtools
 
 from tempest import cli
 from tempest import config
@@ -59,8 +60,12 @@
             'title'
         ])
 
+    @testtools.skipUnless(CONF.data_processing_feature_enabled.plugins,
+                          'No plugins defined')
     def test_sahara_plugins_show(self):
-        result = self.sahara('plugin-show', params='--name vanilla')
+        name_param = '--name %s' % \
+            (CONF.data_processing_feature_enabled.plugins[0])
+        result = self.sahara('plugin-show', params=name_param)
         plugin = self.parser.listing(result)
         self.assertTableStruct(plugin, [
             'Property',
diff --git a/tempest/clients.py b/tempest/clients.py
index 135d74a..894bdb7 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -20,7 +20,8 @@
 from tempest import config
 from tempest import manager
 from tempest.openstack.common import log as logging
-from tempest.services.baremetal.v1.client_json import BaremetalClientJSON
+from tempest.services.baremetal.v1.json.baremetal_client import \
+    BaremetalClientJSON
 from tempest.services import botoclients
 from tempest.services.compute.json.agents_client import \
     AgentsClientJSON
@@ -66,6 +67,8 @@
 from tempest.services.data_processing.v1_1.client import DataProcessingClient
 from tempest.services.database.json.flavors_client import \
     DatabaseFlavorsClientJSON
+from tempest.services.database.json.limits_client import \
+    DatabaseLimitsClientJSON
 from tempest.services.database.json.versions_client import \
     DatabaseVersionsClientJSON
 from tempest.services.identity.json.identity_client import IdentityClientJSON
@@ -159,10 +162,17 @@
         super(Manager, self).__init__(credentials=credentials)
 
         self._set_compute_clients()
+        self._set_database_clients()
         self._set_identity_clients()
         self._set_volume_clients()
+        self._set_object_storage_clients()
 
-        self.baremetal_client = BaremetalClientJSON(self.auth_provider)
+        self.baremetal_client = BaremetalClientJSON(
+            self.auth_provider,
+            CONF.baremetal.catalog_type,
+            CONF.identity.region,
+            endpoint_type=CONF.baremetal.endpoint_type,
+            **self.default_params_with_timeout_values)
         self.network_client = NetworkClientJSON(
             self.auth_provider,
             CONF.network.catalog_type,
@@ -171,36 +181,21 @@
             build_interval=CONF.network.build_interval,
             build_timeout=CONF.network.build_timeout,
             **self.default_params)
-        self.database_flavors_client = DatabaseFlavorsClientJSON(
+        self.messaging_client = MessagingClientJSON(
             self.auth_provider,
-            CONF.database.catalog_type,
+            CONF.messaging.catalog_type,
             CONF.identity.region,
             **self.default_params_with_timeout_values)
-        self.database_versions_client = DatabaseVersionsClientJSON(
-            self.auth_provider,
-            CONF.database.catalog_type,
-            CONF.identity.region,
-            **self.default_params_with_timeout_values)
-        self.messaging_client = MessagingClientJSON(self.auth_provider)
         if CONF.service_available.ceilometer:
             self.telemetry_client = TelemetryClientJSON(
-                self.auth_provider)
-        self.negative_client = negative_rest_client.NegativeRestClient(
-            self.auth_provider, service)
-
-        # TODO(andreaf) EC2 client still do their auth, v2 only
-        ec2_client_args = (self.credentials.username,
-                           self.credentials.password,
-                           CONF.identity.uri,
-                           self.credentials.tenant_name)
-
-        # common clients
-        self.account_client = AccountClient(self.auth_provider)
+                self.auth_provider,
+                CONF.telemetry.catalog_type,
+                CONF.identity.region,
+                endpoint_type=CONF.telemetry.endpoint_type,
+                **self.default_params_with_timeout_values)
         if CONF.service_available.glance:
             self.image_client = ImageClientJSON(self.auth_provider)
             self.image_client_v2 = ImageClientV2JSON(self.auth_provider)
-        self.container_client = ContainerClient(self.auth_provider)
-        self.object_client = ObjectClient(self.auth_provider)
         self.orchestration_client = OrchestrationClient(
             self.auth_provider,
             CONF.orchestration.catalog_type,
@@ -209,7 +204,14 @@
             build_interval=CONF.orchestration.build_interval,
             build_timeout=CONF.orchestration.build_timeout,
             **self.default_params)
+        self.negative_client = negative_rest_client.NegativeRestClient(
+            self.auth_provider, service)
 
+        # TODO(andreaf) EC2 client still do their auth, v2 only
+        ec2_client_args = (self.credentials.username,
+                           self.credentials.password,
+                           CONF.identity.uri,
+                           self.credentials.tenant_name)
         self.ec2api_client = botoclients.APIClientEC2(*ec2_client_args)
         self.s3_client = botoclients.ObjectClientS3(*ec2_client_args)
         self.data_processing_client = DataProcessingClient(
@@ -276,6 +278,23 @@
         self.volumes_extensions_client = VolumesExtensionsClientJSON(
             self.auth_provider, **params_volume)
 
+    def _set_database_clients(self):
+        self.database_flavors_client = DatabaseFlavorsClientJSON(
+            self.auth_provider,
+            CONF.database.catalog_type,
+            CONF.identity.region,
+            **self.default_params_with_timeout_values)
+        self.database_limits_client = DatabaseLimitsClientJSON(
+            self.auth_provider,
+            CONF.database.catalog_type,
+            CONF.identity.region,
+            **self.default_params_with_timeout_values)
+        self.database_versions_client = DatabaseVersionsClientJSON(
+            self.auth_provider,
+            CONF.database.catalog_type,
+            CONF.identity.region,
+            **self.default_params_with_timeout_values)
+
     def _set_identity_clients(self):
         self.identity_client = IdentityClientJSON(self.auth_provider)
         self.identity_v3_client = IdentityV3ClientJSON(self.auth_provider)
@@ -319,6 +338,18 @@
         self.volume_types_v2_client = VolumeTypesV2ClientJSON(
             self.auth_provider)
 
+    def _set_object_storage_clients(self):
+        params = {
+            'service': CONF.object_storage.catalog_type,
+            'region': CONF.object_storage.region or CONF.identity.region,
+            'endpoint_type': CONF.object_storage.endpoint_type
+        }
+        params.update(self.default_params_with_timeout_values)
+
+        self.account_client = AccountClient(self.auth_provider, **params)
+        self.container_client = ContainerClient(self.auth_provider, **params)
+        self.object_client = ObjectClient(self.auth_provider, **params)
+
 
 class AdminManager(Manager):
 
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index e5ffb1b..9fb982c 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -150,6 +150,12 @@
             'ca_certs': CONF.identity.ca_certificates_file,
             'trace_requests': CONF.debug.trace_requests
         }
+        default_params_with_timeout_values = {
+            'build_interval': CONF.compute.build_interval,
+            'build_timeout': CONF.compute.build_timeout
+        }
+        default_params_with_timeout_values.update(default_params)
+
         compute_params = {
             'service': CONF.compute.catalog_type,
             'region': CONF.compute.region or CONF.identity.region,
@@ -159,6 +165,13 @@
         }
         compute_params.update(default_params)
 
+        object_storage_params = {
+            'service': CONF.object_storage.catalog_type,
+            'region': CONF.object_storage.region or CONF.identity.region,
+            'endpoint_type': CONF.object_storage.endpoint_type
+        }
+        object_storage_params.update(default_params)
+
         _creds = tempest.auth.KeystoneV2Credentials(
             username=user,
             password=pw,
@@ -171,10 +184,17 @@
                                                         **compute_params)
         self.secgroups = security_groups_client.SecurityGroupsClientJSON(
             _auth, **compute_params)
-        self.objects = object_client.ObjectClient(_auth)
-        self.containers = container_client.ContainerClient(_auth)
+        self.objects = object_client.ObjectClient(_auth,
+                                                  **object_storage_params)
+        self.containers = container_client.ContainerClient(
+            _auth, **object_storage_params)
         self.images = image_client.ImageClientV2JSON(_auth)
-        self.telemetry = telemetry_client.TelemetryClientJSON(_auth)
+        self.telemetry = telemetry_client.TelemetryClientJSON(
+            _auth,
+            CONF.telemetry.catalog_type,
+            CONF.identity.region,
+            endpoint_type=CONF.telemetry.endpoint_type,
+            **default_params_with_timeout_values)
         self.volumes = volumes_client.VolumesClientJSON(_auth)
         self.networks = network_client.NetworkClientJSON(
             _auth,
@@ -187,7 +207,7 @@
 
 
 def load_resources(fname):
-    """Load the expected resources from a yaml flie."""
+    """Load the expected resources from a yaml file."""
     return yaml.load(open(fname, 'r'))
 
 
@@ -423,7 +443,7 @@
                 self._ping_ip(addr, 60)
 
     def check_secgroups(self):
-        """Check that the security groups are still existing."""
+        """Check that the security groups still exist."""
         LOG.info("Checking security groups")
         for secgroup in self.res['secgroups']:
             client = client_for_user(secgroup['owner'])
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index a7e0ee3..65a3a95 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -335,7 +335,7 @@
             continue
         results = verify_extensions(os, service, results)
 
-    # Verify API verisons of all services in the keystone catalog and keystone
+    # Verify API versions of all services in the keystone catalog and keystone
     # itself.
     services.append('keystone')
     for service in services:
diff --git a/tempest/common/negative_rest_client.py b/tempest/common/negative_rest_client.py
index d9842e6..a02e494 100644
--- a/tempest/common/negative_rest_client.py
+++ b/tempest/common/negative_rest_client.py
@@ -15,18 +15,16 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-from tempest_lib.common import rest_client
-
+from tempest.common import service_client
 from tempest import config
 
 CONF = config.CONF
 
 
-class NegativeRestClient(rest_client.RestClient):
+class NegativeRestClient(service_client.ServiceClient):
     """
     Version of RestClient that does not raise exceptions.
     """
-
     def __init__(self, auth_provider, service):
         region = self._get_region(service)
         super(NegativeRestClient, self).__init__(auth_provider,
diff --git a/tempest/common/service_client.py b/tempest/common/service_client.py
index 45a07f1..dc634a1 100644
--- a/tempest/common/service_client.py
+++ b/tempest/common/service_client.py
@@ -69,20 +69,16 @@
             raise exceptions.Conflict(ex)
         except lib_exceptions.OverLimit as ex:
             raise exceptions.OverLimit(ex)
-        except lib_exceptions.RateLimitExceeded as ex:
-            raise exceptions.RateLimitExceeded(ex)
         except lib_exceptions.InvalidContentType as ex:
             raise exceptions.InvalidContentType(ex)
         except lib_exceptions.UnprocessableEntity as ex:
             raise exceptions.UnprocessableEntity(ex)
-        except lib_exceptions.InvalidHTTPResponseBody as ex:
-            raise exceptions.InvalidHTTPResponseBody(ex)
-        except lib_exceptions.NotImplemented as ex:
-            raise exceptions.NotImplemented(ex)
-        except lib_exceptions.ServerFault as ex:
-            raise exceptions.ServerFault(ex)
-        except lib_exceptions.UnexpectedResponseCode as ex:
-            raise exceptions.UnexpectedResponseCode(ex)
+        # TODO(oomichi): This is just a workaround for failing gate tests
+        # when separating Forbidden from Unauthorized in tempest-lib.
+        # We will need to remove this translation and replace negative tests
+        # with lib_exceptions.Forbidden in the future.
+        except lib_exceptions.Forbidden as ex:
+            raise exceptions.Unauthorized(ex)
 
 
 class ResponseBody(dict):
diff --git a/tempest/config.py b/tempest/config.py
index 1b6ec62..70f972f 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -601,7 +601,7 @@
                         'publicURL', 'adminURL', 'internalURL'],
                help="The endpoint type to use for the object-store service."),
     cfg.IntOpt('container_sync_timeout',
-               default=120,
+               default=600,
                help="Number of seconds to time on waiting for a container "
                     "to container synchronization complete."),
     cfg.IntOpt('container_sync_interval',
@@ -615,6 +615,17 @@
     cfg.StrOpt('reseller_admin_role',
                default='ResellerAdmin',
                help="User role that has reseller admin"),
+    cfg.StrOpt('realm_name',
+               default='realm1',
+               help="Name of sync realm. A sync realm is a set of clusters "
+                    "that have agreed to allow container syncing with each "
+                    "other. Set the same realm name as Swift's "
+                    "container-sync-realms.conf"),
+    cfg.StrOpt('cluster_name',
+               default='name1',
+               help="One name of cluster which is set in the realm whose name "
+                    "is set in 'realm_name' item in this file. Set the "
+                    "same cluster name as Swift's container-sync-realms.conf"),
 ]
 
 object_storage_feature_group = cfg.OptGroup(
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 86f488a..680b92a 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -167,22 +167,10 @@
     message = "Unprocessable entity"
 
 
-class RateLimitExceeded(RestClientException):
-    message = "Rate limit exceeded"
-
-
 class OverLimit(RestClientException):
     message = "Quota exceeded"
 
 
-class ServerFault(RestClientException):
-    message = "Got server fault"
-
-
-class NotImplemented(RestClientException):
-    message = "Got NotImplemented error"
-
-
 class Conflict(RestClientException):
     message = "An object with that identifier already exists"
 
@@ -197,10 +185,6 @@
                "MUST NOT have an entity")
 
 
-class InvalidHTTPResponseBody(RestClientException):
-    message = "HTTP response body is invalid json or xml"
-
-
 class InvalidHTTPResponseHeader(RestClientException):
     message = "HTTP response header is invalid"
 
@@ -209,10 +193,6 @@
     message = "Invalid content type provided"
 
 
-class UnexpectedResponseCode(RestClientException):
-    message = "Unexpected response code received"
-
-
 class InvalidStructure(TempestException):
     message = "Invalid structure of table with details"
 
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index ebc6b15..de211fb 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -247,9 +247,11 @@
 
         if not test.call_until_true(check_ports, CONF.network.build_timeout,
                                     CONF.network.build_interval):
-            raise exceptions.TimeoutException("No new port attached to the "
-                                              "server in time (%s sec) !"
-                                              % CONF.network.build_timeout)
+            raise exceptions.TimeoutException(
+                "No new port attached to the server in time (%s sec)! "
+                "Old port: %s. Number of new ports: %d" % (
+                    CONF.network.build_timeout, old_port,
+                    len(self.new_port_list)))
         new_port = net_resources.DeletablePort(client=self.network_client,
                                                **self.new_port_list[0])
 
@@ -485,3 +487,31 @@
         # definitions from subnet
         ssh_client.renew_lease(fixed_ip=floating_ip['fixed_ip_address'])
         self._check_dns_server(ssh_client, [alt_dns_server])
+
+    @test.attr(type='smoke')
+    @test.services('compute', 'network')
+    def test_update_instance_port_admin_state(self):
+        """
+        1. Check public connectivity before updating
+                admin_state_up attribute of instance port to False
+        2. Check public connectivity after updating
+                admin_state_up attribute of instance port to False
+        3. Check public connectivity after updating
+                admin_state_up attribute of instance port to True
+        """
+        self._setup_network_and_servers()
+        floating_ip, server = self.floating_ip_tuple
+        server_id = server['id']
+        port_id = self._list_ports(device_id=server_id)[0]['id']
+        self.check_public_network_connectivity(
+            should_connect=True, msg="before updating "
+            "admin_state_up of instance port to False")
+        self.network_client.update_port(port_id, admin_state_up=False)
+        self.check_public_network_connectivity(
+            should_connect=False, msg="after updating "
+            "admin_state_up of instance port to False",
+            should_check_floating_ip_status=False)
+        self.network_client.update_port(port_id, admin_state_up=True)
+        self.check_public_network_connectivity(
+            should_connect=True, msg="after updating "
+            "admin_state_up of instance port to True")
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index de6b0f9..83739fd 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -70,7 +70,7 @@
             * test that cross-tenant traffic is enabled once an appropriate
             rule has been created on destination tenant.
             * test that reverse traffic is still blocked
-            * test than revesre traffic is enabled once an appropriate rule has
+            * test than reverse traffic is enabled once an appropriate rule has
             been created on source tenant
         7._test_port_update_new_security_group:
            * test that traffic is blocked with default security group
@@ -85,7 +85,7 @@
             to it, and cross tenant check will be done on the private IP of the
             destination tenant
             or
-            * not defined (empty string), in which case each tanant will have
+            * not defined (empty string), in which case each tenant will have
             its own router connected to the public network
     """
 
@@ -466,7 +466,7 @@
     def test_port_update_new_security_group(self):
         """
         This test verifies the traffic after updating the vm port with new
-        security group having appropiate rule.
+        security group having appropriate rule.
         """
         new_tenant = self.primary_tenant
 
diff --git a/tempest/services/baremetal/base.py b/tempest/services/baremetal/base.py
index a0ffd28..4c6a5bf 100644
--- a/tempest/services/baremetal/base.py
+++ b/tempest/services/baremetal/base.py
@@ -17,9 +17,6 @@
 import six
 
 from tempest.common import service_client
-from tempest import config
-
-CONF = config.CONF
 
 
 def handle_errors(f):
@@ -48,23 +45,17 @@
 
     """
 
-    def __init__(self, auth_provider):
-        super(BaremetalClient, self).__init__(
-            auth_provider,
-            CONF.baremetal.catalog_type,
-            CONF.identity.region,
-            endpoint_type=CONF.baremetal.endpoint_type)
-        self.uri_prefix = ''
+    uri_prefix = ''
 
-    def serialize(self, object_type, object_dict):
+    def serialize(self, object_dict):
         """Serialize an Ironic object."""
 
-        raise NotImplementedError
+        return json.dumps(object_dict)
 
     def deserialize(self, object_str):
         """Deserialize an Ironic object."""
 
-        raise NotImplementedError
+        return json.loads(object_str)
 
     def _get_uri(self, resource_name, uuid=None, permanent=False):
         """
@@ -147,7 +138,7 @@
 
         return resp, self.deserialize(body)
 
-    def _create_request(self, resource, object_type, object_dict):
+    def _create_request(self, resource, object_dict):
         """
         Create an object of the specified type.
 
@@ -158,7 +149,7 @@
                  object.
 
         """
-        body = self.serialize(object_type, object_dict)
+        body = self.serialize(object_dict)
         uri = self._get_uri(resource)
 
         resp, body = self.post(uri, body=body)
diff --git a/tempest/services/baremetal/v1/client_json.py b/tempest/services/baremetal/v1/client_json.py
deleted file mode 100644
index c9dc874..0000000
--- a/tempest/services/baremetal/v1/client_json.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-import json
-
-from tempest.services.baremetal.v1 import base_v1
-
-
-class BaremetalClientJSON(base_v1.BaremetalClientV1):
-    """Tempest REST client for Ironic JSON API v1."""
-
-    def __init__(self, auth_provider):
-        super(BaremetalClientJSON, self).__init__(auth_provider)
-
-        self.serialize = lambda obj_type, obj_body: json.dumps(obj_body)
-        self.deserialize = json.loads
diff --git a/tempest/services/baremetal/v1/json/__init__.py b/tempest/services/baremetal/v1/json/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/services/baremetal/v1/json/__init__.py
diff --git a/tempest/services/baremetal/v1/base_v1.py b/tempest/services/baremetal/v1/json/baremetal_client.py
similarity index 95%
rename from tempest/services/baremetal/v1/base_v1.py
rename to tempest/services/baremetal/v1/json/baremetal_client.py
index 9435dbf..1c72a2b 100644
--- a/tempest/services/baremetal/v1/base_v1.py
+++ b/tempest/services/baremetal/v1/json/baremetal_client.py
@@ -13,18 +13,12 @@
 from tempest.services.baremetal import base
 
 
-class BaremetalClientV1(base.BaremetalClient):
+class BaremetalClientJSON(base.BaremetalClient):
     """
     Base Tempest REST client for Ironic API v1.
-
-    Specific implementations must implement serialize and deserialize
-    methods in order to send requests to Ironic.
-
     """
-    def __init__(self, auth_provider):
-        super(BaremetalClientV1, self).__init__(auth_provider)
-        self.version = '1'
-        self.uri_prefix = 'v%s' % self.version
+    version = '1'
+    uri_prefix = 'v1'
 
     @base.handle_errors
     def list_nodes(self, **kwargs):
@@ -156,7 +150,7 @@
                                'memory': kwargs.get('memory', 4096)},
                 'driver': kwargs.get('driver', 'fake')}
 
-        return self._create_request('nodes', 'node', node)
+        return self._create_request('nodes', node)
 
     @base.handle_errors
     def create_chassis(self, **kwargs):
@@ -170,7 +164,7 @@
         """
         chassis = {'description': kwargs.get('description', 'test-chassis')}
 
-        return self._create_request('chassis', 'chassis', chassis)
+        return self._create_request('chassis', chassis)
 
     @base.handle_errors
     def create_port(self, node_id, **kwargs):
@@ -193,7 +187,7 @@
         if kwargs['address'] is not None:
             port['address'] = kwargs['address']
 
-        return self._create_request('ports', 'port', port)
+        return self._create_request('ports', port)
 
     @base.handle_errors
     def delete_node(self, uuid):
diff --git a/tempest/services/database/json/limits_client.py b/tempest/services/database/json/limits_client.py
new file mode 100644
index 0000000..4daf028
--- /dev/null
+++ b/tempest/services/database/json/limits_client.py
@@ -0,0 +1,33 @@
+# Copyright 2014 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import urllib
+
+from tempest import config
+from tempest_lib.common import rest_client
+
+CONF = config.CONF
+
+
+class DatabaseLimitsClientJSON(rest_client.RestClient):
+
+    def list_db_limits(self, params=None):
+        """List all limits."""
+        url = 'limits'
+        if params:
+            url += '?%s' % urllib.urlencode(params)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        return resp, self._parse_resp(body)
diff --git a/tempest/services/identity/v3/json/identity_client.py b/tempest/services/identity/v3/json/identity_client.py
index 4d333c0..6010249 100644
--- a/tempest/services/identity/v3/json/identity_client.py
+++ b/tempest/services/identity/v3/json/identity_client.py
@@ -316,6 +316,13 @@
         body = json.loads(body)
         return service_client.ResponseBody(resp, body['group'])
 
+    def list_groups(self):
+        """Lists the groups."""
+        resp, body = self.get('groups')
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return service_client.ResponseBodyList(resp, body['groups'])
+
     def update_group(self, group_id, **kwargs):
         """Updates a group."""
         body = self.get_group(group_id)
diff --git a/tempest/services/messaging/json/messaging_client.py b/tempest/services/messaging/json/messaging_client.py
index c4c9f09..36444a9 100644
--- a/tempest/services/messaging/json/messaging_client.py
+++ b/tempest/services/messaging/json/messaging_client.py
@@ -15,27 +15,32 @@
 
 import json
 import urllib
+import uuid
 
 from tempest.api_schema.response.messaging.v1 import queues as queues_schema
 from tempest.common import service_client
-from tempest.common.utils import data_utils
-from tempest import config
-
-
-CONF = config.CONF
 
 
 class MessagingClientJSON(service_client.ServiceClient):
 
-    def __init__(self, auth_provider):
+    def __init__(self, auth_provider, service, region,
+                 endpoint_type=None, build_interval=None, build_timeout=None,
+                 disable_ssl_certificate_validation=None, ca_certs=None,
+                 trace_requests=None):
+        dscv = disable_ssl_certificate_validation
         super(MessagingClientJSON, self).__init__(
-            auth_provider,
-            CONF.messaging.catalog_type,
-            CONF.identity.region)
+            auth_provider, service, region,
+            endpoint_type=endpoint_type,
+            build_interval=build_interval,
+            build_timeout=build_timeout,
+            disable_ssl_certificate_validation=dscv,
+            ca_certs=ca_certs,
+            trace_requests=trace_requests)
+
         self.version = '1'
         self.uri_prefix = 'v{0}'.format(self.version)
 
-        client_id = data_utils.rand_uuid_hex()
+        client_id = uuid.uuid4().hex
         self.headers = {'Client-ID': client_id}
 
     def list_queues(self):
diff --git a/tempest/services/object_storage/account_client.py b/tempest/services/object_storage/account_client.py
index c24bbba..af00eff 100644
--- a/tempest/services/object_storage/account_client.py
+++ b/tempest/services/object_storage/account_client.py
@@ -17,13 +17,10 @@
 import urllib
 from xml.etree import ElementTree as etree
 
-from tempest import config
-from tempest.services.object_storage import base
-
-CONF = config.CONF
+from tempest.common import service_client
 
 
-class AccountClient(base.ObjectStorageClient):
+class AccountClient(service_client.ServiceClient):
 
     def create_account(self, data=None,
                        params=None,
diff --git a/tempest/services/object_storage/base.py b/tempest/services/object_storage/base.py
deleted file mode 100644
index 1e7355e..0000000
--- a/tempest/services/object_storage/base.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2014 NEC Corporation.  All rights reserved.
-#
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
-#    not use this file except in compliance with the License. You may obtain
-#    a copy of the License at
-#
-#         http://www.apache.org/licenses/LICENSE-2.0
-#
-#    Unless required by applicable law or agreed to in writing, software
-#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-#    License for the specific language governing permissions and limitations
-#    under the License.
-
-from tempest.common import service_client
-from tempest import config
-
-CONF = config.CONF
-
-
-class ObjectStorageClient(service_client.ServiceClient):
-    """
-    Base object storage client class
-    """
-
-    def __init__(self, auth_provider):
-        super(ObjectStorageClient, self).__init__(
-            auth_provider,
-            CONF.object_storage.catalog_type,
-            CONF.object_storage.region or CONF.identity.region,
-            endpoint_type=CONF.object_storage.endpoint_type)
-        self.format = 'json'
diff --git a/tempest/services/object_storage/container_client.py b/tempest/services/object_storage/container_client.py
index c55826b..ed74de4 100644
--- a/tempest/services/object_storage/container_client.py
+++ b/tempest/services/object_storage/container_client.py
@@ -17,10 +17,10 @@
 import urllib
 from xml.etree import ElementTree as etree
 
-from tempest.services.object_storage import base
+from tempest.common import service_client
 
 
-class ContainerClient(base.ObjectStorageClient):
+class ContainerClient(service_client.ServiceClient):
 
     def create_container(
             self, container_name,
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index bb74fd7..eaa894d 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -17,13 +17,10 @@
 import urllib
 import urlparse
 
-from tempest import config
-from tempest.services.object_storage import base
-
-CONF = config.CONF
+from tempest.common import service_client
 
 
-class ObjectClient(base.ObjectStorageClient):
+class ObjectClient(service_client.ServiceClient):
 
     def create_object(self, container, object_name, data,
                       params=None, metadata=None, headers=None):
diff --git a/tempest/services/telemetry/json/telemetry_client.py b/tempest/services/telemetry/json/telemetry_client.py
index 2bbd88d..2967cfa 100644
--- a/tempest/services/telemetry/json/telemetry_client.py
+++ b/tempest/services/telemetry/json/telemetry_client.py
@@ -16,22 +16,13 @@
 import urllib
 
 from tempest.common import service_client
-from tempest import config
 from tempest.openstack.common import jsonutils as json
 
-CONF = config.CONF
-
 
 class TelemetryClientJSON(service_client.ServiceClient):
 
-    def __init__(self, auth_provider):
-        super(TelemetryClientJSON, self).__init__(
-            auth_provider,
-            CONF.telemetry.catalog_type,
-            CONF.identity.region,
-            endpoint_type=CONF.telemetry.endpoint_type)
-        self.version = '2'
-        self.uri_prefix = "v%s" % self.version
+    version = '2'
+    uri_prefix = "v2"
 
     def deserialize(self, body):
         return json.loads(body.replace("\n", ""))
diff --git a/tempest/stress/actions/volume_create_delete.py b/tempest/stress/actions/volume_create_delete.py
index b1c5bb7..93402d9 100644
--- a/tempest/stress/actions/volume_create_delete.py
+++ b/tempest/stress/actions/volume_create_delete.py
@@ -20,8 +20,8 @@
         name = data_utils.rand_name("volume")
         self.logger.info("creating %s" % name)
         volumes_client = self.manager.volumes_client
-        _, volume = volumes_client.create_volume(size=1,
-                                                 display_name=name)
+        volume = volumes_client.create_volume(size=1,
+                                              display_name=name)
         vol_id = volume['id']
         volumes_client.wait_for_volume_status(vol_id, 'available')
         self.logger.info("created %s" % volume['id'])
diff --git a/tempest/tests/common/test_service_clients.py b/tempest/tests/common/test_service_clients.py
new file mode 100644
index 0000000..8a2782d
--- /dev/null
+++ b/tempest/tests/common/test_service_clients.py
@@ -0,0 +1,114 @@
+# Copyright 2015 NEC Corporation.  All rights reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import mock
+import random
+import six
+
+from tempest.services.baremetal.v1.json import baremetal_client
+from tempest.services.compute.json import agents_client
+from tempest.services.compute.json import aggregates_client
+from tempest.services.compute.json import availability_zone_client
+from tempest.services.compute.json import certificates_client
+from tempest.services.compute.json import extensions_client
+from tempest.services.compute.json import fixed_ips_client
+from tempest.services.compute.json import flavors_client
+from tempest.services.compute.json import floating_ips_client
+from tempest.services.compute.json import hosts_client
+from tempest.services.compute.json import hypervisor_client
+from tempest.services.compute.json import images_client
+from tempest.services.compute.json import instance_usage_audit_log_client
+from tempest.services.compute.json import interfaces_client
+from tempest.services.compute.json import keypairs_client
+from tempest.services.compute.json import limits_client
+from tempest.services.compute.json import migrations_client
+from tempest.services.compute.json import networks_client as nova_net_client
+from tempest.services.compute.json import quotas_client
+from tempest.services.compute.json import security_group_default_rules_client \
+    as nova_secgrop_default_client
+from tempest.services.compute.json import security_groups_client
+from tempest.services.compute.json import servers_client
+from tempest.services.compute.json import services_client
+from tempest.services.compute.json import tenant_usages_client
+from tempest.services.compute.json import volumes_extensions_client
+from tempest.services.database.json import flavors_client as db_flavor_client
+from tempest.services.database.json import versions_client as db_version_client
+from tempest.services.messaging.json import messaging_client
+from tempest.services.network.json import network_client
+from tempest.services.object_storage import account_client
+from tempest.services.object_storage import container_client
+from tempest.services.object_storage import object_client
+from tempest.services.orchestration.json import orchestration_client
+from tempest.services.telemetry.json import telemetry_client
+from tempest.tests import base
+
+
+class TestServiceClient(base.TestCase):
+
+    @mock.patch('tempest_lib.common.rest_client.RestClient.__init__')
+    def test_service_client_creations_with_specified_args(self, mock_init):
+        test_clients = [
+            baremetal_client.BaremetalClientJSON,
+            agents_client.AgentsClientJSON,
+            aggregates_client.AggregatesClientJSON,
+            availability_zone_client.AvailabilityZoneClientJSON,
+            certificates_client.CertificatesClientJSON,
+            extensions_client.ExtensionsClientJSON,
+            fixed_ips_client.FixedIPsClientJSON,
+            flavors_client.FlavorsClientJSON,
+            floating_ips_client.FloatingIPsClientJSON,
+            hosts_client.HostsClientJSON,
+            hypervisor_client.HypervisorClientJSON,
+            images_client.ImagesClientJSON,
+            instance_usage_audit_log_client.InstanceUsagesAuditLogClientJSON,
+            interfaces_client.InterfacesClientJSON,
+            keypairs_client.KeyPairsClientJSON,
+            limits_client.LimitsClientJSON,
+            migrations_client.MigrationsClientJSON,
+            nova_net_client.NetworksClientJSON,
+            quotas_client.QuotasClientJSON,
+            quotas_client.QuotaClassesClientJSON,
+            nova_secgrop_default_client.SecurityGroupDefaultRulesClientJSON,
+            security_groups_client.SecurityGroupsClientJSON,
+            servers_client.ServersClientJSON,
+            services_client.ServicesClientJSON,
+            tenant_usages_client.TenantUsagesClientJSON,
+            volumes_extensions_client.VolumesExtensionsClientJSON,
+            db_flavor_client.DatabaseFlavorsClientJSON,
+            db_version_client.DatabaseVersionsClientJSON,
+            messaging_client.MessagingClientJSON,
+            network_client.NetworkClientJSON,
+            account_client.AccountClient,
+            container_client.ContainerClient,
+            object_client.ObjectClient,
+            orchestration_client.OrchestrationClient,
+            telemetry_client.TelemetryClientJSON]
+
+        for client in test_clients:
+            fake_string = six.text_type(random.randint(1, 0x7fffffff))
+            auth = 'auth' + fake_string
+            service = 'service' + fake_string
+            region = 'region' + fake_string
+            params = {
+                'endpoint_type': 'URL' + fake_string,
+                'build_interval': random.randint(1, 100),
+                'build_timeout': random.randint(1, 100),
+                'disable_ssl_certificate_validation':
+                    True if random.randint(0, 1) else False,
+                'ca_certs': None,
+                'trace_requests': 'foo' + fake_string
+            }
+            client(auth, service, region, **params)
+            mock_init.assert_called_once_with(auth, service, region, **params)
+            mock_init.reset_mock()
diff --git a/tempest/thirdparty/boto/test_ec2_keys.py b/tempest/thirdparty/boto/test_ec2_keys.py
index c3e1e2a..be5db55 100644
--- a/tempest/thirdparty/boto/test_ec2_keys.py
+++ b/tempest/thirdparty/boto/test_ec2_keys.py
@@ -14,7 +14,6 @@
 #    under the License.
 
 from tempest.common.utils import data_utils
-from tempest import test
 from tempest.thirdparty.boto import test as boto_test
 
 
@@ -40,7 +39,6 @@
         self.assertTrue(compare_key_pairs(keypair,
                         self.client.get_key_pair(key_name)))
 
-    @test.skip_because(bug="1072318")
     def test_delete_ec2_keypair(self):
         # EC2 delete KeyPair
         key_name = data_utils.rand_name("keypair-")
diff --git a/tox.ini b/tox.ini
index fe2f79e..2e8b509 100644
--- a/tox.ini
+++ b/tox.ini
@@ -4,7 +4,7 @@
 skipsdist = True
 
 [tempestenv]
-sitepackages = True
+sitepackages = False
 setenv = VIRTUAL_ENV={envdir}
          OS_TEST_PATH=./tempest/test_discover
 deps = setuptools