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
8 package org.opendaylight.netconf.topology.impl;
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.MoreExecutors;
13 import io.netty.util.concurrent.EventExecutor;
14 import java.util.Collection;
15 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
16 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
17 import org.opendaylight.controller.config.threadpool.ThreadPool;
18 import org.opendaylight.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.binding.api.DataObjectModification;
20 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
21 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.mdsal.binding.api.DataTreeModification;
23 import org.opendaylight.mdsal.binding.api.WriteTransaction;
24 import org.opendaylight.mdsal.common.api.CommitInfo;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
27 import org.opendaylight.netconf.client.NetconfClientDispatcher;
28 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
29 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
30 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
31 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
32 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
33 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
34 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
35 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
45 import org.opendaylight.yangtools.concepts.ListenerRegistration;
46 import org.opendaylight.yangtools.yang.binding.Identifier;
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
48 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 public class NetconfTopologyImpl extends AbstractNetconfTopology
53 implements DataTreeChangeListener<Node>, AutoCloseable {
55 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
57 private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
59 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
60 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
61 final ThreadPool processingExecutor,
62 final SchemaResourceManager schemaRepositoryProvider,
63 final DataBroker dataBroker, final DOMMountPointService mountPointService,
64 final AAAEncryptionService encryptionService, final BaseNetconfSchemas baseSchemas) {
65 this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
66 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, baseSchemas, null);
69 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
70 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
71 final ThreadPool processingExecutor,
72 final SchemaResourceManager schemaRepositoryProvider,
73 final DataBroker dataBroker, final DOMMountPointService mountPointService,
74 final AAAEncryptionService encryptionService, final BaseNetconfSchemas baseSchemas,
75 final DeviceActionFactory deviceActionFactory) {
76 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
77 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
83 // close all existing connectors, delete whole topology in datastore?
84 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
87 activeConnectors.clear();
89 if (datastoreListenerRegistration != null) {
90 datastoreListenerRegistration.close();
91 datastoreListenerRegistration = null;
96 protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id) {
97 return new NetconfDeviceSalFacade(id, mountPointService, dataBroker, topologyId);
101 * Invoked by blueprint.
104 final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
105 initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
106 initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
107 wtx.commit().addCallback(new FutureCallback<CommitInfo>() {
109 public void onSuccess(final CommitInfo result) {
110 LOG.debug("topology initialization successful");
114 public void onFailure(final Throwable throwable) {
115 LOG.error("Unable to initialize netconf-topology", throwable);
117 }, MoreExecutors.directExecutor());
119 LOG.debug("Registering datastore listener");
120 datastoreListenerRegistration = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
121 LogicalDatastoreType.CONFIGURATION, createTopologyListPath(topologyId).child(Node.class)), this);
125 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
126 for (final DataTreeModification<Node> change : collection) {
127 final DataObjectModification<Node> rootNode = change.getRootNode();
129 switch (rootNode.getModificationType()) {
130 case SUBTREE_MODIFIED:
131 nodeId = getNodeId(rootNode.getIdentifier());
132 LOG.debug("Config for node {} updated", nodeId);
133 disconnectNode(nodeId);
134 connectNode(nodeId, rootNode.getDataAfter());
137 nodeId = getNodeId(rootNode.getIdentifier());
138 LOG.debug("Config for node {} created", nodeId);
139 if (activeConnectors.containsKey(nodeId)) {
140 LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", nodeId);
141 disconnectNode(nodeId);
143 connectNode(nodeId, rootNode.getDataAfter());
146 nodeId = getNodeId(rootNode.getIdentifier());
147 LOG.debug("Config for node {} deleted", nodeId);
148 disconnectNode(nodeId);
151 LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
156 private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
157 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
158 final InstanceIdentifier<NetworkTopology> networkTopologyId =
159 InstanceIdentifier.builder(NetworkTopology.class).build();
160 wtx.merge(datastoreType, networkTopologyId, networkTopology);
161 final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
162 wtx.merge(datastoreType,
163 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);
167 * Determines the Netconf Node Node ID, given the node's instance
170 * @param pathArgument Node's path argument
171 * @return NodeId for the node
174 static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
175 if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
176 final Identifier key = ((InstanceIdentifier.IdentifiableItem) pathArgument).getKey();
177 if (key instanceof NodeKey) {
178 return ((NodeKey) key).getNodeId();
181 throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
185 static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
186 final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
187 return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));