NETCONF event handling
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / listeners / 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
9 package org.opendaylight.transportpce.networkmodel.listeners;
10
11 import java.util.Objects;
12 import java.util.Optional;
13 import java.util.concurrent.TimeUnit;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
16 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
17 import org.opendaylight.transportpce.common.device.DeviceTransactionManager;
18 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.ChangeNotification;
19 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceListener;
20 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OtdrScanResult;
21 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.change.notification.Edit;
22 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks;
23 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacksKey;
24 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
25 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 public class DeviceListener implements OrgOpenroadmDeviceListener {
30
31     private static final Logger LOG = LoggerFactory.getLogger(DeviceListener.class);
32     /* TODO: value obtained from DeviceTransactionManagerImpl and increased due to the timeout error described in
33         JIRA TRNSPRTPCE-249. The increase had no effect.
34      */
35     private static final long GET_DATA_SUBMIT_TIMEOUT = 5000;
36     private static final TimeUnit MAX_DURATION_TO_SUBMIT_TIMEUNIT = TimeUnit.MILLISECONDS;
37     private final DeviceTransactionManager deviceTransactionManager;
38     private final String nodeId;
39
40     public DeviceListener(DeviceTransactionManager deviceTransactionManager, String nodeId) {
41         this.deviceTransactionManager = deviceTransactionManager;
42         this.nodeId = nodeId;
43     }
44
45     /**
46      * Callback for change-notification.
47      *
48      * @param notification ChangeNotification object
49      */
50     @Override
51     public void onChangeNotification(ChangeNotification notification) {
52
53         LOG.info("Notification {} received {}", ChangeNotification.QNAME, notification);
54         // NETCONF event notification handling
55         String deviceComponentChanged = null;
56         // Seems like there is only one edit in the NETCONF notification (from honeynode experience)
57         Edit edit = Objects.requireNonNull(notification.getEdit()).get(0);
58         deviceComponentChanged = Objects.requireNonNull(edit.getTarget()).getTargetType().getSimpleName();
59         // Only circuitPack type handled
60         switch (deviceComponentChanged) {
61             case "Interface":
62                 // do changes
63                 LOG.info("Interface modified on device {}", this.nodeId);
64                 break;
65             case "CircuitPacks":
66                 LOG.info("Circuit Pack modified on device {}", this.nodeId);
67                 // 1. Get the name of the component modified
68                 Iterable<InstanceIdentifier.PathArgument> pathArguments = edit.getTarget().getPathArguments();
69                 String cpackId = null;
70                 for (InstanceIdentifier.PathArgument pathArgument : pathArguments) {
71                     if (!pathArgument.toString().contains("CircuitPacks")) {
72                         LOG.warn("Path argument element doesnt reference a Circuit Pack");
73                         continue;
74                     }
75                     Pattern pattern = Pattern.compile("\\{(.*?)}", Pattern.DOTALL);
76                     Matcher matcher = pattern.matcher(pathArgument.toString());
77                     while (matcher.find()) {
78                         String cpackKey = matcher.group(1);
79                         Pattern pattern1 = Pattern.compile("=(.*)", Pattern.DOTALL);
80                         Matcher matcher1 = pattern1.matcher(cpackKey);
81                         while (matcher1.find()) {
82                             cpackId = matcher1.group(1);
83                         }
84                     }
85                 }
86                 // 2. Get new configuration of component from device
87                 if (cpackId == null) {
88                     LOG.warn("No Circuit pack id retrieved from NETCONF notification... aborting");
89                     break;
90                 }
91                 LOG.info("Circuit Pack {} modified on device {}", cpackId, this.nodeId);
92                 if (!this.deviceTransactionManager.isDeviceMounted(nodeId)) {
93                     LOG.error("Device {} not mounted yet", nodeId);
94                     break;
95                 }
96                 InstanceIdentifier<CircuitPacks> cpIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
97                         .child(CircuitPacks.class, new CircuitPacksKey(cpackId));
98                         /* Creating runnable to perform configuration retrieval and topology update in a new thread
99                         to avoid JIRA TRNSPRTCE-251 */
100                 Runnable handlenetconfEvent = new Runnable() {
101                     private CircuitPacks circuitPacks;
102
103                     public CircuitPacks getCircuitPacks() {
104                         return circuitPacks;
105                     }
106
107                     public void setCircuitPacks(CircuitPacks circuitPacks) {
108                         this.circuitPacks = circuitPacks;
109                     }
110
111                     @Override
112                     public void run() {
113                         Optional<CircuitPacks> cpacksOptional = deviceTransactionManager
114                                 .getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL, cpIID,
115                                         GET_DATA_SUBMIT_TIMEOUT, MAX_DURATION_TO_SUBMIT_TIMEUNIT);
116                         if (!cpacksOptional.isPresent()) {
117                             LOG.error("Couldnt read from device datastore");
118                             return;
119                         }
120                         setCircuitPacks(cpacksOptional.get());
121                         LOG.info("Component {} configuration: {}", getCircuitPacks().getCircuitPackName(),
122                                 getCircuitPacks());
123                         // 3. Update openroadm-topology
124                         // TODO
125                         // networkModelService.updateOpenRoadmNode(nodeId, getCircuitPacks());
126                     }
127                 };
128                 Thread thread = new Thread(handlenetconfEvent);
129                 thread.start();
130                 break;
131             default:
132                 // TODO: handle more component types --> it implies development on honeynode simulator
133                 LOG.warn("Component {} change not supported", deviceComponentChanged);
134         }
135
136     }
137
138     /**
139      * Callback for otdr-scan-result.
140      *
141      * @param notification OtdrScanResult object
142      */
143     @Override
144     public void onOtdrScanResult(OtdrScanResult notification) {
145
146         LOG.info("Notification {} received {}", OtdrScanResult.QNAME, notification);
147     }
148
149 }