package org.ovirt.engine.core.bll.storage.disk.image;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.CommandBase;
import org.ovirt.engine.core.bll.InternalCommandAttribute;
import org.ovirt.engine.core.bll.NonTransactiveCommandAttribute;
import org.ovirt.engine.core.bll.SerialChildCommandsExecutionCallback;
import org.ovirt.engine.core.bll.SerialChildExecutingCommand;
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.action.CloneImageGroupVolumesStructureCommandParameters;
import org.ovirt.engine.core.common.action.CopyDataCommandParameters;
import org.ovirt.engine.core.common.action.CopyImageGroupVolumesDataCommandParameters;
import org.ovirt.engine.core.common.action.CopyImageGroupWithDataCommandParameters;
import org.ovirt.engine.core.common.action.CopyImageGroupWithDataCommandParameters.CopyStage;
import org.ovirt.engine.core.common.action.CreateVolumeContainerCommandParameters;
import org.ovirt.engine.core.common.action.VdcActionParametersBase.EndProcedure;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.businessentities.LocationInfo;
import org.ovirt.engine.core.common.businessentities.VdsmImageLocationInfo;
import org.ovirt.engine.core.common.businessentities.storage.DiskImage;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.DiskDao;
import org.ovirt.engine.core.dao.DiskImageDao;
@InternalCommandAttribute
@NonTransactiveCommandAttribute
public class CopyImageGroupWithDataCommand<T extends CopyImageGroupWithDataCommandParameters>
extends CommandBase<T> implements SerialChildExecutingCommand {
@Inject
private DiskImageDao diskImageDao;
@Inject
private DiskDao diskDao;
private DiskImage diskImage;
public CopyImageGroupWithDataCommand(T parameters, CommandContext cmdContext) {
super(parameters, cmdContext);
setStoragePoolId(getParameters().getStoragePoolId());
setStorageDomainId(getParameters().getDestDomain());
}
private void prepareParameters() {
if (getParameters().getJobWeight() != null) {
Map<String, Integer> weights = new HashMap<>();
int createWeight = Long.valueOf(Math.round(getParameters().getJobWeight() / 10d)).intValue();
weights.put(CopyStage.DEST_CREATION.name(), createWeight);
weights.put(CopyStage.DATA_COPY.name(), getParameters().getJobWeight() - createWeight);
getParameters().setOperationsJobWeight(weights);
}
}
@Override
protected void executeCommand() {
prepareParameters();
persistCommandIfNeeded();
if (getParameters().isCollapse()) {
createVolume();
} else {
cloneStructureNotCollapsed();
}
setSucceeded(true);
}
@Override
public List<PermissionSubject> getPermissionCheckSubjects() {
return Collections.emptyList();
}
private void cloneStructureNotCollapsed() {
CloneImageGroupVolumesStructureCommandParameters p = new CloneImageGroupVolumesStructureCommandParameters
(getParameters().getStoragePoolId(), getParameters().getSrcDomain(), getParameters().getDestDomain(),
getParameters().getImageGroupID(), getActionType(), getParameters());
p.setParentParameters(getParameters());
p.setParentCommand(getActionType());
p.setEndProcedure(EndProcedure.COMMAND_MANAGED);
p.setJobWeight(getParameters().getOperationsJobWeight().get(CopyStage.DEST_CREATION.name()));
runInternalAction(VdcActionType.CloneImageGroupVolumesStructure, p);
}
private void populateDiskSnapshotsInfoFromStorage() {
getDiskImage().getSnapshots().clear();
List<DiskImage> images = diskImageDao.getAllSnapshotsForImageGroup(getParameters().getImageGroupID());
for (DiskImage image : images) {
getDiskImage().getSnapshots().add(ImagesHandler.getVolumeInfoFromVdsm(getParameters().getStoragePoolId(),
getParameters().getSrcDomain(), getParameters().getImageGroupID(), image.getImageId()));
}
}
private void updateStage(CopyStage stage) {
getParameters().setStage(stage);
persistCommand(getParameters().getParentCommand(), getCallback() != null);
}
@Override
public CommandCallback getCallback() {
return new SerialChildCommandsExecutionCallback();
}
private void createVolume() {
populateDiskSnapshotsInfoFromStorage();
CreateVolumeContainerCommandParameters parameters = new CreateVolumeContainerCommandParameters(
getParameters().getStoragePoolId(),
getParameters().getDestDomain(),
Guid.Empty,
Guid.Empty,
getParameters().getDestImageGroupId(),
getParameters().getDestinationImageId(),
getParameters().getDestinationFormat(),
getParameters().getDescription(),
getDiskImage().getSize(),
ImagesHandler.determineTotalImageInitialSize(getDiskImage(),
getParameters().getDestinationFormat(),
getParameters().getSrcDomain(),
getParameters().getDestDomain()));
parameters.setJobWeight(getParameters().getOperationsJobWeight().get(CopyStage.DEST_CREATION.name()));
parameters.setParentCommand(getActionType());
parameters.setParentParameters(getParameters());
parameters.setEndProcedure(EndProcedure.COMMAND_MANAGED);
runInternalAction(VdcActionType.CreateVolumeContainer, parameters);
}
@Override
public boolean performNextOperation(int completedChildCount) {
if (getParameters().getStage() == CopyStage.DEST_CREATION) {
updateStage(CopyStage.DATA_COPY);
Integer weight = getParameters().getOperationsJobWeight().get(CopyStage.DATA_COPY.name());
if (getParameters().isCollapse()) {
CopyDataCommandParameters parameters = new CopyDataCommandParameters(getParameters().getStoragePoolId(),
buildImageLocationInfo(getParameters().getSrcDomain(), getParameters().getImageGroupID(),
getParameters().getImageId()),
buildImageLocationInfo(getParameters().getDestDomain(), getParameters().getDestImageGroupId(),
getParameters().getDestinationImageId()), true);
parameters.setEndProcedure(EndProcedure.COMMAND_MANAGED);
parameters.setParentCommand(getActionType());
parameters.setParentParameters(getParameters());
parameters.setJobWeight(weight);
runInternalAction(VdcActionType.CopyData, parameters);
} else {
CopyImageGroupVolumesDataCommandParameters p = new CopyImageGroupVolumesDataCommandParameters(
getParameters().getStoragePoolId(),
getParameters().getSrcDomain(),
getParameters().getImageGroupID(),
getParameters().getDestDomain(),
getActionType(),
getParameters()
);
p.setEndProcedure(EndProcedure.COMMAND_MANAGED);
p.setJobWeight(weight);
runInternalAction(VdcActionType.CopyImageGroupVolumesData, p);
}
return true;
}
return false;
}
private LocationInfo buildImageLocationInfo(Guid domId, Guid imageGroupId, Guid imageId) {
return new VdsmImageLocationInfo(domId, imageGroupId, imageId, null);
}
private DiskImage getDiskImage() {
if (diskImage == null) {
diskImage = (DiskImage) diskDao.get(getParameters().getImageGroupID());
}
return diskImage;
}
}