2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netconf.topology.singleton.impl;
11 import akka.actor.ActorSystem;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import io.netty.util.concurrent.EventExecutor;
16 import java.util.Collection;
17 import java.util.HashMap;
19 import javax.annotation.Nonnull;
20 import org.opendaylight.controller.cluster.ActorSystemProvider;
21 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
22 import org.opendaylight.controller.config.threadpool.ThreadPool;
23 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
26 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
27 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
28 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
31 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
32 import org.opendaylight.controller.sal.core.api.Broker;
33 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
34 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
35 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
36 import org.opendaylight.netconf.client.NetconfClientDispatcher;
37 import org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService;
38 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
39 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup.NetconfTopologySetupBuilder;
40 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
50 import org.opendaylight.yangtools.concepts.ListenerRegistration;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 public class NetconfTopologyManager
56 implements ClusteredDataTreeChangeListener<Node>, NetconfTopologySingletonService, AutoCloseable {
58 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyManager.class);
60 private final Map<InstanceIdentifier<Node>, NetconfTopologyContext> contexts = new HashMap<>();
61 private final Map<InstanceIdentifier<Node>, ClusterSingletonServiceRegistration>
62 clusterRegistrations = new HashMap<>();
64 private ListenerRegistration<NetconfTopologyManager> dataChangeListenerRegistration;
66 private final DataBroker dataBroker;
67 private final RpcProviderRegistry rpcProviderRegistry;
68 private final ClusterSingletonServiceProvider clusterSingletonServiceProvider;
69 private final BindingAwareBroker bindingAwareBroker;
70 private final ScheduledThreadPool keepaliveExecutor;
71 private final ThreadPool processingExecutor;
72 private final Broker domBroker;
73 private final ActorSystem actorSystem;
74 private final EventExecutor eventExecutor;
75 private final NetconfClientDispatcher clientDispatcher;
76 private final String topologyId;
78 public NetconfTopologyManager(final DataBroker dataBroker, final RpcProviderRegistry rpcProviderRegistry,
79 final ClusterSingletonServiceProvider clusterSingletonServiceProvider,
80 final BindingAwareBroker bindingAwareBroker,
81 final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
82 final Broker domBroker, final ActorSystemProvider actorSystemProvider, final EventExecutor eventExecutor,
83 final NetconfClientDispatcher clientDispatcher, final String topologyId) {
84 this.dataBroker = Preconditions.checkNotNull(dataBroker);
85 this.rpcProviderRegistry = Preconditions.checkNotNull(rpcProviderRegistry);
86 this.clusterSingletonServiceProvider = Preconditions.checkNotNull(clusterSingletonServiceProvider);
87 this.bindingAwareBroker = Preconditions.checkNotNull(bindingAwareBroker);
88 this.keepaliveExecutor = Preconditions.checkNotNull(keepaliveExecutor);
89 this.processingExecutor = Preconditions.checkNotNull(processingExecutor);
90 this.domBroker = Preconditions.checkNotNull(domBroker);
91 this.actorSystem = Preconditions.checkNotNull(actorSystemProvider).getActorSystem();
92 this.eventExecutor = Preconditions.checkNotNull(eventExecutor);
93 this.clientDispatcher = Preconditions.checkNotNull(clientDispatcher);
94 this.topologyId = Preconditions.checkNotNull(topologyId);
97 // Blueprint init method
99 dataChangeListenerRegistration = registerDataTreeChangeListener(topologyId);
103 public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<Node>> changes) {
104 for (DataTreeModification<Node> change : changes) {
105 final DataObjectModification<Node> rootNode = change.getRootNode();
106 final InstanceIdentifier<Node> dataModifIdent = change.getRootPath().getRootIdentifier();
107 final NodeId nodeId = NetconfTopologyUtils.getNodeId(rootNode.getIdentifier());
108 switch (rootNode.getModificationType()) {
109 case SUBTREE_MODIFIED:
110 LOG.debug("Config for node {} updated", nodeId);
111 refreshNetconfDeviceContext(dataModifIdent, rootNode.getDataAfter());
114 if (contexts.containsKey(dataModifIdent)) {
115 LOG.debug("RemoteDevice{{}} was already configured, reconfiguring node...", nodeId);
116 refreshNetconfDeviceContext(dataModifIdent, rootNode.getDataAfter());
118 LOG.debug("Config for node {} created", nodeId);
119 startNetconfDeviceContext(dataModifIdent, rootNode.getDataAfter());
123 LOG.debug("Config for node {} deleted", nodeId);
124 stopNetconfDeviceContext(dataModifIdent);
127 LOG.warn("Unknown operation for {}.", nodeId);
132 private void refreshNetconfDeviceContext(InstanceIdentifier<Node> instanceIdentifier, Node node) {
133 final NetconfTopologyContext context = contexts.get(instanceIdentifier);
134 context.refresh(createSetup(instanceIdentifier, node));
137 private void startNetconfDeviceContext(final InstanceIdentifier<Node> instanceIdentifier, final Node node) {
138 final NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
139 Preconditions.checkNotNull(netconfNode);
140 Preconditions.checkNotNull(netconfNode.getHost());
141 Preconditions.checkNotNull(netconfNode.getHost().getIpAddress());
143 final ServiceGroupIdentifier serviceGroupIdent =
144 ServiceGroupIdentifier.create(instanceIdentifier.toString());
146 final NetconfTopologyContext newNetconfTopologyContext =
147 new NetconfTopologyContext(createSetup(instanceIdentifier, node), serviceGroupIdent);
149 final ClusterSingletonServiceRegistration clusterSingletonServiceRegistration =
150 clusterSingletonServiceProvider.registerClusterSingletonService(newNetconfTopologyContext);
152 clusterRegistrations.put(instanceIdentifier, clusterSingletonServiceRegistration);
153 contexts.put(instanceIdentifier, newNetconfTopologyContext);
156 private void stopNetconfDeviceContext(final InstanceIdentifier<Node> instanceIdentifier) {
157 if (contexts.containsKey(instanceIdentifier)) {
159 clusterRegistrations.get(instanceIdentifier).close();
160 contexts.get(instanceIdentifier).closeFinal();
161 } catch (Exception e) {
162 LOG.warn("Error at closing topology context. InstanceIdentifier: " + instanceIdentifier);
164 contexts.remove(instanceIdentifier);
165 clusterRegistrations.remove(instanceIdentifier);
170 public void close() {
171 if (dataChangeListenerRegistration != null) {
172 dataChangeListenerRegistration.close();
173 dataChangeListenerRegistration = null;
175 contexts.forEach((instanceIdentifier, netconfTopologyContext) -> {
177 netconfTopologyContext.closeFinal();
178 } catch (Exception e) {
179 LOG.error("Error at closing topology context. InstanceIdentifier: " + instanceIdentifier, e);
182 clusterRegistrations.forEach((instanceIdentifier, clusterSingletonServiceRegistration) -> {
184 clusterSingletonServiceRegistration.close();
185 } catch (Exception e) {
186 LOG.error("Error at unregistering from cluster. InstanceIdentifier: " + instanceIdentifier, e);
190 clusterRegistrations.clear();
193 private ListenerRegistration<NetconfTopologyManager> registerDataTreeChangeListener(String topologyId) {
194 final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
195 initTopology(wtx, LogicalDatastoreType.CONFIGURATION, topologyId);
196 initTopology(wtx, LogicalDatastoreType.OPERATIONAL, topologyId);
197 Futures.addCallback(wtx.submit(), new FutureCallback<Void>() {
199 public void onSuccess(Void result) {
200 LOG.debug("topology initialization successful");
204 public void onFailure(@Nonnull Throwable throwable) {
205 LOG.error("Unable to initialize netconf-topology, {}", throwable);
209 LOG.debug("Registering datastore listener");
210 return dataBroker.registerDataTreeChangeListener(
211 new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
212 NetconfTopologyUtils.createTopologyListPath(topologyId).child(Node.class)), this);
215 private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType, String topologyId) {
216 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
217 final InstanceIdentifier<NetworkTopology> networkTopologyId =
218 InstanceIdentifier.builder(NetworkTopology.class).build();
219 wtx.merge(datastoreType, networkTopologyId, networkTopology);
220 final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
221 wtx.merge(datastoreType, networkTopologyId.child(Topology.class,
222 new TopologyKey(new TopologyId(topologyId))), topology);
225 private NetconfTopologySetup createSetup(final InstanceIdentifier<Node> instanceIdentifier, final Node node) {
226 final NetconfTopologySetupBuilder builder = NetconfTopologySetupBuilder.create()
227 .setClusterSingletonServiceProvider(clusterSingletonServiceProvider)
228 .setDataBroker(dataBroker)
229 .setInstanceIdentifier(instanceIdentifier)
230 .setRpcProviderRegistry(rpcProviderRegistry)
232 .setBindingAwareBroker(bindingAwareBroker)
233 .setActorSystem(actorSystem)
234 .setEventExecutor(eventExecutor)
235 .setDomBroker(domBroker)
236 .setKeepaliveExecutor(keepaliveExecutor)
237 .setProcessingExecutor(processingExecutor)
238 .setTopologyId(topologyId)
239 .setNetconfClientDispatcher(clientDispatcher);
241 return builder.build();