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.DeviceActionFactory;
30 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
31 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
32 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
33 import org.opendaylight.netconf.topology.spi.NetconfConnectorDTO;
34 import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
35 import org.opendaylight.netconf.topology.spi.NetconfTopologyRPCProvider;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeTopologyService;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
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.TopologyKey;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
44 import org.opendaylight.yangtools.concepts.Registration;
45 import org.opendaylight.yangtools.yang.binding.Identifier;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
48 import org.osgi.service.component.annotations.Activate;
49 import org.osgi.service.component.annotations.Component;
50 import org.osgi.service.component.annotations.Deactivate;
51 import org.osgi.service.component.annotations.Reference;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 // Non-final for testing
57 @Component(service = { })
58 public class NetconfTopologyImpl extends AbstractNetconfTopology
59 implements DataTreeChangeListener<Node>, AutoCloseable {
60 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
62 private Registration dtclReg;
63 private Registration rpcReg;
67 public NetconfTopologyImpl(
68 @Reference(target = "(type=netconf-client-dispatcher)") final NetconfClientDispatcher clientDispatcher,
69 @Reference(target = "(type=global-event-executor)") final EventExecutor eventExecutor,
70 @Reference(target = "(type=global-netconf-ssh-scheduled-executor)")
71 final ScheduledThreadPool keepaliveExecutor,
72 @Reference(target = "(type=global-netconf-processing-executor)") final ThreadPool processingExecutor,
73 @Reference final SchemaResourceManager schemaRepositoryProvider, @Reference final DataBroker dataBroker,
74 @Reference final DOMMountPointService mountPointService,
75 @Reference final AAAEncryptionService encryptionService,
76 @Reference final RpcProviderService rpcProviderService, @Reference final BaseNetconfSchemas baseSchemas,
77 @Reference final DeviceActionFactory deviceActionFactory) {
78 this(NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME, clientDispatcher, eventExecutor, keepaliveExecutor,
79 processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService,
80 rpcProviderService, baseSchemas, deviceActionFactory);
83 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
84 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
85 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
86 final DataBroker dataBroker, final DOMMountPointService mountPointService,
87 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
88 final BaseNetconfSchemas baseSchemas) {
89 this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
90 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
94 @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR",
95 justification = "DTCL registration of 'this'")
96 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
97 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
98 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
99 final DataBroker dataBroker, final DOMMountPointService mountPointService,
100 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
101 final BaseNetconfSchemas baseSchemas, final DeviceActionFactory deviceActionFactory) {
102 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
103 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
106 LOG.debug("Registering datastore listener");
107 dtclReg = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
108 LogicalDatastoreType.CONFIGURATION, createTopologyListPath(topologyId).child(Node.class)), this);
109 rpcReg = rpcProviderService.registerRpcImplementation(NetconfNodeTopologyService.class,
110 new NetconfTopologyRPCProvider(dataBroker, encryptionService, topologyId));
116 public void close() {
117 if (rpcReg != null) {
122 // close all existing connectors, delete whole topology in datastore?
123 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
124 connectorDTO.close();
126 activeConnectors.clear();
128 if (dtclReg != null) {
135 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
136 for (final DataTreeModification<Node> change : collection) {
137 final DataObjectModification<Node> rootNode = change.getRootNode();
139 switch (rootNode.getModificationType()) {
140 case SUBTREE_MODIFIED:
141 nodeId = getNodeId(rootNode.getIdentifier());
142 LOG.debug("Config for node {} updated", nodeId);
143 disconnectNode(nodeId);
144 connectNode(nodeId, rootNode.getDataAfter());
147 nodeId = getNodeId(rootNode.getIdentifier());
148 LOG.debug("Config for node {} created", nodeId);
149 if (activeConnectors.containsKey(nodeId)) {
150 LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", nodeId);
151 disconnectNode(nodeId);
153 connectNode(nodeId, rootNode.getDataAfter());
156 nodeId = getNodeId(rootNode.getIdentifier());
157 LOG.debug("Config for node {} deleted", nodeId);
158 disconnectNode(nodeId);
161 LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
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)));