package org.ovirt.engine.core.bll.hostedengine; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.PostConstruct; import javax.inject.Inject; import org.ovirt.engine.core.bll.VmHandler; import org.ovirt.engine.core.common.businessentities.HaMaintenanceMode; import org.ovirt.engine.core.common.businessentities.HostedEngineDeployConfiguration; import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.StorageDomainStatic; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VmStatic; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.interfaces.VDSBrokerFrontend; import org.ovirt.engine.core.common.vdscommands.SetHaMaintenanceModeVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.StorageDomainDao; import org.ovirt.engine.core.dao.VdsSpmIdMapDao; import org.ovirt.engine.core.dao.VmDao; import org.ovirt.engine.core.dao.VmStaticDao; import org.ovirt.engine.core.vdsbroker.ResourceManager; import org.ovirt.ovirt_host_deploy.constants.Const; import org.ovirt.ovirt_host_deploy.constants.HostedEngineEnv; public class HostedEngineHelper { private static final String HE_CONF_HOST_ID = "host_id"; private VM hostedEngineVm; private StorageDomainStatic storageDomainStatic; @Inject private VmDao vmDao; @Inject private VmStaticDao vmStaticDao; @Inject private VdsSpmIdMapDao vdsSpmIdMapDao; @Inject private StorageDomainDao storageDomainDao; @Inject private ResourceManager resourceManager; @Inject private HostedEngineConfigFetcher hostedEngineConfigFetcher; @Inject private VDSBrokerFrontend vdsBroker; @Inject private VmHandler vmHandler; @PostConstruct private void init() { List<VmStatic> byName = vmStaticDao.getAllByName(Config.getValue(ConfigValues.HostedEngineVmName)); if (byName != null && !byName.isEmpty()) { VmStatic vmStatic = byName.get(0); hostedEngineVm = vmDao.get(vmStatic.getId()); vmHandler.updateDisksFromDb(hostedEngineVm); } initHostedEngineStorageDomain(); } public Map<String, String> createVdsDeployParams(Guid vdsId, HostedEngineDeployConfiguration.Action deployAction) { if (hostedEngineVm == null) { return Collections.emptyMap(); } Map<String, String> params = new HashMap<>(); params.put(HostedEngineEnv.ACTION, fromDeployAction(deployAction)); if (HostedEngineDeployConfiguration.Action.DEPLOY == deployAction) { params.putAll(hostedEngineConfigFetcher.fetch()); // This installation method will generate the host id for this HE host. This MUST be // set in the configuration other wise the agent won't be able to register itself to // the whiteboard and become a part of the cluster. params.put(HE_CONF_HOST_ID, String.valueOf(offerHostId(vdsId))); } return params; } protected String fromDeployAction(HostedEngineDeployConfiguration.Action deployAction) { switch (deployAction) { case DEPLOY: return Const.HOSTED_ENGINE_ACTION_DEPLOY; case UNDEPLOY: return Const.HOSTED_ENGINE_ACTION_REMOVE; } return Const.HOSTED_ENGINE_ACTION_NONE; } public boolean isVmManaged() { return hostedEngineVm != null && hostedEngineVm.isManagedVm(); } /** * Offer the host id this data center allocated for this host in vds_spm_map. This effectively syncs * between the hosted engine HA identifier and vdsm's host ids that are used when locking storage domain for * monitoring. * * @return a numeric host id which identifies this host as part of hosted engine cluster */ private int offerHostId(Guid vdsId) { return vdsSpmIdMapDao.get(vdsId).getVdsSpmId(); } public StorageDomainStatic getStorageDomain() { return storageDomainStatic; } private void initHostedEngineStorageDomain(){ if(hostedEngineVm == null){ return; } List<DiskImage> diskList = hostedEngineVm.getDiskList(); if(diskList == null || diskList.isEmpty()){ return; } DiskImage disk = diskList.get(0); List<StorageDomain> allStorageDomainsByImageId = storageDomainDao.getAllStorageDomainsByImageId(disk.getImageId()); if(allStorageDomainsByImageId == null || allStorageDomainsByImageId.isEmpty()){ return; } StorageDomain storageDomain = allStorageDomainsByImageId.get(0); storageDomainStatic = storageDomain == null ? null : storageDomain.getStorageStaticData(); } /* * @return The Guid of the DC the engine VM is running under */ public Guid getStoragePoolId() { return hostedEngineVm.getStoragePoolId(); } /** * @return The Guid of Storage Domain of the engine VM */ public Guid getStorageDomainId() { return getStorageDomain().getId(); } /** * @return The Guid of the host running the engine VM */ public Guid getRunningHostId() { return hostedEngineVm.getRunOnVds(); } public boolean updateHaLocalMaintenanceMode(VDS vds, boolean localMaintenance){ SetHaMaintenanceModeVDSCommandParameters param = new SetHaMaintenanceModeVDSCommandParameters(vds, HaMaintenanceMode.LOCAL, localMaintenance); return vdsBroker.runVdsCommand(VDSCommandType.SetHaMaintenanceMode, param).getSucceeded(); } /** * Checks, if there are hosts in the cluster * capable to run HE VM. * * @param clusterVdses candidates to select from. * @param vdses Guids of VDSes to be excluded from the candidates list. * @return True if there are any hosts for HE VM, False otherwise */ public static boolean haveHostsAvailableforHE(Collection<VDS> clusterVdses, final Iterable<Guid> vdses) { // It is really hard to query Iterable // especially when you have old commons-collections // So let's convert it to the set. Set<Guid> vdsIds = new HashSet<>(); vdses.forEach(vdsIds::add); return clusterVdses.stream() .filter(v -> !vdsIds.contains(v.getId())) // Remove other hosts in batch .filter(VDS::getHighlyAvailableIsConfigured) // Remove non HE hosts .filter(VDS::getHighlyAvailableIsActive) // Remove non-active HE hosts .filter(v -> !v.getHighlyAvailableLocalMaintenance()) // Remove HE hosts under maintenance .filter(v -> v.getHighlyAvailableScore() > 0) // Remove HE hosts not suitable for the engine VM .findAny() .isPresent(); } }