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.action.LockProperties;
import org.ovirt.engine.core.common.action.LockProperties.Scope;
import org.ovirt.engine.core.common.action.gluster.GlusterHookParameters;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterHookStatus;
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.gluster.GlusterHooksDao;
import org.ovirt.engine.core.utils.threadpool.ThreadPoolUtil;
/**
* BLL command to enable Gluster hook
*/
@NonTransactiveCommandAttribute
public abstract class GlusterHookStatusChangeCommand<T extends GlusterHookParameters> extends GlusterHookCommandBase<T> {
@Inject
private GlusterHooksDao glusterHooksDao;
protected List<String> errors = new ArrayList<>();
private List<VDS> upServers = null;
public GlusterHookStatusChangeCommand(T params, CommandContext commandContext) {
super(params, commandContext);
}
@Override
protected LockProperties applyLockProperties(LockProperties lockProperties) {
return lockProperties.withScope(Scope.Execution).withWait(true);
}
private List<VDS> getAllUpServers() {
if (upServers == null) {
upServers = getAllUpServers(getGlusterHook().getClusterId());
}
return upServers;
}
@Override
protected boolean validate() {
if (!super.validate()) {
return false;
}
if (getAllUpServers() == null || getAllUpServers().isEmpty()) {
addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_NO_UP_SERVER_FOUND);
return false;
}
return true;
}
@Override
protected void executeCommand() {
entity = getGlusterHook();
addCustomValue(GlusterConstants.HOOK_NAME, entity.getName());
if (getAllUpServers().size() < getClusterUtils().getServerCount(getGlusterHook().getClusterId())) {
errors.add(EngineMessage.CLUSTER_ALL_SERVERS_NOT_UP.toString());
}
List<Callable<Pair<VDS, VDSReturnValue>>> taskList = new ArrayList<>();
for (final VDS upServer : getAllUpServers()) {
taskList.add(() -> {
VDSReturnValue returnValue =
runVdsCommand(
getStatusChangeVDSCommand(),
new GlusterHookVDSParameters(upServer.getId(),
entity.getGlusterCommand(),
entity.getStage(),
entity.getName()));
return new Pair<>(upServer, returnValue);
});
}
boolean atLeastOneSuccess = false;
List<Pair<VDS, VDSReturnValue>> pairResults = ThreadPoolUtil.invokeAll(taskList);
for (Pair<VDS, VDSReturnValue> pairResult : pairResults) {
VDSReturnValue retValue = pairResult.getSecond();
if (retValue.getSucceeded() ) {
atLeastOneSuccess = true;
// update status in database
updateServerHookStatusInDb(getGlusterHook().getId(), pairResult.getFirst().getId(), getNewStatus());
} else {
errors.add(retValue.getVdsError().getMessage());
}
}
setSucceeded(atLeastOneSuccess);
if (errors.size() > 0) {
// conflict in status
entity.addStatusConflict();
handleVdsErrors(getAuditLogTypeValue(), errors);
addCustomValue(GlusterConstants.FAILURE_MESSAGE , StringUtils.join(errors, System.lineSeparator()));
}
//The intention was to enable/disable hook. So we update the entity with new status if command succeeded
if (getSucceeded()) {
entity.setStatus(getNewStatus());
//no longer conflicts as all hooks have same status
entity.removeStatusConflict();
updateHookInDb(entity);
if (entity.getConflictStatus() == 0) {
//all conflicts have been resolved, remove server hooks
glusterHooksDao.removeGlusterServerHooks(entity.getId());
}
}
}
@Override
public Map<String, String> getJobMessageProperties() {
if (jobProperties == null) {
jobProperties = super.getJobMessageProperties();
if (getGlusterHook() != null) {
jobProperties.put(GlusterConstants.HOOK_NAME, getGlusterHook().getName());
}
}
return jobProperties;
}
protected abstract VDSCommandType getStatusChangeVDSCommand();
protected abstract GlusterHookStatus getNewStatus();
}