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 static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.VisibleForTesting;
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.RpcProviderService;
24 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
25 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
26 import org.opendaylight.netconf.client.NetconfClientDispatcher;
27 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
28 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
29 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
30 import org.opendaylight.netconf.sal.connect.util.NetconfTopologyRPCProvider;
31 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
32 import org.opendaylight.netconf.topology.spi.NetconfConnectorDTO;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeTopologyService;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
41 import org.opendaylight.yangtools.concepts.ListenerRegistration;
42 import org.opendaylight.yangtools.concepts.ObjectRegistration;
43 import org.opendaylight.yangtools.yang.binding.Identifier;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 public class NetconfTopologyImpl extends AbstractNetconfTopology
50 implements DataTreeChangeListener<Node>, AutoCloseable {
52 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
54 private final RpcProviderService rpcProviderService;
55 private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
56 private ObjectRegistration<?> rpcReg = null;
58 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
59 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
60 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
61 final DataBroker dataBroker, final DOMMountPointService mountPointService,
62 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
63 final BaseNetconfSchemas baseSchemas) {
64 this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
65 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
69 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
70 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
71 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
72 final DataBroker dataBroker, final DOMMountPointService mountPointService,
73 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
74 final BaseNetconfSchemas baseSchemas, final DeviceActionFactory deviceActionFactory) {
75 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
76 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
78 this.rpcProviderService = requireNonNull(rpcProviderService);
88 // close all existing connectors, delete whole topology in datastore?
89 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
92 activeConnectors.clear();
94 if (datastoreListenerRegistration != null) {
95 datastoreListenerRegistration.close();
96 datastoreListenerRegistration = null;
101 * Invoked by blueprint.
104 LOG.debug("Registering datastore listener");
105 datastoreListenerRegistration = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
106 LogicalDatastoreType.CONFIGURATION, createTopologyListPath(topologyId).child(Node.class)), this);
107 rpcReg = rpcProviderService.registerRpcImplementation(NetconfNodeTopologyService.class,
108 new NetconfTopologyRPCProvider(dataBroker, encryptionService, topologyId));
112 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
113 for (final DataTreeModification<Node> change : collection) {
114 final DataObjectModification<Node> rootNode = change.getRootNode();
116 switch (rootNode.getModificationType()) {
117 case SUBTREE_MODIFIED:
118 nodeId = getNodeId(rootNode.getIdentifier());
119 LOG.debug("Config for node {} updated", nodeId);
120 disconnectNode(nodeId);
121 connectNode(nodeId, rootNode.getDataAfter());
124 nodeId = getNodeId(rootNode.getIdentifier());
125 LOG.debug("Config for node {} created", nodeId);
126 if (activeConnectors.containsKey(nodeId)) {
127 LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", nodeId);
128 disconnectNode(nodeId);
130 connectNode(nodeId, rootNode.getDataAfter());
133 nodeId = getNodeId(rootNode.getIdentifier());
134 LOG.debug("Config for node {} deleted", nodeId);
135 disconnectNode(nodeId);
138 LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
144 * Determines the Netconf Node Node ID, given the node's instance
147 * @param pathArgument Node's path argument
148 * @return NodeId for the node
151 static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
152 if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
153 final Identifier<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) pathArgument).getKey();
154 if (key instanceof NodeKey) {
155 return ((NodeKey) key).getNodeId();
158 throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
162 static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
163 final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
164 return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));