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