Merge "Fix object storage capabilities client return value"
diff --git a/doc/source/library.rst b/doc/source/library.rst
index 29248d1..a461a0f 100644
--- a/doc/source/library.rst
+++ b/doc/source/library.rst
@@ -68,3 +68,4 @@
    library/api_microversion_testing
    library/auth
    library/clients
+   library/credential_providers
diff --git a/doc/source/library/credential_providers.rst b/doc/source/library/credential_providers.rst
new file mode 100644
index 0000000..6e14296
--- /dev/null
+++ b/doc/source/library/credential_providers.rst
@@ -0,0 +1,23 @@
+.. _cred_providers:
+
+Credential Providers
+====================
+
+These library interfaces are used to deal with allocating credentials on demand
+either dynamically by calling keystone to allocate new credentials, or from
+a list of preprovisioned credentials.
+
+
+------------------------------
+The dynamic credentials module
+------------------------------
+
+.. automodule:: tempest.lib.common.dynamic_creds
+   :members:
+
+--------------------------------------
+The pre-provisioned credentials module
+--------------------------------------
+
+.. automodule:: tempest.lib.common.preprov_creds
+   :members:
diff --git a/releasenotes/notes/migrate-dynamic-creds-ecebb47528080761.yaml b/releasenotes/notes/migrate-dynamic-creds-ecebb47528080761.yaml
new file mode 100644
index 0000000..c20cbc6
--- /dev/null
+++ b/releasenotes/notes/migrate-dynamic-creds-ecebb47528080761.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    The tempest module tempest.common.dynamic creds which is used for
+    dynamically allocating credentials has been migrated into tempest lib.
diff --git a/releasenotes/notes/migrate-preprov-creds-ef61a046ee1ec604.yaml b/releasenotes/notes/migrate-preprov-creds-ef61a046ee1ec604.yaml
new file mode 100644
index 0000000..aa5f71a
--- /dev/null
+++ b/releasenotes/notes/migrate-preprov-creds-ef61a046ee1ec604.yaml
@@ -0,0 +1,11 @@
+---
+features:
+  - The tempest module tempest.common.preprov_creds which is used to provide
+    credentials from a list of preprovisioned resources has been migrated into
+    tempest lib at tempest.lib.common.preprov_creds.
+  - The InvalidTestResource exception class from tempest.exceptions has been
+    migrated into tempest.lib.exceptions
+  - The tempest module tempest.common.fixed_network which provided utilities for
+    finding fixed networks by and helpers for picking the network to use when
+    multiple tenant networks are available has been migrated into tempest lib
+    at tempest.lib.common.fixed_network.
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index 0521cca..d9a7800 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -14,8 +14,8 @@
 
 from tempest.api.compute import base
 from tempest.common import compute
-from tempest.common import fixed_network
 from tempest.common import waiters
+from tempest.lib.common import fixed_network
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
diff --git a/tempest/api/compute/servers/test_list_server_filters.py b/tempest/api/compute/servers/test_list_server_filters.py
index 921b7da..a4ed8e1 100644
--- a/tempest/api/compute/servers/test_list_server_filters.py
+++ b/tempest/api/compute/servers/test_list_server_filters.py
@@ -15,9 +15,9 @@
 import testtools
 
 from tempest.api.compute import base
-from tempest.common import fixed_network
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common import fixed_network
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 
diff --git a/tempest/api/object_storage/test_account_bulk.py b/tempest/api/object_storage/test_account_bulk.py
index e765414..7c538e8 100644
--- a/tempest/api/object_storage/test_account_bulk.py
+++ b/tempest/api/object_storage/test_account_bulk.py
@@ -58,9 +58,9 @@
         # upload an archived file
         with open(filepath) as fh:
             mydata = fh.read()
-            resp, body = self.bulk_client.upload_archive(
+            resp = self.bulk_client.upload_archive(
                 upload_path='', data=mydata, archive_file_format='tar')
-        return resp, body
+        return resp
 
     def _check_contents_deleted(self, container_name):
         param = {'format': 'txt'}
@@ -73,21 +73,20 @@
     def test_extract_archive(self):
         # Test bulk operation of file upload with an archived file
         filepath, container_name, object_name = self._create_archive()
-        resp, _ = self._upload_archive(filepath)
-
+        resp = self._upload_archive(filepath)
         self.containers.append(container_name)
 
         # When uploading an archived file with the bulk operation, the response
         # does not contain 'content-length' header. This is the special case,
         # therefore the existence of response headers is checked without
         # custom matcher.
-        self.assertIn('transfer-encoding', resp)
-        self.assertIn('content-type', resp)
-        self.assertIn('x-trans-id', resp)
-        self.assertIn('date', resp)
+        self.assertIn('transfer-encoding', resp.response)
+        self.assertIn('content-type', resp.response)
+        self.assertIn('x-trans-id', resp.response)
+        self.assertIn('date', resp.response)
 
         # Check only the format of common headers with custom matcher
-        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
+        self.assertThat(resp.response, custom_matchers.AreAllWellFormatted())
 
         param = {'format': 'json'}
         resp, body = self.account_client.list_account_containers(param)
@@ -112,19 +111,19 @@
         self._upload_archive(filepath)
 
         data = '%s/%s\n%s' % (container_name, object_name, container_name)
-        resp, _ = self.bulk_client.delete_bulk_data(data=data)
+        resp = self.bulk_client.delete_bulk_data(data=data)
 
         # When deleting multiple files using the bulk operation, the response
         # does not contain 'content-length' header. This is the special case,
         # therefore the existence of response headers is checked without
         # custom matcher.
-        self.assertIn('transfer-encoding', resp)
-        self.assertIn('content-type', resp)
-        self.assertIn('x-trans-id', resp)
-        self.assertIn('date', resp)
+        self.assertIn('transfer-encoding', resp.response)
+        self.assertIn('content-type', resp.response)
+        self.assertIn('x-trans-id', resp.response)
+        self.assertIn('date', resp.response)
 
         # Check only the format of common headers with custom matcher
-        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
+        self.assertThat(resp.response, custom_matchers.AreAllWellFormatted())
 
         # Check if uploaded contents are completely deleted
         self._check_contents_deleted(container_name)
@@ -138,19 +137,19 @@
 
         data = '%s/%s\n%s' % (container_name, object_name, container_name)
 
-        resp, _ = self.bulk_client.delete_bulk_data_with_post(data=data)
+        resp = self.bulk_client.delete_bulk_data_with_post(data=data)
 
         # When deleting multiple files using the bulk operation, the response
         # does not contain 'content-length' header. This is the special case,
         # therefore the existence of response headers is checked without
         # custom matcher.
-        self.assertIn('transfer-encoding', resp)
-        self.assertIn('content-type', resp)
-        self.assertIn('x-trans-id', resp)
-        self.assertIn('date', resp)
+        self.assertIn('transfer-encoding', resp.response)
+        self.assertIn('content-type', resp.response)
+        self.assertIn('x-trans-id', resp.response)
+        self.assertIn('date', resp.response)
 
         # Check only the format of common headers with custom matcher
-        self.assertThat(resp, custom_matchers.AreAllWellFormatted())
+        self.assertThat(resp.response, custom_matchers.AreAllWellFormatted())
 
         # Check if uploaded contents are completely deleted
         self._check_contents_deleted(container_name)
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index a76123c..8636405 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -102,8 +102,8 @@
 import yaml
 
 from tempest.common import credentials_factory
-from tempest.common import dynamic_creds
 from tempest import config
+from tempest.lib.common import dynamic_creds
 
 
 LOG = None
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index 9f467fe..e3fbfb8 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -25,9 +25,9 @@
 from oslo_log import log as logging
 from oslo_utils import excutils
 
-from tempest.common import fixed_network
 from tempest.common import waiters
 from tempest import config
+from tempest.lib.common import fixed_network
 from tempest.lib.common import rest_client
 from tempest.lib.common.utils import data_utils
 
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 449c343..a4cf009 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -14,10 +14,10 @@
 from oslo_concurrency import lockutils
 
 from tempest import clients
-from tempest.common import dynamic_creds
-from tempest.common import preprov_creds
 from tempest import config
 from tempest.lib import auth
+from tempest.lib.common import dynamic_creds
+from tempest.lib.common import preprov_creds
 from tempest.lib import exceptions
 
 CONF = config.CONF
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index a437761..b5b2d71 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -52,12 +52,5 @@
                "the configured network")
 
 
-# NOTE(andreaf) This exception is added here to facilitate the migration
-# of get_network_from_name and preprov_creds to tempest.lib, and it should
-# be migrated along with them
-class InvalidTestResource(exceptions.TempestException):
-    message = "%(name)s is not a valid %(type)s, or the name is ambiguous"
-
-
 class RFCViolation(exceptions.RestClientException):
     message = "RFC Violation"
diff --git a/tempest/common/dynamic_creds.py b/tempest/lib/common/dynamic_creds.py
similarity index 100%
rename from tempest/common/dynamic_creds.py
rename to tempest/lib/common/dynamic_creds.py
diff --git a/tempest/common/fixed_network.py b/tempest/lib/common/fixed_network.py
similarity index 99%
rename from tempest/common/fixed_network.py
rename to tempest/lib/common/fixed_network.py
index 4032c90..e2054a4 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/lib/common/fixed_network.py
@@ -14,8 +14,8 @@
 
 from oslo_log import log as logging
 
-from tempest import exceptions
 from tempest.lib.common.utils import test_utils
+from tempest.lib import exceptions
 
 LOG = logging.getLogger(__name__)
 
diff --git a/tempest/common/preprov_creds.py b/tempest/lib/common/preprov_creds.py
similarity index 98%
rename from tempest/common/preprov_creds.py
rename to tempest/lib/common/preprov_creds.py
index 64cabb7..cd3a10e 100644
--- a/tempest/common/preprov_creds.py
+++ b/tempest/lib/common/preprov_creds.py
@@ -20,10 +20,9 @@
 import six
 import yaml
 
-from tempest.common import fixed_network
-from tempest import exceptions
 from tempest.lib import auth
 from tempest.lib.common import cred_provider
+from tempest.lib.common import fixed_network
 from tempest.lib import exceptions as lib_exc
 from tempest.lib.services import clients
 
@@ -350,7 +349,7 @@
         try:
             network = fixed_network.get_network_from_name(
                 net_name, compute_network_client)
-        except exceptions.InvalidTestResource:
+        except lib_exc.InvalidTestResource:
             network = {}
         net_creds.set_resources(network=network)
         return net_creds
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index 68ce57a..cdb8be9 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -269,3 +269,7 @@
 class DeleteErrorException(TempestException):
     message = ("Resource %(resource_id)s failed to delete "
                "and is in ERROR status")
+
+
+class InvalidTestResource(TempestException):
+    message = "%(name)s is not a valid %(type)s, or the name is ambiguous"
diff --git a/tempest/services/object_storage/bulk_middleware_client.py b/tempest/services/object_storage/bulk_middleware_client.py
index 83d2d80..c11a105 100644
--- a/tempest/services/object_storage/bulk_middleware_client.py
+++ b/tempest/services/object_storage/bulk_middleware_client.py
@@ -31,7 +31,7 @@
             headers = {}
         resp, body = self.put(url, data, headers)
         self.expected_success(200, resp.status)
-        return resp, body
+        return rest_client.ResponseBodyData(resp, body)
 
     def delete_bulk_data(self, data=None, headers=None):
         """Delete multiple objects or containers from their account.
@@ -43,9 +43,9 @@
 
         if headers is None:
             headers = {}
-        resp, body = self.delete(url, headers=headers, body=data)
+        resp, body = self.delete(url, headers, data)
         self.expected_success(200, resp.status)
-        return resp, body
+        return rest_client.ResponseBodyData(resp, body)
 
     def delete_bulk_data_with_post(self, data=None, headers=None):
         """Delete multiple objects or containers with POST request.
@@ -57,6 +57,6 @@
 
         if headers is None:
             headers = {}
-        resp, body = self.post(url, headers=headers, body=data)
+        resp, body = self.post(url, data, headers)
         self.expected_success([200, 204], resp.status)
-        return resp, body
+        return rest_client.ResponseBodyData(resp, body)
diff --git a/tempest/test.py b/tempest/test.py
index fc846ff..317c0a7 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -26,10 +26,10 @@
 
 from tempest import clients
 from tempest.common import credentials_factory as credentials
-from tempest.common import fixed_network
 import tempest.common.validation_resources as vresources
 from tempest import config
 from tempest.lib.common import cred_client
+from tempest.lib.common import fixed_network
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
 
diff --git a/tempest/tests/cmd/test_account_generator.py b/tempest/tests/cmd/test_account_generator.py
index 248cfb0..f907bd0 100644
--- a/tempest/tests/cmd/test_account_generator.py
+++ b/tempest/tests/cmd/test_account_generator.py
@@ -140,7 +140,8 @@
 
     identity_version = 2
     cred_client = 'tempest.lib.common.cred_client.V2CredsClient'
-    dynamic_creds = 'tempest.common.dynamic_creds.DynamicCredentialProvider'
+    dynamic_creds = ('tempest.lib.common.dynamic_creds.'
+                     'DynamicCredentialProvider')
 
     def setUp(self):
         super(TestGenerateResourcesV2, self).setUp()
@@ -245,7 +246,8 @@
 
     identity_version = 2
     cred_client = 'tempest.lib.common.cred_client.V2CredsClient'
-    dynamic_creds = 'tempest.common.dynamic_creds.DynamicCredentialProvider'
+    dynamic_creds = ('tempest.lib.common.dynamic_creds.'
+                     'DynamicCredentialProvider')
     domain_is_in = False
 
     def setUp(self):
diff --git a/tempest/tests/common/test_admin_available.py b/tempest/tests/common/test_admin_available.py
index c3d248c..7b3b1b0 100644
--- a/tempest/tests/common/test_admin_available.py
+++ b/tempest/tests/common/test_admin_available.py
@@ -53,7 +53,7 @@
                                  'password': 'p',
                                  'types': ['admin']})
             self.useFixture(fixtures.MockPatch(
-                'tempest.common.preprov_creds.read_accounts_yaml',
+                'tempest.lib.common.preprov_creds.read_accounts_yaml',
                 return_value=accounts))
             cfg.CONF.set_default('test_accounts_file',
                                  use_accounts_file, group='auth')
diff --git a/tempest/tests/common/test_alt_available.py b/tempest/tests/common/test_alt_available.py
index b9a8967..a425bb8 100644
--- a/tempest/tests/common/test_alt_available.py
+++ b/tempest/tests/common/test_alt_available.py
@@ -40,7 +40,7 @@
                              project_name="t%s" % ii,
                              password="p") for ii in creds]
             self.useFixture(fixtures.MockPatch(
-                'tempest.common.preprov_creds.read_accounts_yaml',
+                'tempest.lib.common.preprov_creds.read_accounts_yaml',
                 return_value=accounts))
             cfg.CONF.set_default('test_accounts_file',
                                  use_accounts_file, group='auth')
diff --git a/tempest/tests/common/test_dynamic_creds.py b/tempest/tests/lib/common/test_dynamic_creds.py
similarity index 99%
rename from tempest/tests/common/test_dynamic_creds.py
rename to tempest/tests/lib/common/test_dynamic_creds.py
index cf131eb..6aa7a42 100644
--- a/tempest/tests/common/test_dynamic_creds.py
+++ b/tempest/tests/lib/common/test_dynamic_creds.py
@@ -17,8 +17,8 @@
 from oslo_config import cfg
 
 from tempest.common import credentials_factory as credentials
-from tempest.common import dynamic_creds
 from tempest import config
+from tempest.lib.common import dynamic_creds
 from tempest.lib.common import rest_client
 from tempest.lib import exceptions as lib_exc
 from tempest.lib.services.identity.v2 import identity_client as v2_iden_client
@@ -659,7 +659,7 @@
         creds = dynamic_creds.DynamicCredentialProvider(**self.fixed_params)
         creds.creds_client = mock.MagicMock()
         creds.creds_client.create_user_role.side_effect = lib_exc.Conflict
-        with mock.patch('tempest.common.dynamic_creds.LOG') as log_mock:
+        with mock.patch('tempest.lib.common.dynamic_creds.LOG') as log_mock:
             creds._create_creds()
             log_mock.warning.assert_called_once_with(
                 "Member role already exists, ignoring conflict.")
diff --git a/tempest/tests/common/test_preprov_creds.py b/tempest/tests/lib/common/test_preprov_creds.py
similarity index 97%
rename from tempest/tests/common/test_preprov_creds.py
rename to tempest/tests/lib/common/test_preprov_creds.py
index d894c5e..5402e47 100644
--- a/tempest/tests/common/test_preprov_creds.py
+++ b/tempest/tests/lib/common/test_preprov_creds.py
@@ -24,10 +24,10 @@
 from oslo_concurrency.fixture import lockutils as lockutils_fixtures
 from oslo_config import cfg
 
-from tempest.common import preprov_creds
 from tempest import config
 from tempest.lib import auth
 from tempest.lib.common import cred_provider
+from tempest.lib.common import preprov_creds
 from tempest.lib import exceptions as lib_exc
 from tempest.tests import base
 from tempest.tests import fake_config
@@ -88,7 +88,7 @@
         self.useFixture(lockutils_fixtures.ExternalLockFixture())
         self.test_accounts = self._fake_accounts(cfg.CONF.identity.admin_role)
         self.accounts_mock = self.useFixture(fixtures.MockPatch(
-            'tempest.common.preprov_creds.read_accounts_yaml',
+            'tempest.lib.common.preprov_creds.read_accounts_yaml',
             return_value=self.test_accounts))
         self.useFixture(fixtures.MockPatch(
             'os.path.isfile', return_value=True))
@@ -271,7 +271,7 @@
     def test_is_not_multi_user(self):
         self.test_accounts = [self.test_accounts[0]]
         self.useFixture(fixtures.MockPatch(
-            'tempest.common.preprov_creds.read_accounts_yaml',
+            'tempest.lib.common.preprov_creds.read_accounts_yaml',
             return_value=self.test_accounts))
         test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
             **self.fixed_params)
@@ -335,7 +335,7 @@
              'password': 'p', 'roles': ['role-7', 'role-11'],
              'resources': {'network': 'network-2'}}]
         self.useFixture(fixtures.MockPatch(
-            'tempest.common.preprov_creds.read_accounts_yaml',
+            'tempest.lib.common.preprov_creds.read_accounts_yaml',
             return_value=test_accounts))
         test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
             **self.fixed_params)
@@ -363,7 +363,7 @@
         admin_accounts = [x for x in self.test_accounts if 'test_admin'
                           in x['username']]
         self.useFixture(fixtures.MockPatch(
-            'tempest.common.preprov_creds.read_accounts_yaml',
+            'tempest.lib.common.preprov_creds.read_accounts_yaml',
             return_value=admin_accounts))
         test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
             **self.fixed_params)
@@ -381,7 +381,7 @@
         admin_accounts = [x for x in self.test_accounts if 'test_admin'
                           in x['username']]
         self.useFixture(fixtures.MockPatch(
-            'tempest.common.preprov_creds.read_accounts_yaml',
+            'tempest.lib.common.preprov_creds.read_accounts_yaml',
             return_value=admin_accounts))
         test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
             **self.fixed_params)
@@ -402,7 +402,7 @@
             {'username': 'test_admin1', 'tenant_name': 'test_tenant11',
              'password': 'p', 'types': ['admin']}]
         self.useFixture(fixtures.MockPatch(
-            'tempest.common.preprov_creds.read_accounts_yaml',
+            'tempest.lib.common.preprov_creds.read_accounts_yaml',
             return_value=test_accounts))
         test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
             **self.fixed_params)
@@ -416,7 +416,7 @@
             {'username': 'test_admin1', 'tenant_name': 'test_tenant11',
              'password': 'p', 'roles': [cfg.CONF.identity.admin_role]}]
         self.useFixture(fixtures.MockPatch(
-            'tempest.common.preprov_creds.read_accounts_yaml',
+            'tempest.lib.common.preprov_creds.read_accounts_yaml',
             return_value=test_accounts))
         test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
             **self.fixed_params)
@@ -427,7 +427,7 @@
         non_admin_accounts = [x for x in self.test_accounts if 'test_admin'
                               not in x['username']]
         self.useFixture(fixtures.MockPatch(
-            'tempest.common.preprov_creds.read_accounts_yaml',
+            'tempest.lib.common.preprov_creds.read_accounts_yaml',
             return_value=non_admin_accounts))
         test_accounts_class = preprov_creds.PreProvisionedCredentialProvider(
             **self.fixed_params)
diff --git a/tempest/tests/lib/services/base.py b/tempest/tests/lib/services/base.py
index 778c966..924f9f2 100644
--- a/tempest/tests/lib/services/base.py
+++ b/tempest/tests/lib/services/base.py
@@ -32,6 +32,7 @@
     def check_service_client_function(self, function, function2mock,
                                       body, to_utf=False, status=200,
                                       headers=None, mock_args=None,
+                                      resp_as_string=False,
                                       **kwargs):
         """Mock a service client function for unit testing.
 
@@ -53,6 +54,9 @@
                  ``assert_called_once_with(foo='bar')`` is called.
                * If mock_args='foo' then ``assert_called_once_with('foo')``
                  is called.
+        :param resp_as_string: Whether response body is retruned as string.
+               This is for service client methods which return ResponseBodyData
+               object.
         :param kwargs: kwargs that are passed to function.
         """
         mocked_response = self.create_response(body, to_utf, status, headers)
@@ -62,8 +66,9 @@
             resp = function(**kwargs)
         else:
             resp = function()
+        if resp_as_string:
+            resp = resp.data
         self.assertEqual(body, resp)
-
         if isinstance(mock_args, list):
             fixture.mock.assert_called_once_with(*mock_args)
         elif isinstance(mock_args, dict):
diff --git a/tempest/tests/services/object_storage/test_bulk_middleware_client.py b/tempest/tests/services/object_storage/test_bulk_middleware_client.py
new file mode 100644
index 0000000..163b48e
--- /dev/null
+++ b/tempest/tests/services/object_storage/test_bulk_middleware_client.py
@@ -0,0 +1,66 @@
+# Copyright 2017 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.services.object_storage import bulk_middleware_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestBulkMiddlewareClient(base.BaseServiceTest):
+
+    def setUp(self):
+        super(TestBulkMiddlewareClient, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = bulk_middleware_client.BulkMiddlewareClient(
+            fake_auth, 'object-storage', 'regionOne')
+
+    def test_upload_archive(self):
+        url = 'test_path?extract-archive=tar'
+        data = 'test_data'
+        self.check_service_client_function(
+            self.client.upload_archive,
+            'tempest.lib.common.rest_client.RestClient.put',
+            {},
+            mock_args=[url, data, {}],
+            resp_as_string=True,
+            upload_path='test_path', data=data, archive_file_format='tar')
+
+    def test_delete_bulk_data(self):
+        url = '?bulk-delete'
+        data = 'test_data'
+        self.check_service_client_function(
+            self.client.delete_bulk_data,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            mock_args=[url, {}, data],
+            resp_as_string=True,
+            data=data)
+
+    def _test_delete_bulk_data_with_post(self, status):
+        url = '?bulk-delete'
+        data = 'test_data'
+        self.check_service_client_function(
+            self.client.delete_bulk_data_with_post,
+            'tempest.lib.common.rest_client.RestClient.post',
+            {},
+            mock_args=[url, data, {}],
+            resp_as_string=True,
+            status=status,
+            data=data)
+
+    def test_delete_bulk_data_with_post_200(self):
+        self._test_delete_bulk_data_with_post(200)
+
+    def test_delete_bulk_data_with_post_204(self):
+        self._test_delete_bulk_data_with_post(204)
diff --git a/tempest/tests/test_base_test.py b/tempest/tests/test_base_test.py
index 01b8a72..6c6f612 100644
--- a/tempest/tests/test_base_test.py
+++ b/tempest/tests/test_base_test.py
@@ -16,8 +16,8 @@
 
 from tempest import clients
 from tempest.common import credentials_factory as credentials
-from tempest.common import fixed_network
 from tempest import config
+from tempest.lib.common import fixed_network
 from tempest import test
 from tempest.tests import base
 from tempest.tests import fake_config