Skip to content

Commit eb5c8a5

Browse files
authored
server: correctly list suitable hosts for migration with uefi capability (#7024)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent 89d4c75 commit eb5c8a5

File tree

4 files changed

+197
-45
lines changed

4 files changed

+197
-45
lines changed

engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDao.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.host.dao;
1818

19+
import java.util.List;
1920
import java.util.Map;
2021

2122
import com.cloud.host.DetailVO;
@@ -29,4 +30,6 @@ public interface HostDetailsDao extends GenericDao<DetailVO, Long> {
2930
DetailVO findDetail(long hostId, String name);
3031

3132
void deleteDetails(long hostId);
33+
34+
List<DetailVO> findByName(String name);
3235
}

engine/schema/src/main/java/com/cloud/host/dao/HostDetailsDaoImpl.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.util.List;
2323
import java.util.Map;
2424

25-
2625
import org.springframework.stereotype.Component;
2726

2827
import com.cloud.host.DetailVO;
@@ -37,6 +36,7 @@
3736
public class HostDetailsDaoImpl extends GenericDaoBase<DetailVO, Long> implements HostDetailsDao {
3837
protected final SearchBuilder<DetailVO> HostSearch;
3938
protected final SearchBuilder<DetailVO> DetailSearch;
39+
protected final SearchBuilder<DetailVO> DetailNameSearch;
4040

4141
public HostDetailsDaoImpl() {
4242
HostSearch = createSearchBuilder();
@@ -47,6 +47,10 @@ public HostDetailsDaoImpl() {
4747
DetailSearch.and("hostId", DetailSearch.entity().getHostId(), SearchCriteria.Op.EQ);
4848
DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ);
4949
DetailSearch.done();
50+
51+
DetailNameSearch = createSearchBuilder();
52+
DetailNameSearch.and("name", DetailNameSearch.entity().getName(), SearchCriteria.Op.EQ);
53+
DetailNameSearch.done();
5054
}
5155

5256
@Override
@@ -119,4 +123,11 @@ public void persist(long hostId, Map<String, String> details) {
119123
}
120124
txn.commit();
121125
}
126+
127+
@Override
128+
public List<DetailVO> findByName(String name) {
129+
SearchCriteria<DetailVO> sc = DetailNameSearch.create();
130+
sc.setParameters("name", name);
131+
return listBy(sc);
132+
}
122133
}

server/src/main/java/com/cloud/server/ManagementServerImpl.java

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,6 @@
4343
import javax.inject.Inject;
4444
import javax.naming.ConfigurationException;
4545

46-
import com.cloud.agent.api.Answer;
47-
import com.cloud.agent.api.Command;
48-
import com.cloud.agent.api.PatchSystemVmAnswer;
49-
import com.cloud.agent.api.PatchSystemVmCommand;
50-
import com.cloud.agent.api.routing.NetworkElementCommand;
51-
import com.cloud.agent.manager.Commands;
52-
import com.cloud.dc.DomainVlanMapVO;
53-
import com.cloud.dc.dao.DomainVlanMapDao;
54-
import com.cloud.exception.AgentUnavailableException;
55-
import com.cloud.network.Networks;
56-
import com.cloud.utils.db.UUIDManager;
57-
import com.cloud.utils.fsm.StateMachine2;
58-
import com.cloud.vm.DomainRouterVO;
59-
import com.cloud.vm.NicVO;
60-
import com.cloud.vm.dao.DomainRouterDao;
61-
import com.cloud.vm.dao.NicDao;
6246
import org.apache.cloudstack.acl.ControlledEntity;
6347
import org.apache.cloudstack.acl.SecurityChecker;
6448
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
@@ -611,8 +595,14 @@
611595
import org.apache.log4j.Logger;
612596

613597
import com.cloud.agent.AgentManager;
598+
import com.cloud.agent.api.Answer;
599+
import com.cloud.agent.api.Command;
614600
import com.cloud.agent.api.GetVncPortAnswer;
615601
import com.cloud.agent.api.GetVncPortCommand;
602+
import com.cloud.agent.api.PatchSystemVmAnswer;
603+
import com.cloud.agent.api.PatchSystemVmCommand;
604+
import com.cloud.agent.api.routing.NetworkElementCommand;
605+
import com.cloud.agent.manager.Commands;
616606
import com.cloud.agent.manager.allocator.HostAllocator;
617607
import com.cloud.alert.Alert;
618608
import com.cloud.alert.AlertManager;
@@ -633,6 +623,7 @@
633623
import com.cloud.dc.AccountVlanMapVO;
634624
import com.cloud.dc.ClusterVO;
635625
import com.cloud.dc.DataCenterVO;
626+
import com.cloud.dc.DomainVlanMapVO;
636627
import com.cloud.dc.HostPodVO;
637628
import com.cloud.dc.Pod;
638629
import com.cloud.dc.PodVlanMapVO;
@@ -642,6 +633,7 @@
642633
import com.cloud.dc.dao.AccountVlanMapDao;
643634
import com.cloud.dc.dao.ClusterDao;
644635
import com.cloud.dc.dao.DataCenterDao;
636+
import com.cloud.dc.dao.DomainVlanMapDao;
645637
import com.cloud.dc.dao.HostPodDao;
646638
import com.cloud.dc.dao.PodVlanMapDao;
647639
import com.cloud.dc.dao.VlanDao;
@@ -656,6 +648,7 @@
656648
import com.cloud.event.EventTypes;
657649
import com.cloud.event.EventVO;
658650
import com.cloud.event.dao.EventDao;
651+
import com.cloud.exception.AgentUnavailableException;
659652
import com.cloud.exception.ConcurrentOperationException;
660653
import com.cloud.exception.InsufficientAddressCapacityException;
661654
import com.cloud.exception.InvalidParameterValueException;
@@ -686,6 +679,7 @@
686679
import com.cloud.network.IpAddressManagerImpl;
687680
import com.cloud.network.Network;
688681
import com.cloud.network.NetworkModel;
682+
import com.cloud.network.Networks;
689683
import com.cloud.network.dao.IPAddressDao;
690684
import com.cloud.network.dao.IPAddressVO;
691685
import com.cloud.network.dao.LoadBalancerDao;
@@ -760,13 +754,17 @@
760754
import com.cloud.utils.db.Transaction;
761755
import com.cloud.utils.db.TransactionCallbackNoReturn;
762756
import com.cloud.utils.db.TransactionStatus;
757+
import com.cloud.utils.db.UUIDManager;
763758
import com.cloud.utils.exception.CloudRuntimeException;
759+
import com.cloud.utils.fsm.StateMachine2;
764760
import com.cloud.utils.net.MacAddress;
765761
import com.cloud.utils.net.NetUtils;
766762
import com.cloud.utils.ssh.SSHKeysHelper;
767763
import com.cloud.vm.ConsoleProxyVO;
768764
import com.cloud.vm.DiskProfile;
765+
import com.cloud.vm.DomainRouterVO;
769766
import com.cloud.vm.InstanceGroupVO;
767+
import com.cloud.vm.NicVO;
770768
import com.cloud.vm.SecondaryStorageVmVO;
771769
import com.cloud.vm.UserVmDetailVO;
772770
import com.cloud.vm.UserVmManager;
@@ -778,7 +776,9 @@
778776
import com.cloud.vm.VirtualMachineProfile;
779777
import com.cloud.vm.VirtualMachineProfileImpl;
780778
import com.cloud.vm.dao.ConsoleProxyDao;
779+
import com.cloud.vm.dao.DomainRouterDao;
781780
import com.cloud.vm.dao.InstanceGroupDao;
781+
import com.cloud.vm.dao.NicDao;
782782
import com.cloud.vm.dao.SecondaryStorageVmDao;
783783
import com.cloud.vm.dao.UserVmDao;
784784
import com.cloud.vm.dao.UserVmDetailsDao;
@@ -794,6 +794,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
794794
public static final ConfigKey<String> customCsIdentifier = new ConfigKey<String>("Advanced", String.class, "custom.cs.identifier", UUID.randomUUID().toString().split("-")[0].substring(4), "Custom identifier for the cloudstack installation", true, ConfigKey.Scope.Global);
795795
private static final VirtualMachine.Type []systemVmTypes = { VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.ConsoleProxy};
796796

797+
private static final List<HypervisorType> LIVE_MIGRATION_SUPPORTING_HYPERVISORS = List.of(HypervisorType.Hyperv, HypervisorType.KVM,
798+
HypervisorType.LXC, HypervisorType.Ovm, HypervisorType.Ovm3, HypervisorType.Simulator, HypervisorType.VMware, HypervisorType.XenServer);
799+
797800
@Inject
798801
public AccountManager _accountMgr;
799802
@Inject
@@ -807,7 +810,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
807810
@Inject
808811
private ClusterDao _clusterDao;
809812
@Inject
810-
private UserVmDetailsDao _UserVmDetailsDao;
813+
protected UserVmDetailsDao _UserVmDetailsDao;
811814
@Inject
812815
private SecondaryStorageVmDao _secStorageVmDao;
813816
@Inject
@@ -823,7 +826,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
823826
@Inject
824827
private HostDao _hostDao;
825828
@Inject
826-
private HostDetailsDao _detailsDao;
829+
protected HostDetailsDao _detailsDao;
827830
@Inject
828831
private UserDao _userDao;
829832
@Inject
@@ -1277,6 +1280,26 @@ public Pair<List<? extends Host>, Integer> searchForServers(final ListHostsCmd c
12771280
return new Pair<List<? extends Host>, Integer>(result.first(), result.second());
12781281
}
12791282

1283+
protected Pair<Boolean, List<HostVO>> filterUefiHostsForMigration(List<HostVO> allHosts, List<HostVO> filteredHosts, VMInstanceVO vm) {
1284+
UserVmDetailVO userVmDetailVO = _UserVmDetailsDao.findDetail(vm.getId(), ApiConstants.BootType.UEFI.toString());
1285+
if (userVmDetailVO != null &&
1286+
(ApiConstants.BootMode.LEGACY.toString().equalsIgnoreCase(userVmDetailVO.getValue()) ||
1287+
ApiConstants.BootMode.SECURE.toString().equalsIgnoreCase(userVmDetailVO.getValue()))) {
1288+
s_logger.info(" Live Migration of UEFI enabled VM : " + vm.getInstanceName() + " is not supported");
1289+
if (CollectionUtils.isEmpty(filteredHosts)) {
1290+
filteredHosts = new ArrayList<>(allHosts);
1291+
}
1292+
List<DetailVO> details = _detailsDao.findByName(Host.HOST_UEFI_ENABLE);
1293+
List<Long> uefiEnabledHosts = details.stream().filter(x -> Boolean.TRUE.toString().equalsIgnoreCase(x.getValue())).map(DetailVO::getHostId).collect(Collectors.toList());
1294+
if (CollectionUtils.isEmpty(uefiEnabledHosts)) {
1295+
return new Pair<>(false, null);
1296+
}
1297+
filteredHosts.removeIf(host -> !uefiEnabledHosts.contains(host.getId()));
1298+
return new Pair<>(!filteredHosts.isEmpty(), filteredHosts);
1299+
}
1300+
return new Pair<>(true, filteredHosts);
1301+
}
1302+
12801303
@Override
12811304
public Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>> listHostsForMigrationOfVM(final Long vmId, final Long startIndex, final Long pageSize,
12821305
final String keyword) {
@@ -1303,33 +1326,21 @@ public Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Ho
13031326
throw ex;
13041327
}
13051328

1306-
UserVmDetailVO userVmDetailVO = _UserVmDetailsDao.findDetail(vm.getId(), ApiConstants.BootType.UEFI.toString());
1307-
if (userVmDetailVO != null) {
1308-
s_logger.info(" Live Migration of UEFI enabled VM : " + vm.getInstanceName() + " is not supported");
1309-
if ("legacy".equalsIgnoreCase(userVmDetailVO.getValue()) || "secure".equalsIgnoreCase(userVmDetailVO.getValue())) {
1310-
// Return empty list.
1311-
return new Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>>(new Pair<List<? extends Host>,
1312-
Integer>(new ArrayList<HostVO>(), new Integer(0)), new ArrayList<Host>(), new HashMap<Host, Boolean>());
1313-
}
1314-
}
1315-
13161329
if (_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
13171330
s_logger.info(" Live Migration of GPU enabled VM : " + vm.getInstanceName() + " is not supported");
13181331
// Return empty list.
1319-
return new Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>>(new Pair<List<? extends Host>, Integer>(new ArrayList<HostVO>(), new Integer(0)),
1320-
new ArrayList<Host>(), new HashMap<Host, Boolean>());
1332+
return new Ternary<>(new Pair<>(new ArrayList<HostVO>(), new Integer(0)),
1333+
new ArrayList<>(), new HashMap<>());
13211334
}
13221335

1323-
if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && !vm.getHypervisorType().equals(HypervisorType.VMware) && !vm.getHypervisorType().equals(HypervisorType.KVM)
1324-
&& !vm.getHypervisorType().equals(HypervisorType.Ovm) && !vm.getHypervisorType().equals(HypervisorType.Hyperv) && !vm.getHypervisorType().equals(HypervisorType.LXC)
1325-
&& !vm.getHypervisorType().equals(HypervisorType.Simulator) && !vm.getHypervisorType().equals(HypervisorType.Ovm3)) {
1336+
if (!LIVE_MIGRATION_SUPPORTING_HYPERVISORS.contains(vm.getHypervisorType())) {
13261337
if (s_logger.isDebugEnabled()) {
13271338
s_logger.debug(vm + " is not XenServer/VMware/KVM/Ovm/Hyperv/Ovm3, cannot migrate this VM.");
13281339
}
13291340
throw new InvalidParameterValueException("Unsupported Hypervisor Type for VM migration, we support " + "XenServer/VMware/KVM/Ovm/Hyperv/Ovm3 only");
13301341
}
13311342

1332-
if (vm.getType().equals(VirtualMachine.Type.User) && vm.getHypervisorType().equals(HypervisorType.LXC)) {
1343+
if (VirtualMachine.Type.User.equals(vm.getType()) && HypervisorType.LXC.equals(vm.getHypervisorType())) {
13331344
throw new InvalidParameterValueException("Unsupported Hypervisor Type for User VM migration, we support XenServer/VMware/KVM/Ovm/Hyperv/Ovm3 only");
13341345
}
13351346

@@ -1376,21 +1387,21 @@ public Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Ho
13761387
final Type hostType = srcHost.getType();
13771388
Pair<List<HostVO>, Integer> allHostsPair = null;
13781389
List<HostVO> allHosts = null;
1379-
List<HostVO> hostsForMigrationWithStorage = null;
1380-
final Map<Host, Boolean> requiresStorageMotion = new HashMap<Host, Boolean>();
1390+
List<HostVO> filteredHosts = null;
1391+
final Map<Host, Boolean> requiresStorageMotion = new HashMap<>();
13811392
DataCenterDeployment plan = null;
13821393
if (canMigrateWithStorage) {
13831394
Long podId = !VirtualMachine.Type.User.equals(vm.getType()) ? srcHost.getPodId() : null;
13841395
allHostsPair = searchForServers(startIndex, pageSize, null, hostType, null, srcHost.getDataCenterId(), podId, null, null, keyword,
13851396
null, null, srcHost.getHypervisorType(), null, srcHost.getId());
13861397
allHosts = allHostsPair.first();
1387-
hostsForMigrationWithStorage = new ArrayList<>(allHosts);
1398+
filteredHosts = new ArrayList<>(allHosts);
13881399

13891400
for (final VolumeVO volume : volumes) {
13901401
StoragePool storagePool = _poolDao.findById(volume.getPoolId());
13911402
Long volClusterId = storagePool.getClusterId();
13921403

1393-
for (Iterator<HostVO> iterator = hostsForMigrationWithStorage.iterator(); iterator.hasNext();) {
1404+
for (Iterator<HostVO> iterator = filteredHosts.iterator(); iterator.hasNext();) {
13941405
final Host host = iterator.next();
13951406
String hostVersion = host.getHypervisorVersion();
13961407
if (HypervisorType.KVM.equals(host.getHypervisorType()) && hostVersion == null) {
@@ -1434,6 +1445,9 @@ public Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Ho
14341445
}
14351446
}
14361447

1448+
if (CollectionUtils.isEmpty(filteredHosts)) {
1449+
return new Ternary<>(new Pair<>(allHosts, allHostsPair.second()), new ArrayList<>(), new HashMap<>());
1450+
}
14371451
plan = new DataCenterDeployment(srcHost.getDataCenterId(), podId, null, null, null, null);
14381452
} else {
14391453
final Long cluster = srcHost.getClusterId();
@@ -1446,8 +1460,14 @@ public Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Ho
14461460
plan = new DataCenterDeployment(srcHost.getDataCenterId(), srcHost.getPodId(), srcHost.getClusterId(), null, null, null);
14471461
}
14481462

1449-
final Pair<List<? extends Host>, Integer> otherHosts = new Pair<List<? extends Host>, Integer>(allHosts, allHostsPair.second());
1450-
List<Host> suitableHosts = new ArrayList<Host>();
1463+
final Pair<List<? extends Host>, Integer> otherHosts = new Pair<>(allHosts, allHostsPair.second());
1464+
Pair<Boolean, List<HostVO>> uefiFilteredResult = filterUefiHostsForMigration(allHosts, filteredHosts, vm);
1465+
if (!uefiFilteredResult.first()) {
1466+
return new Ternary<>(otherHosts, new ArrayList<>(), new HashMap<>());
1467+
}
1468+
filteredHosts = uefiFilteredResult.second();
1469+
1470+
List<Host> suitableHosts = new ArrayList<>();
14511471
final ExcludeList excludes = new ExcludeList();
14521472
excludes.addHost(srcHostId);
14531473

@@ -1470,8 +1490,8 @@ public Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Ho
14701490
}
14711491

14721492
for (final HostAllocator allocator : hostAllocators) {
1473-
if (canMigrateWithStorage) {
1474-
suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, hostsForMigrationWithStorage, HostAllocator.RETURN_UPTO_ALL, false);
1493+
if (CollectionUtils.isNotEmpty(filteredHosts)) {
1494+
suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, filteredHosts, HostAllocator.RETURN_UPTO_ALL, false);
14751495
} else {
14761496
suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, HostAllocator.RETURN_UPTO_ALL, false);
14771497
}
@@ -1489,7 +1509,7 @@ public Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Ho
14891509
}
14901510
}
14911511

1492-
return new Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>>(otherHosts, suitableHosts, requiresStorageMotion);
1512+
return new Ternary<>(otherHosts, suitableHosts, requiresStorageMotion);
14931513
}
14941514

14951515
/**

0 commit comments

Comments
 (0)