Eldan Shachar has uploaded a new change for review.

Change subject: core: Editing of template version for stateless VMs and pools
......................................................................

core: Editing of template version for stateless VMs and pools

This patch will allow a user to change a template version for an
existing stateless VM / Pool.

The main issues handled are:
- VM \ Pool object - added support for changing of the template field.
- Frontend - Added support for editing of this field and introduced
some limitations to avoid non-supported behaviors.
- UpdateVmVersion Command - added support for any template versions.
- Pools - Until now pools haven't supported changes affecting the actual VMs
and some logic that depended on this assumption needed change.
- Running VMs - Changes were required in the next-run logic on multiple 
locations.

Change-Id: Ib106016955c702bc28f9347d828c4602e47bd233
Bug-Url: https://bugzilla.redhat.com/1140569
Signed-off-by: Eldan Shachar <[email protected]>
---
A 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/EditableOnStatelessVmField.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmPool.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAO.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAODbFacadeImpl.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmPoolDAODbFacadeImpl.java
M backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
M 
backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmPoolDAOTest.java
M backend/manager/modules/dal/src/test/resources/fixtures.xml
M 
backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/ObjectIdentityChecker.java
M 
backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ObjectIdentityCheckerTest.java
M 
frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
M 
frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
M 
frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
M packaging/dbscripts/create_views.sql
A packaging/dbscripts/upgrade/03_06_0700_add_template_id_to_pool.sql
M packaging/dbscripts/vm_pools_sp.sql
M packaging/dbscripts/vm_templates_sp.sql
M packaging/dbscripts/vms_sp.sql
20 files changed, 168 insertions(+), 34 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/07/36507/1

diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/EditableOnStatelessVmField.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/EditableOnStatelessVmField.java
new file mode 100644
index 0000000..42030bf
--- /dev/null
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/EditableOnStatelessVmField.java
@@ -0,0 +1,12 @@
+package org.ovirt.engine.core.common.businessentities;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface EditableOnStatelessVmField {
+
+}
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmPool.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmPool.java
index 5b11cdd..65dfd20 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmPool.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmPool.java
@@ -38,6 +38,10 @@
 
     private Guid vdsGroupId;
 
+    private Guid vmtGuid;
+
+    private boolean useLatestVersion;
+
     private int prestartedVms;
 
     private int defaultTimeInDays;
@@ -89,6 +93,8 @@
         result = prime * result + vmPoolRunningCount;
         result = prime * result + ((type == null) ? 0 : type.hashCode());
         result = prime * result + maxAssignedVmsPerUser;
+        result = prime * result + ((vmtGuid == null) ? 0 : vmtGuid.hashCode());
+        result = prime * result + (useLatestVersion ? 1249 : 1259);
         return result;
     }
 
@@ -113,7 +119,9 @@
                 && ObjectUtils.objectsEqual(description, other.description)
                 && ObjectUtils.objectsEqual(name, other.name)
                 && ObjectUtils.objectsEqual(type, other.type)
-                && maxAssignedVmsPerUser == other.maxAssignedVmsPerUser);
+                && maxAssignedVmsPerUser == other.maxAssignedVmsPerUser
+                && ObjectUtils.objectsEqual(vmtGuid, other.vmtGuid))
+                && useLatestVersion == other.useLatestVersion;
     }
 
     public String getParameters() {
@@ -249,4 +257,20 @@
     public String getSpiceProxy() {
         return spiceProxy;
     }
+
+    public Guid getVmtGuid() {
+        return vmtGuid;
+    }
+
+    public void setVmtGuid(Guid vmtGuid) {
+        this.vmtGuid = vmtGuid;
+    }
+
+    public boolean isUseLatestVersion() {
+        return useLatestVersion;
+    }
+
+    public void setUseLatestVersion(boolean useLatestVersion) {
+        this.useLatestVersion = useLatestVersion;
+    }
 }
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
index 0f04626..3ce326a 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/businessentities/VmStatic.java
@@ -14,6 +14,7 @@
 public class VmStatic extends VmBase {
     private static final long serialVersionUID = -2753306386502558044L;
 
+    @EditableOnStatelessVmField
     private Guid vmtGuid;
 
     private boolean initialized;
diff --git 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
index 297e153..dcada98 100644
--- 
a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
+++ 
b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.java
@@ -227,6 +227,7 @@
     ACTION_TYPE_FAILED_CANNOT_REMOVE_IMAGE_TEMPLATE(ErrorType.CONFLICT),
     ACTION_TYPE_FAILED_CPU_NOT_FOUND(ErrorType.BAD_PARAMETERS),
     ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST(ErrorType.BAD_PARAMETERS),
+    
ACTION_TYPE_FAILED_TEMPLATE_IS_ON_DIFFERENT_CHAIN(ErrorType.BAD_PARAMETERS),
     ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY(ErrorType.BAD_PARAMETERS),
     
ACTION_TYPE_FAILED_TEMPLATE_VERSION_CANNOT_BE_BASE_TEMPLATE(ErrorType.BAD_PARAMETERS),
     
ACTION_TYPE_FAILED_TEMPLATE_CANNOT_BE_CREATED_WITH_EMPTY_DISK_ALIAS(ErrorType.BAD_PARAMETERS),
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAO.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAO.java
index 1caca5ff..d73f815 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAO.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAO.java
@@ -221,6 +221,13 @@
     List<VM> getAll();
 
     /**
+     * Retrieves the list of all VMS from a given pool.
+     *
+     * @return the list of all VMs in the pool
+     */
+    List<VM> getPoolVms(Guid poolId);
+
+    /**
      * Saves the is_initialized property of the VM.
      *
      * @param vmid
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAODbFacadeImpl.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAODbFacadeImpl.java
index d9e4cfa..1acba05 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAODbFacadeImpl.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmDAODbFacadeImpl.java
@@ -196,6 +196,14 @@
         return getAll(null, false);
     }
 
+    @Override public List<VM> getPoolVms(Guid poolId) {
+        return getCallsHandler().executeReadList("GetPoolVmsFromVms",
+                VMRowMapper.instance,
+                getCustomMapSqlParameterSource().addValue("user_id", null)
+                        .addValue("is_filtered", false)
+                        .addValue("pool_id", poolId));
+    }
+
     @Override
     public List<VM> getAll(Guid userID, boolean isFiltered) {
         return getCallsHandler().executeReadList("GetAllFromVms",
@@ -328,6 +336,20 @@
         }
     }
 
+    static final class VMPoolRowMapper implements RowMapper<VM> {
+        public static final VMPoolRowMapper instance = new VMPoolRowMapper();
+
+        @Override
+        public VM mapRow(ResultSet rs, int rowNum) throws SQLException {
+            VM entity = VMRowMapper.instance.mapRow(rs, rowNum);
+            if (entity != null) {
+                entity.setVmtGuid(getGuidDefaultEmpty(rs, "vm_pool_vmt_guid"));
+                entity.setUseLatestVersion(rs.getBoolean("vm_pool_is_latest"));
+            }
+            return entity;
+        }
+    }
+
     private static final class VMWithPlugInfoRowMapper implements 
RowMapper<Pair<VM, VmDevice>> {
         public static final VMWithPlugInfoRowMapper instance = new 
VMWithPlugInfoRowMapper();
 
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmPoolDAODbFacadeImpl.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmPoolDAODbFacadeImpl.java
index b02f583..f08ede2 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmPoolDAODbFacadeImpl.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/VmPoolDAODbFacadeImpl.java
@@ -10,7 +10,7 @@
 import org.ovirt.engine.core.common.businessentities.VmPoolMap;
 import org.ovirt.engine.core.common.businessentities.VmPoolType;
 import org.ovirt.engine.core.compat.Guid;
-import org.ovirt.engine.core.dao.VmDAODbFacadeImpl.VMRowMapper;
+import org.ovirt.engine.core.dao.VmDAODbFacadeImpl.VMPoolRowMapper;
 import org.springframework.jdbc.core.RowMapper;
 import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
 
@@ -85,7 +85,9 @@
                 .addValue("prestarted_vms", pool.getPrestartedVms())
                 .addValue("vds_group_id", pool.getVdsGroupId())
                 .addValue("max_assigned_vms_per_user", 
pool.getMaxAssignedVmsPerUser())
-                .addValue("spice_proxy", pool.getSpiceProxy());
+                .addValue("spice_proxy", pool.getSpiceProxy())
+                .addValue("vm_pool_vmt_guid", pool.getVmtGuid())
+                .addValue("vm_pool_is_latest", pool.isUseLatestVersion());
 
         getCallsHandler().executeModification("InsertVm_pools", 
parameterSource);
     }
@@ -102,7 +104,9 @@
                 .addValue("prestarted_vms", pool.getPrestartedVms())
                 .addValue("vds_group_id", pool.getVdsGroupId())
                 .addValue("max_assigned_vms_per_user", 
pool.getMaxAssignedVmsPerUser())
-                .addValue("spice_proxy", pool.getSpiceProxy());
+                .addValue("spice_proxy", pool.getSpiceProxy())
+                .addValue("vm_pool_vmt_guid", pool.getVmtGuid())
+                .addValue("vm_pool_is_latest", pool.isUseLatestVersion());
 
         getCallsHandler().executeModification("UpdateVm_pools", 
parameterSource);
     }
@@ -161,6 +165,8 @@
             entity.setRunningVmsCount(rs.getInt("vm_running_count"));
             
entity.setMaxAssignedVmsPerUser(rs.getInt("max_assigned_vms_per_user"));
             entity.setSpiceProxy(rs.getString("spice_proxy"));
+            entity.setVmtGuid(getGuidDefaultEmpty(rs, "vm_pool_vmt_guid"));
+            entity.setUseLatestVersion(rs.getBoolean("vm_pool_is_latest"));
             return entity;
         }
     }
@@ -184,6 +190,8 @@
             entity.setVdsGroupName(rs.getString("vds_group_name"));
             
entity.setMaxAssignedVmsPerUser(rs.getInt("max_assigned_vms_per_user"));
             entity.setSpiceProxy(rs.getString("spice_proxy"));
+            entity.setVmtGuid(getGuidDefaultEmpty(rs, "vm_pool_vmt_guid"));
+            entity.setUseLatestVersion(rs.getBoolean("vm_pool_is_latest"));
             return entity;
         }
     }
@@ -204,13 +212,13 @@
     public VM getVmDataFromPoolByPoolGuid(Guid vmPoolId, Guid userID, boolean 
isFiltered) {
         MapSqlParameterSource parameterSource = 
getCustomMapSqlParameterSource()
                 .addValue("pool_id", vmPoolId).addValue("user_id", 
userID).addValue("is_filtered", isFiltered);
-        return getCallsHandler().executeRead("GetVmDataFromPoolByPoolId", 
VMRowMapper.instance, parameterSource);
+        return getCallsHandler().executeRead("GetVmDataFromPoolByPoolId", 
VMPoolRowMapper.instance, parameterSource);
     }
 
     @Override
     public VM getVmDataFromPoolByPoolName(String vmPoolName, Guid userId, 
boolean isFiltered) {
         MapSqlParameterSource parameterSource = 
getCustomMapSqlParameterSource()
                 .addValue("pool_name", vmPoolName).addValue("user_id", 
userId).addValue("is_filtered", isFiltered);
-        return getCallsHandler().executeRead("GetVmDataFromPoolByPoolName", 
VMRowMapper.instance, parameterSource);
+        return getCallsHandler().executeRead("GetVmDataFromPoolByPoolName", 
VMPoolRowMapper.instance, parameterSource);
     }
 }
diff --git 
a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties 
b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
index 43c2193..c48ce49 100644
--- 
a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
+++ 
b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
@@ -250,6 +250,7 @@
 ACTION_TYPE_FAILED_PROBLEM_WITH_CANDIDATE_INFO=Cannot ${action} ${type}. 
Failed to get data for Import operation.\n\
 - Check your Import Domain.
 ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST=Cannot ${action} ${type}. The 
relevant Template doesn't exist.
+ACTION_TYPE_FAILED_TEMPLATE_IS_ON_DIFFERENT_CHAIN=Cannot ${action} ${type}. 
The requested template doesn't belong to the same base template as the original 
template.
 ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY=Cannot ${action} ${type}. The 
relevant Cluster doesn't exist.
 ACTION_TYPE_FAILED_TEMPLATE_VERSION_CANNOT_BE_BASE_TEMPLATE=Cannot ${action} 
${type}. Only the first template version can be selected as the base template.
 ACTION_TYPE_FAILED_INSTANCE_TYPE_DOES_NOT_EXIST=Cannot ${action} ${type}. The 
relevant Instance Type doesn't exist.
diff --git 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmPoolDAOTest.java
 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmPoolDAOTest.java
index 28e6b6b..253138f 100644
--- 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmPoolDAOTest.java
+++ 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/VmPoolDAOTest.java
@@ -22,6 +22,7 @@
     private static final Guid EXISTING_VM_POOL_ID = new 
Guid("103cfd1d-18b1-4790-8a0c-1e52621b0076");
     private static final Guid FREE_VM_ID = new 
Guid("77296e00-0cad-4e5a-9299-008a7b6f4356");
     private static final Guid EXISTING_VM_ID = new 
Guid("77296e00-0cad-4e5a-9299-008a7b6f4355");
+    private static final Guid POOL_TEMPLATE_ID = new 
Guid("12346e00-0cad-4e5a-9299-008a7b6f4355");
     private static final int VM_POOL_COUNT = 3;
     private VmPoolDAO dao;
     private VmPool existingVmPool;
@@ -44,6 +45,7 @@
         newVmPool.setName("New VM Pool");
         newVmPool.setVmPoolDescription("This is a new VM pool.");
         newVmPool.setVdsGroupId(VDS_GROUP_ID);
+        newVmPool.setVmtGuid(POOL_TEMPLATE_ID);
 
         newVmPoolMap = new VmPoolMap(FREE_VM_ID, EXISTING_VM_POOL_ID);
     }
diff --git a/backend/manager/modules/dal/src/test/resources/fixtures.xml 
b/backend/manager/modules/dal/src/test/resources/fixtures.xml
index d54c080..fb5867a 100644
--- a/backend/manager/modules/dal/src/test/resources/fixtures.xml
+++ b/backend/manager/modules/dal/src/test/resources/fixtures.xml
@@ -1711,6 +1711,8 @@
         <column>vds_group_id</column>
         <column>max_assigned_vms_per_user</column>
         <column>spice_proxy</column>
+        <column>vm_pool_vmt_guid</column>
+        <column>vm_pool_is_latest</column>
         <row>
             <value>103cfd1d-18b1-4790-8a0c-1e52621b0076</value>
             <value>fedora13-pool</value>
@@ -1721,6 +1723,8 @@
             <value>b399944a-81ab-4ec5-8266-e19ba7c3c9d1</value>
             <value>1</value>
             <null/>
+            <null/>
+            <value>false</value>
         </row>
         <row>
             <value>103cfd1d-18b1-4790-8a0c-1e52621b0077</value>
@@ -1732,6 +1736,8 @@
             <value>b399944a-81ab-4ec5-8266-e19ba7c3c9d1</value>
             <value>1</value>
             <null/>
+            <value>1b85420c-b84c-4f29-997e-0eb674b40b79</value>
+            <value>false</value>
         </row>
         <row>
             <value>103cfd1d-18b1-4790-8a0c-1e52621b0078</value>
@@ -1743,6 +1749,8 @@
             <value>b399944a-81ab-4ec5-8266-e19ba7c3c9d1</value>
             <value>1</value>
             <null/>
+            <value>1b85420c-b84c-4f29-997e-0eb674b40b79</value>
+            <value>true</value>
         </row>
     </table>
     <table name="vds_static">
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 a9775da..3e031c2 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
@@ -27,6 +27,7 @@
             new HashMap<Enum<?>, Set<String>>();
     private Set<String> permitted = new HashSet<String>();
     private Set<String> hotsetAllowedFields = new HashSet<String>();
+    private Set<String> statelessAllowedFields = new HashSet<String>();
 
     public ObjectIdentityChecker(Class<?> type) {
         identities.put(type, this);
@@ -92,6 +93,12 @@
         }
     }
 
+    public final void AddStatelessFields(String... fieldNames) {
+        for (String fieldName : fieldNames) {
+            statelessAllowedFields.add(fieldName);
+        }
+    }
+
     public final boolean IsFieldUpdatable(String name) {
         return permitted.contains(name);
     }
@@ -101,10 +108,10 @@
     }
 
     public boolean IsFieldUpdatable(Enum<?> status, String name, Object 
fieldContainer) {
-        return IsFieldUpdatable(status, name, fieldContainer, false);
+        return IsFieldUpdatable(status, name, fieldContainer, false, false);
     }
 
-    public boolean IsFieldUpdatable(Enum<?> status, String name, Object 
fieldContainer, boolean hotsetEnabled) {
+    public boolean IsFieldUpdatable(Enum<?> status, String name, Object 
fieldContainer, boolean hotsetEnabled, boolean statelessEnabled) {
         boolean returnValue = true;
         if (!IsFieldUpdatable(name)) {
             if (fieldContainer != null && container != null
@@ -114,9 +121,9 @@
                 Set<String> values = dictionary.get(status);
                 returnValue = values != null ? values.contains(name) : false;
 
-                // if field is not updateable in this status, check if hotset 
request and its an hotset allowed field
-                if (!returnValue && hotsetEnabled) {
-                    returnValue = isHotSetField(name);
+                // if field is not updateable in this status, check if it's a 
hotset \ stateless request
+                if (!returnValue && (hotsetEnabled || statelessEnabled)) {
+                    returnValue = isHotSetField(name) || 
isStatelessField(name);
                 }
             }
             if (!returnValue) {
@@ -124,6 +131,10 @@
             }
         }
         return returnValue;
+    }
+
+    private boolean isStatelessField(String name) {
+        return hotsetAllowedFields.contains(name);
     }
 
     /**
@@ -173,15 +184,15 @@
     }
 
     public final boolean IsUpdateValid(Object source, Object destination, 
Enum<?> status) {
-        return IsUpdateValid(source, destination, status, false);
+        return IsUpdateValid(source, destination, status, false, false);
     }
 
-    public final boolean IsUpdateValid(Object source, Object destination, 
Enum<?> status, boolean hotsetEnabled) {
+    public final boolean IsUpdateValid(Object source, Object destination, 
Enum<?> status, boolean hotsetEnabled, boolean statelessEnabled) {
         if (source.getClass() != destination.getClass()) {
             return false;
         }
         for (String fieldName : GetChangedFields(source, destination)) {
-            if (!IsFieldUpdatable(status, fieldName, null, hotsetEnabled)) {
+            if (!IsFieldUpdatable(status, fieldName, null, hotsetEnabled, 
statelessEnabled)) {
                 log.warn("ObjectIdentityChecker.IsUpdateValid:: Not updatable 
field '{}' was updated",
                         fieldName);
                 return false;
@@ -196,7 +207,7 @@
             return fields;
         }
         for (String fieldName : GetChangedFields(source, destination)) {
-            if (!IsFieldUpdatable(status, fieldName, null, false)) {
+            if (!IsFieldUpdatable(status, fieldName, null, false, false)) {
                 fields.add(fieldName);
             }
         }
diff --git 
a/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ObjectIdentityCheckerTest.java
 
b/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ObjectIdentityCheckerTest.java
index 0bb62a3..b75014a 100644
--- 
a/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ObjectIdentityCheckerTest.java
+++ 
b/backend/manager/modules/utils/src/test/java/org/ovirt/engine/core/utils/ObjectIdentityCheckerTest.java
@@ -54,7 +54,7 @@
     public void testHotsetUpdateableWhenHotsetRequested() {
         ObjectIdentityChecker oic = new ObjectIdentityChecker(Jedi.class);
         oic.AddHotsetFields("name");
-        assertTrue("hot set requested for hot set fields should be true", 
oic.IsFieldUpdatable(null, "name", null, true));
+        assertTrue("hot set requested for hot set fields should be true", 
oic.IsFieldUpdatable(null, "name", null, true, false));
     }
 
     @Test
@@ -62,7 +62,7 @@
         ObjectIdentityChecker oic = new ObjectIdentityChecker(Jedi.class);
         assertFalse("Should be false by default", 
oic.IsFieldUpdatable("name"));
         oic.AddHotsetFields("name");
-        assertFalse("hot set not requested should return false even if field 
is hot set", oic.IsFieldUpdatable(null, "name", null, false));
+        assertFalse("hot set not requested should return false even if field 
is hot set", oic.IsFieldUpdatable(null, "name", null, false, false));
     }
 
     @Test
@@ -70,7 +70,7 @@
         ObjectIdentityChecker oic = new ObjectIdentityChecker(Jedi.class);
         oic.AddField(VMStatus.Down, "name");
         oic.AddHotsetFields("name");
-        assertTrue("hot set requested for hot set fields should be true", 
oic.IsFieldUpdatable(VMStatus.Down, "name", null, true));
+        assertTrue("hot set requested for hot set fields should be true", 
oic.IsFieldUpdatable(VMStatus.Down, "name", null, true, false));
     }
 
     @Test
@@ -78,6 +78,6 @@
         ObjectIdentityChecker oic = new ObjectIdentityChecker(Jedi.class);
         oic.AddField(VMStatus.Down, "name");
         oic.AddHotsetFields("name");
-        assertTrue("hot set not requested field should be updateable according 
to status", oic.IsFieldUpdatable(VMStatus.Down, "name", null, false));
+        assertTrue("hot set not requested field should be updateable according 
to status", oic.IsFieldUpdatable(VMStatus.Down, "name", null, false, false));
     }
 }
diff --git 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
index 1ca5952..94d04f6 100644
--- 
a/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
+++ 
b/frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
@@ -676,6 +676,9 @@
     @DefaultStringValue("Cannot ${action} ${type}. The relevant Template 
doesn't exist.")
     String ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST();
 
+    @DefaultStringValue("Cannot ${action} ${type}. The requested template 
doesn't belong to the same base template as the original template.")
+    String ACTION_TYPE_FAILED_TEMPLATE_IS_ON_DIFFERENT_CHAIN();
+
     @DefaultStringValue("Cannot ${action} ${type}. The relevant Cluster 
doesn't exist.")
     String ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY();
 
diff --git 
a/frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
 
b/frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
index 23c3cde..d6418a3 100644
--- 
a/frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
+++ 
b/frontend/webadmin/modules/userportal-gwtp/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
@@ -232,6 +232,7 @@
 ACTION_TYPE_FAILED_PROBLEM_WITH_CANDIDATE_INFO=Cannot ${action} ${type}. 
Failed to get data for Import operation.\n\
 - Check your Import Domain.
 ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST=Cannot ${action} ${type}. The 
relevant Template doesn't exist.
+ACTION_TYPE_FAILED_TEMPLATE_IS_ON_DIFFERENT_CHAIN=Cannot ${action} ${type}. 
The requested template doesn't belong to the same base template as the original 
template.
 ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY=Cannot ${action} ${type}. The 
relevant Cluster doesn't exist.
 ACTION_TYPE_FAILED_TEMPLATE_VERSION_CANNOT_BE_BASE_TEMPLATE=Cannot ${action} 
${type}. Only the first template version can be selected as the base template.
 ACTION_TYPE_FAILED_TEMPLATE_CANNOT_BE_CREATED_WITH_EMPTY_DISK_ALIAS=Cannot 
${action} ${type} with an empty disk alias.
diff --git 
a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
 
b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
index a102ceb..08b7877 100644
--- 
a/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
+++ 
b/frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
@@ -246,6 +246,7 @@
 ACTION_TYPE_FAILED_PROBLEM_WITH_CANDIDATE_INFO=Cannot ${action} ${type}. 
Failed to get data for Import operation.\n\
 - Check your Import Domain.
 ACTION_TYPE_FAILED_TEMPLATE_DOES_NOT_EXIST=Cannot ${action} ${type}. The 
relevant Template doesn't exist.
+ACTION_TYPE_FAILED_TEMPLATE_IS_ON_DIFFERENT_CHAIN=Cannot ${action} ${type}. 
The requested template doesn't belong to the same base template as the original 
template.
 ACTION_TYPE_FAILED_CLUSTER_CAN_NOT_BE_EMPTY=Cannot ${action} ${type}. The 
relevant Cluster doesn't exist.
 ACTION_TYPE_FAILED_TEMPLATE_VERSION_CANNOT_BE_BASE_TEMPLATE=Cannot ${action} 
${type}. Only the first template version can be selected as the base template.
 ACTION_TYPE_FAILED_TEMPLATE_CANNOT_BE_CREATED_WITH_EMPTY_DISK_ALIAS=Cannot 
${action} ${type} with an empty disk alias.
diff --git a/packaging/dbscripts/create_views.sql 
b/packaging/dbscripts/create_views.sql
index 0224f22..aa7e43c 100644
--- a/packaging/dbscripts/create_views.sql
+++ b/packaging/dbscripts/create_views.sql
@@ -613,7 +613,9 @@
 vm_pool_map.vm_guid as vm_guid,
 vm_pool_map.vm_pool_id as vm_pool_id,
 vm_pools.vm_pool_name as vm_pool_name,
-vm_pools.spice_proxy as vm_pool_spice_proxy
+vm_pools.spice_proxy as vm_pool_spice_proxy,
+vm_pools.vm_pool_vmt_guid as vm_pool_vmt_guid,
+vm_pools.vm_pool_is_latest as vm_pool_is_latest
 from vm_pool_map
 INNER JOIN vm_pools
 ON vm_pool_map.vm_pool_id = vm_pools.vm_pool_id;
@@ -706,7 +708,7 @@
                       vm_dynamic.guest_last_login_time as 
guest_last_login_time, vm_dynamic.guest_last_logout_time as 
guest_last_logout_time, vm_dynamic.guest_os as guest_os,
                       vm_dynamic.console_user_id as console_user_id, 
vm_dynamic.guest_agent_nics_hash as guest_agent_nics_hash,
                       vm_dynamic.run_on_vds as run_on_vds, 
vm_dynamic.migrating_to_vds as migrating_to_vds, vm_dynamic.app_list as 
app_list, vm_dynamic.display as display, vm_dynamic.hibernation_vol_handle as 
hibernation_vol_handle,
-                      vm_pool_map_view.vm_pool_name as vm_pool_name, 
vm_pool_map_view.vm_pool_id as vm_pool_id, vm_static.vm_guid as vm_guid, 
vm_static.num_of_monitors as num_of_monitors, vm_static.single_qxl_pci as 
single_qxl_pci, vm_static.allow_console_reconnect as allow_console_reconnect, 
vm_static.is_initialized as is_initialized,
+                      vm_pool_map_view.vm_pool_name as vm_pool_name, 
vm_pool_map_view.vm_pool_id as vm_pool_id, vm_pool_map_view.vm_pool_vmt_guid as 
vm_pool_vmt_guid, vm_pool_map_view.vm_pool_is_latest as vm_pool_is_latest, 
vm_static.vm_guid as vm_guid, vm_static.num_of_monitors as num_of_monitors, 
vm_static.single_qxl_pci as single_qxl_pci, vm_static.allow_console_reconnect 
as allow_console_reconnect, vm_static.is_initialized as is_initialized,
                       vm_static.num_of_sockets as num_of_sockets, 
vm_static.cpu_per_socket as cpu_per_socket, vm_static.usb_policy as usb_policy, 
vm_dynamic.acpi_enable as acpi_enable, vm_dynamic.session as session,
                       vm_static.num_of_sockets*vm_static.cpu_per_socket as 
num_of_cpus,
                       vm_static.quota_id as quota_id, quota.quota_name as 
quota_name, storage_pool.quota_enforcement_type as quota_enforcement_type,
@@ -763,7 +765,7 @@
             vms.vm_host, vms.vmt_num_of_sockets * vms.vmt_cpu_per_socket AS 
vmt_num_of_cpus, vms.vm_pid,
             vms.last_start_time, vms.last_stop_time, vms.guest_cur_user_name, 
vms.console_cur_user_name, vms.guest_last_login_time, vms.console_user_id,
             vms.guest_last_logout_time, vms.guest_os, vms.run_on_vds, 
vms.migrating_to_vds, vms.app_list, vms.display,
-            vms.hibernation_vol_handle, vms.vm_pool_name, vms.vm_pool_id, 
vms.vm_guid, vms.num_of_monitors, vms.single_qxl_pci,
+            vms.hibernation_vol_handle, vms.vm_pool_name, vms.vm_pool_id, 
vms.vm_pool_vmt_guid, vms.vm_pool_is_latest, vms.vm_guid, vms.num_of_monitors, 
vms.single_qxl_pci,
             vms.allow_console_reconnect,
             vms.is_initialized, vms.num_of_sockets, vms.cpu_per_socket, 
vms.usb_policy, vms.acpi_enable,
             vms.session, vms.num_of_sockets * vms.cpu_per_socket AS 
num_of_cpus, vms.display_ip, vms.display_type,
@@ -984,7 +986,7 @@
 
 CREATE OR REPLACE VIEW vm_pools_view AS
  SELECT vm_pools.vm_pool_id, vm_pools.vm_pool_name, 
vm_pools.vm_pool_description, vm_pools.vm_pool_comment, vm_pools.vm_pool_type, 
vm_pools.parameters, vm_pools.prestarted_vms, vm_pools.vds_group_id, 
vds_groups.name AS vds_group_name, vds_groups.architecture AS architecture, 
storage_pool.name as storage_pool_name, storage_pool.id as storage_pool_id, 
vm_pools.max_assigned_vms_per_user as max_assigned_vms_per_user,
- vm_pools.spice_proxy as spice_proxy
+ vm_pools.spice_proxy as spice_proxy, vm_pools.vm_pool_vmt_guid as 
vm_pool_vmt_guid, vm_pools.vm_pool_is_latest as vm_pool_is_latest
    FROM vm_pools
    JOIN vds_groups ON vm_pools.vds_group_id = vds_groups.vds_group_id
    LEFT JOIN storage_pool ON storage_pool.id = vds_groups.storage_pool_id;
@@ -992,7 +994,7 @@
 
 
 CREATE OR REPLACE VIEW vm_pools_full_view AS
- SELECT vmp.vm_pool_id, vmp.vm_pool_name, vmp.vm_pool_description, 
vmp.vm_pool_comment, vmp.vm_pool_type, vmp.parameters, vmp.prestarted_vms, 
vmp.vds_group_id, vmp.vds_group_name, vmp.architecture, 
vmp.max_assigned_vms_per_user, vmp.spice_proxy as spice_proxy, ( SELECT 
count(vm_pool_map.vm_pool_id) AS expr1
+ SELECT vmp.vm_pool_id, vmp.vm_pool_name, vmp.vm_pool_description, 
vmp.vm_pool_comment, vmp.vm_pool_type, vmp.parameters, vmp.prestarted_vms, 
vmp.vds_group_id, vmp.vds_group_name, vmp.architecture, 
vmp.max_assigned_vms_per_user, vmp.spice_proxy as spice_proxy, 
vmp.vm_pool_vmt_guid as vm_pool_vmt_guid, vmp.vm_pool_is_latest as 
vm_pool_is_latest, ( SELECT count(vm_pool_map.vm_pool_id) AS expr1
            FROM vm_pools_view v1
       LEFT JOIN vm_pool_map ON v1.vm_pool_id = vm_pool_map.vm_pool_id AND 
v1.vm_pool_id = vmp.vm_pool_id) AS assigned_vm_count, ( SELECT 
count(v2.vm_pool_id) AS expr1
            FROM vm_pools v2
diff --git a/packaging/dbscripts/upgrade/03_06_0700_add_template_id_to_pool.sql 
b/packaging/dbscripts/upgrade/03_06_0700_add_template_id_to_pool.sql
new file mode 100644
index 0000000..9c91c94
--- /dev/null
+++ b/packaging/dbscripts/upgrade/03_06_0700_add_template_id_to_pool.sql
@@ -0,0 +1,7 @@
+SELECT fn_db_add_column('vm_pools', 'vm_pool_vmt_guid', 'uuid');
+SELECT fn_db_add_column('vm_pools', 'vm_pool_is_latest', 'boolean');
+
+-- Updating pool with template-id based on vm_static data (at this point it's 
still safe).
+-- From this point on different VMs in a pool may have different template 
versions (in a NEXT-RUN use case).
+UPDATE vm_pools SET vm_pool_vmt_guid=(SELECT vmt_guid FROM vm_static INNER 
JOIN vm_pool_map ON vm_static.vm_guid=vm_pool_map.vm_guid WHERE 
vm_pool_map.vm_pool_id=vm_pools.vm_pool_id LIMIT 1);
+UPDATE vm_pools SET vm_pool_is_latest=(SELECT CASE WHEN 
template_version_number IS NULL THEN TRUE ELSE FALSE END AS vm_is_latest FROM 
vm_static INNER JOIN vm_pool_map ON vm_static.vm_guid=vm_pool_map.vm_guid WHERE 
vm_pool_map.vm_pool_id=vm_pools.vm_pool_id LIMIT 1);
diff --git a/packaging/dbscripts/vm_pools_sp.sql 
b/packaging/dbscripts/vm_pools_sp.sql
index c59ae00..eced199 100644
--- a/packaging/dbscripts/vm_pools_sp.sql
+++ b/packaging/dbscripts/vm_pools_sp.sql
@@ -12,12 +12,14 @@
  v_prestarted_vms INTEGER,
  v_vds_group_id UUID,
  v_max_assigned_vms_per_user SMALLINT,
- v_spice_proxy VARCHAR(255))
+ v_spice_proxy VARCHAR(255),
+ v_vm_pool_vmt_guid UUID,
+ v_vm_pool_is_latest BOOLEAN)
 RETURNS VOID
    AS $procedure$
 BEGIN
-      INSERT INTO vm_pools(vm_pool_id,vm_pool_description, vm_pool_comment, 
vm_pool_name, vm_pool_type,parameters, prestarted_vms, vds_group_id, 
max_assigned_vms_per_user, spice_proxy)
-      VALUES(v_vm_pool_id,v_vm_pool_description, v_vm_pool_comment, 
v_vm_pool_name,v_vm_pool_type,v_parameters, v_prestarted_vms, v_vds_group_id, 
v_max_assigned_vms_per_user, v_spice_proxy);
+      INSERT INTO vm_pools(vm_pool_id,vm_pool_description, vm_pool_comment, 
vm_pool_name, vm_pool_type,parameters, prestarted_vms, vds_group_id, 
max_assigned_vms_per_user, spice_proxy, vm_pool_vmt_guid, vm_pool_is_latest)
+      VALUES(v_vm_pool_id,v_vm_pool_description, v_vm_pool_comment, 
v_vm_pool_name,v_vm_pool_type,v_parameters, v_prestarted_vms, v_vds_group_id, 
v_max_assigned_vms_per_user, v_spice_proxy, v_vm_pool_vmt_guid, 
v_vm_pool_is_latest);
 END; $procedure$
 LANGUAGE plpgsql;
 
@@ -34,7 +36,9 @@
  v_prestarted_vms INTEGER,
  v_vds_group_id UUID,
  v_max_assigned_vms_per_user SMALLINT,
- v_spice_proxy VARCHAR(255))
+ v_spice_proxy VARCHAR(255),
+ v_vm_pool_vmt_guid UUID,
+ v_vm_pool_is_latest BOOLEAN)
 RETURNS VOID
 
        --The [vm_pools] table doesn't have a timestamp column. Optimistic 
concurrency logic cannot be generated
@@ -43,7 +47,8 @@
       UPDATE vm_pools
       SET vm_pool_description = v_vm_pool_description, vm_pool_comment = 
v_vm_pool_comment, vm_pool_name = v_vm_pool_name,
       vm_pool_type = v_vm_pool_type,parameters = v_parameters, prestarted_vms 
= v_prestarted_vms, vds_group_id = v_vds_group_id,
-      max_assigned_vms_per_user = v_max_assigned_vms_per_user, spice_proxy = 
v_spice_proxy
+      max_assigned_vms_per_user = v_max_assigned_vms_per_user, spice_proxy = 
v_spice_proxy, vm_pool_vmt_guid=v_vm_pool_vmt_guid,
+      vm_pool_is_latest = v_vm_pool_is_latest
       WHERE vm_pool_id = v_vm_pool_id;
 END; $procedure$
 LANGUAGE plpgsql;
@@ -73,7 +78,7 @@
 
 
 DROP TYPE IF EXISTS GetAllFromVm_pools_rs CASCADE;
-Create type GetAllFromVm_pools_rs AS (vm_pool_id UUID, assigned_vm_count 
INTEGER, vm_running_count INTEGER, vm_pool_description VARCHAR(4000), 
vm_pool_comment text, vm_pool_name VARCHAR(255), vm_pool_type INTEGER, 
parameters VARCHAR(200), prestarted_vms INTEGER, vds_group_id UUID, 
vds_group_name VARCHAR(40), max_assigned_vms_per_user SMALLINT, spice_proxy 
VARCHAR(255));
+Create type GetAllFromVm_pools_rs AS (vm_pool_id UUID, assigned_vm_count 
INTEGER, vm_running_count INTEGER, vm_pool_description VARCHAR(4000), 
vm_pool_comment text, vm_pool_name VARCHAR(255), vm_pool_type INTEGER, 
parameters VARCHAR(200), prestarted_vms INTEGER, vds_group_id UUID, 
vds_group_name VARCHAR(40), max_assigned_vms_per_user SMALLINT, spice_proxy 
VARCHAR(255), vm_pool_vmt_guid UUID, vm_pool_is_latest BOOLEAN);
 Create or replace FUNCTION GetAllFromVm_pools() RETURNS SETOF 
GetAllFromVm_pools_rs
    AS $procedure$
 BEGIN
@@ -146,7 +151,9 @@
             vds_group_id UUID,
             vds_group_name VARCHAR(40),
             max_assigned_vms_per_user SMALLINT,
-            spice_proxy VARCHAR(255)
+            spice_proxy VARCHAR(255),
+            vm_pool_vmt_guid UUID,
+            vm_pool_is_latest BOOLEAN
          ) WITH OIDS;
          exception when others then
             truncate table tt_VM_POOL_RESULT;
@@ -163,10 +170,12 @@
             vds_group_id,
             vds_group_name,
             max_assigned_vms_per_user,
-            spice_proxy)
+            spice_proxy,
+            vm_pool_vmt_guid,
+            vm_pool_is_latest)
       select ppr.vm_pool_id, ppr.assigned_vm_count, ppr.vm_running_count,
                                 p.vm_pool_description, p.vm_pool_comment, 
p.vm_pool_name, p.vm_pool_type, p.parameters, p.prestarted_vms,
-                                        p.vds_group_id, p.vds_group_name, 
p.max_assigned_vms_per_user, p.spice_proxy
+                                        p.vds_group_id, p.vds_group_name, 
p.max_assigned_vms_per_user, p.spice_proxy, p.vm_pool_vmt_guid, 
p.vm_pool_is_latest
       from tt_VM_POOL_PRERESULT ppr
       inner join vm_pools_view p on ppr.vm_pool_id = p.vm_pool_id;
       RETURN QUERY select *
diff --git a/packaging/dbscripts/vm_templates_sp.sql 
b/packaging/dbscripts/vm_templates_sp.sql
index 8e8d26f..b454758 100644
--- a/packaging/dbscripts/vm_templates_sp.sql
+++ b/packaging/dbscripts/vm_templates_sp.sql
@@ -550,7 +550,8 @@
 BEGIN
    RETURN QUERY SELECT *
    from vm_templates_view
-   where base_template_id = v_base_template_id and vmt_guid != 
v_base_template_id;
+   where base_template_id = v_base_template_id and vmt_guid != 
v_base_template_id
+   order by template_version_number desc;
 END; $procedure$
 LANGUAGE plpgsql;
 
diff --git a/packaging/dbscripts/vms_sp.sql b/packaging/dbscripts/vms_sp.sql
index 74ef317..dcbce0e 100644
--- a/packaging/dbscripts/vms_sp.sql
+++ b/packaging/dbscripts/vms_sp.sql
@@ -896,6 +896,19 @@
 END; $procedure$
 LANGUAGE plpgsql;
 
+Create or replace FUNCTION GetPoolVmsFromVms(v_user_id UUID, v_pool_id UUID, 
v_is_filtered boolean) RETURNS SETOF vms STABLE
+AS $procedure$
+BEGIN
+RETURN QUERY SELECT DISTINCT vms.*
+   FROM vms
+   WHERE vm_pool_id = v_pool_id AND
+         (NOT v_is_filtered OR EXISTS (SELECT 1
+                                       FROM user_vm_permissions_view
+                                       WHERE user_id = v_user_id AND entity_id 
= vm_guid))
+   ORDER BY vm_guid;
+END; $procedure$
+LANGUAGE plpgsql;
+
 
 
 


-- 
To view, visit http://gerrit.ovirt.org/36507
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib106016955c702bc28f9347d828c4602e47bd233
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Eldan Shachar <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to