Remove use of ThreadPools in sal-netconf-connector
[netconf.git] / netconf / netconf-topology / src / main / java / org / opendaylight / netconf / topology / impl / NetconfTopologyImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.topology.impl;
9
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;
46
47 public class NetconfTopologyImpl extends AbstractNetconfTopology
48         implements DataTreeChangeListener<Node>, AutoCloseable {
49
50     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
51
52     private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
53
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);
62     }
63
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);
73     }
74
75     @Override
76     public void close() {
77         // close all existing connectors, delete whole topology in datastore?
78         for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
79             connectorDTO.close();
80         }
81         activeConnectors.clear();
82
83         if (datastoreListenerRegistration != null) {
84             datastoreListenerRegistration.close();
85             datastoreListenerRegistration = null;
86         }
87     }
88
89     @Override
90     protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(final RemoteDeviceId id) {
91         return new NetconfDeviceSalFacade(id, mountPointService, dataBroker);
92     }
93
94     /**
95      * Invoked by blueprint.
96      */
97     public void init() {
98         final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
99         initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
100         initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
101         wtx.commit().addCallback(new FutureCallback<CommitInfo>() {
102             @Override
103             public void onSuccess(final CommitInfo result) {
104                 LOG.debug("topology initialization successful");
105             }
106
107             @Override
108             public void onFailure(final Throwable throwable) {
109                 LOG.error("Unable to initialize netconf-topology, {}", throwable);
110             }
111         }, MoreExecutors.directExecutor());
112
113         LOG.debug("Registering datastore listener");
114         datastoreListenerRegistration =
115                 dataBroker.registerDataTreeChangeListener(
116                         new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
117                                 TopologyUtil.createTopologyListPath(topologyId).child(Node.class)), this);
118     }
119
120     @Override
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());
129                     break;
130                 case WRITE:
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()));
136                     }
137                     connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
138                     break;
139                 case DELETE:
140                     LOG.debug("Config for node {} deleted", TopologyUtil.getNodeId(rootNode.getIdentifier()));
141                     disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
142                     break;
143                 default:
144                     LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
145             }
146         }
147     }
148
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);
157     }
158
159 }