package org.ovirt.engine.core.bll; import org.ovirt.engine.core.common.businessentities.FenceActionType; import org.ovirt.engine.core.common.businessentities.FenceStatusReturnValue; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.VdsFencingOptions; 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.errors.VdcBLLException; import org.ovirt.engine.core.common.vdscommands.FenceVdsVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.SpmStopVDSCommandParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.compat.LogCompat; import org.ovirt.engine.core.compat.LogFactoryCompat; import org.ovirt.engine.core.dal.dbbroker.DbFacade; import org.ovirt.engine.core.utils.linq.LinqUtils; import org.ovirt.engine.core.utils.linq.Predicate; public class FencingExecutor { private VDS _vds; private FenceActionType _action = FenceActionType.forValue(0); private Guid _vdsToRunId; private String _vdsToRunName; public FencingExecutor(VDS vds, FenceActionType actionType) { _vds = vds; _action = actionType; } public boolean FindVdsToFence() { final Guid NO_VDS = Guid.Empty; int count = 0; // make sure that loop is executed at least once , no matter what is the // value in config int retries = Math.max(Config.<Integer> GetValue(ConfigValues.FindFenceProxyRetries), 1); int delayInMs = 1000 * Config.<Integer> GetValue(ConfigValues.FindFenceProxyDelayBetweenRetriesInSec); _vdsToRunId = NO_VDS; VDS vdsToRun = null; // check if this is a new host, no need to retry , only status is // available on new host. if (_vds.getvds_id().equals(NO_VDS)) { vdsToRun = LinqUtils.firstOrNull(DbFacade.getInstance().getVdsDAO().getAll(), new Predicate<VDS>() { @Override public boolean eval(VDS vds) { return vds.getstatus() == VDSStatus.Up && vds.getstorage_pool_id().equals(_vds.getstorage_pool_id()); } }); if (vdsToRun != null) { _vdsToRunId = vdsToRun.getvds_id(); _vdsToRunName = vdsToRun.getvds_name(); } } else { // If can not find a proxy host retry and delay between retries // as configured. while (count < retries) { vdsToRun = LinqUtils.firstOrNull(DbFacade.getInstance().getVdsDAO().getAll(), new Predicate<VDS>() { @Override public boolean eval(VDS vds) { return !vds.getvds_id().equals(_vds.getvds_id()) && vds.getstorage_pool_id().equals(_vds.getstorage_pool_id()) && vds.getstatus() == VDSStatus.Up; } }); if (vdsToRun != null) { _vdsToRunId = vdsToRun.getvds_id(); _vdsToRunName = vdsToRun.getvds_name(); break; } // do not retry getting proxy for Status operation. if (_action == FenceActionType.Status) break; log.infoFormat("Atempt {0} to find fencing proxy host failed...", ++count); try { Thread.sleep(delayInMs); } catch (Exception e) { log.error(e.getMessage()); break; } } } if (_vdsToRunId == NO_VDS) { log.errorFormat("Failed to run Power Management command on Host {0}, no running proxy Host was found.", _vds.getvds_name()); } return (_vdsToRunId != NO_VDS); } public VDSReturnValue Fence() { VDSReturnValue retValue = null; try { // skip following code in case of testing a new host status if (_vds.getvds_id() != null && !_vds.getvds_id().equals(Guid.Empty)) { // get the host spm status again from the database in order to test it's current state. _vds.setspm_status((DbFacade.getInstance().getVdsDAO().get(_vds.getvds_id()).getspm_status())); // try to stop SPM if action is Restart or Stop and the vds is SPM if ((_action == FenceActionType.Restart || _action == FenceActionType.Stop) && (_vds.getspm_status() != VdsSpmStatus.None)) { Backend.getInstance() .getResourceManager() .RunVdsCommand(VDSCommandType.SpmStop, new SpmStopVDSCommandParameters(_vds.getvds_id(), _vds.getstorage_pool_id())); } } retValue = runFencingAction(_action); } catch (VdcBLLException e) { retValue = new VDSReturnValue(); retValue.setReturnValue(new FenceStatusReturnValue("unknown", e.getMessage())); retValue.setExceptionString(e.getMessage()); retValue.setSucceeded(false); } return retValue; } /** * Check if the proxy can be used to fence the host successfully. * @return Whether the proxy host can be used to fence the host successfully. */ public boolean checkProxyHostConnectionToHost() { return runFencingAction(FenceActionType.Status).getSucceeded(); } /** * Run the specified fencing action. * @param actionType The action to run. * @return The result of running the fencing command. */ private VDSReturnValue runFencingAction(FenceActionType actionType) { String managementPort = ""; if (_vds.getpm_port() != null && _vds.getpm_port() != 0) { managementPort = _vds.getpm_port().toString(); } // get real agent and default parameters String agent = VdsFencingOptions.getRealAgent(_vds.getpm_type()); String managementOptions = VdsFencingOptions.getDefaultAgentOptions(_vds.getpm_type(),_vds.getpm_options()); log.infoFormat("Executing <{0}> Power Management command, Proxy Host:{1}, " + "Agent:{2}, Target Host:{3}, Management IP:{4}, User:{5}, Options:{6}", actionType, _vdsToRunName, agent, _vds.getvds_name(), _vds.getManagmentIp(), _vds.getpm_user(), managementOptions); return Backend .getInstance() .getResourceManager() .RunVdsCommand( VDSCommandType.FenceVds, new FenceVdsVDSCommandParameters(_vdsToRunId, _vds.getvds_id(), _vds.getManagmentIp(), managementPort, agent, _vds.getpm_user(), _vds.getpm_password(), managementOptions, actionType)); } private static LogCompat log = LogFactoryCompat.getLog(FencingExecutor.class); }