6231c88732cd4b41335ee55daa96c0026a24cbd4
[transportpce.git] / renderer / src / main / java / org / opendaylight / transportpce / renderer / RendererNotificationsImpl.java
1 /*
2  * Copyright © 2017 AT&T 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.transportpce.renderer;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.cache.CacheBuilder;
13 import com.google.common.cache.CacheLoader;
14 import com.google.common.cache.LoadingCache;
15 import java.util.Collection;
16 import java.util.List;
17 import java.util.Set;
18 import java.util.stream.Collectors;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
21 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
23 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
24 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
25 import org.opendaylight.controller.md.sal.binding.api.MountPoint;
26 import org.opendaylight.controller.md.sal.binding.api.MountPointService;
27 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
30 import org.opendaylight.transportpce.renderer.listeners.AlarmNotificationListener;
31 import org.opendaylight.transportpce.renderer.listeners.DeOperationsListener;
32 import org.opendaylight.transportpce.renderer.listeners.DeviceListener;
33 import org.opendaylight.transportpce.renderer.listeners.LldpListener;
34 import org.opendaylight.transportpce.renderer.listeners.TcaListener;
35 import org.opendaylight.transportpce.renderer.mapping.PortMapping;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev161014.AlarmNotification;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev161014.OrgOpenroadmAlarmListener;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.de.operations.rev161014.OrgOpenroadmDeOperationsListener;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceListener;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.OrgOpenroadmLldpListener;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.tca.rev161014.OrgOpenroadmTcaListener;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
55 import org.opendaylight.yangtools.concepts.ListenerRegistration;
56 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
57 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61 public class RendererNotificationsImpl implements DataTreeChangeListener<Node> {
62
63     private final DataBroker dataBroker;
64     private final MountPointService mountService;
65     private static final Logger LOG = LoggerFactory.getLogger(RendererNotificationsImpl.class);
66     private ListenerRegistration<RendererNotificationsImpl> dataTreeChangeListenerRegistration;
67
68     private final Set<String> currentMountedDevice;
69     public static final InstanceIdentifier<Topology> NETCONF_TOPO_IID = InstanceIdentifier.create(NetworkTopology.class)
70         .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())));
71
72     LoadingCache<String, KeyedInstanceIdentifier<Node, NodeKey>> mountIds = CacheBuilder.newBuilder().maximumSize(20)
73         .build(new CacheLoader<String, KeyedInstanceIdentifier<Node, NodeKey>>() {
74             @Override
75             public KeyedInstanceIdentifier<Node, NodeKey> load(final String key) {
76                 return NETCONF_TOPO_IID.child(Node.class, new NodeKey(new NodeId(key)));
77             }
78         });
79
80     public RendererNotificationsImpl(final DataBroker dataBroker, final MountPointService mountService,
81         Set<String> currentMountedDevice) {
82         this.dataBroker = dataBroker;
83         this.mountService = mountService;
84         this.currentMountedDevice = currentMountedDevice;
85         if (mountService == null) {
86             LOG.error("Mount service is null");
87
88         }
89         if (dataBroker != null) {
90             this.dataTreeChangeListenerRegistration = dataBroker.registerDataTreeChangeListener(
91                 new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, NETCONF_TOPO_IID.child(Node.class)), this);
92         }
93     }
94
95     private void registerNotificationListener(final NodeId nodeId) {
96
97         MountPoint mountPoint = PortMapping.getDeviceMountPoint(nodeId.getValue(), this.mountService);
98
99         // Register notification service
100         final Optional<NotificationService> notificationService = mountPoint.getService(
101             NotificationService.class);
102         if (!notificationService.isPresent()) {
103             LOG.error("Failed to get RpcService for node {}", nodeId.getValue());
104         }
105
106         final OrgOpenroadmAlarmListener alarmListener;
107         alarmListener = new AlarmNotificationListener();
108         LOG.info("Registering notification listener on {} for node: {}", AlarmNotification.QNAME, nodeId);
109         // Register notification listener
110
111         final OrgOpenroadmDeOperationsListener deOperationsListener;
112         deOperationsListener = new DeOperationsListener();
113         LOG.info("Registering notification listener on OrgOpenroadmDeOperationsListener for node: {}", nodeId);
114         // Register notification listener
115
116         final OrgOpenroadmDeviceListener deviceListener;
117         deviceListener = new DeviceListener();
118         LOG.info("Registering notification listener on OrgOpenroadmDeviceListener for node: {}", nodeId);
119         // Register notification listener
120
121         final OrgOpenroadmLldpListener lldpListener;
122         lldpListener = new LldpListener();
123         LOG.info("Registering notification listener on OrgOpenroadmLldpListener for node: {}", nodeId);
124         // Register notification listener
125
126         final OrgOpenroadmTcaListener tcaListener;
127         tcaListener = new TcaListener();
128         LOG.info("Registering notification listener on OrgOpenroadmTcaListener for node: {}", nodeId);
129         // Register notification listener
130
131         // Listening to NETCONF datastream
132         final String streamName = "NETCONF";
133         final Optional<RpcConsumerRegistry> service = mountPoint.getService(RpcConsumerRegistry.class);
134         if (!service.isPresent()) {
135             LOG.error("Failed to get RpcService for node {}", nodeId.getValue());
136         }
137
138         final NotificationsService rpcService = service.get().getRpcService(NotificationsService.class);
139         final CreateSubscriptionInputBuilder createSubscriptionInputBuilder = new CreateSubscriptionInputBuilder();
140         createSubscriptionInputBuilder.setStream(new StreamNameType(streamName));
141         LOG.info("Triggering notification stream {} for node {}", streamName, nodeId);
142
143     }
144
145     public void close() {
146         LOG.info("RenderernotificationsImpl Closed");
147         // Clean up the Data Change Listener registration
148         if (this.dataTreeChangeListenerRegistration != null) {
149             this.dataTreeChangeListenerRegistration.close();
150         }
151     }
152
153     @Override
154     public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
155
156         for (DataTreeModification<Node> change : changes) {
157
158             DataObjectModification<Node> rootNode = change.getRootNode();
159             NetconfNode nnode = null;
160             String nodeId = new String();
161             if (rootNode.getDataAfter() != null) {
162                 nnode = Preconditions.checkNotNull(rootNode.getDataAfter().getAugmentation(NetconfNode.class),
163                     "Node not connected via Netconf protocol");
164                 nodeId = rootNode.getDataAfter().getKey().getNodeId().getValue();
165             }
166
167             if (rootNode.getModificationType() == ModificationType.DELETE) {
168                 String nodeid = rootNode.getDataBefore().getKey().getNodeId().getValue();
169                 LOG.info("Node {} removed...", nodeid);
170                 this.currentMountedDevice.remove(nodeid);
171                 new PortMapping(this.dataBroker, this.mountService, nodeid).deleteMappingData();
172             }
173
174             if (nnode != null) {
175                 if (nodeId.equals("controller-config")) {
176                     // We shouldn't process controller-config as an OpenROAM device
177                     LOG.info("{} ignored: org-openroadm-device advertised but not a real ROADM device", nodeId);
178                     return;
179                 }
180                 if ((rootNode.getModificationType() == ModificationType.WRITE) ||
181                         (rootNode.getModificationType() == ModificationType.SUBTREE_MODIFIED)) {
182                     LOG.info("Node added or modified {}", nodeId);
183                     ConnectionStatus csts = nnode.getConnectionStatus();
184
185                     switch (csts) {
186                         case Connected: {
187                             LOG.info("NETCONF Node: {} is fully connected", nodeId);
188                             List<String> capabilities = nnode.getAvailableCapabilities().getAvailableCapability()
189                                 .stream().map(cp -> cp.getCapability()).collect(Collectors.toList());
190                             LOG.info("Capabilities: {}", capabilities);
191                             /*
192                              * TODO: check for required capabilities to listen
193                              * for notifications
194                              */
195                             registerNotificationListener(rootNode.getDataAfter().getNodeId());
196                             this.currentMountedDevice.add(nodeId);
197                             new PortMapping(this.dataBroker, this.mountService, nodeId).createMappingData();
198                             break;
199                         }
200                         case Connecting: {
201                             LOG.info("NETCONF Node: {} is (dis)connecting", nodeId);
202                             break;
203                         }
204                         case UnableToConnect: {
205                             LOG.info("NETCONF Node: {} connection failed", nodeId);
206                             break;
207                         }
208                         default:
209                             LOG.warn("Unexpected connection status {}", csts.getName());
210                     }
211                 }
212             }
213         }
214         LOG.info("Netconf devices currently mounted are : {}", this.currentMountedDevice.toString());
215     }
216 }