Hello Shmuel Melamud, I'd like you to do a code review. Please visit
https://gerrit.ovirt.org/40132 to review the following change. Change subject: core: Save RNG device when VM is running ...................................................................... core: Save RNG device when VM is running Added missing functionality to detect changes of RNG device properties when VM is running and to save/restore them to/from NEXT_RUN snapshot. For this purpose Optional<T> class was added to VmManagementParametersBase. This class combines data for the device that needs to be updated with a flag that switches the update on/off. This change makes possible to use @EditableDeviceOnVmStatusField annotation for rngDevice field and to combine rngDevice update with other device updates in a single list. Optional<T> class may be used as well for other fields in VmManagementParametersBase that use the same pattern. Watchdog is one of them. Change-Id: If9aa41b0cacd77120b002123d8e196e215e20fdc Signed-off-by: Shmuel Melamud <smela...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.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/utils/VmDeviceUtils.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/VmManagementParametersBase.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfReader.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfTemplateWriter.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfVmWriter.java M frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java 9 files changed, 150 insertions(+), 50 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/32/40132/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java index 89de6e5..9ff3b55 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/ProcessDownVmCommand.java @@ -22,6 +22,7 @@ import org.ovirt.engine.core.common.businessentities.VmPayload; import org.ovirt.engine.core.common.businessentities.VmPool; import org.ovirt.engine.core.common.businessentities.VmPoolType; +import org.ovirt.engine.core.common.businessentities.VmRngDevice; import org.ovirt.engine.core.common.businessentities.VmWatchdog; import org.ovirt.engine.core.common.businessentities.aaa.DbUser; import org.ovirt.engine.core.common.errors.VdcBllMessages; @@ -184,6 +185,7 @@ updateVmParams.setBalloonEnabled(false); updateVmParams.setVirtioScsiEnabled(false); updateVmParams.setClearPayload(true); + updateVmParams.setUpdateRngDevice(true); for (GraphicsType graphicsType : GraphicsType.values()) { updateVmParams.getGraphicsDevices().put(graphicsType, null); } @@ -212,6 +214,9 @@ case CONSOLE: updateVmParams.setConsoleEnabled(true); break; + case RNG: + updateVmParams.setRngDevice(new VmRngDevice(device)); + break; case GRAPHICS: updateVmParams.getGraphicsDevices().put(GraphicsType.fromString(device.getDevice()), new GraphicsDevice(device)); 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 69dc3f4..ad36f9f 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 @@ -848,6 +848,11 @@ Object value = field.get(objectWithEditableDeviceFields); if (value instanceof Boolean) { addDeviceUpdateOnNextRun(vmId, annotation, null, value, fieldList); + } else if (value instanceof VmManagementParametersBase.Optional) { + VmManagementParametersBase.Optional<?> optional = (VmManagementParametersBase.Optional<?>) value; + if (optional.isUpdate()) { + addDeviceUpdateOnNextRun(vmId, annotation, null, optional.getValue(), fieldList); + } } else if (value instanceof Map) { Map<?, ?> map = (Map<?, ?>) value; for (Map.Entry<?, ?> entry : map.entrySet()) { @@ -864,8 +869,6 @@ log.warn("VmHandler::getVmDevicesFieldsToUpdateOnNextRun: Reflection error"); log.debug("Original exception was:", e); } - - } return fieldList; @@ -873,8 +876,12 @@ private static boolean addDeviceUpdateOnNextRun(Guid vmId, EditableDeviceOnVmStatusField annotation, Object key, Object value, List<VmDeviceUpdate> updates) { - VmDeviceGeneralType generalType = annotation.generalType(); - VmDeviceType type = annotation.type(); + return addDeviceUpdateOnNextRun(vmId, annotation.generalType(), annotation.type(), annotation.isReadOnly(), + key, value, updates); + } + + private static boolean addDeviceUpdateOnNextRun(Guid vmId, VmDeviceGeneralType generalType, VmDeviceType type, + boolean readOnly, Object key, Object value, List<VmDeviceUpdate> updates) { if (key != null) { VmDeviceGeneralType keyGeneralType = VmDeviceGeneralType.UNKNOWN; @@ -910,15 +917,15 @@ if (value == null) { if (VmDeviceUtils.vmDeviceChanged(vmId, generalType, typeName, false)) { - updates.add(new VmDeviceUpdate(generalType, type, annotation.isReadOnly(), false)); + updates.add(new VmDeviceUpdate(generalType, type, readOnly, false)); } } else if (value instanceof Boolean) { if (VmDeviceUtils.vmDeviceChanged(vmId, generalType, typeName, (Boolean) value)) { - updates.add(new VmDeviceUpdate(annotation, (Boolean) value)); + updates.add(new VmDeviceUpdate(generalType, type, readOnly, (Boolean) value)); } } else if (value instanceof VmDevice) { - if (VmDeviceUtils.vmDeviceChanged(vmId, generalType, typeName, true)) { - updates.add(new VmDeviceUpdate(generalType, type, annotation.isReadOnly(), (VmDevice) value)); + if (VmDeviceUtils.vmDeviceChanged(vmId, generalType, typeName, (VmDevice) value)) { + updates.add(new VmDeviceUpdate(generalType, type, readOnly, (VmDevice) value)); } } else { log.warn("VmHandler::addDeviceUpdateOnNextRun: Unsupported value type: " + diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java index e75a409..31531fe 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/utils/VmDeviceUtils.java @@ -1140,10 +1140,42 @@ return deviceEnabled == vmDevices.isEmpty(); } + /** + * Determines whether a VM device change has been request by the user. + * @param deviceGeneralType VmDeviceGeneralType. + * @param deviceTypeName VmDeviceType name. + * @param device device object provided by user + * @return true if a change has been requested; otherwise, false + */ + public static boolean vmDeviceChanged(Guid vmId, VmDeviceGeneralType deviceGeneralType, String deviceTypeName, + VmDevice device) { + List<VmDevice> vmDevices = deviceTypeName != null ? + dao.getVmDeviceByVmIdTypeAndDevice(vmId, deviceGeneralType, deviceTypeName): + dao.getVmDeviceByVmIdAndType(vmId, deviceGeneralType); + + if (device == null) + return !vmDevices.isEmpty(); + if (device != null && vmDevices.isEmpty()) + return true; + if (device.getSpecParams() != null) { // if device.getSpecParams() == null, it is not used for comparison + for (VmDevice vmDevice : vmDevices) { + if (!vmDevice.getSpecParams().equals(device.getSpecParams())) { + return true; + } + } + } + + return false; + } + public static boolean vmDeviceChanged(Guid vmId, VmDeviceGeneralType deviceType, boolean deviceEnabled) { return vmDeviceChanged(vmId, deviceType, null, deviceEnabled); } + public static boolean vmDeviceChanged(Guid vmId, VmDeviceGeneralType deviceType, VmDevice device) { + return vmDeviceChanged(vmId, deviceType, null, device); + } + /** * Returns a map (device ID to VmDevice) of devices that are relevant for next run by examining * properties that are annotated by EditableDeviceOnVmStatusField. 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 b457b43..4e23a8b 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 @@ -1,5 +1,6 @@ package org.ovirt.engine.core.common.action; +import java.io.Serializable; import java.util.HashMap; import java.util.Map; import javax.validation.Valid; @@ -21,6 +22,41 @@ private static final long serialVersionUID = -7695630335738521510L; + /** + * This class combines a value and update flag. If update flag is false, the value is not used to update the VM. + * This is used to maintain backward compatibility in REST API: when null value comes from REST API it doesn't mean + * the value must be cleaned in the VM. REST API has separate commands to update values marked as Optional<T> here. + * + * @param <T> type of the value + */ + public static class Optional<T> implements Serializable { + + private static final long serialVersionUID = 2456445711176920294L; + + private boolean update; + private T value; + + public Optional() { + } + + public boolean isUpdate() { + return update; + } + + public void setUpdate(boolean update) { + this.update = update; + } + + public T getValue() { + return value; + } + + public void setValue(T value) { + this.value = value; + } + + } + @Valid private VmStatic vmStatic; private boolean makeCreatorExplicitOwner; @@ -30,24 +66,16 @@ private boolean clearPayload; private Boolean balloonEnabled; private VM vm; - private VmWatchdog watchdog; - private VmRngDevice rngDevice; private boolean copyTemplatePermissions; private boolean applyChangesLater; private boolean updateNuma; - /* - * This parameter is needed at update to make sure that when we get a null watchdog from rest-api it is not meant to - * be removing the watchdog, rest-api will simply call watchdog commands directly. Default is false so to avoid - * breaking rest-api. - */ - private boolean updateWatchdog; - /* - * This parameter is used to decide if to create sound device or not if it is null then: for add vm legacy logic - * will be used: create device for desktop type for update the current configuration will remain - * Used by rest-api. - */ - private boolean updateRngDevice; + + private Optional<VmWatchdog> watchdog = new Optional<>(); + + @EditableDeviceOnVmStatusField(generalType = VmDeviceGeneralType.RNG, type = VmDeviceType.VIRTIO) + private Optional<VmRngDevice> rngDevice = new Optional<>(); + /* * This parameter is used to decide if to create sound device or not * if it is null then: @@ -56,6 +84,7 @@ */ @EditableDeviceOnVmStatusField(generalType = VmDeviceGeneralType.SOUND, type = VmDeviceType.UNKNOWN, isReadOnly = true) private Boolean soundDeviceEnabled; + /* * This parameter is used to decide if to create console device or not if it is null then: for add vm don't add * console device for update the current configuration will remain @@ -183,38 +212,38 @@ } public VmWatchdog getWatchdog() { - return watchdog; + return watchdog.getValue(); } public void setWatchdog(VmWatchdog watchdog) { - this.watchdog = watchdog; + this.watchdog.setValue(watchdog); } public VmRngDevice getRngDevice() { - return rngDevice; + return rngDevice.getValue(); } public void setRngDevice(VmRngDevice rngDevice) { - this.rngDevice = rngDevice; - if (this.rngDevice != null) { - this.rngDevice.setVmId(getVmId()); + this.rngDevice.setValue(rngDevice); + if (this.rngDevice.getValue() != null) { + this.rngDevice.getValue().setVmId(getVmId()); } } public boolean isUpdateRngDevice() { - return updateRngDevice; + return rngDevice.isUpdate(); } public void setUpdateRngDevice(boolean updateRngDevice) { - this.updateRngDevice = updateRngDevice; + this.rngDevice.setUpdate(updateRngDevice); } public boolean isUpdateWatchdog() { - return updateWatchdog; + return watchdog.isUpdate(); } public void setUpdateWatchdog(boolean updateWatchdog) { - this.updateWatchdog = updateWatchdog; + this.watchdog.setUpdate(updateWatchdog); } public Boolean isConsoleEnabled() { diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java index b679b6f..7d8f424 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/utils/VmDeviceCommonUtils.java @@ -370,6 +370,7 @@ || (VmDeviceType.SPICEVMC.getName().equals(device) && VmDeviceGeneralType.REDIR == type) || (VmDeviceType.MEMBALLOON.getName().equals(device) && VmDeviceGeneralType.BALLOON == type)) || (VmDeviceType.WATCHDOG.getName().equals(device) && VmDeviceGeneralType.WATCHDOG == type) + || (VmDeviceType.VIRTIO.getName().equals(device) && VmDeviceGeneralType.RNG == type) || (VmDeviceType.VIRTIOSERIAL.getName().equals(device) && VmDeviceGeneralType.CONTROLLER == type) || (VmDeviceType.VIRTIOSCSI.getName().equals(device) && VmDeviceGeneralType.CONTROLLER == type); } diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfReader.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfReader.java index 790eb4d..ef1ce15 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfReader.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfReader.java @@ -214,7 +214,6 @@ * Reads vm device attributes from OVF and stores it in the collection * * @param node - * @param vmBase * @param deviceId */ private VmDevice readVmDevice(XmlNode node, Guid deviceId) { diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfTemplateWriter.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfTemplateWriter.java index b49dd46..d593401 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfTemplateWriter.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfTemplateWriter.java @@ -250,7 +250,7 @@ // monitors writeMonitors(_vmTemplate); // graphics - writeGraphics(vmBase); + writeGraphics(_vmTemplate); // CD writeCd(_vmTemplate); // ummanged devices diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfVmWriter.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfVmWriter.java index 1b041de..5d8bb41 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfVmWriter.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ovf/OvfVmWriter.java @@ -344,7 +344,7 @@ writeGraphics(vmBase); // CD writeCd(vmBase); - // ummanged devices + // unmanaged devices writeOtherDevices(vmBase, _writer); // End hardware section diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java index 3ed8392..ee994f5 100644 --- a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java +++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/vms/instancetypes/InstanceTypeManager.java @@ -9,6 +9,7 @@ import org.ovirt.engine.core.common.businessentities.MigrationSupport; import org.ovirt.engine.core.common.businessentities.VmBase; import org.ovirt.engine.core.common.businessentities.VmDevice; +import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType; import org.ovirt.engine.core.common.businessentities.VmEntityType; import org.ovirt.engine.core.common.businessentities.VmRngDevice; import org.ovirt.engine.core.common.businessentities.VmTemplate; @@ -266,8 +267,23 @@ return null; } + private VmDevice findVmDeviceByGeneralType(Map<Guid, VmDevice> vmManagedDeviceMap, + VmDeviceGeneralType generalType) { + for (VmDevice vmDevice : vmManagedDeviceMap.values()) { + if (vmDevice.getType() == generalType) { + return vmDevice; + } + } + + return null; + } + private boolean isVmDeviceExists(Map<Guid, VmDevice> vmManagedDeviceMap, String name) { return findVmDeviceByName(vmManagedDeviceMap, name) != null; + } + + private boolean isVmDeviceExists(Map<Guid, VmDevice> vmManagedDeviceMap, VmDeviceGeneralType generalType) { + return findVmDeviceByGeneralType(vmManagedDeviceMap, generalType) != null; } protected void doUpdateManagedFieldsFrom(final VmBase vmBase) { @@ -401,23 +417,34 @@ protected void updateRngDevice(final VmBase vmBase) { if (model.getIsRngEnabled().getIsChangable() && model.getIsRngEnabled().getIsAvailable()) { - Frontend.getInstance().runQuery(VdcQueryType.GetRngDevice, new IdQueryParameters(vmBase.getId()), new AsyncQuery( - this, - new INewAsyncCallback() { - @Override - public void onSuccess(Object model, Object returnValue) { - deactivate(); - List<VmDevice> rngDevices = ((VdcQueryReturnValue) returnValue).getReturnValue(); - getModel().getIsRngEnabled().setEntity(!rngDevices.isEmpty()); - if (!rngDevices.isEmpty()) { - VmRngDevice rngDevice = new VmRngDevice(rngDevices.get(0)); - getModel().setRngDevice(rngDevice); + if (!isNextRunConfigurationExists()) { + Frontend.getInstance().runQuery(VdcQueryType.GetRngDevice, new IdQueryParameters(vmBase.getId()), new AsyncQuery( + this, + new INewAsyncCallback() { + @Override + public void onSuccess(Object model, Object returnValue) { + deactivate(); + List<VmDevice> rngDevices = ((VdcQueryReturnValue) returnValue).getReturnValue(); + getModel().getIsRngEnabled().setEntity(!rngDevices.isEmpty()); + if (!rngDevices.isEmpty()) { + VmRngDevice rngDevice = new VmRngDevice(rngDevices.get(0)); + getModel().setRngDevice(rngDevice); + } + activate(); + updateVirtioScsi(vmBase); } - activate(); - updateVirtioScsi(vmBase); } - } - )); + )); + } else { + deactivate(); + VmDevice rngDevice = findVmDeviceByGeneralType(vmBase.getManagedDeviceMap(), VmDeviceGeneralType.RNG); + getModel().getIsRngEnabled().setEntity(rngDevice != null); + if (rngDevice != null) { + getModel().setRngDevice(new VmRngDevice(rngDevice)); + } + activate(); + updateVirtioScsi(vmBase); + } } else { updateVirtioScsi(vmBase); } -- To view, visit https://gerrit.ovirt.org/40132 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If9aa41b0cacd77120b002123d8e196e215e20fdc Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Shmuel Leib Melamud <smela...@redhat.com> Gerrit-Reviewer: Shmuel Melamud <smela...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches