Arik Hadas has uploaded a new change for review. Change subject: core: [WIP] ram snapshots related changes in bll project ......................................................................
core: [WIP] ram snapshots related changes in bll project Change-Id: Ifbb28efda1b63e506233a88399488a256e6ab1c8 Signed-off-by: Arik Hadas <[email protected]> --- M backend/manager/dbscripts/snapshots_sp.sql M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/snapshots/SnapshotsManager.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CreateAllSnapshotsFromVmParameters.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDao.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDaoDbFacadeImpl.java 6 files changed, 212 insertions(+), 32 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/91/14291/1 diff --git a/backend/manager/dbscripts/snapshots_sp.sql b/backend/manager/dbscripts/snapshots_sp.sql index 0392b17..6ea0304 100644 --- a/backend/manager/dbscripts/snapshots_sp.sql +++ b/backend/manager/dbscripts/snapshots_sp.sql @@ -154,6 +154,24 @@ LANGUAGE plpgsql; +Create or replace FUNCTION GetSnapshotByVmIdAndTypeAndStatus( + v_vm_id UUID, + v_snapshot_type VARCHAR(32), + v_status VARCHAR(32)) +RETURNS SETOF snapshots +AS $procedure$ +BEGIN + RETURN QUERY + SELECT * + FROM snapshots + WHERE vm_id = v_vm_id + AND snapshot_type = v_snapshot_type + AND status = v_status + ORDER BY creation_date ASC + LIMIT 1; +END; $procedure$ +LANGUAGE plpgsql; + diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java index 3a2893c..5e82346 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CreateAllSnapshotsFromVmCommand.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.ovirt.engine.core.bll.job.ExecutionHandler; import org.ovirt.engine.core.bll.quota.QuotaConsumptionParameter; @@ -14,10 +15,12 @@ import org.ovirt.engine.core.bll.snapshots.SnapshotsManager; import org.ovirt.engine.core.bll.snapshots.SnapshotsValidator; import org.ovirt.engine.core.bll.storage.StoragePoolValidator; +import org.ovirt.engine.core.bll.utils.ClusterUtils; import org.ovirt.engine.core.bll.validator.DiskImagesValidator; import org.ovirt.engine.core.bll.validator.MultipleStorageDomainsValidator; import org.ovirt.engine.core.bll.validator.VmValidator; import org.ovirt.engine.core.common.AuditLogType; +import org.ovirt.engine.core.common.FeatureSupported; import org.ovirt.engine.core.common.VdcObjectType; import org.ovirt.engine.core.common.action.CreateAllSnapshotsFromVmParameters; import org.ovirt.engine.core.common.action.ImagesActionsParametersBase; @@ -30,18 +33,25 @@ import org.ovirt.engine.core.common.businessentities.Snapshot; import org.ovirt.engine.core.common.businessentities.Snapshot.SnapshotStatus; import org.ovirt.engine.core.common.businessentities.Snapshot.SnapshotType; +import org.ovirt.engine.core.common.businessentities.StorageDomain; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmExitStatus; +import org.ovirt.engine.core.common.businessentities.VolumeFormat; +import org.ovirt.engine.core.common.businessentities.VolumeType; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.errors.VdcBLLException; +import org.ovirt.engine.core.common.errors.VdcBllErrors; import org.ovirt.engine.core.common.locks.LockingGroup; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.common.validation.group.CreateEntity; +import org.ovirt.engine.core.common.vdscommands.CreateImageVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.SnapshotVDSCommandParameters; 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.compat.NGuid; import org.ovirt.engine.core.compat.TransactionScopeOption; import org.ovirt.engine.core.dal.VdcBllMessages; import org.ovirt.engine.core.dal.dbbroker.DbFacade; @@ -105,8 +115,10 @@ setActionReturnValue(createdSnapshotId); - addSnapshotToDB(createdSnapshotId); + MemoryImageBuilder memoryImageBuilder = createMemoryImageBuilder(); + addSnapshotToDB(createdSnapshotId, memoryImageBuilder); createSnapshotsForDisks(newActiveSnapshotId); + memoryImageBuilder.build(); if (getTaskIdList().isEmpty()) { getParameters().setTaskGroupSuccess(true); @@ -115,23 +127,37 @@ setSucceeded(true); } - private Snapshot addSnapshotToDB(Guid snapshotId) { - if (getDisksList().isEmpty()) { - return new SnapshotsManager().addSnapshot(snapshotId, - getParameters().getDescription(), - SnapshotStatus.OK, - getParameters().getSnapshotType(), - getVm(), - true, - getCompensationContext()); + private Guid _storageDomainId = Guid.Empty; + + @Override + public NGuid getStorageDomainId() { + if (_storageDomainId.equals(Guid.Empty) && getVm() != null) { + long sizeNeeded = getVm().getImageSizeInBytes() / BYTES_IN_GB; + StorageDomain storageDomain = VmHandler.findStorageDomainForMemory(getVm().getStoragePoolId(), sizeNeeded); + if (storageDomain != null) { + _storageDomainId = storageDomain.getId(); + } } - else { - return new SnapshotsManager().addSnapshot(snapshotId, - getParameters().getDescription(), - getParameters().getSnapshotType(), - getVm(), - getCompensationContext()); - } + return _storageDomainId; + } + + private MemoryImageBuilder createMemoryImageBuilder() { + return FeatureSupported.memorySnapshot(ClusterUtils.getCompatilibilyVersion(getVm())) + && getParameters().isSaveMemory() ? + new DefaultMemoryImageBuilder() : + new NullableImageBuilder(); + } + + private Snapshot addSnapshotToDB(Guid snapshotId, MemoryImageBuilder memoryImageBuilder) { + boolean taskExists = !getDisksList().isEmpty() || !memoryImageBuilder.getVolumeStringRepresentation().isEmpty(); + return new SnapshotsManager().addSnapshot(snapshotId, + getParameters().getDescription(), + taskExists ? SnapshotStatus.LOCKED : SnapshotStatus.OK, + getParameters().getSnapshotType(), + getVm(), + true, + memoryImageBuilder.getVolumeStringRepresentation(), + getCompensationContext()); } private void createSnapshotsForDisks(Guid vmSnapshotId) { @@ -149,6 +175,17 @@ "CreateAllSnapshotsFromVmCommand::executeVmCommand: Failed to create snapshot!"); } } + } + + /** + * Returns whether to use Sparse or Preallocation. If the storage type is file system devices ,it would be more + * efficient to use Sparse allocation. Otherwise for block devices we should use Preallocated for faster allocation. + * + * @return - VolumeType of allocation type to use. + */ + private VolumeType getVolumeType() { + return (getStoragePool().getstorage_pool_type().isFileDomain()) ? VolumeType.Sparse + : VolumeType.Preallocated; } private ImagesActionsParametersBase buildCreateSnapshotParameters(DiskImage image, Guid snapshotId) { @@ -182,17 +219,16 @@ @Override public Void runInTransaction() { final boolean taskGroupSucceeded = getParameters().getTaskGroupSuccess(); - Guid createdSnapshotId = - getSnapshotDao().getId(getVmId(), getParameters().getSnapshotType(), SnapshotStatus.LOCKED); + Snapshot createdSnapshot = getSnapshotDao().get(getVmId(), getParameters().getSnapshotType(), SnapshotStatus.LOCKED); if (taskGroupSucceeded) { - getSnapshotDao().updateStatus(createdSnapshotId, SnapshotStatus.OK); + getSnapshotDao().updateStatus(createdSnapshot.getId(), SnapshotStatus.OK); - if (getParameters().getParentCommand() != VdcActionType.RunVm && getVm() != null && getVm().isRunning() - && getVm().getRunOnVds() != null) { - performLiveSnapshot(createdSnapshotId); + if (getParameters().getParentCommand() != VdcActionType.RunVm && getVm() != null + && getVm().isRunning() && getVm().getRunOnVds() != null) { + performLiveSnapshot(createdSnapshot); } } else { - revertToActiveSnapshot(createdSnapshotId); + revertToActiveSnapshot(createdSnapshot.getId()); } incrementVmGeneration(); @@ -244,22 +280,35 @@ * @param createdSnapshotId * Snapshot to revert to being active, in case of rollback. */ - protected void performLiveSnapshot(Guid createdSnapshotId) { + protected void performLiveSnapshot(final Snapshot snapshot) { try { TransactionSupport.executeInScope(TransactionScopeOption.Suppress, new TransactionMethod<Void>() { @Override public Void runInTransaction() { - List<Disk> pluggedDisks = getDiskDao().getAllForVm(getVm().getId(), true); - runVdsCommand(VDSCommandType.Snapshot, - new SnapshotVDSCommandParameters(getVm().getRunOnVds().getValue(), - getVm().getId(), - ImagesHandler.filterImageDisks(pluggedDisks, false, true))); + + runVdsCommand(VDSCommandType.Snapshot, buildLiveSnapshotParameters(snapshot)); + return null; } }); } catch (VdcBLLException e) { handleVdsLiveSnapshotFailure(e); + } + } + + private SnapshotVDSCommandParameters buildLiveSnapshotParameters(Snapshot snapshot) { + List<Disk> pluggedDisks = getDiskDao().getAllForVm(getVm().getId(), true); + if (FeatureSupported.memorySnapshot(ClusterUtils.getCompatilibilyVersion(getVm()))) { + return new SnapshotVDSCommandParameters(getVm().getRunOnVds().getValue(), + getVm().getId(), + ImagesHandler.filterImageDisks(pluggedDisks, false, true), + snapshot.getMemoryVolume()); + } + else { + return new SnapshotVDSCommandParameters(getVm().getRunOnVds().getValue(), + getVm().getId(), + ImagesHandler.filterImageDisks(pluggedDisks, false, true)); } } @@ -396,4 +445,77 @@ return list; } + + private interface MemoryImageBuilder { + void build(); + String getVolumeStringRepresentation(); + } + + private class DefaultMemoryImageBuilder implements MemoryImageBuilder { + private Guid storageDomainId; + private Guid storagePoolId; + private Guid imageGroupId; + private Guid volumeId; + + private DefaultMemoryImageBuilder() { + this.storageDomainId = getStorageDomainId().getValue(); + this.storagePoolId = getVm().getStoragePoolId(); + this.imageGroupId = Guid.NewGuid(); + this.volumeId = Guid.NewGuid(); + } + + @Override + public void build() { + VDSReturnValue retVal = + Backend + .getInstance() + .getResourceManager() + .RunVdsCommand( + VDSCommandType.CreateImage, + new CreateImageVDSCommandParameters( + storagePoolId, + storageDomainId, + imageGroupId, + getVm().getImageSizeInBytes(), + getVolumeType(), + VolumeFormat.RAW, + volumeId, + "", + getStoragePool().getcompatibility_version().toString())); + + if (retVal.getSucceeded()) { + Guid guid = + createTask(retVal.getCreationInfo(), + VdcActionType.CreateAllSnapshotsFromVm, + VdcObjectType.Storage, + getStorageDomainId().getValue()); + getTaskIdList().add(guid); + } + else { + throw new VdcBLLException(VdcBllErrors.VolumeCreationError, + "CreateAllSnapshotsFromVmCommand::executeVmCommand: Failed to create image for memory!"); + } + } + + @Override + public String getVolumeStringRepresentation() { + return String.format("%1$s,%2$s,%3$s,%4$s", + storageDomainId, + storagePoolId, + imageGroupId, + volumeId); + } + } + + private class NullableImageBuilder implements MemoryImageBuilder { + @Override + public void build() { + //no op + } + + @Override + public String getVolumeStringRepresentation() { + return StringUtils.EMPTY; + } + } } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/snapshots/SnapshotsManager.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/snapshots/SnapshotsManager.java index 66bbcc0..251b9da 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/snapshots/SnapshotsManager.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/snapshots/SnapshotsManager.java @@ -94,6 +94,7 @@ SnapshotType.ACTIVE, vm, false, + StringUtils.EMPTY, compensationContext); } @@ -119,7 +120,8 @@ SnapshotType snapshotType, VM vm, final CompensationContext compensationContext) { - return addSnapshot(snapshotId, description, SnapshotStatus.LOCKED, snapshotType, vm, true, compensationContext); + return addSnapshot(snapshotId, description, SnapshotStatus.LOCKED, + snapshotType, vm, true, StringUtils.EMPTY, compensationContext); } /** @@ -147,6 +149,7 @@ SnapshotType snapshotType, VM vm, boolean saveVmConfiguration, + String memoryVolume, final CompensationContext compensationContext) { final Snapshot snapshot = new Snapshot(snapshotId, snapshotStatus, @@ -156,7 +159,7 @@ description, new Date(), vm.getAppList(), - StringUtils.EMPTY); + memoryVolume); getSnapshotDao().save(snapshot); compensationContext.snapshotNewEntity(snapshot); diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CreateAllSnapshotsFromVmParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CreateAllSnapshotsFromVmParameters.java index f6cc9eb..47f348b 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CreateAllSnapshotsFromVmParameters.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CreateAllSnapshotsFromVmParameters.java @@ -27,6 +27,9 @@ /** Used to indicate the type of snapshot to take */ private SnapshotType snapshotType; + /** Used to indicate whether the memory should be saved as part of this snapshot or not */ + private boolean saveMemory = true; + public CreateAllSnapshotsFromVmParameters() { } @@ -59,6 +62,14 @@ this.snapshotType = snapshotType; } + public boolean isSaveMemory() { + return saveMemory; + } + + public void setSaveMemory(boolean saveMemory) { + this.saveMemory = saveMemory; + } + public boolean isNeedsLocking() { return needsLocking; } diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDao.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDao.java index 08d2d30..200a0cb 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDao.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDao.java @@ -61,6 +61,20 @@ */ Snapshot get(Guid vmId, SnapshotType type); + /** + * Return the <b>first</b> {@link Snapshot} that matches the given parameters.<br> + * <b>Note:</b> If more than one snapshot answers to the parameters, only the first will be returned (oldest by + * creation date). + * + * @param vmId + * The id of the VM to check for. + * @param type + * The type of snapshot. + * @param status + * The status of the snapshot. + * @return The snapshot, or <code>null</code> if it doesn't exist. + */ + Snapshot get(Guid vmId, SnapshotType type, SnapshotStatus status); /** * Return the {@link Snapshot} <b>first</b> id that matches the given parameters.<br> diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDaoDbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDaoDbFacadeImpl.java index 304635e..f3425c6 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDaoDbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/SnapshotDaoDbFacadeImpl.java @@ -86,6 +86,18 @@ } @Override + public Snapshot get(Guid vmId, SnapshotType type, SnapshotStatus status) { + MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() + .addValue("vm_id", vmId) + .addValue("snapshot_type", EnumUtils.nameOrNull(type)) + .addValue("status", EnumUtils.nameOrNull(status)); + + return getCallsHandler().executeRead("GetSnapshotByVmIdAndTypeAndStatus", + createEntityRowMapper(), + parameterSource); + } + + @Override public List<Snapshot> getAllWithConfiguration(Guid vmId) { return getAll(vmId, null, false, true); } -- To view, visit http://gerrit.ovirt.org/14291 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ifbb28efda1b63e506233a88399488a256e6ab1c8 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Arik Hadas <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
