diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDao.java index 7f1a6185e62..8dc4efa91f3 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDao.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDao.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.host.dao; +import java.util.List; import java.util.Map; import com.cloud.host.DetailVO; @@ -29,4 +30,6 @@ public interface HostDetailsDao extends GenericDao { DetailVO findDetail(long hostId, String name); void deleteDetails(long hostId); + + List findByName(String name); } diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDaoImpl.java index b864a592105..9c1340592f9 100644 --- a/engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDaoImpl.java @@ -22,7 +22,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import org.springframework.stereotype.Component; import com.cloud.host.DetailVO; @@ -37,6 +36,7 @@ import com.cloud.utils.exception.CloudRuntimeException; public class HostDetailsDaoImpl extends GenericDaoBase implements HostDetailsDao { protected final SearchBuilder HostSearch; protected final SearchBuilder DetailSearch; + protected final SearchBuilder DetailNameSearch; public HostDetailsDaoImpl() { HostSearch = createSearchBuilder(); @@ -47,6 +47,10 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement DetailSearch.and("hostId", DetailSearch.entity().getHostId(), SearchCriteria.Op.EQ); DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ); DetailSearch.done(); + + DetailNameSearch = createSearchBuilder(); + DetailNameSearch.and("name", DetailNameSearch.entity().getName(), SearchCriteria.Op.EQ); + DetailNameSearch.done(); } @Override @@ -119,4 +123,11 @@ public class HostDetailsDaoImpl extends GenericDaoBase implement } txn.commit(); } + + @Override + public List findByName(String name) { + SearchCriteria sc = DetailNameSearch.create(); + sc.setParameters("name", name); + return listBy(sc); + } } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index aa362b2dc63..5ba1195750b 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -45,28 +45,202 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.user.UserData; -import com.cloud.user.UserDataVO; -import com.cloud.user.dao.UserDataDao; +import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; +import com.cloud.agent.api.GetVncPortAnswer; +import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.PatchSystemVmAnswer; import com.cloud.agent.api.PatchSystemVmCommand; import com.cloud.agent.api.proxy.AllowConsoleAccessCommand; import com.cloud.agent.api.routing.NetworkElementCommand; import com.cloud.agent.manager.Commands; +import com.cloud.agent.manager.allocator.HostAllocator; +import com.cloud.alert.Alert; +import com.cloud.alert.AlertManager; +import com.cloud.alert.AlertVO; +import com.cloud.alert.dao.AlertDao; +import com.cloud.api.ApiDBUtils; +import com.cloud.api.query.dao.StoragePoolJoinDao; +import com.cloud.api.query.vo.StoragePoolJoinVO; +import com.cloud.capacity.Capacity; +import com.cloud.capacity.CapacityVO; +import com.cloud.capacity.dao.CapacityDao; +import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity; +import com.cloud.cluster.ClusterManager; +import com.cloud.configuration.Config; +import com.cloud.configuration.ConfigurationManagerImpl; +import com.cloud.consoleproxy.ConsoleProxyManagementState; +import com.cloud.consoleproxy.ConsoleProxyManager; +import com.cloud.dc.AccountVlanMapVO; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenterVO; import com.cloud.dc.DomainVlanMapVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.Pod; +import com.cloud.dc.PodVlanMapVO; +import com.cloud.dc.Vlan; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; +import com.cloud.dc.dao.AccountVlanMapDao; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DomainVlanMapDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.dc.dao.PodVlanMapDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeploymentPlanner; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.deploy.DeploymentPlanningManager; +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; +import com.cloud.event.ActionEvent; +import com.cloud.event.ActionEventUtils; +import com.cloud.event.EventTypes; +import com.cloud.event.EventVO; +import com.cloud.event.dao.EventDao; import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientAddressCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ManagementServerException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.VirtualMachineMigrationException; +import com.cloud.gpu.GPU; +import com.cloud.ha.HighAvailabilityManager; +import com.cloud.host.DetailVO; +import com.cloud.host.Host; +import com.cloud.host.Host.Type; +import com.cloud.host.HostTagVO; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.host.dao.HostDetailsDao; +import com.cloud.host.dao.HostTagsDao; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.HypervisorCapabilities; +import com.cloud.hypervisor.HypervisorCapabilitiesVO; +import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; +import com.cloud.hypervisor.kvm.dpdk.DpdkHelper; +import com.cloud.info.ConsoleProxyInfo; +import com.cloud.network.IpAddress; +import com.cloud.network.IpAddressManager; +import com.cloud.network.IpAddressManagerImpl; +import com.cloud.network.Network; +import com.cloud.network.NetworkModel; import com.cloud.network.Networks; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LoadBalancerDao; +import com.cloud.network.dao.LoadBalancerVO; +import com.cloud.network.dao.NetworkAccountDao; +import com.cloud.network.dao.NetworkAccountVO; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkDomainDao; +import com.cloud.network.dao.NetworkDomainVO; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.vpc.dao.VpcDao; +import com.cloud.org.Cluster; +import com.cloud.org.Grouping.AllocationState; +import com.cloud.projects.Project; +import com.cloud.projects.Project.ListProjectResourcesCriteria; +import com.cloud.projects.ProjectManager; +import com.cloud.resource.ResourceManager; +import com.cloud.server.ResourceTag.ResourceObjectType; +import com.cloud.server.auth.UserAuthenticator; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.service.dao.ServiceOfferingDetailsDao; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.GuestOS; +import com.cloud.storage.GuestOSCategoryVO; +import com.cloud.storage.GuestOSHypervisor; +import com.cloud.storage.GuestOSHypervisorVO; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.GuestOsCategory; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Storage; +import com.cloud.storage.StorageManager; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiServiceImpl; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.GuestOSCategoryDao; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.GuestOSHypervisorDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.secondary.SecondaryStorageVmManager; +import com.cloud.tags.ResourceTagVO; +import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.template.TemplateManager; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountService; +import com.cloud.user.SSHKeyPair; +import com.cloud.user.SSHKeyPairVO; +import com.cloud.user.User; +import com.cloud.user.UserData; +import com.cloud.user.UserDataVO; +import com.cloud.user.UserVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.SSHKeyPairDao; +import com.cloud.user.dao.UserDao; +import com.cloud.user.dao.UserDataDao; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; +import com.cloud.utils.PasswordGenerator; +import com.cloud.utils.Ternary; +import com.cloud.utils.component.ComponentLifecycle; +import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.concurrency.NamedThreadFactory; +import com.cloud.utils.crypt.DBEncryptionUtil; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.JoinBuilder.JoinType; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.TransactionCallbackNoReturn; +import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.db.UUIDManager; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.StateMachine2; +import com.cloud.utils.net.MacAddress; +import com.cloud.utils.net.NetUtils; +import com.cloud.utils.ssh.SSHKeysHelper; +import com.cloud.vm.ConsoleProxyVO; +import com.cloud.vm.DiskProfile; import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.InstanceGroupVO; import com.cloud.vm.NicVO; +import com.cloud.vm.SecondaryStorageVmVO; +import com.cloud.vm.UserVmDetailVO; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.VirtualMachineProfileImpl; +import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.InstanceGroupDao; import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.SecondaryStorageVmDao; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.UserVmDetailsDao; +import com.cloud.vm.dao.VMInstanceDao; + import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.affinity.AffinityGroupProcessor; @@ -626,179 +800,6 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.GetVncPortAnswer; -import com.cloud.agent.api.GetVncPortCommand; -import com.cloud.agent.manager.allocator.HostAllocator; -import com.cloud.alert.Alert; -import com.cloud.alert.AlertManager; -import com.cloud.alert.AlertVO; -import com.cloud.alert.dao.AlertDao; -import com.cloud.api.ApiDBUtils; -import com.cloud.api.query.dao.StoragePoolJoinDao; -import com.cloud.api.query.vo.StoragePoolJoinVO; -import com.cloud.capacity.Capacity; -import com.cloud.capacity.CapacityVO; -import com.cloud.capacity.dao.CapacityDao; -import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity; -import com.cloud.cluster.ClusterManager; -import com.cloud.configuration.Config; -import com.cloud.configuration.ConfigurationManagerImpl; -import com.cloud.consoleproxy.ConsoleProxyManagementState; -import com.cloud.consoleproxy.ConsoleProxyManager; -import com.cloud.dc.AccountVlanMapVO; -import com.cloud.dc.ClusterVO; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.HostPodVO; -import com.cloud.dc.Pod; -import com.cloud.dc.PodVlanMapVO; -import com.cloud.dc.Vlan; -import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; -import com.cloud.dc.dao.AccountVlanMapDao; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.HostPodDao; -import com.cloud.dc.dao.PodVlanMapDao; -import com.cloud.dc.dao.VlanDao; -import com.cloud.deploy.DataCenterDeployment; -import com.cloud.deploy.DeploymentPlanner; -import com.cloud.deploy.DeploymentPlanner.ExcludeList; -import com.cloud.deploy.DeploymentPlanningManager; -import com.cloud.domain.DomainVO; -import com.cloud.domain.dao.DomainDao; -import com.cloud.event.ActionEvent; -import com.cloud.event.ActionEventUtils; -import com.cloud.event.EventTypes; -import com.cloud.event.EventVO; -import com.cloud.event.dao.EventDao; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ManagementServerException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.exception.VirtualMachineMigrationException; -import com.cloud.gpu.GPU; -import com.cloud.ha.HighAvailabilityManager; -import com.cloud.host.DetailVO; -import com.cloud.host.Host; -import com.cloud.host.Host.Type; -import com.cloud.host.HostTagVO; -import com.cloud.host.HostVO; -import com.cloud.host.dao.HostDao; -import com.cloud.host.dao.HostDetailsDao; -import com.cloud.host.dao.HostTagsDao; -import com.cloud.hypervisor.Hypervisor; -import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.hypervisor.HypervisorCapabilities; -import com.cloud.hypervisor.HypervisorCapabilitiesVO; -import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; -import com.cloud.hypervisor.kvm.dpdk.DpdkHelper; -import com.cloud.info.ConsoleProxyInfo; -import com.cloud.network.IpAddress; -import com.cloud.network.IpAddressManager; -import com.cloud.network.IpAddressManagerImpl; -import com.cloud.network.Network; -import com.cloud.network.NetworkModel; -import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.network.dao.LoadBalancerDao; -import com.cloud.network.dao.LoadBalancerVO; -import com.cloud.network.dao.NetworkAccountDao; -import com.cloud.network.dao.NetworkAccountVO; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkDomainDao; -import com.cloud.network.dao.NetworkDomainVO; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.vpc.dao.VpcDao; -import com.cloud.org.Cluster; -import com.cloud.org.Grouping.AllocationState; -import com.cloud.projects.Project; -import com.cloud.projects.Project.ListProjectResourcesCriteria; -import com.cloud.projects.ProjectManager; -import com.cloud.resource.ResourceManager; -import com.cloud.server.ResourceTag.ResourceObjectType; -import com.cloud.server.auth.UserAuthenticator; -import com.cloud.service.ServiceOfferingVO; -import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.service.dao.ServiceOfferingDetailsDao; -import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.GuestOS; -import com.cloud.storage.GuestOSCategoryVO; -import com.cloud.storage.GuestOSHypervisor; -import com.cloud.storage.GuestOSHypervisorVO; -import com.cloud.storage.GuestOSVO; -import com.cloud.storage.GuestOsCategory; -import com.cloud.storage.ScopeType; -import com.cloud.storage.Storage; -import com.cloud.storage.StorageManager; -import com.cloud.storage.StoragePool; -import com.cloud.storage.StoragePoolStatus; -import com.cloud.storage.Volume; -import com.cloud.storage.VolumeApiServiceImpl; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.DiskOfferingDao; -import com.cloud.storage.dao.GuestOSCategoryDao; -import com.cloud.storage.dao.GuestOSDao; -import com.cloud.storage.dao.GuestOSHypervisorDao; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.secondary.SecondaryStorageVmManager; -import com.cloud.tags.ResourceTagVO; -import com.cloud.tags.dao.ResourceTagDao; -import com.cloud.template.TemplateManager; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.AccountService; -import com.cloud.user.SSHKeyPair; -import com.cloud.user.SSHKeyPairVO; -import com.cloud.user.User; -import com.cloud.user.UserVO; -import com.cloud.user.dao.AccountDao; -import com.cloud.user.dao.SSHKeyPairDao; -import com.cloud.user.dao.UserDao; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.Pair; -import com.cloud.utils.PasswordGenerator; -import com.cloud.utils.Ternary; -import com.cloud.utils.component.ComponentLifecycle; -import com.cloud.utils.component.ManagerBase; -import com.cloud.utils.concurrency.NamedThreadFactory; -import com.cloud.utils.crypt.DBEncryptionUtil; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Filter; -import com.cloud.utils.db.GlobalLock; -import com.cloud.utils.db.JoinBuilder; -import com.cloud.utils.db.JoinBuilder.JoinType; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.Transaction; -import com.cloud.utils.db.TransactionCallbackNoReturn; -import com.cloud.utils.db.TransactionStatus; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.net.MacAddress; -import com.cloud.utils.net.NetUtils; -import com.cloud.utils.ssh.SSHKeysHelper; -import com.cloud.vm.ConsoleProxyVO; -import com.cloud.vm.DiskProfile; -import com.cloud.vm.InstanceGroupVO; -import com.cloud.vm.SecondaryStorageVmVO; -import com.cloud.vm.UserVmDetailVO; -import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.VirtualMachineManager; -import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.VirtualMachineProfileImpl; -import com.cloud.vm.dao.ConsoleProxyDao; -import com.cloud.vm.dao.InstanceGroupDao; -import com.cloud.vm.dao.SecondaryStorageVmDao; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.UserVmDetailsDao; -import com.cloud.vm.dao.VMInstanceDao; import static com.cloud.configuration.ConfigurationManagerImpl.VM_USERDATA_MAX_LENGTH; import static com.cloud.vm.UserVmManager.MAX_USER_DATA_LENGTH_BYTES; @@ -816,6 +817,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private static final int MAX_HTTP_GET_LENGTH = 2 * MAX_USER_DATA_LENGTH_BYTES; private static final int NUM_OF_2K_BLOCKS = 512; private static final int MAX_HTTP_POST_LENGTH = NUM_OF_2K_BLOCKS * MAX_USER_DATA_LENGTH_BYTES; + private static final List LIVE_MIGRATION_SUPPORTING_HYPERVISORS = List.of(HypervisorType.Hyperv, HypervisorType.KVM, + HypervisorType.LXC, HypervisorType.Ovm, HypervisorType.Ovm3, HypervisorType.Simulator, HypervisorType.VMware, HypervisorType.XenServer); @Inject public AccountManager _accountMgr; @@ -830,7 +833,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject private ClusterDao _clusterDao; @Inject - private UserVmDetailsDao _UserVmDetailsDao; + protected UserVmDetailsDao _UserVmDetailsDao; @Inject private SecondaryStorageVmDao _secStorageVmDao; @Inject @@ -846,7 +849,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject private HostDao _hostDao; @Inject - private HostDetailsDao _detailsDao; + protected HostDetailsDao _detailsDao; @Inject private UserDao _userDao; @Inject @@ -1304,6 +1307,26 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return new Pair, Integer>(result.first(), result.second()); } + protected Pair> filterUefiHostsForMigration(List allHosts, List filteredHosts, VMInstanceVO vm) { + UserVmDetailVO userVmDetailVO = _UserVmDetailsDao.findDetail(vm.getId(), ApiConstants.BootType.UEFI.toString()); + if (userVmDetailVO != null && + (ApiConstants.BootMode.LEGACY.toString().equalsIgnoreCase(userVmDetailVO.getValue()) || + ApiConstants.BootMode.SECURE.toString().equalsIgnoreCase(userVmDetailVO.getValue()))) { + s_logger.info(" Live Migration of UEFI enabled VM : " + vm.getInstanceName() + " is not supported"); + if (CollectionUtils.isEmpty(filteredHosts)) { + filteredHosts = new ArrayList<>(allHosts); + } + List details = _detailsDao.findByName(Host.HOST_UEFI_ENABLE); + List uefiEnabledHosts = details.stream().filter(x -> Boolean.TRUE.toString().equalsIgnoreCase(x.getValue())).map(DetailVO::getHostId).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(uefiEnabledHosts)) { + return new Pair<>(false, null); + } + filteredHosts.removeIf(host -> !uefiEnabledHosts.contains(host.getId())); + return new Pair<>(!filteredHosts.isEmpty(), filteredHosts); + } + return new Pair<>(true, filteredHosts); + } + @Override public Ternary, Integer>, List, Map> listHostsForMigrationOfVM(final Long vmId, final Long startIndex, final Long pageSize, final String keyword) { @@ -1330,33 +1353,21 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe throw ex; } - UserVmDetailVO userVmDetailVO = _UserVmDetailsDao.findDetail(vm.getId(), ApiConstants.BootType.UEFI.toString()); - if (userVmDetailVO != null) { - s_logger.info(" Live Migration of UEFI enabled VM : " + vm.getInstanceName() + " is not supported"); - if ("legacy".equalsIgnoreCase(userVmDetailVO.getValue()) || "secure".equalsIgnoreCase(userVmDetailVO.getValue())) { - // Return empty list. - return new Ternary, Integer>, List, Map>(new Pair, - Integer>(new ArrayList(), new Integer(0)), new ArrayList(), new HashMap()); - } - } - if (_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) { s_logger.info(" Live Migration of GPU enabled VM : " + vm.getInstanceName() + " is not supported"); // Return empty list. - return new Ternary, Integer>, List, Map>(new Pair, Integer>(new ArrayList(), new Integer(0)), - new ArrayList(), new HashMap()); + return new Ternary<>(new Pair<>(new ArrayList(), new Integer(0)), + new ArrayList<>(), new HashMap<>()); } - if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && !vm.getHypervisorType().equals(HypervisorType.VMware) && !vm.getHypervisorType().equals(HypervisorType.KVM) - && !vm.getHypervisorType().equals(HypervisorType.Ovm) && !vm.getHypervisorType().equals(HypervisorType.Hyperv) && !vm.getHypervisorType().equals(HypervisorType.LXC) - && !vm.getHypervisorType().equals(HypervisorType.Simulator) && !vm.getHypervisorType().equals(HypervisorType.Ovm3)) { + if (!LIVE_MIGRATION_SUPPORTING_HYPERVISORS.contains(vm.getHypervisorType())) { if (s_logger.isDebugEnabled()) { s_logger.debug(vm + " is not XenServer/VMware/KVM/Ovm/Hyperv/Ovm3, cannot migrate this VM."); } throw new InvalidParameterValueException("Unsupported Hypervisor Type for VM migration, we support " + "XenServer/VMware/KVM/Ovm/Hyperv/Ovm3 only"); } - if (vm.getType().equals(VirtualMachine.Type.User) && vm.getHypervisorType().equals(HypervisorType.LXC)) { + if (VirtualMachine.Type.User.equals(vm.getType()) && HypervisorType.LXC.equals(vm.getHypervisorType())) { throw new InvalidParameterValueException("Unsupported Hypervisor Type for User VM migration, we support XenServer/VMware/KVM/Ovm/Hyperv/Ovm3 only"); } @@ -1403,21 +1414,21 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe final Type hostType = srcHost.getType(); Pair, Integer> allHostsPair = null; List allHosts = null; - List hostsForMigrationWithStorage = null; - final Map requiresStorageMotion = new HashMap(); + List filteredHosts = null; + final Map requiresStorageMotion = new HashMap<>(); DataCenterDeployment plan = null; if (canMigrateWithStorage) { Long podId = !VirtualMachine.Type.User.equals(vm.getType()) ? srcHost.getPodId() : null; allHostsPair = searchForServers(startIndex, pageSize, null, hostType, null, srcHost.getDataCenterId(), podId, null, null, keyword, null, null, srcHost.getHypervisorType(), null, srcHost.getId()); allHosts = allHostsPair.first(); - hostsForMigrationWithStorage = new ArrayList<>(allHosts); + filteredHosts = new ArrayList<>(allHosts); for (final VolumeVO volume : volumes) { StoragePool storagePool = _poolDao.findById(volume.getPoolId()); Long volClusterId = storagePool.getClusterId(); - for (Iterator iterator = hostsForMigrationWithStorage.iterator(); iterator.hasNext();) { + for (Iterator iterator = filteredHosts.iterator(); iterator.hasNext();) { final Host host = iterator.next(); String hostVersion = host.getHypervisorVersion(); if (HypervisorType.KVM.equals(host.getHypervisorType()) && hostVersion == null) { @@ -1461,6 +1472,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } } + if (CollectionUtils.isEmpty(filteredHosts)) { + return new Ternary<>(new Pair<>(allHosts, allHostsPair.second()), new ArrayList<>(), new HashMap<>()); + } plan = new DataCenterDeployment(srcHost.getDataCenterId(), podId, null, null, null, null); } else { final Long cluster = srcHost.getClusterId(); @@ -1473,8 +1487,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe plan = new DataCenterDeployment(srcHost.getDataCenterId(), srcHost.getPodId(), srcHost.getClusterId(), null, null, null); } - final Pair, Integer> otherHosts = new Pair, Integer>(allHosts, allHostsPair.second()); - List suitableHosts = new ArrayList(); + final Pair, Integer> otherHosts = new Pair<>(allHosts, allHostsPair.second()); + Pair> uefiFilteredResult = filterUefiHostsForMigration(allHosts, filteredHosts, vm); + if (!uefiFilteredResult.first()) { + return new Ternary<>(otherHosts, new ArrayList<>(), new HashMap<>()); + } + filteredHosts = uefiFilteredResult.second(); + + List suitableHosts = new ArrayList<>(); final ExcludeList excludes = new ExcludeList(); excludes.addHost(srcHostId); @@ -1497,8 +1517,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } for (final HostAllocator allocator : hostAllocators) { - if (canMigrateWithStorage) { - suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, hostsForMigrationWithStorage, HostAllocator.RETURN_UPTO_ALL, false); + if (CollectionUtils.isNotEmpty(filteredHosts)) { + suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, filteredHosts, HostAllocator.RETURN_UPTO_ALL, false); } else { suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, HostAllocator.RETURN_UPTO_ALL, false); } @@ -1519,7 +1539,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } } - return new Ternary, Integer>, List, Map>(otherHosts, suitableHosts, requiresStorageMotion); + return new Ternary<>(otherHosts, suitableHosts, requiresStorageMotion); } /** diff --git a/server/src/test/java/com/cloud/server/ManagementServerImplTest.java b/server/src/test/java/com/cloud/server/ManagementServerImplTest.java index 3c169cda55d..cf8df1ad372 100644 --- a/server/src/test/java/com/cloud/server/ManagementServerImplTest.java +++ b/server/src/test/java/com/cloud/server/ManagementServerImplTest.java @@ -22,20 +22,38 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.host.DetailVO; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDetailsDao; +import com.cloud.network.IpAddress; +import com.cloud.network.IpAddressManagerImpl; +import com.cloud.network.dao.IPAddressVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.user.Account; import com.cloud.user.AccountManager; +import com.cloud.user.SSHKeyPair; +import com.cloud.user.SSHKeyPairVO; import com.cloud.user.User; import com.cloud.user.UserData; import com.cloud.user.UserDataVO; +import com.cloud.user.dao.SSHKeyPairDao; import com.cloud.user.dao.UserDataDao; import com.cloud.utils.Pair; import com.cloud.utils.db.Filter; import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.UserVmDetailVO; import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.UserVmDao; + import org.apache.cloudstack.annotation.dao.AnnotationDao; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd; import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd; @@ -44,6 +62,7 @@ import org.apache.cloudstack.api.command.user.userdata.ListUserDataCmd; import org.apache.cloudstack.api.command.user.userdata.RegisterUserDataCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.ConfigKey; + import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -57,17 +76,7 @@ import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; - -import com.cloud.dc.Vlan.VlanType; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.IpAddress; -import com.cloud.network.IpAddressManagerImpl; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.user.Account; -import com.cloud.user.SSHKeyPair; -import com.cloud.user.SSHKeyPairVO; -import com.cloud.user.dao.SSHKeyPairDao; -import com.cloud.utils.db.SearchCriteria; +import org.springframework.test.util.ReflectionTestUtils; import java.util.ArrayList; import java.util.List; @@ -117,6 +126,12 @@ public class ManagementServerImplTest { ConfigKey mockConfig; + @Mock + UserVmDetailsDao userVmDetailsDao; + + @Mock + HostDetailsDao hostDetailsDao; + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -128,6 +143,8 @@ public class ManagementServerImplTest { spy.templateDao = _templateDao; spy._userVmDao = _userVmDao; spy.annotationDao = annotationDao; + spy._UserVmDetailsDao = userVmDetailsDao; + spy._detailsDao = hostDetailsDao; } @After @@ -536,4 +553,100 @@ public class ManagementServerImplTest { Assert.assertEquals(userdataResultList.first().get(0), userDataList.get(0)); } + private UserVmVO mockFilterUefiHostsTestVm(String uefiValue) { + UserVmVO vm = Mockito.mock(UserVmVO.class); + Mockito.when(vm.getId()).thenReturn(1L); + if (uefiValue == null) { + Mockito.when(userVmDetailsDao.findDetail(vm.getId(), ApiConstants.BootType.UEFI.toString())).thenReturn(null); + } else { + UserVmDetailVO detail = new UserVmDetailVO(vm.getId(), ApiConstants.BootType.UEFI.toString(), uefiValue, true); + Mockito.when(userVmDetailsDao.findDetail(vm.getId(), ApiConstants.BootType.UEFI.toString())).thenReturn(detail); + Mockito.when(hostDetailsDao.findByName(Host.HOST_UEFI_ENABLE)).thenReturn(new ArrayList<>(List.of(new DetailVO(1l, Host.HOST_UEFI_ENABLE, "true"), new DetailVO(2l, Host.HOST_UEFI_ENABLE, "false")))); + } + return vm; + } + + private List mockHostsList(Long filtered) { + List hosts = new ArrayList<>(); + HostVO h1 = new HostVO("guid-1"); + ReflectionTestUtils.setField(h1, "id", 1L); + hosts.add(h1); + HostVO h2 = new HostVO("guid-2"); + ReflectionTestUtils.setField(h2, "id", 2L); + hosts.add(h2); + HostVO h3 = new HostVO("guid-3"); + ReflectionTestUtils.setField(h3, "id", 3L); + hosts.add(h3); + if (filtered != null) { + hosts.removeIf(h -> h.getId() == filtered); + } + return hosts; + } + + @Test + public void testFilterUefiHostsForMigrationBiosVm() { + UserVmVO vm = mockFilterUefiHostsTestVm(null); + Pair> result = spy.filterUefiHostsForMigration(new ArrayList<>(), new ArrayList<>(), vm); + Assert.assertTrue(result.first()); + } + + @Test + public void testFilterUefiHostsForMigrationBiosVmFiltered() { + List filteredHosts = mockHostsList(2L); + UserVmVO vm = mockFilterUefiHostsTestVm(null); + Pair> result = spy.filterUefiHostsForMigration(new ArrayList<>(), filteredHosts, vm); + Assert.assertTrue(result.first()); + Assert.assertNotNull(result.second()); + Assert.assertEquals(2, result.second().size()); + } + + @Test + public void testFilterUefiHostsForMigrationUefiInvalidValueVm() { + UserVmVO vm = mockFilterUefiHostsTestVm(""); + Pair> result = spy.filterUefiHostsForMigration(new ArrayList<>(), new ArrayList<>(), vm); + Assert.assertTrue(result.first()); + } + + @Test + public void testFilterUefiHostsForMigrationUefiVMHostsUnavailable() { + UserVmVO vm = mockFilterUefiHostsTestVm(ApiConstants.BootMode.SECURE.toString()); + List filteredHosts = new ArrayList<>(); + Mockito.when(hostDetailsDao.findByName(Host.HOST_UEFI_ENABLE)).thenReturn(new ArrayList<>()); + Pair> result = spy.filterUefiHostsForMigration(mockHostsList(null), filteredHosts, vm); + Assert.assertFalse(result.first()); + } + + @Test + public void testFilterUefiHostsForMigrationUefiVMHostsAvailable() { + UserVmVO vm = mockFilterUefiHostsTestVm(ApiConstants.BootMode.LEGACY.toString()); + Pair> result = spy.filterUefiHostsForMigration(mockHostsList(null), null, vm); + Assert.assertTrue(result.first()); + Assert.assertNotNull(result.second()); + Assert.assertEquals(1, result.second().size()); + } + + @Test + public void testFilterUefiHostsForMigrationNoHostsAvailable() { + UserVmVO vm = mockFilterUefiHostsTestVm(ApiConstants.BootMode.SECURE.toString()); + Pair> result = spy.filterUefiHostsForMigration(new ArrayList<>(), null, vm); + Assert.assertFalse(result.first()); + } + + @Test + public void testFilterUefiHostsForMigrationUefiVMHostsAvailableFiltered() { + UserVmVO vm = mockFilterUefiHostsTestVm(ApiConstants.BootMode.LEGACY.toString()); + Pair> result = spy.filterUefiHostsForMigration(mockHostsList(null), mockHostsList(3L), vm); + Assert.assertTrue(result.first()); + Assert.assertNotNull(result.second()); + Assert.assertEquals(1, result.second().size()); + } + + @Test + public void testFilterUefiHostsForMigrationUefiVMNoHostsAvailableFiltered() { + UserVmVO vm = mockFilterUefiHostsTestVm(ApiConstants.BootMode.SECURE.toString()); + Pair> result = spy.filterUefiHostsForMigration(mockHostsList(null), mockHostsList(1L), vm); + Assert.assertFalse(result.first()); + Assert.assertNotNull(result.second()); + Assert.assertEquals(0, result.second().size()); + } }