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 com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import io.netty.util.concurrent.EventExecutor;
16 import java.util.Collection;
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.binding.api.WriteTransaction;
27 import org.opendaylight.mdsal.common.api.CommitInfo;
28 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
29 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
30 import org.opendaylight.netconf.client.NetconfClientDispatcher;
31 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
32 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
33 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
34 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
35 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
36 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
37 import org.opendaylight.netconf.sal.connect.util.NetconfTopologyRPCProvider;
38 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
39 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeTopologyService;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
50 import org.opendaylight.yangtools.concepts.ListenerRegistration;
51 import org.opendaylight.yangtools.concepts.ObjectRegistration;
52 import org.opendaylight.yangtools.yang.binding.Identifier;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
58 public class NetconfTopologyImpl extends AbstractNetconfTopology
59 implements DataTreeChangeListener<Node>, AutoCloseable {
61 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
63 private final RpcProviderService rpcProviderService;
64 private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
65 private ObjectRegistration<?> rpcReg = null;
67 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
68 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
69 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
70 final DataBroker dataBroker, final DOMMountPointService mountPointService,
71 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
72 final BaseNetconfSchemas baseSchemas) {
73 this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
74 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
78 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
79 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
80 final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
81 final DataBroker dataBroker, final DOMMountPointService mountPointService,
82 final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
83 final BaseNetconfSchemas baseSchemas, final DeviceActionFactory deviceActionFactory) {
84 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
85 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
87 this.rpcProviderService = requireNonNull(rpcProviderService);
97 // close all existing connectors, delete whole topology in datastore?
98 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
101 activeConnectors.clear();
103 if (datastoreListenerRegistration != null) {
104 datastoreListenerRegistration.close();
105 datastoreListenerRegistration = null;
110 protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id) {
111 return new NetconfDeviceSalFacade(id, mountPointService, dataBroker, topologyId);
115 * Invoked by blueprint.
118 final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
119 initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
120 initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
121 wtx.commit().addCallback(new FutureCallback<CommitInfo>() {
123 public void onSuccess(final CommitInfo result) {
124 LOG.debug("topology initialization successful");
128 public void onFailure(final Throwable throwable) {
129 LOG.error("Unable to initialize netconf-topology", throwable);
131 }, MoreExecutors.directExecutor());
133 LOG.debug("Registering datastore listener");
134 datastoreListenerRegistration = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
135 LogicalDatastoreType.CONFIGURATION, createTopologyListPath(topologyId).child(Node.class)), this);
136 rpcReg = rpcProviderService.registerRpcImplementation(NetconfNodeTopologyService.class,
137 new NetconfTopologyRPCProvider(dataBroker, encryptionService, topologyId));
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());
172 private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
173 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
174 final InstanceIdentifier<NetworkTopology> networkTopologyId =
175 InstanceIdentifier.builder(NetworkTopology.class).build();
176 wtx.merge(datastoreType, networkTopologyId, networkTopology);
177 final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
178 wtx.merge(datastoreType,
179 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);
183 * Determines the Netconf Node Node ID, given the node's instance
186 * @param pathArgument Node's path argument
187 * @return NodeId for the node
190 static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
191 if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
192 final Identifier<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) pathArgument).getKey();
193 if (key instanceof NodeKey) {
194 return ((NodeKey) key).getNodeId();
197 throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
201 static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
202 final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
203 return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));