Martin Sivák has uploaded a new change for review. Change subject: engine: Update Power Saving policy with power management ......................................................................
engine: Update Power Saving policy with power management Longer description using lines' length under 72 chars. With multiple paragraphs if necessary. Change-Id: I2da9f4e019c3dd006caefbaa9baf9a533ce41f3d Bug-Url: https://bugzilla.redhat.com/?????? Signed-off-by: Martin Sivak <msi...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/FenceVdsBaseCommand.java 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/PowerSavingBalancePolicyUnit.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/FenceVdsActionParameters.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/MaintenanceNumberOfVdssParameters.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java M backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties A packaging/dbscripts/upgrade/03_04_0240_add_power_management_to_cluster_policy.sql M packaging/etc/engine-config/engine-config.properties 10 files changed, 305 insertions(+), 2 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/88/22488/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/FenceVdsBaseCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/FenceVdsBaseCommand.java index e931ed5..ddaa8c1 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/FenceVdsBaseCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/FenceVdsBaseCommand.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; @@ -176,6 +177,13 @@ setStatus(lastStatus); AlertIfPowerManagementOperationFailed(); } + + // Successful fencing with reboot or shutdown op. Clear the power management policy flag + else if (EnumSet.of(FenceActionType.Restart, FenceActionType.Stop).contains(getParameters().getAction()) + && getParameters().getKeepPolicyPMEnabled() == false){ + getVds().setPowerManagementControlledByPolicy(false); + DbFacade.getInstance().getVdsDynamicDao().update(getVds().getDynamicData()); + } } } 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 035f8a0..1515632 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 @@ -123,6 +123,16 @@ NetworkClusterHelper.setStatus(id, net); } } + + // clear the automatic PM flag unless instructed otherwise + if (!getParameters().getKeepPolicyPMEnabled()) { + for (Guid vdsId : getParameters().getVdsIdList()) { + VDS vds = DbFacade.getInstance().getVdsDao().get(vdsId); + vds.setPowerManagementControlledByPolicy(false); + DbFacade.getInstance().getVdsDynamicDao().update(vds.getDynamicData()); + } + } + setSucceeded(true); } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/PowerSavingBalancePolicyUnit.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/PowerSavingBalancePolicyUnit.java index 251498d..cc47f5e 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/PowerSavingBalancePolicyUnit.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/scheduling/policyunits/PowerSavingBalancePolicyUnit.java @@ -7,13 +7,26 @@ import java.util.List; import java.util.Map; +import org.ovirt.engine.core.bll.Backend; +import org.ovirt.engine.core.bll.job.ExecutionHandler; +import org.ovirt.engine.core.common.AuditLogType; +import org.ovirt.engine.core.common.action.FenceVdsActionParameters; +import org.ovirt.engine.core.common.action.MaintenanceNumberOfVdssParameters; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.action.VdsActionParameters; +import org.ovirt.engine.core.common.businessentities.FenceActionType; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSGroup; +import org.ovirt.engine.core.common.businessentities.VDSStatus; +import org.ovirt.engine.core.common.businessentities.VdsSpmStatus; import org.ovirt.engine.core.common.config.Config; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.scheduling.PolicyUnit; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.compat.Guid; +import org.ovirt.engine.core.dal.dbbroker.DbFacade; +import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; +import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase; import org.ovirt.engine.core.utils.linq.LinqUtils; import org.ovirt.engine.core.utils.linq.Predicate; @@ -28,7 +41,210 @@ List<VDS> hosts, Map<String, String> parameters, ArrayList<String> messages) { - return super.balance(cluster, hosts, parameters, messages); + final Pair<List<Guid>, Guid> migrationRule = super.balance(cluster, hosts, parameters, messages); + + List<VDS> allHosts = DbFacade.getInstance().getVdsDao().getAllForVdsGroup(cluster.getId()); + + Pair<VDS, VDSStatus> action = evaluatePowerManagementSituation( + getDownHosts(allHosts, parameters), + getMaintenanceHosts(allHosts, parameters), + getEmptyHosts(allHosts, parameters), + parameters + ); + + if (action != null) processPmAction(action); + + return migrationRule; + } + + private void logAction(VDS vds, AuditLogType type) { + AuditLogableBase loggable = new AuditLogableBase(); + loggable.addCustomValue("Host", vds.getName()); + AuditLogDirector.log(loggable, type); + } + + private void processPmAction(Pair<VDS, VDSStatus> action) { + VDS vds = action.getFirst(); + VDSStatus currentStatus = vds.getStatus(); + VDSStatus targetStatus = action.getSecond(); + + if (targetStatus == VDSStatus.Maintenance && currentStatus == VDSStatus.Up) { + logAction(vds, AuditLogType.PM_POLICY_UP_TO_MAINTENANCE); + + /* Up -> Maint */ + List<Guid> vdsList = new ArrayList<>(1); + vdsList.add(vds.getId()); + MaintenanceNumberOfVdssParameters parameters = new MaintenanceNumberOfVdssParameters(vdsList, true, true); + Backend.getInstance().runInternalAction(VdcActionType.MaintenanceNumberOfVdss, + parameters, + ExecutionHandler.createInternalJobContext()); + } + else if (targetStatus == VDSStatus.Down && currentStatus == VDSStatus.Maintenance) { + logAction(vds, AuditLogType.PM_POLICY_MAINTENANCE_TO_DOWN); + + /* Maint -> Down */ + FenceVdsActionParameters parameters = new FenceVdsActionParameters(vds.getId(), FenceActionType.Start, true); + Backend.getInstance().runInternalAction(VdcActionType.StopVds, + parameters, + ExecutionHandler.createInternalJobContext()); + } + else if (targetStatus == VDSStatus.Up && currentStatus == VDSStatus.Maintenance) { + logAction(vds, AuditLogType.PM_POLICY_TO_UP); + + /* Maint -> Up */ + VdsActionParameters parameters = new VdsActionParameters(vds.getId()); + Backend.getInstance().runInternalAction(VdcActionType.ActivateVds, + parameters, + ExecutionHandler.createInternalJobContext()); + } + else if (targetStatus == VDSStatus.Up && currentStatus == VDSStatus.Down) { + logAction(vds, AuditLogType.PM_POLICY_TO_UP); + + /* Down -> Up */ + FenceVdsActionParameters parameters = new FenceVdsActionParameters(vds.getId(), FenceActionType.Start); + Backend.getInstance().runInternalAction(VdcActionType.StartVds, + parameters, + ExecutionHandler.createInternalJobContext()); + } + else { + /* Should not ever happen... */ + } + } + + /** + * + * @param allHosts All hosts in the cluster regardless of their status or PM configuration + * @param parameters + * @return List of hosts that are Up, contain no Vm and are currently not a target of any scheduling op. + */ + protected List<VDS> getEmptyHosts(List<VDS> allHosts, Map<String, String> parameters) { + List<VDS> emptyHosts = LinqUtils.filter(allHosts, new Predicate<VDS>() { + @Override + public boolean eval(VDS vds) { + return vds.getStatus() == VDSStatus.Up + && vds.getVmCount() == 0 + && vds.getVmMigrating() == 0 + && vds.getPendingVmemSize() == 0 + && vds.getPendingVcpusCount() == 0; + } + }); + + return emptyHosts; + } + + /** + * + * @param allHosts All hosts in the cluster regardless of their status or PM configuration + * @param parameters + * @return List of hosts that were put to maintenance by the policy based power management + * and have the automatic power management still enabled. + */ + protected List<VDS> getMaintenanceHosts(List<VDS> allHosts, Map<String, String> parameters) { + List<VDS> emptyHosts = LinqUtils.filter(allHosts, new Predicate<VDS>() { + @Override + public boolean eval(VDS vds) { + return vds.getStatus() == VDSStatus.Maintenance + && vds.isPowerManagementControlledByPolicy() + && vds.isDisablePowerManagementPolicy() == false; + } + }); + + return emptyHosts; + } + + /** + * + * @param allHosts All hosts in the cluster regardless of their status or PM configuration + * @param parameters + * @return List of hosts that were shut down by the policy based power management + * and have the automatic power management still enabled. + */ + protected List<VDS> getDownHosts(List<VDS> allHosts, Map<String, String> parameters) { + List<VDS> emptyHosts = LinqUtils.filter(allHosts, new Predicate<VDS>() { + @Override + public boolean eval(VDS vds) { + return vds.getStatus() == VDSStatus.Down + && vds.isPowerManagementControlledByPolicy() + && vds.isDisablePowerManagementPolicy() == false; + } + }); + + return emptyHosts; + } + + /** + * + * @param pmDownHosts hosts that were previously powered down by the power management policy + * @param pmMaintenanceHosts hosts that were previously powered down by the power management policy + * @param emptyHosts hosts that are still up, but contain no Vms + * @param parameters + * @return a pair of VDS to update and the desired VDSStatus to get it to + */ + protected Pair<VDS, VDSStatus> evaluatePowerManagementSituation(List<VDS> pmDownHosts, + List<VDS> pmMaintenanceHosts, + List<VDS> emptyHosts, + Map<String, String> parameters) { + final int requiredReserve = tryParseWithDefault(parameters.get("HostsInReserve"), Config + .<Integer> getValue(ConfigValues.HostsInReserve)); + final int enableAutoPM = tryParseWithDefault(parameters.get("EnableAutomaticHostPowerManagement"), Config + .<Integer> getValue(ConfigValues.EnableAutomaticHostPowerManagement)); + + /* Automatic power management is disabled */ + if (enableAutoPM == 0) return null; + + /* We need more hosts but there are no available for us */ + if (requiredReserve > emptyHosts.size() + && pmDownHosts.isEmpty() + && pmMaintenanceHosts.isEmpty()) return null; + + /* We have enough free hosts so shut some hosts in maintenance down + keep at least one spare in maintenance during the process. + */ + else if (requiredReserve < emptyHosts.size() + && pmMaintenanceHosts.size() > 1) { + return new Pair<>(pmMaintenanceHosts.get(0), VDSStatus.Down); + } + + /* We do have enough empty hosts to put something to maintenance */ + else if (requiredReserve < emptyHosts.size()) { + /* Find hosts with automatic PM enabled that are not the current SPM */ + List<VDS> hostsWithAutoPM = LinqUtils.filter(emptyHosts, new Predicate<VDS>() { + @Override + public boolean eval(VDS vds) { + return !vds.isDisablePowerManagementPolicy() + && vds.getSpmStatus() != VdsSpmStatus.SPM + && vds.getpm_enabled(); + } + }); + + return hostsWithAutoPM.isEmpty() ? null : new Pair<>(hostsWithAutoPM.get(0), VDSStatus.Maintenance); + } + + /* We have the right amount of empty hosts to start shutting the + hosts that are resting in maintenance down. + */ + else if (requiredReserve == emptyHosts.size() + && pmMaintenanceHosts.isEmpty() == false) { + return new Pair<>(pmMaintenanceHosts.get(0), VDSStatus.Down); + } + + /* We do not have enough free hosts, but we still have some hosts + in maintenance. We can easily activate those. + */ + else if (requiredReserve > emptyHosts.size() + && pmMaintenanceHosts.isEmpty() == false) { + return new Pair<>(pmMaintenanceHosts.get(0), VDSStatus.Up); + } + + /* We do not have enough free hosts and no hosts in pm maintenance, + so we need to start some hosts up. + */ + else if (requiredReserve > emptyHosts.size() + && pmMaintenanceHosts.isEmpty()) { + return new Pair<>(pmDownHosts.get(0), VDSStatus.Up); + } + + return null; } @Override diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java index 51faf1c..da58065 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/AuditLogType.java @@ -821,7 +821,12 @@ //mom policies USER_UPDATED_MOM_POLICIES(10200), - USER_FAILED_TO_UPDATE_MOM_POLICIES(10201); + USER_FAILED_TO_UPDATE_MOM_POLICIES(10201), + + //power management policy + PM_POLICY_UP_TO_MAINTENANCE(10250), + PM_POLICY_MAINTENANCE_TO_DOWN(10251), + PM_POLICY_TO_UP(10252); private int intValue; // indicates time interval in seconds on which identical events from same instance are suppressed. diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/FenceVdsActionParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/FenceVdsActionParameters.java index cecdc07..a2d69a1 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/FenceVdsActionParameters.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/FenceVdsActionParameters.java @@ -6,9 +6,22 @@ public class FenceVdsActionParameters extends VdsActionParameters { private static final long serialVersionUID = 6174371941176548263L; + /* + * If the power management policy is responsible for this action + * pass true so we keep the powerManagementControlledByPolicy flag set. + * + * If the user triggered this action, clear the flag. + */ + private boolean _keepPolicyPMEnabled = false; + public FenceVdsActionParameters(Guid vdsId, FenceActionType action) { super(vdsId); _action = action; + } + + public FenceVdsActionParameters(Guid vdsId, FenceActionType action, boolean keepPolicyPMEnabled) { + this(vdsId, action); + this._keepPolicyPMEnabled = keepPolicyPMEnabled; } private FenceActionType _action; @@ -20,4 +33,12 @@ public FenceVdsActionParameters() { _action = FenceActionType.Restart; } + + public boolean getKeepPolicyPMEnabled() { + return _keepPolicyPMEnabled; + } + + public void setKeepPolicyPMEnabled(boolean _keepPolicyPMEnabled) { + this._keepPolicyPMEnabled = _keepPolicyPMEnabled; + } } diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/MaintenanceNumberOfVdssParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/MaintenanceNumberOfVdssParameters.java index 79ca8b7..427db92 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/MaintenanceNumberOfVdssParameters.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/MaintenanceNumberOfVdssParameters.java @@ -11,9 +11,22 @@ private boolean _isInternal; + /* + * If the power management policy is responsible for this action + * pass true so we keep the powerManagementControlledByPolicy flag set. + * + * If the user triggered this action, clear the flag. + */ + private boolean _keepPolicyPMEnabled = false; + public MaintenanceNumberOfVdssParameters(java.util.List<Guid> vdsIdList, boolean isInternal) { _vdsIdList = vdsIdList; _isInternal = isInternal; + } + + public MaintenanceNumberOfVdssParameters(java.util.List<Guid> vdsIdList, boolean isInternal, boolean keepPolicyPMEnabled) { + this(vdsIdList, isInternal); + this._keepPolicyPMEnabled = keepPolicyPMEnabled; } public Iterable<Guid> getVdsIdList() { @@ -28,6 +41,14 @@ return _isInternal; } + public boolean getKeepPolicyPMEnabled() { + return _keepPolicyPMEnabled; + } + + public void setKeepPolicyPMEnabled(boolean _keepPolicyPMEnabled) { + this._keepPolicyPMEnabled = _keepPolicyPMEnabled; + } + public MaintenanceNumberOfVdssParameters() { } } diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java index c292842..2cbc461 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java @@ -402,6 +402,14 @@ LowUtilizationForPowerSave, @Reloadable @TypeConverterAttribute(Integer.class) + @DefaultValueAttribute("0") + HostsInReserve, + @Reloadable + @TypeConverterAttribute(Integer.class) + @DefaultValueAttribute("0") + EnableAutomaticHostPowerManagement, + @Reloadable + @TypeConverterAttribute(Integer.class) @DefaultValueAttribute("10") HighUtilizationForEvenlyDistribute, @Reloadable diff --git a/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties b/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties index dd92ebc..1b7954a 100644 --- a/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties +++ b/backend/manager/modules/dal/src/main/resources/bundles/AuditLogMessages.properties @@ -717,3 +717,6 @@ VM_MEMORY_NOT_IN_RECOMMENDED_RANGE=VM ${VmName} was configured with ${VmMemInMb}mb of memory while the recommended value range is ${VmMinMemInMb}mb - ${VmMaxMemInMb}mb VM_CONSOLE_CONNECTED=User ${UserName} is connected to VM ${VmName}. VM_CONSOLE_DISCONNECTED=User ${UserName} got disconnected from VM ${VmName}. +PM_POLICY_UP_TO_MAINTENANCE=Host ${Host} is not currently needed, activating maintenance mode in preparation for shutdown. +PM_POLICY_MAINTENANCE_TO_DOWN=Host ${Host} is not currently needed, shutting down. +PM_POLICY_TO_UP=Reactivating host ${Host} according to the current power management policy. diff --git a/packaging/dbscripts/upgrade/03_04_0240_add_power_management_to_cluster_policy.sql b/packaging/dbscripts/upgrade/03_04_0240_add_power_management_to_cluster_policy.sql new file mode 100644 index 0000000..9f4cf61 --- /dev/null +++ b/packaging/dbscripts/upgrade/03_04_0240_add_power_management_to_cluster_policy.sql @@ -0,0 +1,7 @@ +UPDATE policy_units SET custom_properties_regex='{ + "CpuOverCommitDurationMinutes" : "^([1-9])$", + "HighUtilization" : "^([5-9][0-9])$", + "LowUtilization" : "^([1-4][0-9])$", + "HostsInReserve": "^[0-9][0-9]*$", + "EnableAutomaticHostPowerManagement": "^[01]$" +}' WHERE id='736999d0-1023-46a4-9a75-1316ed50e151'; diff --git a/packaging/etc/engine-config/engine-config.properties b/packaging/etc/engine-config/engine-config.properties index 5a75619..c9e9d9c 100644 --- a/packaging/etc/engine-config/engine-config.properties +++ b/packaging/etc/engine-config/engine-config.properties @@ -354,5 +354,9 @@ SchedulerAllowOverBooking.type=Boolean SchedulerOverBookingThreshold.description="Skip Scheduling resource synchronization, which could result in overbooking, if there are more than X requests pending for scheduling (in case SchedulerAllowOverBooking=true and cluster is configured as allow overbooking)." SchedulerOverBookingThreshold.type=Integer +HostsInReserve.description="Keep this amount of hosts running even though there are no running Vms on them" +HostsInReserve.type=Integer +EnableAutomaticHostPowerManagement.description=Enable (1) or disable (0) automatic host power management +EnableAutomaticHostPowerManagement.type=Integer -- To view, visit http://gerrit.ovirt.org/22488 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I2da9f4e019c3dd006caefbaa9baf9a533ce41f3d Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Martin Sivák <msi...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches