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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import io.netty.util.concurrent.EventExecutor;
13 import java.util.Collection;
14 import javax.annotation.PreDestroy;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
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.mdsal.binding.api.DataBroker;
21 import org.opendaylight.mdsal.binding.api.DataObjectModification;
22 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
23 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
24 import org.opendaylight.mdsal.binding.api.DataTreeModification;
25 import org.opendaylight.mdsal.binding.api.RpcProviderService;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
28 import org.opendaylight.netconf.client.NetconfClientDispatcher;
29 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
30 import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
31 import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
32 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
33 import org.opendaylight.netconf.client.mdsal.api.SslHandlerFactoryProvider;
34 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
35 import org.opendaylight.netconf.topology.spi.NetconfConnectorDTO;
36 import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
37 import org.opendaylight.netconf.topology.spi.NetconfTopologyRPCProvider;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeTopologyService;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
46 import org.opendaylight.yangtools.concepts.Registration;
47 import org.opendaylight.yangtools.yang.binding.Identifier;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
50 import org.osgi.service.component.annotations.Activate;
51 import org.osgi.service.component.annotations.Component;
52 import org.osgi.service.component.annotations.Deactivate;
53 import org.osgi.service.component.annotations.Reference;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
57 // Non-final for testing
59 @Component(service = { })
60 public class NetconfTopologyImpl extends AbstractNetconfTopology
61 implements DataTreeChangeListener<Node>, AutoCloseable {
62 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
64 private Registration dtclReg;
65 private Registration rpcReg;
69 public NetconfTopologyImpl(
70 @Reference(target = "(type=netconf-client-dispatcher)") final NetconfClientDispatcher clientDispatcher,
71 @Reference(target = "(type=global-event-executor)") final EventExecutor eventExecutor,
72 @Reference(target = "(type=global-netconf-ssh-scheduled-executor)")
73 final ScheduledThreadPool keepaliveExecutor,
74 @Reference(target = "(type=global-netconf-processing-executor)") final ThreadPool processingExecutor,
75 @Reference final SchemaResourceManager schemaRepositoryProvider, @Reference final DataBroker dataBroker,
76 @Reference final DOMMountPointService mountPointService,
77 @Reference final AAAEncryptionService encryptionService,
78 @Reference final RpcProviderService rpcProviderService, @Reference final BaseNetconfSchemas baseSchemas,
79 @Reference final CredentialProvider credentialProvider,
80 @Reference final SslHandlerFactoryProvider sslHandlerFactoryProvider,
81 @Reference final DeviceActionFactory deviceActionFactory) {
82 this(NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME, clientDispatcher, eventExecutor, keepaliveExecutor,
83 processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService,
84 rpcProviderService, baseSchemas, credentialProvider, sslHandlerFactoryProvider, deviceActionFactory);
87 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
88 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
89 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
90 final DataBroker dataBroker, final DOMMountPointService mountPointService,
91 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
92 final BaseNetconfSchemas baseSchemas, final CredentialProvider credentialProvider,
93 final SslHandlerFactoryProvider sslHandlerFactoryProvider) {
94 this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
95 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
96 baseSchemas, credentialProvider, sslHandlerFactoryProvider, null);
99 @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR",
100 justification = "DTCL registration of 'this'")
101 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
102 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
103 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
104 final DataBroker dataBroker, final DOMMountPointService mountPointService,
105 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
106 final BaseNetconfSchemas baseSchemas, final CredentialProvider credentialProvider,
107 final SslHandlerFactoryProvider sslHandlerFactoryProvider, final DeviceActionFactory deviceActionFactory) {
108 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
109 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
110 baseSchemas, credentialProvider, sslHandlerFactoryProvider);
112 LOG.debug("Registering datastore listener");
113 dtclReg = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
114 LogicalDatastoreType.CONFIGURATION, createTopologyListPath(topologyId).child(Node.class)), this);
115 rpcReg = rpcProviderService.registerRpcImplementation(NetconfNodeTopologyService.class,
116 new NetconfTopologyRPCProvider(dataBroker, encryptionService, topologyId));
122 public void close() {
123 if (rpcReg != null) {
128 // close all existing connectors, delete whole topology in datastore?
129 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
130 connectorDTO.close();
132 activeConnectors.clear();
134 if (dtclReg != null) {
141 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
142 for (final DataTreeModification<Node> change : collection) {
143 final DataObjectModification<Node> rootNode = change.getRootNode();
145 switch (rootNode.getModificationType()) {
146 case SUBTREE_MODIFIED:
147 nodeId = getNodeId(rootNode.getIdentifier());
148 LOG.debug("Config for node {} updated", nodeId);
149 disconnectNode(nodeId);
150 connectNode(nodeId, rootNode.getDataAfter());
153 nodeId = getNodeId(rootNode.getIdentifier());
154 LOG.debug("Config for node {} created", nodeId);
155 if (activeConnectors.containsKey(nodeId)) {
156 LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", nodeId);
157 disconnectNode(nodeId);
159 connectNode(nodeId, rootNode.getDataAfter());
162 nodeId = getNodeId(rootNode.getIdentifier());
163 LOG.debug("Config for node {} deleted", nodeId);
164 disconnectNode(nodeId);
167 LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
173 * Determines the Netconf Node Node ID, given the node's instance
176 * @param pathArgument Node's path argument
177 * @return NodeId for the node
180 static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
181 if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
182 final Identifier<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) pathArgument).getKey();
183 if (key instanceof NodeKey) {
184 return ((NodeKey) key).getNodeId();
187 throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
191 static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
192 final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
193 return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));