Daniel Erez has uploaded a new change for review. Change subject: core: introduce add Cinder disk support ......................................................................
core: introduce add Cinder disk support Adding support for creating a Cinder disk. Introduced AddCinderDiskCommand and AddCinderDiskCommandCallback. AddCinderDiskCommand is invoked from AddDiskCommand. Change-Id: Ie20f31afc59801e951b52053ba8bfef55e13e323 Bug-Url: https://bugzilla.redhat.com/1185826 Signed-off-by: Daniel Erez <de...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AddCinderDiskCommand.java A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AddCinderDiskCommandCallback.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java 5 files changed, 291 insertions(+), 7 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/24/39024/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java index 52ac334..2b6a6cc 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java @@ -6,6 +6,7 @@ import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.snapshots.SnapshotsValidator; +import org.ovirt.engine.core.bll.storage.CinderBroker; import org.ovirt.engine.core.bll.storage.IStorageHelper; import org.ovirt.engine.core.bll.storage.StorageHelperBase; import org.ovirt.engine.core.bll.storage.StorageHelperDirector; @@ -41,6 +42,8 @@ import org.ovirt.engine.core.dao.StoragePoolIsoMapDAO; public abstract class AbstractDiskVmCommand<T extends VmDiskOperationParameterBase> extends VmCommand<T> { + + private CinderBroker cinderBroker; public AbstractDiskVmCommand(T parameters) { this(parameters, null); @@ -307,4 +310,11 @@ getVm() != null && validate(new VmValidator(getVm()).vmNotLocked()); } + + public CinderBroker getCinderBroker() { + if (cinderBroker == null) { + cinderBroker = new CinderBroker(getStorageDomainId(), getReturnValue().getExecuteFailedMessages()); + } + return cinderBroker; + } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java index 1e0e567..e2a8da8 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AddDiskCommand.java @@ -1,9 +1,12 @@ package org.ovirt.engine.core.bll; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.bll.context.CommandContext; @@ -12,8 +15,10 @@ import org.ovirt.engine.core.bll.quota.QuotaStorageConsumptionParameter; import org.ovirt.engine.core.bll.quota.QuotaStorageDependent; import org.ovirt.engine.core.bll.storage.StorageDomainCommandBase; +import org.ovirt.engine.core.bll.tasks.CommandCoordinatorUtil; import org.ovirt.engine.core.bll.utils.PermissionSubject; import org.ovirt.engine.core.bll.utils.VmDeviceUtils; +import org.ovirt.engine.core.bll.validator.storage.CinderDisksValidator; import org.ovirt.engine.core.bll.validator.storage.DiskValidator; import org.ovirt.engine.core.bll.validator.storage.StorageDomainValidator; import org.ovirt.engine.core.bll.validator.storage.StoragePoolValidator; @@ -22,6 +27,7 @@ import org.ovirt.engine.core.common.action.AddDiskParameters; import org.ovirt.engine.core.common.action.AddImageFromScratchParameters; import org.ovirt.engine.core.common.action.HotPlugDiskToVmParameters; +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.asynctasks.EntityInfo; @@ -35,6 +41,7 @@ import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType; import org.ovirt.engine.core.common.businessentities.VmDeviceId; +import org.ovirt.engine.core.common.businessentities.storage.CinderDisk; import org.ovirt.engine.core.common.businessentities.storage.Disk; import org.ovirt.engine.core.common.businessentities.storage.DiskStorageType; import org.ovirt.engine.core.common.businessentities.storage.DiskImage; @@ -52,6 +59,7 @@ import org.ovirt.engine.core.common.validation.group.UpdateEntity; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.dao.DiskImageDynamicDAO; import org.ovirt.engine.core.dao.DiskLunMapDao; import org.ovirt.engine.core.dao.SnapshotDao; import org.ovirt.engine.core.utils.transaction.TransactionMethod; @@ -125,6 +133,14 @@ if (DiskStorageType.LUN == getParameters().getDiskInfo().getDiskStorageType()) { return checkIfLunDiskCanBeAdded(diskValidator); + } + + if (DiskStorageType.CINDER == getParameters().getDiskInfo().getDiskStorageType()) { + CinderDisk cinderDisk = (CinderDisk) getParameters().getDiskInfo(); + cinderDisk.setStorageIds(new ArrayList<>(Arrays.asList(getStorageDomainId()))); + StorageDomainValidator storageDomainValidator = createStorageDomainValidator(); + CinderDisksValidator cinderDisksValidator = new CinderDisksValidator(cinderDisk); + return validate(storageDomainValidator.isDomainExistAndActive()) && validate(cinderDisksValidator.validateCinderDiskLimits()); } return true; @@ -288,6 +304,10 @@ return DbFacade.getInstance().getDiskLunMapDao(); } + protected DiskImageDynamicDAO getDiskImageDynamicDao() { + return getDbFacade().getDiskImageDynamicDao(); + } + /** * @return The id of the storage domain where the first encountered VM image disk reside, if the vm doesn't have no * image disks then Guid.Empty will be returned. @@ -366,10 +386,16 @@ getParameters().getDiskInfo().setId(Guid.newGuid()); getParameters().setEntityInfo(new EntityInfo(VdcObjectType.Disk, getParameters().getDiskInfo().getId())); ImagesHandler.setDiskAlias(getParameters().getDiskInfo(), getVm()); - if (DiskStorageType.IMAGE == getParameters().getDiskInfo().getDiskStorageType()) { - createDiskBasedOnImage(); - } else { - createDiskBasedOnLun(); + switch (getParameters().getDiskInfo().getDiskStorageType()) { + case IMAGE: + createDiskBasedOnImage(); + break; + case LUN: + createDiskBasedOnLun(); + break; + case CINDER: + createDiskBasedOnCinder(); + break; } } @@ -398,7 +424,7 @@ setSucceeded(true); } - private boolean shouldDiskBePlugged() { + protected boolean shouldDiskBePlugged() { return getVm().getStatus() == VMStatus.Down && !Boolean.FALSE.equals(getParameters().getPlugDiskToVm()); } @@ -461,6 +487,31 @@ setSucceeded(tmpRetValue.getSucceeded()); } + private void createDiskBasedOnCinder() { + Future<VdcReturnValueBase> future = CommandCoordinatorUtil.executeAsyncCommand( + VdcActionType.AddCinderDisk, + buildAddCinderDiskParameters(), + cloneContextAndDetachFromParent()); + try { + setReturnValue(future.get()); + setSucceeded(getReturnValue().getSucceeded()); + } catch (InterruptedException | ExecutionException e) { + log.error("Error creating Cinder disk '{}': {}", + getParameters().getDiskInfo().getDiskAlias(), + e.getMessage()); + log.debug("Exception", e); + } + } + + private VdcActionParametersBase buildAddCinderDiskParameters() { + AddDiskParameters parameters = new AddDiskParameters(); + parameters.setDiskInfo(getParameters().getDiskInfo()); + parameters.setPlugDiskToVm(getParameters().getPlugDiskToVm()); + parameters.setVmId(getParameters().getVmId()); + parameters.setStorageDomainId(getParameters().getStorageDomainId()); + return parameters; + } + /** * If disk is not allow to have snapshot no VM snapshot Id should be updated. * @param parameters @@ -486,7 +537,8 @@ public AuditLogType getAuditLogTypeValue() { switch (getActionState()) { case EXECUTE: - if (getParameters().getDiskInfo().getDiskStorageType() == DiskStorageType.IMAGE) { + if (getParameters().getDiskInfo().getDiskStorageType() == DiskStorageType.IMAGE || + getParameters().getDiskInfo().getDiskStorageType() == DiskStorageType.CINDER) { return getExecuteAuditLogTypeValue(getSucceeded()); } else { return getEndSuccessAuditLogTypeValue(getSucceeded()); @@ -522,7 +574,7 @@ } } - private AuditLogType getEndSuccessAuditLogTypeValue(boolean successful) { + protected AuditLogType getEndSuccessAuditLogTypeValue(boolean successful) { boolean isVmNameExist = StringUtils.isNotEmpty(getVmName()); if (successful) { if (isVmNameExist) { diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AddCinderDiskCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AddCinderDiskCommand.java new file mode 100644 index 0000000..c08b718 --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AddCinderDiskCommand.java @@ -0,0 +1,146 @@ +package org.ovirt.engine.core.bll.storage; + +import org.ovirt.engine.core.bll.AddDiskCommand; +import org.ovirt.engine.core.bll.ImagesHandler; +import org.ovirt.engine.core.bll.InternalCommandAttribute; +import org.ovirt.engine.core.bll.context.CommandContext; +import org.ovirt.engine.core.bll.tasks.interfaces.CommandCallback; +import org.ovirt.engine.core.bll.utils.VmDeviceUtils; +import org.ovirt.engine.core.common.action.AddDiskParameters; +import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType; +import org.ovirt.engine.core.common.businessentities.VmDeviceId; +import org.ovirt.engine.core.common.businessentities.storage.CinderDisk; +import org.ovirt.engine.core.common.businessentities.storage.DiskImageDynamic; +import org.ovirt.engine.core.common.businessentities.storage.ImageStatus; +import org.ovirt.engine.core.common.businessentities.storage.ImageStorageDomainMap; +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.Pair; +import org.ovirt.engine.core.common.utils.VmDeviceType; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.utils.transaction.TransactionMethod; +import org.ovirt.engine.core.utils.transaction.TransactionSupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.Map; + +@InternalCommandAttribute +public class AddCinderDiskCommand<T extends AddDiskParameters> extends AddDiskCommand<T> { + + private static final Logger log = LoggerFactory.getLogger(AddCinderDiskCommand.class); + + public AddCinderDiskCommand(T parameters) { + super(parameters); + } + + public AddCinderDiskCommand(T parameters, CommandContext cmdContext) { + super(parameters, cmdContext); + } + + @Override + public void executeCommand() { + CinderDisk cinderDisk = createCinderDisk(); + String volumeId = getCinderBroker().createDisk(cinderDisk); + + cinderDisk.setId(Guid.createGuidFromString(volumeId)); + cinderDisk.setImageId(Guid.createGuidFromString(volumeId)); + addCinderDiskToDB(cinderDisk); + + getParameters().setDiskInfo(cinderDisk); + persistCommand(getParameters().getParentCommand(), true); + getReturnValue().setActionReturnValue(cinderDisk.getId()); + setSucceeded(true); + } + + protected void addCinderDiskToDB(final CinderDisk cinderDisk) { + TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() { + @Override + public Void runInTransaction() { + getBaseDiskDao().save(cinderDisk); + getImageDao().save(cinderDisk.getImage()); + getImageStorageDomainMapDao().save(new ImageStorageDomainMap(cinderDisk.getImageId(), + cinderDisk.getStorageIds().get(0), cinderDisk.getQuotaId(), cinderDisk.getDiskProfileId())); + + DiskImageDynamic diskDynamic = new DiskImageDynamic(); + diskDynamic.setId(cinderDisk.getImageId()); + getDiskImageDynamicDao().save(diskDynamic); + + if (getVm() != null) { + VmDeviceUtils.addManagedDevice(new VmDeviceId(cinderDisk.getId(), getVmId()), + VmDeviceGeneralType.DISK, + VmDeviceType.DISK, + null, + shouldDiskBePlugged(), + Boolean.TRUE.equals(cinderDisk.getReadOnly()), + null); + } + return null; + } + }); + } + + private CinderDisk createCinderDisk() { + final CinderDisk cinderDisk = new CinderDisk(); + cinderDisk.setDiskAlias(getDiskAlias()); + cinderDisk.setSize(getParameters().getDiskInfo().getSize()); + cinderDisk.setBoot(getParameters().getDiskInfo().isBoot()); + cinderDisk.setDiskInterface(getParameters().getDiskInfo().getDiskInterface()); + cinderDisk.setDiskAlias(getParameters().getDiskInfo().getDiskAlias()); + cinderDisk.setDiskDescription(getParameters().getDiskInfo().getDiskDescription()); + cinderDisk.setShareable(getParameters().getDiskInfo().isShareable()); + cinderDisk.setStorageIds(new ArrayList<>(Arrays.asList(getParameters().getStorageDomainId()))); + cinderDisk.setSize(getParameters().getDiskInfo().getSize()); + cinderDisk.setVolumeType(VolumeType.Unassigned); + cinderDisk.setvolumeFormat(VolumeFormat.RAW); + cinderDisk.setCreationDate(new Date()); + cinderDisk.setLastModified(new Date()); + cinderDisk.setActive(true); + cinderDisk.setImageStatus(ImageStatus.LOCKED); + cinderDisk.setVmSnapshotId(getParameters().getVmSnapshotId()); + cinderDisk.setCinderVolumeType(getParameters().getDiskInfo().getCinderVolumeType()); + return cinderDisk; + } + + @Override + protected void endSuccessfully() { + super.endSuccessfully(); + ImagesHandler.updateImageStatus(getDiskId(), ImageStatus.OK); + auditLogDirector.log(this, getEndSuccessAuditLogTypeValue(true)); + } + + @Override + protected void endWithFailure() { + super.endWithFailure(); + ImagesHandler.updateImageStatus(getDiskId(), ImageStatus.ILLEGAL); + auditLogDirector.log(this, getEndSuccessAuditLogTypeValue(false)); + } + + private Guid getDiskId() { + return getParameters().getDiskInfo().getId(); + } + + @Override + public boolean canDoAction() { + return true; + } + + @Override + public CommandCallback getCallback() { + return new AddCinderDiskCommandCallback(); + } + + @Override + protected Map<String, Pair<String, String>> getExclusiveLocks() { + return Collections.emptyMap(); + } + + @Override + protected Map<String, Pair<String, String>> getSharedLocks() { + return Collections.emptyMap(); + } +} diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AddCinderDiskCommandCallback.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AddCinderDiskCommandCallback.java new file mode 100644 index 0000000..844537d --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/storage/AddCinderDiskCommandCallback.java @@ -0,0 +1,73 @@ +package org.ovirt.engine.core.bll.storage; + +import org.ovirt.engine.core.bll.tasks.CommandCoordinatorUtil; +import org.ovirt.engine.core.common.action.AddDiskParameters; +import org.ovirt.engine.core.common.businessentities.storage.CinderDisk; +import org.ovirt.engine.core.common.businessentities.storage.DiskImage; +import org.ovirt.engine.core.common.businessentities.storage.ImageStatus; +import org.ovirt.engine.core.compat.CommandStatus; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.dao.DiskDao; + +import java.util.List; + +public class AddCinderDiskCommandCallback extends AbstractCinderDiskCommandCallback<AddCinderDiskCommand<AddDiskParameters>> { + + @Override + public void doPolling(Guid cmdId, List<Guid> childCmdIds) { + super.doPolling(cmdId, childCmdIds); + + ImageStatus imageStatus = getCinderBroker().getDiskStatus(getDiskId()); + DiskImage disk = getDisk(); + if (imageStatus != null && imageStatus != disk.getImageStatus()) { + switch (imageStatus) { + case OK: + getCommand().setCommandStatus(CommandStatus.SUCCEEDED); + break; + case ILLEGAL: + getCommand().setCommandStatus(CommandStatus.FAILED); + break; + } + } + } + + @Override + public void onFailed(Guid cmdId, List<Guid> childCmdIds) { + super.onFailed(cmdId, childCmdIds); + + log.error("Failed adding disk to Cinder. ID: {}", getDiskId()); + getCommand().endAction(); + CommandCoordinatorUtil.removeAllCommandsInHierarchy(cmdId); + } + + @Override + public void onSucceeded(Guid cmdId, List<Guid> childCmdIds) { + super.onSucceeded(cmdId, childCmdIds); + + log.error("Disk has been successfully added to Cinder. ID: {}", getDiskId()); + getCommand().endAction(); + CommandCoordinatorUtil.removeAllCommandsInHierarchy(cmdId); + } + + @Override + protected Guid getDiskId() { + return getCommand().getParameters().getDiskInfo().getId(); + } + + protected CinderDisk getDisk() { + if (disk == null) { + disk = (CinderDisk) getDiskDao().get(getDiskId()); + } + return disk; + } + + protected DiskDao getDiskDao() { + return DbFacade.getInstance().getDiskDao(); + } + + @Override + protected CinderBroker getCinderBroker() { + return getCommand().getCinderBroker(); + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java index c524d69..26796ef 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java @@ -424,6 +424,9 @@ UpdateMacPool(3101, ActionGroup.EDIT_MAC_POOL, false, QuotaDependency.NONE), RemoveMacPool(3102, ActionGroup.DELETE_MAC_POOL, false, QuotaDependency.NONE), + // Cinder + AddCinderDisk(3200, ActionGroup.CONFIGURE_VM_STORAGE, false, QuotaDependency.NONE), + // Host Devices RefreshHostDevices(4000, ActionGroup.MANIPULATE_HOST, false, QuotaDependency.NONE); -- To view, visit https://gerrit.ovirt.org/39024 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie20f31afc59801e951b52053ba8bfef55e13e323 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Daniel Erez <de...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches