blob: 2cdcc1a49349f537ff85c14d72a7ae46c41f887b [file] [log] [blame]
Alessio Giorgetti648b5382018-02-15 18:35:45 +01001/*
2 * Copyright 2017-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.drivers.lumentum;
18
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.Lists;
21
22import org.apache.commons.configuration.HierarchicalConfiguration;
23import org.apache.commons.configuration.XMLConfiguration;
24import org.apache.commons.lang3.StringUtils;
25
26import org.onosproject.drivers.utilities.XmlConfigParser;
27import org.onosproject.net.Port;
28import org.onosproject.net.PortNumber;
29import org.onosproject.net.DefaultAnnotations;
30import org.onosproject.net.SparseAnnotations;
31import org.onosproject.net.AnnotationKeys;
32import org.onosproject.net.Device;
33import org.onosproject.net.DeviceId;
34import org.onosproject.net.device.DefaultDeviceDescription;
35import org.onosproject.net.device.DefaultPortDescription;
36import org.onosproject.net.device.DeviceDescription;
37import org.onosproject.net.device.DeviceDescriptionDiscovery;
38import org.onosproject.net.device.DeviceService;
39import org.onosproject.net.device.PortDescription;
40import org.onosproject.net.driver.AbstractHandlerBehaviour;
41import org.onosproject.netconf.NetconfController;
42import org.onosproject.netconf.NetconfException;
43import org.onosproject.netconf.NetconfSession;
44import org.onosproject.netconf.NetconfDevice;
45
46import org.slf4j.Logger;
47
48import java.io.ByteArrayInputStream;
49import java.util.List;
50
51import static com.google.common.base.Preconditions.checkNotNull;
52import static org.slf4j.LoggerFactory.getLogger;
53
54/**
55 * Device description behaviour for Lumentum ROADM-A Whitebox devices using NETCONF.
56 */
57public class LumentumNetconfRoadmDiscovery
58 extends AbstractHandlerBehaviour implements DeviceDescriptionDiscovery {
59
60 private static final String PHYSICAL_PORT = "data.physical-ports.physical-port";
61
62 private static final String DN = "dn";
63 private static final String DN_PORT = "port=";
64 private static final String PORT_EXTENSION = "port-extension";
65 protected static final String OPTICAL_INPUT = "port-optical-input";
66 protected static final String OPTICAL_OUTPUT = "port-optical-output";
67 private static final String PORT_PLUGGABLE = "port-pluggable";
68 private static final String PORT_ETHERNET = "port-ethernet";
69
70 private static final String MAINTENANCE_STATE = "config.maintenance-state";
71 private static final String PORT_SPEED = "config.loteeth:port-speed";
72 private static final String IN_SERVICE = "in-service";
73 private static final String PORT_NAME = "entity-description";
74
75 private final Logger log = getLogger(getClass());
76
77 @Override
78 public DeviceDescription discoverDeviceDetails() {
79
80 // Some defaults values
81 String vendor = "Lumentum";
82 String hwVersion = "not loaded";
83 String swVersion = "not loaded";
84 String serialNumber = "not loaded";
85 String chassisId = "not loaded";
86
87 DeviceId deviceId = handler().data().deviceId();
88 DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
89 Device device = deviceService.getDevice(deviceId);
90
91 //Get the configuration from the device
92 if (device == null) {
93 log.error("Lumentum NETCONF - device object not found for {}", deviceId);
94 return null;
95 }
96
97 NetconfSession session = getNetconfSession();
98
99 if (session == null) {
100 log.error("Lumentum NETCONF - session not found for {}", deviceId);
101 return null;
102 }
103
104 //Retrieve system information from ietf-system
105 StringBuilder systemRequestBuilder = new StringBuilder();
106 systemRequestBuilder.append("<system-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-system\">");
107 systemRequestBuilder.append("</system-state>");
108
109 try {
110 String reply = session.get(systemRequestBuilder.toString(), null);
111 log.info("Lumentum NETCONF - session.get reply {}", reply);
112
113 XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(reply);
114
115 vendor = xconf.getString("data.system-state.platform.machine", vendor);
116 swVersion = xconf.getString("data.system-state.platform.os-version", swVersion);
117 } catch (NetconfException e) {
118 log.error("Lumentum NETCONF error in session.get with filter <system-state>", e);
119 }
120
121 //Retrieve system information
122 StringBuilder chassisRequestBuilder = new StringBuilder();
123 chassisRequestBuilder.append("<chassis-list xmlns=\"http://www.lumentum.com/lumentum-ote-equipment\">");
124 chassisRequestBuilder.append("</chassis-list>");
125
126 try {
127 String reply = session.get(chassisRequestBuilder.toString(), null);
128 log.info("Lumentum NETCONF - session.get reply {}", reply);
129
130 XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(reply);
131
132 hwVersion = xconf.getString("data.chassis-list.chassis.state.loteq:hardware-rev", hwVersion);
133 serialNumber = xconf.getString("data.chassis-list.chassis.state.loteq:serial-no", serialNumber);
134 chassisId = xconf.getString("data.chassis-list.chassis.dn", chassisId);
135
136 } catch (NetconfException e) {
137 log.error("Lumentum NETCONF error in session.get", e);
138 }
139
140 //Upon connection of a new devices all pre-configured connections are removed
141 //TODO: do not cancel and import already configured connections
142 rpcRemoveAllConnections("1");
143 rpcRemoveAllConnections("2");
144
145 log.info("TYPE {}", Device.Type.ROADM);
146 log.info("VENDOR {}", vendor);
147 log.info("HWVERSION {}", hwVersion);
148 log.info("SWVERSION {}", swVersion);
149 log.info("SERIAL {}", serialNumber);
150 log.info("CHASSISID {}", chassisId);
151
152 //Return the Device Description
153 return new DefaultDeviceDescription(deviceId.uri(), Device.Type.ROADM,
154 vendor, hwVersion, swVersion, serialNumber,
155 device.chassisId(), (SparseAnnotations) device.annotations());
156 }
157
158 @Override
159 public List<PortDescription> discoverPortDetails() {
160 String reply;
161 DeviceId deviceId = handler().data().deviceId();
162 DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
163 Device device = deviceService.getDevice(deviceId);
164
165 //Get the configuration from the device
166 if (device == null) {
167 log.error("Lumentum NETCONF - device object not found for {}", deviceId);
168 return ImmutableList.of();
169 }
170
171 NetconfSession session = getNetconfSession();
172
173 if (session == null) {
174 log.error("Lumentum NETCONF - session not found for {}", deviceId);
175 return ImmutableList.of();
176 }
177
178 StringBuilder requestBuilder = new StringBuilder();
179 requestBuilder.append("<physical-ports xmlns=\"http://www.lumentum.com/lumentum-ote-port\" ");
180 requestBuilder.append("xmlns:lotep=\"http://www.lumentum.com/lumentum-ote-port\" ");
181 requestBuilder.append("xmlns:lotepopt=\"http://www.lumentum.com/lumentum-ote-port-optical\" ");
182 requestBuilder.append("xmlns:loteeth=\"http://www.lumentum.com/lumentum-ote-port-ethernet\">");
183 requestBuilder.append("</physical-ports>");
184
185 try {
186 reply = session.get(requestBuilder.toString(), null);
187 } catch (NetconfException e) {
188 log.error("Lumentum NETCONF - " +
189 "discoverPortDetails failed to retrieve port details {}", handler().data().deviceId(), e);
190 return ImmutableList.of();
191 }
192
193 List<PortDescription> descriptions = parseLumentumRoadmPorts(XmlConfigParser.
194 loadXml(new ByteArrayInputStream(reply.getBytes())));
195
196 return ImmutableList.copyOf(descriptions);
197 }
198
199 /**
200 * Parses a configuration and returns a set of ports.
201 *
202 * @param cfg a hierarchical configuration
203 * @return a list of port descriptions
204 */
205 protected List<PortDescription> parseLumentumRoadmPorts(HierarchicalConfiguration cfg) {
206 List<PortDescription> portDescriptions = Lists.newArrayList();
207 List<HierarchicalConfiguration> ports = cfg.configurationsAt(PHYSICAL_PORT);
208
209 ports.stream().forEach(pcfg -> {
210
211 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
212
213 //Load port number
214 PortNumber portNum = PortNumber.portNumber(
215 pcfg.getString(DN).substring(pcfg.getString(DN).lastIndexOf(DN_PORT) + 5));
216
217 //Load port state
218 String maintenanceState = pcfg.getString(MAINTENANCE_STATE);
219 boolean isEnabled = ((maintenanceState != null) && (maintenanceState).equals(IN_SERVICE));
220
221 //Load port type (FIBER/COPPER)
222 Port.Type type = null;
223 for (Object o : pcfg.getList(PORT_EXTENSION)) {
224 String s = (String) o;
225 if (s.equals(OPTICAL_INPUT) || s.equals(OPTICAL_OUTPUT)) {
226 type = Port.Type.FIBER;
227
228 } else if (s.equals(PORT_ETHERNET) || s.equals(PORT_PLUGGABLE)) {
229 type = Port.Type.COPPER;
230 }
231 }
232
233 //Load port speed of Ethernet interface, expressed in Mb/s
234 Long speed = 0L; //should be the speed of optical port
235 if (type != null) {
236 if (type.equals(Port.Type.COPPER)) {
237 String speedString = pcfg.getString(PORT_SPEED);
238 if (speedString != null) {
239 speed = Long.parseLong(speedString.substring(speedString.lastIndexOf("speed_") + 6,
240 speedString.lastIndexOf("Mb")));
241 } else {
242 log.error("Lumentum NETCONF - Port speed of Ethernet port not correctly loaded");
243 }
244 }
245 } else {
246 log.error("Port Type not correctly loaded");
247 }
248
249 //Load other information
250 pcfg.getKeys().forEachRemaining(k -> {
251 if (!k.contains(DN) && !k.contains(PORT_SPEED) && !k.contains(PORT_EXTENSION)
252 && !k.contains(MAINTENANCE_STATE)) {
253 String value = pcfg.getString(k);
254 if (!value.isEmpty()) {
255 k = StringUtils.replaceEach(k, new String[]{"loteeth:", "lotep:",
256 "lotepopt:", "config.", "=", ":",
257 "state."},
258 new String[]{"", "", "", "", "", "", ""});
259
260 annotations.set(k, value);
261
262 //To visualize port name in the ROADM app GUI
263 if (k.equals(PORT_NAME)) {
264 annotations.set(AnnotationKeys.PORT_NAME, value);
265 }
266
267 }
268 }
269 });
270
271 log.debug("Lumentum NETCONF - retrieved port {},{},{},{},{}",
272 portNum, isEnabled, type, speed, annotations.build());
273
Ray Milkeyf031e302018-09-07 10:07:24 -0700274 DefaultPortDescription.Builder portDescriptionBuilder = DefaultPortDescription.builder();
275 portDescriptionBuilder.withPortNumber(portNum)
276 .isEnabled(isEnabled)
277 .type(type)
278 .portSpeed(speed)
279 .annotations(annotations.build());
280
281 portDescriptions.add(portDescriptionBuilder.build());
Alessio Giorgetti648b5382018-02-15 18:35:45 +0100282 });
283
284 return portDescriptions;
285 }
286
287 //Following Lumentum documentation rpc operation to delete all connections
288 private boolean rpcRemoveAllConnections(String module) {
289 StringBuilder stringBuilder = new StringBuilder();
290 stringBuilder.append("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">" + "\n");
291 stringBuilder.append(
292 "<remove-all-connections xmlns=\"http://www.lumentum.com/lumentum-ote-connection\">" + "\n");
293 stringBuilder.append("<dn>ne=1;chassis=1;card=1;module=" + module + "</dn>" + "\n");
294 stringBuilder.append("</remove-all-connections>" + "\n");
295 stringBuilder.append("</rpc>" + "\n");
296
297 return editCrossConnect(stringBuilder.toString());
298 }
299
300 private boolean editCrossConnect(String xcString) {
301 NetconfSession session = getNetconfSession();
302
303 if (session == null) {
304 log.error("Lumentum NETCONF - session not found for {}", handler().data().deviceId());
305 return false;
306 }
307
308 try {
309 return session.editConfig(xcString);
310 } catch (NetconfException e) {
311 log.error("Failed to edit the CrossConnect edid-cfg for device {}",
312 handler().data().deviceId(), e);
313 log.debug("Failed configuration {}", xcString);
314 return false;
315 }
316 }
317
318 private NetconfSession getNetconfSession() {
319 NetconfController controller = checkNotNull(handler().get(NetconfController.class));
320 NetconfDevice ncDevice = controller.getNetconfDevice(handler().data().deviceId());
321
322 if (ncDevice == null) {
323 log.error("Lumentum NETCONF - device not found for {}", handler().data().deviceId());
324 return null;
325 }
326
327 return ncDevice.getSession();
328 }
329}