package org.ovirt.engine.core.bll.network.host; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import org.ovirt.engine.core.common.action.HostSetupNetworksParameters; import org.ovirt.engine.core.common.businessentities.BusinessEntityMap; import org.ovirt.engine.core.common.businessentities.network.IpConfiguration; import org.ovirt.engine.core.common.businessentities.network.Network; import org.ovirt.engine.core.common.businessentities.network.NetworkAttachment; import org.ovirt.engine.core.common.businessentities.network.NicLabel; import org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface; import org.ovirt.engine.core.common.utils.MapNetworkAttachments; import org.ovirt.engine.core.common.utils.NetworkCommonUtils; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.utils.NetworkUtils; import org.ovirt.engine.core.utils.collections.MultiValueMapUtils; public class NicLabelsCompleter { private HostSetupNetworksParameters params; private Map<String, List<Network>> labelToNetworks; private Map<Guid, NetworkAttachment> attachmentsByNetworkId; private Map<Guid, NetworkAttachment> existingNetworkAttachmentsByNetworkId; private List<Network> clusterNetworks; private BusinessEntityMap<VdsNetworkInterface> existingNicsBusinessEntityMap; public NicLabelsCompleter(HostSetupNetworksParameters params, List<NetworkAttachment> existingNetworkAttachments, List<Network> clusterNetworks, BusinessEntityMap<VdsNetworkInterface> existingNicsBusinessEntityMap) { this.labelToNetworks = new HashMap<>(); this.params = params; this.clusterNetworks = clusterNetworks; this.attachmentsByNetworkId = new MapNetworkAttachments(params.getNetworkAttachments()).byNetworkId(); this.existingNetworkAttachmentsByNetworkId = new MapNetworkAttachments(existingNetworkAttachments).byNetworkId(); this.existingNicsBusinessEntityMap = existingNicsBusinessEntityMap; initLabelsToNetworks(); } /** * The method updates <code>networkAttachments</code> and <code>removedNetworkAttachments</code> according to * <code>labels</code> and <code>removedLabels</code>. * * <code>labels</code> can contain two types- * <ol> * <li>labels that are already attached to a nic on the host.</li> * <li>new labels.</li> * </ol> * <br> * * For the first type, the existing attachment is modified to contain the new nic (and added to <code>networkAttachments</code>). * For the second type, a new network attachment is created (and added to <code>networkAttachments</code> ). * * An attachment is added to the <code>removedNetworkAttachments</code> in case the network was attached to the nic * via one of the <code>removedLabels</code>. */ public void completeNetworkAttachments() { completeNetworkAttachmentsByLabels(); completeNetworkAttachmentsByRemovedLabels(); } private void initLabelsToNetworks() { for (Network network : clusterNetworks) { MultiValueMapUtils.addToMap(network.getLabel(), network, labelToNetworks, new MultiValueMapUtils.ListCreator<>()); } } private void completeNetworkAttachmentsByRemovedLabels() { for (String removedLabel : params.getRemovedLabels()) { List<Network> labelNetworks = labelToNetworks.get(removedLabel); if (labelNetworks == null) { continue; } for (Network network : labelNetworks) { NetworkAttachment existingNetworkAttachment = existingNetworkAttachmentsByNetworkId.get(network.getId()); if (shouldRemoveExistingAttachment(existingNetworkAttachment, removedLabel)) { params.getRemovedNetworkAttachments().add(existingNetworkAttachment.getId()); } } } } private boolean shouldRemoveExistingAttachment(NetworkAttachment existingAttachmentWithLabeledNetwork, String removedLabel) { if (existingAttachmentWithLabeledNetwork == null) { return false; } NetworkAttachment newOrModifiedNetworkAttachment = attachmentsByNetworkId.get(existingAttachmentWithLabeledNetwork.getNetworkId()); boolean attachmentWasUpdated = newOrModifiedNetworkAttachment != null && existingAttachmentWithLabeledNetwork.getId().equals(newOrModifiedNetworkAttachment.getId()); if (!attachmentWasUpdated) { return containsLabel(existingAttachmentWithLabeledNetwork.getNicId(), removedLabel); } return false; } private boolean containsLabel(Guid nicId, String label) { VdsNetworkInterface attachmentNic = existingNicsBusinessEntityMap.get(nicId); return NetworkUtils.isLabeled(attachmentNic) && attachmentNic.getLabels().contains(label); } private void completeNetworkAttachmentsByLabels() { for (NicLabel nicLabel : params.getLabels()) { List<Network> labelNetworks = labelToNetworks.get(nicLabel.getLabel()); if (labelNetworks == null) { continue; } for (Network network : labelNetworks) { NetworkAttachment newOrModifiedNetworkAttachment = attachmentsByNetworkId.get(network.getId()); NetworkAttachment existingNetworkAttachment = existingNetworkAttachmentsByNetworkId.get(network.getId()); boolean existingAttachmentRemoved = existingNetworkAttachment == null ? false : params.getRemovedNetworkAttachments() .contains(existingNetworkAttachment.getId()); boolean noNewOrModifiedNetworkAttachment = newOrModifiedNetworkAttachment == null; NetworkAttachment attachmentToConfigure = noNewOrModifiedNetworkAttachment && !existingAttachmentRemoved ? existingNetworkAttachment : newOrModifiedNetworkAttachment; if (attachmentToConfigure == null) { params.getNetworkAttachments().add(createNetworkAttachment(nicLabel.getNicId(), nicLabel.getNicName(), network.getId(), network.getName())); } else if (!Objects.equals(attachmentToConfigure.getNicName(), nicLabel.getNicName()) && noNewOrModifiedNetworkAttachment) { NetworkAttachment updatedNetworkAttachment = new NetworkAttachment(existingNetworkAttachment); updatedNetworkAttachment.setNicId(nicLabel.getNicId()); updatedNetworkAttachment.setNicName(nicLabel.getNicName()); params.getNetworkAttachments().add(updatedNetworkAttachment); } } } } private NetworkAttachment createNetworkAttachment(Guid nicId, String nicName, Guid networkId, String networkName) { NetworkAttachment networkAttachment = new NetworkAttachment(); networkAttachment.setNicId(nicId); networkAttachment.setNicName(nicName); networkAttachment.setNetworkId(networkId); networkAttachment.setNetworkName(networkName); IpConfiguration ipConfiguration = NetworkCommonUtils.createDefaultIpConfiguration(); networkAttachment.setIpConfiguration(ipConfiguration); return networkAttachment; } }