5d88e18f11af8e00bb4953ccb4d944444c2d0864
[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.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.WriteTransaction;
24 import org.opendaylight.mdsal.common.api.CommitInfo;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
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 = dataBroker.registerDataTreeChangeListener(DataTreeIdentifier.create(
115             LogicalDatastoreType.CONFIGURATION, TopologyUtil.createTopologyListPath(topologyId).child(Node.class)),
116             this);
117     }
118
119     @Override
120     public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<Node>> collection) {
121         for (final DataTreeModification<Node> change : collection) {
122             final DataObjectModification<Node> rootNode = change.getRootNode();
123             switch (rootNode.getModificationType()) {
124                 case SUBTREE_MODIFIED:
125                     LOG.debug("Config for node {} updated", TopologyUtil.getNodeId(rootNode.getIdentifier()));
126                     disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
127                     connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
128                     break;
129                 case WRITE:
130                     LOG.debug("Config for node {} created", TopologyUtil.getNodeId(rootNode.getIdentifier()));
131                     if (activeConnectors.containsKey(TopologyUtil.getNodeId(rootNode.getIdentifier()))) {
132                         LOG.warn("RemoteDevice{{}} was already configured, reconfiguring..",
133                                 TopologyUtil.getNodeId(rootNode.getIdentifier()));
134                         disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
135                     }
136                     connectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()), rootNode.getDataAfter());
137                     break;
138                 case DELETE:
139                     LOG.debug("Config for node {} deleted", TopologyUtil.getNodeId(rootNode.getIdentifier()));
140                     disconnectNode(TopologyUtil.getNodeId(rootNode.getIdentifier()));
141                     break;
142                 default:
143                     LOG.debug("Unsupported modification type: {}.", rootNode.getModificationType());
144             }
145         }
146     }
147
148     private void initTopology(final WriteTransaction wtx, final LogicalDatastoreType datastoreType) {
149         final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
150         final InstanceIdentifier<NetworkTopology> networkTopologyId =
151                 InstanceIdentifier.builder(NetworkTopology.class).build();
152         wtx.merge(datastoreType, networkTopologyId, networkTopology);
153         final Topology topology = new TopologyBuilder().setTopologyId(new TopologyId(topologyId)).build();
154         wtx.merge(datastoreType,
155                 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(topologyId))), topology);
156     }
157
158 }