Move netconf topology applications in apps/
[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 static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.VisibleForTesting;
13 import io.netty.util.concurrent.EventExecutor;
14 import java.util.Collection;
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.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.binding.api.DataObjectModification;
20 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
21 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.mdsal.binding.api.DataTreeModification;
23 import org.opendaylight.mdsal.binding.api.RpcProviderService;
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.SchemaResourceManager;
29 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
30 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
31 import org.opendaylight.netconf.topology.spi.NetconfConnectorDTO;
32 import org.opendaylight.netconf.topology.spi.NetconfTopologyRPCProvider;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeTopologyService;
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.NodeId;
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.TopologyKey;
39 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
41 import org.opendaylight.yangtools.concepts.ListenerRegistration;
42 import org.opendaylight.yangtools.concepts.ObjectRegistration;
43 import org.opendaylight.yangtools.yang.binding.Identifier;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 public class NetconfTopologyImpl extends AbstractNetconfTopology
50         implements DataTreeChangeListener<Node>, AutoCloseable {
51
52     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
53
54     private final RpcProviderService rpcProviderService;
55     private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
56     private ObjectRegistration<?> rpcReg = null;
57
58     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
59             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
60             final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
61             final DataBroker dataBroker, final DOMMountPointService mountPointService,
62             final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
63             final BaseNetconfSchemas baseSchemas) {
64         this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
65                 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
66                 baseSchemas, null);
67     }
68
69     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
70             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
71             final ThreadPool processingExecutor, final SchemaResourceManager schemaRepositoryProvider,
72             final DataBroker dataBroker, final DOMMountPointService mountPointService,
73             final AAAEncryptionService encryptionService, final RpcProviderService rpcProviderService,
74             final BaseNetconfSchemas baseSchemas, final DeviceActionFactory deviceActionFactory) {
75         super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
76                 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, deviceActionFactory,
77                 baseSchemas);
78         this.rpcProviderService = requireNonNull(rpcProviderService);
79     }
80
81     @Override
82     public void close() {
83         if (rpcReg != null) {
84             rpcReg.close();
85             rpcReg = null;
86         }
87
88         // close all existing connectors, delete whole topology in datastore?
89         for (final NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
90             connectorDTO.close();
91         }
92         activeConnectors.clear();
93
94         if (datastoreListenerRegistration != null) {
95             datastoreListenerRegistration.close();
96             datastoreListenerRegistration = null;
97         }
98     }
99
100     /**
101      * Invoked by blueprint.
102      */
103     public void init() {
104         LOG.debug("Registering datastore listener");
105         datastoreListenerRegistration = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
106             LogicalDatastoreType.CONFIGURATION, createTopologyListPath(topologyId).child(Node.class)), this);
107         rpcReg = rpcProviderService.registerRpcImplementation(NetconfNodeTopologyService.class,
108             new NetconfTopologyRPCProvider(dataBroker, encryptionService, topologyId));
109     }
110
111     @Override
112     public void onDataTreeChanged(final Collection<DataTreeModification<Node>> collection) {
113         for (final DataTreeModification<Node> change : collection) {
114             final DataObjectModification<Node> rootNode = change.getRootNode();
115             final NodeId nodeId;
116             switch (rootNode.getModificationType()) {
117                 case SUBTREE_MODIFIED:
118                     nodeId = getNodeId(rootNode.getIdentifier());
119                     LOG.debug("Config for node {} updated", nodeId);
120                     disconnectNode(nodeId);
121                     connectNode(nodeId, rootNode.getDataAfter());
122                     break;
123                 case WRITE:
124                     nodeId = getNodeId(rootNode.getIdentifier());
125                     LOG.debug("Config for node {} created", nodeId);
126                     if (activeConnectors.containsKey(nodeId)) {
127                         LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", nodeId);
128                         disconnectNode(nodeId);
129                     }
130                     connectNode(nodeId, rootNode.getDataAfter());
131                     break;
132                 case DELETE:
133                     nodeId = getNodeId(rootNode.getIdentifier());
134                     LOG.debug("Config for node {} deleted", nodeId);
135                     disconnectNode(nodeId);
136                     break;
137                 default:
138                     LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
139             }
140         }
141     }
142
143     /**
144      * Determines the Netconf Node Node ID, given the node's instance
145      * identifier.
146      *
147      * @param pathArgument Node's path argument
148      * @return     NodeId for the node
149      */
150     @VisibleForTesting
151     static NodeId getNodeId(final InstanceIdentifier.PathArgument pathArgument) {
152         if (pathArgument instanceof InstanceIdentifier.IdentifiableItem<?, ?>) {
153             final Identifier<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) pathArgument).getKey();
154             if (key instanceof NodeKey) {
155                 return ((NodeKey) key).getNodeId();
156             }
157         }
158         throw new IllegalStateException("Unable to create NodeId from: " + pathArgument);
159     }
160
161     @VisibleForTesting
162     static KeyedInstanceIdentifier<Topology, TopologyKey> createTopologyListPath(final String topologyId) {
163         final InstanceIdentifier<NetworkTopology> networkTopology = InstanceIdentifier.create(NetworkTopology.class);
164         return networkTopology.child(Topology.class, new TopologyKey(new TopologyId(topologyId)));
165     }
166 }