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.RemoteDeviceHandler;
29 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
30 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
31 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
32 import org.opendaylight.netconf.sal.connect.util.NetconfTopologyRPCProvider;
33 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
34 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
35 import org.opendaylight.netconf.topology.spi.NetconfConnectorDTO;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.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.ListenerRegistration;
45 import org.opendaylight.yangtools.concepts.ObjectRegistration;
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 final RpcProviderService rpcProviderService;
58 private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
59 private ObjectRegistration<?> rpcReg = null;
61 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
62 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
63 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
64 final DataBroker dataBroker, final DOMMountPointService mountPointService,
65 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
66 final BaseNetconfSchemas baseSchemas) {
67 this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
68 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
72 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
73 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
74 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
75 final DataBroker dataBroker, final DOMMountPointService mountPointService,
76 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
77 final BaseNetconfSchemas baseSchemas, final DeviceActionFactory deviceActionFactory) {
78 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
79 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
81 this.rpcProviderService = requireNonNull(rpcProviderService);
91 // close all existing connectors, delete whole topology in datastore?
92 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
95 activeConnectors.clear();
97 if (datastoreListenerRegistration != null) {
98 datastoreListenerRegistration.close();
99 datastoreListenerRegistration = null;
104 protected RemoteDeviceHandler createSalFacade(final RemoteDeviceId id) {
105 return new NetconfDeviceSalFacade(id, mountPointService, dataBroker, topologyId);
109 * Invoked by blueprint.
112 LOG.debug("Registering datastore listener");
113 datastoreListenerRegistration = 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));
120 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
121 for (final DataTreeModification<Node> change : collection) {
122 final DataObjectModification<Node> rootNode = change.getRootNode();
124 switch (rootNode.getModificationType()) {
125 case SUBTREE_MODIFIED:
126 nodeId = getNodeId(rootNode.getIdentifier());
127 LOG.debug("Config for node {} updated", nodeId);
128 disconnectNode(nodeId);
129 connectNode(nodeId, rootNode.getDataAfter());
132 nodeId = getNodeId(rootNode.getIdentifier());
133 LOG.debug("Config for node {} created", nodeId);
134 if (activeConnectors.containsKey(nodeId)) {
135 LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", nodeId);
136 disconnectNode(nodeId);
138 connectNode(nodeId, rootNode.getDataAfter());
141 nodeId = getNodeId(rootNode.getIdentifier());
142 LOG.debug("Config for node {} deleted", nodeId);
143 disconnectNode(nodeId);
146 LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
152 * Determines the Netconf Node Node ID, given the node's instance
155 * @param pathArgument Node's path argument
156 * @return NodeId for the node
159 static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
160 if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
161 final Identifier<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) pathArgument).getKey();
162 if (key instanceof NodeKey) {
163 return ((NodeKey) key).getNodeId();
166 throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
170 static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
171 final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
172 return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));