package org.ovirt.engine.core.bll.gluster;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.ovirt.engine.core.bll.context.CommandContext;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.action.gluster.GlusterVolumeGeoRepSessionParameters;
import org.ovirt.engine.core.common.action.gluster.SetUpMountBrokerParameters;
import org.ovirt.engine.core.common.action.gluster.SetUpPasswordLessSSHParameters;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.VDSStatus;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterBrickEntity;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterGeoRepSession;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterStatus;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity;
import org.ovirt.engine.core.common.businessentities.gluster.ServiceType;
import org.ovirt.engine.core.common.constants.gluster.GlusterConstants;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.vdscommands.VDSCommandType;
import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
import org.ovirt.engine.core.common.vdscommands.gluster.GlusterVolumeGeoRepSessionVDSParameters;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.VdsDao;
public class CreateGlusterVolumeGeoRepSessionCommand extends GlusterVolumeCommandBase<GlusterVolumeGeoRepSessionParameters> {
private GlusterVolumeEntity slaveVolume;
private Set<VDS> remoteServersSet;
private VDS slaveHost;
@Inject
private GlusterGeoRepSyncJob glusterGeoRepSyncJob;
@Inject
private VdsDao vdsDao;
public CreateGlusterVolumeGeoRepSessionCommand(GlusterVolumeGeoRepSessionParameters params, CommandContext context) {
super(params, context);
}
@Override
protected boolean validate() {
slaveHost = getSlaveHost();
if (slaveHost == null) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_HOST_NOT_EXIST);
}
if (slaveHost.getStatus() != VDSStatus.Up) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_SERVER_STATUS_NOT_UP,
String.format("$%1$s %2$s", "VdsName", slaveHost.getName()));
}
slaveVolume = getSlaveVolume();
if (slaveVolume == null) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_INVALID);
}
if (slaveVolume.getStatus() != GlusterStatus.UP) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_GLUSTER_VOLUME_SHOULD_BE_STARTED);
}
if (!areAllRemoteServersUp()) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_ONE_OR_MORE_REMOTE_HOSTS_ARE_NOT_ACCESSIBLE);
}
GlusterGeoRepSession geoRepSession =
glusterGeoRepDao.getGeoRepSession(getGlusterVolumeId(),
slaveHost.getId(),
getParameters().getSlaveVolumeName());
if (geoRepSession != null) {
return failValidation(EngineMessage.ACTION_TYPE_FAILED_GLUSTER_GEOREP_SESSION_ALREADY_CREATED);
}
return super.validate();
}
protected GlusterVolumeEntity getSlaveVolume() {
return glusterVolumeDao.getByName(slaveHost.getClusterId(), getParameters().getSlaveVolumeName());
}
protected VDS getSlaveHost() {
return vdsDao.get(getParameters().getSlaveHostId());
}
private boolean areAllRemoteServersUp() {
remoteServersSet = fetchRemoteServers();
for (VDS currentRemoteServer : remoteServersSet) {
if (currentRemoteServer.getStatus() != VDSStatus.Up) {
return false;
}
}
return true;
}
@Override
public Map<String, String> getCustomValues() {
addCustomValue(GlusterConstants.VOLUME_NAME, getGlusterVolumeName());
addCustomValue(GlusterConstants.GEO_REP_USER, getParameters().getUserName());
addCustomValue(GlusterConstants.GEO_REP_SLAVE_VOLUME_NAME, getParameters().getSlaveVolumeName());
addCustomValue(GlusterConstants.SERVICE_TYPE, ServiceType.GLUSTER.name());
return super.getCustomValues();
}
@Override
protected void setActionMessageParameters() {
addValidationMessage(EngineMessage.VAR__ACTION__CREATE);
addValidationMessage(EngineMessage.VAR__TYPE__GLUSTER_GEOREP_SESSION);
}
@Override
protected void executeCommand() {
boolean rootSession = getParameters().getUserName().equalsIgnoreCase("root");
boolean succeeded = true;
Set<Guid> remoteServerIds = getServerIds(remoteServersSet);
Guid slaveHostId = getParameters().getSlaveHostId();
if (!rootSession) {
VdcReturnValueBase completeMountBrokerSetupOnSlaveInternalAction =
getBackend().runInternalAction(VdcActionType.SetupGlusterGeoRepMountBrokerInternal,
new SetUpMountBrokerParameters(vdsDao.get(slaveHostId).getClusterId(),
new HashSet<>(Collections.singletonList(getParameters().getSlaveHostId())),
getParameters().getSlaveVolumeName(),
getParameters().getUserName(),
getParameters().getUserGroup()));
succeeded = evaluateReturnValue(AuditLogType.GLUSTER_GEOREP_SETUP_MOUNT_BROKER_FAILED, completeMountBrokerSetupOnSlaveInternalAction);
remoteServerIds.remove(slaveHostId);
if (succeeded) {
auditLogDirector.log(this, AuditLogType.GLUSTER_SETUP_GEOREP_MOUNT_BROKER);
if (!remoteServerIds.isEmpty()) {
VdcReturnValueBase mountBrokerPartialSetupInternalAction =
getBackend().runInternalAction(VdcActionType.SetupGlusterGeoRepMountBrokerInternal,
new SetUpMountBrokerParameters(vdsDao.get(slaveHostId).getClusterId(),
remoteServerIds,
getParameters().getSlaveVolumeName(),
getParameters().getUserName()));
succeeded =
evaluateReturnValue(AuditLogType.GLUSTER_GEOREP_SETUP_MOUNT_BROKER_FAILED,
mountBrokerPartialSetupInternalAction);
if (succeeded) {
auditLogDirector.log(this, AuditLogType.GLUSTER_SETUP_GEOREP_MOUNT_BROKER);
}
}
}
}
if (succeeded) {
remoteServerIds.add(slaveHostId);
VdcReturnValueBase setUpPasswordLessSSHinternalAction =
runInternalAction(VdcActionType.SetUpPasswordLessSSHInternal,
new SetUpPasswordLessSSHParameters(upServer.getClusterId(),
remoteServerIds,
getParameters().getUserName()));
succeeded = evaluateReturnValue(errorType, setUpPasswordLessSSHinternalAction);
if (succeeded) {
auditLogDirector.log(this, AuditLogType.SET_UP_PASSWORDLESS_SSH);
VDSReturnValue createVdsReturnValue = runVdsCommand(VDSCommandType.CreateGlusterVolumeGeoRepSession,
new GlusterVolumeGeoRepSessionVDSParameters(upServer.getId(),
getGlusterVolumeName(),
vdsDao.get(slaveHostId).getHostName(),
getParameters().getSlaveVolumeName(),
getParameters().getUserName(),
getParameters().isForce()));
succeeded = evaluateReturnValue(AuditLogType.GLUSTER_GEOREP_SESSION_CREATE_FAILED, createVdsReturnValue);
if (succeeded) {
glusterGeoRepSyncJob.refreshGeoRepDataForVolume(getGlusterVolume());
}
}
}
setSucceeded(succeeded);
}
private Set<Guid> getServerIds(Set<VDS> remoteServersSet) {
Set<Guid> remoteServerIds = new HashSet<>();
for (VDS currentVds : remoteServersSet) {
remoteServerIds.add(currentVds.getId());
}
return remoteServerIds;
}
private Set<VDS> fetchRemoteServers() {
Set<VDS> remoteServers = new HashSet<>();
List<GlusterBrickEntity> slaveBricks = slaveVolume.getBricks();
for (GlusterBrickEntity currentBrick : slaveBricks) {
remoteServers.add(vdsDao.get(currentBrick.getServerId()));
}
return remoteServers;
}
@Override
public AuditLogType getAuditLogTypeValue() {
return getSucceeded() ? AuditLogType.CREATE_GLUSTER_VOLUME_GEOREP_SESSION : AuditLogType.GLUSTER_GEOREP_SESSION_CREATE_FAILED;
}
}