2 * Copyright © 2017 AT&T and others. All rights reserved.
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
8 package org.opendaylight.transportpce.renderer;
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;
16 import java.util.Collection;
17 import java.util.List;
19 import java.util.stream.Collectors;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
23 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType;
24 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
25 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
26 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
27 import org.opendaylight.controller.md.sal.binding.api.MountPoint;
28 import org.opendaylight.controller.md.sal.binding.api.MountPointService;
29 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
32 import org.opendaylight.transportpce.renderer.listeners.AlarmNotificationListener;
33 import org.opendaylight.transportpce.renderer.listeners.DeOperationsListener;
34 import org.opendaylight.transportpce.renderer.listeners.DeviceListener;
35 import org.opendaylight.transportpce.renderer.listeners.LldpListener;
36 import org.opendaylight.transportpce.renderer.listeners.TcaListener;
37 import org.opendaylight.transportpce.renderer.mapping.PortMapping;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev161014.AlarmNotification;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev161014.OrgOpenroadmAlarmListener;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.de.operations.rev161014.OrgOpenroadmDeOperationsListener;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceListener;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.lldp.rev161014.OrgOpenroadmLldpListener;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.tca.rev161014.OrgOpenroadmTcaListener;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.CreateSubscriptionInputBuilder;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.NotificationsService;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.notification._1._0.rev080714.StreamNameType;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
57 import org.opendaylight.yangtools.concepts.ListenerRegistration;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
63 public class RendererNotificationsImpl implements DataTreeChangeListener<Node> {
65 private final DataBroker dataBroker;
66 private final MountPointService mountService;
67 private static final Logger LOG = LoggerFactory.getLogger(RendererNotificationsImpl.class);
68 private ListenerRegistration<RendererNotificationsImpl> dataTreeChangeListenerRegistration;
70 private final Set<String> currentMountedDevice;
71 public static final InstanceIdentifier<Topology> NETCONF_TOPO_IID = InstanceIdentifier.create(NetworkTopology.class)
72 .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName())));
74 LoadingCache<String, KeyedInstanceIdentifier<Node, NodeKey>> mountIds = CacheBuilder.newBuilder().maximumSize(20)
75 .build(new CacheLoader<String, KeyedInstanceIdentifier<Node, NodeKey>>() {
77 public KeyedInstanceIdentifier<Node, NodeKey> load(final String key) {
78 return NETCONF_TOPO_IID.child(Node.class, new NodeKey(new NodeId(key)));
82 public RendererNotificationsImpl(final DataBroker dataBroker, final MountPointService mountService,
83 Set<String> currentMountedDevice) {
84 this.dataBroker = dataBroker;
85 this.mountService = mountService;
86 this.currentMountedDevice = currentMountedDevice;
87 if (mountService == null) {
88 LOG.error("Mount service is null");
91 if (dataBroker != null) {
92 this.dataTreeChangeListenerRegistration = dataBroker.registerDataTreeChangeListener(
93 new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, NETCONF_TOPO_IID.child(Node.class)), this);
97 private void registerNotificationListener(final NodeId nodeId) {
99 MountPoint mountPoint = PortMapping.getDeviceMountPoint(nodeId.getValue(), mountService);
101 // Register notification service
102 final Optional<NotificationService> notificationService = mountPoint.getService(
103 NotificationService.class);
104 if (!notificationService.isPresent()) {
105 LOG.error("Failed to get RpcService for node {}", nodeId.getValue());
108 final OrgOpenroadmAlarmListener alarmListener;
109 alarmListener = new AlarmNotificationListener();
110 LOG.info("Registering notification listener on {} for node: {}", AlarmNotification.QNAME, nodeId);
111 // Register notification listener
114 final OrgOpenroadmDeOperationsListener deOperationsListener;
115 deOperationsListener = new DeOperationsListener();
116 LOG.info("Registering notification listener on OrgOpenroadmDeOperationsListener for node: {}", nodeId);
117 // Register notification listener
120 final OrgOpenroadmDeviceListener deviceListener;
121 deviceListener = new DeviceListener();
122 LOG.info("Registering notification listener on OrgOpenroadmDeviceListener for node: {}", nodeId);
123 // Register notification listener
126 final OrgOpenroadmLldpListener lldpListener;
127 lldpListener = new LldpListener();
128 LOG.info("Registering notification listener on OrgOpenroadmLldpListener for node: {}", nodeId);
129 // Register notification listener
132 final OrgOpenroadmTcaListener tcaListener;
133 tcaListener = new TcaListener();
134 LOG.info("Registering notification listener on OrgOpenroadmTcaListener for node: {}", nodeId);
135 // Register notification listener
138 // Listening to NETCONF datastream
139 final String streamName = "NETCONF";
140 final Optional<RpcConsumerRegistry> service = mountPoint.getService(RpcConsumerRegistry.class);
141 if (!service.isPresent()) {
142 LOG.error("Failed to get RpcService for node {}", nodeId.getValue());
145 final NotificationsService rpcService = service.get().getRpcService(NotificationsService.class);
146 final CreateSubscriptionInputBuilder createSubscriptionInputBuilder = new CreateSubscriptionInputBuilder();
147 createSubscriptionInputBuilder.setStream(new StreamNameType(streamName));
148 LOG.info("Triggering notification stream {} for node {}", streamName, nodeId);
152 public void close() {
153 LOG.info("RenderernotificationsImpl Closed");
154 // Clean up the Data Change Listener registration
155 if (dataTreeChangeListenerRegistration != null) {
156 dataTreeChangeListenerRegistration.close();
161 public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
163 for (DataTreeModification<Node> change : changes) {
165 DataObjectModification<Node> rootNode = change.getRootNode();
166 NetconfNode nnode = null;
167 String nodeId = new String();
168 if (rootNode.getDataAfter() != null) {
169 nnode = Preconditions.checkNotNull(rootNode.getDataAfter().getAugmentation(NetconfNode.class),
170 "Node not connected via Netconf protocol");
171 nodeId = rootNode.getDataAfter().getKey().getNodeId().getValue();
174 if (rootNode.getModificationType() == ModificationType.WRITE) {
175 LOG.info("Node added " + nodeId);
177 } else if (rootNode.getModificationType() == ModificationType.SUBTREE_MODIFIED) {
179 LOG.info("Node modified " + nodeId);
180 ConnectionStatus csts = nnode.getConnectionStatus();
184 LOG.info("NETCONF Node: {} is fully connected", nodeId);
185 List<String> capabilities = nnode.getAvailableCapabilities().getAvailableCapability()
186 .stream().map(cp -> cp.getCapability()).collect(Collectors.toList());
187 LOG.info("Capabilities: {}", capabilities);
189 * TODO: check for required
190 * capabilities to listen for notifications
192 registerNotificationListener(rootNode.getDataAfter(). getNodeId());
193 currentMountedDevice.add(nodeId);
194 new PortMapping(dataBroker, mountService, nodeId).createMappingData();
198 LOG.info("NETCONF Node: {} was disconnected", nodeId);
201 case UnableToConnect: {
202 LOG.info("NETCONF Node: {} connection failed", nodeId);
206 LOG.warn("Unexpected connection status " + csts.getName());
208 } else if (rootNode.getModificationType() == ModificationType.DELETE) {
209 LOG.info("Node removed " + nodeId);
210 currentMountedDevice.remove(nodeId);