Merge "Fix create/show/delete methods on subnetpools_client"
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index f7b3655..4c7bab7 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -75,7 +75,8 @@
         cls.floating_ip_pools_client = cls.os.floating_ip_pools_client
         cls.floating_ips_client = cls.os.compute_floating_ips_client
         cls.keypairs_client = cls.os.keypairs_client
-        cls.security_group_rules_client = cls.os.security_group_rules_client
+        cls.security_group_rules_client = (
+            cls.os.compute_security_group_rules_client)
         cls.security_groups_client = cls.os.compute_security_groups_client
         cls.quotas_client = cls.os.quotas_client
         cls.quota_classes_client = cls.os.quota_classes_client
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index 24d503f..a6ccdd3 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -47,7 +47,7 @@
         cls.client = cls.os.interfaces_client
 
     def wait_for_interface_status(self, server, port_id, status):
-        """Waits for a interface to reach a given status."""
+        """Waits for an interface to reach a given status."""
         body = (self.client.show_interface(server, port_id)
                 ['interfaceAttachment'])
         interface_status = body['port_state']
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index e363fc4..67e6f4a 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -52,14 +52,15 @@
         cls.glance_client = cls.os.image_client
         cls.keypairs_client = cls.os.keypairs_client
         cls.security_client = cls.os.compute_security_groups_client
-        cls.rule_client = cls.os.security_group_rules_client
+        cls.rule_client = cls.os.compute_security_group_rules_client
 
         cls.alt_client = cls.alt_manager.servers_client
         cls.alt_images_client = cls.alt_manager.images_client
         cls.alt_keypairs_client = cls.alt_manager.keypairs_client
         cls.alt_security_client = (
             cls.alt_manager.compute_security_groups_client)
-        cls.alt_rule_client = cls.alt_manager.security_group_rules_client
+        cls.alt_rule_client = (
+            cls.alt_manager.compute_security_group_rules_client)
 
     @classmethod
     def resource_setup(cls):
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 2e6c268..04582c6 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -147,7 +147,7 @@
                      for disk_fmt in disk_fmts]
 
         for (container_fmt, disk_fmt) in all_pairs[:6]:
-            LOG.debug("Creating a image"
+            LOG.debug("Creating an image"
                       "(Container format: %s, Disk format: %s).",
                       container_fmt, disk_fmt)
             cls._create_standard_image(container_fmt, disk_fmt)
diff --git a/tempest/clients.py b/tempest/clients.py
index 772ddfc..0496002 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -52,7 +52,7 @@
 from tempest_lib.services.compute.security_group_default_rules_client import \
     SecurityGroupDefaultRulesClient
 from tempest_lib.services.compute.security_group_rules_client import \
-    SecurityGroupRulesClient
+    SecurityGroupRulesClient as ComputeSecurityGroupRulesClient
 from tempest_lib.services.compute.security_groups_client import \
     SecurityGroupsClient as ComputeSecurityGroupsClient
 from tempest_lib.services.compute.server_groups_client import \
@@ -412,8 +412,8 @@
             self.auth_provider, **params)
         self.compute_floating_ips_client = ComputeFloatingIPsClient(
             self.auth_provider, **params)
-        self.security_group_rules_client = SecurityGroupRulesClient(
-            self.auth_provider, **params)
+        self.compute_security_group_rules_client = \
+            ComputeSecurityGroupRulesClient(self.auth_provider, **params)
         self.compute_security_groups_client = ComputeSecurityGroupsClient(
             self.auth_provider, **params)
         self.interfaces_client = InterfacesClient(self.auth_provider,
diff --git a/tempest/common/api_version_utils.py b/tempest/common/api_version_utils.py
index 6b6364e..ac3322e 100644
--- a/tempest/common/api_version_utils.py
+++ b/tempest/common/api_version_utils.py
@@ -39,7 +39,7 @@
     if ((min_version > max_version) or
        (config_min_version > config_max_version)):
         msg = ("Min version is greater than Max version. Test Class versions "
-               "[%s - %s]. configration versions [%s - %s]."
+               "[%s - %s]. configuration versions [%s - %s]."
                % (min_version.get_string(),
                   max_version.get_string(),
                   config_min_version.get_string(),
@@ -56,7 +56,7 @@
     if (max_version < config_min_version or
         config_max_version < min_version):
         msg = ("The microversion range[%s - %s] of this test is out of the "
-               "configration range[%s - %s]."
+               "configuration range[%s - %s]."
                % (min_version.get_string(),
                   max_version.get_string(),
                   config_min_version.get_string(),
diff --git a/tempest/common/validation_resources.py b/tempest/common/validation_resources.py
index bb71a51..9457a60 100644
--- a/tempest/common/validation_resources.py
+++ b/tempest/common/validation_resources.py
@@ -24,7 +24,7 @@
 
 def create_ssh_security_group(os, add_rule=False):
     security_groups_client = os.compute_security_groups_client
-    security_group_rules_client = os.security_group_rules_client
+    security_group_rules_client = os.compute_security_group_rules_client
     sg_name = data_utils.rand_name('securitygroup-')
     sg_description = data_utils.rand_name('description-')
     security_group = security_groups_client.create_security_group(
diff --git a/tempest/exceptions.py b/tempest/exceptions.py
index 1d725af..931737d 100644
--- a/tempest/exceptions.py
+++ b/tempest/exceptions.py
@@ -181,6 +181,11 @@
                "be of format MajorNum.MinorNum or string 'latest'.")
 
 
+class JSONSchemaNotFound(TempestException):
+    message = ("JSON Schema for %(version)s is not found in \n"
+               " %(schema_versions_info)s")
+
+
 class CommandFailed(Exception):
     def __init__(self, returncode, cmd, output, stderr):
         super(CommandFailed, self).__init__()
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index e5e0d16..eb5ea16 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -57,8 +57,8 @@
         # Nova security groups client
         cls.compute_security_groups_client = (
             cls.manager.compute_security_groups_client)
-        cls.security_group_rules_client = (
-            cls.manager.security_group_rules_client)
+        cls.compute_security_group_rules_client = (
+            cls.manager.compute_security_group_rules_client)
         cls.servers_client = cls.manager.servers_client
         cls.interface_client = cls.manager.interfaces_client
         # Neutron network client
@@ -289,7 +289,7 @@
 
     def _create_loginable_secgroup_rule(self, secgroup_id=None):
         _client = self.compute_security_groups_client
-        _client_rules = self.security_group_rules_client
+        _client_rules = self.compute_security_group_rules_client
         if secgroup_id is None:
             sgs = _client.list_security_groups()['security_groups']
             for sg in sgs:
diff --git a/tempest/services/compute/json/base.py b/tempest/services/compute/json/base.py
index ea1a696..40d3056 100644
--- a/tempest/services/compute/json/base.py
+++ b/tempest/services/compute/json/base.py
@@ -14,6 +14,9 @@
 
 from tempest_lib.common import rest_client
 
+from tempest.common import api_version_request
+from tempest import exceptions
+
 
 class BaseComputeClient(rest_client.RestClient):
     api_microversion = None
@@ -26,3 +29,36 @@
 
     def set_api_microversion(self, microversion):
         self.api_microversion = microversion
+
+    def get_schema(self, schema_versions_info):
+        """Get JSON schema
+
+        This method provides the matching schema for requested
+        microversion (self.api_microversion).
+        :param schema_versions_info: List of dict which provides schema
+        information with range of valid versions.
+        Example -
+        schema_versions_info = [
+            {'min': None, 'max': '2.1', 'schema': schemav21},
+            {'min': '2.2', 'max': '2.9', 'schema': schemav22},
+            {'min': '2.10', 'max': None, 'schema': schemav210}]
+        """
+        schema = None
+        version = api_version_request.APIVersionRequest(self.api_microversion)
+        for items in schema_versions_info:
+            min_version = api_version_request.APIVersionRequest(items['min'])
+            max_version = api_version_request.APIVersionRequest(items['max'])
+            # This is case where self.api_microversion is None, which means
+            # request without microversion So select base v2.1 schema.
+            if version.is_null() and items['min'] is None:
+                schema = items['schema']
+                break
+            # else select appropriate schema as per self.api_microversion
+            elif version.matches(min_version, max_version):
+                schema = items['schema']
+                break
+        if schema is None:
+            raise exceptions.JSONSchemaNotFound(
+                version=version.get_string(),
+                schema_versions_info=schema_versions_info)
+        return schema
diff --git a/tempest/tests/services/compute/test_base_compute_client.py b/tempest/tests/services/compute/test_base_compute_client.py
index 13461e4..134fe39 100644
--- a/tempest/tests/services/compute/test_base_compute_client.py
+++ b/tempest/tests/services/compute/test_base_compute_client.py
@@ -16,6 +16,7 @@
 import mock
 from tempest_lib.common import rest_client
 
+from tempest import exceptions
 from tempest.services.compute.json import base as base_compute_client
 from tempest.tests import fake_auth_provider
 from tempest.tests.services.compute import base
@@ -70,3 +71,82 @@
                                'raw_request') as mock_get:
             mock_get.side_effect = raw_request
             self.client.get('fake_url')
+
+
+class DummyServiceClient1(base_compute_client.BaseComputeClient):
+    schema_versions_info = [
+        {'min': None, 'max': '2.1', 'schema': 'schemav21'},
+        {'min': '2.2', 'max': '2.9', 'schema': 'schemav22'},
+        {'min': '2.10', 'max': None, 'schema': 'schemav210'}]
+
+    def return_selected_schema(self):
+        return self.get_schema(self.schema_versions_info)
+
+
+class TestSchemaVersionsNone(base.BaseComputeServiceTest):
+    api_microversion = None
+    expected_schema = 'schemav21'
+
+    def setUp(self):
+        super(TestSchemaVersionsNone, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = DummyServiceClient1(fake_auth, 'compute', 'regionOne')
+        self.client.api_microversion = self.api_microversion
+
+    def test_schema(self):
+        self.assertEqual(self.expected_schema,
+                         self.client.return_selected_schema())
+
+
+class TestSchemaVersionsV21(TestSchemaVersionsNone):
+    api_microversion = '2.1'
+    expected_schema = 'schemav21'
+
+
+class TestSchemaVersionsV22(TestSchemaVersionsNone):
+    api_microversion = '2.2'
+    expected_schema = 'schemav22'
+
+
+class TestSchemaVersionsV25(TestSchemaVersionsNone):
+    api_microversion = '2.5'
+    expected_schema = 'schemav22'
+
+
+class TestSchemaVersionsV29(TestSchemaVersionsNone):
+    api_microversion = '2.9'
+    expected_schema = 'schemav22'
+
+
+class TestSchemaVersionsV210(TestSchemaVersionsNone):
+    api_microversion = '2.10'
+    expected_schema = 'schemav210'
+
+
+class TestSchemaVersionsLatest(TestSchemaVersionsNone):
+    api_microversion = 'latest'
+    expected_schema = 'schemav210'
+
+
+class DummyServiceClient2(base_compute_client.BaseComputeClient):
+    schema_versions_info = [
+        {'min': None, 'max': '2.1', 'schema': 'schemav21'},
+        {'min': '2.2', 'max': '2.9', 'schema': 'schemav22'}]
+
+    def return_selected_schema(self):
+        return self.get_schema(self.schema_versions_info)
+
+
+class TestSchemaVersionsNotFound(base.BaseComputeServiceTest):
+    api_microversion = '2.10'
+    expected_schema = 'schemav210'
+
+    def setUp(self):
+        super(TestSchemaVersionsNotFound, self).setUp()
+        fake_auth = fake_auth_provider.FakeAuthProvider()
+        self.client = DummyServiceClient2(fake_auth, 'compute', 'regionOne')
+        self.client.api_microversion = self.api_microversion
+
+    def test_schema(self):
+        self.assertRaises(exceptions.JSONSchemaNotFound,
+                          self.client.return_selected_schema)
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index ce3eb7e..98b045a 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -140,7 +140,7 @@
                 self.fail('%s is not listed in the valid service tag list'
                           % service)
             except KeyError:
-                # NOTE(mtreinish): This condition is to test for a entry in
+                # NOTE(mtreinish): This condition is to test for an entry in
                 # the outer decorator list but not in the service_list dict.
                 # However, because we're looping over the service_list dict
                 # it's unlikely we'll trigger this. So manual review is still