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 com.google.common.util.concurrent.MoreExecutors;
14 import io.netty.util.concurrent.EventExecutor;
15 import java.util.Collection;
16 import javax.annotation.Nonnull;
17 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
18 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
19 import org.opendaylight.controller.config.threadpool.ThreadPool;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
24 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
25 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
28 import org.opendaylight.netconf.client.NetconfClientDispatcher;
29 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
30 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
31 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
32 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
33 import org.opendaylight.netconf.topology.AbstractNetconfTopology;
34 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
42 import org.opendaylight.yangtools.concepts.ListenerRegistration;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public class NetconfTopologyImpl extends AbstractNetconfTopology
48 implements DataTreeChangeListener<Node>, AutoCloseable {
50 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
52 private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
54 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
55 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
56 final ThreadPool processingExecutor,
57 final SchemaRepositoryProvider schemaRepositoryProvider,
58 final DataBroker dataBroker, final DOMMountPointService mountPointService,
59 final AAAEncryptionService encryptionService) {
60 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
61 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService);
65 public void close() throws Exception {
66 // close all existing connectors, delete whole topology in datastore?
67 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
70 activeConnectors.clear();
72 if (datastoreListenerRegistration != null) {
73 datastoreListenerRegistration.close();
74 datastoreListenerRegistration = null;
79 protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id) {
80 return new NetconfDeviceSalFacade(id, mountPointService, dataBroker);
84 * Invoked by blueprint.
87 final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
88 initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
89 initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
90 Futures.addCallback(wtx.submit(), new FutureCallback<Void>() {
92 public void onSuccess(final Void result) {
93 LOG.debug("topology initialization successful");
97 public void onFailure(final Throwable throwable) {
98 LOG.error("Unable to initialize netconf-topology, {}", throwable);
100 }, MoreExecutors.directExecutor());
102 LOG.debug("Registering datastore listener");
103 datastoreListenerRegistration =
104 dataBroker.registerDataTreeChangeListener(
105 new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
106 TopologyUtil.createTopologyListPath(topologyId).child(Node.class)), this);
110 public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<Node>> collection) {
111 for (final 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..",
123 TopologyUtil.getNodeId(rootNode.getIdentifier()));
124 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
126 connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
129 LOG.debug("Config for node {} deleted", TopologyUtil.getNodeId(rootNode.getIdentifier()));
130 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
133 LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
138 private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
139 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
140 final InstanceIdentifier<NetworkTopology> networkTopologyId =
141 InstanceIdentifier.builder(NetworkTopology.class).build();
142 wtx.merge(datastoreType, networkTopologyId, networkTopology);
143 final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
144 wtx.merge(datastoreType,
145 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);