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.NetconfNodeUtils;
36 import org.opendaylight.netconf.topology.spi.NetconfTopologyRPCProvider;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeTopologyService;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
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.Registration;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
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?
131 if (dtclReg != null) {
138 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
139 for (final DataTreeModification<Node> change : collection) {
140 final DataObjectModification<Node> rootNode = change.getRootNode();
142 switch (rootNode.getModificationType()) {
143 case SUBTREE_MODIFIED -> {
144 LOG.debug("Config for node {} updated", getNodeId(rootNode.getIdentifier()));
145 ensureNode(rootNode.getDataAfter());
148 LOG.debug("Config for node {} created", getNodeId(rootNode.getIdentifier()));
149 ensureNode(rootNode.getDataAfter());
152 nodeId = getNodeId(rootNode.getIdentifier());
153 LOG.debug("Config for node {} deleted", nodeId);
156 default -> LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
162 * Determines the Netconf Node Node ID, given the node's instance
165 * @param pathArgument Node's path argument
166 * @return NodeId for the node
169 static NodeId getNodeId(final PathArgument pathArgument) {
170 if (pathArgument instanceof IdentifiableItem<?, ?> ident && ident.getKey() instanceof NodeKey nodeKey) {
171 return nodeKey.getNodeId();
173 throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
177 static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
178 return InstanceIdentifier.create(NetworkTopology.class)
179 .child(Topology.class, new TopologyKey(new TopologyId(topologyId)));