<dluxapps.version>0.5.0-SNAPSHOT</dluxapps.version>
<mdsal.version>1.5.0-SNAPSHOT</mdsal.version>
<mdsal.model.version>0.10.0-SNAPSHOT</mdsal.model.version>
+ <netconf.version>1.2.0-SNAPSHOT</netconf.version>
<neutron.version>0.8.0-SNAPSHOT</neutron.version>
<restconf.version>1.5.0-SNAPSHOT</restconf.version>
+ <vbd.version>1.1.0-SNAPSHOT</vbd.version>
</properties>
<dependencyManagement>
<type>pom</type>
<scope>import</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.honeycomb.vbd</groupId>
+ <artifactId>vbd-artifacts</artifactId>
+ <version>${vbd.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
<type>xml</type>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>features-netconf-connector</artifactId>
+ <version>${netconf.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>org.opendaylight.dlux</groupId>
<artifactId>features-dlux</artifactId>
<classifier>features</classifier>
<type>xml</type>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.honeycomb.vbd</groupId>
+ <artifactId>vbd-features</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
</dependencies>
<!--
<repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
<!-- Needed for odl-restconf -->
<repository>mvn:org.opendaylight.netconf/features-restconf/{{VERSION}}/xml/features</repository>
+ <!-- Needed by neutron intent handler -->
+ <repository>mvn:org.opendaylight.honeycomb.vbd/vbd-features/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.netconf/features-netconf-connector/{{VERSION}}/xml/features</repository>
<feature name="odl-lispflowmapping-msmr" description="OpenDaylight :: LISP Flow Mapping :: Map-Server/Map-Resolver" version='${project.version}'>
<feature version="${project.version}">odl-lispflowmapping-mappingservice</feature>
<feature name="odl-lispflowmapping-neutron" description="OpenDaylight :: LISP Flow Mapping :: Neutron Integration" version='${project.version}'>
<feature version="${neutron.version}">odl-neutron-service</feature>
<feature version="${project.version}">odl-lispflowmapping-mappingservice</feature>
+ <feature version="${vbd.version}">odl-vbd</feature>
+ <feature version='${netconf.version}'>odl-netconf-clustered-topology</feature>
<bundle>mvn:org.opendaylight.lispflowmapping/mappingservice.neutron/{{VERSION}}</bundle>
</feature>
<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.honeycomb.vbd</groupId>
+ <artifactId>odl-vbd</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>odl-netconf-tcp</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>odl-netconf-clustered-topology</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>odl-lispflowmapping-mappingservice</artifactId>
build failure. Please do not modify this unless you have a good reason. -->
<name>ODL :: lispflowmapping :: ${project.artifactId}</name>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>netconf-artifacts</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>mdsal-artifacts</artifactId>
+ <version>1.5.0-SNAPSHOT</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
<dependencies>
<dependency>
<groupId>org.opendaylight.lispflowmapping</groupId>
<groupId>org.opendaylight.lispflowmapping</groupId>
<artifactId>common.unittest.tools</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.honeycomb.vbd</groupId>
+ <artifactId>vbd-api</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>sal-netconf-connector</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-singleton-common-api</artifactId>
+ <version>2.2.0-SNAPSHOT</version>
+ </dependency>
</dependencies>
<!--
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.lispflowmapping.neutron.intenthandler.listener.service.VbridgeTopologyListenerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 1/19/17.
+ */
+
+/*
+ * This is the bean instantiated when lisp neutron service is installed. This bean
+ * registers and maintain listeners for getting updates of Neutron Topology
+ * maintained by groupbasedpolicy and honeycomb vbd.
+ */
+public class GroupBasedPolicyNeutronIntentHandlerBean implements AutoCloseable, BindingAwareProvider {
+ private static final Logger LOG = LoggerFactory.getLogger(GroupBasedPolicyNeutronIntentHandlerBean.class);
+
+ private DataBroker dataBroker;
+ private MountPointService mountService;
+
+ private VbridgeTopologyListenerService vbridgeTopologyListenerService;
+
+ private IntentHandlerAsyncExecutorProvider intentHandlerAsyncExecutorProvider =
+ IntentHandlerAsyncExecutorProvider.getInstace();
+
+ public GroupBasedPolicyNeutronIntentHandlerBean(final BindingAwareBroker bindingAwareBroker) {
+ bindingAwareBroker.registerProvider(this);
+ }
+
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("Clustering provider closed for {}", this.getClass().getSimpleName());
+ intentHandlerAsyncExecutorProvider.close();
+ }
+
+ @Override
+ public void onSessionInitiated(BindingAwareBroker.ProviderContext session) {
+ LOG.info("LFM neutron handler service registered", this.getClass().getSimpleName());
+ dataBroker = session.getSALService(DataBroker.class);
+ mountService = session.getSALService(MountPointService.class);
+ vbridgeTopologyListenerService = VbridgeTopologyListenerService.initialize(dataBroker, mountService);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+
+import java.util.concurrent.Executors;
+
+/**
+ * Created by Shakib Ahmed on 1/24/17.
+ */
+public class IntentHandlerAsyncExecutorProvider {
+ private static ListeningExecutorService listeningExecutorService;
+
+ private static final int EXTRA_THREADS_TO_HANDLE_VPP_LISTENER = 1;
+
+ private static IntentHandlerAsyncExecutorProvider intentHandlerAsyncExecutorProvider;
+
+ private IntentHandlerAsyncExecutorProvider() {
+ listeningExecutorService = MoreExecutors
+ .listeningDecorator(Executors.newFixedThreadPool(EXTRA_THREADS_TO_HANDLE_VPP_LISTENER));
+ }
+
+ public static synchronized IntentHandlerAsyncExecutorProvider getInstace() {
+ if (intentHandlerAsyncExecutorProvider == null) {
+ intentHandlerAsyncExecutorProvider = new IntentHandlerAsyncExecutorProvider();
+ }
+ return intentHandlerAsyncExecutorProvider;
+ }
+
+ public synchronized ListeningExecutorService getExecutor() {
+ return listeningExecutorService;
+ }
+
+ public void close() {
+ listeningExecutorService.shutdown();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.exception;
+
+/**
+ * Created by Shakib Ahmed on 1/12/17.
+ */
+public class RlocNotFoundOnVppNode extends RuntimeException {
+ public RlocNotFoundOnVppNode(String hostId) {
+ super("No available interface found on node " + hostId);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.listener;
+
+import com.google.common.base.Preconditions;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.topology.types.VbridgeTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 1/19/17.
+ */
+public class VbridgeTopologyListener implements ClusteredDataTreeChangeListener<VbridgeTopology>, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(VbridgeTopologyListener.class);
+
+ private DataBroker dataBroker;
+ private MountPointService mountPointService;
+
+ @GuardedBy("this")
+ private final Map<TopologyKey, VppEndpointListener> domains = new ConcurrentHashMap<>();
+
+ public VbridgeTopologyListener(final DataBroker dataBroker,
+ final MountPointService mountPointService) {
+ this.dataBroker = Preconditions.checkNotNull(dataBroker);
+ this.mountPointService = Preconditions.checkNotNull(mountPointService);
+ }
+
+ @Override
+ public synchronized void onDataTreeChanged(@Nonnull Collection<DataTreeModification<VbridgeTopology>> changes) {
+ for (DataTreeModification<VbridgeTopology> topologyData : changes) {
+ final KeyedInstanceIdentifier<Topology, TopologyKey> topologyInstanceIdentifier =
+ (KeyedInstanceIdentifier<Topology, TopologyKey>) topologyData
+ .getRootPath()
+ .getRootIdentifier()
+ .firstIdentifierOf(Topology.class);
+
+ Preconditions.checkArgument(!topologyInstanceIdentifier
+ .isWildcarded(), "Wildcard topology %s is not supported",
+ topologyInstanceIdentifier);
+
+ final DataObjectModification<VbridgeTopology> modification = topologyData.getRootNode();
+
+ switch (modification.getModificationType()) {
+ case DELETE:
+ handleVbridgeTopologyDelete(topologyInstanceIdentifier);
+ break;
+ case WRITE:
+ handleVbridgeTopologyWrite(topologyInstanceIdentifier);
+ break;
+ default:
+ LOG.warn("Ignoring unhandled modification type {}", modification.getModificationType());
+ break;
+
+ }
+ }
+ }
+
+ private void handleVbridgeTopologyDelete(KeyedInstanceIdentifier<Topology, TopologyKey> topology) {
+ VppEndpointListener endpointListener = domains.get(topology.getKey());
+ endpointListener.close();
+ domains.remove(topology.getKey());
+ }
+
+ private void handleVbridgeTopologyWrite(KeyedInstanceIdentifier<Topology, TopologyKey> topology) {
+ if (domains.containsKey(topology.getKey())) {
+ domains.get(topology.getKey()).close();
+ domains.remove(topology.getKey());
+ }
+ domains.put(topology.getKey(), new VppEndpointListener(dataBroker, mountPointService, topology));
+ }
+
+ @Override
+ public void close() {
+ domains.forEach((topologyKey, vppEndpointListener) -> {
+ vppEndpointListener.close();
+ });
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.listener;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
+import org.opendaylight.lispflowmapping.neutron.intenthandler.IntentHandlerAsyncExecutorProvider;
+import org.opendaylight.lispflowmapping.neutron.intenthandler.util.VppNetconfConnectionProbe;
+import org.opendaylight.lispflowmapping.neutron.intenthandler.util.VppNodeReader;
+import org.opendaylight.lispflowmapping.neutron.mappingmanager.HostIdToRlocMapper;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNode;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 1/11/17.
+ */
+public class VppEndpointListener implements AutoCloseable, ClusteredDataTreeChangeListener<Topology> {
+ private static final Logger LOG = LoggerFactory.getLogger(VppEndpointListener.class);
+
+ private final DataBroker dataBroker;
+ private final MountPointService mountService;
+ private final ListenerRegistration<?> reg;
+
+ private final VppNodeReader vppNodeReader;
+ private final HostIdToRlocMapper hostIdToRlocMapper;
+
+ private final Multimap<NodeId, KeyedInstanceIdentifier<Node, NodeKey>> nodeIdToKeyedInstanceIdentifierMap =
+ ArrayListMultimap.create();
+
+ private final ListeningExecutorService executorService;
+
+ public VppEndpointListener(final DataBroker dataBroker,
+ final MountPointService mountPointService,
+ KeyedInstanceIdentifier<Topology, TopologyKey> topologyII) {
+
+ this.dataBroker = dataBroker;
+ this.mountService = mountPointService;
+
+ vppNodeReader = new VppNodeReader(this.dataBroker, this.mountService);
+
+ hostIdToRlocMapper = HostIdToRlocMapper.getInstance();
+
+ reg = dataBroker.registerDataTreeChangeListener(
+ new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, topologyII), this);
+
+ executorService = IntentHandlerAsyncExecutorProvider.getInstace().getExecutor();
+ }
+
+ @Override
+ public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Topology>> changes) {
+ for (DataTreeModification<Topology> change : changes) {
+ final DataObjectModification<Topology> modification = change.getRootNode();
+ ListenableFuture<Void> modificationTaskHandler;
+ switch (modification.getModificationType()) {
+ case WRITE:
+ modificationTaskHandler = handleChange(modification);
+ break;
+ case SUBTREE_MODIFIED:
+ modificationTaskHandler = handleChange(modification);
+ break;
+ case DELETE:
+ modificationTaskHandler = handleDeleteOnTopology();
+ break;
+ default:
+ LOG.warn("Ignored topology modification {}", modification);
+ modificationTaskHandler = Futures.immediateFuture(null);
+ break;
+ }
+ Futures.addCallback(modificationTaskHandler, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(@Nullable Void vd) {
+ LOG.debug("VppEndpoint modification handled successfully!");
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.debug("Failed to handle VppEndpoint modifications!");
+ }
+ });
+ }
+ }
+
+ private ListenableFuture<Void> handleChange(DataObjectModification modification) {
+ Collection<DataObjectModification<? extends DataObject>> modifiedChildren = modification.getModifiedChildren();
+ List<ListenableFuture<KeyedInstanceIdentifier<Node, NodeKey>>> processingTasks = new ArrayList<>();
+ for (DataObjectModification modifiedNode : modifiedChildren) {
+ final Node newOrModifiedNode = (Node) modifiedNode.getDataAfter();
+ ListenableFuture<KeyedInstanceIdentifier<Node, NodeKey>> processingTask = processNode(newOrModifiedNode);
+ Futures.addCallback(processingTask, new FutureCallback<KeyedInstanceIdentifier<Node, NodeKey>>() {
+ @Override
+ public void onSuccess(@Nullable KeyedInstanceIdentifier<Node, NodeKey> kiiToNode) {
+ hostIdToRlocMapper.addMapping(newOrModifiedNode.getNodeId().getValue(),
+ LispAddressUtil.toRloc(vppNodeReader.rlocIpOfNode(kiiToNode)));
+ }
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.debug("Couldn't process {}", newOrModifiedNode.getNodeId().getValue());
+ }
+ });
+ processingTasks.add(processNode(newOrModifiedNode));
+ }
+ return Futures.immediateFuture(null);
+ }
+
+ private ListenableFuture<KeyedInstanceIdentifier<Node, NodeKey>> processNode(final Node newOrModifiedNode) {
+ ListenableFuture<Void> probeVppNodeForConnection = executorService
+ .submit(() -> {
+ processNodeOnConnection(newOrModifiedNode);
+ return null;
+ });
+
+ return Futures.transform(probeVppNodeForConnection,
+ new Function<Void, KeyedInstanceIdentifier<Node, NodeKey>>() {
+ @Nullable
+ @Override
+ public KeyedInstanceIdentifier<Node, NodeKey> apply(@Nullable Void vd) {
+ return nodeIdToKeyedInstanceIdentifierMap.get(newOrModifiedNode.getNodeId()).iterator().next();
+ }
+ });
+ }
+
+ private void processNodeOnConnection(final Node newOrModifiedNode) {
+ for (SupportingNode supportingNode : newOrModifiedNode.getSupportingNode()) {
+ final NodeId nodeMount = supportingNode.getNodeRef();
+ final VppNetconfConnectionProbe probe = new VppNetconfConnectionProbe(supportingNode.getNodeRef(),
+ dataBroker);
+
+ try {
+ // Verify netconf connection
+ boolean connectionReady = probe.startProbing();
+ if (connectionReady) {
+ LOG.debug("Node {} is connected, creating ...", supportingNode.getNodeRef());
+ final TopologyId topologyMount = supportingNode.getTopologyRef();
+ final KeyedInstanceIdentifier<Node, NodeKey> iiToVpp =
+ InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(topologyMount))
+ .child(Node.class, new NodeKey(nodeMount));
+ nodeIdToKeyedInstanceIdentifierMap.put(newOrModifiedNode.getNodeId(), iiToVpp);
+ } else {
+ LOG.debug("Failed while connecting to node {}", supportingNode.getNodeRef());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception while processing node {} ... ", supportingNode.getNodeRef(), e);
+ } catch (TimeoutException e) {
+ LOG.warn("Node {} was not connected within {} seconds. "
+ + "Check node configuration and connectivity to proceed",
+ supportingNode.getNodeRef(), VppNetconfConnectionProbe.NODE_CONNECTION_TIMER);
+ }
+ }
+ }
+
+ private ListenableFuture<Void> handleDeleteOnTopology() {
+ //TODO
+ return Futures.immediateFuture(null);
+ }
+
+ @Override
+ public void close() {
+ reg.close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.listener.service;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.lispflowmapping.neutron.intenthandler.listener.VbridgeTopologyListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyTypesVbridgeAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.network.topology.topology.topology.types.VbridgeTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 1/19/17.
+ */
+public class VbridgeTopologyListenerService implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(VbridgeTopologyListenerService.class);
+
+ private final ListenerRegistration<VbridgeTopologyListener> listenerRegistration;
+
+ private boolean closed;
+
+ private static final DataTreeIdentifier<VbridgeTopology> TREE_LISTENER_IDENTIFIER =
+ new DataTreeIdentifier<>(
+ LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class)
+ .child(TopologyTypes.class)
+ .augmentation(TopologyTypesVbridgeAugment.class)
+ .child(VbridgeTopology.class).build());
+
+ public VbridgeTopologyListenerService(final ListenerRegistration<VbridgeTopologyListener> reg) {
+ this.listenerRegistration = reg;
+ this.closed = false;
+ }
+
+ public static VbridgeTopologyListenerService initialize(@Nonnull final DataBroker dataBroker,
+ @Nonnull final MountPointService mountPointService) {
+ final ListenerRegistration<VbridgeTopologyListener> reg =
+ dataBroker.registerDataTreeChangeListener(TREE_LISTENER_IDENTIFIER,
+ new VbridgeTopologyListener(dataBroker, mountPointService));
+
+ return new VbridgeTopologyListenerService(reg);
+ }
+
+
+ @Override
+ public void close() {
+ if (!closed) {
+
+ final VbridgeTopologyListener listener = listenerRegistration.getInstance();
+
+ listenerRegistration.close();
+ listener.close();
+
+ closed = true;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.util;
+
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Created by Shakib Ahmed on 1/23/17.
+ */
+public class InfoUtil {
+
+ private InfoUtil() {
+
+ }
+
+ public static String topology(final KeyedInstanceIdentifier<Topology, TopologyKey> topoIID) {
+ return topoIID.getKey().getTopologyId().getValue();
+ }
+
+ public static String topology(final Topology topology) {
+ return topology.getKey().getTopologyId().getValue();
+ }
+
+ public static String node(final KeyedInstanceIdentifier<Node, NodeKey> nodeIID) {
+ return nodeIID.getKey().getNodeId().getValue();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.util;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPoint;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 1/12/17.
+ */
+public class LispNeutronUtil {
+ protected static final Logger LOG = LoggerFactory.getLogger(LispNeutronUtil.class);
+
+ private LispNeutronUtil(){}
+
+ public static DataBroker resolveDataBrokerForMountPoint(InstanceIdentifier<Node> iiToMountPoint,
+ MountPointService mountService) {
+ final Optional<MountPoint> vppMountPointOpt = mountService.getMountPoint(iiToMountPoint);
+ if (vppMountPointOpt.isPresent()) {
+ final MountPoint vppMountPoint = vppMountPointOpt.get();
+ final Optional<DataBroker> dataBrokerOpt = vppMountPoint.getService(DataBroker.class);
+ if (dataBrokerOpt.isPresent()) {
+ return dataBrokerOpt.get();
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.util;
+
+/**
+ * Created by Shakib Ahmed on 1/23/17.
+ */
+
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connected;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connecting;
+
+
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Purpose: verify whether provided netconf node is already connected or wait if not.
+ *
+ * <p>
+ * VppNetconfConnectionProbe registers istener which catches node-related changes from topology-netconf.
+ * A {@link SettableFuture} is set {@link Boolean#TRUE}, if the node is connected within {@link
+ * VppNetconfConnectionProbe#NODE_CONNECTION_TIMER} seconds. Else, proper exception is throws.
+ * </p>
+ *
+ */
+public class VppNetconfConnectionProbe implements ClusteredDataTreeChangeListener<Node> {
+ private static final Logger LOG = LoggerFactory.getLogger(VppNodeReader.class);
+
+ public static final int NODE_CONNECTION_TIMER = 60;
+ private final DataBroker dataBroker;
+ private ListenerRegistration<VppNetconfConnectionProbe> registeredListener;
+ private SettableFuture<Boolean> connectionStatusFuture = SettableFuture.create();
+
+ private static final String TOPOLOGY_IDENTIFIER = "topology-netconf";
+
+ private final DataTreeIdentifier<Node> path;
+
+ public VppNetconfConnectionProbe(final NodeId nodeId, final DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ final InstanceIdentifier<Node> nodeIid = InstanceIdentifier.builder(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_IDENTIFIER)))
+ .child(Node.class, new NodeKey(nodeId))
+ .build();
+
+ path = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, nodeIid);
+ }
+
+ public boolean startProbing() throws ExecutionException, InterruptedException, TimeoutException {
+ registeredListener = dataBroker.registerDataTreeChangeListener(path, this);
+ return connectionStatusFuture.get(NODE_CONNECTION_TIMER, TimeUnit.SECONDS);
+ }
+
+ @Override
+ public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> changes) {
+ changes.forEach(modification -> {
+ final DataObjectModification<Node> rootNode = modification.getRootNode();
+ final Node node = rootNode.getDataAfter();
+ final NetconfNode netconfNode = getNodeAugmentation(node);
+ if (node == null || node.getNodeId() == null) {
+ return;
+ }
+ if (netconfNode == null || netconfNode.getConnectionStatus() == null) {
+ connectionStatusFuture.set(false);
+ unregister();
+ } else {
+ final NetconfNodeConnectionStatus.ConnectionStatus status = netconfNode.getConnectionStatus();
+ if (status.equals(Connected)) {
+ connectionStatusFuture.set(true);
+ unregister();
+ } else if (!status.equals(Connecting)) {
+ connectionStatusFuture.set(false);
+ unregister();
+ }
+ }
+ });
+ }
+
+ private NetconfNode getNodeAugmentation(Node node) {
+ NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
+ if (netconfNode == null) {
+ return null;
+ }
+ return netconfNode;
+ }
+
+ private void unregister() {
+ if (registeredListener != null) {
+ registeredListener.close();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.util;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 1/12/17.
+ */
+public class VppNetconfTrasaction {
+ private static final Logger LOG = LoggerFactory.getLogger(VppNetconfTrasaction.class);
+
+ public static final byte RETRY_COUNT = 5;
+
+ public static synchronized <T extends DataObject> Optional<T> read(DataBroker dataBroker,
+ LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> instanceIdentifier) {
+ LOG.trace("Started Netconf transaction on VPP Node");
+ Preconditions.checkNotNull(dataBroker);
+
+ Optional<T> returnData;
+
+ int retryCounter = RETRY_COUNT;
+
+ while (retryCounter > 0) {
+ ReadOnlyTransaction readTransaction = dataBroker.newReadOnlyTransaction();
+ try {
+ returnData = readTransaction(instanceIdentifier, datastoreType, readTransaction);
+ LOG.trace("Netconf READ transaction SUCCESSFUL. Data present: {}", returnData.isPresent());
+ readTransaction.close();
+ return returnData;
+ } catch (IllegalStateException e) {
+
+ LOG.warn("Assuming that netconf read-transaction failed, retrying. Retry Count: " + retryCounter,
+ e.getMessage());
+ readTransaction.close();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception while reading data. Retry Aborted.", e.getMessage());
+ readTransaction.close();
+ break;
+ }
+ retryCounter--;
+ }
+ return Optional.absent();
+ }
+
+ private static <T extends DataObject> Optional<T> readTransaction(InstanceIdentifier<T> instanceIdentifier,
+ LogicalDatastoreType datastoreType,
+ ReadOnlyTransaction readTransaction)
+ throws IllegalStateException, InterruptedException, ExecutionException {
+
+ CheckedFuture<Optional<T>, ReadFailedException> futureData =
+ readTransaction.read(datastoreType, instanceIdentifier);
+
+ return futureData.get();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.intenthandler.util;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.lispflowmapping.neutron.intenthandler.exception.RlocNotFoundOnVppNode;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces.state._interface.ipv4.Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.Loopback;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Created by Shakib Ahmed on 1/12/17.
+ */
+public class VppNodeReader {
+ private static final Logger LOG = LoggerFactory.getLogger(VppNodeReader.class);
+
+ private final DataBroker dataBroker;
+ private final MountPointService mountService;
+
+ public VppNodeReader(DataBroker dataBroker, MountPointService mountService) {
+ this.dataBroker = dataBroker;
+ this.mountService = mountService;
+ }
+
+ public Ipv4Address rlocIpOfNode(KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifierToVppNode) {
+ try {
+ Optional<Ipv4Address> ipv4AddressOptional =
+ readFirstAvailableIpOfVppNode(instanceIdentifierToVppNode).get();
+ if (!ipv4AddressOptional.isPresent()) {
+ throw new RlocNotFoundOnVppNode(InfoUtil.node(instanceIdentifierToVppNode));
+ }
+
+ return ipv4AddressOptional.get();
+ } catch (final InterruptedException | ExecutionException ex) {
+ LOG.warn("Got exception while reading IP addresses from nodes {}",
+ InfoUtil.node(instanceIdentifierToVppNode));
+ throw new RlocNotFoundOnVppNode(InfoUtil.node(instanceIdentifierToVppNode));
+ }
+ }
+
+ private ListenableFuture<Optional<Ipv4Address>>
+ readFirstAvailableIpOfVppNode(final KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifierToVppNode) {
+
+ final SettableFuture<Optional<Ipv4Address>> resultFuture = SettableFuture.create();
+
+ final DataBroker vppDataBroker = LispNeutronUtil.resolveDataBrokerForMountPoint(instanceIdentifierToVppNode,
+ mountService);
+ if (vppDataBroker != null) {
+ final Optional<InterfacesState> interfacesOnVppNodeOptional = VppNetconfTrasaction.read(vppDataBroker,
+ LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(InterfacesState.class));
+ if (interfacesOnVppNodeOptional.isPresent()) {
+
+ for (Interface intf : interfacesOnVppNodeOptional.get().getInterface()) {
+
+ if (intf.getType().equals(Loopback.class)) {
+ continue;
+ }
+
+ final Optional<Ipv4Address> ipv4AddressOptional = readIpAddressFromInterface(intf,
+ instanceIdentifierToVppNode);
+
+ if (ipv4AddressOptional.isPresent()) {
+ resultFuture.set(ipv4AddressOptional);
+ break;
+ }
+ }
+
+ }
+
+ resultFuture.set(Optional.absent());
+ } else {
+ LOG.debug("Data broker for vpp {} is missing.", instanceIdentifierToVppNode);
+ }
+ return resultFuture;
+ }
+
+ private Optional<Ipv4Address> readIpAddressFromInterface(Interface intf,
+ KeyedInstanceIdentifier iiToVpp) {
+ Interface2 augIntf = intf.getAugmentation(Interface2.class);
+
+ if (augIntf == null) {
+ LOG.debug("Cannot get Interface2 augmentation for intf {}");
+ return Optional.absent();
+ }
+
+ Ipv4 ipv4 = augIntf.getIpv4();
+
+ if (ipv4 == null) {
+ LOG.debug("Ipv4 address for interface {} on node {} is null!", augIntf, InfoUtil.node(iiToVpp));
+ return Optional.absent();
+ }
+
+ final List<Address> addresses = ipv4.getAddress();
+ if (addresses == null || addresses.isEmpty()) {
+ LOG.debug("Ipv4 addresses list is empty for interface {} on node {}", augIntf, InfoUtil.node(iiToVpp));
+ return Optional.absent();
+ }
+
+ final Ipv4AddressNoZone ip = addresses.iterator().next().getIp();
+ if (ip == null) {
+ LOG.debug("Ipv4AddressNoZone is null for node {}", InfoUtil.node(iiToVpp));
+ return Optional.absent();
+ }
+
+ LOG.debug("Got ip address {} from interface {} on node {}", ip.getValue(), intf.getName(),
+ InfoUtil.node(iiToVpp));
+ return Optional.of(ip);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc. 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.lispflowmapping.neutron.mappingmanager;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 1/12/17.
+ */
+public class HostIdToRlocMapper {
+ private static final Logger LOG = LoggerFactory.getLogger(HostIdToRlocMapper.class);
+
+ private ConcurrentHashMap<String, List<Rloc>> mapper;
+ private static HostIdToRlocMapper instance;
+
+ private HostIdToRlocMapper() {
+ mapper = new ConcurrentHashMap();
+ }
+
+ public static synchronized HostIdToRlocMapper getInstance() {
+ if (instance == null) {
+ instance = new HostIdToRlocMapper();
+ }
+ return instance;
+ }
+
+ public synchronized void addMapping(String hostId, Rloc hostRloc) {
+ List<Rloc> hostIdSpeceficRlocs = mapper.get(hostId);
+
+ if (hostIdSpeceficRlocs == null) {
+ hostIdSpeceficRlocs = new ArrayList<>();
+ }
+
+ hostIdSpeceficRlocs.add(hostRloc);
+ mapper.put(hostId, hostIdSpeceficRlocs);
+ LOG.debug("Adding " + hostRloc.getAddress() + " as Rloc of " + hostId);
+ }
+
+ public List<Rloc> getRlocs(String hostId) {
+ return mapper.get(hostId);
+ }
+
+ public synchronized void deleteMapping(String hostId) {
+ //for now, delete all rlocs
+ mapper.remove(hostId);
+ }
+}
\ No newline at end of file
<argument ref="mappingService" />
<argument ref="bindingAwareBroker"/>
</bean>
+ <bean id="lispNeutronIntent"
+ class="org.opendaylight.lispflowmapping.neutron.intenthandler.GroupBasedPolicyNeutronIntentHandlerBean"
+ destroy-method="close">
+ <argument ref="bindingAwareBroker"/>
+ </bean>
+
<service ref="lispNeutronPlugin"
interface="org.opendaylight.lispflowmapping.neutron.ILispNeutronService"
odl:type="default" />