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

Reply via email to