package org.ovirt.engine.core.bll.gluster;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.LockMessagesMatchUtil;
import org.ovirt.engine.core.bll.VdsCommand;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.bll.validator.HostValidator;
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.CreateBrickParameters;
import org.ovirt.engine.core.common.businessentities.Cluster;
import org.ovirt.engine.core.common.businessentities.RaidType;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.gluster.StorageDevice;
import org.ovirt.engine.core.common.constants.gluster.GlusterConstants;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.locks.LockingGroup;
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.CreateBrickVDSParameters;
import org.ovirt.engine.core.dao.gluster.StorageDeviceDao;
public class CreateBrickCommand extends VdsCommand<CreateBrickParameters> {
@Inject
private StorageDeviceDao storageDeviceDao;
public CreateBrickCommand(CreateBrickParameters parameters, CommandContext cmdContext) {
super(parameters, cmdContext);
}
@Override
protected void setActionMessageParameters() {
addValidationMessage(EngineMessage.VAR__ACTION__CREATE);
addValidationMessage(EngineMessage.VAR__TYPE__GLUSTER_BRICK);
addValidationMessageVariable("brickName", getParameters().getLvName());
}
@Override
public Map<String, String> getCustomValues() {
addCustomValue(GlusterConstants.BRICK_NAME, getParameters().getLvName());
return super.getCustomValues();
}
@Override
protected boolean validate() {
Cluster cluster = getCluster();
if (!cluster.supportsGlusterService()) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_STORAGE_PROVISIONING_NOT_SUPPORTED_BY_CLUSTER);
}
HostValidator validator = HostValidator.createInstance(getVds());
if (!validate(validator.isUp())) {
return false;
}
String deviceType;
if (getParameters().getDisks() == null || getParameters().getDisks().isEmpty()) {
addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_STORAGE_DEVICE_REQUIRED);
return false;
} else {
deviceType = getParameters().getDisks().get(0).getDevType();
}
for (StorageDevice device : getParameters().getDisks()) {
// Check that all the selected devices are of same type. Mixing device types in Brick creation is not
// allowed
// for performance reasons.
if (!Objects.equals(deviceType, device.getDevType())) {
addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_DIFFERENT_STORAGE_DEVICE_TYPES_SELECTED);
return false;
}
// Ensure that device is not already used by some other brick or LVM.
if (!device.getCanCreateBrick()) {
addValidationMessage(EngineMessage.ACTION_TYPE_FAILED_DEVICE_IS_ALREADY_IN_USE);
addValidationMessageVariable("storageDevice", device.getName());
return false;
}
}
return true;
}
@Override
protected void executeCommand() {
Map<String, Object> raidParams = new HashMap<>();
if (!getParameters().getRaidType().equals(RaidType.NONE)
&& !getParameters().getRaidType().equals(RaidType.RAID0)) {
raidParams.put("type", getParameters().getRaidType().getValue()); //$NON-NLS-1$
raidParams.put("pdCount", getParameters().getNoOfPhysicalDisksInRaidVolume()); //$NON-NLS-1$
raidParams.put("stripeSize", getParameters().getStripeSize()); //$NON-NLS-1$
}
VDSReturnValue returnValue = runVdsCommand(
VDSCommandType.CreateBrick,
new CreateBrickVDSParameters(getVdsId(),
getParameters().getLvName(),
getParameters().getMountPoint(),
raidParams,
GlusterConstants.FS_TYPE_XFS,
getParameters().getDisks()));
setSucceeded(returnValue.getSucceeded());
if (getSucceeded()) {
StorageDevice storageDevice = (StorageDevice) returnValue.getReturnValue();
storageDevice.setMountPoint(getParameters().getMountPoint());
storageDevice.setGlusterBrick(true);
saveStoageDevice(storageDevice);
// Reset the isFree flag on all the devices which are used for brick creation
resetIsFreeFlag(getParameters().getDisks());
} else {
handleVdsError(returnValue);
}
}
private void resetIsFreeFlag(List<StorageDevice> devices) {
for (StorageDevice device : devices) {
storageDeviceDao.updateIsFreeFlag(device.getId(), false);
}
}
private void saveStoageDevice(StorageDevice storageDevice) {
storageDeviceDao.save(storageDevice);
}
@Override
protected VDS getVds() {
return super.getVds();
}
@Override
protected Map<String, Pair<String, String>> getExclusiveLocks() {
Map<String, Pair<String, String>> locksMap = new HashMap<>();
for (StorageDevice disk : getParameters().getDisks()) {
locksMap.put(disk.getId().toString(),
LockMessagesMatchUtil.makeLockingPair(LockingGroup.HOST_STORAGE_DEVICES,
EngineMessage.ACTION_TYPE_FAILED_STORAGE_DEVICE_LOCKED));
}
return locksMap;
}
@Override
protected LockProperties applyLockProperties(LockProperties lockProperties) {
return lockProperties.withScope(Scope.Execution).withWait(false);
}
@Override
public AuditLogType getAuditLogTypeValue() {
return getSucceeded() ? AuditLogType.CREATE_GLUSTER_BRICK : AuditLogType.CREATE_GLUSTER_BRICK_FAILED;
}
}