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 org.opendaylight.aaa.encrypt.AAAEncryptionService;
15 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
16 import org.opendaylight.controller.config.threadpool.ThreadPool;
17 import org.opendaylight.mdsal.binding.api.DataBroker;
18 import org.opendaylight.mdsal.binding.api.DataObjectModification;
19 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
20 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
21 import org.opendaylight.mdsal.binding.api.DataTreeModification;
22 import org.opendaylight.mdsal.binding.api.WriteTransaction;
23 import org.opendaylight.mdsal.common.api.CommitInfo;
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.netconf.listener.NetconfSessionPreferences;
30 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
31 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
32 import org.opendaylight.netconf.topology.AbstractNetconfTopology;
33 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
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.NetworkTopologyBuilder;
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.TopologyBuilder;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
41 import org.opendaylight.yangtools.concepts.ListenerRegistration;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 public class NetconfTopologyImpl extends AbstractNetconfTopology
47 implements DataTreeChangeListener<Node>, AutoCloseable {
49 private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
51 private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
53 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
54 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
55 final ThreadPool processingExecutor,
56 final SchemaRepositoryProvider schemaRepositoryProvider,
57 final DataBroker dataBroker, final DOMMountPointService mountPointService,
58 final AAAEncryptionService encryptionService) {
59 this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
60 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, null);
63 public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
64 final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
65 final ThreadPool processingExecutor,
66 final SchemaRepositoryProvider schemaRepositoryProvider,
67 final DataBroker dataBroker, final DOMMountPointService mountPointService,
68 final AAAEncryptionService encryptionService,
69 final DeviceActionFactory deviceActionFactory) {
70 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
71 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory);
76 // close all existing connectors, delete whole topology in datastore?
77 for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
80 activeConnectors.clear();
82 if (datastoreListenerRegistration != null) {
83 datastoreListenerRegistration.close();
84 datastoreListenerRegistration = null;
89 protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id) {
90 return new NetconfDeviceSalFacade(id, mountPointService, dataBroker);
94 * Invoked by blueprint.
97 final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
98 initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
99 initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
100 wtx.commit().addCallback(new FutureCallback<CommitInfo>() {
102 public void onSuccess(final CommitInfo result) {
103 LOG.debug("topology initialization successful");
107 public void onFailure(final Throwable throwable) {
108 LOG.error("Unable to initialize netconf-topology, {}", throwable);
110 }, MoreExecutors.directExecutor());
112 LOG.debug("Registering datastore listener");
113 datastoreListenerRegistration = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
114 LogicalDatastoreType.CONFIGURATION, TopologyUtil.createTopologyListPath(topologyId).child(Node.class)),
119 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
120 for (final DataTreeModification<Node> change : collection) {
121 final DataObjectModification<Node> rootNode = change.getRootNode();
122 switch (rootNode.getModificationType()) {
123 case SUBTREE_MODIFIED:
124 LOG.debug("Config for node {} updated", TopologyUtil.getNodeId(rootNode.getIdentifier()));
125 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
126 connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
129 LOG.debug("Config for node {} created", TopologyUtil.getNodeId(rootNode.getIdentifier()));
130 if (activeConnectors.containsKey(TopologyUtil.getNodeId(rootNode.getIdentifier()))) {
131 LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..",
132 TopologyUtil.getNodeId(rootNode.getIdentifier()));
133 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
135 connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
138 LOG.debug("Config for node {} deleted", TopologyUtil.getNodeId(rootNode.getIdentifier()));
139 disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
142 LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
147 private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
148 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
149 final InstanceIdentifier<NetworkTopology> networkTopologyId =
150 InstanceIdentifier.builder(NetworkTopology.class).build();
151 wtx.merge(datastoreType, networkTopologyId, networkTopology);
152 final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
153 wtx.merge(datastoreType,
154 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);