package org.ovirt.engine.core.bll.utils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.ovirt.engine.core.bll.Backend;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.gluster.GlusterGeoRepNonEligibilityReason;
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.vdscommands.VDSCommandType;
import org.ovirt.engine.core.common.vdscommands.VDSReturnValue;
import org.ovirt.engine.core.common.vdscommands.gluster.GlusterVolumeVDSParameters;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.compat.Version;
import org.ovirt.engine.core.dal.dbbroker.DbFacade;
import org.ovirt.engine.core.dao.ClusterDao;
import org.ovirt.engine.core.dao.gluster.GlusterGeoRepDao;
@Singleton
public class GlusterGeoRepUtil {
@Inject
private GlusterUtil glusterUtil;
public Map<GlusterGeoRepNonEligibilityReason, Predicate<GlusterVolumeEntity>> getEligibilityPredicates(final GlusterVolumeEntity masterVolume) {
Map<GlusterGeoRepNonEligibilityReason, Predicate<GlusterVolumeEntity>> eligibilityPredicates = new HashMap<>();
final List<Guid> existingSessionSlavesIds = getSessionSlaveVolumeIds();
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.SLAVE_VOLUME_SHOULD_BE_UP, slaveVolume -> slaveVolume.getStatus() == GlusterStatus.UP);
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.SLAVE_AND_MASTER_VOLUMES_SHOULD_NOT_BE_IN_SAME_CLUSTER, slaveVolume -> ! masterVolume.getClusterId().equals(slaveVolume.getClusterId()));
final Predicate<GlusterVolumeEntity> nonNullSlaveSizePredicate = slaveVolume -> slaveVolume.getAdvancedDetails().getCapacityInfo() != null;
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.SLAVE_VOLUME_SIZE_TO_BE_AVAILABLE, nonNullSlaveSizePredicate);
final Predicate<GlusterVolumeEntity> nonNullMasterSizePredicate = slaveVolume -> masterVolume.getAdvancedDetails().getCapacityInfo() != null;
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.MASTER_VOLUME_SIZE_TO_BE_AVAILABLE, nonNullMasterSizePredicate);
Predicate<GlusterVolumeEntity> masterSlaveSizePredicate = slaveVolume -> {
boolean eligible = nonNullSlaveSizePredicate.test(slaveVolume) && nonNullMasterSizePredicate.test(masterVolume);
if (eligible) {
eligible = slaveVolume.getAdvancedDetails().getCapacityInfo().getTotalSize() >= masterVolume.getAdvancedDetails().getCapacityInfo().getTotalSize();
}
return eligible;
};
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.SLAVE_VOLUME_SIZE_SHOULD_BE_GREATER_THAN_MASTER_VOLUME_SIZE, masterSlaveSizePredicate);
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.SLAVE_VOLUME_SHOULD_NOT_BE_SLAVE_OF_ANOTHER_GEO_REP_SESSION, slaveVolume -> !existingSessionSlavesIds.contains(slaveVolume.getId()));
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.SLAVE_CLUSTER_AND_MASTER_CLUSTER_COMPATIBILITY_VERSIONS_DO_NOT_MATCH, slaveVolume -> {
ClusterDao clusterDao = getClusterDao();
Version slaveCompatibilityVersion = clusterDao.get(slaveVolume.getClusterId()).getCompatibilityVersion();
Version masterCompatibilityVersion = clusterDao.get(masterVolume.getClusterId()).getCompatibilityVersion();
return masterCompatibilityVersion.equals(slaveCompatibilityVersion);
});
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.NO_UP_SLAVE_SERVER,
slaveVolume -> {
Guid slaveUpserverId = getUpServerId(slaveVolume.getClusterId());
return slaveUpserverId != null;
});
eligibilityPredicates.put(GlusterGeoRepNonEligibilityReason.SLAVE_VOLUME_TO_BE_EMPTY,
slaveVolume -> {
Guid slaveUpserverId = getUpServerId(slaveVolume.getClusterId());
return slaveUpserverId != null && checkEmptyGlusterVolume(slaveUpserverId, slaveVolume.getName());
});
return eligibilityPredicates;
}
private List<Guid> getSessionSlaveVolumeIds() {
List<GlusterGeoRepSession> existingSessions = getGeoRepDao().getAllSessions();
return existingSessions.stream().map(GlusterGeoRepSession::getSlaveVolumeId).collect(Collectors.toList());
}
public boolean checkEmptyGlusterVolume(Guid slaveUpserverId, String slaveVolumeName) {
VDSReturnValue returnValue =
Backend.getInstance()
.getResourceManager()
.runVdsCommand(VDSCommandType.CheckEmptyGlusterVolume,
new GlusterVolumeVDSParameters(slaveUpserverId, slaveVolumeName));
return returnValue.getSucceeded() && (boolean) returnValue.getReturnValue();
}
public Guid getUpServerId(Guid clusterId) {
VDS randomUpServer = glusterUtil.getRandomUpServer(clusterId);
return randomUpServer == null ? null : randomUpServer.getId();
}
public ClusterDao getClusterDao() {
return DbFacade.getInstance().getClusterDao();
}
public GlusterGeoRepDao getGeoRepDao() {
return DbFacade.getInstance().getGlusterGeoRepDao();
}
}