package org.ovirt.engine.api.restapi.types; import static java.util.stream.Collectors.joining; import java.util.List; import org.apache.commons.lang.StringUtils; import org.ovirt.engine.api.model.Bonding; import org.ovirt.engine.api.model.BootProtocol; import org.ovirt.engine.api.model.HostNic; import org.ovirt.engine.api.model.HostNicVirtualFunctionsConfiguration; import org.ovirt.engine.api.model.Ip; import org.ovirt.engine.api.model.IpVersion; import org.ovirt.engine.api.model.Mac; import org.ovirt.engine.api.model.Network; import org.ovirt.engine.api.model.NicStatus; import org.ovirt.engine.api.model.Option; import org.ovirt.engine.api.model.Options; import org.ovirt.engine.api.restapi.utils.GuidUtils; import org.ovirt.engine.core.common.action.UpdateHostNicVfsConfigParameters; import org.ovirt.engine.core.common.businessentities.network.Bond; import org.ovirt.engine.core.common.businessentities.network.HostNetworkQos; import org.ovirt.engine.core.common.businessentities.network.HostNicVfsConfig; import org.ovirt.engine.core.common.businessentities.network.InterfaceStatus; import org.ovirt.engine.core.common.businessentities.network.Ipv4BootProtocol; import org.ovirt.engine.core.common.businessentities.network.Ipv6BootProtocol; import org.ovirt.engine.core.common.businessentities.network.Nic; import org.ovirt.engine.core.common.businessentities.network.VdsNetworkInterface; import org.ovirt.engine.core.common.businessentities.network.Vlan; public class HostNicMapper { private static final String OPTIONS_DELIMITER = "\\ "; private static final String OPTIONS_EQ = "\\="; private static final String[] BONDING_MODS = new String[]{"Active-Backup", "Load balance (balance-xor)", null, "Dynamic link aggregation (802.3ad)", "Adaptive transmit load balancing (balance-tlb)"}; @Mapping(from = HostNic.class, to = VdsNetworkInterface.class) public static VdsNetworkInterface map(HostNic model, VdsNetworkInterface template) { VdsNetworkInterface entity; if (template != null) { entity = template; } else if (model.isSetBonding()) { entity = new Bond(); } else if (model.isSetVlan()) { entity = new Vlan(); } else { entity = new Nic(); } if (model.isSetId()) { entity.setId(GuidUtils.asGuid(model.getId())); } if (model.isSetNetwork() && model.getNetwork().isSetName()) { entity.setNetworkName(model.getNetwork().getName()); } if (model.isSetName()) { entity.setName(model.getName()); } if (model.isSetBaseInterface()) { entity.setBaseInterface(model.getBaseInterface()); } mapIpv4FromModel(model, entity); mapIpv6FromModel(model, entity); if (model.isSetMac() && model.getMac().isSetAddress()) { entity.setMacAddress(model.getMac().getAddress()); } if (model.isSetBonding()) { entity.setBonded(true); if (model.getBonding().isSetOptions()) { List<Option> bondingOptions = model.getBonding().getOptions().getOptions(); String optionsString = bondingOptions.stream() .filter(Option::isSetName) .map(x -> x.getName() + "=" + x.getValue()) .collect(joining(" ")); entity.setBondOptions(optionsString); } } if (model.isSetQos()) { entity.setQos((HostNetworkQos) QosMapper.map(model.getQos(), null)); } return entity; } private static void mapIpv4FromModel(HostNic model, VdsNetworkInterface entity) { if (model.isSetIp()) { if (model.getIp().isSetAddress()) { entity.setIpv4Address(model.getIp().getAddress()); } if (model.getIp().isSetGateway()) { entity.setIpv4Gateway(model.getIp().getGateway()); } if (model.getIp().isSetNetmask()) { entity.setIpv4Subnet(model.getIp().getNetmask()); } } if (model.isSetBootProtocol()) { Ipv4BootProtocol ipv4BootProtocol = Ipv4BootProtocolMapper.map(model.getBootProtocol()); if (ipv4BootProtocol != null) { entity.setIpv4BootProtocol(ipv4BootProtocol); } } } private static void mapIpv6FromModel(HostNic model, VdsNetworkInterface entity) { if (model.isSetIpv6()) { if (model.getIpv6().isSetAddress()) { entity.setIpv6Address(model.getIpv6().getAddress()); } if (model.getIpv6().isSetGateway()) { entity.setIpv6Gateway(model.getIpv6().getGateway()); } if (model.getIpv6().isSetNetmask()) { try { final Integer ipv6Prefix = Integer.valueOf(model.getIpv6().getNetmask()); entity.setIpv6Prefix(ipv6Prefix); } catch (NumberFormatException ignore) { } } } if (model.isSetIpv6BootProtocol()) { Ipv6BootProtocol ipv6BootProtocol = Ipv6BootProtocolMapper.map(model.getIpv6BootProtocol()); if (ipv6BootProtocol != null) { entity.setIpv6BootProtocol(ipv6BootProtocol); } } } @Mapping(from = HostNic.class, to = Bond.class) public static Bond map(HostNic model, Bond template) { Bond entity = template == null ? new Bond() : template; if (model.isSetId()) { entity.setId(GuidUtils.asGuid(model.getId())); } if (model.isSetName()) { entity.setName(model.getName()); } if (model.isSetBonding()) { entity.setBonded(true); if (model.getBonding().isSetSlaves()) { entity.getSlaves().clear(); for (HostNic slave : model.getBonding().getSlaves().getHostNics()) { if (slave.isSetName()) { entity.getSlaves().add(slave.getName()); } } } if (model.getBonding().isSetOptions()) { entity.setBondOptions(calculateBondingOptionsString(model)); } } if (model.isSetQos()) { entity.setQos((HostNetworkQos) QosMapper.map(model.getQos(), null)); } return entity; } private static String calculateBondingOptionsString(HostNic model) { List<Option> bondingOptions = model.getBonding().getOptions().getOptions(); if (bondingOptions.isEmpty()) { return ""; } StringBuilder builder = new StringBuilder(); appendBondingOption(builder, bondingOptions.get(0)); for(int i = 1; i < bondingOptions.size(); i++) { builder.append(" "); appendBondingOption(builder, bondingOptions.get(i)); } return builder.toString(); } private static StringBuilder appendBondingOption(StringBuilder builder, Option opt) { return builder.append(opt.getName()) .append("=") .append(opt.getValue()); } @Mapping(from = VdsNetworkInterface.class, to = HostNic.class) public static HostNic map(VdsNetworkInterface entity, HostNic template) { HostNic model = template != null ? template : new HostNic(); if (entity.getId() != null) { model.setId(entity.getId().toString()); } if (entity.getNetworkName() != null) { model.setNetwork(new Network()); model.getNetwork().setName(entity.getNetworkName()); } if (entity.getName() != null) { model.setName(entity.getName()); } if (entity.getBaseInterface() != null) { model.setBaseInterface(entity.getBaseInterface()); } if (entity.getVlanId() != null) { model.setVlan(new org.ovirt.engine.api.model.Vlan()); model.getVlan().setId(entity.getVlanId()); } mapIpv4ToModel(entity, model); mapIpv6ToModel(entity, model); if (entity.getMacAddress() != null) { model.setMac(new Mac()); model.getMac().setAddress(entity.getMacAddress()); } if (entity.getStatistics().getStatus()!=InterfaceStatus.NONE) { NicStatus nicStatus = mapNicStatus(entity.getStatistics().getStatus()); if (nicStatus != null) { model.setStatus(nicStatus); } } if(entity.getSpeed()!=null && entity.getSpeed()>0){ model.setSpeed(entity.getSpeed() * 1000L * 1000); } if (!StringUtils.isEmpty(entity.getBondOptions())) { if(model.getBonding() == null) { model.setBonding(new Bonding()); } model.getBonding().setOptions(new Options()); for(String opt : entity.getBondOptions().split(OPTIONS_DELIMITER)){ String[] option_pair = opt.split(OPTIONS_EQ); if(option_pair.length == 2){ Option option = new Option(); option.setName(option_pair[0]); option.setValue(option_pair[1]); option.setType(getType(option_pair)); model.getBonding().getOptions().getOptions().add(option); } } if (entity.getAdPartnerMac() != null) { model.getBonding().setAdPartnerMac(new Mac()); model.getBonding().getAdPartnerMac().setAddress(entity.getAdPartnerMac()); } } model.setMtu(entity.getMtu()); model.setBridged(entity.isBridged()); if (entity.getNetworkImplementationDetails() != null) { model.setCustomConfiguration(!entity.getNetworkImplementationDetails().isInSync()); } HostNetworkQos qos = entity.getQos(); if (qos != null) { model.setQos(QosMapper.map(qos, null)); } if (entity.getAdAggregatorId() != null) { model.setAdAggregatorId(entity.getAdAggregatorId()); } return model; } private static void mapIpv4ToModel(VdsNetworkInterface entity, HostNic model) { BootProtocol ipv4BootProtocol = Ipv4BootProtocolMapper.map(entity.getIpv4BootProtocol()); if(ipv4BootProtocol!=null){ model.setBootProtocol(ipv4BootProtocol); } if (entity.getIpv4Address() != null || entity.getIpv4Gateway() != null || entity.getIpv4Subnet() != null) { final Ip ipv4 = new Ip(); ipv4.setVersion(IpVersion.V4); if (entity.getIpv4Address() != null) { ipv4.setAddress(entity.getIpv4Address()); } if (entity.getIpv4Gateway() != null) { ipv4.setGateway(entity.getIpv4Gateway()); } if (entity.getIpv4Subnet() != null) { ipv4.setNetmask(entity.getIpv4Subnet()); } model.setIp(ipv4); } } private static void mapIpv6ToModel(VdsNetworkInterface entity, HostNic model) { BootProtocol ipv6BootProtocol = Ipv6BootProtocolMapper.map(entity.getIpv6BootProtocol()); if(ipv6BootProtocol!=null){ model.setIpv6BootProtocol(ipv6BootProtocol); } if (entity.getIpv6Address() != null || entity.getIpv6Gateway() != null || entity.getIpv6Prefix() != null) { final Ip ipv6 = new Ip(); ipv6.setVersion(IpVersion.V6); if (entity.getIpv6Address() != null) { ipv6.setAddress(entity.getIpv6Address()); } if (entity.getIpv6Gateway() != null) { ipv6.setGateway(entity.getIpv6Gateway()); } if (entity.getIpv6Prefix() != null) { ipv6.setNetmask(entity.getIpv6Prefix().toString()); } model.setIpv6(ipv6); } } private static String getType(final String[] optionPair) { if (!StringUtils.isEmpty(optionPair[0]) && optionPair[0].equals("mode") && !StringUtils.isEmpty(optionPair[1])) { Integer mode = tryParse(optionPair[1]); if(mode != null && mode > 0 && mode < 6){ return BONDING_MODS[mode - 1]; } } return null; } public static Integer tryParse(String text) { try { return Integer.valueOf(text); } catch (NumberFormatException e) { return null; } } public static NicStatus mapNicStatus(InterfaceStatus status) { if (status == null) { return null; } switch (status) { case UP: return NicStatus.UP; case DOWN: return NicStatus.DOWN; default: return null; } } @Mapping(from = HostNicVfsConfig.class, to = HostNicVirtualFunctionsConfiguration.class) public static HostNicVirtualFunctionsConfiguration map(HostNicVfsConfig entity, HostNicVirtualFunctionsConfiguration apiModel) { apiModel.setAllNetworksAllowed(entity.isAllNetworksAllowed()); apiModel.setMaxNumberOfVirtualFunctions(entity.getMaxNumOfVfs()); apiModel.setNumberOfVirtualFunctions(entity.getNumOfVfs()); return apiModel; } @Mapping(from = HostNicVirtualFunctionsConfiguration.class, to = UpdateHostNicVfsConfigParameters.class) public static UpdateHostNicVfsConfigParameters map(HostNicVirtualFunctionsConfiguration apiModel, UpdateHostNicVfsConfigParameters params) { if (apiModel.isSetAllNetworksAllowed()) { params.setAllNetworksAllowed(apiModel.isAllNetworksAllowed()); } if (apiModel.isSetNumberOfVirtualFunctions()) { params.setNumOfVfs(apiModel.getNumberOfVirtualFunctions()); } return params; } @Mapping(from = HostNicVfsConfig.class, to = UpdateHostNicVfsConfigParameters.class) public static UpdateHostNicVfsConfigParameters map(HostNicVfsConfig entity, UpdateHostNicVfsConfigParameters params) { params.setNicId(entity.getNicId()); params.setAllNetworksAllowed(entity.isAllNetworksAllowed()); params.setNumOfVfs(entity.getNumOfVfs()); return params; } }