Eli Mesika has uploaded a new change for review. Change subject: core: handle fence agent power wait param on stop ......................................................................
core: handle fence agent power wait param on stop When a host restart is dome manually or as a result of a non-responsive host treatment and in the case that power wait parameter is used the host may stay in 'off' state and even release its lock on HA VMs before the host is really down This is the scenario: 1) A restart command is issued and actually performed as stop -> wait for 'off' status -> start -> wait for 'on' status 2) power wait parameter is added to the command implicitly or explicitly giving a delay of X seconds before the operation is actually performed 3) The fence agent script returns immediately with 'off' status 4) A 'on' command is sent to the fence agent by the start operation 5) X seconds passed and the host is actually shutdown This patch handles this by adding a new configuration value that maps fence agents to the name of the parameter for power wait and it also adds a custom configuration value that may be set for custom fence agents. Upon stop operation, we will wait a fixed delay (5 seconds hard-coded) before starting to sample the host status, if power wait parameter is used, the value is extracted and we will wait for 5 + X seconds. Change-Id: I310e076ecf84988cacd0b179954d2460d7988b91 Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1093742 Signed-off-by: Eli Mesika <emes...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/FenceVdsBaseCommand.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/config/ConfigValues.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/FenceConfigHelper.java M backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/VdsFenceOptions.java M packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql M packaging/etc/engine-config/engine-config.properties 6 files changed, 85 insertions(+), 1 deletion(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/83/29383/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 d185b57..033e7dd 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 @@ -3,12 +3,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.bll.context.CommandContext; @@ -20,7 +22,9 @@ import org.ovirt.engine.core.common.businessentities.FenceStatusReturnValue; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VM; +import org.ovirt.engine.core.common.businessentities.VdsStatic; import org.ovirt.engine.core.common.config.Config; +import org.ovirt.engine.core.common.config.ConfigCommon; import org.ovirt.engine.core.common.config.ConfigValues; import org.ovirt.engine.core.common.errors.VdcBLLException; import org.ovirt.engine.core.common.errors.VdcBllErrors; @@ -35,6 +39,8 @@ import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector; import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableBase; import org.ovirt.engine.core.utils.ThreadUtils; +import org.ovirt.engine.core.utils.pm.FenceConfigHelper; +import org.ovirt.engine.core.utils.pm.VdsFenceOptions; import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil; public abstract class FenceVdsBaseCommand<T extends FenceVdsActionParameters> extends VdsCommand<T> { @@ -472,7 +478,7 @@ // This is done because if we will attempt to get host status immediately // in most cases it will not turn from on/off to off/on and we will need // to wait a full cycle for it. - ThreadUtils.sleep(SLEEP_BEFORE_FIRST_ATTEMPT); + ThreadUtils.sleep(getSleep(actionType, order)); while (!statusReached && i <= getRerties()) { log.infoFormat("Attempt {0} to get vds {1} status", i, vdsName); if (executor.findProxyHost()) { @@ -521,6 +527,36 @@ return statusReached; } + private int getSleep(FenceActionType actionType, FenceAgentOrder order) { + if (actionType != FenceActionType.Stop) { + return SLEEP_BEFORE_FIRST_ATTEMPT; + } + // We have to find out if power off delay was used and add this to the wait time + // since otherwise the command will return immediately with 'off' status and + // subsequent 'on' command issued during this delay will be overridden by the actual shutdown + String agent = (order == FenceAgentOrder.Primary) ? getVds().getPmType() : getVds().getPmSecondaryType(); + String options = (order == FenceAgentOrder.Primary) ? getVds().getPmOptions() : getVds().getPmSecondaryOptions(); + options = VdsFenceOptions.getDefaultAgentOptions(agent, options); + HashMap<String, String> optionsMap = VdsStatic.pmOptionsStringToMap(options); + String powerWaitParamSettings = FenceConfigHelper.getFenceConfigurationValue(ConfigValues.FencePowerWaitParam.name(), ConfigCommon.defaultConfigurationVersion); + String powerWaitParam = VdsFenceOptions.getAgentPowerWaitParam(agent, powerWaitParamSettings); + if (powerWaitParam == null) { + // no power wait for this agent + return SLEEP_BEFORE_FIRST_ATTEMPT; + } + if (optionsMap.containsKey(powerWaitParam)) { + try { + Integer powerWaitValueInSec = Integer.parseInt(optionsMap.get(powerWaitParam)); + return SLEEP_BEFORE_FIRST_ATTEMPT + (int)TimeUnit.SECONDS.toMillis(powerWaitValueInSec); + } + catch(NumberFormatException nfe) { + // illegal value + return SLEEP_BEFORE_FIRST_ATTEMPT; + } + } + return SLEEP_BEFORE_FIRST_ATTEMPT; + } + protected void setStatus(VDSStatus status) { if (getVds().getStatus() != status) { runVdsCommand(VDSCommandType.SetVdsStatus, 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 588e797..a0e02da 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 @@ -1840,5 +1840,19 @@ @DefaultValueAttribute("300") AlertOnNumberOfLVs, + /** + * Defines the parameter name used by the agent script to delay host on/off + */ + @TypeConverterAttribute(String.class) + @DefaultValueAttribute("apc=power_wait,apc_snmp=power_wait,bladecenter=power_wait,cisco_ucs=power_wait,drac5=power_wait,drac7=power_wait,eps=delay,hpblade=power_wait,ilo=power_wait,ilo2=power_wait,ilo3=power_wait,ilo4=power_wait,ipmilan=power_wait,rsa=power_wait,rsb=power_wait,wti=power_wait") + FencePowerWaitParam, + + /** + * Defines the parameter name used by the custom agent script to delay host on/off + */ + @TypeConverterAttribute(String.class) + @DefaultValueAttribute("") + CustomFencePowerWaitParam, + Invalid } diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/FenceConfigHelper.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/FenceConfigHelper.java index 5c9f40a..1b81d3c 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/FenceConfigHelper.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/FenceConfigHelper.java @@ -19,6 +19,7 @@ private static final String FenceAgentDefaultParamsExpr = "([\\w]+([=][\\w]+){0,1}[,]{0,1})+"; private static final String VdsFenceOptionMappingExpr = "([\\w]+[:]([\\w]*[=][\\w]*[,]{0,1}[;]{0,1}){0,3}[;]{0,1})+"; private static final String CustomVdsFenceTypeExpr = "((\\w)+[,]{0,1})+"; + private static final String FencePowerWaitParamExpr = "((\\w)+[=](\\w)+[,]{0,1})+"; private static final String COMMA = ","; private static final String SEMICOLON = ";"; @@ -30,21 +31,25 @@ keyValidatorMap.put("FenceAgentDefaultParams", FenceAgentDefaultParamsExpr); keyValidatorMap.put("VdsFenceOptionMapping", VdsFenceOptionMappingExpr); keyValidatorMap.put("VdsFenceType", CustomVdsFenceTypeExpr); + keyValidatorMap.put("FencePowerWaitParam", FencePowerWaitParamExpr); keyValidatorMap.put("CustomFenceAgentMapping", FenceAgentMappingExpr); keyValidatorMap.put("CustomFenceAgentDefaultParams", FenceAgentDefaultParamsExpr); keyValidatorMap.put("CustomVdsFenceOptionMapping", VdsFenceOptionMappingExpr); keyValidatorMap.put("CustomVdsFenceType", CustomVdsFenceTypeExpr); + keyValidatorMap.put("CustomFencePowerWaitParam", FencePowerWaitParamExpr); keyValidatorExampleMap = new HashMap<String, String>(); keyValidatorExampleMap.put("CustomFenceAgentMapping", "agent1=agent2,agent3=agent4"); keyValidatorExampleMap.put("CustomFenceAgentDefaultParams", "agent1=key1=val1,flag;key2=val2"); keyValidatorExampleMap.put("CustomVdsFenceOptionMapping", "agent1:secure=secure;agent2:port=ipport,slot=slot"); keyValidatorExampleMap.put("CustomVdsFenceType", "agent1,agent2"); + keyValidatorExampleMap.put("CustomFencePowerWaitParam", "agent1=power_wait,agent2=delay"); keySeparatorMap = new HashMap<String, String>(); keySeparatorMap.put("FenceAgentMapping", COMMA); keySeparatorMap.put("FenceAgentDefaultParams", SEMICOLON); keySeparatorMap.put("VdsFenceOptionMapping", SEMICOLON); keySeparatorMap.put("VdsFenceType", COMMA); + keySeparatorMap.put("FencePowerWaitParam", COMMA); initialized = true; } } diff --git a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/VdsFenceOptions.java b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/VdsFenceOptions.java index 2f4bffb..9f120f2 100644 --- a/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/VdsFenceOptions.java +++ b/backend/manager/modules/utils/src/main/java/org/ovirt/engine/core/utils/pm/VdsFenceOptions.java @@ -291,6 +291,31 @@ } /** + * handles agent power wait parameter mapping + * @param agent + * @param powerWait + * @return + */ + public static String getAgentPowerWaitParam(String agent, String powerWait) { + String param = null; + // result has the format [<agent>=<real agent>[,]]* + String[] settings = powerWait.split(Pattern.quote(COMMA), -1); + if (settings.length > 0) { + for (String setting : settings) { + // get the <agent>=<real agent> pair + String[] pair = setting.split(Pattern.quote(EQUAL), -1); + if (pair.length == 2) { + if (agent.equalsIgnoreCase(pair[0])) { + param = pair[1]; + break; + } + } + } + } + return param; + } + + /** * handles agent default options * * @param agent diff --git a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql index 9ea49e2..1b2c583 100644 --- a/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql +++ b/packaging/dbscripts/upgrade/pre_upgrade/0000_config.sql @@ -127,12 +127,14 @@ select fn_db_add_config_value('CustomFenceAgentDefaultParams','','general'); select fn_db_add_config_value('FenceAgentMapping','drac7=ipmilan,ilo2=ilo,ilo3=ipmilan,ilo4=ipmilan','general'); select fn_db_add_config_value('CustomFenceAgentMapping','','general'); +select fn_db_add_config_value('CustomFencePowerWaitParam','','general'); select fn_db_add_config_value('FenceProxyDefaultPreferences','cluster,dc','general'); select fn_db_add_config_value('FenceQuietTimeBetweenOperationsInSec','180','general'); select fn_db_add_config_value('FenceStartStatusDelayBetweenRetriesInSec','60','general'); select fn_db_add_config_value('FenceStartStatusRetries','3','general'); select fn_db_add_config_value('FenceStopStatusDelayBetweenRetriesInSec','60','general'); select fn_db_add_config_value('FenceStopStatusRetries','3','general'); +select fn_db_add_config_value('FencePowerWaitParam','apc=power_wait,apc_snmp=power_wait,bladecenter=power_wait,cisco_ucs=power_wait,drac5=power_wait,drac7=power_wait,eps=delay,hpblade=power_wait,ilo=power_wait,ilo2=power_wait,ilo3=power_wait,ilo4=power_wait,ipmilan=power_wait,rsa=power_wait,rsb=power_wait,wti=power_wait','general'); select fn_db_add_config_value('FilteringLUNsEnabled','true','3.0'); select fn_db_add_config_value('FindFenceProxyDelayBetweenRetriesInSec','30','general'); select fn_db_add_config_value('FindFenceProxyRetries','3','general'); diff --git a/packaging/etc/engine-config/engine-config.properties b/packaging/etc/engine-config/engine-config.properties index d12a26c..a70de6f 100644 --- a/packaging/etc/engine-config/engine-config.properties +++ b/packaging/etc/engine-config/engine-config.properties @@ -418,6 +418,8 @@ CustomVdsFenceOptionMapping.type=FenceConfig CustomVdsFenceType.description="Fence agents types. Format ((\\w)+[,]{0,1})+. Example: agent1,agent2" CustomVdsFenceType.type=FenceConfig +CustomFencePowerWaitParam.type=FenceConfig +CustomFencePowerWaitParam.description="Maps a fencing agent to the param for delay on/off actions. Format : ((\\w)+[=](\\w)+[,]{0,1})+. Example: agent1=power_wait,agent2=delay" # Random Number Generator device VirtIoRngDeviceSupported.description="Defines whether VirtIO Random Number Generator devices is supported for given cluster level." VirtIoRngDeviceSupported.type=Boolean -- To view, visit http://gerrit.ovirt.org/29383 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I310e076ecf84988cacd0b179954d2460d7988b91 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Eli Mesika <emes...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches