Merge "tempest: migrate api and scnario tests from tempest"
diff --git a/ceilometer/tests/tempest/api/base.py b/ceilometer/tests/tempest/api/base.py
index 938bc88..103a123 100644
--- a/ceilometer/tests/tempest/api/base.py
+++ b/ceilometer/tests/tempest/api/base.py
@@ -13,27 +13,43 @@
 import time
 
 from oslo_utils import timeutils
-from tempest_lib import exceptions as lib_exc
-
 from tempest.common import compute
 from tempest.common.utils import data_utils
 from tempest import config
 from tempest import exceptions
+from tempest.lib import exceptions as lib_exc
 import tempest.test
 
+from ceilometer.tests.tempest.service import client
+
+
 CONF = config.CONF
 
 
+class ClientManager(client.Manager):
+
+    load_clients = [
+        'servers_client',
+        'compute_networks_client',
+        'compute_floating_ips_client',
+        'flavors_client',
+        'image_client',
+        'image_client_v2',
+        'telemetry_client',
+    ]
+
+
 class BaseTelemetryTest(tempest.test.BaseTestCase):
 
     """Base test case class for all Telemetry API tests."""
 
     credentials = ['primary']
+    client_manager = ClientManager
 
     @classmethod
     def skip_checks(cls):
         super(BaseTelemetryTest, cls).skip_checks()
-        if not CONF.service_available.ceilometer:
+        if not CONF.service_available.ceilometer_plugin:
             raise cls.skipException("Ceilometer support is required")
 
     @classmethod
@@ -44,11 +60,11 @@
     @classmethod
     def setup_clients(cls):
         super(BaseTelemetryTest, cls).setup_clients()
-        cls.telemetry_client = cls.os.telemetry_client
-        cls.servers_client = cls.os.servers_client
-        cls.flavors_client = cls.os.flavors_client
-        cls.image_client = cls.os.image_client
-        cls.image_client_v2 = cls.os.image_client_v2
+        cls.telemetry_client = cls.os_primary.telemetry_client
+        cls.servers_client = cls.os_primary.servers_client
+        cls.flavors_client = cls.os_primary.flavors_client
+        cls.image_client = cls.os_primary.image_client
+        cls.image_client_v2 = cls.os_primary.image_client_v2
 
     @classmethod
     def resource_setup(cls):
@@ -67,7 +83,7 @@
     def create_server(cls):
         tenant_network = cls.get_tenant_network()
         body, server = compute.create_test_server(
-            cls.os,
+            cls.os_primary,
             tenant_network=tenant_network,
             name=data_utils.rand_name('ceilometer-instance'),
             wait_until='ACTIVE')
@@ -75,10 +91,11 @@
         return body
 
     @classmethod
-    def create_image(cls, client):
-        body = client.create_image(
-            data_utils.rand_name('image'), container_format='bare',
-            disk_format='raw', visibility='private')
+    def create_image(cls, client, **kwargs):
+        body = client.create_image(name=data_utils.rand_name('image'),
+                                   container_format='bare',
+                                   disk_format='raw',
+                                   **kwargs)
         # TODO(jswarren) Move ['image'] up to initial body value assignment
         # once both v1 and v2 glance clients include the full response
         # object.
diff --git a/ceilometer/tests/tempest/api/test_telemetry_notification_api.py b/ceilometer/tests/tempest/api/test_telemetry_notification_api.py
new file mode 100644
index 0000000..6c1ee6b
--- /dev/null
+++ b/ceilometer/tests/tempest/api/test_telemetry_notification_api.py
@@ -0,0 +1,87 @@
+#    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.
+
+# Change-Id: I14e16a1a7d9813b324ee40545c07f0e88fb637b7
+
+import testtools
+
+from ceilometer.tests.tempest.api import base
+from tempest import config
+from tempest.lib import decorators
+from tempest import test
+
+
+CONF = config.CONF
+
+
+class TelemetryNotificationAPITest(base.BaseTelemetryTest):
+
+    @test.idempotent_id('d7f8c1c8-d470-4731-8604-315d3956caae')
+    @test.services('compute')
+    def test_check_nova_notification(self):
+
+        body = self.create_server()
+
+        query = ('resource', 'eq', body['id'])
+
+        for metric in self.nova_notifications:
+            self.await_samples(metric, query)
+
+    @test.attr(type="smoke")
+    @test.idempotent_id('04b10bfe-a5dc-47af-b22f-0460426bf499')
+    @test.services("image")
+    @testtools.skipIf(not CONF.image_feature_enabled.api_v1,
+                      "Glance api v1 is disabled")
+    def test_check_glance_v1_notifications(self):
+        body = self.create_image(self.image_client, is_public=False)
+        self.image_client.update_image(body['id'], data='data')
+
+        query = 'resource', 'eq', body['id']
+
+        self.image_client.delete_image(body['id'])
+
+        for metric in self.glance_notifications:
+            self.await_samples(metric, query)
+
+    @test.attr(type="smoke")
+    @test.idempotent_id('c240457d-d943-439b-8aea-85e26d64fe8f')
+    @test.services("image")
+    @testtools.skipIf(not CONF.image_feature_enabled.api_v2,
+                      "Glance api v2 is disabled")
+    def test_check_glance_v2_notifications(self):
+        body = self.create_image(self.image_client_v2, visibility='private')
+
+        self.image_client_v2.store_image_file(body['id'], "file")
+        self.image_client_v2.show_image_file(body['id'])
+
+        query = 'resource', 'eq', body['id']
+
+        for metric in self.glance_v2_notifications:
+            self.await_samples(metric, query)
+
+
+class TelemetryNotificationAdminAPITest(base.BaseTelemetryAdminTest):
+
+    @test.idempotent_id('29604198-8b45-4fc0-8af8-1cae4f94ebea')
+    @test.services('compute')
+    @decorators.skip_because(bug='1480490')
+    def test_check_nova_notification_event_and_meter(self):
+
+        body = self.create_server()
+
+        if CONF.telemetry_plugin.event_enabled:
+            query = ('instance_id', 'eq', body['id'])
+            self.await_events(query)
+
+        query = ('resource', 'eq', body['id'])
+        for metric in self.nova_notifications:
+            self.await_samples(metric, query)
diff --git a/ceilometer/tests/tempest/client.py b/ceilometer/tests/tempest/client.py
deleted file mode 100644
index b0173ef..0000000
--- a/ceilometer/tests/tempest/client.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# 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 oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
-
-from tempest.common import service_client
-from tempest import config
-from tempest import manager
-
-
-CONF = config.CONF
-
-
-class TelemetryClient(service_client.ServiceClient):
-
-    version = '2'
-    uri_prefix = "v2"
-
-    def deserialize(self, body):
-        return json.loads(body.replace("\n", ""))
-
-    def serialize(self, body):
-        return json.dumps(body)
-
-    def add_sample(self, sample_list, meter_name, meter_unit, volume,
-                   sample_type, resource_id, **kwargs):
-        sample = {"counter_name": meter_name, "counter_unit": meter_unit,
-                  "counter_volume": volume, "counter_type": sample_type,
-                  "resource_id": resource_id}
-        for key in kwargs:
-            sample[key] = kwargs[key]
-
-        sample_list.append(self.serialize(sample))
-        return sample_list
-
-    def create_sample(self, meter_name, sample_list):
-        uri = "%s/meters/%s" % (self.uri_prefix, meter_name)
-        body = self.serialize(sample_list)
-        resp, body = self.post(uri, body)
-        self.expected_success(200, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBody(resp, body)
-
-    def _helper_list(self, uri, query=None, period=None):
-        uri_dict = {}
-        if query:
-            uri_dict = {'q.field': query[0],
-                        'q.op': query[1],
-                        'q.value': query[2]}
-        if period:
-            uri_dict['period'] = period
-        if uri_dict:
-            uri += "?%s" % urllib.urlencode(uri_dict)
-        resp, body = self.get(uri)
-        self.expected_success(200, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBodyList(resp, body)
-
-    def list_resources(self, query=None):
-        uri = '%s/resources' % self.uri_prefix
-        return self._helper_list(uri, query)
-
-    def list_meters(self, query=None):
-        uri = '%s/meters' % self.uri_prefix
-        return self._helper_list(uri, query)
-
-    def list_statistics(self, meter, period=None, query=None):
-        uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
-        return self._helper_list(uri, query, period)
-
-    def list_samples(self, meter_id, query=None):
-        uri = '%s/meters/%s' % (self.uri_prefix, meter_id)
-        return self._helper_list(uri, query)
-
-    def list_events(self, query=None):
-        uri = '%s/events' % self.uri_prefix
-        return self._helper_list(uri, query)
-
-    def show_resource(self, resource_id):
-        uri = '%s/resources/%s' % (self.uri_prefix, resource_id)
-        resp, body = self.get(uri)
-        self.expected_success(200, resp.status)
-        body = self.deserialize(body)
-        return service_client.ResponseBody(resp, body)
-
-
-class Manager(manager.Manager):
-
-    def __init__(self, credentials=None, service=None):
-        super(Manager, self).__init__(credentials, service)
-        self._set_telemetry_client()
-
-    def _set_telemetry_client(self):
-        if CONF.service_available.ceilometer:
-            self.telemetry_client = TelemetryClient(
-                self.auth_provider,
-                CONF.telemetry.catalog_type,
-                CONF.identity.region,
-                endpoint_type=CONF.telemetry.endpoint_type,
-                disable_ssl_certificate_validation=(
-                    CONF.identity.disable_ssl_certificate_validation),
-                ca_certs=CONF.identity.ca_certificates_file,
-                trace_requests=CONF.debug.trace_requests)
diff --git a/ceilometer/tests/tempest/config.py b/ceilometer/tests/tempest/config.py
index 96dc6a2..a83a509 100644
--- a/ceilometer/tests/tempest/config.py
+++ b/ceilometer/tests/tempest/config.py
@@ -20,12 +20,12 @@
                                        title="Available OpenStack Services")
 
 ServiceAvailableGroup = [
-    cfg.BoolOpt('ceilometer',
+    cfg.BoolOpt('ceilometer_plugin',
                 default=True,
                 help="Whether or not Ceilometer is expected to be available"),
 ]
 
-telemetry_group = cfg.OptGroup(name='telemetry',
+telemetry_group = cfg.OptGroup(name='telemetry_plugin',
                                title='Telemetry Service Options')
 
 TelemetryGroup = [
@@ -37,4 +37,7 @@
                choices=['public', 'admin', 'internal',
                         'publicURL', 'adminURL', 'internalURL'],
                help="The endpoint type to use for the telemetry service."),
+    cfg.BoolOpt('event_enabled',
+                default=True,
+                help="Runs Ceilometer event-related tests"),
 ]
diff --git a/ceilometer/tests/tempest/scenario/__init__.py b/ceilometer/tests/tempest/scenario/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ceilometer/tests/tempest/scenario/__init__.py
diff --git a/ceilometer/tests/tempest/scenario/test_object_storage_telemetry_middleware.py b/ceilometer/tests/tempest/scenario/test_object_storage_telemetry_middleware.py
new file mode 100644
index 0000000..4bb287d
--- /dev/null
+++ b/ceilometer/tests/tempest/scenario/test_object_storage_telemetry_middleware.py
@@ -0,0 +1,146 @@
+# Copyright 2014 Red Hat
+#
+# 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 oslo_log import log as logging
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest import test
+
+from ceilometer.tests.tempest.service import client
+
+
+CONF = config.CONF
+
+LOG = logging.getLogger(__name__)
+
+# Loop for up to 120 seconds waiting on notifications
+# NOTE(chdent): The choice of 120 seconds is fairly
+# arbitrary: Long enough to give the notifications the
+# chance to travel across a highly latent bus but not
+# so long as to allow excessive latency to never be visible.
+# TODO(chdent): Ideally this value would come from configuration.
+NOTIFICATIONS_WAIT = 120
+NOTIFICATIONS_SLEEP = 1
+
+
+class ClientManager(client.Manager):
+
+    load_clients = [
+        'telemetry_client',
+        'container_client',
+        'object_client',
+    ]
+
+
+class TestObjectStorageTelemetry(test.BaseTestCase):
+    """Test that swift uses the ceilometer middleware.
+
+     * create container.
+     * upload a file to the created container.
+     * retrieve the file from the created container.
+     * wait for notifications from ceilometer.
+    """
+
+    credentials = ['primary']
+    client_manager = ClientManager
+
+    @classmethod
+    def skip_checks(cls):
+        super(TestObjectStorageTelemetry, cls).skip_checks()
+        if not CONF.service_available.swift:
+            skip_msg = ("%s skipped as swift is not available" %
+                        cls.__name__)
+            raise cls.skipException(skip_msg)
+        if not CONF.service_available.ceilometer_plugin:
+            skip_msg = ("%s skipped as ceilometer is not available" %
+                        cls.__name__)
+            raise cls.skipException(skip_msg)
+
+    @classmethod
+    def setup_credentials(cls):
+        cls.set_network_resources()
+        super(TestObjectStorageTelemetry, cls).setup_credentials()
+
+    @classmethod
+    def setup_clients(cls):
+        super(TestObjectStorageTelemetry, cls).setup_clients()
+        cls.telemetry_client = cls.os_primary.telemetry_client
+        cls.container_client = cls.os_primary.container_client
+        cls.object_client = cls.os_primary.object_client
+
+    def _confirm_notifications(self, container_name, obj_name):
+        # NOTE: Loop seeking for appropriate notifications about the containers
+        # and objects sent to swift.
+
+        def _check_samples():
+            # NOTE: Return True only if we have notifications about some
+            # containers and some objects and the notifications are about
+            # the expected containers and objects.
+            # Otherwise returning False will case _check_samples to be
+            # called again.
+            results = self.telemetry_client.list_samples(
+                'storage.objects.incoming.bytes')
+            LOG.debug('got samples %s', results)
+
+            # Extract container info from samples.
+            containers, objects = [], []
+            for sample in results:
+                meta = sample['resource_metadata']
+                if meta.get('container') and meta['container'] != 'None':
+                    containers.append(meta['container'])
+                elif (meta.get('target.metadata:container') and
+                      meta['target.metadata:container'] != 'None'):
+                    containers.append(meta['target.metadata:container'])
+
+                if meta.get('object') and meta['object'] != 'None':
+                    objects.append(meta['object'])
+                elif (meta.get('target.metadata:object') and
+                      meta['target.metadata:object'] != 'None'):
+                    objects.append(meta['target.metadata:object'])
+
+            return (container_name in containers and obj_name in objects)
+
+        self.assertTrue(test.call_until_true(_check_samples,
+                                             NOTIFICATIONS_WAIT,
+                                             NOTIFICATIONS_SLEEP),
+                        'Correct notifications were not received after '
+                        '%s seconds.' % NOTIFICATIONS_WAIT)
+
+    def create_container(self):
+        name = data_utils.rand_name('swift-scenario-container')
+        self.container_client.create_container(name)
+        # look for the container to assure it is created
+        self.container_client.list_container_contents(name)
+        LOG.debug('Container %s created' % (name))
+        self.addCleanup(self.container_client.delete_container,
+                        name)
+        return name
+
+    def upload_object_to_container(self, container_name):
+        obj_name = data_utils.rand_name('swift-scenario-object')
+        obj_data = data_utils.arbitrary_string()
+        self.object_client.create_object(container_name, obj_name, obj_data)
+        self.addCleanup(self.object_client.delete_object,
+                        container_name,
+                        obj_name)
+        return obj_name
+
+    @test.idempotent_id('6d6b88e5-3e38-41bc-b34a-79f713a6cb85')
+    @test.services('object_storage', 'telemetry')
+    def test_swift_middleware_notifies(self):
+        container_name = self.create_container()
+        obj_name = self.upload_object_to_container(container_name)
+        self._confirm_notifications(container_name, obj_name)
diff --git a/ceilometer/tests/tempest/service/__init__.py b/ceilometer/tests/tempest/service/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ceilometer/tests/tempest/service/__init__.py
diff --git a/ceilometer/tests/tempest/service/client.py b/ceilometer/tests/tempest/service/client.py
new file mode 100644
index 0000000..81d67d8
--- /dev/null
+++ b/ceilometer/tests/tempest/service/client.py
@@ -0,0 +1,190 @@
+# 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 oslo_serialization import jsonutils as json
+from six.moves.urllib import parse as urllib
+
+from tempest import config
+from tempest.lib.common import rest_client
+from tempest.lib.services.compute.flavors_client import FlavorsClient
+from tempest.lib.services.compute.floating_ips_client import FloatingIPsClient
+from tempest.lib.services.compute.networks_client import NetworksClient
+from tempest.lib.services.compute.servers_client import ServersClient
+from tempest import manager
+from tempest.services.image.v1.json.images_client import ImagesClient
+from tempest.services.image.v2.json.images_client import ImagesClientV2
+from tempest.services.object_storage.container_client import ContainerClient
+from tempest.services.object_storage.object_client import ObjectClient
+
+
+CONF = config.CONF
+
+
+class TelemetryClient(rest_client.RestClient):
+
+    version = '2'
+    uri_prefix = "v2"
+
+    def deserialize(self, body):
+        return json.loads(body.replace("\n", ""))
+
+    def serialize(self, body):
+        return json.dumps(body)
+
+    def create_sample(self, meter_name, sample_list):
+        uri = "%s/meters/%s" % (self.uri_prefix, meter_name)
+        body = self.serialize(sample_list)
+        resp, body = self.post(uri, body)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def _helper_list(self, uri, query=None, period=None):
+        uri_dict = {}
+        if query:
+            uri_dict = {'q.field': query[0],
+                        'q.op': query[1],
+                        'q.value': query[2]}
+        if period:
+            uri_dict['period'] = period
+        if uri_dict:
+            uri += "?%s" % urllib.urlencode(uri_dict)
+        resp, body = self.get(uri)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return rest_client.ResponseBodyList(resp, body)
+
+    def list_resources(self, query=None):
+        uri = '%s/resources' % self.uri_prefix
+        return self._helper_list(uri, query)
+
+    def list_meters(self, query=None):
+        uri = '%s/meters' % self.uri_prefix
+        return self._helper_list(uri, query)
+
+    def list_statistics(self, meter, period=None, query=None):
+        uri = "%s/meters/%s/statistics" % (self.uri_prefix, meter)
+        return self._helper_list(uri, query, period)
+
+    def list_samples(self, meter_id, query=None):
+        uri = '%s/meters/%s' % (self.uri_prefix, meter_id)
+        return self._helper_list(uri, query)
+
+    def list_events(self, query=None):
+        uri = '%s/events' % self.uri_prefix
+        return self._helper_list(uri, query)
+
+    def show_resource(self, resource_id):
+        uri = '%s/resources/%s' % (self.uri_prefix, resource_id)
+        resp, body = self.get(uri)
+        self.expected_success(200, resp.status)
+        body = self.deserialize(body)
+        return rest_client.ResponseBody(resp, body)
+
+
+class Manager(manager.Manager):
+
+    load_clients = [
+        'servers_client',
+        'compute_networks_client',
+        'compute_floating_ips_client',
+        'flavors_client',
+        'image_client',
+        'image_client_v2',
+        'telemetry_client',
+        'container_client',
+        'object_client',
+    ]
+
+    default_params = {
+        'disable_ssl_certificate_validation':
+            CONF.identity.disable_ssl_certificate_validation,
+        'ca_certs': CONF.identity.ca_certificates_file,
+        'trace_requests': CONF.debug.trace_requests
+    }
+
+    compute_params = {
+        'service': CONF.compute.catalog_type,
+        'region': CONF.compute.region or CONF.identity.region,
+        'endpoint_type': CONF.compute.endpoint_type,
+        'build_interval': CONF.compute.build_interval,
+        'build_timeout': CONF.compute.build_timeout,
+    }
+    compute_params.update(default_params)
+
+    image_params = {
+        'catalog_type': CONF.image.catalog_type,
+        'region': CONF.image.region or CONF.identity.region,
+        'endpoint_type': CONF.image.endpoint_type,
+        'build_interval': CONF.image.build_interval,
+        'build_timeout': CONF.image.build_timeout,
+    }
+    image_params.update(default_params)
+
+    telemetry_params = {
+        'service': CONF.telemetry_plugin.catalog_type,
+        'region': CONF.identity.region,
+        'endpoint_type': CONF.telemetry_plugin.endpoint_type,
+    }
+    telemetry_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)
+
+    def __init__(self, credentials=None, service=None):
+        super(Manager, self).__init__(credentials)
+        for client in self.load_clients:
+            getattr(self, 'set_%s' % client)()
+
+    def set_servers_client(self):
+        self.servers_client = ServersClient(self.auth_provider,
+                                            **self.compute_params)
+
+    def set_compute_networks_client(self):
+        self.compute_networks_client = NetworksClient(self.auth_provider,
+                                                      **self.compute_params)
+
+    def set_compute_floating_ips_client(self):
+        self.compute_floating_ips_client = FloatingIPsClient(
+            self.auth_provider,
+            **self.compute_params)
+
+    def set_flavors_client(self):
+        self.flavors_client = FlavorsClient(self.auth_provider,
+                                            **self.compute_params)
+
+    def set_image_client(self):
+        self.image_client = ImagesClient(self.auth_provider,
+                                         **self.image_params)
+
+    def set_image_client_v2(self):
+        self.image_client_v2 = ImagesClientV2(self.auth_provider,
+                                              **self.image_params)
+
+    def set_telemetry_client(self):
+        self.telemetry_client = TelemetryClient(self.auth_provider,
+                                                **self.telemetry_params)
+
+    def set_container_client(self):
+        self.container_client = ContainerClient(self.auth_provider,
+                                                **self.object_storage_params)
+
+    def set_object_client(self):
+        self.object_client = ObjectClient(self.auth_provider,
+                                          **self.object_storage_params)