mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	api,server: add params for updatehypervisorcapabilities API (#5473)
* api,server: add params for updatehypervisorcapabilities API Allows updating following capabilities for a hypervisor, version: - Max DATA volumes limit - Storage motion supported - Max hosts per cluster - VM snapshot enabled * added test * changes Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * Update test/integration/smoke/test_hypervisor_capabilities.py Co-authored-by: dahn <daan.hoogland@gmail.com>
This commit is contained in:
		
							parent
							
								
									8adb8df2fe
								
							
						
					
					
						commit
						62b806ac13
					
				| @ -52,4 +52,6 @@ public interface HypervisorCapabilities extends Identity, InternalIdentity { | |||||||
| 
 | 
 | ||||||
|     boolean isStorageMotionSupported(); |     boolean isStorageMotionSupported(); | ||||||
| 
 | 
 | ||||||
|  |     Boolean isVmSnapshotEnabled(); | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -22,6 +22,7 @@ import java.util.Map; | |||||||
| 
 | 
 | ||||||
| import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; | import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; | ||||||
| import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; | import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; | ||||||
|  | import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; | ||||||
| import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCmd; | import org.apache.cloudstack.api.command.admin.guest.AddGuestOsCmd; | ||||||
| import org.apache.cloudstack.api.command.admin.guest.AddGuestOsMappingCmd; | import org.apache.cloudstack.api.command.admin.guest.AddGuestOsMappingCmd; | ||||||
| import org.apache.cloudstack.api.command.admin.guest.ListGuestOsMappingCmd; | import org.apache.cloudstack.api.command.admin.guest.ListGuestOsMappingCmd; | ||||||
| @ -407,7 +408,7 @@ public interface ManagementService { | |||||||
|     Pair<List<? extends HypervisorCapabilities>, Integer> listHypervisorCapabilities(Long id, HypervisorType hypervisorType, String keyword, Long startIndex, |     Pair<List<? extends HypervisorCapabilities>, Integer> listHypervisorCapabilities(Long id, HypervisorType hypervisorType, String keyword, Long startIndex, | ||||||
|             Long pageSizeVal); |             Long pageSizeVal); | ||||||
| 
 | 
 | ||||||
|     HypervisorCapabilities updateHypervisorCapabilities(Long id, Long maxGuestsLimit, Boolean securityGroupEnabled); |     HypervisorCapabilities updateHypervisorCapabilities(UpdateHypervisorCapabilitiesCmd cmd); | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * list all the top consumed resources across different capacity types |      * list all the top consumed resources across different capacity types | ||||||
|  | |||||||
| @ -590,6 +590,7 @@ public class ApiConstants { | |||||||
|     public static final String MIGRATE_ALLOWED = "migrateallowed"; |     public static final String MIGRATE_ALLOWED = "migrateallowed"; | ||||||
|     public static final String MIGRATE_TO = "migrateto"; |     public static final String MIGRATE_TO = "migrateto"; | ||||||
|     public static final String GUID = "guid"; |     public static final String GUID = "guid"; | ||||||
|  |     public static final String VM_SNAPSHOT_ENABELD = "vmsnapshotenabled"; | ||||||
|     public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; |     public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; | ||||||
|     public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; |     public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; | ||||||
|     public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname"; |     public static final String VSWITCH_NAME_GUEST_TRAFFIC = "guestvswitchname"; | ||||||
|  | |||||||
| @ -52,6 +52,18 @@ public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { | |||||||
|     @Parameter(name = ApiConstants.MAX_GUESTS_LIMIT, type = CommandType.LONG, description = "the max number of Guest VMs per host for this hypervisor.") |     @Parameter(name = ApiConstants.MAX_GUESTS_LIMIT, type = CommandType.LONG, description = "the max number of Guest VMs per host for this hypervisor.") | ||||||
|     private Long maxGuestsLimit; |     private Long maxGuestsLimit; | ||||||
| 
 | 
 | ||||||
|  |     @Parameter(name = ApiConstants.MAX_DATA_VOLUMES_LIMIT, type = CommandType.INTEGER, description = "the maximum number of Data Volumes that can be attached to a VM for this hypervisor.", since = "4.16.0") | ||||||
|  |     private Integer maxDataVolumesLimit; | ||||||
|  | 
 | ||||||
|  |     @Parameter(name = ApiConstants.STORAGE_MOTION_ENABLED, type = CommandType.BOOLEAN, description = "set true to enable storage motion support for this hypervisor", since = "4.16.0") | ||||||
|  |     private Boolean storageMotionSupported; | ||||||
|  | 
 | ||||||
|  |     @Parameter(name = ApiConstants.MAX_HOSTS_PER_CLUSTER, type = CommandType.INTEGER, description = "the maximum number of the hypervisor hosts per cluster ", since = "4.16.0") | ||||||
|  |     private Integer maxHostsPerClusterLimit; | ||||||
|  | 
 | ||||||
|  |     @Parameter(name = ApiConstants.VM_SNAPSHOT_ENABELD, type = CommandType.BOOLEAN, description = "set true to enable VM snapshots for this hypervisor", since = "4.16.0") | ||||||
|  |     private Boolean vmSnapshotEnabled; | ||||||
|  | 
 | ||||||
|     ///////////////////////////////////////////////////// |     ///////////////////////////////////////////////////// | ||||||
|     /////////////////// Accessors /////////////////////// |     /////////////////// Accessors /////////////////////// | ||||||
|     ///////////////////////////////////////////////////// |     ///////////////////////////////////////////////////// | ||||||
| @ -68,6 +80,22 @@ public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { | |||||||
|         return maxGuestsLimit; |         return maxGuestsLimit; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public Integer getMaxDataVolumesLimit() { | ||||||
|  |         return maxDataVolumesLimit; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Boolean getStorageMotionSupported() { | ||||||
|  |         return storageMotionSupported; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Integer getMaxHostsPerClusterLimit() { | ||||||
|  |         return maxHostsPerClusterLimit; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Boolean getVmSnapshotEnabled() { | ||||||
|  |         return vmSnapshotEnabled; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     ///////////////////////////////////////////////////// |     ///////////////////////////////////////////////////// | ||||||
|     /////////////// API Implementation/////////////////// |     /////////////// API Implementation/////////////////// | ||||||
|     ///////////////////////////////////////////////////// |     ///////////////////////////////////////////////////// | ||||||
| @ -84,7 +112,7 @@ public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { | |||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void execute() { |     public void execute() { | ||||||
|         HypervisorCapabilities result = _mgr.updateHypervisorCapabilities(getId(), getMaxGuestsLimit(), getSecurityGroupEnabled()); |         HypervisorCapabilities result = _mgr.updateHypervisorCapabilities(this); | ||||||
|         if (result != null) { |         if (result != null) { | ||||||
|             HypervisorCapabilitiesResponse response = _responseGenerator.createHypervisorCapabilitiesResponse(result); |             HypervisorCapabilitiesResponse response = _responseGenerator.createHypervisorCapabilitiesResponse(result); | ||||||
|             response.setResponseName(getCommandName()); |             response.setResponseName(getCommandName()); | ||||||
|  | |||||||
| @ -16,8 +16,6 @@ | |||||||
| // under the License. | // under the License. | ||||||
| package org.apache.cloudstack.api.response; | package org.apache.cloudstack.api.response; | ||||||
| 
 | 
 | ||||||
| import com.google.gson.annotations.SerializedName; |  | ||||||
| 
 |  | ||||||
| import org.apache.cloudstack.api.ApiConstants; | import org.apache.cloudstack.api.ApiConstants; | ||||||
| import org.apache.cloudstack.api.BaseResponse; | import org.apache.cloudstack.api.BaseResponse; | ||||||
| import org.apache.cloudstack.api.EntityReference; | import org.apache.cloudstack.api.EntityReference; | ||||||
| @ -25,6 +23,7 @@ import org.apache.cloudstack.api.EntityReference; | |||||||
| import com.cloud.hypervisor.Hypervisor.HypervisorType; | import com.cloud.hypervisor.Hypervisor.HypervisorType; | ||||||
| import com.cloud.hypervisor.HypervisorCapabilities; | import com.cloud.hypervisor.HypervisorCapabilities; | ||||||
| import com.cloud.serializer.Param; | import com.cloud.serializer.Param; | ||||||
|  | import com.google.gson.annotations.SerializedName; | ||||||
| 
 | 
 | ||||||
| @EntityReference(value = HypervisorCapabilities.class) | @EntityReference(value = HypervisorCapabilities.class) | ||||||
| public class HypervisorCapabilitiesResponse extends BaseResponse { | public class HypervisorCapabilitiesResponse extends BaseResponse { | ||||||
| @ -60,6 +59,10 @@ public class HypervisorCapabilitiesResponse extends BaseResponse { | |||||||
|     @Param(description = "true if storage motion is supported") |     @Param(description = "true if storage motion is supported") | ||||||
|     private boolean isStorageMotionSupported; |     private boolean isStorageMotionSupported; | ||||||
| 
 | 
 | ||||||
|  |     @SerializedName(ApiConstants.VM_SNAPSHOT_ENABELD) | ||||||
|  |     @Param(description = "true if VM snapshots are enabled for this hypervisor") | ||||||
|  |     private boolean isVmSnapshotEnabled; | ||||||
|  | 
 | ||||||
|     public String getId() { |     public String getId() { | ||||||
|         return id; |         return id; | ||||||
|     } |     } | ||||||
| @ -123,4 +126,12 @@ public class HypervisorCapabilitiesResponse extends BaseResponse { | |||||||
|     public void setMaxHostsPerCluster(Integer maxHostsPerCluster) { |     public void setMaxHostsPerCluster(Integer maxHostsPerCluster) { | ||||||
|         this.maxHostsPerCluster = maxHostsPerCluster; |         this.maxHostsPerCluster = maxHostsPerCluster; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public boolean isVmSnapshotEnabled() { | ||||||
|  |         return isVmSnapshotEnabled; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setVmSnapshotEnabled(boolean vmSnapshotEnabled) { | ||||||
|  |         isVmSnapshotEnabled = vmSnapshotEnabled; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -189,7 +189,8 @@ public class HypervisorCapabilitiesVO implements HypervisorCapabilities { | |||||||
|         this.maxHostsPerCluster = maxHostsPerCluster; |         this.maxHostsPerCluster = maxHostsPerCluster; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Boolean getVmSnapshotEnabled() { |     @Override | ||||||
|  |     public Boolean isVmSnapshotEnabled() { | ||||||
|         return vmSnapshotEnabled; |         return vmSnapshotEnabled; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -105,7 +105,7 @@ public class HypervisorCapabilitiesDaoImpl extends GenericDaoBase<HypervisorCapa | |||||||
|     @Override |     @Override | ||||||
|     public Boolean isVmSnapshotEnabled(HypervisorType hypervisorType, String hypervisorVersion) { |     public Boolean isVmSnapshotEnabled(HypervisorType hypervisorType, String hypervisorVersion) { | ||||||
|         HypervisorCapabilitiesVO result = getCapabilities(hypervisorType, hypervisorVersion); |         HypervisorCapabilitiesVO result = getCapabilities(hypervisorType, hypervisorVersion); | ||||||
|         return result.getVmSnapshotEnabled(); |         return result.isVmSnapshotEnabled(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
| @ -34,7 +34,6 @@ import java.util.stream.Collectors; | |||||||
| 
 | 
 | ||||||
| import javax.inject.Inject; | import javax.inject.Inject; | ||||||
| 
 | 
 | ||||||
| import com.cloud.server.ResourceIcon; |  | ||||||
| import org.apache.cloudstack.acl.ControlledEntity; | import org.apache.cloudstack.acl.ControlledEntity; | ||||||
| import org.apache.cloudstack.acl.ControlledEntity.ACLType; | import org.apache.cloudstack.acl.ControlledEntity.ACLType; | ||||||
| import org.apache.cloudstack.affinity.AffinityGroup; | import org.apache.cloudstack.affinity.AffinityGroup; | ||||||
| @ -304,6 +303,7 @@ import com.cloud.projects.ProjectAccount; | |||||||
| import com.cloud.projects.ProjectInvitation; | import com.cloud.projects.ProjectInvitation; | ||||||
| import com.cloud.region.ha.GlobalLoadBalancerRule; | import com.cloud.region.ha.GlobalLoadBalancerRule; | ||||||
| import com.cloud.resource.RollingMaintenanceManager; | import com.cloud.resource.RollingMaintenanceManager; | ||||||
|  | import com.cloud.server.ResourceIcon; | ||||||
| import com.cloud.server.ResourceTag; | import com.cloud.server.ResourceTag; | ||||||
| import com.cloud.server.ResourceTag.ResourceObjectType; | import com.cloud.server.ResourceTag.ResourceObjectType; | ||||||
| import com.cloud.service.ServiceOfferingVO; | import com.cloud.service.ServiceOfferingVO; | ||||||
| @ -2614,6 +2614,7 @@ public class ApiResponseHelper implements ResponseGenerator { | |||||||
|         hpvCapabilitiesResponse.setMaxDataVolumesLimit(hpvCapabilities.getMaxDataVolumesLimit()); |         hpvCapabilitiesResponse.setMaxDataVolumesLimit(hpvCapabilities.getMaxDataVolumesLimit()); | ||||||
|         hpvCapabilitiesResponse.setMaxHostsPerCluster(hpvCapabilities.getMaxHostsPerCluster()); |         hpvCapabilitiesResponse.setMaxHostsPerCluster(hpvCapabilities.getMaxHostsPerCluster()); | ||||||
|         hpvCapabilitiesResponse.setIsStorageMotionSupported(hpvCapabilities.isStorageMotionSupported()); |         hpvCapabilitiesResponse.setIsStorageMotionSupported(hpvCapabilities.isStorageMotionSupported()); | ||||||
|  |         hpvCapabilitiesResponse.setVmSnapshotEnabled(hpvCapabilities.isVmSnapshotEnabled()); | ||||||
|         return hpvCapabilitiesResponse; |         return hpvCapabilitiesResponse; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -35,8 +35,6 @@ import java.util.concurrent.Executors; | |||||||
| import java.util.concurrent.ScheduledExecutorService; | import java.util.concurrent.ScheduledExecutorService; | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
| import java.util.function.Predicate; | import java.util.function.Predicate; | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
| 
 | 
 | ||||||
| import javax.crypto.Mac; | import javax.crypto.Mac; | ||||||
| @ -44,8 +42,6 @@ import javax.crypto.spec.SecretKeySpec; | |||||||
| import javax.inject.Inject; | import javax.inject.Inject; | ||||||
| import javax.naming.ConfigurationException; | import javax.naming.ConfigurationException; | ||||||
| 
 | 
 | ||||||
| import com.cloud.dc.DomainVlanMapVO; |  | ||||||
| import com.cloud.dc.dao.DomainVlanMapDao; |  | ||||||
| import org.apache.cloudstack.acl.ControlledEntity; | import org.apache.cloudstack.acl.ControlledEntity; | ||||||
| import org.apache.cloudstack.affinity.AffinityGroupProcessor; | import org.apache.cloudstack.affinity.AffinityGroupProcessor; | ||||||
| import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; | import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; | ||||||
| @ -605,6 +601,7 @@ import com.cloud.consoleproxy.ConsoleProxyManager; | |||||||
| import com.cloud.dc.AccountVlanMapVO; | import com.cloud.dc.AccountVlanMapVO; | ||||||
| import com.cloud.dc.ClusterVO; | import com.cloud.dc.ClusterVO; | ||||||
| import com.cloud.dc.DataCenterVO; | import com.cloud.dc.DataCenterVO; | ||||||
|  | import com.cloud.dc.DomainVlanMapVO; | ||||||
| import com.cloud.dc.HostPodVO; | import com.cloud.dc.HostPodVO; | ||||||
| import com.cloud.dc.Pod; | import com.cloud.dc.Pod; | ||||||
| import com.cloud.dc.PodVlanMapVO; | import com.cloud.dc.PodVlanMapVO; | ||||||
| @ -614,6 +611,7 @@ import com.cloud.dc.VlanVO; | |||||||
| import com.cloud.dc.dao.AccountVlanMapDao; | import com.cloud.dc.dao.AccountVlanMapDao; | ||||||
| import com.cloud.dc.dao.ClusterDao; | import com.cloud.dc.dao.ClusterDao; | ||||||
| import com.cloud.dc.dao.DataCenterDao; | import com.cloud.dc.dao.DataCenterDao; | ||||||
|  | import com.cloud.dc.dao.DomainVlanMapDao; | ||||||
| import com.cloud.dc.dao.HostPodDao; | import com.cloud.dc.dao.HostPodDao; | ||||||
| import com.cloud.dc.dao.PodVlanMapDao; | import com.cloud.dc.dao.PodVlanMapDao; | ||||||
| import com.cloud.dc.dao.VlanDao; | import com.cloud.dc.dao.VlanDao; | ||||||
| @ -663,9 +661,9 @@ import com.cloud.network.dao.LoadBalancerDao; | |||||||
| import com.cloud.network.dao.LoadBalancerVO; | import com.cloud.network.dao.LoadBalancerVO; | ||||||
| import com.cloud.network.dao.NetworkAccountDao; | import com.cloud.network.dao.NetworkAccountDao; | ||||||
| import com.cloud.network.dao.NetworkAccountVO; | import com.cloud.network.dao.NetworkAccountVO; | ||||||
|  | import com.cloud.network.dao.NetworkDao; | ||||||
| import com.cloud.network.dao.NetworkDomainDao; | import com.cloud.network.dao.NetworkDomainDao; | ||||||
| import com.cloud.network.dao.NetworkDomainVO; | import com.cloud.network.dao.NetworkDomainVO; | ||||||
| import com.cloud.network.dao.NetworkDao; |  | ||||||
| import com.cloud.network.dao.NetworkVO; | import com.cloud.network.dao.NetworkVO; | ||||||
| import com.cloud.network.vpc.dao.VpcDao; | import com.cloud.network.vpc.dao.VpcDao; | ||||||
| import com.cloud.org.Cluster; | import com.cloud.org.Cluster; | ||||||
| @ -4459,7 +4457,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public HypervisorCapabilities updateHypervisorCapabilities(final Long id, final Long maxGuestsLimit, final Boolean securityGroupEnabled) { |     public HypervisorCapabilities updateHypervisorCapabilities(UpdateHypervisorCapabilitiesCmd cmd) { | ||||||
|  |         final Long id = cmd.getId(); | ||||||
|  |         final Boolean securityGroupEnabled = cmd.getSecurityGroupEnabled(); | ||||||
|  |         final Long maxGuestsLimit = cmd.getMaxGuestsLimit(); | ||||||
|  |         final Integer maxDataVolumesLimit = cmd.getMaxDataVolumesLimit(); | ||||||
|  |         final Boolean storageMotionSupported = cmd.getStorageMotionSupported(); | ||||||
|  |         final Integer maxHostsPerClusterLimit = cmd.getMaxHostsPerClusterLimit(); | ||||||
|  |         final Boolean vmSnapshotEnabled = cmd.getVmSnapshotEnabled(); | ||||||
|         HypervisorCapabilitiesVO hpvCapabilities = _hypervisorCapabilitiesDao.findById(id, true); |         HypervisorCapabilitiesVO hpvCapabilities = _hypervisorCapabilitiesDao.findById(id, true); | ||||||
| 
 | 
 | ||||||
|         if (hpvCapabilities == null) { |         if (hpvCapabilities == null) { | ||||||
| @ -4468,19 +4473,37 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe | |||||||
|             throw ex; |             throw ex; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         final boolean updateNeeded = maxGuestsLimit != null || securityGroupEnabled != null; |         final boolean updateNeeded = securityGroupEnabled != null || maxGuestsLimit != null || | ||||||
|  |                 maxDataVolumesLimit != null || storageMotionSupported != null || maxHostsPerClusterLimit != null || | ||||||
|  |                 vmSnapshotEnabled != null; | ||||||
|         if (!updateNeeded) { |         if (!updateNeeded) { | ||||||
|             return hpvCapabilities; |             return hpvCapabilities; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         hpvCapabilities = _hypervisorCapabilitiesDao.createForUpdate(id); |         hpvCapabilities = _hypervisorCapabilitiesDao.createForUpdate(id); | ||||||
| 
 | 
 | ||||||
|  |         if (securityGroupEnabled != null) { | ||||||
|  |             hpvCapabilities.setSecurityGroupEnabled(securityGroupEnabled); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if (maxGuestsLimit != null) { |         if (maxGuestsLimit != null) { | ||||||
|             hpvCapabilities.setMaxGuestsLimit(maxGuestsLimit); |             hpvCapabilities.setMaxGuestsLimit(maxGuestsLimit); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (securityGroupEnabled != null) { |         if (maxDataVolumesLimit != null) { | ||||||
|             hpvCapabilities.setSecurityGroupEnabled(securityGroupEnabled); |             hpvCapabilities.setMaxDataVolumesLimit(maxDataVolumesLimit); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (storageMotionSupported != null) { | ||||||
|  |             hpvCapabilities.setStorageMotionSupported(storageMotionSupported); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (maxHostsPerClusterLimit != null) { | ||||||
|  |             hpvCapabilities.setMaxHostsPerCluster(maxHostsPerClusterLimit); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (vmSnapshotEnabled != null) { | ||||||
|  |             hpvCapabilities.setVmSnapshotEnabled(vmSnapshotEnabled); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (_hypervisorCapabilitiesDao.update(id, hpvCapabilities)) { |         if (_hypervisorCapabilitiesDao.update(id, hpvCapabilities)) { | ||||||
|  | |||||||
							
								
								
									
										289
									
								
								test/integration/component/test_hypervisor_capabilities.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								test/integration/component/test_hypervisor_capabilities.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,289 @@ | |||||||
|  | # 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. | ||||||
|  | """ Test cases for Testing Hypervisor Capabilities | ||||||
|  | """ | ||||||
|  | from nose.plugins.attrib import attr | ||||||
|  | from marvin.cloudstackTestCase import cloudstackTestCase | ||||||
|  | from marvin.lib.utils import (cleanup_resources, | ||||||
|  |                               validateList) | ||||||
|  | from marvin.lib.base import (Account, | ||||||
|  |                              ServiceOffering, | ||||||
|  |                              DiskOffering, | ||||||
|  |                              VirtualMachine, | ||||||
|  |                              Volume, | ||||||
|  |                              Host, | ||||||
|  |                              VmSnapshot) | ||||||
|  | from marvin.lib.common import (get_domain, | ||||||
|  |                                get_zone, | ||||||
|  |                                get_template, | ||||||
|  |                                list_virtual_machines, | ||||||
|  |                                list_ssvms, | ||||||
|  |                                list_routers) | ||||||
|  | from marvin.lib.decoratorGenerators import skipTestIf | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | from marvin.cloudstackAPI import (updateHypervisorCapabilities, | ||||||
|  |                                   listHypervisorCapabilities) | ||||||
|  | 
 | ||||||
|  | from marvin.codes import PASS | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TestHypervisorCapabilities(cloudstackTestCase): | ||||||
|  | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def setUpClass(cls): | ||||||
|  |         testClient = super(TestHypervisorCapabilities, cls).getClsTestClient() | ||||||
|  |         cls.apiclient = testClient.getApiClient() | ||||||
|  |         cls.services = testClient.getParsedTestDataConfig() | ||||||
|  |         cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) | ||||||
|  |         cls.domain = get_domain(cls.apiclient) | ||||||
|  | 
 | ||||||
|  |         cls.hypervisor = cls.testClient.getHypervisorInfo() | ||||||
|  |         # Get Zone, Domain and templates | ||||||
|  | 
 | ||||||
|  |         cls.notSupported = True | ||||||
|  |         cls._cleanup = [] | ||||||
|  |         cls.hosts = Host.list(cls.apiclient, zoneid=cls.zone.id, type='Routing') | ||||||
|  |         if isinstance(cls.hosts, list) and len(cls.hosts) > 0: | ||||||
|  |             cls.host = cls.hosts[0] | ||||||
|  |             cls.notSupported = False | ||||||
|  | 
 | ||||||
|  |         cls.hypervisorversion = "default" | ||||||
|  |         if hasattr(cls.host, 'hypervisorversion'): | ||||||
|  |             cls.hypervisorversion = cls.host.hypervisorversion | ||||||
|  | 
 | ||||||
|  |         if cls.notSupported == False: | ||||||
|  |             cls.notSupported = True | ||||||
|  |             cmdList = listHypervisorCapabilities.listHypervisorCapabilitiesCmd() | ||||||
|  |             cmdList.hypervisor = cls.hypervisor | ||||||
|  |             capabilities = cls.apiclient.listHypervisorCapabilities(cmdList) | ||||||
|  |             for capability in capabilities: | ||||||
|  |                 if capability.hypervisorversion == cls.hypervisorversion: | ||||||
|  |                    cls.hostCapability = capability | ||||||
|  |                    cls.notSupported = False | ||||||
|  |                    break | ||||||
|  | 
 | ||||||
|  |             if cls.notSupported == True: | ||||||
|  |                 cls.hypervisorversion = "default" | ||||||
|  |                 for capability in capabilities: | ||||||
|  |                     if capability.hypervisorversion == cls.hypervisorversion: | ||||||
|  |                        cls.hostCapability = capability | ||||||
|  |                        cls.notSupported = False | ||||||
|  |                        break | ||||||
|  | 
 | ||||||
|  |         if cls.notSupported == False: | ||||||
|  |             cls.template = get_template( | ||||||
|  |                 cls.apiclient, | ||||||
|  |                 cls.zone.id, | ||||||
|  |                 cls.services["ostype"]) | ||||||
|  | 
 | ||||||
|  |             # Create an account | ||||||
|  |             cls.account = Account.create( | ||||||
|  |                 cls.apiclient, | ||||||
|  |                 cls.services["account"], | ||||||
|  |                 domainid=cls.domain.id | ||||||
|  |             ) | ||||||
|  |             cls._cleanup.append(cls.account) | ||||||
|  | 
 | ||||||
|  |             # Create user api client of the account | ||||||
|  |             cls.userapiclient = testClient.getUserApiClient( | ||||||
|  |                 UserName=cls.account.name, | ||||||
|  |                 DomainName=cls.account.domain | ||||||
|  |             ) | ||||||
|  |             # Create Service offering | ||||||
|  |             cls.service_offering = ServiceOffering.create( | ||||||
|  |                 cls.apiclient, | ||||||
|  |                 cls.services["service_offering"], | ||||||
|  |                 hosttags="host1" | ||||||
|  |             ) | ||||||
|  |             cls._cleanup.append(cls.service_offering) | ||||||
|  | 
 | ||||||
|  |             cls.disk_offering = DiskOffering.create( | ||||||
|  |                 cls.apiclient, | ||||||
|  |                 cls.services["disk_offering"] | ||||||
|  |             ) | ||||||
|  |             cls._cleanup.append(cls.disk_offering) | ||||||
|  | 
 | ||||||
|  |         return | ||||||
|  | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def tearDownClass(cls): | ||||||
|  |         super(TestHypervisorCapabilities, cls).tearDownClass() | ||||||
|  | 
 | ||||||
|  |     def setUp(self): | ||||||
|  |         self.cleanup = [] | ||||||
|  | 
 | ||||||
|  |         self.apiclient = self.testClient.getApiClient() | ||||||
|  |         self.dbclient = self.testClient.getDbConnection() | ||||||
|  | 
 | ||||||
|  |     def tearDown(self): | ||||||
|  |         try: | ||||||
|  |             if self.notSupported == False: | ||||||
|  |                 Host.update(self.apiclient, id=self.host.id, hosttags="") | ||||||
|  |                 self.updateHostHypervisorCapability(self.hostCapability.id, | ||||||
|  |                     self.hostCapability.maxdatavolumeslimit, | ||||||
|  |                     self.hostCapability.vmsnapshotenabled) | ||||||
|  | 
 | ||||||
|  |             super(TestHypervisorCapabilities, self).tearDown() | ||||||
|  |         except Exception as e: | ||||||
|  |             raise Exception("Warning: Exception during cleanup : %s" % e) | ||||||
|  |         return | ||||||
|  | 
 | ||||||
|  |     @skipTestIf("notSupported") | ||||||
|  |     @attr(tags=["advanced", "basic"], required_hardware="false") | ||||||
|  |     def test_01_check_hypervisor_max_data_volume_limit(self): | ||||||
|  |         """ Test hypervisor maxdatavolumeslimit effect | ||||||
|  | 
 | ||||||
|  |         # 1. Set maxdatavolumeslimit to 1 for hypervisor | ||||||
|  |         # 2. List capabilities and verify value | ||||||
|  |         # 3. Deploy a VM and attach a volume to it | ||||||
|  |         # 4. Try attach another volume, it should fail | ||||||
|  |         # 5. Set maxdatavolumeslimit to 32 for hypervisor | ||||||
|  |         # 6. Try attach second volume, it should succeed | ||||||
|  |         """ | ||||||
|  |         self.updateHostHypervisorCapability(self.hostCapability.id, 1) | ||||||
|  |         capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id) | ||||||
|  |         self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list") | ||||||
|  |         self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid") | ||||||
|  |         self.assertEqual(capabilities[0].maxdatavolumeslimit, | ||||||
|  |             1, | ||||||
|  |             "listHypervisorCapabilities response maxdatavolumeslimit value not 1") | ||||||
|  | 
 | ||||||
|  |         Host.update(self.apiclient, id=self.host.id, hosttags="host1") | ||||||
|  |         volume_created1 = Volume.create( | ||||||
|  |             self.userapiclient, | ||||||
|  |             self.services["volume"], | ||||||
|  |             zoneid=self.zone.id, | ||||||
|  |             diskofferingid=self.disk_offering.id | ||||||
|  |         ) | ||||||
|  |         self.cleanup.append(volume_created1) | ||||||
|  |         volume_created2 = Volume.create( | ||||||
|  |             self.userapiclient, | ||||||
|  |             self.services["volume"], | ||||||
|  |             zoneid=self.zone.id, | ||||||
|  |             diskofferingid=self.disk_offering.id | ||||||
|  |         ) | ||||||
|  |         self.cleanup.append(volume_created2) | ||||||
|  |         vm = VirtualMachine.create( | ||||||
|  |             self.userapiclient, | ||||||
|  |             self.services["small"], | ||||||
|  |             templateid=self.template.id, | ||||||
|  |             accountid=self.account.name, | ||||||
|  |             domainid=self.account.domainid, | ||||||
|  |             serviceofferingid=self.service_offering.id, | ||||||
|  |             zoneid=self.zone.id | ||||||
|  |         ) | ||||||
|  |         self.cleanup.append(vm) | ||||||
|  | 
 | ||||||
|  |         vm.attach_volume( | ||||||
|  |             self.userapiclient, | ||||||
|  |             volume_created1 | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         try: | ||||||
|  |             vm.attach_volume( | ||||||
|  |                 self.userapiclient, | ||||||
|  |                 volume_created2 | ||||||
|  |             ) | ||||||
|  |             vm.detach_volume(self.userapiclient, volume_created1) | ||||||
|  |             vm.detach_volume(self.userapiclient, volume_created2) | ||||||
|  |             self.fail("Successful to attach 2 DATA disks when max DATA disk limit was set to 1") | ||||||
|  |         except Exception as e: | ||||||
|  |             self.debug("Failed to attach 2nd DATA disk when max DATA disk limit was set to 1: %s" % e) | ||||||
|  | 
 | ||||||
|  |         self.updateHostHypervisorCapability(self.hostCapability.id, 32) | ||||||
|  | 
 | ||||||
|  |         vm.attach_volume( | ||||||
|  |             self.userapiclient, | ||||||
|  |             volume_created2 | ||||||
|  |         ) | ||||||
|  |         vm.stop(self.userapiclient, forced=True) | ||||||
|  |         vm.detach_volume(self.userapiclient, volume_created1) | ||||||
|  |         vm.detach_volume(self.userapiclient, volume_created2) | ||||||
|  | 
 | ||||||
|  |     @skipTestIf("notSupported") | ||||||
|  |     @attr(tags=["advanced", "basic"], required_hardware="false") | ||||||
|  |     def test_02_check_hypervisor_vm_snapshot(self): | ||||||
|  |         """ Test hypervisor vmsnapshotenabled effect | ||||||
|  | 
 | ||||||
|  |         # 1. Set vmsnapshotenabled to false for hypervisor | ||||||
|  |         # 2. List capabilities and verify value | ||||||
|  |         # 3. Deploy a VM | ||||||
|  |         # 4. Try VM snapshot, it should fail | ||||||
|  |         # 5. Set vmsnapshotenabled to true for hypervisor | ||||||
|  |         # 6. Try VM snapshot again, it should succeed | ||||||
|  |         """ | ||||||
|  |         if self.hypervisor == "KVM": | ||||||
|  |             self.skipTest("Skipping test: Reason -  VM Snapshot of running VM is not supported for KVM") | ||||||
|  |         self.updateHostHypervisorCapability(self.hostCapability.id, None, False) | ||||||
|  |         capabilities = self.listHostHypervisorCapabilities(self.hostCapability.id) | ||||||
|  |         self.assertTrue(isinstance(capabilities, list), "listHypervisorCapabilities response not a valid list") | ||||||
|  |         self.assertEqual(len(capabilities), 1, "listHypervisorCapabilities response not valid") | ||||||
|  |         self.assertEqual(capabilities[0].vmsnapshotenabled, | ||||||
|  |             False, | ||||||
|  |             "listHypervisorCapabilities response vmsnapshotenabled value not False") | ||||||
|  | 
 | ||||||
|  |         Host.update(self.apiclient, id=self.host.id, hosttags="host1") | ||||||
|  |         vm = VirtualMachine.create( | ||||||
|  |             self.userapiclient, | ||||||
|  |             self.services["small"], | ||||||
|  |             templateid=self.template.id, | ||||||
|  |             accountid=self.account.name, | ||||||
|  |             domainid=self.account.domainid, | ||||||
|  |             serviceofferingid=self.service_offering.id, | ||||||
|  |             zoneid=self.zone.id | ||||||
|  |         ) | ||||||
|  |         self.cleanup.append(vm) | ||||||
|  | 
 | ||||||
|  |         try: | ||||||
|  |             fail_snapshot = VmSnapshot.create( | ||||||
|  |                 self.userapiclient, | ||||||
|  |                 vmid=vm.id, | ||||||
|  |                 snapshotmemory="false", | ||||||
|  |                 name="Test Snapshot", | ||||||
|  |                 description="Test Snapshot Desc" | ||||||
|  |             ) | ||||||
|  |             self.cleanup.append(fail_snapshot) | ||||||
|  |             self.fail("Successful to take VM snapshot even when vmsnapshotenabled was set to False") | ||||||
|  |         except Exception as e: | ||||||
|  |             self.debug("Failed to take VM snapshot even vmsnapshotenabled was set to False: %s" % e) | ||||||
|  | 
 | ||||||
|  |         self.updateHostHypervisorCapability(self.hostCapability.id, None, True) | ||||||
|  | 
 | ||||||
|  |         vm_snapshot = VmSnapshot.create( | ||||||
|  |             self.userapiclient, | ||||||
|  |             vmid=vm.id, | ||||||
|  |             snapshotmemory="false", | ||||||
|  |             name="Test Snapshot", | ||||||
|  |             description="Test Snapshot Desc" | ||||||
|  |         ) | ||||||
|  |         self.cleanup.append(vm_snapshot) | ||||||
|  | 
 | ||||||
|  |     def updateHostHypervisorCapability(self, id, maxDataVolumes, vmSnapshotEnabled=None): | ||||||
|  |         cmd = updateHypervisorCapabilities.updateHypervisorCapabilitiesCmd() | ||||||
|  |         cmd.id = id | ||||||
|  |         if maxDataVolumes != None: | ||||||
|  |             cmd.maxdatavolumeslimit = maxDataVolumes | ||||||
|  |         if vmSnapshotEnabled != None: | ||||||
|  |             cmd.vmsnapshotenabled = vmSnapshotEnabled | ||||||
|  |         self.apiclient.updateHypervisorCapabilities(cmd) | ||||||
|  | 
 | ||||||
|  |     def listHostHypervisorCapabilities(self, id, hypervisor=None): | ||||||
|  |         cmd = listHypervisorCapabilities.listHypervisorCapabilitiesCmd() | ||||||
|  |         cmd.id = id | ||||||
|  |         return self.apiclient.listHypervisorCapabilities(cmd) | ||||||
|  | 
 | ||||||
| @ -5097,6 +5097,11 @@ class VmSnapshot: | |||||||
|         cmd.vmsnapshotid = vmsnapshotid |         cmd.vmsnapshotid = vmsnapshotid | ||||||
|         return apiclient.deleteVMSnapshot(cmd) |         return apiclient.deleteVMSnapshot(cmd) | ||||||
| 
 | 
 | ||||||
|  |     def delete(self, apiclient): | ||||||
|  |         cmd = deleteVMSnapshot.deleteVMSnapshotCmd() | ||||||
|  |         cmd.vmsnapshotid = self.id | ||||||
|  |         return apiclient.deleteVMSnapshot(cmd) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class Region: | class Region: | ||||||
|     """ Regions related Api """ |     """ Regions related Api """ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user