This is an automated email from the ASF dual-hosted git repository.

dahn pushed a commit to branch 4.18
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.18 by this push:
     new cec6ade257c change live migration API used on kvm (#8952)
cec6ade257c is described below

commit cec6ade257ca231f7bb5a7062ee1ef0739b24e32
Author: João Jandre <[email protected]>
AuthorDate: Thu Apr 25 04:35:25 2024 -0300

    change live migration API used on kvm (#8952)
---
 .../hypervisor/kvm/resource/LibvirtVMDef.java      |  4 ++
 .../hypervisor/kvm/resource/MigrateKVMAsync.java   | 45 +++++++++++-
 .../wrapper/LibvirtMigrateCommandWrapper.java      | 29 +++++++-
 .../kvm/resource/MigrateKVMAsyncTest.java          | 83 ++++++++++++++++++++++
 .../wrapper/LibvirtMigrateCommandWrapperTest.java  | 78 ++++++++++++++++++--
 5 files changed, 230 insertions(+), 9 deletions(-)

diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
index 6d69b2f9664..c3b5f9857eb 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
@@ -972,6 +972,10 @@ public class LibvirtVMDef {
             return _diskLabel;
         }
 
+        public void setDiskLabel(String label) {
+            _diskLabel = label;
+        }
+
         public DiskType getDiskType() {
             return _diskType;
         }
diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/MigrateKVMAsync.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/MigrateKVMAsync.java
index c3917314250..bc94bb47ed8 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/MigrateKVMAsync.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/MigrateKVMAsync.java
@@ -18,13 +18,20 @@
  */
 package com.cloud.hypervisor.kvm.resource;
 
+import java.util.Iterator;
+import java.util.Set;
 import java.util.concurrent.Callable;
 
+import org.apache.log4j.Logger;
 import org.libvirt.Connect;
 import org.libvirt.Domain;
 import org.libvirt.LibvirtException;
+import org.libvirt.TypedParameter;
+import org.libvirt.TypedStringParameter;
+import org.libvirt.TypedUlongParameter;
 
 public class MigrateKVMAsync implements Callable<Domain> {
+    protected Logger logger = Logger.getLogger(getClass());
 
     private final LibvirtComputingResource libvirtComputingResource;
 
@@ -37,6 +44,8 @@ public class MigrateKVMAsync implements Callable<Domain> {
     private boolean migrateNonSharedInc;
     private boolean autoConvergence;
 
+    protected Set<String> migrateDiskLabels;
+
     // Libvirt Migrate Flags reference:
     // 
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainMigrateFlags
 
@@ -87,7 +96,7 @@ public class MigrateKVMAsync implements Callable<Domain> {
     private static final int LIBVIRT_VERSION_SUPPORTS_AUTO_CONVERGE = 1002003;
 
     public MigrateKVMAsync(final LibvirtComputingResource 
libvirtComputingResource, final Domain dm, final Connect dconn, final String 
dxml,
-            final boolean migrateStorage, final boolean migrateNonSharedInc, 
final boolean autoConvergence, final String vmName, final String destIp) {
+            final boolean migrateStorage, final boolean migrateNonSharedInc, 
final boolean autoConvergence, final String vmName, final String destIp, 
Set<String> migrateDiskLabels) {
         this.libvirtComputingResource = libvirtComputingResource;
 
         this.dm = dm;
@@ -98,6 +107,7 @@ public class MigrateKVMAsync implements Callable<Domain> {
         this.autoConvergence = autoConvergence;
         this.vmName = vmName;
         this.destIp = destIp;
+        this.migrateDiskLabels = migrateDiskLabels;
     }
 
     @Override
@@ -121,6 +131,37 @@ public class MigrateKVMAsync implements Callable<Domain> {
             flags |= VIR_MIGRATE_AUTO_CONVERGE;
         }
 
-        return dm.migrate(dconn, flags, dxml, vmName, "tcp:" + destIp, 
libvirtComputingResource.getMigrateSpeed());
+        TypedParameter [] parameters = createTypedParameterList();
+
+        logger.debug(String.format("Migrating [%s] with flags [%s], 
destination [%s] and speed [%s]. The disks with the following labels will be 
migrated [%s].", vmName, flags,
+                destIp, libvirtComputingResource.getMigrateSpeed(), 
migrateDiskLabels));
+
+        return dm.migrate(dconn, parameters, flags);
+
+    }
+
+    protected TypedParameter[] createTypedParameterList() {
+        int sizeOfMigrateDiskLabels = 0;
+        if (migrateDiskLabels != null) {
+            sizeOfMigrateDiskLabels = migrateDiskLabels.size();
+        }
+
+        TypedParameter[] parameters = new TypedParameter[4 + 
sizeOfMigrateDiskLabels];
+        parameters[0] = new 
TypedStringParameter(Domain.DomainMigrateParameters.VIR_MIGRATE_PARAM_DEST_NAME,
 vmName);
+        parameters[1] = new 
TypedStringParameter(Domain.DomainMigrateParameters.VIR_MIGRATE_PARAM_DEST_XML, 
dxml);
+        parameters[2] = new 
TypedStringParameter(Domain.DomainMigrateParameters.VIR_MIGRATE_PARAM_URI, 
"tcp:" + destIp);
+        parameters[3] = new 
TypedUlongParameter(Domain.DomainMigrateParameters.VIR_MIGRATE_PARAM_BANDWIDTH, 
libvirtComputingResource.getMigrateSpeed());
+
+        if (sizeOfMigrateDiskLabels == 0) {
+            return parameters;
+        }
+
+        Iterator<String> iterator = migrateDiskLabels.iterator();
+        for (int i = 0; i < sizeOfMigrateDiskLabels; i++) {
+            parameters[4 + i] = new 
TypedStringParameter(Domain.DomainMigrateParameters.VIR_MIGRATE_PARAM_MIGRATE_DISKS,
 iterator.next());
+        }
+
+        return parameters;
     }
+
 }
diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java
index fb526626ef8..aebbaa4119d 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -190,6 +191,7 @@ public final class LibvirtMigrateCommandWrapper extends 
CommandWrapper<MigrateCo
             // migrateStorage's value should always only be associated with 
the initial state of mapMigrateStorage.
             final boolean migrateStorage = 
MapUtils.isNotEmpty(mapMigrateStorage);
             final boolean migrateStorageManaged = 
command.isMigrateStorageManaged();
+            Set<String> migrateDiskLabels = null;
 
             if (migrateStorage) {
                 if (s_logger.isDebugEnabled()) {
@@ -199,6 +201,7 @@ public final class LibvirtMigrateCommandWrapper extends 
CommandWrapper<MigrateCo
                 if (s_logger.isDebugEnabled()) {
                     s_logger.debug(String.format("Changed VM [%s] XML 
configuration of used storage. New XML configuration is [%s].", vmName, 
xmlDesc));
                 }
+                migrateDiskLabels = getMigrateStorageDeviceLabels(disks, 
mapMigrateStorage);
             }
 
             Map<String, DpdkTO> dpdkPortsMapping = 
command.getDpdkInterfaceMapping();
@@ -227,7 +230,7 @@ public final class LibvirtMigrateCommandWrapper extends 
CommandWrapper<MigrateCo
 
             final Callable<Domain> worker = new 
MigrateKVMAsync(libvirtComputingResource, dm, dconn, xmlDesc,
                     migrateStorage, migrateNonSharedInc,
-                    command.isAutoConvergence(), vmName, 
command.getDestinationIp());
+                    command.isAutoConvergence(), vmName, 
command.getDestinationIp(), migrateDiskLabels);
             final Future<Domain> migrateThread = executor.submit(worker);
             executor.shutdown();
             long sleeptime = 0;
@@ -365,6 +368,30 @@ public final class LibvirtMigrateCommandWrapper extends 
CommandWrapper<MigrateCo
         return new MigrateAnswer(command, result == null, result, null);
     }
 
+    /**
+     * Gets the disk labels (vda, vdb...) of the disks mapped for migration on 
mapMigrateStorage.
+     * @param diskDefinitions list of all the disksDefinitions of the VM.
+     * @param mapMigrateStorage map of the disks that should be migrated.
+     * @return set with the labels of the disks that should be migrated.
+     * */
+    protected Set<String> getMigrateStorageDeviceLabels(List<DiskDef> 
diskDefinitions, Map<String, MigrateCommand.MigrateDiskInfo> mapMigrateStorage) 
{
+        HashSet<String> setOfLabels = new HashSet<>();
+        s_logger.debug(String.format("Searching for disk labels of disks 
[%s].", mapMigrateStorage.keySet()));
+        for (String fileName : mapMigrateStorage.keySet()) {
+            for (DiskDef diskDef : diskDefinitions) {
+                String diskPath = diskDef.getDiskPath();
+                if (diskPath != null && diskPath.contains(fileName)) {
+                    setOfLabels.add(diskDef.getDiskLabel());
+                    s_logger.debug(String.format("Found label [%s] for disk 
[%s].", diskDef.getDiskLabel(), fileName));
+                    break;
+                }
+            }
+        }
+
+        return setOfLabels;
+    }
+
+
     /**
      * Checks if the CPU shares are equal in the source host and destination 
host.
      *  <ul>
diff --git 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/MigrateKVMAsyncTest.java
 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/MigrateKVMAsyncTest.java
new file mode 100644
index 00000000000..28633b925b2
--- /dev/null
+++ 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/MigrateKVMAsyncTest.java
@@ -0,0 +1,83 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+//
+
+package com.cloud.hypervisor.kvm.resource;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.libvirt.Connect;
+import org.libvirt.Domain;
+import org.libvirt.TypedParameter;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Set;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MigrateKVMAsyncTest {
+
+    @Mock
+    private LibvirtComputingResource libvirtComputingResource;
+    @Mock
+    private Connect connect;
+    @Mock
+    private Domain domain;
+
+
+    @Test
+    public void createTypedParameterListTestNoMigrateDiskLabels() {
+        MigrateKVMAsync migrateKVMAsync = new 
MigrateKVMAsync(libvirtComputingResource, domain, connect, "testxml",
+                false, false, false, "tst", "1.1.1.1", null);
+
+        Mockito.doReturn(10).when(libvirtComputingResource).getMigrateSpeed();
+
+        TypedParameter[] result = migrateKVMAsync.createTypedParameterList();
+
+        Assert.assertEquals(4, result.length);
+
+        Assert.assertEquals("tst", result[0].getValueAsString());
+        Assert.assertEquals("testxml", result[1].getValueAsString());
+        Assert.assertEquals("tcp:1.1.1.1", result[2].getValueAsString());
+        Assert.assertEquals("10", result[3].getValueAsString());
+
+    }
+
+    @Test
+    public void createTypedParameterListTestWithMigrateDiskLabels() {
+        Set<String> labels = Set.of("vda", "vdb");
+        MigrateKVMAsync migrateKVMAsync = new 
MigrateKVMAsync(libvirtComputingResource, domain, connect, "testxml",
+                false, false, false, "tst", "1.1.1.1", labels);
+
+        Mockito.doReturn(10).when(libvirtComputingResource).getMigrateSpeed();
+
+        TypedParameter[] result = migrateKVMAsync.createTypedParameterList();
+
+        Assert.assertEquals(6, result.length);
+
+        Assert.assertEquals("tst", result[0].getValueAsString());
+        Assert.assertEquals("testxml", result[1].getValueAsString());
+        Assert.assertEquals("tcp:1.1.1.1", result[2].getValueAsString());
+        Assert.assertEquals("10", result[3].getValueAsString());
+
+        Assert.assertEquals(labels, Set.of(result[4].getValueAsString(), 
result[5].getValueAsString()));
+    }
+
+}
diff --git 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java
 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java
index c206f898e97..7071758fcbe 100644
--- 
a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java
+++ 
b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java
@@ -26,10 +26,12 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Scanner;
+import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -585,6 +587,14 @@ public class LibvirtMigrateCommandWrapperTest {
             "  </devices>\n" +
             "</domain>\n";
 
+    private Map<String, MigrateDiskInfo> createMapMigrateStorage(String 
sourceText, String path) {
+        Map<String, MigrateDiskInfo> mapMigrateStorage = new HashMap<String, 
MigrateDiskInfo>();
+
+        MigrateDiskInfo diskInfo = new MigrateDiskInfo("123456", 
DiskType.BLOCK, DriverType.RAW, Source.FILE, sourceText);
+        mapMigrateStorage.put(path, diskInfo);
+        return mapMigrateStorage;
+    }
+
     @Test
     public void testReplaceIpForVNCInDescFile() {
         final String targetIp = "192.168.22.21";
@@ -761,10 +771,8 @@ public class LibvirtMigrateCommandWrapperTest {
 
     @Test
     public void testReplaceStorage() throws Exception {
-        Map<String, MigrateDiskInfo> mapMigrateStorage = new HashMap<String, 
MigrateDiskInfo>();
+        Map<String, MigrateDiskInfo> mapMigrateStorage = 
createMapMigrateStorage("sourceTest", 
"/mnt/812ea6a3-7ad0-30f4-9cab-01e3f2985b98/4650a2f7-fce5-48e2-beaa-bcdf063194e6");
 
-        MigrateDiskInfo diskInfo = new MigrateDiskInfo("123456", 
DiskType.BLOCK, DriverType.RAW, Source.FILE, "sourctest");
-        
mapMigrateStorage.put("/mnt/812ea6a3-7ad0-30f4-9cab-01e3f2985b98/4650a2f7-fce5-48e2-beaa-bcdf063194e6",
 diskInfo);
         final String result = 
libvirtMigrateCmdWrapper.replaceStorage(fullfile, mapMigrateStorage, true);
 
         InputStream in = IOUtils.toInputStream(result);
@@ -778,7 +786,6 @@ public class LibvirtMigrateCommandWrapperTest {
 
     @Test
     public void testReplaceStorageWithSecrets() throws Exception {
-        Map<String, MigrateDiskInfo> mapMigrateStorage = new HashMap<String, 
MigrateDiskInfo>();
 
         final String xmlDesc =
             "<domain type='kvm' id='3'>" +
@@ -799,8 +806,7 @@ public class LibvirtMigrateCommandWrapperTest {
 
         final String volumeFile = "3530f749-82fd-458e-9485-a357e6e541db";
         String newDiskPath = "/mnt/2d0435e1-99e0-4f1d-94c0-bee1f6f8b99e/" + 
volumeFile;
-        MigrateDiskInfo diskInfo = new MigrateDiskInfo("123456", 
DiskType.BLOCK, DriverType.RAW, Source.FILE, newDiskPath);
-        
mapMigrateStorage.put("/mnt/07eb495b-5590-3877-9fb7-23c6e9a40d40/bf8621b3-027c-497d-963b-06319650f048",
 diskInfo);
+        Map<String, MigrateDiskInfo> mapMigrateStorage = 
createMapMigrateStorage(newDiskPath, 
"/mnt/07eb495b-5590-3877-9fb7-23c6e9a40d40/bf8621b3-027c-497d-963b-06319650f048");
         final String result = libvirtMigrateCmdWrapper.replaceStorage(xmlDesc, 
mapMigrateStorage, false);
         final String expectedSecretUuid = 
LibvirtComputingResource.generateSecretUUIDFromString(volumeFile);
 
@@ -951,4 +957,64 @@ public class LibvirtMigrateCommandWrapperTest {
 
         Assert.assertEquals(updateShares, newVmCpuShares);
     }
+
+    @Test
+    public void getMigrateStorageDeviceLabelsTestNoDiskDefinitions() {
+        Map<String, MigrateDiskInfo> mapMigrateStorage = 
createMapMigrateStorage("sourceTest", 
"/mnt/812ea6a3-7ad0-30f4-9cab-01e3f2985b98/4650a2f7-fce5-48e2-beaa-bcdf063194e6");
+
+        Set<String> result = 
libvirtMigrateCmdWrapper.getMigrateStorageDeviceLabels(new ArrayList<>(), 
mapMigrateStorage);
+
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void getMigrateStorageDeviceLabelsTestNoMapMigrateStorage() {
+        List<DiskDef> disks = new ArrayList<>();
+        DiskDef diskDef0 = new DiskDef();
+
+        diskDef0.setDiskPath("volPath");
+        disks.add(diskDef0);
+
+        Set<String> result = 
libvirtMigrateCmdWrapper.getMigrateStorageDeviceLabels(disks, new HashMap<>());
+
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void getMigrateStorageDeviceLabelsTestPathIsNotFound() {
+        List<DiskDef> disks = new ArrayList<>();
+        DiskDef diskDef0 = new DiskDef();
+
+        diskDef0.setDiskPath("volPath");
+        disks.add(diskDef0);
+
+        Map<String, MigrateDiskInfo> mapMigrateStorage = 
createMapMigrateStorage("sourceTest", 
"/mnt/812ea6a3-7ad0-30f4-9cab-01e3f2985b98/4650a2f7-fce5-48e2-beaa-bcdf063194e6");
+
+        Set<String> result = 
libvirtMigrateCmdWrapper.getMigrateStorageDeviceLabels(disks, 
mapMigrateStorage);
+
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void getMigrateStorageDeviceLabelsTestFindPathAndLabels() {
+        List<DiskDef> disks = new ArrayList<>();
+        DiskDef diskDef0 = new DiskDef();
+        DiskDef diskDef1 = new DiskDef();
+
+        diskDef0.setDiskPath("volPath1");
+        diskDef0.setDiskLabel("vda");
+        disks.add(diskDef0);
+
+        diskDef1.setDiskPath("volPath2");
+        diskDef1.setDiskLabel("vdb");
+        disks.add(diskDef1);
+
+        Map<String, MigrateDiskInfo> mapMigrateStorage = 
createMapMigrateStorage("sourceTest", "volPath1");
+        mapMigrateStorage.put("volPath2", new MigrateDiskInfo("123457", 
DiskType.BLOCK, DriverType.RAW, Source.FILE, "sourceText"));
+
+        Set<String> result = 
libvirtMigrateCmdWrapper.getMigrateStorageDeviceLabels(disks, 
mapMigrateStorage);
+
+        assertTrue(result.containsAll(Arrays.asList("vda", "vdb")));
+    }
+
 }

Reply via email to