package org.ovirt.engine.core.bll.pm;
import java.util.Arrays;
import java.util.List;
import org.ovirt.engine.core.common.businessentities.FencingPolicy;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.pm.FenceActionType;
import org.ovirt.engine.core.common.businessentities.pm.FenceAgent;
import org.ovirt.engine.core.common.businessentities.pm.FenceOperationResult;
import org.ovirt.engine.core.common.businessentities.pm.FenceOperationResult.Status;
import org.ovirt.engine.core.common.businessentities.pm.PowerStatus;
/**
* It manages:
* <ul>
* <li>Iteration on specified fence agents using {@code PowerManagementHelper.AgentsIterator}</li>
* <li>Execution of fence action using all existing fence agents for the host</li>
* <li>Execution of fence action using only specified fence agents</li>
* <li>Usage of {@code SingleAgentFenceActionExecutor} and {@code ConcurrentAgentsFenceActionExecutor}
* to execute fence action for particular fence agent(s)</li>
* </ul>
*/
public class HostFenceActionExecutor {
/**
* Host which the action is executed for
*/
private final VDS fencedHost;
/**
* Fencing policy applied during action execution
*/
private final FencingPolicy fencingPolicy;
public HostFenceActionExecutor(VDS fencedHost) {
this(fencedHost, null);
}
public HostFenceActionExecutor(VDS fencedHost, FencingPolicy fencingPolicy) {
this.fencedHost = fencedHost;
this.fencingPolicy = fencingPolicy;
}
/**
* Executes specified fence action on the {@code fencedHost} using fence agents defined for the host
*
* @param fenceAction
* specified fence action
* @return result of the action
*/
public FenceOperationResult fence(FenceActionType fenceAction) {
if (fencedHost.getFenceAgents() == null || fencedHost.getFenceAgents().isEmpty()) {
return new FenceOperationResult(
Status.ERROR,
PowerStatus.UNKNOWN,
String.format(
"Invalid fence agents defined for host '%s'.",
fencedHost.getHostName()));
}
return fence(fenceAction, fencedHost.getFenceAgents());
}
/**
* Executes status fence action on fence agents defined for {@code fencedHost} to determine if it's powered off
*
* @return {@code true} if host is powered off, otherwise {@code false}
*/
public boolean isHostPoweredOff() {
FenceOperationResult result = fence(FenceActionType.STATUS);
return result.getStatus() == FenceOperationResult.Status.SUCCESS
&& result.getPowerStatus() == PowerStatus.OFF;
}
/**
* Executes status fence action on the {@code fencedHost} using only specified fence agent
*
* @param fenceAgent
* specified fence agent
* @return result of the action
*/
public FenceOperationResult getFenceAgentStatus(FenceAgent fenceAgent) {
if (fenceAgent == null) {
return new FenceOperationResult(
Status.ERROR,
PowerStatus.UNKNOWN,
"Invalid fence agent specified.");
}
return fence(FenceActionType.STATUS, Arrays.asList(fenceAgent));
}
/**
* Executes specified fence action using specified fence agents
*/
protected FenceOperationResult fence(FenceActionType fenceAction, List<FenceAgent> fenceAgents) {
PowerManagementHelper.AgentsIterator iterator = createFenceAgentsIterator(fenceAgents);
FenceOperationResult result = null;
while (iterator.hasNext()) {
result = createFenceActionExecutor(iterator.next()).fence(fenceAction);
if (result.getStatus() == Status.SUCCESS) {
break;
}
}
return result;
}
/**
* Creates fence agents iterator
*/
protected PowerManagementHelper.AgentsIterator createFenceAgentsIterator(List<FenceAgent> fenceAgents) {
return PowerManagementHelper.getAgentsIterator(fenceAgents);
}
/**
* Creates instance of {@code FenceActionExecutor} according to specified fence agents
*/
FenceActionExecutor createFenceActionExecutor(List<FenceAgent> fenceAgents) {
if (fenceAgents.size() == 1) {
return new SingleAgentFenceActionExecutor(fencedHost, fenceAgents.get(0), fencingPolicy);
} else {
return new ConcurrentAgentsFenceActionExecutor(fencedHost, fenceAgents, fencingPolicy);
}
}
}