package org.ovirt.engine.core.dao.gluster;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.apache.commons.lang.StringUtils;
import org.ovirt.engine.core.common.businessentities.VdsStatic;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterBrickEntity;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterServer;
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.GlusterVolumeSnapshotConfig;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeType;
import org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dao.VdsStaticDao;
import org.ovirt.engine.core.dao.network.InterfaceDao;
@Singleton
public class GlusterDBUtils {
@Inject
private GlusterBrickDao glusterBrickDao;
@Inject
private GlusterVolumeDao glusterVolumeDao;
@Inject
private GlusterServerDao glusterServerDao;
@Inject
private GlusterVolumeSnapshotConfigDao glusterVolumeSnapshotConfigDao;
@Inject
private VdsStaticDao vdsStaticDao;
@Inject
private InterfaceDao interfaceDao;
public boolean hasBricks(Guid serverId) {
return glusterBrickDao.getGlusterVolumeBricksByServerId(serverId).size() > 0;
}
/**
* Update status of all bricks of the given volume to the new status
*/
public void updateBricksStatuses(Guid volumeId, GlusterStatus newStatus) {
for (GlusterBrickEntity brick : glusterBrickDao.getBricksOfVolume(volumeId)) {
glusterBrickDao.updateBrickStatus(brick.getId(), newStatus);
}
}
/**
* Update status of the given volume to the new status. This internally updates statuses of all bricks of the volume
* as well.
*/
public void updateVolumeStatus(Guid volumeId, GlusterStatus newStatus) {
glusterVolumeDao.updateVolumeStatus(volumeId, newStatus);
// When a volume goes UP or DOWN, all it's bricks should also be updated with the new status.
updateBricksStatuses(volumeId, newStatus);
}
public boolean serverExists(Guid clusterId, String hostnameOrIp) {
return getServer(clusterId, hostnameOrIp) != null;
}
public boolean serverExists(Guid uuid) {
return getServerByUuid(uuid) != null;
}
/**
* Returns a server from the given cluster, having given
* gluster server UUID
*
* @return GlusterServer object for the said server if found, else null
*/
public GlusterServer getServerByUuid(Guid uuid) {
return glusterServerDao.getByGlusterServerUuid(uuid);
}
/**
* Returns a server from the given cluster, having give host name or IP address.
*
* @return VDS object for the server if found, else null
*/
public VdsStatic getServer(Guid clusterId, String hostnameOrIp) {
// first check for hostname
VdsStatic server = vdsStaticDao.getByHostName(hostnameOrIp);
if (server != null) {
return server.getClusterId().equals(clusterId) ? server : null;
}
// then for ip
List<VdsNetworkInterface> ifaces;
try {
ifaces =
interfaceDao.getAllInterfacesWithIpAddress(clusterId,
InetAddress.getByName(hostnameOrIp).getHostAddress());
switch (ifaces.size()) {
case 0:
// not found
return null;
case 1:
return vdsStaticDao.get(ifaces.get(0).getVdsId());
default:
// multiple servers in the DB having this ip address!
throw new RuntimeException("There are multiple servers in DB having same IP address " + hostnameOrIp);
}
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
public void removeBricksFromVolumeInDb(GlusterVolumeEntity volume,
List<GlusterBrickEntity> brickList,
int volumeReplicaCount) {
glusterBrickDao.removeAllInBatch(brickList);
// Update volume type and replica/stripe count
if (volume.getVolumeType() == GlusterVolumeType.DISTRIBUTED_REPLICATE
&& volume.getReplicaCount() == (volume.getBricks().size() - brickList.size())) {
volume.setVolumeType(GlusterVolumeType.REPLICATE);
}
if (volume.getVolumeType().isReplicatedType()) {
int replicaCount =
(volumeReplicaCount == 0)
? volume.getReplicaCount()
: volumeReplicaCount;
volume.setReplicaCount(replicaCount);
glusterVolumeDao.updateGlusterVolume(volume);
}
if (volume.getVolumeType() == GlusterVolumeType.DISTRIBUTED_STRIPE
&& volume.getStripeCount() == (volume.getBricks().size() - brickList.size())) {
volume.setVolumeType(GlusterVolumeType.STRIPE);
glusterVolumeDao.updateGlusterVolume(volume);
}
if (volume.getVolumeType() == GlusterVolumeType.DISTRIBUTED_STRIPED_REPLICATE
&& (volume.getStripeCount() * volume.getReplicaCount()) == (volume.getBricks().size() - brickList.size())) {
volume.setVolumeType(GlusterVolumeType.STRIPED_REPLICATE);
glusterVolumeDao.updateGlusterVolume(volume);
}
}
public String getHostNameOrIP(Guid glusterHostUuid) {
String hostName = null;
if (glusterHostUuid != null) {
GlusterServer glusterServer = glusterServerDao.getByGlusterServerUuid(glusterHostUuid);
if(glusterServer != null) {
VdsStatic vds = vdsStaticDao.get(glusterServer.getId());
if(vds != null) {
hostName = vds.getHostName();
}
}
}
return hostName;
}
public GlusterBrickEntity getGlusterBrickByServerUuidAndBrickDir(Guid serverId, String brickDir) {
return glusterBrickDao.getBrickByServerIdAndDirectory(serverId, brickDir);
}
public boolean isVolumeSnapshotSoftLimitReached(Guid volumeId) {
GlusterVolumeEntity volume = glusterVolumeDao.getById(volumeId);
if (volume != null) {
GlusterVolumeSnapshotConfig config =
glusterVolumeSnapshotConfigDao.getConfigByClusterIdAndName(volume.getClusterId(),
"snap-max-soft-limit");
if (config != null) {
// remove the % sign in the last
String configValue = StringUtils.removeEnd(config.getParamValue(), "%");
int snapMaxSoftLimitPcnt = Integer.parseInt(configValue);
int snapshotCount = volume.getSnapshotsCount();
int snapMaxLimit = volume.getSnapMaxLimit();
return snapshotCount >= (snapMaxLimit * snapMaxSoftLimitPcnt) / 100;
}
}
return false;
}
public boolean isVolumeSnapshotHardLimitReached(Guid volumeId) {
GlusterVolumeEntity volume = glusterVolumeDao.getById(volumeId);
if (volume != null) {
GlusterVolumeSnapshotConfig config =
glusterVolumeSnapshotConfigDao.getConfigByVolumeIdAndName(volume.getClusterId(),
volumeId,
"snap-max-hard-limit");
if (config != null) {
int snapMaxHardLimit = Integer.parseInt(config.getParamValue());
int snapshotCount = volume.getSnapshotsCount();
return snapshotCount >= snapMaxHardLimit;
}
}
return false;
}
}