Tomas Jelinek has uploaded a new change for review. Change subject: engine,frontend: clone VM WIP ......................................................................
engine,frontend: clone VM WIP Just a WIP, do not review Change-Id: I2492f54834553e1dd06675b20342410152759f7f Signed-off-by: Tomas Jelinek <tjeli...@redhat.com> --- A backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CloneVmCommand.java A backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CloneVmParameters.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VdcActionType.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/job/StepEnum.java M frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java M frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java M frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java 7 files changed, 313 insertions(+), 1 deletion(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/81/23581/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CloneVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CloneVmCommand.java new file mode 100644 index 0000000..bdc353c --- /dev/null +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/CloneVmCommand.java @@ -0,0 +1,214 @@ +package org.ovirt.engine.core.bll; + +import org.ovirt.engine.core.bll.context.CommandContext; +import org.ovirt.engine.core.bll.job.ExecutionContext; +import org.ovirt.engine.core.bll.job.ExecutionHandler; +import org.ovirt.engine.core.bll.job.JobRepositoryFactory; +import org.ovirt.engine.core.bll.utils.PermissionSubject; +import org.ovirt.engine.core.common.VdcObjectType; +import org.ovirt.engine.core.common.action.AddVmFromSnapshotParameters; +import org.ovirt.engine.core.common.action.CloneVmParameters; +import org.ovirt.engine.core.common.action.CreateAllSnapshotsFromVmParameters; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.action.VdcReturnValueBase; +import org.ovirt.engine.core.common.businessentities.Snapshot; +import org.ovirt.engine.core.common.errors.VdcBLLException; +import org.ovirt.engine.core.common.errors.VdcBllErrors; +import org.ovirt.engine.core.common.errors.VdcBllMessages; +import org.ovirt.engine.core.common.job.Job; +import org.ovirt.engine.core.common.job.Step; +import org.ovirt.engine.core.common.job.StepEnum; +import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.dal.job.ExecutionMessageDirector; +import org.ovirt.engine.core.utils.RandomUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@NonTransactiveCommandAttribute +public class CloneVmCommand<T extends CloneVmParameters> extends CommandBase<T> { + + public static final String CLONE_SNAPSHOT_DESCRIPTION = "clone snapshot"; + + public CloneVmCommand(T parameters) { + super(parameters); + setVmId((parameters.getVmId().equals(Guid.Empty)) ? Guid.newGuid() : parameters.getVmId()); + parameters.getVm().setName(parameters.getNewName() + RandomUtils.instance().nextInt()); + setVmName(parameters.getVm().getName()); + } + + @Override + protected void executeCommand() { + if (getParameters().getNextAction() == null) { + makeSnapshot(); + } + } + + private void makeSnapshot() { + VdcReturnValueBase vdcReturnValue = getBackend().runInternalAction( + VdcActionType.CreateAllSnapshotsFromVm, + buildCreateSnapshotParameters(), + createSubstepContext(StepEnum.CREATING_SNAPSHOTS)); + + // setting lock to null in order not to release lock twice + setLock(null); + setSucceeded(vdcReturnValue.getSucceeded()); + + if (vdcReturnValue.getSucceeded()) { + List<Guid> internalVdsmTaskIdList = vdcReturnValue.getInternalVdsmTaskIdList(); + if (internalVdsmTaskIdList == null || internalVdsmTaskIdList.size() == 0) { + cloneVmFromSnapshot(); + } else { + getReturnValue().getVdsmTaskIdList().addAll(internalVdsmTaskIdList); + } + } else { + if (areDisksLocked(vdcReturnValue)) { + throw new VdcBLLException(VdcBllErrors.IRS_IMAGE_STATUS_ILLEGAL); + } + getReturnValue().setFault(vdcReturnValue.getFault()); + log.errorFormat("Failed to create stateless snapshot for VM {0} ({1})", + getVm().getName(), getVm().getId()); + } + } + + private void cloneVmFromSnapshot() { + VdcReturnValueBase vdcReturnValue = getBackend().runInternalAction( + VdcActionType.AddVmFromSnapshot, + creataAddVmFromSnapshotParameters(), + createContextForRunStatelessVm(StepEnum.CLONE_VM)); + + // setting lock to null in order not to release lock twice + setLock(null); + setSucceeded(vdcReturnValue.getSucceeded()); + + if (vdcReturnValue.getSucceeded()) { + List<Guid> internalVdsmTaskIdList = vdcReturnValue.getInternalVdsmTaskIdList(); + if (internalVdsmTaskIdList == null || internalVdsmTaskIdList.size() == 0) { + setSucceeded(true); + } else { + getReturnValue().getVdsmTaskIdList().addAll(internalVdsmTaskIdList); + } + } else { + if (areDisksLocked(vdcReturnValue)) { + throw new VdcBLLException(VdcBllErrors.IRS_IMAGE_STATUS_ILLEGAL); + } + getReturnValue().setFault(vdcReturnValue.getFault()); + log.errorFormat("Failed to create stateless snapshot for VM {0} ({1})", + getVm().getName(), getVm().getId()); + } + } + + private AddVmFromSnapshotParameters creataAddVmFromSnapshotParameters() { + List<Snapshot> snapshots = DbFacade.getInstance().getSnapshotDao().getAll(getVmId()); + // TODO handle the situation when there is no snapshot + Snapshot snapshot = snapshots.get(snapshots.size() - 1); + String name = getVm().getStaticData().getName() + RandomUtils.instance().nextByte(); + getVm().getStaticData().setName(name); + AddVmFromSnapshotParameters parameters = + new AddVmFromSnapshotParameters(getVm().getStaticData(), snapshot.getId()); + parameters.setDiskInfoDestinationMap(getParameters().getDiskInfoDestinationMap()); + parameters.setSessionId(getParameters().getSessionId()); + parameters.setParentParameters(getParameters()); + + return parameters; + } + + @Override + protected void endSuccessfully() { + if (getParameters().getNextAction() == null) { + getBackend().endAction(VdcActionType.CreateAllSnapshotsFromVm, buildCreateSnapshotParametersForEndAction()); + getParameters().setShouldBeLogged(false); + + setSucceeded(true); + + if (!getSucceeded()) { + getParameters().setShouldBeLogged(true); + log.errorFormat("Could not run VM {0} ({1}) in stateless mode", + getVm().getName(), getVm().getId()); + // could not run the vm don't try to run the end action again + getReturnValue().setEndActionTryAgain(false); + } + + getParameters().setNextAction(VdcActionType.AddVmFromSnapshot); + cloneVmFromSnapshot(); + } else if (getParameters().getNextAction() == VdcActionType.AddVmFromSnapshot) { + getBackend().endAction(VdcActionType.AddVmFromSnapshot, creataAddVmFromSnapshotParameters()); + + + + setSucceeded(true); + } + + } + + private CommandContext createContextForRunStatelessVm(StepEnum substepName) { + Step step = getExecutionContext().getStep(); + Job job = JobRepositoryFactory.getJobRepository().getJobWithSteps(step.getJobId()); + Step executingStep = job.getDirectStep(StepEnum.EXECUTING); + + ExecutionContext runStatelessVmCtx = new ExecutionContext(); + runStatelessVmCtx.setMonitored(true); + Step runStatelessStep = + ExecutionHandler.addSubStep(getExecutionContext(), + executingStep, + substepName, + ExecutionMessageDirector.resolveStepMessage(substepName, + getVmValuesForMsgResolving())); + runStatelessVmCtx.setShouldEndJob(true); + runStatelessVmCtx.setJob(job); + runStatelessVmCtx.setStep(runStatelessStep); + return new CommandContext(runStatelessVmCtx); + } + + private CommandContext createSubstepContext(StepEnum substepName) { + Map<String, String> values = getVmValuesForMsgResolving(); + // Creating snapshots as sub step of run stateless + Step createSnapshotsStep = addSubStep(StepEnum.EXECUTING, substepName, values); + + // Add the step as the first step of the new context + ExecutionContext createSnapshotsCtx = new ExecutionContext(); + createSnapshotsCtx.setMonitored(true); + createSnapshotsCtx.setStep(createSnapshotsStep); + return new CommandContext(createSnapshotsCtx, getCompensationContext(), getLock()); + } + + private CreateAllSnapshotsFromVmParameters buildCreateSnapshotParameters() { + CreateAllSnapshotsFromVmParameters parameters = + new CreateAllSnapshotsFromVmParameters(getVm().getId(), CLONE_SNAPSHOT_DESCRIPTION); + parameters.setShouldBeLogged(false); + parameters.setParentCommand(getActionType()); + parameters.setEntityInfo(getParameters().getEntityInfo()); + parameters.setSnapshotType(Snapshot.SnapshotType.REGULAR); + parameters.setParentParameters(getParameters()); + parameters.setSessionId(getParameters().getSessionId()); + + return parameters; + } + + private CreateAllSnapshotsFromVmParameters buildCreateSnapshotParametersForEndAction() { + CreateAllSnapshotsFromVmParameters parameters = buildCreateSnapshotParameters(); + parameters.setImagesParameters(getParameters().getImagesParameters()); + return parameters; + } + + private boolean areDisksLocked(VdcReturnValueBase vdcReturnValue) { + return vdcReturnValue.getCanDoActionMessages().contains( + VdcBllMessages.ACTION_TYPE_FAILED_DISKS_LOCKED.name()); + } + + protected Map<String, String> getVmValuesForMsgResolving() { + return Collections.singletonMap(VdcObjectType.VM.name().toLowerCase(), getVmName()); + } + + @Override + public List<PermissionSubject> getPermissionCheckSubjects() { + List<PermissionSubject> permissionList = new ArrayList<PermissionSubject>(); + permissionList.add(new PermissionSubject(getParameters().getVmId(), + VdcObjectType.VM, + getActionType().getActionGroup())); + return permissionList; + } +} diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CloneVmParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CloneVmParameters.java new file mode 100644 index 0000000..7275a97 --- /dev/null +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/CloneVmParameters.java @@ -0,0 +1,35 @@ +package org.ovirt.engine.core.common.action; + +import org.ovirt.engine.core.common.businessentities.VM; + +public class CloneVmParameters extends VmManagementParametersBase { + + public CloneVmParameters() { + + } + + public CloneVmParameters(VM vm, String newName) { + super(vm); + this.newName = newName; + } + + private String newName; + + public String getNewName() { + return newName; + } + + public void setNewName(String newName) { + this.newName = newName; + } + + private VdcActionType nextAction; + + public VdcActionType getNextAction() { + return nextAction; + } + + public void setNextAction(VdcActionType nextAction) { + this.nextAction = nextAction; + } +} 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 cf253f0..ead34e9 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 @@ -51,6 +51,8 @@ CancelMigrateVm(41, ActionGroup.MIGRATE_VM, false, QuotaDependency.NONE), ActivateDeactivateVmNic(42, QuotaDependency.NONE), AddVmFromSnapshot(52, ActionGroup.CREATE_VM, QuotaDependency.BOTH), + // the sub commands take care of it + CloneVm(53, ActionGroup.CREATE_VM, QuotaDependency.NONE), ImportVmFromConfiguration(43, ActionGroup.IMPORT_EXPORT_VM, QuotaDependency.NONE), // VdsCommands AddVds(101, ActionGroup.CREATE_HOST, QuotaDependency.NONE), diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/job/StepEnum.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/job/StepEnum.java index c13c17a..5fbb9df 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/job/StepEnum.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/job/StepEnum.java @@ -18,6 +18,7 @@ MIGRATE_VM, CREATING_SNAPSHOTS, RUN_STATELESS_VM, + CLONE_VM, TAKING_VM_FROM_POOL, // Gluster diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java index e929e14..f461435 100644 --- a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/CommonApplicationConstants.java @@ -345,6 +345,9 @@ @DefaultStringValue("New VM") String newVm(); + @DefaultStringValue("Clone VM") + String cloneVm(); + @DefaultStringValue("Power Off") String powerOffVm(); diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java index a3c57c4..88b9560 100644 --- a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java +++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/VmListModel.java @@ -14,6 +14,7 @@ import org.ovirt.engine.core.common.action.AttachEntityToTagParameters; import org.ovirt.engine.core.common.action.ChangeDiskCommandParameters; import org.ovirt.engine.core.common.action.ChangeVMClusterParameters; +import org.ovirt.engine.core.common.action.CloneVmParameters; import org.ovirt.engine.core.common.action.MigrateVmParameters; import org.ovirt.engine.core.common.action.MigrateVmToServerParameters; import org.ovirt.engine.core.common.action.MoveVmParameters; @@ -46,6 +47,7 @@ import org.ovirt.engine.core.common.queries.IdQueryParameters; import org.ovirt.engine.core.common.queries.SearchParameters; import org.ovirt.engine.core.common.queries.VdcQueryParametersBase; +import org.ovirt.engine.core.common.queries.VdcQueryReturnValue; import org.ovirt.engine.core.common.queries.VdcQueryType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.StringHelper; @@ -92,6 +94,17 @@ public class VmListModel extends VmBaseListModel<VM> implements ISupportSystemTreeContext { public static final Version BALLOON_DEVICE_MIN_VERSION = Version.v3_2; + + private UICommand cloneVmCommand; + + public UICommand getCloneVmCommand() { + return cloneVmCommand; + } + + public void setCloneVmCommand(UICommand cloneVmCommand) { + this.cloneVmCommand = cloneVmCommand; + } + private UICommand newVMCommand; public UICommand getNewVmCommand() { @@ -392,6 +405,7 @@ setConsoleHelpers(); setNewVmCommand(new UICommand("NewVm", this)); //$NON-NLS-1$ + setCloneVmCommand(new UICommand("NewVm", this)); //$NON-NLS-1$ setEditCommand(new UICommand("Edit", this)); //$NON-NLS-1$ setRemoveCommand(new UICommand("Remove", this)); //$NON-NLS-1$ setRunCommand(new UICommand("Run", this, true)); //$NON-NLS-1$ @@ -2233,6 +2247,7 @@ getSelectedItems() != null && getSelectedItem() != null ? getSelectedItems() : new ArrayList(); + getCloneVmCommand().setIsExecutionAllowed(items.size() == 1); getEditCommand().setIsExecutionAllowed(isEditCommandExecutionAllowed(items)); getRemoveCommand().setIsExecutionAllowed(items.size() > 0 && VdcActionUtils.canExecute(items, VM.class, VdcActionType.RemoveVm)); @@ -2319,7 +2334,9 @@ { super.executeCommand(command); - if (command == getNewVmCommand()) + if (command == getCloneVmCommand()) { + cloneVm(); + } else if (command == getNewVmCommand()) { newVm(); } @@ -2461,6 +2478,39 @@ } + private void cloneVm() { + final VM vm = (VM) getSelectedItem(); + if (vm == null) { + return; + } + + final HashMap<Guid, DiskImage> diskInfoDestinationMap = new HashMap<Guid, DiskImage>(); + + Frontend.getInstance().runQuery(VdcQueryType.GetAllDisksByVmId, new IdQueryParameters(vm.getId()), + new AsyncQuery(this, new INewAsyncCallback() { + + @Override + public void onSuccess(Object model, Object returnValue) { + List<Disk> vmDisks = ((VdcQueryReturnValue) returnValue).getReturnValue(); + for (Disk disk : vmDisks) { + if (disk.getDiskStorageType() == DiskStorageType.IMAGE) { + diskInfoDestinationMap.put(disk.getId(), (DiskImage) disk); + } + } + + CloneVmParameters params = new CloneVmParameters(vm, "someNewName"); //$NON-NLS-1$ + params.setDiskInfoDestinationMap(diskInfoDestinationMap); + Frontend.getInstance().runAction(VdcActionType.CloneVm, params, + new IFrontendActionAsyncCallback() { + @Override + public void executed(FrontendActionAsyncResult result) { + System.out.println(""); + } + }, this); + } + })); + } + private void connectToConsoles() { StringBuilder errorMessages = null; diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java index 08c11c5..9b73883 100644 --- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/tab/MainTabVirtualMachineView.java @@ -191,6 +191,13 @@ return getMainModel().getRemoveCommand(); } }); + getTable().addActionButton(new WebAdminButtonDefinition<VM>(constants.cloneVm()) { + + @Override + protected UICommand resolveCommand() { + return getMainModel().getCloneVmCommand(); + } + }); // TODO: separator getTable().addActionButton(new WebAdminButtonDefinition<VM>(constants.runOnceVm()) { @Override -- To view, visit http://gerrit.ovirt.org/23581 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I2492f54834553e1dd06675b20342410152759f7f Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Tomas Jelinek <tjeli...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches