/* * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.genius.itm.cli; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Singleton; import org.apache.commons.lang3.StringUtils; import org.apache.commons.net.util.SubnetUtils; import org.apache.felix.service.command.CommandSession; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.genius.itm.globals.ITMConstants; import org.opendaylight.genius.itm.impl.ItmUtils; import org.opendaylight.genius.mdsalutil.MDSALDataStoreUtils; import org.opendaylight.genius.utils.cache.DataStoreCache; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBfd; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeLldp; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeGre; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeMplsOverGre; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.ItmConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.TunnelMonitorInterval; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.TunnelMonitorIntervalBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.TunnelMonitorParams; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.config.rev160406.TunnelMonitorParamsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZonesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.SubnetsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.VtepsKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton public class TepCommandHelper { private static final Logger LOG = LoggerFactory.getLogger(TepCommandHelper.class); private final DataBroker dataBroker; private final ItmConfig itmConfig; static int check = 0; static short flag = 0; /* * boolean flag add_or_delete --- can be set to true if the last called tep * command is Tep-add else set to false when Tep-delete is called * tepCommandHelper object is created only once in session initiated */ final Map>> transportZonesHashMap = new HashMap<>(); private List subnetList = new ArrayList<>(); private List transportZoneArrayList = new ArrayList<>(); private List vtepDelCommitList = new ArrayList<>(); // private List> vtepPaths = new // ArrayList<>(); @Inject public TepCommandHelper(final DataBroker dataBroker, final ItmConfig itmConfig) { this.dataBroker = dataBroker; this.itmConfig = itmConfig; } @PostConstruct public void start() throws Exception { boolean defTzEnabled = itmConfig.isDefTzEnabled(); if (defTzEnabled) { String tunnelType = itmConfig.getDefTzTunnelType(); if (tunnelType == null || tunnelType.isEmpty()) { tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN; } configureTunnelType(ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType); LOG.debug("{} is created with {} tunnel-type.", ITMConstants.DEFAULT_TRANSPORT_ZONE, tunnelType); } else { LOG.debug("Removing {} on start-up, def-tz-enabled is false.", ITMConstants.DEFAULT_TRANSPORT_ZONE); // check if default-TZ already exists, then delete it because flag is OFF now. ItmUtils.deleteTransportZoneFromConfigDS(ITMConstants.DEFAULT_TRANSPORT_ZONE, dataBroker); } LOG.info("TepCommandHelper Started"); } @PreDestroy public void close() { LOG.info("TepCommandHelper Closed"); } @SuppressWarnings("checkstyle:IllegalCatch") public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, String gatewayIp, String transportZone, CommandSession session) throws TepException { check++; IpAddress ipAddressObj = null; IpAddress gatewayIpObj = null; IpPrefix subnetMaskObj = null; final VtepsKey vtepkey = new VtepsKey(dpnId, portName); try { ipAddressObj = new IpAddress(ipAddress.toCharArray()); gatewayIpObj = new IpAddress("0.0.0.0".toCharArray()); if (gatewayIp != null) { gatewayIpObj = new IpAddress(gatewayIp.toCharArray()); } else { LOG.debug("gateway is null"); } } catch (Exception e) { handleError("Invalid IpAddress. Expected: 1.0.0.0 to 254.255.255.255", session); return; } try { subnetMaskObj = new IpPrefix(subnetMask.toCharArray()); } catch (Exception e) { handleError("Invalid Subnet Mask. Expected: 0.0.0.0/0 to 255.255.255.255/32", session); return; } if (!validateIPs(ipAddress, subnetMask, gatewayIp)) { handleError("IpAddress and gateWayIp should belong to the subnet provided", session); return; } if (checkTepPerTzPerDpn(transportZone, dpnId)) { if (session != null) { session.getConsole().println("Only one end point per transport Zone per Dpn is allowed"); } return; } Vteps vtepCli = new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey) .setPortname(portName).build(); validateForDuplicates(vtepCli, transportZone); SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj); SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId); if (transportZonesHashMap.containsKey(transportZone)) { Map> subVtepMapTemp = transportZonesHashMap.get(transportZone); if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists List vtepListTemp = subVtepMapTemp.get(subObCli); if (vtepListTemp.contains(vtepCli)) { // do nothing } else { vtepListTemp.add(vtepCli); } } else { // subnet doesnt exist if (checkExistingSubnet(subVtepMapTemp, subObCli)) { if (session != null) { session.getConsole().println("subnet with subnet mask " + subObCli.get_key() + "already exists"); } return; } List vtepListTemp = new ArrayList<>(); vtepListTemp.add(vtepCli); subVtepMapTemp.put(subObCli, vtepListTemp); } } else { List vtepListTemp = new ArrayList<>(); vtepListTemp.add(vtepCli); Map> subVtepMapTemp = new HashMap<>(); subVtepMapTemp.put(subObCli, vtepListTemp); transportZonesHashMap.put(transportZone, subVtepMapTemp); } } private boolean validateIPs(String ipAddress, String subnetMask, String gatewayIp) { SubnetUtils utils = new SubnetUtils(subnetMask); if ((utils.getInfo().isInRange(ipAddress)) && ((gatewayIp == null) || (utils.getInfo().isInRange(gatewayIp)))) { return true; } else { LOG.trace("InValid IP"); return false; } } /** * Validate for duplicates. * * @param inputVtep * the input vtep * @param transportZone * the transport zone */ public void validateForDuplicates(Vteps inputVtep, String transportZone) { Map allTransportZonesAsMap = getAllTransportZonesAsMap(); boolean isConfiguredTepGreType = isGreTunnelType(transportZone, allTransportZonesAsMap); // Checking for duplicates in local cache for (String tz : transportZonesHashMap.keySet()) { boolean isGreType = isGreTunnelType(tz, allTransportZonesAsMap); Map> subVtepMapTemp = transportZonesHashMap.get(tz); for (SubnetObject subOb : subVtepMapTemp.keySet()) { List vtepList = subVtepMapTemp.get(subOb); validateForDuplicateAndSingleGreTep(inputVtep, isConfiguredTepGreType, isGreType, vtepList); } } // Checking for duplicates in config DS for (TransportZone tz : allTransportZonesAsMap.values()) { boolean isGreType = false; if (tz.getTunnelType().equals(TunnelTypeGre.class)) { isGreType = true; } for (Subnets sub : ItmUtils.emptyIfNull(tz.getSubnets())) { List vtepList = sub.getVteps(); validateForDuplicateAndSingleGreTep(inputVtep, isConfiguredTepGreType, isGreType, vtepList); } } } private void validateForDuplicateAndSingleGreTep(Vteps inputVtep, boolean isConfiguredTepGreType, boolean isGreType, List vtepList) { if (ItmUtils.isEmpty(vtepList)) { return; } if (vtepList.contains(inputVtep)) { Preconditions.checkArgument(false, "VTEP already exists"); } BigInteger dpnId = inputVtep.getDpnId(); if (isConfiguredTepGreType && isGreType) { for (Vteps vtep : vtepList) { if (vtep.getDpnId().equals(dpnId)) { String errMsg = "DPN [" + dpnId + "] already configured with GRE TEP." + " Mutiple GRE TEP's on a single DPN are not allowed."; Preconditions.checkArgument(false, errMsg); } } } } /** * Gets all transport zones as map. * * @return all transport zones as map */ private Map getAllTransportZonesAsMap() { TransportZones allTransportZones = getAllTransportZones(); Map transportZoneMap = new HashMap<>(); if (null != allTransportZones) { for (TransportZone tzone : ItmUtils.emptyIfNull(allTransportZones.getTransportZone())) { transportZoneMap.put(tzone.getZoneName(), tzone); } } return transportZoneMap; } /** * Checks if is gre tunnel type. * * @param transportZoneName * the zone name * @param trsnsportZoneMap * the zone map * @return true, if is gre tunnel type */ private boolean isGreTunnelType(String transportZoneName, Map trsnsportZoneMap) { TransportZone tzone = trsnsportZoneMap.get(transportZoneName); /* * if (tzone != null && * StringUtils.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_GRE, * tzone.getTunnelType())) { return true; } */ return (tzone != null) && (tzone.getTunnelType()).equals(TunnelTypeGre.class); } /** * Gets the transport zone. * * @param transportZoneName * the tzone * @return the transport zone */ public TransportZone getTransportZone(String transportZoneName) { InstanceIdentifier tzonePath = InstanceIdentifier.builder(TransportZones.class) .child(TransportZone.class, new TransportZoneKey(transportZoneName)).build(); return ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker).orNull(); } /** * Gets all transport zones. * * @return all transport zones */ public TransportZones getAllTransportZones() { InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); return ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker).orNull(); } public boolean checkExistingSubnet(Map> subVtepMapTemp, SubnetObject subObCli) { for (SubnetObject subOb : subVtepMapTemp.keySet()) { if (subOb.get_key().equals(subObCli.get_key())) { if (!(subOb.get_vlanId().equals(subObCli.get_vlanId()))) { return true; } if (!(subOb.get_gatewayIp().equals(subObCli.get_gatewayIp()))) { return true; } } } return false; } public boolean checkTepPerTzPerDpn(String tzone, BigInteger dpnId) { // check in local cache if (transportZonesHashMap.containsKey(tzone)) { Map> subVtepMapTemp = transportZonesHashMap.get(tzone); for (SubnetObject subOb : subVtepMapTemp.keySet()) { List vtepList = subVtepMapTemp.get(subOb); for (Vteps vtep : vtepList) { if (vtep.getDpnId().equals(dpnId)) { return true; } } } } // check in DS InstanceIdentifier tzonePath = InstanceIdentifier.builder(TransportZones.class) .child(TransportZone.class, new TransportZoneKey(tzone)).build(); Optional transportZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker); if (transportZoneOptional.isPresent()) { TransportZone tz = transportZoneOptional.get(); if (tz.getSubnets() == null || tz.getSubnets().isEmpty()) { return false; } for (Subnets sub : tz.getSubnets()) { if (sub.getVteps() == null || sub.getVteps().isEmpty()) { continue; } for (Vteps vtep : sub.getVteps()) { if (vtep.getDpnId().equals(dpnId)) { return true; } } } } return false; } @SuppressWarnings("checkstyle:IllegalCatch") public void buildTeps() { TransportZones transportZonesBuilt = null; TransportZone transportZone = null; try { LOG.debug("no of teps added" + check); if (transportZonesHashMap != null || !transportZonesHashMap.isEmpty()) { transportZoneArrayList = new ArrayList<>(); for (String tz : transportZonesHashMap.keySet()) { LOG.debug("transportZonesHashMap" + tz); subnetList = new ArrayList<>(); Map> subVtepMapTemp = transportZonesHashMap.get(tz); for (SubnetObject subOb : subVtepMapTemp.keySet()) { LOG.debug("subnets" + subOb.get_prefix()); List vtepList = subVtepMapTemp.get(subOb); Subnets subnet = new SubnetsBuilder().setGatewayIp(subOb.get_gatewayIp()) .setKey(subOb.get_key()).setPrefix(subOb.get_prefix()).setVlanId(subOb.get_vlanId()) .setVteps(vtepList).build(); subnetList.add(subnet); LOG.debug("vteps" + vtepList); } InstanceIdentifier transportZonePath = InstanceIdentifier.builder(TransportZones.class) .child(TransportZone.class, new TransportZoneKey(tz)).build(); Optional transportZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, transportZonePath, dataBroker); LOG.debug("read container from DS"); if (transportZoneOptional.isPresent()) { TransportZone tzoneFromDs = transportZoneOptional.get(); LOG.debug("read tzone container" + tzoneFromDs.toString()); if (tzoneFromDs.getTunnelType() == null || (tzoneFromDs.getTunnelType()).equals(TunnelTypeVxlan.class)) { transportZone = new TransportZoneBuilder().setKey(new TransportZoneKey(tz)) .setTunnelType(TunnelTypeVxlan.class).setSubnets(subnetList) .setZoneName(tz).build(); } else if ((tzoneFromDs.getTunnelType()).equals(TunnelTypeGre.class)) { transportZone = new TransportZoneBuilder().setKey(new TransportZoneKey(tz)) .setTunnelType(TunnelTypeGre.class).setSubnets(subnetList) .setZoneName(tz).build(); } } else { transportZone = new TransportZoneBuilder().setKey(new TransportZoneKey(tz)) .setTunnelType(TunnelTypeVxlan.class).setSubnets(subnetList).setZoneName(tz) .build(); } LOG.debug("tzone object" + transportZone); transportZoneArrayList.add(transportZone); } transportZonesBuilt = new TransportZonesBuilder().setTransportZone(transportZoneArrayList).build(); InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); LOG.debug("InstanceIdentifier" + path); ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, transportZonesBuilt, dataBroker, ItmUtils.DEFAULT_CALLBACK); LOG.debug("wrote to Config DS" + transportZonesBuilt); transportZonesHashMap.clear(); transportZoneArrayList.clear(); subnetList.clear(); LOG.debug("Everything cleared"); } else { LOG.debug("NO vteps were configured"); } } catch (Exception e) { LOG.error(e.getMessage()); } } @SuppressWarnings("checkstyle:RegexpSinglelineJava") public void showTeps(boolean monitorEnabled, int monitorInterval, CommandSession session) throws TepException { boolean flag = false; InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); Optional transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); if (transportZonesOptional.isPresent()) { TransportZones transportZones = transportZonesOptional.get(); if (transportZones.getTransportZone() == null || transportZones.getTransportZone().isEmpty()) { handleError("No teps configured", session); return; } List result = new ArrayList<>(); result.add(String.format("Tunnel Monitoring (for VXLAN tunnels): %s", (monitorEnabled ? "On" : "Off"))); result.add(String.format("Tunnel Monitoring Interval (for VXLAN tunnels): %d", monitorInterval)); result.add(System.lineSeparator()); result.add(String.format("%-16s %-16s %-16s %-12s %-12s %-12s %-16s %-12s", "TransportZone", "TunnelType", "SubnetMask", "GatewayIP", "VlanID", "DpnID", "IPAddress", "PortName")); result.add("---------------------------------------------------------------------------------------------" + "---------------------------------"); for (TransportZone tz : transportZones.getTransportZone()) { if (tz.getSubnets() == null || tz.getSubnets().isEmpty()) { LOG.error("Transport Zone " + tz.getZoneName() + "has no subnets"); continue; } for (Subnets sub : tz.getSubnets()) { if (sub.getVteps() == null || sub.getVteps().isEmpty()) { LOG.error("Transport Zone " + tz.getZoneName() + "subnet " + sub.getPrefix() + "has no vteps"); continue; } for (Vteps vtep : sub.getVteps()) { flag = true; String strTunnelType ; if ((tz.getTunnelType()).equals(TunnelTypeGre.class)) { strTunnelType = ITMConstants.TUNNEL_TYPE_GRE; } else { strTunnelType = ITMConstants.TUNNEL_TYPE_VXLAN; } result.add(String.format("%-16s %-16s %-16s %-12s %-12s %-12s %-16s %-12s", tz.getZoneName(), strTunnelType, sub.getPrefix().getIpv4Prefix().getValue(), sub.getGatewayIp().getIpv4Address().getValue(), sub.getVlanId().toString(), vtep.getDpnId().toString(), vtep.getIpAddress().getIpv4Address().getValue(), vtep.getPortname())); } } } if (session != null) { if (flag) { for (String print : result) { System.out.println(print); } } else { System.out.println("No teps to display"); } } } else if (session != null) { System.out.println("No teps configured"); } } @SuppressWarnings("checkstyle:RegexpSinglelineJava") public void showCache(String cacheName) { if (!DataStoreCache.isCacheValid(cacheName)) { System.out.println(" " + cacheName + " is not a valid Cache Name "); return ; } List keys = null; keys = DataStoreCache.getKeys(cacheName); if (keys != null && !keys.isEmpty()) { System.out.println("Dumping the data in cache for " + cacheName); for (Object key : keys) { System.out.println(" KEY: " + key + " Value: " + DataStoreCache.get(cacheName, key)); System.out.println(); } } else { System.out.println("No data in cache for " + cacheName); } } @SuppressWarnings("checkstyle:IllegalCatch") public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, String gatewayIp, String transportZone, CommandSession session) throws TepException { IpAddress ipAddressObj = null; IpAddress gatewayIpObj = null; IpPrefix subnetMaskObj = null; final VtepsKey vtepkey = new VtepsKey(dpnId, portName); try { ipAddressObj = new IpAddress(ipAddress.toCharArray()); gatewayIpObj = new IpAddress("0.0.0.0".toCharArray()); if (gatewayIp != null) { gatewayIpObj = new IpAddress(gatewayIp.toCharArray()); } else { LOG.debug("gateway is null"); } } catch (Exception e) { handleError("Invalid IpAddress. Expected: 1.0.0.0 to 254.255.255.255", session); return; } try { subnetMaskObj = new IpPrefix(subnetMask.toCharArray()); } catch (Exception e) { handleError("Invalid Subnet Mask. Expected: 0.0.0.0/0 to 255.255.255.255/32", session); return; } if (!validateIPs(ipAddress, subnetMask, gatewayIp)) { handleError("IpAddress and gateWayIp should belong to the subnet provided", session); return; } SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj); Vteps vtepCli = null; Subnets subCli = null; InstanceIdentifier vpath = InstanceIdentifier.builder(TransportZones.class) .child(TransportZone.class, new TransportZoneKey(transportZone)).child(Subnets.class, subnetsKey) .child(Vteps.class, vtepkey).build(); // check if present in tzones and delete from cache boolean existsInCache = isInCache(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone, session); if (!existsInCache) { Optional vtepOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, vpath, dataBroker); if (vtepOptional.isPresent()) { vtepCli = vtepOptional.get(); if (vtepCli.getIpAddress().equals(ipAddressObj)) { InstanceIdentifier spath = InstanceIdentifier .builder(TransportZones.class) .child(TransportZone.class, new TransportZoneKey(transportZone)) .child(Subnets.class, subnetsKey).build(); Optional subOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, spath, dataBroker); if (subOptional.isPresent()) { subCli = subOptional.get(); if (subCli.getGatewayIp().equals(gatewayIpObj) && subCli.getVlanId().equals(vlanId)) { vtepDelCommitList.add(vtepCli); } else if (session != null) { session.getConsole().println("vtep with this vlan or gateway doesnt exist"); } } } else if (session != null) { session.getConsole().println("Vtep with this ipaddress doesnt exist"); } } else if (session != null) { session.getConsole().println("Vtep Doesnt exist"); } } } @SuppressWarnings("checkstyle:IllegalCatch") public void deleteOnCommit() { List> vtepPaths = new ArrayList<>(); List> subnetPaths = new ArrayList<>(); List> tzPaths = new ArrayList<>(); List subDelList = new ArrayList<>(); List tzDelList = new ArrayList<>(); List vtepDelList = new ArrayList<>(); List> allPaths = new ArrayList<>(); try { if (vtepDelCommitList != null && !vtepDelCommitList.isEmpty()) { InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); Optional transportZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); if (transportZonesOptional.isPresent()) { TransportZones transportZones = transportZonesOptional.get(); for (TransportZone tz : transportZones.getTransportZone()) { if (tz.getSubnets() == null || tz.getSubnets().isEmpty()) { continue; } for (Subnets sub : tz.getSubnets()) { vtepDelList.addAll(vtepDelCommitList); for (Vteps vtep : vtepDelList) { InstanceIdentifier vpath = (InstanceIdentifier) InstanceIdentifier .builder(TransportZones.class) .child(TransportZone.class, tz.getKey()) .child(Subnets.class, sub.getKey()) .child(Vteps.class, vtep.getKey()).build(); if (sub.getVteps().remove(vtep)) { vtepPaths.add(vpath); if (sub.getVteps().size() == 0 || sub.getVteps() == null) { subDelList.add(sub); } } } } } for (TransportZone tz : transportZones.getTransportZone()) { if (tz.getSubnets() == null || tz.getSubnets().isEmpty()) { continue; } for (Subnets sub : subDelList) { if (tz.getSubnets().remove(sub)) { InstanceIdentifier spath = (InstanceIdentifier) InstanceIdentifier .builder(TransportZones.class) .child(TransportZone.class, tz.getKey()) .child(Subnets.class, sub.getKey()).build(); subnetPaths.add(spath); if (tz.getSubnets() == null || tz.getSubnets().size() == 0) { tzDelList.add(tz); } } } } for (TransportZone tz : tzDelList) { if (transportZones.getTransportZone().remove(tz)) { InstanceIdentifier tpath = (InstanceIdentifier) InstanceIdentifier.builder(TransportZones.class) .child(TransportZone.class, tz.getKey()).build(); tzPaths.add(tpath); if (transportZones.getTransportZone() == null || transportZones.getTransportZone().size() == 0) { MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.CONFIGURATION, path, ItmUtils.DEFAULT_CALLBACK); return; } } } allPaths.addAll(vtepPaths); allPaths.addAll(subnetPaths); allPaths.addAll(tzPaths); ItmUtils.asyncBulkRemove(dataBroker, LogicalDatastoreType.CONFIGURATION, allPaths, ItmUtils.DEFAULT_CALLBACK); } vtepPaths.clear(); subnetPaths.clear(); tzPaths.clear(); allPaths.clear(); vtepDelCommitList.clear(); } } catch (Exception e) { LOG.error(e.getMessage()); } } @SuppressWarnings("checkstyle:RegexpSinglelineJava") public void showState(List tunnelLists, boolean tunnelMonitorEnabled, CommandSession session) throws TepException { if (tunnelLists == null || tunnelLists.isEmpty()) { handleError("No Internal Tunnels Exist", session); return; } if (!tunnelMonitorEnabled) { if (session != null) { session.getConsole().println("Tunnel Monitoring is Off"); } } String displayFormat = "%-16s %-16s %-16s %-16s %-16s %-10s %-10s"; System.out.println(String.format(displayFormat, "Tunnel Name", "Source-DPN", "Destination-DPN", "Source-IP", "Destination-IP", "Trunk-State", "Transport Type")); System.out.println("-----------------------------------------------------------------------------------------" + "--------------------------------------------"); for (StateTunnelList tunnelInst : tunnelLists) { // Display only the internal tunnels if (tunnelInst.getDstInfo().getTepDeviceType().equals(TepTypeInternal.class)) { String tunnelInterfaceName = tunnelInst.getTunnelInterfaceName(); LOG.trace("tunnelInterfaceName::: {}", tunnelInterfaceName); String tunnelState = ITMConstants.TUNNEL_STATE_UNKNOWN; if (tunnelInst.getOperState() == TunnelOperStatus.Up) { tunnelState = ITMConstants.TUNNEL_STATE_UP; } else if (tunnelInst.getOperState() == TunnelOperStatus.Down) { tunnelState = ITMConstants.TUNNEL_STATE_DOWN; } Class tunType = tunnelInst.getTransportType(); String tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN; if (tunType.equals(TunnelTypeVxlan.class)) { tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN; } else if (tunType.equals(TunnelTypeGre.class)) { tunnelType = ITMConstants.TUNNEL_TYPE_GRE; } else if (tunType.equals(TunnelTypeMplsOverGre.class)) { tunnelType = ITMConstants.TUNNEL_TYPE_MPLSoGRE; } System.out.println(String.format(displayFormat, tunnelInst.getTunnelInterfaceName(), tunnelInst.getSrcInfo().getTepDeviceId(), tunnelInst.getDstInfo().getTepDeviceId(), tunnelInst.getSrcInfo().getTepIp().getIpv4Address().getValue(), tunnelInst.getDstInfo().getTepIp().getIpv4Address().getValue(), tunnelState, tunnelType)); } } } // deletes from ADD-cache if it exists. public boolean isInCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, String gatewayIp, String transportZone, CommandSession session) { boolean exists = false; final VtepsKey vtepkey = new VtepsKey(dpnId, portName); IpAddress ipAddressObj = new IpAddress(ipAddress.toCharArray()); IpPrefix subnetMaskObj = new IpPrefix(subnetMask.toCharArray()); IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray()); if (gatewayIp != null) { gatewayIpObj = new IpAddress(gatewayIp.toCharArray()); } else { LOG.debug("gateway is null"); } SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj); Vteps vtepCli = new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey) .setPortname(portName).build(); SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId); if (transportZonesHashMap.containsKey(transportZone)) { Map> subVtepMapTemp = transportZonesHashMap.get(transportZone); if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists List vtepListTemp = subVtepMapTemp.get(subObCli); if (vtepListTemp.contains(vtepCli)) { exists = true; // return true if tzones has vtep vtepListTemp.remove(vtepCli); if (vtepListTemp.size() == 0) { subVtepMapTemp.remove(subObCli); if (subVtepMapTemp.size() == 0) { transportZonesHashMap.remove(transportZone); } } } else if (session != null) { session.getConsole().println("Vtep " + "has not been configured"); } } } return exists; } public void configureTunnelType(String transportZoneName, String tunnelType) { LOG.debug("configureTunnelType {} for transportZone {}", tunnelType, transportZoneName); TransportZone transportZoneFromConfigDS = ItmUtils.getTransportZoneFromConfigDS(transportZoneName, dataBroker); Class tunType; validateTunnelType(transportZoneName, tunnelType, transportZoneFromConfigDS); if (transportZoneFromConfigDS != null) { if (!transportZoneName.equals(ITMConstants.DEFAULT_TRANSPORT_ZONE)) { LOG.debug("Transport zone {} with tunnel type {} already exists. No action required.", transportZoneName, tunnelType); return; } else { tunnelType = StringUtils.upperCase(tunnelType); tunType = ItmUtils.TUNNEL_TYPE_MAP.get(tunnelType); if (transportZoneFromConfigDS.getTunnelType().equals(tunType)) { // default-TZ already exists and tunnel-type is not changed during // controller restart, then nothing to do now. Just return. return; } } } // get tunnel-type tunnelType = StringUtils.upperCase(tunnelType); tunType = ItmUtils.TUNNEL_TYPE_MAP.get(tunnelType); TransportZones transportZones = null; List tzList = null; InstanceIdentifier path = InstanceIdentifier.builder(TransportZones.class).build(); Optional tzones = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); TransportZone tzone = new TransportZoneBuilder().setKey(new TransportZoneKey(transportZoneName)) .setTunnelType(tunType).build(); if (tzones.isPresent()) { tzList = tzones.get().getTransportZone(); if (tzList == null || tzList.isEmpty()) { tzList = new ArrayList<>(); } } else { tzList = new ArrayList<>(); } tzList.add(tzone); transportZones = new TransportZonesBuilder().setTransportZone(tzList).build(); ItmUtils.syncWrite(LogicalDatastoreType.CONFIGURATION, path, transportZones, dataBroker); } /** * Validate tunnel type. * * @param transportZoneName * the t zone name * @param tunnelType * the tunnel type */ private void validateTunnelType(String transportZoneName, String tunnelType,TransportZone tzoneFromConfigDs) { /* * String strTunnelType = ItmUtils.validateTunnelType(tunnelType); * * TransportZone tZone = getTransportZone(tZoneName); if (tZone != null) * { if (!StringUtils.equalsIgnoreCase(strTunnelType, * tZone.getTunnelType()) && ItmUtils.isNotEmpty(tZone.getSubnets())) { * String errorMsg = new StringBuilder("Changing the tunnel type from " * ).append(tZone.getTunnelType()) .append(" to ").append(strTunnelType) * .append(" is not allowed for already configured transport zone [" * ).append(tZoneName) .append("].").toString(); * Preconditions.checkArgument(false, errorMsg); } } */ String strTunnelType = ItmUtils.validateTunnelType(tunnelType); Class tunType; if (strTunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN)) { tunType = TunnelTypeVxlan.class; } else { tunType = TunnelTypeGre.class; } // TransportZone tZone = getTransportZone(tZoneName); // if (tZone != null) { if (tzoneFromConfigDs != null) { if ((!tzoneFromConfigDs.getTunnelType().equals(tunType)) && ItmUtils.isNotEmpty(tzoneFromConfigDs .getSubnets())) { // for default-TZ, such error message is not needed to be thrown. // it needs to be handled in different way, by deleting default-TZ // with old tunnel-type and then add default-TZ with new tunnel-type if (!transportZoneName.equals(ITMConstants.DEFAULT_TRANSPORT_ZONE)) { String errorMsg = "Changing the tunnel type from " + tzoneFromConfigDs.getTunnelType() + " to " + strTunnelType + " is not allowed for already configured transport zone [" + transportZoneName + "]."; Preconditions.checkArgument(false, errorMsg); } else { // delete already existing default TZ ItmUtils.deleteTransportZoneFromConfigDS(ITMConstants.DEFAULT_TRANSPORT_ZONE, dataBroker); } } } } public void configureTunnelMonitorParams(boolean monitorEnabled, String monitorProtocol) { InstanceIdentifier path = InstanceIdentifier.builder(TunnelMonitorParams.class).build(); Optional storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); Class monitorType ; if (storedTunnelMonitor.isPresent() && storedTunnelMonitor.get().getMonitorProtocol() != null) { monitorType = storedTunnelMonitor.get().getMonitorProtocol(); } else { if (monitorProtocol != null && monitorProtocol.equalsIgnoreCase(ITMConstants.MONITOR_TYPE_LLDP)) { monitorType = TunnelMonitoringTypeLldp.class; } else { monitorType = TunnelMonitoringTypeBfd.class; } } if (!storedTunnelMonitor.isPresent() || storedTunnelMonitor.get().isEnabled() != monitorEnabled) { TunnelMonitorParams tunnelMonitor = new TunnelMonitorParamsBuilder().setEnabled(monitorEnabled) .setMonitorProtocol(monitorType).build(); ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker, ItmUtils.DEFAULT_CALLBACK); } } public void configureTunnelMonitorInterval(int interval) { InstanceIdentifier path = InstanceIdentifier.builder(TunnelMonitorInterval.class).build(); Optional storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker); if (!storedTunnelMonitor.isPresent() || storedTunnelMonitor.get().getInterval() != interval) { TunnelMonitorInterval tunnelMonitor = new TunnelMonitorIntervalBuilder().setInterval(interval).build(); ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker, ItmUtils.DEFAULT_CALLBACK); } } public void handleError(String errorMessage, CommandSession session) throws TepException { if (session != null) { session.getConsole().println(errorMessage); } else { throw new TepException(errorMessage); } } }