package org.ovirt.engine.core.bll.scheduling.policyunits; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; import javax.inject.Inject; import org.ovirt.engine.core.bll.scheduling.PolicyUnitImpl; import org.ovirt.engine.core.bll.scheduling.SchedulingUnit; import org.ovirt.engine.core.bll.scheduling.pending.PendingResourceManager; import org.ovirt.engine.core.common.businessentities.Cluster; import org.ovirt.engine.core.common.businessentities.Label; import org.ovirt.engine.core.common.businessentities.VDS; import org.ovirt.engine.core.common.businessentities.VM; import org.ovirt.engine.core.common.scheduling.PerHostMessages; import org.ovirt.engine.core.common.scheduling.PolicyUnit; import org.ovirt.engine.core.common.scheduling.PolicyUnitType; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.dao.LabelDao; @SchedulingUnit( guid = "27846536-f653-11e5-9ce9-5e5517507c66", name = "Label", type = PolicyUnitType.FILTER, description = "Filters out hosts that do not have the required labels" ) public class LabelFilterPolicyUnit extends PolicyUnitImpl { public LabelFilterPolicyUnit(PolicyUnit policyUnit, PendingResourceManager pendingResourceManager) { super(policyUnit, pendingResourceManager); } @Inject LabelDao labelDao; @Override public List<VDS> filter(Cluster cluster, List<VDS> hosts, VM vm, Map<String, String> parameters, PerHostMessages messages) { Map<Guid, Set<Guid>> objectToTags = new HashMap<>(); final List<Guid> objects = hosts.stream().map(VDS::getId).collect(Collectors.toList()); objects.add(vm.getId()); // Prepare the entity -> label reverse mapping for (Label label: labelDao.getAllByEntityIds(objects)) { for (Guid entity: label.getVms()) { objectToTags.putIfAbsent(entity, new HashSet<>()); objectToTags.get(entity).add(label.getId()); } for (Guid entity: label.getHosts()) { objectToTags.putIfAbsent(entity, new HashSet<>()); objectToTags.get(entity).add(label.getId()); } } return hosts.stream().filter(new TagMatcher(objectToTags, vm)).collect(Collectors.toList()); } static class TagMatcher implements Predicate<VDS> { final Map<Guid, Set<Guid>> objectToTags; final VM vm; public TagMatcher(Map<Guid, Set<Guid>> objectToTags, VM vm) { this.objectToTags = objectToTags; this.vm = vm; } @Override public boolean test(final VDS vds) { // Compute whether all VM Labels are present for the host under test final Set<Guid> vmLabels = objectToTags.getOrDefault(vm.getId(), Collections.emptySet()); final Set<Guid> hostLabels = objectToTags.getOrDefault(vds.getId(), Collections.emptySet()); return hostLabels.containsAll(vmLabels); } } }