From 2bb182a28a2f9cb757eb7fb1f53847c1f62ef063 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Sat, 7 Aug 2021 01:04:45 +0530 Subject: [PATCH 1/3] test: add smoke test for live migrate VM with volume Current tests in test_vm_life_cyle.py for migrate VM with volume only do offline migration. Signed-off-by: Abhishek Kumar --- test/integration/smoke/test_vm_life_cycle.py | 72 ++++++++++++++++---- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index 61b3a22a6c8e..8626a3dcaff7 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -1226,7 +1226,7 @@ def tearDown(self): def get_target_host(self, virtualmachineid): target_hosts = Host.listForMigration(self.apiclient, - virtualmachineid=virtualmachineid)[0] + virtualmachineid=virtualmachineid) if len(target_hosts) < 1: self.skipTest("No target hosts found") @@ -1252,7 +1252,8 @@ def deploy_vm(self): serviceofferingid=self.small_offering.id, mode=self.services["mode"]) - def migrate_vm_with_pools(self, target_pool, id): + def migrate_vm_to_pool(self, target_pool, id): + cmd = migrateVirtualMachine.migrateVirtualMachineCmd() cmd.storageid = target_pool.id @@ -1273,17 +1274,17 @@ def create_volume(self): ) """ - BVT for Vmware Offline VM and Volume Migration + BVT for Vmware Offline and Live VM and Volume Migration """ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "security"], required_hardware="false") - def test_01_migrate_VM_and_root_volume(self): + def test_01_offline_migrate_VM_and_root_volume(self): """Test VM will be migrated with it's root volume""" # Validate the following # 1. Deploys a VM - # 2. Finds suitable host for migration + # 2. Stops the VM # 3. Finds suitable storage pool for root volume - # 4. Migrate the VM to new host and storage pool and assert migration successful + # 4. Migrate the VM to new storage pool and assert migration successful vm = self.deploy_vm() @@ -1293,19 +1294,19 @@ def test_01_migrate_VM_and_root_volume(self): vm.stop(self.apiclient) - self.migrate_vm_with_pools(target_pool, vm.id) + self.migrate_vm_to_pool(target_pool, vm.id) root_volume = self.get_vm_volumes(vm.id)[0] self.assertEqual(root_volume.storageid, target_pool.id, "Pool ID was not as expected") @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "security"], required_hardware="false") - def test_02_migrate_VM_with_two_data_disks(self): + def test_02_offline_migrate_VM_with_two_data_disks(self): """Test VM will be migrated with it's root volume""" # Validate the following # 1. Deploys a VM and attaches 2 data disks - # 2. Finds suitable host for migration + # 2. Stops the VM # 3. Finds suitable storage pool for volumes - # 4. Migrate the VM to new host and storage pool and assert migration successful + # 4. Migrate the VM to new storage pool and assert migration successful vm = self.deploy_vm() @@ -1321,7 +1322,7 @@ def test_02_migrate_VM_with_two_data_disks(self): vm.stop(self.apiclient) - self.migrate_vm_with_pools(target_pool, vm.id) + self.migrate_vm_to_pool(target_pool, vm.id) volume1 = Volume.list(self.apiclient, id=volume1.id)[0] volume2 = Volume.list(self.apiclient, id=volume2.id)[0] @@ -1332,7 +1333,54 @@ def test_02_migrate_VM_with_two_data_disks(self): self.assertEqual(volume2.storageid, target_pool.id, "Pool ID was not as expected") @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "security"], required_hardware="false") - def test_03_migrate_detached_volume(self): + def test_03_live_migrate_VM_with_two_data_disks(self): + """Test VM will be migrated with it's root volume""" + # Validate the following + # 1. Deploys a VM and attaches 2 data disks + # 2. Finds suitable host for migration + # 3. Finds suitable storage pool for volumes + # 4. Migrate the VM to new host and storage pool and assert migration successful + + vm = self.deploy_vm() + + root_volume = self.get_vm_volumes(vm.id)[0] + volume1 = self.create_volume() + volume2 = self.create_volume() + vm.attach_volume(self.apiclient, volume1) + vm.attach_volume(self.apiclient, volume2) + + target_host = self.get_target_host(vm.id) + target_pool = self.get_target_pool(root_volume.id) + volume1.target_pool = self.get_target_pool(volume1.id) + volume2.target_pool = self.get_target_pool(volume2.id) + + cmd = migrateVirtualMachineWithVolume.migrateVirtualMachineWithVolumeCmd() + cmd.migrateto = [{"volume": str(root_volume.id), "pool": str(target_pool.id)}, + {"volume": str(volume1.id), "pool": str(volume1.target_pool.id)}, + {"volume": str(volume2.id), "pool": str(volume2.target_pool.id)}] + cmd.virtualmachineid = vm.id + cmd.hostid = target_host.id + + response = self.apiclient.migrateVirtualMachineWithVolume(cmd) + + self.assertEqual(Volume.list(self.apiclient, id=root_volume.id)[0].storageid, + target_pool.id, + "Pool ID not as expected") + + self.assertEqual(Volume.list(self.apiclient, id=volume1.id)[0].storageid, + volume1.target_pool.id, + "Pool ID not as expected") + + self.assertEqual(Volume.list(self.apiclient, id=volume2.id)[0].storageid, + volume2.target_pool.id, + "Pool ID not as expected") + + self.assertEqual(response.hostid, + target_host.id, + "HostID not as expected") + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "security"], required_hardware="false") + def test_04_migrate_detached_volume(self): """Test VM will be migrated with it's root volume""" # Validate the following # 1. Deploys a VM and attaches 1 data disk From 68f6ac35e8296b0392f7f44d48793bb0a88f16d1 Mon Sep 17 00:00:00 2001 From: Gabriel Brascher Date: Fri, 6 Aug 2021 11:28:24 -0300 Subject: [PATCH 2/3] Fix migration issue in UserVmManagerImpl.migrateVirtualMachineWithVolume --- server/src/main/java/com/cloud/vm/UserVmManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index c56a82681d9f..4bd80dadb9ca 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -6418,7 +6418,7 @@ public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinatio throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported"); } - if (VM_STORAGE_MIGRATION_SUPPORTING_HYPERVISORS.contains(vm.getHypervisorType())) { + if (!VM_STORAGE_MIGRATION_SUPPORTING_HYPERVISORS.contains(vm.getHypervisorType())) { throw new InvalidParameterValueException(String.format("Unsupported hypervisor: %s for VM migration, we support XenServer/VMware/KVM only", vm.getHypervisorType())); } From 212056e2f136556c12688d20d0af17560fc92dbe Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Sat, 7 Aug 2021 01:07:34 +0530 Subject: [PATCH 3/3] fix format exception Signed-off-by: Abhishek Kumar --- .../hypervisor/vmware/resource/VmwareResource.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 3e234f2b28d5..d7dc35c1645b 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -48,8 +48,6 @@ import javax.naming.ConfigurationException; import javax.xml.datatype.XMLGregorianCalendar; -import com.cloud.agent.api.GetStoragePoolCapabilitiesAnswer; -import com.cloud.agent.api.GetStoragePoolCapabilitiesCommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; @@ -96,6 +94,8 @@ import com.cloud.agent.api.DeleteVMSnapshotCommand; import com.cloud.agent.api.GetHostStatsAnswer; import com.cloud.agent.api.GetHostStatsCommand; +import com.cloud.agent.api.GetStoragePoolCapabilitiesAnswer; +import com.cloud.agent.api.GetStoragePoolCapabilitiesCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetUnmanagedInstancesAnswer; @@ -103,12 +103,12 @@ import com.cloud.agent.api.GetVmDiskStatsAnswer; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmIpAddressCommand; -import com.cloud.agent.api.GetVmVncTicketCommand; -import com.cloud.agent.api.GetVmVncTicketAnswer; import com.cloud.agent.api.GetVmNetworkStatsAnswer; import com.cloud.agent.api.GetVmNetworkStatsCommand; import com.cloud.agent.api.GetVmStatsAnswer; import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVmVncTicketAnswer; +import com.cloud.agent.api.GetVmVncTicketCommand; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.GetVolumeStatsAnswer; @@ -7540,7 +7540,7 @@ private List relocateVirtualMachine(final VmwareHypervisorHost h } else { String msg = String.format("Successfully migrated VM: %s with its storage to target datastore(s)", vmName); if (targetHyperHost != null) { - msg = String.format("% from host %s to %s", msg, sourceHyperHost.getHyperHostName(), targetHyperHost.getHyperHostName()); + msg = String.format("%s from host %s to %s", msg, sourceHyperHost.getHyperHostName(), targetHyperHost.getHyperHostName()); } s_logger.debug(msg); }