package org.ovirt.engine.core.bll;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import javax.ejb.EJB;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.interfaces.BackendInternal;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.ImportVmParameters;
import org.ovirt.engine.core.common.action.RemoveVmParameters;
import org.ovirt.engine.core.common.action.StorageDomainManagementParameter;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.businessentities.Cluster;
import org.ovirt.engine.core.common.businessentities.MigrationSupport;
import org.ovirt.engine.core.common.businessentities.OriginType;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StorageDomainStatus;
import org.ovirt.engine.core.common.businessentities.StoragePool;
import org.ovirt.engine.core.common.businessentities.StoragePoolStatus;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
import org.ovirt.engine.core.common.businessentities.storage.ImageStatus;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.osinfo.OsRepository;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase;
import org.ovirt.engine.core.dao.ClusterDao;
import org.ovirt.engine.core.dao.StorageDomainDao;
import org.ovirt.engine.core.dao.StoragePoolDao;
import org.ovirt.engine.core.dao.VmStaticDao;
import org.ovirt.engine.core.dao.profiles.DiskProfileDao;
import org.ovirt.engine.core.vdsbroker.ResourceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Hosted Engine VM Importer.
* This class takes a VM and imports it, including its disks and nics.
* It is assumed that all devices are set on the VM (disks and nics).
* It is assumed that the disks exists already on the target storage domain.
* It will try to import the storage domain of the VM.
*/
public class HostedEngineImporter {
private static final Logger log = LoggerFactory.getLogger(HostedEngineImporter.class);
@EJB
private BackendInternal backend;
@Inject
private AuditLogDirector auditLogDirector;
@Inject
private DiskProfileDao diskProfileDao;
@Inject
private ClusterDao clusterDAO;
@Inject
private VmStaticDao vmStaticDAO;
@Inject
private StoragePoolDao storagePoolDao;
@Inject
private OsRepository osRepository;
@Inject
private StorageDomainDao storageDomainDao;
@Inject
private VmHandler vmHandler;
@Inject
private ResourceManager resourceManager;
/**
* Import the VM into ovirt engine by removing the old, un-managed VM
* and re-import it with its disks and nics.
*
* @param vm the VM to import
*/
public void doImport(VM vm) {
StoragePool storagePool = storagePoolDao.getForCluster(vm.getClusterId());
if (!Config.<Boolean>getValue(ConfigValues.AutoImportHostedEngine)) {
return;
}
VdcReturnValueBase heVmImported;
// get the special sd of hosted engine
Guid storageDomainId = vm.getImages().get(0).getStorageIds().get(0);
StorageDomain sd = getHEStorageDomain(vm, storagePool, storageDomainId);
// no point in trying this without the SD
if (sd != null
&& (sd.getStatus() == StorageDomainStatus.Active)
&& storagePool.getStatus() == StoragePoolStatus.Up) {
log.info("Try to import the Hosted Engine VM '{}'", vm);
if (vmStaticDAO.get(vm.getId()) == null || removedHEVM(vm)) {
heVmImported = importHEVM(vm, sd);
if (heVmImported.getSucceeded()) {
resourceManager.getVmManager(vm.getId()).update(vm.getStaticData());
log.info("Successfully imported the Hosted Engine VM");
auditLogDirector.log(new AuditLogableBase(), AuditLogType.HOSTED_ENGINE_VM_IMPORT_SUCCEEDED);
} else {
log.error("Failed importing the Hosted Engine VM");
auditLogDirector.log(new AuditLogableBase(), AuditLogType.HOSTED_ENGINE_VM_IMPORT_FAILED);
}
}
} else {
if (sd == null) {
log.debug("Skip trying to import the Hosted Engine VM. Storage Domain '{}' doesn't exist",
storageDomainId);
auditLogDirector.log(new AuditLogableBase(), AuditLogType.HOSTED_ENGINE_SD_NOT_EXIT);
} else {
log.debug("Skip trying to import the Hosted Engine VM. Storage Domain '{}' isn't ACTIVE", sd);
auditLogDirector.log(new AuditLogableBase(), AuditLogType.HOSTED_ENGINE_SD_NOT_ACTIVE);
}
}
}
private boolean removedHEVM(VM vm) {
RemoveVmParameters parameters = new RemoveVmParameters(vm.getId(), true);
parameters.setRemoveDisks(false);
return backend.runInternalAction(
VdcActionType.RemoveVm,
parameters).getSucceeded();
}
private VdcReturnValueBase importHEVM(VM vm, StorageDomain sd) {
return backend.runInternalAction(
VdcActionType.ImportVm,
createImportParams(vm, sd));
}
private ImportVmParameters createImportParams(VM vm, StorageDomain sd) {
ImportVmParameters parameters = new ImportVmParameters(
vm,
sd.getId(),
sd.getId(),
sd.getStoragePoolId(),
vm.getClusterId());
// assumption is that there's only 1 profile for hosted engine domain. its an unmanged domain.
Guid sdProfileId = diskProfileDao.getAllForStorageDomain(sd.getId()).get(0).getId();
for (DiskImage image : vm.getImages()) {
image.setDiskProfileId(sdProfileId);
image.setStorageIds(new ArrayList(Arrays.asList(sd.getId())));
image.setVmSnapshotId(Guid.newGuid());
image.setImageStatus(ImageStatus.OK);
}
// disks are there already(the vm is running)
parameters.setImagesExistOnTargetStorageDomain(true);
// distinguish from "regular" he vm.
vm.setOrigin(OriginType.MANAGED_HOSTED_ENGINE);
// architecture is a missing attribute from vdsm structure. relying on the cluster is perfectly reliable.
Cluster cluster = clusterDAO.get(vm.getClusterId());
vm.setClusterArch(cluster.getArchitecture());
vm.setVmCreationDate(new Date());
vm.setMigrationSupport(MigrationSupport.IMPLICITLY_NON_MIGRATABLE);
vm.setVmOs(osRepository.getLinuxOss().stream()
.sorted()
.findFirst().get());
vm.setPriority(1);
vmHandler.updateDefaultTimeZone(vm.getStaticData());
return parameters;
}
private StorageDomain getHEStorageDomain(VM vm, StoragePool storagePool, Guid storageDomainId) {
StorageDomain storageDomain = storageDomainDao.getForStoragePool(storageDomainId, storagePool.getId());
if(storageDomain != null){
return storageDomain;
}
StorageDomainManagementParameter importParams = new StorageDomainManagementParameter();
importParams.setStorageDomainId(storageDomainId);
importParams.setVdsId(vm.getRunOnVds());
return backend.runInternalAction(
VdcActionType.ImportHostedEngineStorageDomain,
importParams).getActionReturnValue();
}
}