2 * Copyright (c) 2015 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.impl;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import io.netty.util.concurrent.EventExecutor;
14 import java.util.Collection;
15 import javax.annotation.Nonnull;
16 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
17 import org.opendaylight.controller.config.threadpool.ThreadPool;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
20 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
26 import org.opendaylight.controller.sal.core.api.Broker;
27 import org.opendaylight.netconf.client.NetconfClientDispatcher;
28 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
29 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
30 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
31 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
32 import org.opendaylight.netconf.topology.AbstractNetconfTopology;
33 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
41 import org.opendaylight.yangtools.concepts.ListenerRegistration;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 public class NetconfTopologyImpl extends AbstractNetconfTopology implements DataTreeChangeListener<Node>, AutoCloseable {
48 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
50 private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
52 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
53 final BindingAwareBroker bindingAwareBroker, final Broker domBroker,
54 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
55 final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
56 final DataBroker dataBroker) {
57 super(topologyId, clientDispatcher,
58 bindingAwareBroker, domBroker, eventExecutor,
59 keepaliveExecutor, processingExecutor, schemaRepositoryProvider, dataBroker);
63 public void close() throws Exception {
64 // close all existing connectors, delete whole topology in datastore?
65 for (NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
68 activeConnectors.clear();
70 if (datastoreListenerRegistration != null) {
71 datastoreListenerRegistration.close();
72 datastoreListenerRegistration = null;
77 protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker) {
78 return new NetconfDeviceSalFacade(id, domBroker, bindingAwareBroker);
85 final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
86 initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
87 initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
88 Futures.addCallback(wtx.submit(), new FutureCallback<Void>() {
90 public void onSuccess(Void result) {
91 LOG.debug("topology initialization successful");
95 public void onFailure(Throwable t) {
96 LOG.error("Unable to initialize netconf-topology, {}", t);
100 LOG.debug("Registering datastore listener");
101 datastoreListenerRegistration =
102 dataBroker.registerDataTreeChangeListener(
103 new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
104 TopologyUtil.createTopologyListPath(topologyId).child(Node.class)), this);
110 public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> collection) {
111 for (DataTreeModification<Node> change : collection) {
112 final DataObjectModification<Node> rootNode = change.getRootNode();
113 switch (rootNode.getModificationType()) {
114 case SUBTREE_MODIFIED:
115 LOG.debug("Config for node {} updated", TopologyUtil.getNodeId(rootNode.getIdentifier()));
116 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
117 connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
120 LOG.debug("Config for node {} created", TopologyUtil.getNodeId(rootNode.getIdentifier()));
121 if (activeConnectors.containsKey(TopologyUtil.getNodeId(rootNode.getIdentifier()))) {
122 LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", TopologyUtil.getNodeId(rootNode.getIdentifier()));
123 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
125 connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
128 LOG.debug("Config for node {} deleted", TopologyUtil.getNodeId(rootNode.getIdentifier()));
129 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
135 private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
136 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
137 final InstanceIdentifier<NetworkTopology> networkTopologyId = InstanceIdentifier.builder(NetworkTopology.class).build();
138 wtx.merge(datastoreType, networkTopologyId, networkTopology);
139 final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
140 wtx.merge(datastoreType, networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);