package org.ovirt.engine.core.bll.gluster; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import javax.inject.Inject; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute; import org.ovirt.engine.core.bll.context.CommandContext; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.LockProperties; import org.ovirt.engine.core.common.action.LockProperties.Scope; import org.ovirt.engine.core.common.action.gluster.GlusterHookManageParameters; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VDSStatus; import org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStatus; import org.ovirt.engine.core.common.businessentities.gluster.GlusterServerHook; import org.ovirt.engine.core.common.constants.gluster.GlusterConstants; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.utils.Pair; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.common.vdscommands.gluster.GlusterHookVDSParameters; import org.ovirt.engine.core.dao.VdsDao; import org.ovirt.engine.core.dao.gluster.GlusterHooksDao; import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil; /** * BLL command to add gluster hook on servers where the hook is missing */ @NonTransactiveCommandAttribute public class AddGlusterHookCommand<T extends GlusterHookManageParameters> extends GlusterHookCommandBase<T> { @Inject private VdsDao vdsDao; @Inject private GlusterHooksDao glusterHooksDao; protected List<String> errors = new ArrayList<>(); private List<GlusterServerHook> missingServerHooks = null; public AddGlusterHookCommand(T params, CommandContext commandContext) { super(params, commandContext); } @Override protected LockProperties applyLockProperties(LockProperties lockProperties) { return lockProperties.withScope(Scope.Execution).withWait(true); } @Override protected void setActionMessageParameters() { addValidationMessage(EngineMessage.VAR__ACTION__ADD); addValidationMessage(EngineMessage.VAR__TYPE__GLUSTER_HOOK); } private List<GlusterServerHook> getMissingServerHooks() { //get all destination servers - only serverhooks where hook is missing if (missingServerHooks == null) { missingServerHooks = new ArrayList<>(); for (GlusterServerHook serverHook: getGlusterHook().getServerHooks()) { if (serverHook.getStatus().equals(GlusterHookStatus.MISSING)) { missingServerHooks.add(serverHook); } } } return missingServerHooks; } @Override protected boolean validate() { if (!super.validate()) { return false; } if (getMissingServerHooks().isEmpty()) { addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_GLUSTER_HOOK_NO_CONFLICT_SERVERS); return false; } for (GlusterServerHook serverHook: getMissingServerHooks()) { VDS vds = vdsDao.get(serverHook.getServerId()); if (vds == null || vds.getStatus() != VDSStatus.Up) { String vdsName = vds != null ? vds.getName() : GlusterConstants.NO_SERVER; setVdsName(vdsName); addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_SERVER_STATUS_NOT_UP); addValidationMessage(String.format("$%1$s %2$s", "VdsName", vdsName)); return false; } } return true; } @Override protected void executeCommand() { entity = getGlusterHook(); addCustomValue(GlusterConstants.HOOK_NAME, entity.getName()); final boolean hookEnabled = entity.getStatus() == GlusterHookStatus.ENABLED; List<Callable<Pair<GlusterServerHook, VDSReturnValue>>> taskList = new ArrayList<>(); for (final GlusterServerHook serverHook : getMissingServerHooks()) { taskList.add(() -> { VDSReturnValue returnValue; returnValue = runVdsCommand( VDSCommandType.AddGlusterHook, new GlusterHookVDSParameters(serverHook.getServerId(), entity.getGlusterCommand(), entity.getStage(), entity.getName(), entity.getContent(), entity.getChecksum(), hookEnabled)); return new Pair<>(serverHook, returnValue); }); } if (!taskList.isEmpty()) { List<Pair<GlusterServerHook, VDSReturnValue>> pairResults = ThreadPoolUtil.invokeAll(taskList); for (Pair<GlusterServerHook, VDSReturnValue> pairResult : pairResults) { VDSReturnValue retValue = pairResult.getSecond(); if (!retValue.getSucceeded() ) { errors.add(retValue.getVdsError().getMessage()); } else { //hook added successfully, so remove from gluster server hooks table glusterHooksDao.removeGlusterServerHook(pairResult.getFirst().getHookId(), pairResult.getFirst().getServerId()); } } } if (errors.size() > 0) { setSucceeded(false); errorType = AuditLogType.GLUSTER_HOOK_ADD_FAILED; handleVdsErrors(getAuditLogTypeValue(), errors); addCustomValue(GlusterConstants.FAILURE_MESSAGE , StringUtils.join(errors, System.lineSeparator())); } else { setSucceeded(true); } if (getSucceeded()) { entity.removeMissingConflict(); updateGlusterHook(entity); } } @Override public Map<String, String> getJobMessageProperties() { if (jobProperties == null) { jobProperties = super.getJobMessageProperties(); if (getGlusterHook() != null) { jobProperties.put(GlusterConstants.HOOK_NAME, getGlusterHook().getName()); } } return jobProperties; } @Override public AuditLogType getAuditLogTypeValue() { return getSucceeded() ? AuditLogType.GLUSTER_HOOK_ADDED : errorType; } }