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