Natservice module bug fixes
[vpnservice.git] / natservice / natservice-impl / src / main / java / org / opendaylight / vpnservice / natservice / internal / ExternalNetworksChangeListener.java
index 3207b5c74b9fd834712937f80b687a748ada6766..8f847962a5b3abab1c745fde0e37b008f72a5a97 100644 (file)
-/*
- * Copyright (c) 2016 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.vpnservice.natservice.internal;
-
-import com.google.common.base.Optional;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
-import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
-import org.opendaylight.vpnservice.mdsalutil.ActionType;
-import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
-import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
-import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
-import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
-import org.opendaylight.vpnservice.mdsalutil.InstructionType;
-import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
-import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
-import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
-import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
-import org.opendaylight.vpnservice.mdsalutil.NwConstants;
-import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExtRouters;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpMap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.RoutersKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.math.BigInteger;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
-import org.opendaylight.bgpmanager.api.IBgpManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;
-
-/**
- * Created by ESUMAMS on 1/21/2016.
- */
-public class ExternalNetworksChangeListener extends AsyncDataTreeChangeListenerBase<Networks, ExternalNetworksChangeListener>
-{
-    private static final Logger LOG = LoggerFactory.getLogger( ExternalNetworksChangeListener.class);
-
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private final DataBroker dataBroker;
-    private IMdsalApiManager mdsalManager;
-    //private VpnFloatingIpHandler vpnFloatingIpHandler;
-    private FloatingIPListener floatingIpListener;
-    private ExternalRoutersListener externalRouterListener;
-    private OdlInterfaceRpcService interfaceManager;
-    private NaptManager naptManager;
-
-    private IBgpManager bgpManager;
-    private VpnRpcService vpnService;
-    private FibRpcService fibService;
-
-
-    private ExternalRoutersListener externalRoutersListener;
-
-    void setMdsalManager(IMdsalApiManager mdsalManager) {
-        this.mdsalManager = mdsalManager;
-    }
-
-    void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
-        this.interfaceManager = interfaceManager;
-    }
-
-    void setFloatingIpListener(FloatingIPListener floatingIpListener) {
-        this.floatingIpListener = floatingIpListener;
-    }
-
-    void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {
-        this.externalRouterListener = externalRoutersListener;
-    }
-
-    public void setBgpManager(IBgpManager bgpManager) {
-        this.bgpManager = bgpManager;
-    }
-
-    public void setNaptManager(NaptManager naptManager) {
-        this.naptManager = naptManager;
-    }
-
-    public void setVpnService(VpnRpcService vpnService) {
-        this.vpnService = vpnService;
-    }
-
-    public void setFibService(FibRpcService fibService) {
-        this.fibService = fibService;
-    }
-
-    public void setListenerRegistration(ListenerRegistration<DataChangeListener> listenerRegistration) {
-        this.listenerRegistration = listenerRegistration;
-    }
-
-    public ExternalNetworksChangeListener(final DataBroker dataBroker ) {
-        super( Networks.class, ExternalNetworksChangeListener.class );
-        this.dataBroker = dataBroker;
-    }
-
-
-    protected InstanceIdentifier<Networks> getWildCardPath() {
-        return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class);
-    }
-
-
-    @Override
-    protected void add(InstanceIdentifier<Networks> identifier, Networks networks) {
-
-    }
-
-    @Override
-    protected ExternalNetworksChangeListener getDataTreeChangeListener() {
-        return ExternalNetworksChangeListener.this;
-    }
-
-    @Override
-    protected void remove(InstanceIdentifier<Networks> identifier, Networks networks) {
-        if( identifier == null || networks == null || networks.getRouterIds().isEmpty() ) {
-            LOG.info( "ExternalNetworksChangeListener:remove:: returning without processing since networks/identifier is null"  );
-            return;
-        }
-
-        for( Uuid routerId: networks.getRouterIds() ) {
-            String routerName = routerId.toString();
-
-            InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitchInstanceIdentifier =
-                    getRouterToNaptSwitchInstanceIdentifier( routerName);
-
-            MDSALUtil.syncDelete( dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitchInstanceIdentifier );
-
-            LOG.debug( "ExternalNetworksChangeListener:delete:: successful deletion of data in napt-switches container" );
-        }
-    }
-
-    private static InstanceIdentifier<RouterToNaptSwitch> getRouterToNaptSwitchInstanceIdentifier( String routerName ) {
-
-        return  InstanceIdentifier.builder( NaptSwitches.class )
-                        .child( RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
-
-    }
-
-    public void close() throws Exception {
-        if (listenerRegistration != null) {
-            try {
-                listenerRegistration.close();
-            }
-            catch (final Exception e) {
-                LOG.error("Error when cleaning up ExternalNetworksChangeListener.", e);
-            }
-
-            listenerRegistration = null;
-        }
-        LOG.debug("ExternalNetworksChangeListener Closed");
-    }
-
-
-    @Override
-    protected void update(InstanceIdentifier<Networks> identifier, Networks original, Networks update) {
-        //Check for VPN disassociation
-        Uuid originalVpn = original.getVpnid();
-        Uuid updatedVpn = update.getVpnid();
-        if(originalVpn == null && updatedVpn != null) {
-            //external network is dis-associated from L3VPN instance
-            associateExternalNetworkWithVPN(update);
-            //Install the VPN related FIB entries
-            installVpnFibEntries(update, updatedVpn.getValue());
-        } else if(originalVpn != null && updatedVpn == null) {
-            //external network is associated with vpn
-            disassociateExternalNetworkFromVPN(update, originalVpn.getValue());
-            //Remove the SNAT entries
-            removeSnatEntries(original, original.getId());
-        }
-    }
-
-    private void installVpnFibEntries(Networks update, String vpnName){
-        List<Uuid> routerUuids = update.getRouterIds();
-        for(Uuid routerUuid :routerUuids){
-            InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
-                    (Routers.class, new RoutersKey(routerUuid.getValue())).build();
-            Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
-            if(!routerData.isPresent()){
-                continue;
-            }
-            String routerName = routerData.get().getRouterName();
-            List<String> externalIps = routerData.get().getExternalIps();
-            InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
-            Optional<RouterToNaptSwitch> rtrToNapt = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch);
-            if(!rtrToNapt.isPresent()) {
-                LOG.debug("Unable to retrieve the Primary switch DPN ID");
-                continue;
-            }
-            BigInteger naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
-            for(String externalIp: externalIps) {
-                externalRouterListener.advToBgpAndInstallFibAndTsFlows(naptSwitchDpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, NatUtil.getVpnId(dataBroker, routerName), externalIp,
-                        vpnService, fibService, bgpManager, dataBroker, LOG);
-            }
-        }
-    }
-
-    private void removeSnatEntries(Networks original, Uuid networkUuid){
-        List<Uuid> routerUuids = original.getRouterIds();
-        for(Uuid routerUuid :routerUuids){
-            InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
-                    (Routers.class, new RoutersKey(routerUuid.getValue())).build();
-            Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
-            List<String> externalIps = null;
-            if(!routerData.isPresent()){
-                continue;
-            }
-            externalIps = routerData.get().getExternalIps();
-            externalRouterListener.handleDisableSnat(routerUuid.getValue(), networkUuid, externalIps);
-        }
-    }
-
-    private void associateExternalNetworkWithVPN(Networks network) {
-        List<Uuid> routerIds = network.getRouterIds();
-        for(Uuid routerId : routerIds) {
-            //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
-
-            InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
-            Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
-            if(!optRouterPorts.isPresent()) {
-                LOG.debug("Could not read Router Ports data object with id: {} to handle associate ext nw {}", routerId, network.getId());
-                continue;
-            }
-            RouterPorts routerPorts = optRouterPorts.get();
-            List<Ports> interfaces = routerPorts.getPorts();
-            for(Ports port : interfaces) {
-                String portName = port.getPortName();
-                BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
-                if(dpnId.equals(BigInteger.ZERO)) {
-                    LOG.debug("DPN not found for {}, skip handling of ext nw {} association", portName, network.getId());
-                    continue;
-                }
-                List<IpMapping> ipMapping = port.getIpMapping();
-                for(IpMapping ipMap : ipMapping) {
-                    String externalIp = ipMap.getExternalIp();
-                    //remove all VPN related entries
-                    floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);
-                }
-            }
-        }
-
-        // SNAT
-        for(Uuid routerId : routerIds) {
-            LOG.debug("NAT Service : associateExternalNetworkWithVPN() for routerId {}",  routerId);
-            Uuid networkId = network.getId();
-            if(networkId == null) {
-                LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
-                return;
-            }
-            final String vpnName = network.getVpnid().getValue();
-            if(vpnName == null) {
-                LOG.error("NAT Service : No VPN associated with ext nw {} for router {}", networkId, routerId);
-                return;
-            }
-
-            BigInteger dpnId = new BigInteger("0");
-            InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue());
-            Optional<RouterToNaptSwitch> rtrToNapt = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch );
-            if(rtrToNapt.isPresent()) {
-                dpnId = rtrToNapt.get().getPrimarySwitchId();
-            }
-            LOG.debug("NAT Service : got primarySwitch as dpnId{} ", dpnId);
-
-            Long routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue());
-            InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> idBuilder =
-                            InstanceIdentifier.builder(IntextIpMap.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey(routerIdentifier));
-            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> id = idBuilder.build();
-            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
-            if (ipMapping.isPresent()) {
-                  List<IpMap> ipMaps = ipMapping.get().getIpMap();
-                  for (IpMap ipMap : ipMaps) {
-                      String externalIp = ipMap.getExternalIp();
-                      LOG.debug("NAT Service : got externalIp as {}", externalIp);
-                      LOG.debug("NAT Service : About to call advToBgpAndInstallFibAndTsFlows for dpnId {}, vpnName {} and externalIp {}", dpnId, vpnName, externalIp);
-                      externalRouterListener.advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, NatUtil.getVpnId(dataBroker, routerId.getValue()), externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
-                  }
-            } else {
-                LOG.warn("NAT Service : No ipMapping present fot the routerId {}", routerId);
-            }
-
-            long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
-            // Install 47 entry to point to 21
-            if(vpnId != -1) {
-                LOG.debug("NAT Service : Calling externalRouterListener installNaptPfibEntry for donId {} and vpnId {}", dpnId, vpnId);
-                externalRouterListener.installNaptPfibEntry(dpnId, vpnId);
-            }
-
-        }
-
-    }
-
-    private void disassociateExternalNetworkFromVPN(Networks network, String vpnName) {
-        List<Uuid> routerIds = network.getRouterIds();
-
-        //long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
-        for(Uuid routerId : routerIds) {
-            //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());
-
-            InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());
-            Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
-            if(!optRouterPorts.isPresent()) {
-                LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate ext nw {}", routerId, network.getId());
-                continue;
-            }
-            RouterPorts routerPorts = optRouterPorts.get();
-            List<Ports> interfaces = routerPorts.getPorts();
-            for(Ports port : interfaces) {
-                String portName = port.getPortName();
-                BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
-                if(dpnId.equals(BigInteger.ZERO)) {
-                    LOG.debug("DPN not found for {}, skip handling of ext nw {} disassociation", portName, network.getId());
-                    continue;
-                }
-                List<IpMapping> ipMapping = port.getIpMapping();
-                for(IpMapping ipMap : ipMapping) {
-                    String externalIp = ipMap.getExternalIp();
-                    floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);
-                }
-            }
-        }
-    }
-
-    public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
-        BigInteger nodeId = BigInteger.ZERO;
-        try {
-            GetDpidFromInterfaceInput
-                    dpIdInput =
-                    new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
-            Future<RpcResult<GetDpidFromInterfaceOutput>>
-                    dpIdOutput =
-                    interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
-            RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
-            if (dpIdResult.isSuccessful()) {
-                nodeId = dpIdResult.getResult().getDpid();
-            } else {
-                LOG.error("Could not retrieve DPN Id for interface {}", ifName);
-            }
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.error("Exception when getting dpn for interface {}", ifName,  e);
-        }
-        return nodeId;
-    }
-
-}
+/*\r
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.vpnservice.natservice.internal;\r
+\r
+import com.google.common.base.Optional;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;\r
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;\r
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpMap;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;\r
+import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;\r
+import org.opendaylight.yangtools.yang.common.RpcResult;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import java.math.BigInteger;\r
+import java.util.List;\r
+import java.util.concurrent.ExecutionException;\r
+import java.util.concurrent.Future;\r
+\r
+import org.opendaylight.bgpmanager.api.IBgpManager;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;\r
+\r
+/**\r
+ * Created by ESUMAMS on 1/21/2016.\r
+ */\r
+public class ExternalNetworksChangeListener extends AsyncDataTreeChangeListenerBase<Networks, ExternalNetworksChangeListener>\r
+{\r
+    private static final Logger LOG = LoggerFactory.getLogger( ExternalNetworksChangeListener.class);\r
+\r
+    private ListenerRegistration<DataChangeListener> listenerRegistration;\r
+    private final DataBroker dataBroker;\r
+    private IMdsalApiManager mdsalManager;\r
+    //private VpnFloatingIpHandler vpnFloatingIpHandler;\r
+    private FloatingIPListener floatingIpListener;\r
+    private ExternalRoutersListener externalRouterListener;\r
+    private OdlInterfaceRpcService interfaceManager;\r
+    private NaptManager naptManager;\r
+\r
+    private IBgpManager bgpManager;\r
+    private VpnRpcService vpnService;\r
+    private FibRpcService fibService;\r
+\r
+\r
+    private ExternalRoutersListener externalRoutersListener;\r
+\r
+    void setMdsalManager(IMdsalApiManager mdsalManager) {\r
+        this.mdsalManager = mdsalManager;\r
+    }\r
+\r
+    void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {\r
+        this.interfaceManager = interfaceManager;\r
+    }\r
+\r
+    void setFloatingIpListener(FloatingIPListener floatingIpListener) {\r
+        this.floatingIpListener = floatingIpListener;\r
+    }\r
+\r
+    void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {\r
+        this.externalRouterListener = externalRoutersListener;\r
+    }\r
+\r
+    public void setBgpManager(IBgpManager bgpManager) {\r
+        this.bgpManager = bgpManager;\r
+    }\r
+\r
+    public void setNaptManager(NaptManager naptManager) {\r
+        this.naptManager = naptManager;\r
+    }\r
+\r
+    public void setVpnService(VpnRpcService vpnService) {\r
+        this.vpnService = vpnService;\r
+    }\r
+\r
+    public void setFibService(FibRpcService fibService) {\r
+        this.fibService = fibService;\r
+    }\r
+\r
+    public void setListenerRegistration(ListenerRegistration<DataChangeListener> listenerRegistration) {\r
+        this.listenerRegistration = listenerRegistration;\r
+    }\r
+\r
+    public ExternalNetworksChangeListener(final DataBroker dataBroker ) {\r
+        super( Networks.class, ExternalNetworksChangeListener.class );\r
+        this.dataBroker = dataBroker;\r
+    }\r
+\r
+\r
+    protected InstanceIdentifier<Networks> getWildCardPath() {\r
+        return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class);\r
+    }\r
+\r
+\r
+    @Override\r
+    protected void add(InstanceIdentifier<Networks> identifier, Networks networks) {\r
+\r
+    }\r
+\r
+    @Override\r
+    protected ExternalNetworksChangeListener getDataTreeChangeListener() {\r
+        return ExternalNetworksChangeListener.this;\r
+    }\r
+\r
+    @Override\r
+    protected void remove(InstanceIdentifier<Networks> identifier, Networks networks) {\r
+        if( identifier == null || networks == null || networks.getRouterIds().isEmpty() ) {\r
+            LOG.info( "ExternalNetworksChangeListener:remove:: returning without processing since networks/identifier is null"  );\r
+            return;\r
+        }\r
+\r
+        for( Uuid routerId: networks.getRouterIds() ) {\r
+            String routerName = routerId.toString();\r
+\r
+            InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitchInstanceIdentifier =\r
+                    getRouterToNaptSwitchInstanceIdentifier( routerName);\r
+\r
+            MDSALUtil.syncDelete( dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitchInstanceIdentifier );\r
+\r
+            LOG.debug( "ExternalNetworksChangeListener:delete:: successful deletion of data in napt-switches container" );\r
+        }\r
+    }\r
+\r
+    private static InstanceIdentifier<RouterToNaptSwitch> getRouterToNaptSwitchInstanceIdentifier( String routerName ) {\r
+\r
+        return  InstanceIdentifier.builder( NaptSwitches.class )\r
+                        .child( RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();\r
+\r
+    }\r
+\r
+    public void close() throws Exception {\r
+        if (listenerRegistration != null) {\r
+            try {\r
+                listenerRegistration.close();\r
+            }\r
+            catch (final Exception e) {\r
+                LOG.error("Error when cleaning up ExternalNetworksChangeListener.", e);\r
+            }\r
+\r
+            listenerRegistration = null;\r
+        }\r
+        LOG.debug("ExternalNetworksChangeListener Closed");\r
+    }\r
+\r
+\r
+    @Override\r
+    protected void update(InstanceIdentifier<Networks> identifier, Networks original, Networks update) {\r
+        //Check for VPN disassociation\r
+        Uuid originalVpn = original.getVpnid();\r
+        Uuid updatedVpn = update.getVpnid();\r
+        if(originalVpn == null && updatedVpn != null) {\r
+            //external network is dis-associated from L3VPN instance\r
+            associateExternalNetworkWithVPN(update);\r
+        } else if(originalVpn != null && updatedVpn == null) {\r
+            //external network is associated with vpn\r
+            disassociateExternalNetworkFromVPN(update, originalVpn.getValue());\r
+            //Remove the SNAT entries\r
+            removeSnatEntries(original, original.getId());\r
+        }\r
+    }\r
+\r
+    private void removeSnatEntries(Networks original, Uuid networkUuid) {\r
+        List<Uuid> routerUuids = original.getRouterIds();\r
+        for (Uuid routerUuid : routerUuids) {\r
+            Long routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue());\r
+            if (routerId == NatConstants.INVALID_ID) {\r
+                LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerUuid.getValue());\r
+                return;\r
+            }\r
+            List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);\r
+            externalRouterListener.handleDisableSnatInternetVpn(routerUuid.getValue(), networkUuid, externalIps, false, original.getVpnid().getValue());\r
+        }\r
+    }\r
+\r
+    private void associateExternalNetworkWithVPN(Networks network) {\r
+        List<Uuid> routerIds = network.getRouterIds();\r
+        for(Uuid routerId : routerIds) {\r
+            //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());\r
+\r
+            InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());\r
+            Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);\r
+            if(!optRouterPorts.isPresent()) {\r
+                LOG.debug("Could not read Router Ports data object with id: {} to handle associate ext nw {}", routerId, network.getId());\r
+                continue;\r
+            }\r
+            RouterPorts routerPorts = optRouterPorts.get();\r
+            List<Ports> interfaces = routerPorts.getPorts();\r
+            for(Ports port : interfaces) {\r
+                String portName = port.getPortName();\r
+                BigInteger dpnId = getDpnForInterface(interfaceManager, portName);\r
+                if(dpnId.equals(BigInteger.ZERO)) {\r
+                    LOG.debug("DPN not found for {}, skip handling of ext nw {} association", portName, network.getId());\r
+                    continue;\r
+                }\r
+                List<IpMapping> ipMapping = port.getIpMapping();\r
+                for(IpMapping ipMap : ipMapping) {\r
+                    String externalIp = ipMap.getExternalIp();\r
+                    //remove all VPN related entries\r
+                    floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);\r
+                }\r
+            }\r
+        }\r
+\r
+        // SNAT\r
+        for(Uuid routerId : routerIds) {\r
+            LOG.debug("NAT Service : associateExternalNetworkWithVPN() for routerId {}",  routerId);\r
+            Uuid networkId = network.getId();\r
+            if(networkId == null) {\r
+                LOG.error("NAT Service : networkId is null for the router ID {}", routerId);\r
+                return;\r
+            }\r
+            final String vpnName = network.getVpnid().getValue();\r
+            if(vpnName == null) {\r
+                LOG.error("NAT Service : No VPN associated with ext nw {} for router {}", networkId, routerId);\r
+                return;\r
+            }\r
+\r
+            BigInteger dpnId = new BigInteger("0");\r
+            InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue());\r
+            Optional<RouterToNaptSwitch> rtrToNapt = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch );\r
+            if(rtrToNapt.isPresent()) {\r
+                dpnId = rtrToNapt.get().getPrimarySwitchId();\r
+            }\r
+            LOG.debug("NAT Service : got primarySwitch as dpnId{} ", dpnId);\r
+\r
+            Long routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue());\r
+            InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> idBuilder =\r
+                            InstanceIdentifier.builder(IntextIpMap.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey(routerIdentifier));\r
+            InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> id = idBuilder.build();\r
+            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);\r
+            if (ipMapping.isPresent()) {\r
+                  List<IpMap> ipMaps = ipMapping.get().getIpMap();\r
+                  for (IpMap ipMap : ipMaps) {\r
+                      String externalIp = ipMap.getExternalIp();\r
+                      LOG.debug("NAT Service : got externalIp as {}", externalIp);\r
+                      LOG.debug("NAT Service : About to call advToBgpAndInstallFibAndTsFlows for dpnId {}, vpnName {} and externalIp {}", dpnId, vpnName, externalIp);\r
+                      externalRouterListener.advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, NatUtil.getVpnId(dataBroker, routerId.getValue()), externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);\r
+                  }\r
+            } else {\r
+                LOG.warn("NAT Service : No ipMapping present fot the routerId {}", routerId);\r
+            }\r
+\r
+            long vpnId = NatUtil.getVpnId(dataBroker, vpnName);\r
+            // Install 47 entry to point to 21\r
+            if(vpnId != -1) {\r
+                LOG.debug("NAT Service : Calling externalRouterListener installNaptPfibEntry for donId {} and vpnId {}", dpnId, vpnId);\r
+                externalRouterListener.installNaptPfibEntry(dpnId, vpnId);\r
+            }\r
+\r
+        }\r
+\r
+    }\r
+\r
+    private void disassociateExternalNetworkFromVPN(Networks network, String vpnName) {\r
+        List<Uuid> routerIds = network.getRouterIds();\r
+\r
+        //long vpnId = NatUtil.getVpnId(dataBroker, vpnName);\r
+        for(Uuid routerId : routerIds) {\r
+            //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());\r
+\r
+            InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());\r
+            Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);\r
+            if(!optRouterPorts.isPresent()) {\r
+                LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate ext nw {}", routerId, network.getId());\r
+                continue;\r
+            }\r
+            RouterPorts routerPorts = optRouterPorts.get();\r
+            List<Ports> interfaces = routerPorts.getPorts();\r
+            for(Ports port : interfaces) {\r
+                String portName = port.getPortName();\r
+                BigInteger dpnId = getDpnForInterface(interfaceManager, portName);\r
+                if(dpnId.equals(BigInteger.ZERO)) {\r
+                    LOG.debug("DPN not found for {}, skip handling of ext nw {} disassociation", portName, network.getId());\r
+                    continue;\r
+                }\r
+                List<IpMapping> ipMapping = port.getIpMapping();\r
+                for(IpMapping ipMap : ipMapping) {\r
+                    String externalIp = ipMap.getExternalIp();\r
+                    floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {\r
+        BigInteger nodeId = BigInteger.ZERO;\r
+        try {\r
+            GetDpidFromInterfaceInput\r
+                    dpIdInput =\r
+                    new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();\r
+            Future<RpcResult<GetDpidFromInterfaceOutput>>\r
+                    dpIdOutput =\r
+                    interfaceManagerRpcService.getDpidFromInterface(dpIdInput);\r
+            RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();\r
+            if (dpIdResult.isSuccessful()) {\r
+                nodeId = dpIdResult.getResult().getDpid();\r
+            } else {\r
+                LOG.error("Could not retrieve DPN Id for interface {}", ifName);\r
+            }\r
+        } catch (InterruptedException | ExecutionException e) {\r
+            LOG.error("Exception when getting dpn for interface {}", ifName,  e);\r
+        }\r
+        return nodeId;\r
+    }\r
+\r
+}\r