977adc71278f6e339bf07c65d6441de9b81fb4fa
[transportpce.git] / inventory / src / main / java / org / opendaylight / transportpce / inventory / listener / DeviceListener.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.inventory.listener;
9
10 import java.util.Collection;
11 import java.util.List;
12 import java.util.concurrent.ExecutionException;
13 import java.util.stream.Collectors;
14 import org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType;
15 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
16 import org.opendaylight.mdsal.binding.api.DataTreeModification;
17 import org.opendaylight.transportpce.common.StringConstants;
18 import org.opendaylight.transportpce.inventory.DeviceInventory;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev231024.ConnectionOper.ConnectionStatus;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNode;
21 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 /**
26  * This class implements the {@link DataTreeChangeListener} on a {@link Node}.
27  * This listener should be registered on a netconf topology node.
28  */
29 public class DeviceListener implements DataTreeChangeListener<Node> {
30
31     private static final Logger LOG = LoggerFactory.getLogger(DeviceListener.class);
32     private final DeviceInventory deviceInventory;
33
34     /**
35      * Default constructor invoked by blueprint injects {@link DeviceInventory} as a persistence layer.
36      *
37      * @param deviceInventory reference to the {@link DeviceInventory}
38      */
39     public DeviceListener(DeviceInventory deviceInventory) {
40         this.deviceInventory = deviceInventory;
41     }
42
43     @Override
44     public void onDataTreeChanged(Collection<DataTreeModification<Node>> changes) {
45         //LOG.debug("testing np1: {}", changes.toString());
46         String openROADMversion = "";
47         List<DataTreeModification<Node>> changesWithoutDefaultNetconfNode = getRealDevicesOnly(changes);
48         for (DataTreeModification<Node> device : changesWithoutDefaultNetconfNode) {
49             String nodeId = device.getRootNode().getDataAfter().key().getNodeId().getValue();
50             NetconfNode netconfNode = device.getRootNode().getDataAfter().augmentation(NetconfNode.class);
51             ConnectionStatus connectionStatus = netconfNode.getConnectionStatus();
52             long count = netconfNode.getAvailableCapabilities().getAvailableCapability().stream()
53                     .filter(cp -> cp.getCapability().contains(StringConstants.OPENROADM_DEVICE_MODEL_NAME))
54                     .count();
55             LOG.debug("DL Modification Type {}", device.getRootNode().getModificationType().toString());
56             LOG.debug("DL Capability Count {}", count);
57             LOG.debug("DL Connection Status {}", connectionStatus);
58             LOG.debug("DL device.getRootNode().getDataBefore() {}", device.getRootNode().getDataBefore());
59             LOG.debug("DL device.getRootNode().getDataAfter() {}", device.getRootNode().getDataAfter());
60
61             if (isCreate(device)) {
62                 LOG.info("Node {} was created", nodeId);
63                 try {
64                     processModifiedSubtree(nodeId, netconfNode, openROADMversion);
65                 } catch (InterruptedException | ExecutionException e) {
66                     LOG.error("something wrong when creating node {}", nodeId, e);
67                 }
68             } else if (isDelete(device)) {
69                 LOG.info("Node {} was deleted", nodeId);
70             }
71         }
72     }
73
74     /**
75      * Handles the {@link ModificationType#SUBTREE_MODIFIED} case.
76      * If the changed node has.
77      *
78      * @param nodeId      device id
79      * @param netconfNode netconf node
80      * @throws InterruptedException may be thrown if there is a problem getting the device from
81      *                              datastore
82      * @throws ExecutionException   may be thrown if there is a problem getting the device from datastore
83      */
84     private void processModifiedSubtree(String nodeId, NetconfNode netconfNode, String openROADMversion)
85             throws InterruptedException, ExecutionException {
86         ConnectionStatus connectionStatus = netconfNode.getConnectionStatus();
87
88         long count = netconfNode.getAvailableCapabilities().getAvailableCapability().stream()
89                 .filter(cp -> cp.getCapability().contains(StringConstants.OPENROADM_DEVICE_MODEL_NAME))
90                 .count();
91
92         if (count < 1) {
93             LOG.info("No {} capable device was found", StringConstants.OPENROADM_DEVICE_MODEL_NAME);
94             return;
95         }
96         if (ConnectionStatus.Connected.equals(connectionStatus)) {
97             LOG.info("DL The device is in {} state", connectionStatus);
98             deviceInventory.initializeDevice(nodeId, openROADMversion);
99         } else if (ConnectionStatus.Connecting.equals(connectionStatus)
100                 || ConnectionStatus.UnableToConnect.equals(connectionStatus)) {
101             LOG.info("DL The device is in {} state", connectionStatus);
102         } else {
103             LOG.warn("DL Invalid connection status {}", connectionStatus);
104         }
105
106     }
107
108     /**
109      * Filters the {@link StringConstants#DEFAULT_NETCONF_NODEID} nodes from the provided {@link Collection}.
110      *
111      */
112     private static List<DataTreeModification<Node>> getRealDevicesOnly(Collection<DataTreeModification<Node>> changes) {
113         return changes.stream()
114                 .filter(change -> (change.getRootNode().getDataAfter() != null
115                         && !StringConstants.DEFAULT_NETCONF_NODEID
116                         .equalsIgnoreCase(change.getRootNode().getDataAfter().key().getNodeId().getValue())
117                         && change.getRootNode().getDataAfter().augmentation(NetconfNode.class) != null)
118                         || (change.getRootNode().getDataBefore() != null
119                         && !StringConstants.DEFAULT_NETCONF_NODEID.equalsIgnoreCase(
120                         change.getRootNode().getDataBefore().key().getNodeId().getValue())
121                         && change.getRootNode().getDataBefore().augmentation(NetconfNode.class) != null
122
123                 )).collect(Collectors.toList());
124     }
125
126     /**
127      * In the filtered collection checks if the change is a new write.
128      *
129      */
130     private static boolean isCreate(DataTreeModification<Node> change) {
131         return change.getRootNode().getModificationType().toString().equalsIgnoreCase("WRITE");
132     }
133
134     /**
135      * In the filtered collection checks if the node was deleted.
136      *
137      */
138     private static boolean isDelete(DataTreeModification<Node> change) {
139         return change.getRootNode().getDataBefore() != null && change.getRootNode().getDataAfter() == null
140                 && ModificationType.DELETE.equals(change.getRootNode().getModificationType());
141     }
142 }