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