Merge "Add a common class for Nova v2/v3 API tests"
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 533c7d0..edeb2fc 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -30,6 +30,7 @@
 class BaseComputeTest(tempest.test.BaseTestCase):
     """Base test case class for all Compute API tests."""
 
+    _api_version = 3
     force_tenant_isolation = False
 
     @classmethod
@@ -54,6 +55,57 @@
         cls.multi_user = cls.get_multi_user()
         cls.security_groups = []
 
+        if cls._api_version == 2:
+            cls.servers_client = cls.os.servers_client
+            cls.flavors_client = cls.os.flavors_client
+            cls.images_client = cls.os.images_client
+            cls.extensions_client = cls.os.extensions_client
+            cls.floating_ips_client = cls.os.floating_ips_client
+            cls.keypairs_client = cls.os.keypairs_client
+            cls.security_groups_client = cls.os.security_groups_client
+            cls.quotas_client = cls.os.quotas_client
+            cls.limits_client = cls.os.limits_client
+            cls.volumes_extensions_client = cls.os.volumes_extensions_client
+            cls.volumes_client = cls.os.volumes_client
+            cls.interfaces_client = cls.os.interfaces_client
+            cls.fixed_ips_client = cls.os.fixed_ips_client
+            cls.availability_zone_client = cls.os.availability_zone_client
+            cls.agents_client = cls.os.agents_client
+            cls.aggregates_client = cls.os.aggregates_client
+            cls.services_client = cls.os.services_client
+            cls.instance_usages_audit_log_client = \
+                cls.os.instance_usages_audit_log_client
+            cls.hypervisor_client = cls.os.hypervisor_client
+            cls.certificates_client = cls.os.certificates_client
+            cls.migrations_client = cls.os.migrations_client
+
+        elif cls._api_version == 3:
+            if not CONF.compute_feature_enabled.api_v3:
+                skip_msg = ("%s skipped as nova v3 api is not available" %
+                            cls.__name__)
+                raise cls.skipException(skip_msg)
+            cls.servers_client = cls.os.servers_v3_client
+            cls.images_client = cls.os.image_client
+            cls.flavors_client = cls.os.flavors_v3_client
+            cls.services_client = cls.os.services_v3_client
+            cls.extensions_client = cls.os.extensions_v3_client
+            cls.availability_zone_client = cls.os.availability_zone_v3_client
+            cls.interfaces_client = cls.os.interfaces_v3_client
+            cls.hypervisor_client = cls.os.hypervisor_v3_client
+            cls.keypairs_client = cls.os.keypairs_v3_client
+            cls.volumes_client = cls.os.volumes_client
+            cls.certificates_client = cls.os.certificates_v3_client
+            cls.keypairs_client = cls.os.keypairs_v3_client
+            cls.aggregates_client = cls.os.aggregates_v3_client
+            cls.hosts_client = cls.os.hosts_v3_client
+            cls.quotas_client = cls.os.quotas_v3_client
+            cls.version_client = cls.os.version_v3_client
+            cls.migrations_client = cls.os.migrations_v3_client
+        else:
+            msg = ("Unexpected API version is specified (%s)" %
+                   cls._api_version)
+            raise exceptions.InvalidConfiguration(message=msg)
+
     @classmethod
     def get_multi_user(cls):
         multi_user = True
@@ -231,38 +283,6 @@
             cls.set_network_resources(network=True, subnet=True, router=True,
                                       dhcp=True)
 
-
-class BaseV2ComputeTest(BaseComputeTest):
-
-    _interface = "json"
-
-    @classmethod
-    def setUpClass(cls):
-        # By default compute tests do not create network resources
-        super(BaseV2ComputeTest, cls).setUpClass()
-        cls.servers_client = cls.os.servers_client
-        cls.flavors_client = cls.os.flavors_client
-        cls.images_client = cls.os.images_client
-        cls.extensions_client = cls.os.extensions_client
-        cls.floating_ips_client = cls.os.floating_ips_client
-        cls.keypairs_client = cls.os.keypairs_client
-        cls.security_groups_client = cls.os.security_groups_client
-        cls.quotas_client = cls.os.quotas_client
-        cls.limits_client = cls.os.limits_client
-        cls.volumes_extensions_client = cls.os.volumes_extensions_client
-        cls.volumes_client = cls.os.volumes_client
-        cls.interfaces_client = cls.os.interfaces_client
-        cls.fixed_ips_client = cls.os.fixed_ips_client
-        cls.availability_zone_client = cls.os.availability_zone_client
-        cls.agents_client = cls.os.agents_client
-        cls.aggregates_client = cls.os.aggregates_client
-        cls.services_client = cls.os.services_client
-        cls.instance_usages_audit_log_client = \
-            cls.os.instance_usages_audit_log_client
-        cls.hypervisor_client = cls.os.hypervisor_client
-        cls.certificates_client = cls.os.certificates_client
-        cls.migrations_client = cls.os.migrations_client
-
     @classmethod
     def create_image_from_server(cls, server_id, **kwargs):
         """Wrapper utility that returns an image created from the server."""
@@ -270,21 +290,25 @@
         if 'name' in kwargs:
             name = kwargs.pop('name')
 
-        resp, image = cls.images_client.create_image(
-            server_id, name)
+        if cls._api_version == 2:
+            resp, image = cls.images_client.create_image(server_id, name)
+        elif cls._api_version == 3:
+            resp, image = cls.servers_client.create_image(server_id, name)
         image_id = data_utils.parse_image_id(resp['location'])
         cls.images.append(image_id)
 
         if 'wait_until' in kwargs:
             cls.images_client.wait_for_image_status(image_id,
                                                     kwargs['wait_until'])
-            resp, image = cls.images_client.get_image(image_id)
+            if cls._api_version == 2:
+                resp, image = cls.images_client.get_image(image_id)
+            elif cls._api_version == 3:
+                resp, image = cls.images_client.get_image_meta(image_id)
 
             if kwargs['wait_until'] == 'ACTIVE':
                 if kwargs.get('wait_for_server', True):
                     cls.servers_client.wait_for_server_status(server_id,
                                                               'ACTIVE')
-
         return resp, image
 
     @classmethod
@@ -298,13 +322,24 @@
                 LOG.exception('Failed to delete server %s' % server_id)
                 pass
         resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
-        cls.password = server['adminPass']
+        if cls._api_version == 2:
+            cls.password = server['adminPass']
+        elif cls._api_version == 3:
+            cls.password = server['admin_password']
         return server['id']
 
     @classmethod
     def delete_volume(cls, volume_id):
         """Deletes the given volume and waits for it to be gone."""
-        cls._delete_volume(cls.volumes_extensions_client, volume_id)
+        if cls._api_version == 2:
+            cls._delete_volume(cls.volumes_extensions_client, volume_id)
+        elif cls._api_version == 3:
+            cls._delete_volume(cls.volumes_client, volume_id)
+
+
+class BaseV2ComputeTest(BaseComputeTest):
+    _api_version = 2
+    _interface = "json"
 
 
 class BaseV2ComputeAdminTest(BaseV2ComputeTest):
@@ -333,74 +368,9 @@
 
 
 class BaseV3ComputeTest(BaseComputeTest):
-
+    _api_version = 3
     _interface = "json"
 
-    @classmethod
-    def setUpClass(cls):
-        # By default compute tests do not create network resources
-        if not CONF.compute_feature_enabled.api_v3:
-            skip_msg = ("%s skipped as nova v3 api is not available" %
-                        cls.__name__)
-            raise cls.skipException(skip_msg)
-
-        super(BaseV3ComputeTest, cls).setUpClass()
-
-        cls.servers_client = cls.os.servers_v3_client
-        cls.images_client = cls.os.image_client
-        cls.flavors_client = cls.os.flavors_v3_client
-        cls.services_client = cls.os.services_v3_client
-        cls.extensions_client = cls.os.extensions_v3_client
-        cls.availability_zone_client = cls.os.availability_zone_v3_client
-        cls.interfaces_client = cls.os.interfaces_v3_client
-        cls.hypervisor_client = cls.os.hypervisor_v3_client
-        cls.keypairs_client = cls.os.keypairs_v3_client
-        cls.volumes_client = cls.os.volumes_client
-        cls.certificates_client = cls.os.certificates_v3_client
-        cls.keypairs_client = cls.os.keypairs_v3_client
-        cls.aggregates_client = cls.os.aggregates_v3_client
-        cls.hosts_client = cls.os.hosts_v3_client
-        cls.quotas_client = cls.os.quotas_v3_client
-        cls.version_client = cls.os.version_v3_client
-        cls.migrations_client = cls.os.migrations_v3_client
-
-    @classmethod
-    def create_image_from_server(cls, server_id, **kwargs):
-        """Wrapper utility that returns an image created from the server."""
-        name = data_utils.rand_name(cls.__name__ + "-image")
-        if 'name' in kwargs:
-            name = kwargs.pop('name')
-
-        resp, image = cls.servers_client.create_image(
-            server_id, name)
-        image_id = data_utils.parse_image_id(resp['location'])
-        cls.images.append(image_id)
-
-        if 'wait_until' in kwargs:
-            cls.images_client.wait_for_image_status(image_id,
-                                                    kwargs['wait_until'])
-            resp, image = cls.images_client.get_image_meta(image_id)
-
-        return resp, image
-
-    @classmethod
-    def rebuild_server(cls, server_id, **kwargs):
-        # Destroy an existing server and creates a new one
-        try:
-            cls.servers_client.delete_server(server_id)
-            cls.servers_client.wait_for_server_termination(server_id)
-        except Exception:
-            LOG.exception('Failed to delete server %s' % server_id)
-            pass
-        resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
-        cls.password = server['admin_password']
-        return server['id']
-
-    @classmethod
-    def delete_volume(cls, volume_id):
-        """Deletes the given volume and waits for it to be gone."""
-        cls._delete_volume(cls.volumes_client, volume_id)
-
 
 class BaseV3ComputeAdminTest(BaseV3ComputeTest):
     """Base test case class for all Compute Admin API V3 tests."""
diff --git a/tempest/api/compute/servers/test_availability_zone.py b/tempest/api/compute/servers/test_availability_zone.py
index 7b12555..cf9837f 100644
--- a/tempest/api/compute/servers/test_availability_zone.py
+++ b/tempest/api/compute/servers/test_availability_zone.py
@@ -17,15 +17,15 @@
 from tempest import test
 
 
-class AZTestJSON(base.BaseV2ComputeTest):
-
+class AZV3Test(base.BaseComputeTest):
     """
     Tests Availability Zone API List
     """
+    _api_version = 3
 
     @classmethod
     def setUpClass(cls):
-        super(AZTestJSON, cls).setUpClass()
+        super(AZV3Test, cls).setUpClass()
         cls.client = cls.availability_zone_client
 
     @test.attr(type='gate')
@@ -36,5 +36,9 @@
         self.assertTrue(len(availability_zone) > 0)
 
 
-class AZTestXML(AZTestJSON):
+class AZV2TestJSON(AZV3Test):
+    _api_version = 2
+
+
+class AZV2TestXML(AZV2TestJSON):
     _interface = 'xml'
diff --git a/tempest/api/compute/v2/__init__.py b/tempest/api/compute/v2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/compute/v2/__init__.py
diff --git a/tempest/api/compute/v3/servers/test_availability_zone.py b/tempest/api/compute/v3/servers/test_availability_zone.py
deleted file mode 100644
index 5a1e07e..0000000
--- a/tempest/api/compute/v3/servers/test_availability_zone.py
+++ /dev/null
@@ -1,36 +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.api.compute import base
-from tempest import test
-
-
-class AZV3Test(base.BaseV3ComputeTest):
-
-    """
-    Tests Availability Zone API List
-    """
-
-    @classmethod
-    def setUpClass(cls):
-        super(AZV3Test, cls).setUpClass()
-        cls.client = cls.availability_zone_client
-
-    @test.attr(type='gate')
-    def test_get_availability_zone_list_with_non_admin_user(self):
-        # List of availability zone with non-administrator user
-        resp, availability_zone = self.client.get_availability_zone_list()
-        self.assertEqual(200, resp.status)
-        self.assertTrue(len(availability_zone) > 0)