package org.ovirt.engine.core.bll.gluster;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.LockMessagesMatchUtil;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.gluster.tasks.GlusterTaskUtils;
import org.ovirt.engine.core.bll.job.ExecutionContext;
import org.ovirt.engine.core.bll.job.JobRepository;
import org.ovirt.engine.core.bll.validator.gluster.GlusterBrickValidator;
import org.ovirt.engine.core.common.action.gluster.GlusterVolumeParameters;
import org.ovirt.engine.core.common.asynctasks.gluster.GlusterAsyncTask;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
import org.ovirt.engine.core.common.constants.gluster.GlusterConstants;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.job.ExternalSystemType;
import org.ovirt.engine.core.common.job.JobExecutionStatus;
import org.ovirt.engine.core.common.job.Step;
import org.ovirt.engine.core.common.job.StepEnum;
import org.ovirt.engine.core.common.locks.LockingGroup;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.job.ExecutionMessageDirector;
import org.ovirt.engine.core.dao.StepDao;
import org.ovirt.engine.core.utils.lock.EngineLock;
public abstract class GlusterAsyncCommandBase<T extends GlusterVolumeParameters> extends GlusterVolumeCommandBase<T> {
private Step asyncTaskStep;
@Inject
private JobRepository jobRepository;
@Inject
protected GlusterTaskUtils glusterTaskUtils;
@Inject
private StepDao stepDao;
public GlusterAsyncCommandBase(T params, CommandContext commandContext) {
super(params, commandContext);
}
@Override
protected boolean validate() {
GlusterVolumeEntity glusterVolume = getGlusterVolume();
if (!super.validate()) {
return false;
}
if (!glusterVolume.isOnline()) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_SHOULD_BE_STARTED);
}
return true;
}
@Override
protected void setActionMessageParameters() {
addValidationMessageVariable("volumeName", getGlusterVolumeName());
addValidationMessageVariable("cluster", getClusterName());
}
protected Map<String, String> getStepMessageMap(JobExecutionStatus status, String jobInfo) {
Map<String, String> values = new HashMap<>();
values.put(GlusterConstants.CLUSTER, getClusterName());
values.put(GlusterConstants.VOLUME, getGlusterVolumeName());
values.put(GlusterConstants.JOB_STATUS, status.toString());
values.put(GlusterConstants.JOB_INFO, jobInfo == null ? " " : jobInfo);
return values;
}
/**
*
* @return the StepEnum associated with this command. This is used to start a sub step for the executing step.
*/
protected abstract StepEnum getStepType();
protected void startSubStep() {
asyncTaskStep =
executionHandler.addSubStep(this.getExecutionContext(),
getExecutionContext().getJob().getStep(StepEnum.EXECUTING),
getStepType(),
ExecutionMessageDirector.resolveStepMessage(getStepType(),
getStepMessageMap(JobExecutionStatus.STARTED, null)));
}
protected void endStepJobAborted(String jobInfo) {
endStepJob(JobExecutionStatus.ABORTED, getStepMessageMap(JobExecutionStatus.ABORTED, jobInfo), false);
}
protected void endStepJob(JobExecutionStatus status, Map<String, String> stepMessageMap, boolean exitStatus) {
GlusterAsyncTask asyncTask = getGlusterVolume().getAsyncTask();
// Gluster Task will be associated with only one step ( REBALANCING_VOLUME or REMOVING_BRICK)
Step step = stepDao.getStepsByExternalId(asyncTask.getTaskId()).get(0);
step.setStatus(status);
step.setEndTime(new Date());
step.setDescription(ExecutionMessageDirector.resolveStepMessage(getStepType(), stepMessageMap));
jobRepository.updateStep(step);
ExecutionContext finalContext = executionHandler.createFinalizingContext(step.getId());
executionHandler.endTaskStepAndJob(finalContext, exitStatus);
}
protected GlusterAsyncTask handleTaskReturn(GlusterAsyncTask asyncTask) {
Guid externalTaskId = asyncTask.getTaskId();
asyncTaskStep.setStatus(JobExecutionStatus.STARTED);
executionHandler.updateStepExternalId(asyncTaskStep,
externalTaskId,
ExternalSystemType.GLUSTER);
getExecutionContext().getJob().setStatus(JobExecutionStatus.STARTED);
asyncTask.setStepId(asyncTaskStep.getId());
return asyncTask;
}
@Override
protected Map<String, Pair<String, String>> getExclusiveLocks() {
return Collections.singletonMap(getGlusterVolumeId().toString(),
LockMessagesMatchUtil.makeLockingPair(LockingGroup.GLUSTER,
EngineMessage.ACTION_TYPE_FAILED_VOLUME_OPERATION_IN_PROGRESS));
}
protected void releaseVolumeLock() {
EngineLock lock = new EngineLock(getExclusiveLocks(), getSharedLocks());
setLock(lock);
freeLock();
}
public GlusterBrickValidator getBrickValidator() {
return new GlusterBrickValidator();
}
}