package org.ovirt.engine.core.bll;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.pm.PmHealthCheckManager;
import org.ovirt.engine.core.bll.provider.NetworkProviderValidator;
import org.ovirt.engine.core.bll.utils.GlusterUtil;
import org.ovirt.engine.core.bll.utils.PermissionSubject;
import org.ovirt.engine.core.bll.validator.FenceValidator;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.VdcObjectType;
import org.ovirt.engine.core.common.action.VdsActionParameters;
import org.ovirt.engine.core.common.businessentities.NonOperationalReason;
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.businessentities.pm.FenceAgent;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.vdscommands.AddVdsVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.RemoveVdsVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.SetVdsStatusVDSCommandParameters;
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.dal.dbbroker.auditloghandling.AlertDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogable;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableImpl;
import org.ovirt.engine.core.dao.VdsSpmIdMapDao;
import org.ovirt.engine.core.dao.gluster.GlusterDBUtils;
import org.ovirt.engine.core.dao.provider.ProviderDao;
import org.ovirt.engine.core.utils.EngineLocalConfig;
import org.ovirt.engine.core.utils.ThreadUtils;
import org.ovirt.engine.core.utils.lock.EngineLock;
import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil;
import org.ovirt.engine.core.vdsbroker.ResourceManager;
public abstract class VdsCommand<T extends VdsActionParameters> extends CommandBase<T> {
protected String _failureMessage = null;
@Inject
private PmHealthCheckManager pmHealthCheckManager;
@Inject
protected CpuFlagsManagerHandler cpuFlagsManagerHandler;
@Inject
private ResourceManager resourceManager;
@Inject
private HostLocking hostLocking;
@Inject
protected VdsSpmIdMapDao vdsSpmIdMapDao;
@Inject
protected GlusterUtil glusterUtil;
@Inject
protected GlusterDBUtils glusterDBUtils;
@Inject
private ProviderDao providerDao;
@Inject
private AlertDirector alertDirector;
/**
* Constructor for command creation when compensation is applied on startup
*/
protected VdsCommand(Guid commandId) {
super(commandId);
}
public VdsCommand(T parameters, CommandContext cmdContext) {
super(parameters, cmdContext);
setVdsId(parameters.getVdsId());
}
protected CpuFlagsManagerHandler getCpuFlagsManagerHandler() {
return cpuFlagsManagerHandler;
}
protected void initializeVds() {
initializeVds(false);
}
protected void initializeVds(boolean newHost) {
runVdsCommand(VDSCommandType.RemoveVds,
new RemoveVdsVDSCommandParameters(getVdsId(), newHost));
runVdsCommand(VDSCommandType.AddVds, new AddVdsVDSCommandParameters(getVdsId()));
}
@Override
protected String getDescription() {
return getVdsName();
}
protected void runSleepOnReboot() {
runSleepOnReboot(VDSStatus.NonResponsive);
}
protected void runSleepOnReboot(final VDSStatus status) {
ThreadPoolUtil.execute(() -> sleepOnReboot(status));
}
private void sleepOnReboot(final VDSStatus status) {
int sleepTimeInSec = Config.<Integer> getValue(ConfigValues.ServerRebootTimeout);
log.info("Waiting {} seconds, for server to finish reboot process.",
sleepTimeInSec);
ThreadUtils.sleep(TimeUnit.SECONDS.toMillis(sleepTimeInSec));
setVdsStatus(status);
}
/**
* Alerts the specified log type.
*
* @param logType
* Type of the log.
*/
private void alert(AuditLogType logType) {
AuditLogable alert = new AuditLogableImpl();
alert.setVdsName(getVds().getName());
alert.setVdsId(getVds().getId());
auditLogDirector.log(alert, logType);
}
/**
* Alerts if power management not configured.
*
* @param vdsStatic
* The VDS static.
*/
protected void alertIfPowerManagementNotConfigured(VdsStatic vdsStatic) {
if (getCluster() != null && !getCluster().supportsVirtService()) {
return;
}
// Check first if PM is enabled on the cluster level
if (getVds().isFencingEnabled()) {
if (!vdsStatic.isPmEnabled()) {
alert(AuditLogType.VDS_ALERT_FENCE_IS_NOT_CONFIGURED);
// remove any test failure alerts
alertDirector.removeVdsAlert(vdsStatic.getId(), AuditLogType.VDS_ALERT_FENCE_TEST_FAILED);
} else {
alertDirector.removeVdsAlert(vdsStatic.getId(), AuditLogType.VDS_ALERT_FENCE_IS_NOT_CONFIGURED);
}
}
}
/**
* Alerts if power management status failed.
*
* @param vdsStatic
* The VDS static.
*/
protected void testVdsPowerManagementStatus(VdsStatic vdsStatic) {
if (vdsStatic.isPmEnabled()) {
pmHealthCheckManager.pmHealthCheck(vdsStatic.getId());
}
}
/**
* Alerts if power management operation failed.
*/
protected void alertIfPowerManagementOperationFailed() {
alert(AuditLogType.VDS_ALERT_FENCE_OPERATION_FAILED);
}
/**
* Alerts if power management operation skipped.
*/
protected void alertIfPowerManagementOperationSkipped() {
alert(AuditLogType.VDS_ALERT_FENCE_OPERATION_SKIPPED);
}
protected void logSettingVmToDown(VM vm) {
AuditLogable logable = new AuditLogableImpl();
logable.setVdsName(getVds().getName());
logable.setVdsId(getVds().getId());
logable.setVmName(vm.getName());
logable.setVmId(vm.getId());
auditLogDirector.log(logable, AuditLogType.VM_WAS_SET_DOWN_DUE_TO_HOST_REBOOT_OR_MANUAL_FENCE);
}
/**
* Check if given agent is valid.
* The check that is made is that 'user' and 'password' values are not empty.
*/
protected boolean isFenceAgentValid(FenceAgent agent) {
if (StringUtils.isEmpty(agent.getUser()) ||
StringUtils.isEmpty(agent.getPassword())) {
addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_PM_ENABLED_WITHOUT_AGENT_CREDENTIALS);
return false;
} else {
return true;
}
}
/**
* Check if power management(pm) parameters are legal.
* Parameters are valid if:
* 1) user don't have pm enabled and fence agents are null.
* 2) user has pm enabled and send valid non-empty list of fence agents
* Parameters aren't valid if:
* 1) user has pm enabled and send empty list of fence agents
*/
protected boolean isPowerManagementLegal(boolean pmEnabled,
List<FenceAgent> fenceAgents,
String clusterCompatibilityVersion) {
if (pmEnabled && fenceAgents != null) {
if (fenceAgents.isEmpty()) {
addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_PM_ENABLED_WITHOUT_AGENT);
return false;
}
FenceValidator fenceValidator = new FenceValidator();
for (FenceAgent agent : fenceAgents) {
if (!fenceValidator.isFenceAgentVersionCompatible(agent,
clusterCompatibilityVersion,
getReturnValue().getValidationMessages())
|| !isFenceAgentValid(agent)) {
return false;
}
}
}
return true;
}
@Override
public List<PermissionSubject> getPermissionCheckSubjects() {
return Collections.singletonList(new PermissionSubject(getVdsId(), VdcObjectType.VDS,
getActionType().getActionGroup()));
}
public void handleVdsError(VDSReturnValue returnValue) {
getReturnValue().getFault().setError(returnValue.getVdsError().getCode());
getReturnValue().getFault().setMessage(returnValue.getVdsError().getMessage());
getReturnValue().getExecuteFailedMessages().add(returnValue.getVdsError().getMessage());
}
public EngineLock acquireMonitorLock(String lockReleaseMessage) {
return this.hostLocking.acquireMonitorLock(getVds(), lockReleaseMessage, log);
}
protected void handleError(Exception e, VDSStatus status) {
log.error(
"Host installation failed for host '{}', '{}': {}",
getVds().getId(),
getVds().getName(),
e.getMessage());
log.debug("Exception", e);
setVdsStatus(status);
setSucceeded(false);
_failureMessage = e.getMessage();
}
protected VDSReturnValue setVdsStatus(VDSStatus status) {
SetVdsStatusVDSCommandParameters parameters = new SetVdsStatusVDSCommandParameters(getVdsId(), status);
return invokeSetHostStatus(parameters);
}
protected VDSReturnValue setVdsStatus(VDSStatus status, NonOperationalReason reason) {
SetVdsStatusVDSCommandParameters parameters = new SetVdsStatusVDSCommandParameters(getVdsId(), status, reason);
return invokeSetHostStatus(parameters);
}
private VDSReturnValue invokeSetHostStatus(SetVdsStatusVDSCommandParameters parameters) {
return runVdsCommand(VDSCommandType.SetVdsStatus, parameters);
}
protected String getErrorMessage(String msg) {
return !StringUtils.isEmpty(msg) ? msg : String.format(
"Please refer to %1$s/engine.log and log logs under %1$s/host-deploy/ for further details.",
EngineLocalConfig.getInstance().getLogDir()
);
}
protected boolean validateNetworkProviderProperties(Guid providerId, String networkMappings) {
NetworkProviderValidator validator = new NetworkProviderValidator(providerDao.get(providerId));
return validate(validator.providerIsSet())
&& validate(validator.providerTypeValid())
&& validate(validator.networkMappingsProvided(networkMappings))
&& validate(validator.messagingBrokerProvided());
}
}