Merge "Use yangtools ParserStreamUtils.findSchemaNodeByNameAndNamespace() method"
[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
9 package org.opendaylight.netconf.topology.impl;
10
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import io.netty.util.concurrent.EventExecutor;
14 import java.util.Collection;
15 import javax.annotation.Nonnull;
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.controller.sal.binding.api.BindingAwareBroker;
27 import org.opendaylight.controller.sal.core.api.Broker;
28 import org.opendaylight.netconf.client.NetconfClientDispatcher;
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 implements DataTreeChangeListener<Node>, AutoCloseable {
48
49     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyImpl.class);
50
51     private ListenerRegistration<NetconfTopologyImpl> datastoreListenerRegistration = null;
52
53     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
54                                final BindingAwareBroker bindingAwareBroker, final Broker domBroker,
55                                final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
56                                final ThreadPool processingExecutor, final SchemaRepositoryProvider schemaRepositoryProvider,
57                                final DataBroker dataBroker, final DOMMountPointService mountPointService) {
58         super(topologyId, clientDispatcher,
59                 bindingAwareBroker, domBroker, eventExecutor,
60                 keepaliveExecutor, processingExecutor, schemaRepositoryProvider, dataBroker, mountPointService);
61     }
62
63     @Override
64     public void close() throws Exception {
65         // close all existing connectors, delete whole topology in datastore?
66         for (NetconfConnectorDTO connectorDTO : activeConnectors.values()) {
67             connectorDTO.close();
68         }
69         activeConnectors.clear();
70
71         if (datastoreListenerRegistration != null) {
72             datastoreListenerRegistration.close();
73             datastoreListenerRegistration = null;
74         }
75     }
76
77     @Override
78     protected RemoteDeviceHandler<NetconfSessionPreferences> createSalFacade(RemoteDeviceId id, Broker domBroker, BindingAwareBroker bindingBroker) {
79         return new NetconfDeviceSalFacade(id, domBroker, bindingAwareBroker);
80     }
81
82     /**
83      * Invoke by blueprint
84      */
85     public void init() {
86         final WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
87         initTopology(wtx, LogicalDatastoreType.CONFIGURATION);
88         initTopology(wtx, LogicalDatastoreType.OPERATIONAL);
89         Futures.addCallback(wtx.submit(), new FutureCallback<Void>() {
90             @Override
91             public void onSuccess(Void result) {
92                 LOG.debug("topology initialization successful");
93             }
94
95             @Override
96             public void onFailure(Throwable t) {
97                 LOG.error("Unable to initialize netconf-topology, {}", t);
98             }
99         });
100
101         LOG.debug("Registering datastore listener");
102         datastoreListenerRegistration =
103                 dataBroker.registerDataTreeChangeListener(
104                         new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
105                                 TopologyUtil.createTopologyListPath(topologyId).child(Node.class)), this);
106
107
108     }
109
110     @Override
111     public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<Node>> collection) {
112         for (DataTreeModification<Node> change : collection) {
113             final DataObjectModification<Node> rootNode = change.getRootNode();
114             switch (rootNode.getModificationType()) {
115                 case SUBTREE_MODIFIED:
116                     LOG.debug("Config for node {} updated", TopologyUtil.getNodeId(rootNode.getIdentifier()));
117                     disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
118                     connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
119                     break;
120                 case WRITE:
121                     LOG.debug("Config for node {} created", TopologyUtil.getNodeId(rootNode.getIdentifier()));
122                     if (activeConnectors.containsKey(TopologyUtil.getNodeId(rootNode.getIdentifier()))) {
123                         LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..", TopologyUtil.getNodeId(rootNode.getIdentifier()));
124                         disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
125                     }
126                     connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
127                     break;
128                 case DELETE:
129                     LOG.debug("Config for node {} deleted", TopologyUtil.getNodeId(rootNode.getIdentifier()));
130                     disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
131                     break;
132             }
133         }
134     }
135
136     private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
137         final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
138         final InstanceIdentifier<NetworkTopology> networkTopologyId = InstanceIdentifier.builder(NetworkTopology.class).build();
139         wtx.merge(datastoreType, networkTopologyId, networkTopology);
140         final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
141         wtx.merge(datastoreType, networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);
142     }
143
144 }