Omer Frenkel has uploaded a new change for review. Change subject: core: add support to update running vm ......................................................................
core: add support to update running vm Change-Id: Ie433352852f53f62e58349ce85475ee89e37ce89 Signed-off-by: Omer Frenkel <[email protected]> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmHandler.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolHandler.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ObjectIdentityChecker.java 5 files changed, 173 insertions(+), 6 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/58/26758/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java index fd7e711..bd8e80c 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmCommand.java @@ -15,6 +15,7 @@ import org.ovirt.engine.core.bll.quota.QuotaSanityParameter; import org.ovirt.engine.core.bll.quota.QuotaVdsDependent; import org.ovirt.engine.core.bll.quota.QuotaVdsGroupConsumptionParameter; +import org.ovirt.engine.core.bll.snapshots.SnapshotsManager; import org.ovirt.engine.core.bll.utils.PermissionSubject; import org.ovirt.engine.core.bll.utils.VmDeviceUtils; import org.ovirt.engine.core.bll.validator.VmWatchdogValidator; @@ -31,6 +32,7 @@ import org.ovirt.engine.core.common.businessentities.Disk; import org.ovirt.engine.core.common.businessentities.DiskInterface; import org.ovirt.engine.core.common.businessentities.MigrationSupport; +import org.ovirt.engine.core.common.businessentities.Snapshot; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.businessentities.VMStatus; import org.ovirt.engine.core.common.businessentities.VmDevice; @@ -51,8 +53,10 @@ import org.ovirt.engine.core.common.validation.group.UpdateVm; import org.ovirt.engine.core.compat.DateTime; import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase; +import org.ovirt.engine.core.dao.SnapshotDao; import org.ovirt.engine.core.dao.VmDeviceDAO; import org.ovirt.engine.core.utils.customprop.ValidationError; import org.ovirt.engine.core.utils.customprop.VmPropertiesUtils; @@ -87,6 +91,10 @@ @Override protected void executeVmCommand() { + if (isRunningConfigurationNeeded()) { + createNextRunSnapshot(); + } + oldVm = getVm(); VmHandler.warnMemorySizeLegal(getParameters().getVm().getStaticData(), getVdsGroup().getcompatibility_version()); getVmStaticDAO().incrementDbGeneration(getVm().getId()); @@ -95,15 +103,48 @@ if (newVmStatic.getCreationDate().equals(DateTime.getMinValue())) { newVmStatic.setCreationDate(new Date()); } + + if (getVm().isRunningOrPaused()) { + VmHandler.CopyNonEditableFieldsToDestination(oldVm.getStaticData(), newVmStatic); + } + UpdateVmNetworks(); - hotSetCpus(); + if (!getParameters().isApplyChangesLater()) { + hotSetCpus(); + } getVmStaticDAO().update(newVmStatic); - updateVmPayload(); - VmDeviceUtils.updateVmDevices(getParameters(), oldVm); - updateWatchdog(); - checkTrustedService(); + if (getVm().isNotRunning()) { + updateVmPayload(); + VmDeviceUtils.updateVmDevices(getParameters(), oldVm); + updateWatchdog(); + } VmHandler.updateVmInitToDB(getParameters().getVmStaticData()); + + checkTrustedService(); setSucceeded(true); + } + + private void createNextRunSnapshot() { + // first remove existing snapshot + Snapshot runSnap = getSnapshotDao().get(getVmId(), Snapshot.SnapshotType.NEXT_RUN); + if (runSnap != null) { + getSnapshotDao().remove(runSnap.getId()); + } + + // create new snapshot with new configuration + new SnapshotsManager().addSnapshot(Guid.newGuid(), + "Next Run configuration snapshot", + Snapshot.SnapshotStatus.OK, + Snapshot.SnapshotType.NEXT_RUN, + getVm(), + true, + StringUtils.EMPTY, + Collections.EMPTY_LIST, + getCompensationContext()); + } + + protected SnapshotDao getSnapshotDao() { + return DbFacade.getInstance().getSnapshotDao(); } private void hotSetCpus() { @@ -501,7 +542,18 @@ protected boolean areUpdatedFieldsLegal() { return VmHandler.isUpdateValid(getVm().getStaticData(), getParameters().getVmStaticData(), - getVm().getStatus()); + VMStatus.Down); + } + + /** + * check if we need to use running-configuration + * @return true if vm is running and we change field that has @EditableOnVmStatusField annotation + * or runningConfiguration already exist + */ + private boolean isRunningConfigurationNeeded() { + return !VmHandler.isUpdateValid(getVm().getStaticData(), + getParameters().getVmStaticData(), + getVm().getStatus()) || getVm().isNextRunConfigurationExists(); } @Override @@ -571,6 +623,15 @@ } @Override + protected Map<String, Pair<String, String>> getSharedLocks() { + return Collections.singletonMap( + getVmId().toString(), + LockMessagesMatchUtil.makeLockingPair( + LockingGroup.VM, + VdcBllMessages.ACTION_TYPE_FAILED_OBJECT_LOCKED)); + } + + @Override public List<QuotaConsumptionParameter> getQuotaVdsConsumptionParameters() { List<QuotaConsumptionParameter> list = new ArrayList<QuotaConsumptionParameter>(); diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmHandler.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmHandler.java index 14c7f87..0f9bc30 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmHandler.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmHandler.java @@ -135,6 +135,10 @@ return mUpdateVmsStatic.IsUpdateValid(source, destination); } + public static boolean CopyNonEditableFieldsToDestination(VmStatic source, VmStatic destination) { + return mUpdateVmsStatic.CopyNonEditableFieldsToDestination(source, destination); + } + /** * Verifies the add vm command . * diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolHandler.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolHandler.java index cfaddcc..59bc380 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolHandler.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/VmPoolHandler.java @@ -1,17 +1,26 @@ package org.ovirt.engine.core.bll; +import java.util.Date; import java.util.List; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.bll.quota.QuotaManager; +import org.ovirt.engine.core.bll.snapshots.SnapshotsManager; import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.action.VmManagementParametersBase; import org.ovirt.engine.core.common.action.VmOperationParameterBase; import org.ovirt.engine.core.common.action.VmPoolSimpleUserParameters; import org.ovirt.engine.core.common.businessentities.DbUser; +import org.ovirt.engine.core.common.businessentities.Snapshot; import org.ovirt.engine.core.common.businessentities.Snapshot.SnapshotType; +import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VmDevice; +import org.ovirt.engine.core.common.businessentities.VmPayload; import org.ovirt.engine.core.common.businessentities.VmPool; import org.ovirt.engine.core.common.businessentities.VmPoolMap; import org.ovirt.engine.core.common.businessentities.VmPoolType; +import org.ovirt.engine.core.common.businessentities.VmWatchdog; +import org.ovirt.engine.core.common.utils.VmDeviceType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.log.Log; @@ -50,6 +59,57 @@ QuotaManager.getInstance().rollbackQuotaByVmId(vmId); VmHandler.removeStatelessVmUnmanagedDevices(vmId); + + // apply running configuration + Snapshot runSnap = DbFacade.getInstance().getSnapshotDao().get(vmId, Snapshot.SnapshotType.NEXT_RUN); + if (runSnap != null) { + DbFacade.getInstance().getSnapshotDao().remove(runSnap.getId()); + VM vm = DbFacade.getInstance().getVmDao().get(vmId); + if (vm != null) { + Date originalCreationDate = vm.getVmCreationDate(); + new SnapshotsManager().updateVmFromConfiguration(vm, runSnap.getVmConfiguration()); + // override creation date because the value in the config is the creation date of the config, not the vm + vm.setVmCreationDate(originalCreationDate); + vm.setExportDate(null); + vm.setOvfVersion(null); + + VmManagementParametersBase updateVmParams = new VmManagementParametersBase(vm); + updateVmParams.setUpdateWatchdog(true); + updateVmParams.setSoundDeviceEnabled(false); + updateVmParams.setBalloonEnabled(false); + updateVmParams.setVirtioScsiEnabled(false); + updateVmParams.setClearPayload(true); + + for (VmDevice device : vm.getManagedVmDeviceMap().values()) { + switch (device.getType()) { + case WATCHDOG: + updateVmParams.setWatchdog(new VmWatchdog(device)); + break; + case SOUND: + updateVmParams.setSoundDeviceEnabled(true); + break; + case BALLOON: + updateVmParams.setBalloonEnabled(true); + break; + case CONTROLLER: + if (VmDeviceType.VIRTIOSCSI.getName().equals(device.getDevice())) { + updateVmParams.setVirtioScsiEnabled(true); + } + break; + case DISK: + if (VmPayload.isPayload(device.getSpecParams())) { + updateVmParams.setVmPayload(new VmPayload(VmDeviceType.getByName(device.getDevice()), device.getSpecParams())); + } + break; + case CONSOLE: + updateVmParams.setConsoleEnabled(true); + } + } + vm.getManagedVmDeviceMap().clear(); + vm.getVmUnamagedDeviceList().clear(); + Backend.getInstance().runInternalAction(VdcActionType.UpdateVm, updateVmParams); + } + } } public static void removeVmStatelessImages(Guid vmId, CommandContext context) { diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java index 143a3c9..80a390b 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java @@ -26,6 +26,7 @@ private VM vm; private VmWatchdog watchdog; private boolean copyTemplatePermissions; + private boolean applyChangesLater; /* * This parameter is needed at update to make sure that when we get a null watchdog from rest-api it is not meant to @@ -197,4 +198,12 @@ public void setVirtioScsiEnabled(Boolean virtioScsiEnabled) { this.virtioScsiEnabled = virtioScsiEnabled; } + + public boolean isApplyChangesLater() { + return applyChangesLater; + } + + public void setApplyChangesLater(boolean applyChangesLater) { + this.applyChangesLater = applyChangesLater; + } } diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ObjectIdentityChecker.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ObjectIdentityChecker.java index f1a6612..d5bb2f6 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ObjectIdentityChecker.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ObjectIdentityChecker.java @@ -1,5 +1,7 @@ package org.ovirt.engine.core.utils; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -102,6 +104,37 @@ return returnValue; } + /** + * This method will copy all fields that are not @editable from source obj to dest obj + * + * @param source object that has values of non editable fields + * @param destination object to copy the non editable to it + */ + public boolean CopyNonEditableFieldsToDestination(Object source, Object destination) { + Class<?> srcCls = source.getClass(); + Class<?> dstCls = destination.getClass(); + while (!srcCls.equals(Object.class)) { + for (Field srcFld : srcCls.getDeclaredFields()) + try { + if (!Modifier.isFinal(srcFld.getModifiers()) && !IsFieldUpdatable(srcFld.getName())) { + srcFld.setAccessible(true); + + Field dstFld = dstCls.getDeclaredField(srcFld.getName()); + dstFld.setAccessible(true); + dstFld.set(destination, srcFld.get(source)); + } + } catch (Exception exp) { + log.errorFormat("Failed to copy non editable field {0}, error: {1}", + srcFld.getName(), + exp.getMessage()); + return false; + } + srcCls = srcCls.getSuperclass(); + dstCls = dstCls.getSuperclass(); + } + return true; + } + public final boolean IsUpdateValid(Object source, Object destination) { if (source.getClass() != destination.getClass()) { return false; -- To view, visit http://gerrit.ovirt.org/26758 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie433352852f53f62e58349ce85475ee89e37ce89 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Omer Frenkel <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
