Eliminate blueprint from netconf-topology-impl
[netconf.git] / apps / netconf-topology-impl / 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.annotations.VisibleForTesting;
11 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import io.netty.util.concurrent.EventExecutor;
13 import java.util.Collection;
14 import javax.annotation.PreDestroy;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
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.common.api.LogicalDatastoreType;
27 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
28 import org.opendaylight.netconf.client.NetconfClientDispatcher;
29 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
30 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
31 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
32 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
33 import org.opendaylight.netconf.topology.spi.NetconfConnectorDTO;
34 import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
35 import org.opendaylight.netconf.topology.spi.NetconfTopologyRPCProvider;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeTopologyService;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
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.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
44 import org.opendaylight.yangtools.concepts.Registration;
45 import org.opendaylight.yangtools.yang.binding.Identifier;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
48 import org.osgi.service.component.annotations.Activate;
49 import org.osgi.service.component.annotations.Component;
50 import org.osgi.service.component.annotations.Deactivate;
51 import org.osgi.service.component.annotations.Reference;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
54
55 // Non-final for testing
56 @Singleton
57 @Component(service = { })
58 public class NetconfTopologyImpl extends AbstractNetconfTopology
59         implements DataTreeChangeListener<Node>, AutoCloseable {
60     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
61
62     private Registration dtclReg;
63     private Registration rpcReg;
64
65     @Inject
66     @Activate
67     public NetconfTopologyImpl(
68             @Reference(target = "(type=netconf-client-dispatcher)") final NetconfClientDispatcher clientDispatcher,
69             @Reference(target = "(type=global-event-executor)") final EventExecutor eventExecutor,
70             @Reference(target = "(type=global-netconf-ssh-scheduled-executor)")
71             final ScheduledThreadPool keepaliveExecutor,
72             @Reference(target = "(type=global-netconf-processing-executor)") final ThreadPool processingExecutor,
73             @Reference final SchemaResourceManager schemaRepositoryProvider, @Reference final DataBroker dataBroker,
74             @Reference final DOMMountPointService mountPointService,
75             @Reference final AAAEncryptionService encryptionService,
76             @Reference final RpcProviderService rpcProviderService, @Reference final BaseNetconfSchemas baseSchemas,
77             @Reference final DeviceActionFactory deviceActionFactory) {
78         this(NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME, clientDispatcher, eventExecutor, keepaliveExecutor,
79             processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService, encryptionService,
80             rpcProviderService, baseSchemas, deviceActionFactory);
81     }
82
83     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
84             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
85             final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
86             final DataBroker dataBroker, final DOMMountPointService mountPointService,
87             final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
88             final BaseNetconfSchemas baseSchemas) {
89         this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
90                 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
91                 baseSchemas, null);
92     }
93
94     @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR",
95         justification = "DTCL registration of 'this'")
96     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
97             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
98             final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
99             final DataBroker dataBroker, final DOMMountPointService mountPointService,
100             final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
101             final BaseNetconfSchemas baseSchemas, final DeviceActionFactory deviceActionFactory) {
102         super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
103                 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
104                 baseSchemas);
105
106         LOG.debug("Registering datastore listener");
107         dtclReg = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
108             LogicalDatastoreType.CONFIGURATION, createTopologyListPath(topologyId).child(Node.class)), this);
109         rpcReg = rpcProviderService.registerRpcImplementation(NetconfNodeTopologyService.class,
110             new NetconfTopologyRPCProvider(dataBroker, encryptionService, topologyId));
111     }
112
113     @PreDestroy
114     @Deactivate
115     @Override
116     public void close() {
117         if (rpcReg != null) {
118             rpcReg.close();
119             rpcReg = null;
120         }
121
122         // close all existing connectors, delete whole topology in datastore?
123         for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
124             connectorDTO.close();
125         }
126         activeConnectors.clear();
127
128         if (dtclReg != null) {
129             dtclReg.close();
130             dtclReg = null;
131         }
132     }
133
134     @Override
135     public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
136         for (final DataTreeModification<Node> change : collection) {
137             final DataObjectModification<Node> rootNode = change.getRootNode();
138             final NodeId nodeId;
139             switch (rootNode.getModificationType()) {
140                 case SUBTREE_MODIFIED:
141                     nodeId = getNodeId(rootNode.getIdentifier());
142                     LOG.debug("Config for node {} updated", nodeId);
143                     disconnectNode(nodeId);
144                     connectNode(nodeId, rootNode.getDataAfter());
145                     break;
146                 case WRITE:
147                     nodeId = getNodeId(rootNode.getIdentifier());
148                     LOG.debug("Config for node {} created", nodeId);
149                     if (activeConnectors.containsKey(nodeId)) {
150                         LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", nodeId);
151                         disconnectNode(nodeId);
152                     }
153                     connectNode(nodeId, rootNode.getDataAfter());
154                     break;
155                 case DELETE:
156                     nodeId = getNodeId(rootNode.getIdentifier());
157                     LOG.debug("Config for node {} deleted", nodeId);
158                     disconnectNode(nodeId);
159                     break;
160                 default:
161                     LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
162             }
163         }
164     }
165
166     /**
167      * Determines the Netconf Node Node ID, given the node's instance
168      * identifier.
169      *
170      * @param pathArgument Node's path argument
171      * @return     NodeId for the node
172      */
173     @VisibleForTesting
174     static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
175         if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
176             final Identifier<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) pathArgument).getKey();
177             if (key instanceof NodeKey) {
178                 return ((NodeKey) key).getNodeId();
179             }
180         }
181         throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
182     }
183
184     @VisibleForTesting
185     static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
186         final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
187         return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
188     }
189 }