package org.ovirt.engine.core.bll.storage.repoimage; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.ovirt.engine.core.bll.CommandBase; import org.ovirt.engine.core.bll.LockMessage; import org.ovirt.engine.core.bll.LockMessagesMatchUtil; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.provider.ProviderProxyFactory; import org.ovirt.engine.core.bll.provider.storage.OpenStackImageProviderProxy; import org.ovirt.engine.core.bll.storage.disk.image.ImagesHandler; import org.ovirt.engine.core.bll.utils.PermissionSubject; import org.ovirt.engine.core.bll.validator.storage.DiskImagesValidator; import org.ovirt.engine.core.bll.validator.storage.DiskValidator; import org.ovirt.engine.core.bll.validator.storage.StorageDomainValidator; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.ExportRepoImageParameters; import org.ovirt.engine.core.common.action.LockProperties; import org.ovirt.engine.core.common.action.LockProperties.Scope; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.asynctasks.AsyncTaskType; import org.ovirt.engine.core.common.asynctasks.EntityInfo; import org.ovirt.engine.core.common.businessentities.ActionGroup; import org.ovirt.engine.core.common.businessentities.HttpLocationInfo; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.storage.Disk; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; import org.ovirt.engine.core.common.businessentities.storage.DiskStorageType; import org.ovirt.engine.core.common.businessentities.storage.ImageStatus; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.locks.LockingGroup; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.common.vdscommands.UploadImageVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.DiskDao; import org.ovirt.engine.core.dao.StorageDomainDao; import org.ovirt.engine.core.dao.VmDao; @SuppressWarnings("unused") public class ExportRepoImageCommand<T extends ExportRepoImageParameters> extends CommandBase<T> { @Inject private DiskDao diskDao; @Inject private StorageDomainDao storageDomainDao; @Inject private VmDao vmDao; private DiskImage diskImage; private OpenStackImageProviderProxy providerProxy; public ExportRepoImageCommand(T parameters, CommandContext cmdContext) { super(parameters, cmdContext); getParameters().setCommandType(getActionType()); } @Override protected LockProperties applyLockProperties(LockProperties lockProperties) { return lockProperties.withScope(Scope.Execution); } protected ProviderProxyFactory getProviderProxyFactory() { return ProviderProxyFactory.getInstance(); } protected OpenStackImageProviderProxy getProviderProxy() { if (providerProxy == null) { providerProxy = OpenStackImageProviderProxy .getFromStorageDomainId(getParameters().getDestinationDomainId()); } return providerProxy; } @Override protected Map<String, Pair<String, String>> getExclusiveLocks() { DiskImage diskImage = getDiskImage(); if (diskImage == null) { return null; } return Collections.singletonMap(diskImage.getId().toString(), LockMessagesMatchUtil.makeLockingPair(LockingGroup.DISK, new LockMessage(EngineMessage.ACTION_TYPE_FAILED_DISK_IS_BEING_EXPORTED) .withOptional("DiskAlias", getDiskImage() != null ? getDiskImage().getDiskAlias() : null))); } @Override protected AsyncTaskType getTaskType() { return AsyncTaskType.copyImage; } protected void acquireImageDbLock() { getDiskImage().setImageStatus(ImageStatus.LOCKED); ImagesHandler.updateImageStatus(getDiskImage().getImageId(), getDiskImage().getImageStatus()); } protected void releaseImageDbLock() { getDiskImage().setImageStatus(ImageStatus.OK); ImagesHandler.updateImageStatus(getDiskImage().getImageId(), getDiskImage().getImageStatus()); } @Override protected void executeCommand() { DiskImage diskImage = getDiskImage(); OpenStackImageProviderProxy proxy = getProviderProxy(); acquireImageDbLock(); String newImageId = proxy.createImageFromDiskImage(diskImage); getParameters().setParentCommand(VdcActionType.ExportRepoImage); Guid taskId = persistAsyncTaskPlaceHolder(getParameters().getParentCommand()); getParameters().setEntityInfo(new EntityInfo(VdcObjectType.Disk, getParameters().getImageGroupID())); VDSReturnValue vdsReturnValue = runVdsCommand(VDSCommandType.UploadImage, new UploadImageVDSCommandParameters( getStorageDomain().getStoragePoolId(), getStorageDomain().getId(), diskImage.getId(), diskImage.getImageId(), new HttpLocationInfo( getProviderProxy().getImageUrl(newImageId), getProviderProxy().getUploadHeaders() ) )); if (vdsReturnValue.getSucceeded()) { getReturnValue().getVdsmTaskIdList().add( createTask(taskId, vdsReturnValue.getCreationInfo(), getParameters().getParentCommand(), VdcObjectType.Disk, getParameters().getImageGroupID(), getParameters().getDestinationDomainId())); } getReturnValue().setActionReturnValue(newImageId); setSucceeded(true); } @Override public void endSuccessfully() { super.endSuccessfully(); releaseImageDbLock(); } @Override public void endWithFailure() { super.endWithFailure(); releaseImageDbLock(); } @Override public List<PermissionSubject> getPermissionCheckSubjects() { List<PermissionSubject> permissionSubjects = new ArrayList<>(); DiskImage diskImage = getDiskImage(); if (diskImage != null) { permissionSubjects.add(new PermissionSubject(diskImage.getId(), VdcObjectType.Disk, ActionGroup.ATTACH_DISK)); } permissionSubjects.add(new PermissionSubject(getParameters().getDestinationDomainId(), VdcObjectType.Storage, ActionGroup.CREATE_DISK)); return permissionSubjects; } @Override protected void setActionMessageParameters() { addValidationMessage(EngineMessage.VAR__ACTION__EXPORT); addValidationMessage(EngineMessage.VAR__TYPE__DISK); } @Override public Map<String, String> getJobMessageProperties() { if (jobProperties == null) { jobProperties = super.getJobMessageProperties(); jobProperties.put("diskalias", getDiskImage() != null ? getDiskImage().getDiskAlias() : ""); jobProperties.put("storage", getStorageDomain() != null ? getStorageDomain().getStorageName() : ""); } return jobProperties; } @Override public AuditLogType getAuditLogTypeValue() { switch (getActionState()) { case EXECUTE: return getSucceeded() ? AuditLogType.USER_EXPORT_IMAGE : AuditLogType.USER_EXPORT_IMAGE_FINISHED_FAILURE; case END_SUCCESS: return AuditLogType.USER_EXPORT_IMAGE_FINISHED_SUCCESS; case END_FAILURE: return AuditLogType.USER_EXPORT_IMAGE_FINISHED_FAILURE; } return AuditLogType.UNASSIGNED; } @Override public Guid getStorageDomainId() { return getDiskImage() != null ? getDiskImage().getStorageIds().get(0) : null; } @Override public Guid getStoragePoolId() { return getDiskImage() != null ? getDiskImage().getStoragePoolId() : null; } protected DiskImage getDiskImage() { if (diskImage == null) { Disk disk = diskDao.get(getParameters().getImageGroupID()); if (disk != null && disk.getDiskStorageType() == DiskStorageType.IMAGE) { diskImage = (DiskImage) disk; } } return diskImage; } private boolean validateDiskImage() { Disk disk = diskDao.get(getParameters().getImageGroupID()); if (disk != null && !validate(new DiskValidator(disk).validateUnsupportedDiskStorageType( DiskStorageType.LUN, DiskStorageType.CINDER)) ) { return false; } if (getDiskImage() == null) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_DISK_NOT_EXIST); } return true; } public String getRepoImageName() { return getDiskImage() != null ? getDiskImage().getDiskAlias() : ""; } public String getDestinationStorageDomainName() { return storageDomainDao.get(getParameters().getDestinationDomainId()).getName(); } @Override protected boolean validate() { if (!validateDiskImage()) { return false; } if (!validate(new StorageDomainValidator(getStorageDomain()).isDomainExistAndActive())) { return false; } // At the moment it's not possible to export images that have a snapshot // or that are based on a a template. if (!getDiskImage().getParentId().equals(Guid.Empty)) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_DISK_CONFIGURATION_NOT_SUPPORTED); } for (VM vm : vmDao.getVmsListForDisk(getDiskImage().getId(), false)) { if (vm.getStatus() != VMStatus.Down) { return failValidation(EngineMessage.ACTION_TYPE_FAILED_VM_IS_RUNNING); } } DiskImagesValidator diskImagesValidator = new DiskImagesValidator(getDiskImage()); if (!validate(diskImagesValidator.diskImagesNotIllegal()) || !validate(diskImagesValidator.diskImagesNotLocked())) { return false; } return true; } }