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; } }