package org.ovirt.engine.core.bll.gluster; import java.util.Arrays; import java.util.List; import javax.inject.Inject; 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.GlusterServerService; import org.ovirt.engine.core.common.businessentities.gluster.GlusterStatus; import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeAdvancedDetails; import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeEntity; import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeType; import org.ovirt.engine.core.common.errors.EngineMessage; import org.ovirt.engine.core.common.queries.gluster.GlusterVolumeAdvancedDetailsParameters; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.common.vdscommands.VDSReturnValue; import org.ovirt.engine.core.common.vdscommands.gluster.GlusterVolumeAdvancedDetailsVDSParameters; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.VdsDao; import org.ovirt.engine.core.dao.gluster.GlusterDBUtils; /** * Query to get volume advanced details */ public class GetGlusterVolumeAdvancedDetailsQuery<P extends GlusterVolumeAdvancedDetailsParameters> extends GlusterQueriesCommandBase<P> { private static final String OPTION_KEY_NFS_DISABLE = "nfs.disable"; private static final String OPTION_VALUE_OFF = "off"; private static final List<GlusterVolumeType> replicateVolumeTypes = Arrays.asList(GlusterVolumeType.REPLICATE, GlusterVolumeType.DISTRIBUTED_REPLICATE); private GlusterBrickEntity brick = null; private Guid clusterId = null; private boolean detailRequired = false; @Inject private VdsDao vdsDao; @Inject private GlusterDBUtils glusterDBUtils; public GetGlusterVolumeAdvancedDetailsQuery(P params) { super(params); } @Override protected void executeQueryCommand() { clusterId = getParameters().getClusterId(); detailRequired = getParameters().isDetailRequired(); Guid volumeId = getParameters().getVolumeId(); if (volumeId != null) { GlusterVolumeEntity volume = glusterVolumeDao.getById(volumeId); if (volume == null) { throw new RuntimeException(EngineMessage.GLUSTER_VOLUME_ID_INVALID.toString()); } brick = getBrick(getParameters().getBrickId()); getQueryReturnValue().setReturnValue(fetchAdvancedDetails(volume.getName())); } else { GlusterVolumeAdvancedDetails advancedDetails = getServiceInfo(); if (advancedDetails != null) { List<GlusterServerService> serviceList = advancedDetails.getServiceInfo(); if (serviceList != null) { for (GlusterServerService service : serviceList) { String hostName = glusterDBUtils.getHostNameOrIP(service.getGlusterHostUuid()); if (hostName != null) { service.setHostName(hostName); } } } } getQueryReturnValue().setReturnValue(advancedDetails); } } private GlusterBrickEntity getBrick(Guid brickId) { return (brickId == null) ? null : glusterBrickDao.getById(brickId); } /** * To get the service info, the UI will not pass the volume name, in that case engine will fetch the volume name in * the database. * * NFS volume name should be passed to get nfs service details, similarly REPLICATE/DISTRIBUTED_REPLICATE volume * name should be passed as an argument to get the SHD details. * * So to get volume name from database engine will do the following steps.<br> * 1. First fetch NFS + REPLICATE/DISTRIBUTED_REPLICATE volume name<br> * 2. If not found then fetch the nfs volume name and then fetch REPLICATE/DISTRIBUTED_REPLICATE volume name<br> * 3. The VDS query will be called twice, one with nfs volume name and another with replicate volume name, finally * combine the service details. */ private GlusterVolumeAdvancedDetails getServiceInfo() { // Get Nfs + Replicated/Distributed Replicate volume. GlusterVolumeEntity nfsReplicateVolume = getNfsReplicateVolume(clusterId); if (nfsReplicateVolume != null) { return fetchAdvancedDetails(nfsReplicateVolume.getName()); } // Get Nfs enabled volume GlusterVolumeEntity nfsVolume = getNfsVolume(clusterId); // Get Replicated volume GlusterVolumeEntity replicateVolume = getReplicateVolume(clusterId); // If there is no volume present in the cluster, then return empty Volume Advanced Details if (nfsVolume == null && replicateVolume == null) { log.error("To get service details, no Nfs or Replicated volumes found in the cluster."); return new GlusterVolumeAdvancedDetails(); } GlusterVolumeAdvancedDetails nfsServiceInfo = null; GlusterVolumeAdvancedDetails shdServiceInfo = null; if (nfsVolume != null) { nfsServiceInfo = fetchAdvancedDetails(nfsVolume.getName()); } if (replicateVolume != null) { shdServiceInfo = fetchAdvancedDetails(replicateVolume.getName()); } if (nfsServiceInfo == null && shdServiceInfo != null) { return shdServiceInfo; } else if (nfsServiceInfo != null && shdServiceInfo != null) { // combine the Nfs + Shd status nfsServiceInfo.getServiceInfo().addAll(shdServiceInfo.getServiceInfo()); } return nfsServiceInfo; } /** * Returns the server id on which the brick resides if <br> * a) brick id passed is not null <br> * b) the brick server is UP <br> * Otherwise returns a random up server from the cluster */ protected Guid getUpServerId() { if (brick == null) { return getRandomUpServerId(clusterId); } VDS brickServer = vdsDao.get(brick.getServerId()); if (brickServer.getStatus() == VDSStatus.Up) { return brickServer.getId(); } // brick server is down return super.getRandomUpServerId(clusterId); } private GlusterVolumeAdvancedDetails fetchAdvancedDetails(String volumeName) { VDSReturnValue returnValue = runVdsCommand(VDSCommandType.GetGlusterVolumeAdvancedDetails, new GlusterVolumeAdvancedDetailsVDSParameters(getUpServerId(), clusterId, volumeName, brick == null ? null : brick.getQualifiedName(), detailRequired)); return (GlusterVolumeAdvancedDetails) returnValue.getReturnValue(); } private GlusterVolumeEntity getReplicateVolume(Guid clusterId) { List<GlusterVolumeEntity> replicateVolumes = getReplicateVolumes(clusterId, replicateVolumeTypes); if (replicateVolumes.size() > 0) { return replicateVolumes.get(0); } return null; } private GlusterVolumeEntity getNfsVolume(Guid clusterId) { List<GlusterVolumeEntity> nfsVolumes = getNfsVolumes(clusterId); if (nfsVolumes.size() > 0) { return nfsVolumes.get(0); } return null; } private GlusterVolumeEntity getNfsReplicateVolume(Guid clusterId) { List<GlusterVolumeEntity> nfsReplicateVolumes = getReplicateAndNfsVolumes(clusterId, replicateVolumeTypes); if (nfsReplicateVolumes.size() > 0) { return nfsReplicateVolumes.get(0); } return null; } private List<GlusterVolumeEntity> getReplicateAndNfsVolumes(Guid clusterId, List<GlusterVolumeType> volumeTypes) { return glusterVolumeDao.getVolumesByStatusTypesAndOption(clusterId, GlusterStatus.UP, volumeTypes, OPTION_KEY_NFS_DISABLE, OPTION_VALUE_OFF); } private List<GlusterVolumeEntity> getNfsVolumes(Guid clusterId) { return glusterVolumeDao.getVolumesByOption(clusterId, GlusterStatus.UP, OPTION_KEY_NFS_DISABLE, OPTION_VALUE_OFF); } private List<GlusterVolumeEntity> getReplicateVolumes(Guid clusterId, List<GlusterVolumeType> volumeTypes) { return glusterVolumeDao.getVolumesByStatusAndTypes(clusterId, GlusterStatus.UP, volumeTypes); } }