Merge "Add logic to select the request microversion"
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index aa8ee3f..165f565 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -55,6 +55,13 @@
     @classmethod
     def setup_credentials(cls):
         cls.set_network_resources()
+        cls.request_microversion = (
+            api_version_utils.select_request_microversion(
+                cls.min_microversion,
+                CONF.compute_feature_enabled.min_microversion))
+        if cls.request_microversion:
+            cls.services_microversion = {
+                CONF.compute.catalog_type: cls.request_microversion}
         super(BaseV2ComputeTest, cls).setup_credentials()
 
     @classmethod
diff --git a/tempest/clients.py b/tempest/clients.py
index 54218d6..772ddfc 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -192,9 +192,30 @@
     }
     default_params_with_timeout_values.update(default_params)
 
-    def __init__(self, credentials, service=None):
-        super(Manager, self).__init__(credentials=credentials)
+    def __init__(self, credentials, service=None, api_microversions=None):
+        """Initialization of Manager class.
 
+        Setup all services clients and make them available for tests cases.
+        :param credentials: type Credentials or TestResources
+        :param service: Service name
+        :param api_microversions: This is dict of services catalog type
+               and their microversion which will be set on respective
+               services clients.
+               {<service catalog type>: request_microversion}
+               Example :
+                {'compute': request_microversion}
+                    - request_microversion will be set on all compute
+                      service clients.
+                OR
+                {'compute': request_microversion,
+                 'volume': request_microversion}
+                    - request_microversion of compute will be set on all
+                      compute service clients.
+                    - request_microversion of volume will be set on all
+                      volume service clients.
+        """
+        super(Manager, self).__init__(credentials=credentials)
+        self.api_microversions = api_microversions or {}
         self._set_compute_clients()
         self._set_database_clients()
         self._set_identity_clients()
@@ -348,6 +369,8 @@
         self.negative_client = negative_rest_client.NegativeRestClient(
             self.auth_provider, service, **self.default_params)
 
+        self._set_api_microversions()
+
     def _set_compute_clients(self):
         params = {
             'service': CONF.compute.catalog_type,
@@ -566,3 +589,15 @@
         self.account_client = AccountClient(self.auth_provider, **params)
         self.container_client = ContainerClient(self.auth_provider, **params)
         self.object_client = ObjectClient(self.auth_provider, **params)
+
+    def _set_api_microversions(self):
+        service_clients = [x for x in self.__dict__ if x.endswith('_client')]
+        for client in service_clients:
+            client_obj = getattr(self, client)
+            microversion = self.api_microversions.get(client_obj.service)
+            if microversion:
+                if hasattr(client_obj, 'set_api_microversion'):
+                    client_obj.set_api_microversion(microversion)
+                else:
+                    LOG.debug("Need to implement set_api_microversion on %s"
+                              % client)
diff --git a/tempest/common/api_version_utils.py b/tempest/common/api_version_utils.py
index c499f23..6b6364e 100644
--- a/tempest/common/api_version_utils.py
+++ b/tempest/common/api_version_utils.py
@@ -62,3 +62,10 @@
                   config_min_version.get_string(),
                   config_max_version.get_string()))
         raise testtools.TestCase.skipException(msg)
+
+
+def select_request_microversion(test_min_version, cfg_min_version):
+    test_version = api_version_request.APIVersionRequest(test_min_version)
+    cfg_version = api_version_request.APIVersionRequest(cfg_min_version)
+    max_version = cfg_version if cfg_version >= test_version else test_version
+    return max_version.get_string()
diff --git a/tempest/test.py b/tempest/test.py
index 407df3b..339c1a0 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -226,6 +226,7 @@
     # Resources required to validate a server using ssh
     validation_resources = {}
     network_resources = {}
+    services_microversion = {}
 
     # NOTE(sdague): log_format is defined inline here instead of using the oslo
     # default because going through the config path recouples config to the
@@ -515,7 +516,8 @@
             else:
                 raise exceptions.InvalidCredentials(
                     "Invalid credentials type %s" % credential_type)
-        return clients.Manager(credentials=creds, service=cls._service)
+        return clients.Manager(credentials=creds, service=cls._service,
+                               api_microversions=cls.services_microversion)
 
     @classmethod
     def clear_credentials(cls):
@@ -602,7 +604,8 @@
                 credentials.is_admin_available(
                     identity_version=cls.get_identity_version())):
             admin_creds = cred_provider.get_admin_creds()
-            admin_manager = clients.Manager(admin_creds)
+            admin_manager = clients.Manager(
+                admin_creds, api_microversions=cls.services_microversion)
             networks_client = admin_manager.compute_networks_client
         return fixed_network.get_tenant_network(
             cred_provider, networks_client, CONF.compute.fixed_network_name)
diff --git a/tempest/tests/common/test_api_version_utils.py b/tempest/tests/common/test_api_version_utils.py
index 33024b6..9f399a2 100644
--- a/tempest/tests/common/test_api_version_utils.py
+++ b/tempest/tests/common/test_api_version_utils.py
@@ -192,3 +192,30 @@
     def test_cfg_version_min_greater_than_max(self):
         self.assertRaises(exceptions.InvalidConfiguration,
                           self._test_version, '2.2', '2.7', '2.9', '2.7')
+
+
+class TestSelectRequestMicroversion(base.TestCase):
+
+    def _test_request_version(self, test_min_version,
+                              cfg_min_version, expected_version):
+        selected_version = api_version_utils.select_request_microversion(
+            test_min_version, cfg_min_version)
+        self.assertEqual(expected_version, selected_version)
+
+    def test_cfg_min_version_greater(self):
+        self._test_request_version('2.1', '2.3', expected_version='2.3')
+
+    def test_class_min_version_greater(self):
+        self._test_request_version('2.5', '2.3', expected_version='2.5')
+
+    def test_cfg_min_version_none(self):
+        self._test_request_version('2.5', None, expected_version='2.5')
+
+    def test_class_min_version_none(self):
+        self._test_request_version(None, '2.3', expected_version='2.3')
+
+    def test_both_min_version_none(self):
+        self._test_request_version(None, None, expected_version=None)
+
+    def test_both_min_version_equal(self):
+        self._test_request_version('2.3', '2.3', expected_version='2.3')