Ramon Casellas | 99c1625 | 2019-05-31 14:29:00 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018-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 | * This work was partially supported by EC H2020 project METRO-HAUL (761727). |
| 17 | */ |
| 18 | package org.onosproject.drivers.odtn.openroadm; |
| 19 | |
| 20 | import static com.google.common.base.Preconditions.checkNotNull; |
| 21 | |
| 22 | import com.google.common.collect.ImmutableList; |
| 23 | import java.util.ArrayList; |
| 24 | import java.util.HashMap; |
| 25 | import java.util.List; |
| 26 | import java.util.Map; |
| 27 | import org.apache.commons.configuration.HierarchicalConfiguration; |
| 28 | import org.apache.commons.configuration.XMLConfiguration; |
| 29 | import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine; |
| 30 | import org.onlab.packet.ChassisId; |
| 31 | import org.onlab.util.Frequency; |
| 32 | import org.onosproject.drivers.utilities.XmlConfigParser; |
| 33 | import org.onosproject.net.AnnotationKeys; |
| 34 | import org.onosproject.net.ChannelSpacing; |
| 35 | import org.onosproject.net.DefaultAnnotations; |
| 36 | import org.onosproject.net.OchSignal; |
| 37 | import org.onosproject.net.OduSignalType; |
| 38 | import org.onosproject.net.PortNumber; |
| 39 | import org.onosproject.net.device.DefaultDeviceDescription; |
| 40 | import org.onosproject.net.device.DeviceDescription; |
| 41 | import org.onosproject.net.device.DeviceDescriptionDiscovery; |
| 42 | import org.onosproject.net.device.PortDescription; |
| 43 | import org.onosproject.net.intent.OpticalPathIntent; |
| 44 | import org.onosproject.net.optical.device.OchPortHelper; |
| 45 | import org.onosproject.net.optical.device.OmsPortHelper; |
| 46 | import org.onosproject.netconf.NetconfDevice; |
| 47 | import org.onosproject.netconf.NetconfException; |
| 48 | import org.onosproject.netconf.NetconfSession; |
| 49 | |
| 50 | import java.util.concurrent.ExecutionException; |
| 51 | /** |
| 52 | * Driver Implementation of the DeviceDescrption discovery for OpenROADM. |
| 53 | */ |
| 54 | public class OpenRoadmDeviceDescription extends OpenRoadmNetconfHandlerBehaviour |
| 55 | implements DeviceDescriptionDiscovery { |
| 56 | |
| 57 | // These annotations are added to the device and ports |
| 58 | public final class AnnotationKeys { |
| 59 | public static final String OPENROADM_NODEID = "openroadm-node-id"; |
| 60 | public static final String OPENROADM_CIRCUIT_PACK_NAME = |
| 61 | "openroadm-circuit-pack-name"; |
| 62 | public static final String OPENROADM_PORT_NAME = "openroadm-port-name"; |
| 63 | public static final String OPENROADM_PARTNER_CIRCUIT_PACK_NAME = |
| 64 | "openroadm-partner-circuit-pack-name"; |
| 65 | public static final String OPENROADM_PARTNER_PORT_NAME = |
| 66 | "openroadm-partner-port-name"; |
| 67 | public static final String OPENROADM_LOGICAL_CONNECTION_POINT = |
| 68 | "openroadm-logical-connection-point"; |
| 69 | private AnnotationKeys() { |
| 70 | // utility class |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | public static final ChannelSpacing CHANNEL_SPACING = |
| 75 | ChannelSpacing.CHL_50GHZ; |
| 76 | |
| 77 | |
| 78 | /* |
| 79 | * The following 2 values are not specified by the OpenROADM standard, |
| 80 | * but they are a reasonable default for a tunable C-band, defined from |
| 81 | * Channel C1 at 191.35 to C96 at 196.10 GHz (for a spacing at 50GHz) |
| 82 | */ |
| 83 | public static final Frequency START_CENTER_FREQ = Frequency.ofGHz(191_350); |
| 84 | public static final Frequency STOP_CENTER_FREQ = Frequency.ofGHz(196_100); |
| 85 | |
| 86 | |
| 87 | public static final String OPENROADM_DEVICE_OPEN = // |
| 88 | "<org-openroadm-device xmlns=\"http://org/openroadm/device\">"; |
| 89 | public static final String OPENROADM_DEVICE_CLOSE = // |
| 90 | "</org-openroadm-device>"; |
| 91 | |
| 92 | |
| 93 | /** |
| 94 | * Builds a request to get OpenRoadm Device main node (within root). |
| 95 | * |
| 96 | * @param nodeTag the tag with the name to get e.g. <info/> |
| 97 | * |
| 98 | * @return A string with the Netconf RPC for a get with subtree info |
| 99 | */ |
| 100 | private String getDeviceXmlNodeBuilder(final String nodeTag) { |
| 101 | StringBuilder filter = new StringBuilder(); |
| 102 | filter.append(OPENROADM_DEVICE_OPEN); |
| 103 | filter.append(nodeTag); |
| 104 | filter.append(OPENROADM_DEVICE_CLOSE); |
| 105 | return filteredGetBuilder(filter.toString()); |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * Builds a request to get Device details (<info>). |
| 110 | * |
| 111 | * @return A string with the Netconf RPC for a get with subtree info |
| 112 | */ |
| 113 | private String getDeviceDetailsBuilder() { |
| 114 | return getDeviceXmlNodeBuilder("<info/>"); |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | * Builds a request to get Ports data (<circuit-packs>). |
| 119 | * |
| 120 | * @return A string with the Netconf RPC |
| 121 | */ |
| 122 | private String getDeviceCircuitPacksBuilder() { |
| 123 | return getDeviceXmlNodeBuilder("<circuit-packs/>"); |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Builds a request to get External Links data (<external-link>). |
| 128 | * |
| 129 | * @return A string with the Netconf RPC |
| 130 | */ |
| 131 | private String getDeviceExternalLinksBuilder() { |
| 132 | return getDeviceXmlNodeBuilder("<external-link/>"); |
| 133 | } |
| 134 | |
| 135 | /** |
| 136 | * Builds a request to get Device Degrees, config and operational data. |
| 137 | * |
| 138 | * @return A string with the Netconf RPC for a get with subtree rpcing based |
| 139 | * on /components/component/state/type being oc-platform-types:PORT |
| 140 | */ |
| 141 | private String getDeviceDegreesBuilder() { |
| 142 | return getDeviceXmlNodeBuilder("<degree/>"); |
| 143 | } |
| 144 | |
| 145 | /** |
| 146 | * Builds a request to get Device SharedRiskGroups, config and operational |
| 147 | * data. |
| 148 | * |
| 149 | * @return A string with the Netconf RPC for a get with subtree |
| 150 | */ |
| 151 | private String getDeviceSharedRiskGroupsBuilder() { |
| 152 | return getDeviceXmlNodeBuilder("<shared-risk-group/>"); |
| 153 | } |
| 154 | |
| 155 | /** |
| 156 | * Builds a request to get Ports data. |
| 157 | * Changed to XPath and added one based on classic filters since some agents |
| 158 | * do not support xpath filtering. |
| 159 | * |
| 160 | * @return A string with the Netconf RPC |
| 161 | */ |
| 162 | private String getDeviceExternalPortsBuilderXPath() { |
| 163 | StringBuilder filter = new StringBuilder(); |
| 164 | filter.append( |
| 165 | "/org-openroadm-device/circuit-packs/ports[port-qual='roadm-external']"); |
| 166 | return xpathFilteredGetBuilder(filter.toString()); |
| 167 | } |
| 168 | |
| 169 | /** |
| 170 | * Builds a request to get Ports data. |
| 171 | * |
| 172 | * @return A string with the Netconf RPC |
| 173 | */ |
| 174 | private String getDeviceExternalPortsBuilder() { |
| 175 | StringBuilder filter = new StringBuilder(); |
| 176 | filter.append(OPENROADM_DEVICE_OPEN); |
| 177 | filter.append("<circuit-packs>"); |
| 178 | filter.append(" <ports>"); |
| 179 | filter.append(" <port-qual>roadm-external</port-qual>"); |
| 180 | filter.append(" </ports>"); |
| 181 | filter.append("</circuit-packs>"); |
| 182 | filter.append(OPENROADM_DEVICE_CLOSE); |
| 183 | return filteredGetBuilder(filter.toString()); |
| 184 | } |
| 185 | |
| 186 | /** |
| 187 | * Builds a request to get External Links data. |
| 188 | * |
| 189 | * @return A string with the Netconf RPC |
| 190 | */ |
| 191 | private String getDeviceExternalLinksBuilderXpath() { |
| 192 | StringBuilder filter = new StringBuilder(); |
| 193 | filter.append("/org-openroadm-device/external-link"); |
| 194 | return xpathFilteredGetBuilder(filter.toString()); |
| 195 | } |
| 196 | |
| 197 | /** |
| 198 | * Builds a request to get External Links data. |
| 199 | * |
| 200 | * @param nodeId OpenROADM node identifier. |
| 201 | * @param circuitPackName name of the circuit part of the port. |
| 202 | * @param portName name of the port. |
| 203 | * @return A string with the Netconf RPC |
| 204 | */ |
| 205 | private String getDeviceExternalLinkForPortBuilderXPath( |
| 206 | String nodeId, String circuitPackName, String portName) { |
| 207 | StringBuilder filter = new StringBuilder(); |
| 208 | filter.append("/org-openroadm-device/external-link["); |
| 209 | filter.append("./source/node-id='"); |
| 210 | filter.append(nodeId); |
| 211 | filter.append("' and "); |
| 212 | filter.append("./source/circuit-pack-name='"); |
| 213 | filter.append(circuitPackName); |
| 214 | filter.append("' and "); |
| 215 | filter.append("./source/port-name='"); |
| 216 | filter.append(portName); |
| 217 | filter.append("']"); |
| 218 | return xpathFilteredGetBuilder(filter.toString()); |
| 219 | } |
| 220 | |
| 221 | private String getDeviceExternalLinkForPortBuilder(String nodeId, |
| 222 | String circuitPackName, |
| 223 | String portName) { |
| 224 | StringBuilder filter = new StringBuilder(); |
| 225 | filter.append(OPENROADM_DEVICE_OPEN); |
| 226 | filter.append("<external-link>"); |
| 227 | filter.append(" <source>"); |
| 228 | filter.append(" <node-id>"); |
| 229 | filter.append(nodeId); |
| 230 | filter.append("</node-id>"); |
| 231 | filter.append(" <circuit-pack-name>"); |
| 232 | filter.append(circuitPackName); |
| 233 | filter.append("</circuit-pack-name>"); |
| 234 | filter.append(" <port-name>"); |
| 235 | filter.append(portName); |
| 236 | filter.append("</port-name>"); |
| 237 | filter.append(" </source>"); |
| 238 | filter.append("</external-link>"); |
| 239 | filter.append(OPENROADM_DEVICE_CLOSE); |
| 240 | return xpathFilteredGetBuilder(filter.toString()); |
| 241 | } |
| 242 | |
| 243 | |
| 244 | /** |
| 245 | * Returns a DeviceDescription with Device info. |
| 246 | * |
| 247 | * @return DeviceDescription or null |
| 248 | */ |
| 249 | @Override |
| 250 | public DeviceDescription discoverDeviceDetails() { |
| 251 | boolean defaultAvailable = true; |
| 252 | NetconfDevice ncDevice = getNetconfDevice(); |
| 253 | if (ncDevice == null) { |
| 254 | log.error("ONOS Error: Device reachable, deviceID {} is not in Map", did()); |
| 255 | return null; |
| 256 | } |
| 257 | DefaultAnnotations.Builder annotationsBuilder = |
| 258 | DefaultAnnotations.builder(); |
| 259 | |
| 260 | // Some defaults |
| 261 | String vendor = "UNKNOWN"; |
| 262 | String hwVersion = "2.2.0"; |
| 263 | String swVersion = "2.2.0"; |
| 264 | String serialNumber = "0x0000"; |
| 265 | String chassisId = "0"; |
| 266 | String nodeType = "rdm"; |
| 267 | |
| 268 | // Get the session, if null, at least we can use the defaults. |
| 269 | NetconfSession session = getNetconfSession(did()); |
| 270 | if (session != null) { |
| 271 | try { |
| 272 | String reply = session.rpc(getDeviceDetailsBuilder()).get(); |
| 273 | XMLConfiguration xconf = |
| 274 | (XMLConfiguration) XmlConfigParser.loadXmlString(reply); |
| 275 | String nodeId = |
| 276 | xconf.getString("data.org-openroadm-device.info.node-id", ""); |
| 277 | if (nodeId.equals("")) { |
| 278 | log.error("[OPENROADM] {} org-openroadm-device node-id undefined, returning", did()); |
| 279 | return null; |
| 280 | } |
| 281 | annotationsBuilder.set(AnnotationKeys.OPENROADM_NODEID, nodeId); |
| 282 | nodeType = xconf.getString("data.org-openroadm-device.info.node-type", ""); |
| 283 | if (nodeType.equals("")) { |
| 284 | log.error("[OPENROADM] {} empty node-type", did()); |
| 285 | return null; |
| 286 | } |
| 287 | vendor = xconf.getString( |
| 288 | "data.org-openroadm-device.info.vendor", vendor); |
| 289 | hwVersion = xconf.getString( |
| 290 | "data.org-openroadm-device.info.model", hwVersion); |
| 291 | swVersion = xconf.getString( |
| 292 | "data.org-openroadm-device.info.softwareVersion", swVersion); |
| 293 | serialNumber = xconf.getString( |
| 294 | "data.org-openroadm-device.info.serial-id", serialNumber); |
| 295 | chassisId = xconf.getString( |
| 296 | "data.org-openroadm-device.info.node-number", chassisId); |
| 297 | |
| 298 | // GEOLOCATION |
| 299 | String longitudeStr = xconf.getString( |
| 300 | "data.org-openroadm-device.info.geoLocation.longitude"); |
| 301 | String latitudeStr = xconf.getString( |
| 302 | "data.org-openroadm-device.info.geoLocation.latitude"); |
| 303 | if (longitudeStr != null && latitudeStr != null) { |
| 304 | annotationsBuilder |
| 305 | .set(org.onosproject.net.AnnotationKeys.LONGITUDE, |
| 306 | longitudeStr) |
| 307 | .set(org.onosproject.net.AnnotationKeys.LATITUDE, |
| 308 | latitudeStr); |
| 309 | } |
| 310 | } catch (NetconfException | InterruptedException | ExecutionException e) { |
| 311 | log.error("[OPENROADM] {} exception", did()); |
| 312 | return null; |
| 313 | } |
| 314 | } else { |
| 315 | log.debug("[OPENROADM] - No session {}", did()); |
| 316 | } |
| 317 | |
| 318 | log.debug("[OPENROADM] {} - VENDOR {} HWVERSION {} SWVERSION {} SERIAL {} CHASSIS {}", |
| 319 | did(), vendor, hwVersion, swVersion, serialNumber, chassisId); |
| 320 | ChassisId cid = new ChassisId(Long.valueOf(chassisId, 10)); |
| 321 | /* |
| 322 | * OpenROADM defines multiple devices (node types). This driver has been tested with |
| 323 | * ROADMS, (node type, "rdm"). Other devices can also be discovered, and this code is here |
| 324 | * for future developments - untested - it is likely that the XML documents |
| 325 | * are model specific. |
| 326 | */ |
| 327 | org.onosproject.net.Device.Type type; |
| 328 | if (nodeType.equals("rdm")) { |
| 329 | type = org.onosproject.net.Device.Type.ROADM; |
| 330 | } else if (nodeType.equals("ila")) { |
| 331 | type = org.onosproject.net.Device.Type.OPTICAL_AMPLIFIER; |
| 332 | } else if (nodeType.equals("xpdr")) { |
| 333 | type = org.onosproject.net.Device.Type.TERMINAL_DEVICE; |
| 334 | } else if (nodeType.equals("extplug")) { |
| 335 | type = org.onosproject.net.Device.Type.OTHER; |
| 336 | } else { |
| 337 | log.error("[OPENROADM] {} unsupported node-type", did()); |
| 338 | return null; |
| 339 | } |
| 340 | DeviceDescription desc = new DefaultDeviceDescription( |
| 341 | did().uri(), type, vendor, hwVersion, swVersion, serialNumber, cid, |
| 342 | defaultAvailable, annotationsBuilder.build()); |
| 343 | return desc; |
| 344 | } |
| 345 | |
| 346 | |
| 347 | |
| 348 | |
| 349 | /** |
| 350 | * Get the external links as a list of XML hieriarchical configs. |
| 351 | * @param session the NETConf session to the OpenROADM device. |
| 352 | * @return a list of hierarchical conf. each one external link. |
| 353 | */ |
| 354 | List<HierarchicalConfiguration> getExternalLinks(NetconfSession session) { |
| 355 | try { |
| 356 | String reply = session.rpc(getDeviceExternalLinksBuilder()).get(); |
| 357 | XMLConfiguration extLinksConf = // |
| 358 | (XMLConfiguration) XmlConfigParser.loadXmlString(reply); |
| 359 | extLinksConf.setExpressionEngine(new XPathExpressionEngine()); |
| 360 | return extLinksConf.configurationsAt( |
| 361 | "/data/org-openroadm-device/external-link"); |
| 362 | } catch (NetconfException | InterruptedException | ExecutionException e) { |
| 363 | log.error("[OPENROADM] {} exception getting external links", did()); |
| 364 | return ImmutableList.of(); |
| 365 | } |
| 366 | } |
| 367 | |
| 368 | |
| 369 | /** |
| 370 | * Get the circuit packs from the device as a list of XML hierarchical configs. |
| 371 | * @param session the NETConf session to the OpenROADM device. |
| 372 | * @return a list of hierarchical conf. each one circuit pack. |
| 373 | */ |
| 374 | List<HierarchicalConfiguration> getCircuitPacks(NetconfSession session) { |
| 375 | try { |
| 376 | String reply = session.rpc(getDeviceCircuitPacksBuilder()).get(); |
| 377 | XMLConfiguration cpConf = // |
| 378 | (XMLConfiguration) XmlConfigParser.loadXmlString(reply); |
| 379 | cpConf.setExpressionEngine(new XPathExpressionEngine()); |
| 380 | return cpConf.configurationsAt( |
| 381 | "/data/org-openroadm-device/circuit-packs"); |
| 382 | } catch (NetconfException | InterruptedException | ExecutionException e) { |
| 383 | log.error("[OPENROADM] {} exception getting circuit packs", did()); |
| 384 | return ImmutableList.of(); |
| 385 | } |
| 386 | } |
| 387 | |
| 388 | /** |
| 389 | * Returns a list of PortDescriptions for the device. |
| 390 | * |
| 391 | * @return a list of descriptions. |
| 392 | */ |
| 393 | @Override |
| 394 | public List<PortDescription> discoverPortDetails() { |
| 395 | NetconfSession session = getNetconfSession(did()); |
| 396 | if (session == null) { |
| 397 | log.error("discoverPortDetails null session for {}", did()); |
| 398 | return ImmutableList.of(); |
| 399 | } |
| 400 | if (!getDevice().annotations().keys().contains("openroadm-node-id")) { |
| 401 | log.error("PortDiscovery before DeviceDiscovery, using netconf"); |
| 402 | return ImmutableList.of(); |
| 403 | } |
| 404 | String nodeId = getDevice().annotations().value("openroadm-node-id"); |
| 405 | List<PortDescription> list = new ArrayList<PortDescription>(); |
| 406 | List<HierarchicalConfiguration> circuitPacks = getCircuitPacks(session); |
| 407 | /* |
| 408 | * Iterate all the ports. We need to pass the whole circuitPacks list |
| 409 | * because some port data refers to ports in other circuit packs |
| 410 | * (reverse), in addition to pass the current circuit pack name, list of |
| 411 | * external ports etc |
| 412 | */ |
| 413 | for (HierarchicalConfiguration c : circuitPacks) { |
| 414 | parsePorts(list, nodeId, // c contains the whole circuit pack |
| 415 | c.getString("circuit-pack-name"), // |
| 416 | c.configurationsAt( |
| 417 | "ports[port-qual='roadm-external']"), // ext ports |
| 418 | circuitPacks, getExternalLinks(session)); |
| 419 | } |
| 420 | return list; |
| 421 | } |
| 422 | |
| 423 | /** |
| 424 | * Parses port information. |
| 425 | * |
| 426 | * @param list List of port descriptions to append to. |
| 427 | * @param nodeId OpenROADM node identifier. |
| 428 | * @param circuitPackName Name of the circuit pack the ports belong to |
| 429 | * @param ports hierarchical conf containing all the ports for the circuit |
| 430 | * pack |
| 431 | * @param circuitPacks all the circuit packs (to correlate data). |
| 432 | * @param extLinks Hierarchical configuration containing all the ext. |
| 433 | * links. |
| 434 | */ |
| 435 | protected void parsePorts(List<PortDescription> list, String nodeId, |
| 436 | String circuitPackName, |
| 437 | List<HierarchicalConfiguration> ports, |
| 438 | List<HierarchicalConfiguration> circuitPacks, |
| 439 | List<HierarchicalConfiguration> extLinks) { |
| 440 | checkNotNull(nodeId); |
| 441 | checkNotNull(circuitPackName); |
| 442 | for (HierarchicalConfiguration port : ports) { |
| 443 | try { |
| 444 | String portName = checkNotNull(port.getString("port-name")); |
| 445 | long portNum = Long.parseLong(port.getString("label")); |
| 446 | PortNumber pNum = PortNumber.portNumber(portNum); |
| 447 | PortNumber reversepNum = findReversePort(port, circuitPacks); |
| 448 | // To see if we have an external port |
| 449 | HierarchicalConfiguration eLink = null; |
| 450 | for (HierarchicalConfiguration extLink : extLinks) { |
| 451 | String eln = |
| 452 | checkNotNull(extLink.getString("external-link-name")); |
| 453 | String esnid = |
| 454 | checkNotNull(extLink.getString("source/node-id")); |
| 455 | String escpn = |
| 456 | checkNotNull(extLink.getString("source/circuit-pack-name")); |
| 457 | String espn = |
| 458 | checkNotNull(extLink.getString("source/port-name")); |
| 459 | if (nodeId.equals(esnid) && circuitPackName.equals(escpn) && |
| 460 | portName.equals(espn)) { |
| 461 | eLink = extLink; |
| 462 | } |
| 463 | } |
| 464 | PortDescription pd = parsePortComponent( |
| 465 | nodeId, circuitPackName, pNum, reversepNum, port, eLink); |
| 466 | if (pd != null) { |
| 467 | list.add(pd); |
| 468 | } |
| 469 | } catch (NetconfException e) { |
| 470 | log.error("[OPENROADM] {} NetConf exception", did()); |
| 471 | return; |
| 472 | } |
| 473 | } |
| 474 | } |
| 475 | |
| 476 | /** |
| 477 | * Given a device port (external), return its patner/reverse port. |
| 478 | * |
| 479 | * @param thisPort the port for which we are looking for the reverse port. |
| 480 | * @param circuitPacks all the circuit packs (to correlate data). |
| 481 | * @return the port number for the reverse port. |
| 482 | * @throws NetconfException . |
| 483 | */ |
| 484 | protected PortNumber |
| 485 | findReversePort(HierarchicalConfiguration thisPort, |
| 486 | List<HierarchicalConfiguration> circuitPacks) |
| 487 | throws NetconfException { |
| 488 | String partnerCircuitPackName = |
| 489 | checkNotNull(thisPort.getString("partner-port/circuit-pack-name")); |
| 490 | String partnerPortName = |
| 491 | checkNotNull(thisPort.getString("partner-port/port-name")); |
| 492 | for (HierarchicalConfiguration c : circuitPacks) { |
| 493 | if (!partnerCircuitPackName.equals( |
| 494 | c.getString("circuit-pack-name"))) { |
| 495 | continue; |
| 496 | } |
| 497 | for (HierarchicalConfiguration thatPort : |
| 498 | c.configurationsAt("ports[port-qual='roadm-external']")) { |
| 499 | String thatPortName = thatPort.getString("port-name"); |
| 500 | if (partnerPortName.equals(thatPortName)) { |
| 501 | long thatPortNum = |
| 502 | Long.parseLong(thatPort.getString("label")); |
| 503 | return PortNumber.portNumber(thatPortNum); |
| 504 | } |
| 505 | } |
| 506 | } |
| 507 | // We should not reach here |
| 508 | throw new NetconfException("missing partner/reverse port info"); |
| 509 | } |
| 510 | |
| 511 | /** |
| 512 | * Parses a component XML doc into a PortDescription. |
| 513 | * An OMS port description is constructed from XML parsed data. |
| 514 | * |
| 515 | * @param port the port to parse |
| 516 | * @return PortDescription or null |
| 517 | */ |
| 518 | private PortDescription |
| 519 | parsePortComponent(String nodeId, String circuitPackName, PortNumber pNum, |
| 520 | PortNumber reversepNum, HierarchicalConfiguration port, |
| 521 | HierarchicalConfiguration extLink) { |
| 522 | Map<String, String> annotations = new HashMap<>(); |
| 523 | annotations.put(AnnotationKeys.OPENROADM_NODEID, nodeId); |
| 524 | annotations.put(AnnotationKeys.OPENROADM_CIRCUIT_PACK_NAME, |
| 525 | circuitPackName); |
| 526 | annotations.put(AnnotationKeys.OPENROADM_PORT_NAME, |
| 527 | port.getString("port-name")); |
| 528 | annotations.put(AnnotationKeys.OPENROADM_PARTNER_CIRCUIT_PACK_NAME, |
| 529 | port.getString("partner-port/circuit-pack-name", "")); |
| 530 | annotations.put(AnnotationKeys.OPENROADM_PARTNER_PORT_NAME, |
| 531 | port.getString("partner-port/port-name", "")); |
| 532 | annotations.put(AnnotationKeys.OPENROADM_LOGICAL_CONNECTION_POINT, |
| 533 | port.getString("logical-connection-point", "")); |
| 534 | // Annotate the reverse port, this is needed for bidir intents. |
| 535 | annotations.put(OpticalPathIntent.REVERSE_PORT_ANNOTATION_KEY, |
| 536 | Long.toString(reversepNum.toLong())); |
| 537 | |
| 538 | // for backwards compatibility |
| 539 | annotations.put("logical-connection-point", |
| 540 | port.getString("logical-connection-point", "")); |
| 541 | // Annotate external link if we found one for this port |
| 542 | if (extLink != null) { |
| 543 | String ednid = extLink.getString("destination/node-id"); |
| 544 | String edcpn = extLink.getString("destination/circuit-pack-name"); |
| 545 | String edpn = extLink.getString("destination/port-name"); |
| 546 | annotations.put("openroadm-external-node-id", ednid); |
| 547 | annotations.put("openroadm-external-circuit-pack-name", edcpn); |
| 548 | annotations.put("openroadm-external-port-name", edpn); |
| 549 | } |
| 550 | |
| 551 | /* |
| 552 | * Declare the actual optical port: |
| 553 | * Assumptions: client ports are OCh, assumed to carry ODU4 (should be |
| 554 | * configurable) |
| 555 | */ |
| 556 | if (port.getString("port-wavelength-type", "wavelength") |
| 557 | .equals("wavelength")) { |
| 558 | // OchSignal is needed for OchPortDescription constructor, but it's |
| 559 | // tunable |
| 560 | OchSignal signalId = |
| 561 | OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 3); |
| 562 | return OchPortHelper.ochPortDescription( |
| 563 | pNum, true /* enabled */, OduSignalType.ODU4, true /* tunable */, |
| 564 | signalId, |
| 565 | DefaultAnnotations.builder().putAll(annotations).build()); |
| 566 | } else { |
| 567 | return OmsPortHelper.omsPortDescription( |
| 568 | pNum, true /* enabled */, |
| 569 | // Relationship : START and STOP Freq not being used (See |
| 570 | // LambdaQuery) |
| 571 | START_CENTER_FREQ, STOP_CENTER_FREQ, CHANNEL_SPACING.frequency(), |
| 572 | DefaultAnnotations.builder().putAll(annotations).build()); |
| 573 | } |
| 574 | } |
| 575 | } |