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

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


The following commit(s) were added to refs/heads/4.20 by this push:
     new 52e7b41a54e Add support for functionality in hypervisor class (#9736)
52e7b41a54e is described below

commit 52e7b41a54ee107166421bf14c9d8606c86a9511
Author: Vishesh <[email protected]>
AuthorDate: Tue Dec 3 12:20:59 2024 +0530

    Add support for functionality in hypervisor class (#9736)
    
    * Add support for functionality in hypervisor class
    
    * Address comments
    
    * address comments
---
 .../main/java/com/cloud/hypervisor/Hypervisor.java | 47 +++++++++++++++++++---
 .../command/user/template/RegisterTemplateCmd.java |  4 +-
 .../main/java/com/cloud/vm/UserVmManagerImpl.java  | 36 ++++++-----------
 .../java/com/cloud/vm/UserVmManagerImplTest.java   |  2 +-
 4 files changed, 58 insertions(+), 31 deletions(-)

diff --git a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java 
b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
index e1108b34a83..27ffef1c370 100644
--- a/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
+++ b/api/src/main/java/com/cloud/hypervisor/Hypervisor.java
@@ -20,37 +20,57 @@ import com.cloud.storage.Storage.ImageFormat;
 import org.apache.commons.lang3.StringUtils;
 
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.stream.Collectors;
+
+import static 
com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.DirectDownloadTemplate;
+import static 
com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.RootDiskSizeOverride;
+import static 
com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.VmStorageMigration;
 
 public class Hypervisor {
     public static class HypervisorType {
+        public enum Functionality {
+            DirectDownloadTemplate,
+            RootDiskSizeOverride,
+            VmStorageMigration
+        }
+
         private static final Map<String, HypervisorType> hypervisorTypeMap = 
new LinkedHashMap<>();
         public static final HypervisorType None = new HypervisorType("None"); 
//for storage hosts
-        public static final HypervisorType XenServer = new 
HypervisorType("XenServer", ImageFormat.VHD);
-        public static final HypervisorType KVM = new HypervisorType("KVM", 
ImageFormat.QCOW2);
-        public static final HypervisorType VMware = new 
HypervisorType("VMware", ImageFormat.OVA);
+        public static final HypervisorType XenServer = new 
HypervisorType("XenServer", ImageFormat.VHD, EnumSet.of(RootDiskSizeOverride, 
VmStorageMigration));
+        public static final HypervisorType KVM = new HypervisorType("KVM", 
ImageFormat.QCOW2, EnumSet.of(DirectDownloadTemplate, RootDiskSizeOverride, 
VmStorageMigration));
+        public static final HypervisorType VMware = new 
HypervisorType("VMware", ImageFormat.OVA, EnumSet.of(RootDiskSizeOverride, 
VmStorageMigration));
         public static final HypervisorType Hyperv = new 
HypervisorType("Hyperv");
         public static final HypervisorType VirtualBox = new 
HypervisorType("VirtualBox");
         public static final HypervisorType Parralels = new 
HypervisorType("Parralels");
         public static final HypervisorType BareMetal = new 
HypervisorType("BareMetal");
-        public static final HypervisorType Simulator = new 
HypervisorType("Simulator");
+        public static final HypervisorType Simulator = new 
HypervisorType("Simulator", null, EnumSet.of(RootDiskSizeOverride, 
VmStorageMigration));
         public static final HypervisorType Ovm = new HypervisorType("Ovm", 
ImageFormat.RAW);
         public static final HypervisorType Ovm3 = new HypervisorType("Ovm3", 
ImageFormat.RAW);
         public static final HypervisorType LXC = new HypervisorType("LXC");
-        public static final HypervisorType Custom = new 
HypervisorType("Custom");
+        public static final HypervisorType Custom = new 
HypervisorType("Custom", null, EnumSet.of(RootDiskSizeOverride));
         public static final HypervisorType Any = new HypervisorType("Any"); 
/*If you don't care about the hypervisor type*/
         private final String name;
         private final ImageFormat imageFormat;
+        private final Set<Functionality> supportedFunctionalities;
 
         public HypervisorType(String name) {
-            this(name, null);
+            this(name, null, EnumSet.noneOf(Functionality.class));
         }
 
         public HypervisorType(String name, ImageFormat imageFormat) {
+            this(name, imageFormat, EnumSet.noneOf(Functionality.class));
+        }
+
+        public HypervisorType(String name, ImageFormat imageFormat, 
Set<Functionality> supportedFunctionalities) {
             this.name = name;
             this.imageFormat = imageFormat;
+            this.supportedFunctionalities = supportedFunctionalities;
             if (name.equals("Parralels")){ // typo in the original code
                 hypervisorTypeMap.put("parallels", this);
             } else {
@@ -81,6 +101,12 @@ public class Hypervisor {
             return hypervisorType;
         }
 
+        public static List<HypervisorType> 
getListOfHypervisorsSupportingFunctionality(Functionality functionality) {
+            return hypervisorTypeMap.values().stream()
+                    .filter(hypervisor -> 
hypervisor.supportedFunctionalities.contains(functionality))
+                    .collect(Collectors.toList());
+        }
+
         /**
          * Returns the display name of a hypervisor type in case the custom 
hypervisor is used,
          * using the 'hypervisor.custom.display.name' setting. Otherwise, 
returns hypervisor name
@@ -102,6 +128,15 @@ public class Hypervisor {
             return name;
         }
 
+        /**
+         * Make this method to be part of the properties of the hypervisor 
type itself.
+         *
+         * @return true if the hypervisor plugin support the specified 
functionality
+         */
+        public boolean isFunctionalitySupported(Functionality functionality) {
+            return supportedFunctionalities.contains(functionality);
+        }
+
         @Override
         public int hashCode() {
             return Objects.hash(name);
diff --git 
a/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
 
b/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
index a7826dedcd0..1f968b869b9 100644
--- 
a/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
+++ 
b/api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
@@ -362,7 +362,9 @@ public class RegisterTemplateCmd extends BaseCmd implements 
UserCmd {
                     "Parameter zoneids cannot combine all zones (-1) option 
with other zones");
 
         String customHypervisor = 
HypervisorGuru.HypervisorCustomDisplayName.value();
-        if (isDirectDownload() && 
!(getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.KVM.toString())
+        if (isDirectDownload() &&
+                !(Hypervisor.HypervisorType.getType(getHypervisor())
+                        
.isFunctionalitySupported(Hypervisor.HypervisorType.Functionality.DirectDownloadTemplate)
                 || getHypervisor().equalsIgnoreCase(customHypervisor))) {
             throw new ServerApiException(ApiErrorCode.PARAM_ERROR, 
String.format("Parameter directdownload " +
                     "is only allowed for KVM or %s templates", 
customHypervisor));
diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java 
b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 219feeef5a9..04b64dd80a3 100644
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.vm;
 
+import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality;
 import static com.cloud.storage.Volume.IOPS_LIMIT;
 import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
 import static org.apache.cloudstack.api.ApiConstants.MAX_IOPS;
@@ -679,23 +680,6 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
     private static final ConfigKey<Boolean> VmDestroyForcestop = new 
ConfigKey<Boolean>("Advanced", Boolean.class, "vm.destroy.forcestop", "false",
             "On destroy, force-stop takes this value ", true);
 
-    public static final List<HypervisorType> 
VM_STORAGE_MIGRATION_SUPPORTING_HYPERVISORS = new ArrayList<>(Arrays.asList(
-            HypervisorType.KVM,
-            HypervisorType.VMware,
-            HypervisorType.XenServer,
-            HypervisorType.Simulator
-    ));
-
-    protected static final List<HypervisorType> 
ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS = Arrays.asList(
-            HypervisorType.KVM,
-            HypervisorType.XenServer,
-            HypervisorType.VMware,
-            HypervisorType.Simulator,
-            HypervisorType.Custom
-    );
-
-    private static final List<HypervisorType> 
HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS = 
Arrays.asList(HypervisorType.KVM, HypervisorType.VMware);
-
     @Override
     public UserVmVO getVirtualMachine(long vmId) {
         return _vmDao.findById(vmId);
@@ -4563,7 +4547,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
      * @throws InvalidParameterValueException if the hypervisor does not 
support rootdisksize override
      */
     protected void 
verifyIfHypervisorSupportsRootdiskSizeOverride(HypervisorType hypervisorType) {
-        if 
(!ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS.contains(hypervisorType)) {
+        if 
(!hypervisorType.isFunctionalitySupported(Functionality.RootDiskSizeOverride)) {
             throw new InvalidParameterValueException("Hypervisor " + 
hypervisorType + " does not support rootdisksize override");
         }
     }
@@ -6606,9 +6590,12 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
         }
 
         HypervisorType hypervisorType = vm.getHypervisorType();
-        if (vm.getType() != VirtualMachine.Type.User && 
!HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS.contains(hypervisorType))
 {
-            throw new InvalidParameterValueException(String.format("Unable to 
migrate storage of non-user VMs for hypervisor [%s]. Operation only supported 
for the following"
-                    + " hypervisors: [%s].", hypervisorType, 
HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS));
+        List<HypervisorType> supportedHypervisorsForNonUserVMStorageMigration 
= 
HypervisorType.getListOfHypervisorsSupportingFunctionality(Functionality.VmStorageMigration)
+                .stream().filter(hypervisor -> 
!hypervisor.equals(HypervisorType.XenServer)).collect(Collectors.toList());
+        if (vm.getType() != VirtualMachine.Type.User && 
!supportedHypervisorsForNonUserVMStorageMigration.contains(hypervisorType)) {
+            throw new InvalidParameterValueException(String.format(
+                    "Unable to migrate storage of non-user VMs for hypervisor 
[%s]. Operation only supported for the following hypervisors: [%s].",
+                    hypervisorType, 
supportedHypervisorsForNonUserVMStorageMigration));
         }
 
         List<VolumeVO> vols = _volsDao.findByInstance(vm.getId());
@@ -7318,8 +7305,11 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Vir
             throw new InvalidParameterValueException("Live Migration of GPU 
enabled VM is not supported");
         }
 
-        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()));
+        if 
(!vm.getHypervisorType().isFunctionalitySupported(Functionality.VmStorageMigration))
 {
+            throw new InvalidParameterValueException(
+                    String.format("Unsupported hypervisor: %s for VM 
migration, we support [%s] only",
+                            vm.getHypervisorType(),
+                            
HypervisorType.getListOfHypervisorsSupportingFunctionality(Functionality.VmStorageMigration)));
         }
 
         if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java 
b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
index 8316c57d67d..d49dcd0f00c 100644
--- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
+++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java
@@ -635,7 +635,7 @@ public class UserVmManagerImplTest {
         int expectedExceptionCounter = hypervisorTypeArray.length - 5;
 
         for(int i = 0; i < hypervisorTypeArray.length; i++) {
-            if 
(UserVmManagerImpl.ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS.contains(hypervisorTypeArray[i]))
 {
+            if 
(hypervisorTypeArray[i].isFunctionalitySupported(Hypervisor.HypervisorType.Functionality.RootDiskSizeOverride))
 {
                 
userVmManagerImpl.verifyIfHypervisorSupportsRootdiskSizeOverride(hypervisorTypeArray[i]);
             } else {
                 try {

Reply via email to