Gilad Chaplik has uploaded a new change for review.

Change subject: core: prevent maintenance a host with hard affinity
......................................................................

core: prevent maintenance a host with hard affinity

Maintenance a host can break the affinity rule of its running vm
The user should be aware of it, and manually handle it:
soften the affinity rule or migrate the VMs.

Change-Id: Idd93ddca562bf739b2cd423e907be1b6da861735
Bug-Url: https://bugzilla.redhat.com/1084794
Signed-off-by: Gilad Chaplik <[email protected]>
---
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MaintenanceNumberOfVdssCommand.java
M 
backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/VmAffinityFilterPolicyUnit.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/scheduling/AffinityGroupDao.java
M 
backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDaoImpl.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/AffinityGroupDaoTest.java
M 
frontend/webadmin/modules/frontend/src/main/java/org/ovirt/engine/ui/frontend/AppErrors.java
M 
frontend/webadmin/modules/webadmin/src/main/resources/org/ovirt/engine/ui/frontend/AppErrors.properties
M packaging/dbscripts/affinity_groups_sp.sql
10 files changed, 78 insertions(+), 11 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/60/34060/1

diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MaintenanceNumberOfVdssCommand.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MaintenanceNumberOfVdssCommand.java
index 9ce78cd..cb857a3 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MaintenanceNumberOfVdssCommand.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/MaintenanceNumberOfVdssCommand.java
@@ -1,7 +1,5 @@
 package org.ovirt.engine.core.bll;
 
-import org.ovirt.engine.core.bll.context.CommandContext;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -12,6 +10,7 @@
 import java.util.Set;
 
 import org.apache.commons.lang.StringUtils;
+import org.ovirt.engine.core.bll.context.CommandContext;
 import org.ovirt.engine.core.bll.job.ExecutionHandler;
 import org.ovirt.engine.core.bll.network.cluster.NetworkClusterHelper;
 import org.ovirt.engine.core.bll.utils.PermissionSubject;
@@ -31,11 +30,13 @@
 import org.ovirt.engine.core.common.businessentities.network.Network;
 import org.ovirt.engine.core.common.errors.VdcBllMessages;
 import org.ovirt.engine.core.common.locks.LockingGroup;
+import org.ovirt.engine.core.common.scheduling.AffinityGroup;
 import org.ovirt.engine.core.common.utils.Pair;
 import 
org.ovirt.engine.core.common.vdscommands.SetVdsStatusVDSCommandParameters;
 import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
 import org.ovirt.engine.core.compat.Guid;
 import org.ovirt.engine.core.dal.dbbroker.DbFacade;
+import org.ovirt.engine.core.utils.ReplacementUtils;
 import org.ovirt.engine.core.vdsbroker.vdsbroker.CancelMigrationVDSParameters;
 
 @InternalCommandAttribute
@@ -246,6 +247,24 @@
                                 
getAsyncTaskDao().getAsyncTaskIdsByStoragePoolId(vds.getStoragePoolId()).size() 
> 0) {
                             
addCanDoActionMessage(VdcBllMessages.VDS_CANNOT_MAINTENANCE_SPM_WITH_RUNNING_TASKS);
                             result = false;
+                        } else {
+                            if (!vms.isEmpty()) {
+                                List<AffinityGroup> affinityGroups =
+                                        getDbFacade().getAffinityGroupDao()
+                                                
.getEnforcingAffinityGroupsByRunningVmsOnVdsId(vdsId);
+                                if (!affinityGroups.isEmpty()) {
+                                    List<Object> items = new ArrayList<>();
+                                    for (AffinityGroup affinityGroup : 
affinityGroups) {
+                                        items.add(String.format("%1$s (%2$s)",
+                                                affinityGroup.getName(),
+                                                
StringUtils.join(affinityGroup.getEntityNames(), " ,").replaceAll(" ,$", "")));
+                                    }
+                                    
addCanDoActionMessage(VdcBllMessages.VDS_CANNOT_MAINTENANCE_VDS_HAS_AFFINITY_VMS);
+                                    getReturnValue().getCanDoActionMessages()
+                                            
.addAll(ReplacementUtils.replaceWith("AFFINITY_GROUPS_VMS", items));
+                                    result = false;
+                                }
+                            }
                         }
                     }
                 }
diff --git 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/VmAffinityFilterPolicyUnit.java
 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/VmAffinityFilterPolicyUnit.java
index 79f7952..5b2851e 100644
--- 
a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/VmAffinityFilterPolicyUnit.java
+++ 
b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/VmAffinityFilterPolicyUnit.java
@@ -9,7 +9,6 @@
 
 import org.ovirt.engine.core.bll.scheduling.PolicyUnitImpl;
 import org.ovirt.engine.core.common.businessentities.VDS;
-import org.ovirt.engine.core.common.businessentities.VDSStatus;
 import org.ovirt.engine.core.common.businessentities.VM;
 import org.ovirt.engine.core.common.errors.VdcBllMessages;
 import org.ovirt.engine.core.common.scheduling.AffinityGroup;
@@ -71,19 +70,12 @@
         for (VM iter : getVmDao().getAllRunningByCluster(vm.getVdsGroupId())) {
             runningVMsMap.put(iter.getId(), iter);
         }
-        Map<Guid, VDS> hostMap = new HashMap<>();
-        for (VDS host : hosts) {
-            hostMap.put(host.getId(), host);
-        }
 
         Set<Guid> acceptableHosts = new HashSet<>();
         // Group all hosts for VMs with positive affinity
         for (Guid id : allVmIdsPositive) {
             VM runVm = runningVMsMap.get(id);
-            if (runVm != null && runVm.getRunOnVds() != null && 
hostMap.get(runVm.getRunOnVds()) != null
-                    // when a host preparing for maintenance, we should ignore 
the positive affinity (without that we
-                    // can't migrate).
-                    && hostMap.get(runVm.getRunOnVds()).getStatus() != 
VDSStatus.PreparingForMaintenance) {
+            if (runVm != null && runVm.getRunOnVds() != null) {
                 acceptableHosts.add(runVm.getRunOnVds());
             }
         }
@@ -97,6 +89,11 @@
             }
         }
 
+        Map<Guid, VDS> hostMap = new HashMap<>();
+        for (VDS host : hosts) {
+            hostMap.put(host.getId(), host);
+        }
+
         // Compute the intersection of hosts with positive and negative 
affinity and report that
         // contradicting rules to the log
         unacceptableHosts.retainAll(acceptableHosts);
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 750c860..f592ee9 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
@@ -306,6 +306,7 @@
     VDS_CANNOT_MAINTENANCE_SPM_WITH_RUNNING_TASKS(ErrorType.CONFLICT),
     VDS_CANNOT_MAINTENANCE_SPM_CONTENDING(ErrorType.CONFLICT),
     VDS_CANNOT_MAINTENANCE_VDS_IS_IN_MAINTENANCE(ErrorType.CONFLICT),
+    VDS_CANNOT_MAINTENANCE_VDS_HAS_AFFINITY_VMS(ErrorType.CONFLICT),
     VDS_NO_UUID(ErrorType.CONFLICT),
     VDS_ALREADY_UP(ErrorType.CONFLICT),
     VDS_NON_RESPONSIVE(ErrorType.CONFLICT),
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDao.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDao.java
index b10a636..b9bfbb9 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDao.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDao.java
@@ -37,4 +37,11 @@
      * @param vmId
      */
     void removeVmFromAffinityGroups(Guid vmId);
+
+    /**
+     * get all enforcing affinity groups containing VMs running on given host
+     *
+     * @param vdsId
+     */
+    List<AffinityGroup> getEnforcingAffinityGroupsByRunningVmsOnVdsId(Guid 
vdsId);
 }
diff --git 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDaoImpl.java
 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDaoImpl.java
index 58b237e..260178c 100644
--- 
a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDaoImpl.java
+++ 
b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/scheduling/AffinityGroupDaoImpl.java
@@ -61,6 +61,13 @@
     }
 
     @Override
+    public List<AffinityGroup> 
getEnforcingAffinityGroupsByRunningVmsOnVdsId(Guid vdsId) {
+        return 
getCallsHandler().executeReadList("getEnforcingAffinityGroupsByRunningVmsOnVdsId",
+                createEntityRowMapper(),
+                getCustomMapSqlParameterSource().addValue("vds_id", vdsId));
+    }
+
+    @Override
     protected MapSqlParameterSource createFullParametersMapper(AffinityGroup 
entity) {
         return createIdParameterMapper(entity.getId())
                 .addValue("name", entity.getName())
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 3b63397..0f077a4 100644
--- 
a/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
+++ 
b/backend/manager/modules/dal/src/main/resources/bundles/AppErrors.properties
@@ -79,6 +79,7 @@
               To do so, verify that the node is really down by right clicking 
on the host and confirm that the node was shutdown manually.
 VDS_CANNOT_MAINTENANCE_VDS_IS_NOT_OPERATIONAL=Cannot switch Host to 
Maintenance mode, Host is not operational.
 VDS_CANNOT_MAINTENANCE_VDS_IS_IN_MAINTENANCE=Cannot switch Host to Maintenance 
mode. Host is already in Maintenance mode.
+VDS_CANNOT_MAINTENANCE_VDS_HAS_AFFINITY_VMS=Cannot switch Host(s) to 
Maintenance mode.\nThe following Enforcing Affinity Groups (VMs) have running 
VMs and can break affinity rule.\n${AFFINITY_GROUPS_VMS}\nPlease manually 
migrate the VM(s), or change Affinity Group's enforcing to false.
 VDS_CANNOT_MAINTENANCE_SPM_WITH_RUNNING_TASKS=Cannot switch Host to 
Maintenance mode. Host has asynchronous running tasks,\n\
        wait for operation to complete and retry.
 VDS_CANNOT_MAINTENANCE_SPM_CONTENDING=Cannot switch Host to Maintenance mode. 
Host is contending for Storage Pool Manager,\n\
diff --git 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/AffinityGroupDaoTest.java
 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/AffinityGroupDaoTest.java
index c089e84..fd2d071 100644
--- 
a/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/AffinityGroupDaoTest.java
+++ 
b/backend/manager/modules/dal/src/test/java/org/ovirt/engine/core/dao/AffinityGroupDaoTest.java
@@ -142,4 +142,22 @@
         dao.removeVmFromAffinityGroups(FixturesTool.VM_RHEL5_POOL_50);
         
assertTrue(dao.getAllAffinityGroupsByVmId(FixturesTool.VM_RHEL5_POOL_50).isEmpty());
     }
+
+    @Test
+    public void testEmptyGetAffinityGroupByVdsId() {
+        getAffinityGroupByVdsIdHelper(Guid.Empty, 0);
+    }
+
+    @Test
+    public void testGetAffinityGroupByVdsId() {
+        getAffinityGroupByVdsIdHelper(FixturesTool.VDS_RHEL6_NFS_SPM, 1);
+    }
+
+    private void getAffinityGroupByVdsIdHelper(Guid vdsId, int count) {
+        List<AffinityGroup> affinityGroups =
+                dao.getEnforcingAffinityGroupsByRunningVmsOnVdsId(vdsId);
+
+        assertNotNull(affinityGroups);
+        assertEquals(count, affinityGroups.size());
+    }
 }
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 f579459..1c3326f 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
@@ -190,6 +190,9 @@
     @DefaultStringValue("Cannot switch Host to Maintenance mode. Host is 
already in Maintenance mode.")
     String VDS_CANNOT_MAINTENANCE_VDS_IS_IN_MAINTENANCE();
 
+    @DefaultStringValue("Cannot switch Host(s) to Maintenance mode.\nThe 
following Enforcing Affinity Groups (VMs) have running VMs and can break 
affinity rule.\n${AFFINITY_GROUPS_VMS}\nPlease manually migrate the VM(s), or 
change Affinity Group's enforcing to false.")
+    String VDS_CANNOT_MAINTENANCE_VDS_HAS_AFFINITY_VMS();
+
     @DefaultStringValue("Host CPU type is not supported in this cluster 
compatibility version or is not supported at all.")
     String CPU_TYPE_UNSUPPORTED_IN_THIS_CLUSTER_VERSION();
 
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 5c15576..8ea2a57 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
@@ -79,6 +79,7 @@
               To do so, verify that the node is really down by right clicking 
on the host and confirm that the node was shutdown manually.
 VDS_CANNOT_MAINTENANCE_VDS_IS_NOT_OPERATIONAL=Cannot switch Host to 
Maintenance mode, Host is not operational.
 VDS_CANNOT_MAINTENANCE_VDS_IS_IN_MAINTENANCE=Cannot switch Host to Maintenance 
mode. Host is already in Maintenance mode.
+VDS_CANNOT_MAINTENANCE_VDS_HAS_AFFINITY_VMS=Cannot switch Host(s) to 
Maintenance mode.\nThe following Enforcing Affinity Groups (VMs) have running 
VMs and can break affinity rule.\n${AFFINITY_GROUPS_VMS}\nPlease manually 
migrate the VM(s), or change Affinity Group's enforcing to false.
 VDS_CANNOT_MAINTENANCE_SPM_WITH_RUNNING_TASKS=Cannot switch Host to 
Maintenance mode. Host has asynchronous running tasks,\n\
        wait for operation to complete and retry.
 VDS_CANNOT_MAINTENANCE_SPM_CONTENDING=Cannot switch Host to Maintenance mode. 
Host is contending for Storage Pool Manager,\n\
diff --git a/packaging/dbscripts/affinity_groups_sp.sql 
b/packaging/dbscripts/affinity_groups_sp.sql
index 34eb8e9..70e5129 100644
--- a/packaging/dbscripts/affinity_groups_sp.sql
+++ b/packaging/dbscripts/affinity_groups_sp.sql
@@ -132,3 +132,16 @@
     WHERE vm_id = v_vm_id;
 END; $procedure$
 LANGUAGE plpgsql;
+
+-- Get All enforcing Affinity Groups which contain VMs running on given host id
+Create or replace FUNCTION 
getEnforcingAffinityGroupsByRunningVmsOnVdsId(v_vds_id UUID) RETURNS SETOF 
affinity_groups_view STABLE
+AS $procedure$
+BEGIN
+    RETURN QUERY
+    SELECT DISTINCT affinity_groups_view.* FROM affinity_groups_view
+    INNER JOIN affinity_group_members ON id = 
affinity_group_members.affinity_group_id
+    INNER JOIN vm_dynamic ON affinity_group_members.vm_id = vm_dynamic.vm_guid 
AND vm_dynamic.run_on_vds = v_vds_id
+    WHERE enforcing;
+END; $procedure$
+LANGUAGE plpgsql;
+


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

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

Reply via email to