Add tests for VMs booted from raw image type

Smoke:
- ServerActionsRawImageTestJSON.test_reboot_server_hard
- test_server_basic_ops_2_image_raw_ref
Full:
- ServerActionsRawImageTestJSON.test_stop_start_server
- ServerActionsRawImageTestJSON.test_shelve_unshelve_server
- test_shelve_instance_2_image_raw_ref
- test_cold_migration_2_image_raw_ref
- test_revert_cold_migration_2_image_raw_ref
- LiveMigrationTest.test_live_block_migration_2_image_raw_ref
- LiveAutoBlockMigrationV225Test.test_live_block_migration_2_image_raw_ref

Related-Prod: PRODX-40251
Change-Id: I2c5edbe5409f53dd969da702c705a7c74b50a315
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 20fa7bd..24bb38b 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -49,6 +49,11 @@
                 "Less than 2 compute nodes, skipping migration test.")
 
     @classmethod
+    def setup_credentials(cls):
+        cls.prepare_instance_network()
+        super(LiveMigrationTestBase, cls).setup_credentials()
+
+    @classmethod
     def setup_clients(cls):
         super(LiveMigrationTestBase, cls).setup_clients()
         cls.admin_migration_client = cls.os_admin.migrations_client
@@ -94,17 +99,8 @@
             self.assertEqual(target_host, self.get_host_for_server(server_id),
                              msg)
 
-
-class LiveMigrationTest(LiveMigrationTestBase):
-    max_microversion = '2.24'
-    block_migration = None
-
-    @classmethod
-    def setup_credentials(cls):
-        cls.prepare_instance_network()
-        super(LiveMigrationTest, cls).setup_credentials()
-
-    def _test_live_migration(self, state='ACTIVE', volume_backed=False):
+    def _test_live_migration(
+            self, state='ACTIVE', volume_backed=False, image_id=None):
         """Tests live migration between two hosts.
 
         Requires CONF.compute_feature_enabled.live_migration to be True.
@@ -117,7 +113,8 @@
         """
         # Live migrate an instance to another host
         server_id = self.create_test_server(wait_until="ACTIVE",
-                                            volume_backed=volume_backed)['id']
+                                            volume_backed=volume_backed,
+                                            image_id=image_id)['id']
         source_host = self.get_host_for_server(server_id)
         if not CONF.compute_feature_enabled.can_migrate_between_any_hosts:
             # not to specify a host so that the scheduler will pick one
@@ -140,6 +137,11 @@
             LOG.info("Live migrate back to source %s", source_host)
             self._live_migrate(server_id, source_host, state, volume_backed)
 
+
+class LiveMigrationTest(LiveMigrationTestBase):
+    max_microversion = '2.24'
+    block_migration = None
+
     @decorators.attr(type='multinode')
     @decorators.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
     @testtools.skipUnless(CONF.compute_feature_enabled.
@@ -384,3 +386,53 @@
 
     if CONF.compute_feature_enabled.volume_multiattach:
         min_microversion = '2.60'
+
+
+class LiveMigrationTestRaw(LiveMigrationTestBase):
+    max_microversion = '2.24'
+    block_migration = None
+    image_id = CONF.compute.image_raw_ref
+
+    @classmethod
+    def skip_checks(cls):
+        super(LiveMigrationTestRaw, cls).skip_checks()
+
+        if not cls.image_id:
+            skip_msg = ("Environment doesn't have raw type image")
+            raise cls.skipException(skip_msg)
+
+    @decorators.attr(type='multinode')
+    @decorators.idempotent_id('6916bb20-fbf1-42df-958d-fa19acbbc09d')
+    @testtools.skipUnless(CONF.compute_feature_enabled.
+                          block_migration_for_live_migration,
+                          'Block Live migration not available')
+    def test_live_block_migration(self):
+        """Test live migrating an active server"""
+        self._test_live_migration(image_id=self.image_id)
+
+
+class LiveAutoBlockMigrationV225TestRaw(LiveMigrationTestBase):
+    min_microversion = '2.25'
+    max_microversion = 'latest'
+    block_migration = 'auto'
+    image_id = CONF.compute.image_raw_ref
+
+    if CONF.compute_feature_enabled.volume_multiattach:
+        min_microversion = '2.60'
+
+    @classmethod
+    def skip_checks(cls):
+        super(LiveAutoBlockMigrationV225TestRaw, cls).skip_checks()
+
+        if not cls.image_id:
+            skip_msg = ("Environment doesn't have raw type image")
+            raise cls.skipException(skip_msg)
+
+    @decorators.attr(type='multinode')
+    @decorators.idempotent_id('f7aeae41-83af-4574-87d1-bdd11d2f994e')
+    @testtools.skipUnless(CONF.compute_feature_enabled.
+                          block_migration_for_live_migration,
+                          'Block Live migration not available')
+    def test_live_block_migration(self):
+        """Test live migrating an active server"""
+        self._test_live_migration(image_id=self.image_id)
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 6b27355..1f43f38 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -24,14 +24,43 @@
 CONF = config.CONF
 
 
-class MigrationsAdminTest(base.BaseV2ComputeAdminTest):
+class MigrationsAdminTestBase(base.BaseV2ComputeAdminTest):
     """Test migration operations supported by admin user"""
 
     @classmethod
     def setup_clients(cls):
-        super(MigrationsAdminTest, cls).setup_clients()
+        super(MigrationsAdminTestBase, cls).setup_clients()
         cls.client = cls.os_admin.migrations_client
 
+    def _test_cold_migrate_server(self, revert=False, image_id=None):
+        if CONF.compute.min_compute_nodes < 2:
+            msg = "Less than 2 compute nodes, skipping multinode tests."
+            raise self.skipException(msg)
+
+        server = self.create_test_server(image_id=image_id,
+                                         wait_until="ACTIVE")
+        src_host = self.get_host_for_server(server['id'])
+
+        self.admin_servers_client.migrate_server(server['id'])
+
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'VERIFY_RESIZE')
+
+        if revert:
+            self.servers_client.revert_resize_server(server['id'])
+            assert_func = self.assertEqual
+        else:
+            self.servers_client.confirm_resize_server(server['id'])
+            assert_func = self.assertNotEqual
+
+        waiters.wait_for_server_status(self.servers_client,
+                                       server['id'], 'ACTIVE')
+        dst_host = self.get_host_for_server(server['id'])
+        assert_func(src_host, dst_host)
+
+
+class MigrationsAdminTest(MigrationsAdminTestBase):
+
     @decorators.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
     def test_list_migrations(self):
         """Test admin user can get the migrations list"""
@@ -137,31 +166,6 @@
                        'flavor!' % key)
                 self.assertEqual(pre_flavor[key], server['flavor'][key], msg)
 
-    def _test_cold_migrate_server(self, revert=False):
-        if CONF.compute.min_compute_nodes < 2:
-            msg = "Less than 2 compute nodes, skipping multinode tests."
-            raise self.skipException(msg)
-
-        server = self.create_test_server(wait_until="ACTIVE")
-        src_host = self.get_host_for_server(server['id'])
-
-        self.admin_servers_client.migrate_server(server['id'])
-
-        waiters.wait_for_server_status(self.servers_client,
-                                       server['id'], 'VERIFY_RESIZE')
-
-        if revert:
-            self.servers_client.revert_resize_server(server['id'])
-            assert_func = self.assertEqual
-        else:
-            self.servers_client.confirm_resize_server(server['id'])
-            assert_func = self.assertNotEqual
-
-        waiters.wait_for_server_status(self.servers_client,
-                                       server['id'], 'ACTIVE')
-        dst_host = self.get_host_for_server(server['id'])
-        assert_func(src_host, dst_host)
-
     @decorators.attr(type='multinode')
     @decorators.idempotent_id('4bf0be52-3b6f-4746-9a27-3143636fe30d')
     @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
@@ -177,3 +181,32 @@
     def test_revert_cold_migration(self):
         """Test cold migrating server and then revert the migration"""
         self._test_cold_migrate_server(revert=True)
+
+
+class MigrationsAdminTestRaw(MigrationsAdminTestBase):
+
+    image_id = CONF.compute.image_raw_ref
+
+    @classmethod
+    def skip_checks(cls):
+        super(MigrationsAdminTestRaw, cls).skip_checks()
+
+        if not cls.image_id:
+            skip_msg = ("Environment doesn't have raw type image")
+            raise cls.skipException(skip_msg)
+
+    @decorators.attr(type='multinode')
+    @decorators.idempotent_id('17f41ec8-734d-41cf-b18c-6c2fe3eb65c3')
+    @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+                          'Cold migration not available.')
+    def test_cold_migration(self):
+        """Test cold migrating server and then confirm the migration"""
+        self._test_cold_migrate_server(revert=False, image_id=self.image_id)
+
+    @decorators.attr(type='multinode')
+    @decorators.idempotent_id('c9d5dc79-d7fc-4f81-9a8d-e6e104ec4f98')
+    @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+                          'Cold migration not available.')
+    def test_revert_cold_migration(self):
+        """Test cold migrating server and then revert the migration"""
+        self._test_cold_migrate_server(revert=True, image_id=self.image_id)
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index d01df51..47f97b0 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -37,6 +37,7 @@
 class ServerActionsBase(base.BaseV2ComputeTest):
     """Test server actions"""
 
+    image_id = None
     if CONF.compute_feature_enabled.volume_multiattach:
         min_microversion = '2.60'
 
@@ -49,6 +50,7 @@
         server = self.create_test_server(
             validatable=True,
             validation_resources=self.validation_resources,
+            image_id=self.image_id,
             wait_until='SSHABLE')
         self.server_id = server['id']
         self.addCleanup(self.delete_server, self.server_id)
@@ -229,15 +231,6 @@
                 servers_client=self.client)
             linux_client.validate_authentication()
 
-    @decorators.attr(type='smoke')
-    @decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
-    def test_reboot_server_hard(self):
-        """Test hard rebooting server
-
-        The server should be power cycled.
-        """
-        self._test_reboot_server(self.server_id, 'HARD')
-
     @decorators.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c')
     def test_rebuild_server(self):
         """Test rebuilding server
@@ -317,14 +310,6 @@
         self.client.resume_server(self.server_id)
         waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
 
-    @decorators.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560')
-    def test_stop_start_server(self):
-        """Test stopping and starting server"""
-        self.client.stop_server(self.server_id)
-        waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
-        self.client.start_server(self.server_id)
-        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
-
     @decorators.idempotent_id('80a8094c-211e-440a-ab88-9e59d556c7ee')
     def test_lock_unlock_server(self):
         """Test locking and unlocking server
@@ -657,36 +642,6 @@
         waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
         self.wait_for(self._get_output, self.server_id)
 
-    @decorators.idempotent_id('77eba8e0-036e-4635-944b-f7a8f3b78dc9')
-    @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
-                          'Shelve is not available.')
-    @utils.services('image')
-    def test_shelve_unshelve_server(self):
-        """Test shelving and unshelving server"""
-        if CONF.image_feature_enabled.api_v2:
-            glance_client = self.os_primary.image_client_v2
-        else:
-            raise lib_exc.InvalidConfiguration(
-                'api_v2 must be True in [image-feature-enabled].')
-        compute.shelve_server(self.client, self.server_id,
-                              force_shelve_offload=True)
-
-        server = self.client.show_server(self.server_id)['server']
-        image_name = server['name'] + '-shelved'
-        params = {'name': image_name}
-        images = glance_client.list_images(params)['images']
-        self.assertEqual(1, len(images))
-        self.assertEqual(image_name, images[0]['name'])
-
-        body = self.client.unshelve_server(self.server_id)
-        waiters.wait_for_server_status(
-            self.client,
-            self.server_id,
-            "ACTIVE",
-            request_id=body.response["x-openstack-request-id"],
-        )
-        glance_client.wait_for_resource_deletion(images[0]['id'])
-
     @decorators.idempotent_id('8cf9f450-a871-42cf-9bef-77eba189c0b0')
     @decorators.related_bug('1745529')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
@@ -721,6 +676,61 @@
         self._validate_url(body['url'])
 
 
+class ServerActionsImageTest(ServerActionsBase):
+
+    @decorators.attr(type='smoke')
+    @decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
+    def test_reboot_server_hard(self):
+        """Test hard rebooting server
+
+        The server should be power cycled.
+        """
+        self._test_reboot_server(self.server_id, 'HARD')
+
+    @decorators.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560')
+    def test_stop_start_server(self):
+        """Test stopping and starting server"""
+        self.client.stop_server(self.server_id)
+        waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
+        self.client.start_server(self.server_id)
+        waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
+
+    @decorators.idempotent_id('77eba8e0-036e-4635-944b-f7a8f3b78dc9')
+    @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+                          'Shelve is not available.')
+    @utils.services('image')
+    def test_shelve_unshelve_server(self):
+        """Test shelving and unshelving server"""
+        if CONF.image_feature_enabled.api_v2:
+            glance_client = self.os_primary.image_client_v2
+        else:
+            raise lib_exc.InvalidConfiguration(
+                'api_v2 must be True in [image-feature-enabled].')
+        compute.shelve_server(self.client, self.server_id,
+                              force_shelve_offload=True)
+
+        server = self.client.show_server(self.server_id)['server']
+        image_name = server['name'] + '-shelved'
+        params = {'name': image_name}
+        images = glance_client.list_images(params)['images']
+        self.assertEqual(1, len(images))
+        self.assertEqual(image_name, images[0]['name'])
+
+        body = self.client.unshelve_server(self.server_id)
+        waiters.wait_for_server_status(
+            self.client,
+            self.server_id,
+            "ACTIVE",
+            request_id=body.response["x-openstack-request-id"],
+        )
+        glance_client.wait_for_resource_deletion(images[0]['id'])
+
+
+class ServerActionsImageRawTest(ServerActionsImageTest):
+    """Test server actions with raw image type"""
+    image_id = CONF.compute.image_raw_ref
+
+
 class ServersAaction247Test(base.BaseV2ComputeTest):
     """Test compute server with microversion greater than 2.47
 
diff --git a/tempest/config.py b/tempest/config.py
index d57864d..cffeb35 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -302,6 +302,10 @@
                help="This is image with full OS like ubuntu/centos used"
                     "in some tests. When not set related tests will be "
                     "skipped"),
+    cfg.StrOpt('image_raw_ref',
+               default=None,
+               help="Valid image reference in raw format to be used "
+                    "in tests."),
     cfg.StrOpt('image_full_username',
                default="ubuntu",
                help="Username for image_full_ref authentication."),
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index ad86d0f..f2249f2 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -27,7 +27,7 @@
 CONF = config.CONF
 
 
-class TestServerBasicOps(manager.ScenarioTestWithNetwork):
+class TestServerBasicOpsBase(manager.ScenarioTestWithNetwork):
 
     """The test suite for server basic operations
 
@@ -43,7 +43,7 @@
     """
 
     def setUp(self):
-        super(TestServerBasicOps, self).setUp()
+        super(TestServerBasicOpsBase, self).setUp()
         self.run_ssh = CONF.validation.run_validation
         self.ssh_user = CONF.validation.image_ssh_user
 
@@ -117,6 +117,9 @@
             # TODO(clarkb) construct network_data from known network
             # instance info and do direct comparison.
 
+
+class TestServerBasicOps(TestServerBasicOpsBase):
+
     @decorators.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
     @decorators.attr(type='smoke')
     @utils.services('compute', 'network')
@@ -137,3 +140,37 @@
         self.servers_client.delete_server(self.instance['id'])
         waiters.wait_for_server_termination(
             self.servers_client, self.instance['id'], ignore_error=False)
+
+
+class TestServerBasicOpsRaw(TestServerBasicOpsBase):
+
+    image_id = CONF.compute.image_raw_ref
+
+    @classmethod
+    def skip_checks(cls):
+        super(TestServerBasicOpsRaw, cls).skip_checks()
+
+        if not cls.image_id:
+            skip_msg = ("Environment doesn't have raw type image")
+            raise cls.skipException(skip_msg)
+
+    @decorators.idempotent_id('2d203d40-c3d4-4e2f-b22f-380c1a165f79')
+    @decorators.attr(type='smoke')
+    @utils.services('compute', 'network')
+    def test_server_basic_ops(self):
+        keypair = self.create_keypair()
+        security_group = self.create_security_group()
+        self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
+        self.instance = self.create_server(
+            image_id=self.image_id,
+            key_name=keypair['name'],
+            security_groups=[{'name': security_group['name']}],
+            config_drive=CONF.compute_feature_enabled.config_drive,
+            metadata=self.md)
+        self.verify_ssh(keypair)
+        self.verify_metadata()
+        self.verify_metadata_on_config_drive()
+        self.verify_networkdata_on_config_drive()
+        self.servers_client.delete_server(self.instance['id'])
+        waiters.wait_for_server_termination(
+            self.servers_client, self.instance['id'], ignore_error=False)
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 204471e..3ba301a 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -25,7 +25,7 @@
 CONF = config.CONF
 
 
-class TestShelveInstance(manager.ScenarioTest):
+class TestShelveInstanceBase(manager.ScenarioTest):
     """This test shelves then unshelves a Nova instance
 
     The following is the scenario outline:
@@ -42,12 +42,12 @@
 
     @classmethod
     def setup_clients(cls):
-        super(TestShelveInstance, cls).setup_clients()
+        super(TestShelveInstanceBase, cls).setup_clients()
         cls.admin_servers_client = cls.os_admin.servers_client
 
     @classmethod
     def skip_checks(cls):
-        super(TestShelveInstance, cls).skip_checks()
+        super(TestShelveInstanceBase, cls).skip_checks()
         if not CONF.compute_feature_enabled.shelve:
             raise cls.skipException("Shelve is not available.")
 
@@ -72,14 +72,15 @@
         dst_host = self.get_host_for_server(server['id'])
         self.assertNotEqual(src_host, dst_host)
 
-    def _create_server_then_shelve_and_unshelve(self, boot_from_volume=False,
-                                                cold_migrate=False):
+    def _create_server_then_shelve_and_unshelve(
+            self, boot_from_volume=False, cold_migrate=False, image_id=None):
         keypair = self.create_keypair()
 
         security_group = self.create_security_group()
         security_groups = [{'name': security_group['name']}]
 
         server = self.create_server(
+            image_id=image_id,
             key_name=keypair['name'],
             security_groups=security_groups,
             volume_backed=boot_from_volume)
@@ -103,6 +104,9 @@
                                         server=server)
         self.assertEqual(timestamp, timestamp2)
 
+
+class TestShelveInstance(TestShelveInstanceBase):
+
     @decorators.attr(type='slow')
     @decorators.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
     @testtools.skipUnless(CONF.network.public_network_id,
@@ -133,3 +137,24 @@
     @utils.services('compute', 'network', 'image')
     def test_cold_migrate_unshelved_instance(self):
         self._create_server_then_shelve_and_unshelve(cold_migrate=True)
+
+
+class TestShelveInstanceRaw(TestShelveInstanceBase):
+
+    image_id = CONF.compute.image_raw_ref
+
+    @classmethod
+    def skip_checks(cls):
+        super(TestShelveInstanceRaw, cls).skip_checks()
+
+        if not cls.image_id:
+            skip_msg = ("Environment doesn't have raw type image")
+            raise cls.skipException(skip_msg)
+
+    @decorators.attr(type='slow')
+    @decorators.idempotent_id('ee0b7d90-54e3-4f50-abd0-cef03c793914')
+    @testtools.skipUnless(CONF.network.public_network_id,
+                          'The public_network_id option must be specified.')
+    @utils.services('compute', 'network', 'image')
+    def test_shelve_instance(self):
+        self._create_server_then_shelve_and_unshelve(image_id=self.image_id)