X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=natservice%2Fimpl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetvirt%2Fnatservice%2Finternal%2FExternalNetworksChangeListener.java;h=377db6a72d0260bf63fab2106ce19fc78df895ae;hb=cf1ea9172b94fc17e45391b62bf4ca24ac5c5fe0;hp=0f04056a856b0c840134e633745ca17380984819;hpb=faf17bf83e36dccddf9fdcb84f60a06cac349339;p=netvirt.git diff --git a/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalNetworksChangeListener.java b/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalNetworksChangeListener.java index 0f04056a85..377db6a72d 100644 --- a/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalNetworksChangeListener.java +++ b/natservice/impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalNetworksChangeListener.java @@ -7,24 +7,26 @@ */ package org.opendaylight.netvirt.natservice.internal; -import com.google.common.base.Optional; -import java.math.BigInteger; +import static org.opendaylight.genius.infra.Datastore.CONFIGURATION; + import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.concurrent.ExecutionException; -import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import javax.inject.Inject; import javax.inject.Singleton; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase; +import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker; import org.opendaylight.genius.infra.ManagedNewTransactionRunner; import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl; import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.genius.mdsalutil.NwConstants; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; +import org.opendaylight.infrautils.utils.concurrent.Executors; +import org.opendaylight.mdsal.binding.api.DataBroker; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener; 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.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.config.rev170206.NatserviceConfig; @@ -39,12 +41,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Singleton -public class ExternalNetworksChangeListener - extends AsyncDataTreeChangeListenerBase { +public class ExternalNetworksChangeListener extends AbstractAsyncDataTreeChangeListener { private static final Logger LOG = LoggerFactory.getLogger(ExternalNetworksChangeListener.class); private final DataBroker dataBroker; private final ManagedNewTransactionRunner txRunner; @@ -60,7 +63,9 @@ public class ExternalNetworksChangeListener final OdlInterfaceRpcService interfaceManager, final NatserviceConfig config, final JobCoordinator coordinator) { - super(Networks.class, ExternalNetworksChangeListener.class); + super(dataBroker, LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(ExternalNetworks.class) + .child(Networks.class), + Executors.newListeningSingleThreadExecutor("ExternalNetworksChangeListener", LOG)); this.dataBroker = dataBroker; this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker); this.floatingIpListener = floatingIpListener; @@ -74,31 +79,26 @@ public class ExternalNetworksChangeListener } } - @Override - @PostConstruct public void init() { LOG.info("{} init", getClass().getSimpleName()); - registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker); } @Override - protected InstanceIdentifier getWildCardPath() { - return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class); + @PreDestroy + public void close() { + super.close(); + Executors.shutdownAndAwaitTermination(getExecutorService()); } @Override - protected void add(InstanceIdentifier identifier, Networks networks) { + public void add(InstanceIdentifier identifier, Networks networks) { } @Override - protected ExternalNetworksChangeListener getDataTreeChangeListener() { - return ExternalNetworksChangeListener.this; - } - - @Override - protected void remove(InstanceIdentifier identifier, Networks networks) { - if (identifier == null || networks == null || networks.getRouterIds().isEmpty()) { + public void remove(InstanceIdentifier identifier, Networks networks) { + if (identifier == null || networks == null || networks.getRouterIds() == null + || networks.getRouterIds().isEmpty()) { LOG.warn("remove : returning without processing since networks/identifier is null: " + "identifier: {}, networks: {}", identifier, networks); return; @@ -117,179 +117,205 @@ public class ExternalNetworksChangeListener } @Override - protected void update(InstanceIdentifier identifier, Networks original, Networks update) { + public void update(InstanceIdentifier identifier, Networks original, Networks update) { //Check for VPN disassociation Uuid originalVpn = original.getVpnid(); Uuid updatedVpn = update.getVpnid(); - coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + update.getKey(), - () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> { - if (originalVpn == null && updatedVpn != null) { - //external network is dis-associated from L3VPN instance - associateExternalNetworkWithVPN(update, tx); - } else if (originalVpn != null && updatedVpn == null) { - //external network is associated with vpn - disassociateExternalNetworkFromVPN(update, originalVpn.getValue()); - //Remove the SNAT entries - removeSnatEntries(original, original.getId(), tx); - } - })), NatConstants.NAT_DJC_MAX_RETRIES); + if (originalVpn == null && updatedVpn != null) { + //external network is dis-associated from L3VPN instance + associateExternalNetworkWithVPN(update); + } 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 removeSnatEntries(Networks original, Uuid networkUuid, WriteTransaction writeFlowInvTx) { - List routerUuids = original.getRouterIds(); - for (Uuid routerUuid : routerUuids) { - Long routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue()); - if (routerId == NatConstants.INVALID_ID) { - LOG.error("removeSnatEntries : Invalid routerId returned for routerName {}", routerUuid.getValue()); - return; - } - Collection externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId); - if (natMode == NatMode.Controller) { - externalRouterListener.handleDisableSnatInternetVpn(routerUuid.getValue(), routerId, networkUuid, - externalIps, original.getVpnid().getValue(), writeFlowInvTx); + private void removeSnatEntries(Networks original, Uuid networkUuid) { + if (original.getRouterIds() != null) { + for (Uuid routerUuid : original.getRouterIds()) { + Uint32 routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue()); + if (routerId == NatConstants.INVALID_ID) { + LOG.error("removeSnatEntries : Invalid routerId returned for routerName {}", routerUuid.getValue()); + return; + } + Collection externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId); + if (natMode == NatMode.Controller) { + coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routerUuid.getValue(), + () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, + tx -> externalRouterListener.handleDisableSnatInternetVpn(routerUuid.getValue(), routerId, + networkUuid, externalIps, original.getVpnid().getValue(), tx))), + NatConstants.NAT_DJC_MAX_RETRIES); + } } } } - private void associateExternalNetworkWithVPN(Networks network, WriteTransaction writeFlowInvTx) { - List routerIds = network.getRouterIds(); - for (Uuid routerId : routerIds) { - //long router = NatUtil.getVpnId(dataBroker, routerId.getValue()); + private void associateExternalNetworkWithVPN(Networks network) { + if (network.getRouterIds() != null) { + List routerIds = network.getRouterIds(); + for (Uuid routerId : routerIds) { + //long router = NatUtil.getVpnId(dataBroker, routerId.getValue()); - InstanceIdentifier routerPortsId = NatUtil.getRouterPortsId(routerId.getValue()); - Optional optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, - routerPortsId); - if (!optRouterPorts.isPresent()) { - LOG.debug("associateExternalNetworkWithVPN : Could not read Router Ports data object with id: {} " + InstanceIdentifier routerPortsId = NatUtil.getRouterPortsId(routerId.getValue()); + Optional optRouterPorts = null; + try { + optRouterPorts = SingleTransactionDataBroker.syncReadOptional(dataBroker, + LogicalDatastoreType.CONFIGURATION, routerPortsId); + } catch (ExecutionException | InterruptedException e) { + LOG.error("associateExternalNetworkWithVPN: Exception while reading RouterPorts DS for the " + + "router {} network {} ", routerId, network.getId().getValue(), e); + continue; + } + if (!optRouterPorts.isPresent()) { + LOG.debug("associateExternalNetworkWithVPN : Could not read Router Ports data object with id: {} " + "to handle associate ext nw {}", routerId, network.getId()); - continue; - } - RouterPorts routerPorts = optRouterPorts.get(); - List interfaces = routerPorts.getPorts(); - for (Ports port : interfaces) { - String portName = port.getPortName(); - BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName); - if (dpnId.equals(BigInteger.ZERO)) { - LOG.debug("associateExternalNetworkWithVPN : DPN not found for {}, " - + "skip handling of ext nw {} association", portName, network.getId()); continue; } - List intExtPortMapList = port.getInternalToExternalPortMap(); - for (InternalToExternalPortMap ipMap : intExtPortMapList) { - //remove all VPN related entries - floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), network.getId(), - ipMap, writeFlowInvTx); + RouterPorts routerPorts = optRouterPorts.get(); + for (Ports port : routerPorts.nonnullPorts().values()) { + String portName = port.getPortName(); + Uint64 dpnId = NatUtil.getDpnForInterface(interfaceManager, portName); + if (dpnId.equals(Uint64.ZERO)) { + LOG.debug("associateExternalNetworkWithVPN : DPN not found for {}, " + + "skip handling of ext nw {} association", portName, network.getId()); + continue; + } + for (InternalToExternalPortMap ipMap : port.nonnullInternalToExternalPortMap().values()) { + // remove all VPN related entries + coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + ipMap.key(), + () -> Collections.singletonList( + txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, + tx -> floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), + network.getId(), ipMap, tx))), NatConstants.NAT_DJC_MAX_RETRIES); + } } } - } - // SNAT - for (Uuid routerId : routerIds) { - LOG.debug("associateExternalNetworkWithVPN() : for routerId {}", routerId); - Uuid networkId = network.getId(); - if (networkId == null) { - LOG.error("associateExternalNetworkWithVPN : networkId is null for the router ID {}", routerId); - return; - } - final String vpnName = network.getVpnid().getValue(); - if (vpnName == null) { - LOG.error("associateExternalNetworkWithVPN : No VPN associated with ext nw {} for router {}", + // SNAT + for (Uuid routerId : routerIds) { + LOG.debug("associateExternalNetworkWithVPN() : for routerId {}", routerId); + Uuid networkId = network.getId(); + if (networkId == null) { + LOG.error("associateExternalNetworkWithVPN : networkId is null for the router ID {}", routerId); + return; + } + final String vpnName = network.getVpnid().getValue(); + if (vpnName == null) { + LOG.error("associateExternalNetworkWithVPN : No VPN associated with ext nw {} for router {}", networkId, routerId); - return; - } - - BigInteger dpnId = new BigInteger("0"); - InstanceIdentifier routerToNaptSwitch = - NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue()); - Optional rtrToNapt = - MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch); - if (rtrToNapt.isPresent()) { - dpnId = rtrToNapt.get().getPrimarySwitchId(); - } - LOG.debug("associateExternalNetworkWithVPN : got primarySwitch as dpnId{} ", dpnId); - if (dpnId == null || dpnId.equals(BigInteger.ZERO)) { - LOG.warn("associateExternalNetworkWithVPN : primary napt Switch not found for router {} on dpn: {}", - routerId, dpnId); - return; - } - - Long routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue()); - InstanceIdentifierBuilder idBuilder = - InstanceIdentifier.builder(IntextIpMap.class) - .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111 - .intext.ip.map.IpMapping.class, - new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111 - .intext.ip.map.IpMappingKey(routerIdentifier)); - InstanceIdentifier id = idBuilder.build(); - Optional ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id); - if (ipMapping.isPresent()) { - List ipMaps = ipMapping.get().getIpMap(); - for (IpMap ipMap : ipMaps) { - String externalIp = ipMap.getExternalIp(); - LOG.debug("associateExternalNetworkWithVPN : Calling advToBgpAndInstallFibAndTsFlows for dpnId {}," - + "vpnName {} and externalIp {}", dpnId, vpnName, externalIp); - if (natMode == NatMode.Controller) { - externalRouterListener.advToBgpAndInstallFibAndTsFlows(dpnId, NwConstants.INBOUND_NAPT_TABLE, - vpnName, routerIdentifier, routerId.getValue(), - externalIp, network.getId(), null /* external-router */, - writeFlowInvTx); - } + return; } - } else { - LOG.warn("associateExternalNetworkWithVPN : No ipMapping present fot the routerId {}", routerId); - } - long vpnId = NatUtil.getVpnId(dataBroker, vpnName); - // Install 47 entry to point to 21 - if (natMode == NatMode.Controller) { - externalRouterListener.installNaptPfibEntriesForExternalSubnets(routerId.getValue(), dpnId, - writeFlowInvTx); - if (vpnId != -1) { - LOG.debug("associateExternalNetworkWithVPN : Calling externalRouterListener installNaptPfibEntry " - + "for dpnId {} and vpnId {}", dpnId, vpnId); - externalRouterListener.installNaptPfibEntry(dpnId, vpnId, writeFlowInvTx); + Uint64 dpnId = Uint64.valueOf("0"); + InstanceIdentifier routerToNaptSwitch = + NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue()); + Optional rtrToNapt = Optional.empty(); + try { + rtrToNapt = SingleTransactionDataBroker.syncReadOptional(dataBroker, + LogicalDatastoreType.CONFIGURATION, routerToNaptSwitch); + } catch (ExecutionException | InterruptedException e) { + LOG.error("associateExternalNetworkWithVPN: Exception while reading routerToNaptSwitch DS for the " + + "router {}", routerId, e); + } + if (rtrToNapt.isPresent()) { + dpnId = rtrToNapt.get().getPrimarySwitchId(); + } + LOG.debug("associateExternalNetworkWithVPN : got primarySwitch as dpnId{} ", dpnId); + if (dpnId == null || dpnId.equals(Uint64.ZERO)) { + LOG.warn("associateExternalNetworkWithVPN : primary napt Switch not found for router {} on dpn: {}", + routerId, dpnId); + return; } + final Uint64 finalDpnId = dpnId; + coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + routerId.getValue(), + () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, + confTx -> { + Uint32 routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue()); + InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(IntextIpMap.class) + .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111 + .intext.ip.map.IpMapping.class, + new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111 + .intext.ip.map.IpMappingKey(routerIdentifier)); + InstanceIdentifier id = idBuilder.build(); + Optional ipMapping = MDSALUtil.read(dataBroker, + LogicalDatastoreType.OPERATIONAL, id); + if (ipMapping.isPresent()) { + for (IpMap ipMap : ipMapping.get().nonnullIpMap().values()) { + String externalIp = ipMap.getExternalIp(); + LOG.debug( + "associateExternalNetworkWithVPN : Calling advToBgpAndInstallFibAndTsFlows " + + "for dpnId {},vpnName {} and externalIp {}", finalDpnId, vpnName, + externalIp); + if (natMode == NatMode.Controller) { + externalRouterListener.advToBgpAndInstallFibAndTsFlows(finalDpnId, + NwConstants.INBOUND_NAPT_TABLE, vpnName, routerIdentifier, + routerId.getValue(), externalIp, network.getId(), + null /* external-router */, confTx); + } + } + } else { + LOG.warn("associateExternalNetworkWithVPN: No ipMapping present fot the routerId {}", + routerId); + } + + Uint32 vpnId = NatUtil.getVpnId(dataBroker, vpnName); + // Install 47 entry to point to 21 + if (natMode == NatMode.Controller) { + externalRouterListener.installNaptPfibEntriesForExternalSubnets(routerId.getValue(), + finalDpnId, confTx); + if (vpnId.longValue() != -1) { + LOG.debug("associateExternalNetworkWithVPN : Calling externalRouterListener " + + "installNaptPfibEntry for dpnId {} and vpnId {}", finalDpnId, vpnId); + externalRouterListener.installNaptPfibEntry(finalDpnId, vpnId, confTx); + } + } + })), NatConstants.NAT_DJC_MAX_RETRIES); } } - } private void disassociateExternalNetworkFromVPN(Networks network, String vpnName) { - List routerIds = network.getRouterIds(); - - for (Uuid routerId : routerIds) { - InstanceIdentifier routerPortsId = NatUtil.getRouterPortsId(routerId.getValue()); - Optional optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, - routerPortsId); - if (!optRouterPorts.isPresent()) { - LOG.debug("disassociateExternalNetworkFromVPN : Could not read Router Ports data object with id: {} " - + "to handle disassociate ext nw {}", routerId, network.getId()); - continue; - } - RouterPorts routerPorts = optRouterPorts.get(); - List interfaces = routerPorts.getPorts(); - try { - txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> { - for (Ports port : interfaces) { - String portName = port.getPortName(); - BigInteger dpnId = NatUtil.getDpnForInterface(interfaceManager, portName); - if (dpnId.equals(BigInteger.ZERO)) { - LOG.debug("disassociateExternalNetworkFromVPN : DPN not found for {}," - + "skip handling of ext nw {} disassociation", portName, network.getId()); - continue; - } - List intExtPortMapList = port.getInternalToExternalPortMap(); - for (InternalToExternalPortMap intExtPortMap : intExtPortMapList) { - floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(), - intExtPortMap, tx); - } + if (network.getRouterIds() != null) { + for (Uuid routerId : network.getRouterIds()) { + InstanceIdentifier routerPortsId = NatUtil.getRouterPortsId(routerId.getValue()); + Optional optRouterPorts = Optional.empty(); + try { + optRouterPorts = SingleTransactionDataBroker.syncReadOptional(dataBroker, + LogicalDatastoreType.CONFIGURATION, routerPortsId); + } catch (ExecutionException | InterruptedException e) { + LOG.error("disassociateExternalNetworkFromVPN: Exception while reading RouterPorts DS for the " + + "router {} network {} vpn {}", routerId, network.getId().getValue(), vpnName, e); + } + if (!optRouterPorts.isPresent()) { + LOG.debug( + "disassociateExternalNetworkFromVPN : Could not read Router Ports data object with id: {} " + + "to handle disassociate ext nw {}", routerId, network.getId()); + continue; + } + RouterPorts routerPorts = optRouterPorts.get(); + for (Ports port : routerPorts.nonnullPorts().values()) { + String portName = port.getPortName(); + Uint64 dpnId = NatUtil.getDpnForInterface(interfaceManager, portName); + if (dpnId.equals(Uint64.ZERO)) { + LOG.debug("disassociateExternalNetworkFromVPN : DPN not found for {}," + + "skip handling of ext nw {} disassociation", portName, network.getId()); + continue; } - }).get(); - } catch (ExecutionException | InterruptedException e) { - LOG.error("Error writing to datastore {}", e); + for (InternalToExternalPortMap intExtPortMap : port.nonnullInternalToExternalPortMap().values()) { + coordinator.enqueueJob(NatConstants.NAT_DJC_PREFIX + intExtPortMap.key(), + () -> Collections.singletonList( + txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, + tx -> floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, + routerId.getValue(), + intExtPortMap, tx))), NatConstants.NAT_DJC_MAX_RETRIES); + } + } } } }