Tomer Saban has uploaded a new change for review.

Change subject: core:Added affinity Group collision validation.
......................................................................

Added affinity Group collision test to canDoAction

CRUD Affinity Group Command's validateParameters() now have a test
that checks for affinity rules collision, To prevent the user from
creating problematic Affinity Rules from the first place.

Change-Id: I56c483023ed14e238c8a67ec0890812158ecd0b2
Signed-off-by: Tomer Saban <tsa...@redhat.com>
---
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/commands/AffinityGroupCRUDCommand.java
M 
backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/errors/VdcBllMessages.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
5 files changed, 133 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/05/41805/3

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/commands/AffinityGroupCRUDCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/commands/AffinityGroupCRUDCommand.java
index ad0b157..c933515 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/commands/AffinityGroupCRUDCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/commands/AffinityGroupCRUDCommand.java
@@ -9,12 +9,14 @@
 import org.ovirt.engine.core.bll.CommandBase;
 import org.ovirt.engine.core.bll.utils.PermissionSubject;
 import org.ovirt.engine.core.common.VdcObjectType;
+import org.ovirt.engine.core.common.businessentities.VM;
 import org.ovirt.engine.core.common.businessentities.VmStatic;
 import org.ovirt.engine.core.common.errors.VdcBllMessages;
 import org.ovirt.engine.core.common.scheduling.AffinityGroup;
 import 
org.ovirt.engine.core.common.scheduling.parameters.AffinityGroupCRUDParameters;
 import org.ovirt.engine.core.compat.Guid;
 import org.ovirt.engine.core.dal.dbbroker.DbFacade;
+import org.ovirt.engine.core.dao.VmDAO;
 import org.ovirt.engine.core.dao.scheduling.AffinityGroupDao;
 
 public abstract class AffinityGroupCRUDCommand extends 
CommandBase<AffinityGroupCRUDParameters> {
@@ -33,6 +35,7 @@
         if (getVdsGroup() == null) {
             return 
failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_INVALID_CLUSTER_FOR_AFFINITY_GROUP);
         }
+
         if (getParameters().getAffinityGroup().getEntityIds() != null) {
             VmStatic vmStatic = null;
             Set<Guid> vmSet = new HashSet<>();
@@ -51,9 +54,133 @@
                 }
             }
         }
+
+        return hasAffinityCollisions(getParameters());
+    }
+
+    private Boolean hasAffinityCollisions(AffinityGroupCRUDParameters 
parameters) {
+        List<AffinityGroup> affinity_groups = 
getAllAffinityGroups(parameters.getAffinityGroup().getClusterId());
+        affinity_groups.add(parameters.getAffinityGroup());
+        return getUnifiedAffinityGroups(affinity_groups);
+    }
+
+    private List<AffinityGroup> getAllAffinityGroups(Guid clusterId) {
+        return 
DbFacade.getInstance().getAffinityGroupDao().getAllAffinityGroupsByClusterId(clusterId);
+    }
+
+    /**
+     # UAG = {{vm} for each vm}
+     # For each (+) affinity group(Sorted by group id):
+     ## unify VMs from the group in UAG(Sorted by vm id).
+     ## For each (-) affinity group(Sorted by group id):
+     ### For each group in UAG(Sorted by first vm uuid):
+     #### if size of the intersection of group from UAG and the negative group 
is > 1:
+     ##### throw exception “Affinity group contradiction detected” (With 
associated groups).
+
+     */
+    private Boolean getUnifiedAffinityGroups(List<AffinityGroup> 
affinityGroups) {
+        Set<Set<VM>> uag = new HashSet();
+
+        VmDAO vm_dao = DbFacade.getInstance().getVmDao();
+
+        //uag = {{vm} for each vm}
+        for(AffinityGroup ag: affinityGroups) {
+            for(Guid id : ag.getEntityIds()) {
+                Set<VM> temp = new HashSet<VM>();
+                temp.add(vm_dao.get(id));
+                uag.add(temp);
+            }
+        }
+
+        //# For each (+) affinity group(Sorted by group id):
+        //## unify VMs from the group in UAG(Sorted by vm id).
+        for(AffinityGroup ag : affinityGroups) {
+            if(ag.isPositive()) {
+                Set<VM> vm_set;
+                vm_set = new HashSet<VM>();
+
+                for(Guid id : ag.getEntityIds()) {
+                    Set<VM> vm_group = getVmGroupByGuid(uag, vm_dao.get(id));
+                    vm_set.addAll(vm_group);
+                }
+
+                uag.add(vm_set);
+            }
+        }
+
+        //Checking negative affinity group collisions
+        for(AffinityGroup ag : affinityGroups) {
+            if(ag.isPositive()) {
+                continue;
+            }
+
+            Set<VM> vm_set = createVmsSetFromAffinityGroup(vm_dao, ag);
+            for (Set<VM> positive_group : uag) {
+                Set<VM> intersection = new HashSet<VM>(positive_group);
+
+                intersection.retainAll(vm_set);
+
+                if(intersection.size() > 1) {
+                    return 
failCanDoAction(VdcBllMessages.ACTION_TYPE_FAILED_AFFINITY_RULES_COLLISION,
+                            String.format("$UAG %s", 
positive_group.toString()),
+                            String.format("$negativeAR %s", 
vm_set.toString()));
+                }
+            }
+        }
+
+        //Adding to UAG VMs that are not in it's Sets yet.
+        for(AffinityGroup ag : affinityGroups) {
+            if(ag.isPositive()) {
+                continue;
+            }
+
+            //Getting the VMs which are not in group in UAG.
+            Set<VM> vm_set = createVmsSetFromAffinityGroup(vm_dao, ag);
+            for (Set<VM> positive_group : uag) {
+                Set<VM> intersection = new HashSet<VM>(positive_group);
+
+                intersection.retainAll(vm_set);
+
+                for(VM vm : intersection) {
+                    vm_set.remove(vm);
+                }
+            }
+
+            //Adding for each VM a set with it to the uag.
+            for(VM vm : vm_set) {
+                Set<VM> new_set = new HashSet<VM>();
+                new_set.add(vm);
+                uag.add(new_set);
+            }
+        }
+
+        //Sorting affinityGroups by group id.
         return true;
     }
 
+    private Set<VM> getVmGroupByGuid(Set<Set<VM>> uag, VM vm) {
+        for(Set<VM> s : uag) {
+            if(s.contains(vm)) {
+                return s;
+            }
+        }
+
+        log.error("Impossible situation happened. No vm group found for a vm 
during UnifiedAffinityGroups creation(Although all VMs should be added at the 
start).\n");
+        return null; //Not really possible because we added all VMs at the 
start.
+    }
+
+    private Set<VM> createVmsSetFromAffinityGroup(VmDAO vm_dao, AffinityGroup 
ag) {
+        Set<VM> vm_set;
+        VM vm;
+        vm_set = new HashSet<VM>();
+
+        for(Guid id : ag.getEntityIds()) {
+            vm = vm_dao.get(id);
+            vm_set.add(vm);
+        }
+        return vm_set;
+    }
+
     protected AffinityGroup getAffinityGroup() {
         if (affinityGroup == null) {
             affinityGroup = 
getAffinityGroupDao().get(getParameters().getAffinityGroupId());
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 38902b9..23e9157 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
@@ -1200,6 +1200,7 @@
     ACTION_TYPE_FAILED_POSITIVE_AFFINITY_GROUP(ErrorType.CONFLICT),
     ACTION_TYPE_FAILED_NEGATIVE_AFFINITY_GROUP(ErrorType.CONFLICT),
     
ACTION_TYPE_FAILED_MIX_POSITIVE_NEGATIVE_AFFINITY_GROUP(ErrorType.CONFLICT),
+    ACTION_TYPE_FAILED_AFFINITY_RULES_COLLISION(ErrorType.CONFLICT),
 
     // Iscsi bonds
     ISCSI_BOND_WITH_SAME_NAME_EXIST_IN_DATA_CENTER(ErrorType.CONFLICT),
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 ab111a8..d171b76 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
@@ -3686,6 +3686,9 @@
     @DefaultStringValue("VM is associated with both positive and negative 
Affinity Groups, please reconfigure VM's affinity groups")
     String ACTION_TYPE_FAILED_MIX_POSITIVE_NEGATIVE_AFFINITY_GROUP();
 
+    @DefaultStringValue("Affinity Group contradiction detected between 
UAG:\n${UAG}\nand negative Affinity Group:\n${negativeAR}")
+    String ACTION_TYPE_FAILED_AFFINITY_RULES_COLLISION();
+
     @DefaultStringValue("iSCSI bond name must not exceed 50 characters")
     String VALIDATION_ISCSI_BOND_NAME_MAX();
 
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 bd8e233..e387d8a 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
@@ -1050,6 +1050,7 @@
 ACTION_TYPE_FAILED_POSITIVE_AFFINITY_GROUP=VM is associated with a positive 
Affinity Group (${affinityGroupName}) and require to run on the same Host 
(${hostName}) as the other group VMs
 ACTION_TYPE_FAILED_NEGATIVE_AFFINITY_GROUP=VM is associated with a negative 
Affinity Group and require to run on separate Host, which doesn't run other 
group VMs
 ACTION_TYPE_FAILED_MIX_POSITIVE_NEGATIVE_AFFINITY_GROUP=VM is associated with 
both positive and negative Affinity Groups, please contact your system 
administrator
+ACTION_TYPE_FAILED_AFFINITY_RULES_COLLISION=Affinity Group contradiction 
detected between UAG:\n${UAG}\nand negative Affinity Group:\n${negativeAR}
 
 # Iscsi Bond
 VALIDATION_ISCSI_BOND_NAME_MAX=iSCSI bond name must not exceed 50 characters
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 5d036ad..264fd47 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
@@ -1320,6 +1320,7 @@
 ACTION_TYPE_FAILED_POSITIVE_AFFINITY_GROUP=VM is associated with a positive 
Affinity Group (${affinityGroupName}) and require to run on the same Host 
(${hostName}) as the other group VMs
 ACTION_TYPE_FAILED_NEGATIVE_AFFINITY_GROUP=VM is associated with a negative 
Affinity Group and require to run on separte Host, which doesn't run the other 
group VMs
 ACTION_TYPE_FAILED_MIX_POSITIVE_NEGATIVE_AFFINITY_GROUP=VM is associated with 
both positive and negative Affinity Groups, please reconfigure VM's affinity 
groups
+ACTION_TYPE_FAILED_AFFINITY_RULES_COLLISION=Affinity Group contradiction 
detected between UAG:\n${UAG}\nand negative Affinity Group:\n${negativeAR}
 
 # Iscsi Bond
 VALIDATION_ISCSI_BOND_NAME_MAX=iSCSI bond name must not exceed 50 characters


-- 
To view, visit https://gerrit.ovirt.org/41805
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I56c483023ed14e238c8a67ec0890812158ecd0b2
Gerrit-PatchSet: 3
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Tomer Saban <tsa...@redhat.com>
Gerrit-Reviewer: Gilad Chaplik <gchap...@redhat.com>
Gerrit-Reviewer: Jenkins CI
Gerrit-Reviewer: Martin Sivák <msi...@redhat.com>
Gerrit-Reviewer: Roy Golan <rgo...@redhat.com>
Gerrit-Reviewer: Tomer Saban <tsa...@redhat.com>
Gerrit-Reviewer: automat...@ovirt.org
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to