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.util.concurrent.FutureCallback;
11 import com.google.common.util.concurrent.MoreExecutors;
12 import io.netty.util.concurrent.EventExecutor;
13 import java.util.Collection;
14 import javax.annotation.Nonnull;
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.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
20 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
26 import org.opendaylight.mdsal.common.api.CommitInfo;
27 import org.opendaylight.netconf.client.NetconfClientDispatcher;
28 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
29 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
30 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
31 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
32 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
33 import org.opendaylight.netconf.topology.AbstractNetconfTopology;
34 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
42 import org.opendaylight.yangtools.concepts.ListenerRegistration;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public class NetconfTopologyImpl extends AbstractNetconfTopology
48 implements DataTreeChangeListener<Node>, AutoCloseable {
50 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
52 private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
54 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
55 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
56 final ThreadPool processingExecutor,
57 final SchemaRepositoryProvider schemaRepositoryProvider,
58 final DataBroker dataBroker, final DOMMountPointService mountPointService,
59 final AAAEncryptionService encryptionService) {
60 this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
61 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, null);
64 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
65 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
66 final ThreadPool processingExecutor,
67 final SchemaRepositoryProvider schemaRepositoryProvider,
68 final DataBroker dataBroker, final DOMMountPointService mountPointService,
69 final AAAEncryptionService encryptionService,
70 final DeviceActionFactory deviceActionFactory) {
71 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
72 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory);
77 // close all existing connectors, delete whole topology in datastore?
78 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
81 activeConnectors.clear();
83 if (datastoreListenerRegistration != null) {
84 datastoreListenerRegistration.close();
85 datastoreListenerRegistration = null;
90 protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id) {
91 return new NetconfDeviceSalFacade(id, mountPointService, dataBroker);
95 * Invoked by blueprint.
98 final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
99 initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
100 initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
101 wtx.commit().addCallback(new FutureCallback<CommitInfo>() {
103 public void onSuccess(final CommitInfo result) {
104 LOG.debug("topology initialization successful");
108 public void onFailure(final Throwable throwable) {
109 LOG.error("Unable to initialize netconf-topology, {}", throwable);
111 }, MoreExecutors.directExecutor());
113 LOG.debug("Registering datastore listener");
114 datastoreListenerRegistration =
115 dataBroker.registerDataTreeChangeListener(
116 new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
117 TopologyUtil.createTopologyListPath(topologyId).child(Node.class)), this);
121 public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<Node>> collection) {
122 for (final DataTreeModification<Node> change : collection) {
123 final DataObjectModification<Node> rootNode = change.getRootNode();
124 switch (rootNode.getModificationType()) {
125 case SUBTREE_MODIFIED:
126 LOG.debug("Config for node {} updated", TopologyUtil.getNodeId(rootNode.getIdentifier()));
127 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
128 connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
131 LOG.debug("Config for node {} created", TopologyUtil.getNodeId(rootNode.getIdentifier()));
132 if (activeConnectors.containsKey(TopologyUtil.getNodeId(rootNode.getIdentifier()))) {
133 LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..",
134 TopologyUtil.getNodeId(rootNode.getIdentifier()));
135 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
137 connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
140 LOG.debug("Config for node {} deleted", TopologyUtil.getNodeId(rootNode.getIdentifier()));
141 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
144 LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
149 private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
150 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
151 final InstanceIdentifier<NetworkTopology> networkTopologyId =
152 InstanceIdentifier.builder(NetworkTopology.class).build();
153 wtx.merge(datastoreType, networkTopologyId, networkTopology);
154 final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
155 wtx.merge(datastoreType,
156 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);