package org.ovirt.engine.core.bll.storage.ovfstore; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import javax.inject.Inject; import org.ovirt.engine.core.bll.ConcurrentChildCommandsExecutionCallback; import org.ovirt.engine.core.bll.InternalCommandAttribute; import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.storage.domain.StorageDomainCommandBase; import org.ovirt.engine.core.bll.tasks.interfaces.CommandCallback; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.AddDiskParameters; import org.ovirt.engine.core.common.action.CreateOvfVolumeForStorageDomainCommandParameters; import org.ovirt.engine.core.common.action.VdcActionParametersBase; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.businessentities.StorageDomainOvfInfo; import org.ovirt.engine.core.common.businessentities.StorageDomainOvfInfoStatus; import org.ovirt.engine.core.common.businessentities.storage.DiskContentType; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.businessentities.storage.StorageType; import org.ovirt.engine.core.common.businessentities.storage.VolumeFormat; import org.ovirt.engine.core.common.businessentities.storage.VolumeType; import org.ovirt.engine.core.common.utils.SizeConverter; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dao.StorageDomainOvfInfoDao; import org.ovirt.engine.core.utils.ovf.OvfInfoFileConstants; @InternalCommandAttribute @NonTransactiveCommandAttribute public class CreateOvfVolumeForStorageDomainCommand<T extends CreateOvfVolumeForStorageDomainCommandParameters> extends StorageDomainCommandBase<T> { @Inject private AuditLogDirector auditLogDirector; @Inject private StorageDomainOvfInfoDao storageDomainOvfInfoDao; public CreateOvfVolumeForStorageDomainCommand(T parameters, CommandContext cmdContext) { super(parameters, cmdContext); setStorageDomainId(getParameters().getStorageDomainId()); setStoragePoolId(getParameters().getStoragePoolId()); } public CreateOvfVolumeForStorageDomainCommand(Guid commandId) { super(commandId); } @Override public CommandCallback getCallback() { return new ConcurrentChildCommandsExecutionCallback(); } @Override protected void executeCommand() { AddDiskParameters diskParameters = new AddDiskParameters(createDisk(getStorageDomainId())); diskParameters.setStorageDomainId(getStorageDomainId()); diskParameters.setParentCommand(getActionType()); diskParameters.setParentParameters(getParameters()); diskParameters.setShouldRemainIllegalOnFailedExecution(true); diskParameters.setSkipDomainCheck(getParameters().isSkipDomainChecks()); VdcReturnValueBase vdcReturnValueBase = runInternalActionWithTasksContext(VdcActionType.AddDisk, diskParameters); Guid createdId = vdcReturnValueBase.getActionReturnValue(); if (createdId != null) { setActionReturnValue(createdId); addStorageDomainOvfInfoToDb(createdId); } setSucceeded(vdcReturnValueBase.getSucceeded()); } private boolean shouldOvfStoreBeShareable() { // we don't create shareable disks on gluster domains to avoid // split brain - see BZ 1024654 return getStorageDomain().getStorageType() != StorageType.GLUSTERFS; } public DiskImage createDisk(Guid domainId) { DiskImage createdDiskImage = new DiskImage(); createdDiskImage.setContentType(DiskContentType.OVF_STORE); createdDiskImage.setWipeAfterDelete(false); createdDiskImage.setDiskAlias(OvfInfoFileConstants.OvfStoreDescriptionLabel); createdDiskImage.setDiskDescription(OvfInfoFileConstants.OvfStoreDescriptionLabel); createdDiskImage.setShareable(shouldOvfStoreBeShareable()); createdDiskImage.setStorageIds(new ArrayList<>(Collections.singletonList(domainId))); createdDiskImage.setSize(SizeConverter.BYTES_IN_MB * 128); createdDiskImage.setVolumeFormat(VolumeFormat.RAW); createdDiskImage.setVolumeType(VolumeType.Preallocated); createdDiskImage.setDescription("OVF store for domain " + domainId); Date creationDate = new Date(); createdDiskImage.setCreationDate(creationDate); createdDiskImage.setLastModified(creationDate); return createdDiskImage; } private void addStorageDomainOvfInfoToDb(Guid diskId) { StorageDomainOvfInfo storageDomainOvfInfo = new StorageDomainOvfInfo(getStorageDomainId(), null, diskId, StorageDomainOvfInfoStatus.DISABLED, null); storageDomainOvfInfoDao.save(storageDomainOvfInfo); } private void logFailure() { Guid createdDiskId = (Guid) getActionReturnValue(); if (createdDiskId != null) { addCustomValue("DiskId", createdDiskId.toString()); new AuditLogDirector().log(this, AuditLogType.CREATE_OVF_STORE_FOR_STORAGE_DOMAIN_FAILED); } else { new AuditLogDirector().log(this, AuditLogType.CREATE_OVF_STORE_FOR_STORAGE_DOMAIN_INITIATE_FAILED); } } private void endChildCommand(boolean succeeded) { if (!getParameters().getImagesParameters().isEmpty()) { VdcActionParametersBase childParams = getParameters().getImagesParameters().get(0); childParams.setTaskGroupSuccess(succeeded); getBackend().endAction(childParams.getCommandType(), childParams, getContext().clone().withoutCompensationContext().withoutExecutionContext().withoutLock()); } } @Override protected void endSuccessfully() { Guid createdDiskId = (Guid) getActionReturnValue(); endChildCommand(true); StorageDomainOvfInfo storageDomainOvfInfoDb = storageDomainOvfInfoDao.get(createdDiskId); if (storageDomainOvfInfoDb == null || storageDomainOvfInfoDb.getStatus() != StorageDomainOvfInfoStatus.DISABLED) { return; } storageDomainOvfInfoDb.setStatus(StorageDomainOvfInfoStatus.OUTDATED); storageDomainOvfInfoDao.update(storageDomainOvfInfoDb); setSucceeded(true); } @Override protected void endWithFailure() { endChildCommand(false); logFailure(); setSucceeded(true); } }