Merge "Add tests to boot WindowsVM from volume" into mcp/caracal
diff --git a/tempest/api/compute/admin/test_servers_on_multinodes.py b/tempest/api/compute/admin/test_servers_on_multinodes.py
index 013e7d8..e8367c5 100644
--- a/tempest/api/compute/admin/test_servers_on_multinodes.py
+++ b/tempest/api/compute/admin/test_servers_on_multinodes.py
@@ -142,6 +142,14 @@
     def skip_checks(cls):
         super(UnshelveToHostMultiNodesTest, cls).skip_checks()
 
+        if not CONF.compute_feature_enabled.shelve:
+            raise cls.skipException("Shelve is not available.")
+        # Test has two users from different projects. Member user creates VM
+        # and shelve it but admin user unshelve this VM. In case of encrypted
+        # Nova storage the admin user has no access to the user encryption
+        # keys and not be able to perform unshelve action.
+        if CONF.ephemeral_storage_encryption.enabled:
+            raise cls.skipException("Nova has encrypted storage.")
         if CONF.compute.min_compute_nodes < 2:
             raise cls.skipException(
                 "Less than 2 compute nodes, skipping multi-nodes test.")
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 0180513..dcdfae2 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -30,16 +30,34 @@
         super(TestVolumeSwapBase, cls).setup_credentials()
 
     @classmethod
+    def setup_clients(cls):
+        super(TestVolumeSwapBase, cls).setup_clients()
+
+        cls.volume_type_client = cls.os_admin.volume_types_client_latest
+        cls.encryption_client = cls.os_admin.encryption_types_client_latest
+
+    @classmethod
     def skip_checks(cls):
         super(TestVolumeSwapBase, cls).skip_checks()
         if not CONF.service_available.cinder:
             raise cls.skipException("Cinder is not available")
         if not CONF.compute_feature_enabled.swap_volume:
             raise cls.skipException("Swapping volumes is not supported.")
-        if CONF.compute_feature_enabled.attach_encrypted_volume:
-            raise cls.skipException(
-                'Volume swap is not available for OS configurations '
-                'with crypted volumes.')
+
+    @classmethod
+    def _check_default_volume_type(cls):
+        default_volume_type = cls.volume_type_client.\
+            show_default_volume_type()["volume_type"]["id"]
+        volume_encryption = cls.encryption_client.show_encryption_type(
+            default_volume_type)
+        if volume_encryption and volume_encryption.get("provider"):
+            raise cls.skipException("Not allowed to run this test with "
+                                    "encrypted volume")
+
+    @classmethod
+    def resource_setup(cls):
+        cls._check_default_volume_type()
+        super(TestVolumeSwapBase, cls).resource_setup()
 
     def wait_for_server_volume_swap(self, server_id, old_volume_id,
                                     new_volume_id):
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 36c2b8b..ae0bd76 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -679,8 +679,9 @@
     raise lib_exc.TimeoutException()
 
 
-def wait_for_cloudinit(ssh_client, timeout=60):
+def wait_for_cloudinit(ssh_client):
     """Waits for cloud-init completed"""
+    timeout = CONF.compute.cloudinit_timeout
     start_time = int(time.time())
     while int(time.time()) - start_time < timeout:
         try:
diff --git a/tempest/config.py b/tempest/config.py
index cffeb35..d5eeb21 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -348,6 +348,9 @@
                help="Timeout in seconds to wait for an instance to build. "
                     "Other services that do not define build_timeout will "
                     "inherit this value."),
+    cfg.IntOpt('cloudinit_timeout',
+               default=90,
+               help="Timeout in seconds to wait for a cloudinit on VM."),
     cfg.IntOpt('ready_wait',
                default=0,
                help="Additional wait time for clean state, when there is "
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 212c1b3..94cc3bd 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -1342,12 +1342,12 @@
         return self.create_server(**create_kwargs)
 
     def wait_for_cloud_init(
-            self, ip_address, server, private_key, username, timeout=60):
+            self, ip_address, server, private_key, username):
         ssh_client = self.get_remote_client(ip_address,
                                             private_key=private_key,
                                             server=server,
                                             username=username)
-        waiters.wait_for_cloudinit(ssh_client, timeout)
+        waiters.wait_for_cloudinit(ssh_client)
 
     def create_volume_from_image(self, **kwargs):
         """Create volume from image.
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index 62b2823..1afb940 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -80,9 +80,10 @@
     @utils.services('compute', 'volume', 'image')
     def test_encrypted_cinder_volumes_luksv2(self):
         """LUKs v2 decrypts volume through os-brick."""
-        volume = self.create_encrypted_volume('luks2',
-                                              volume_type='luksv2',
-                                              wait_until=None)
+        volume = self.create_encrypted_volume(
+            'luks2',
+            volume_type=CONF.volume.volume_type_luks_v2,
+            wait_until=None)
         server = self.launch_instance()
         waiters.wait_for_volume_resource_status(self.volumes_client,
                                                 volume['id'], 'available')
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 3a93f74..ba5245b 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -193,9 +193,10 @@
         # check if microversion is less than 2.25 because of
         # disk_over_commit is depracted since compute api version 2.25
         # if min_microversion is None, it runs on version < 2.25
-        if not migration and (CONF.compute.min_microversion is None or
-                              CONF.compute.min_microversion < '2.25'):
-            migration_kwargs['disk_over_commit'] = False
+        if (self.compute_request_microversion and
+                self.compute_request_microversion < '2.25'):
+            if not migration:
+                migration_kwargs['disk_over_commit'] = False
 
         if dest_host:
             migration_kwargs['host'] = dest_host
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index 700ad3b..5cdf692 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -401,10 +401,29 @@
     def _live_migrate_server(self, server, host_id=None):
         src_host = self.get_host_for_server(server['id'])
 
+        # check if microversion is equal or more than 2.25 because of
+        # block_migration(str) = 'auto' is supported since compute
+        # api version 2.25
+        # else use block_migration_for_live_migration config option
+        # and add disk_over_commit option to migration_kwargs
+        if (self.compute_request_microversion and
+                self.compute_request_microversion < '2.25'):
+            migration_kwargs = {
+                "host": host_id,
+                "block_migration": (CONF.compute_feature_enabled.
+                                    block_migration_for_live_migration),
+                "disk_over_commit": False,
+            }
+
+        else:
+            migration_kwargs = {
+                "host": host_id,
+                "block_migration": "auto",
+            }
+
         self.os_adm.servers_client.live_migrate_server(
             server_id=server['id'],
-            block_migration='auto',
-            host=host_id)
+            **migration_kwargs)
 
         waiters.wait_for_server_status(
             self.servers_client, server['id'], 'ACTIVE')
@@ -997,3 +1016,43 @@
         # Check ping between servers after live migration
         self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
                                         server02_ip, should_connect=True)
+
+    @decorators.idempotent_id('392939d1-2a96-4985-9360-6a222373107a')
+    @testtools.skipUnless(CONF.compute_feature_enabled.live_migration,
+                          'Live migration is not available.')
+    @decorators.attr(type='slow')
+    @utils.services('compute', 'network')
+    def test_live_migrate_vm_with_two_networks(self):
+        """Live migrate a VM with two different networks.
+
+        1. Create server1 with tenant network1 and floating IP
+        2. Check connectivity to server1 via public and private networks
+        3. Create tenant network 2 with server 2
+        4. Attach the new network to the server1
+        5. Check connectivity to server2 from server1
+        6. Live migrate server1
+        7. Check connectivity to server1 via networks 1 and 2
+        8. Check connectivity to server2 from server1
+        """
+
+        self._setup_network_and_servers()
+        server1 = self.servers[0]
+        self._check_public_network_connectivity(should_connect=True)
+        self._check_network_internal_connectivity(network=self.network)
+        self._check_network_external_connectivity()
+        self._create_new_network()
+        new_server = self._create_server(self.new_net)
+        new_server_ips = [addr['addr'] for addr in
+                          new_server['addresses'][self.new_net['name']]]
+
+        # Attach the new network to the server1
+        self._hotplug_server()
+        self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
+                                        new_server_ips, should_connect=True)
+
+        # Live migrate server1 and check connectivity
+        self._live_migrate_server(server=server1)
+        self._check_network_internal_connectivity(network=self.network)
+        self._check_public_network_connectivity(should_connect=True)
+        self._check_server_connectivity(self.floating_ip_tuple.floating_ip,
+                                        new_server_ips, should_connect=True)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 1c3c8bf..28d8ff8 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -288,10 +288,10 @@
         # Assert that the underlying volume is gone.
         self.volumes_client.wait_for_resource_deletion(volume_origin['id'])
 
-    def _do_test_boot_server_from_encrypted_volume_luks(self, provider):
+    def _do_test_boot_server_from_encrypted_volume_luks(self, provider, vtype):
         # Create an encrypted volume
         volume = self.create_encrypted_volume(provider,
-                                              volume_type=provider)
+                                              volume_type=vtype)
 
         self.volumes_client.set_bootable_volume(volume['id'], bootable=True)
 
@@ -315,6 +315,7 @@
     def test_boot_server_from_encrypted_volume_luks(self):
         """LUKs v1 decrypts volume through libvirt."""
         self._do_test_boot_server_from_encrypted_volume_luks(
+            "luks",
             CONF.volume.volume_type_luks
         )
 
@@ -330,5 +331,6 @@
     def test_boot_server_from_encrypted_volume_luksv2(self):
         """LUKs v2 decrypts volume through os-brick."""
         self._do_test_boot_server_from_encrypted_volume_luks(
+            "luks2",
             CONF.volume.volume_type_luks_v2
         )