package org.ovirt.engine.core.utils;
import static java.util.stream.Collectors.toList;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.codec.digest.DigestUtils;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.network.IPv4Address;
import org.ovirt.engine.core.common.businessentities.network.IpConfiguration;
import org.ovirt.engine.core.common.businessentities.network.IpV6Address;
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.NetworkCluster;
import org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface;
import org.ovirt.engine.core.common.businessentities.network.VmNetworkInterface;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.utils.NetworkCommonUtils;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.utils.network.function.NicToIpv4AddressFunction;
import org.ovirt.engine.core.utils.network.function.NicToIpv6AddressFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class NetworkUtils {
private static final Logger log = LoggerFactory.getLogger(NetworkUtils.class);
public static Integer getDefaultMtu() {
return Config.<Integer> getValue(ConfigValues.DefaultMTU);
}
/**
* Check if the proposed interface represents a VLAN of the given interface name or is equal to it.<br>
* If either of the parameters is null, <code>false</code> is returned.
*
* @param proposedIface
* The interface to check if it's a VLAN of the other interface or it is the other interface.
* @param iface
* The interface to check for.
*
* @return <code>true</code> if the proposed interface is a VLAN on the interface or if it is the other interface,
* <code>false</code> otherwise.
*/
public static boolean interfaceBasedOn(VdsNetworkInterface proposedIface, String iface) {
return iface != null && proposedIface != null && iface.equals(NetworkCommonUtils.stripVlan(proposedIface));
}
public static boolean interfaceHasVlan(VdsNetworkInterface iface, List<VdsNetworkInterface> allIfaces) {
for (VdsNetworkInterface i : allIfaces) {
if (NetworkCommonUtils.isVlan(i) && interfaceBasedOn(i, iface.getName())) {
return true;
}
}
return false;
}
public static Map<String, Network> networksByName(List<Network> networks) {
if (!networks.isEmpty()) {
Map<String, Network> byName = new HashMap<>();
for (Network net : networks) {
byName.put(net.getName(), net);
}
return byName;
} else {
return Collections.emptyMap();
}
}
/**
* filter networks which are not VM networks from the newtorkNames list
* @param networks
* logical networks
* @param networkNames
* target names to match non-VM networks upon
*/
public static List<String> filterNonVmNetworkNames(List<Network> networks, Set<String> networkNames) {
List<String> list = new ArrayList<>();
for (Network net : networks) {
if (!net.isVmNetwork() && networkNames.contains(net.getName())) {
list.add(net.getName());
}
}
return list;
}
/**
* Check whether the network attachment has any QoS configured on it, whether via its network or overridden.
*
* @param networkAttachment
* The network interface.
* @param network
* The network attached to the interface.
* @return true iff any QoS is applied to the interface.
*/
public static boolean qosConfiguredOnInterface(NetworkAttachment networkAttachment, Network network) {
if (networkAttachment != null && networkAttachment.isQosOverridden()) {
return networkAttachment.getHostNetworkQos() != null && !networkAttachment.getHostNetworkQos().isEmpty();
} else {
return network != null && network.getQosId() != null;
}
}
/**
* Determine if a given network is configured as a vlan
*
* @param network
* the network to check.
* @return <code>true</code> iff the network is a vlan.
*/
public static boolean isVlan(Network network) {
return network.getVlanId() != null;
}
/**
* Determine if a given network is labeled
*
* @param network
* the network to check.
* @return <code>true</code> iff the network is labeled.
*/
public static boolean isLabeled(Network network) {
return network.getLabel() != null;
}
/**
* Determine if a given network interface is labeled
*
* @param nic
* the nic to check.
* @return <code>true</code> iff the nic is labeled.
*/
public static boolean isLabeled(VdsNetworkInterface nic) {
return nic.getLabels() != null && !nic.getLabels().isEmpty();
}
/**
* Determine if a given network interface should be configured on hosts
*
* @param network
* the network to check.
* @return <code>true</code> iff the network is labeled and not an external network.
*/
public static boolean isConfiguredByLabel(Network network) {
return isLabeled(network) && !network.isExternal();
}
/**
* Constructs the vlan device name in the format of "{nic name}.{vlan-id}"
*
* @param underlyingNic
* the device on top the vlan device is created
* @param network
* the network which holds the vlan-id
* @return a name representing the vlan device
*/
public static String constructVlanDeviceName(VdsNetworkInterface underlyingNic, Network network) {
return underlyingNic.getName() + "." + network.getVlanId();
}
/**
* Returns the cluster's display network
*/
public static Network getDisplayNetwork(Collection<Network> clusterNetworks) {
Network displayNetwork = null;
for (Network network : clusterNetworks) {
if (network.getCluster().isDisplay()) {
displayNetwork = network;
break;
}
}
return displayNetwork;
}
/**
* @return A unique host name representation
*/
public static String getUniqueHostName(VDS host) {
return host.getHostName() + "-" + DigestUtils.md5Hex(host.getId().toByteArray()).substring(0, 6);
}
/**
* resolve the host ip address
*
* @param host
* the host which it's address is about to be resolved
* @return if succeeded, string representing the host ip, null otherwise
*/
public static String getHostIp(VDS host) {
try {
final InetAddress address = InetAddress.getByName(host.getHostName());
return address.getHostAddress().trim();
} catch (UnknownHostException ex) {
final String msg = "Failed to resolve host ip by name '{}'";
log.warn(msg, " Details: '{}' ", host.getHostName(), ex.getCause());
log.debug(msg, host.getHostName(), ex);
return null;
}
}
/**
* returns whether the network has a role in the cluster
*
* @return whether the network has a role (display, migration or gluster) in the cluster
*/
public static boolean isRoleNetwork(NetworkCluster networkCluster) {
return networkCluster.isDisplay() || networkCluster.isMigration() || networkCluster.isGluster();
}
public static IpConfiguration createIpConfigurationFromVdsNetworkInterface(VdsNetworkInterface nic) {
if (nic == null) {
return NetworkCommonUtils.createDefaultIpConfiguration();
}
final List<IPv4Address> iPv4Addresses = Stream.of(nic).map(new NicToIpv4AddressFunction()).collect(toList());
final List<IpV6Address> ipV6Addresses = Stream.of(nic).map(new NicToIpv6AddressFunction()).collect(toList());
IpConfiguration ipConfiguration = new IpConfiguration();
ipConfiguration.setIPv4Addresses(iPv4Addresses);
ipConfiguration.setIpV6Addresses(ipV6Addresses);
return ipConfiguration;
}
public static <E extends VmNetworkInterface> Map<Guid, List<E>> vmInterfacesByVmId(List<E> vnics) {
return vnics == null
? Collections.emptyMap()
: vnics.stream().collect(Collectors.groupingBy(VmNetworkInterface::getVmId));
}
public static <E extends VdsNetworkInterface> Map<String, E> hostInterfacesByNetworkName(Collection<E> hostNics) {
return hostNics == null
? Collections.emptyMap()
: hostNics.stream()
.filter(hostNic -> hostNic.getNetworkName() != null)
.collect(Collectors.toMap(VdsNetworkInterface::getNetworkName, Function.<E>identity()));
}
}