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