package org.ovirt.engine.core.bll;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.tasks.interfaces.CommandCallback;
import org.ovirt.engine.core.bll.utils.PermissionSubject;
import org.ovirt.engine.core.common.VdcObjectType;
import org.ovirt.engine.core.common.action.MergeParameters;
import org.ovirt.engine.core.common.businessentities.VmBlockJob;
import org.ovirt.engine.core.common.businessentities.VmJobState;
import org.ovirt.engine.core.common.businessentities.VmJobType;
import org.ovirt.engine.core.common.errors.EngineError;
import org.ovirt.engine.core.common.errors.EngineException;
import org.ovirt.engine.core.common.vdscommands.MergeVDSCommandParameters;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.common.vdscommands.VDSParametersBase;
import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
import org.ovirt.engine.core.compat.CommandStatus;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.di.Injector;
import org.ovirt.engine.core.vdsbroker.monitoring.VmJobsMonitoring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@InternalCommandAttribute
public class MergeCommand<T extends MergeParameters>
extends CommandBase<T> {
private static final Logger log = LoggerFactory.getLogger(MergeCommand.class);
@Inject
private VmJobsMonitoring vmJobsMonitoring;
public MergeCommand(T parameters, CommandContext cmdContext) {
super(parameters, cmdContext);
}
@Override
public void executeCommand() {
boolean mergeRunning = false;
try {
VDSReturnValue vdsReturnValue = runVdsCommand(VDSCommandType.Merge,
createVDSParameters());
if (vdsReturnValue.getSucceeded()) {
Guid jobId = (Guid) vdsReturnValue.getReturnValue();
persistBlockJobPlaceholder(jobId);
getParameters().setVmJobId(jobId);
persistCommand(getParameters().getParentCommand(), true);
log.debug("Merge started successfully");
mergeRunning = true;
} else {
log.error("Failed to start Merge on VDS");
}
} catch (EngineException e) {
log.error("Engine exception thrown while sending merge command", e);
if (e.getErrorCode() == EngineError.imageErr || e.getErrorCode() == EngineError.mergeErr) {
// In this case, we are not certain whether merge is currently running or
// whether one of the relevant volumes already removed from the chain. In these cases,
// we want to verify the current state; therefore, we consider the merge to be running.
mergeRunning = true;
}
} finally {
if (mergeRunning) {
setSucceeded(true);
} else {
setCommandStatus(CommandStatus.FAILED);
}
}
}
private VDSParametersBase createVDSParameters() {
return new MergeVDSCommandParameters(
getParameters().getVdsId(),
getParameters().getVmId(),
getParameters().getStoragePoolId(),
getParameters().getStorageDomainId(),
getParameters().getImageGroupId(),
getParameters().getImageId(),
getParameters().getBaseImage().getImageId(),
getParameters().getTopImage().getImageId(),
getParameters().getBandwidth());
}
private void persistBlockJobPlaceholder(Guid jobId) {
VmBlockJob blockJob = new VmBlockJob();
blockJob.setVmId(getParameters().getVmId());
blockJob.setId(jobId);
blockJob.setJobType(VmJobType.BLOCK);
blockJob.setJobState(VmJobState.UNKNOWN);
blockJob.setImageGroupId(getParameters().getImageGroupId());
vmJobsMonitoring.addJob(blockJob);
}
@Override
public List<PermissionSubject> getPermissionCheckSubjects() {
return Collections.singletonList(new PermissionSubject(getParameters().getStorageDomainId(),
VdcObjectType.Storage,
getActionType().getActionGroup()));
}
@Override
public CommandCallback getCallback() {
return Injector.injectMembers(new MergeCommandCallback());
}
}