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