blob: 2c35a29001dc7594fb6e377a2819b54dada58f20 [file] [log] [blame]
Diego Garcia09ab5e22018-12-18 11:47:01 +01001/*
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 */
18package org.onosproject.drivers.odtn.tapi;
19
20import com.fasterxml.jackson.databind.JsonNode;
21import com.fasterxml.jackson.databind.ObjectMapper;
22import com.google.common.collect.ImmutableList;
23import com.google.common.collect.Lists;
24import org.onlab.packet.ChassisId;
Andrea Campanellab9e491b2019-02-18 17:45:01 +010025import org.onosproject.net.DefaultAnnotations;
Diego Garcia09ab5e22018-12-18 11:47:01 +010026import org.onosproject.net.Device;
Diego Garcia09ab5e22018-12-18 11:47:01 +010027import org.onosproject.net.DeviceId;
Andrea Campanellab9e491b2019-02-18 17:45:01 +010028import org.onosproject.net.OchSignal;
29import org.onosproject.net.OduSignalType;
30import org.onosproject.net.PortNumber;
Diego Garcia09ab5e22018-12-18 11:47:01 +010031import org.onosproject.net.device.DefaultDeviceDescription;
32import org.onosproject.net.device.DeviceDescription;
33import org.onosproject.net.device.DeviceDescriptionDiscovery;
34import org.onosproject.net.device.DeviceService;
Andrea Campanellab9e491b2019-02-18 17:45:01 +010035import org.onosproject.net.device.PortDescription;
Diego Garcia09ab5e22018-12-18 11:47:01 +010036import org.onosproject.net.driver.AbstractHandlerBehaviour;
Diego Garcia09ab5e22018-12-18 11:47:01 +010037import org.onosproject.protocol.rest.RestSBController;
38import org.slf4j.Logger;
39
40import javax.ws.rs.core.MediaType;
41import java.io.IOException;
42import java.io.InputStream;
43import java.util.Iterator;
44import java.util.List;
45
46import static com.google.common.base.Preconditions.checkNotNull;
Andrea Campanella3d2ba462019-08-22 16:29:21 +020047import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.CONTEXT;
Andrea Campanella2bdf2042019-01-28 13:47:11 +010048import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.LAYER_PROTOCOL_NAME;
Andrea Campanella2bdf2042019-01-28 13:47:11 +010049import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.MC_POOL;
Andrea Campanellab9e491b2019-02-18 17:45:01 +010050import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.MEDIA_CHANNEL_SERVICE_INTERFACE_POINT_SPEC;
Andrea Campanella2bdf2042019-01-28 13:47:11 +010051import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.PHOTONIC_LAYER_QUALIFIER_NMC;
52import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.PHOTONIC_MEDIA;
53import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SERVICE_INTERFACE_POINT;
54import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SUPPORTED_LAYER_PROTOCOL_QUALIFIER;
Andrea Campanella2bdf2042019-01-28 13:47:11 +010055import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.UUID;
Andrea Campanellab9e491b2019-02-18 17:45:01 +010056import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.getOchSignal;
Diego Garcia09ab5e22018-12-18 11:47:01 +010057import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
58import static org.slf4j.LoggerFactory.getLogger;
59
60/**
61 * Driver Implementation of the DeviceDescrption discovery for ONF Transport-API (TAPI) v2.1 based
62 * open line systems (OLS).
63 */
64
65public class TapiDeviceDescriptionDiscovery
66 extends AbstractHandlerBehaviour
67 implements DeviceDescriptionDiscovery {
68
69 private static final Logger log = getLogger(TapiDeviceDescriptionDiscovery.class);
Andrea Campanellab9e491b2019-02-18 17:45:01 +010070 private static final String SIP_REQUEST_DATA_API = "/restconf/data/tapi-common:context";
Diego Garcia09ab5e22018-12-18 11:47:01 +010071
72 /**
73 * Get the deviceId for which the methods apply.
74 *
75 * @return The deviceId as contained in the handler data
76 */
77 private DeviceId did() {
78 return handler().data().deviceId();
79 }
80
81 @Override
82 public DeviceDescription discoverDeviceDetails() {
83 log.debug("Getting device description");
84 DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
85 DeviceId deviceId = handler().data().deviceId();
86 Device device = deviceService.getDevice(deviceId);
87
88 if (device == null) {
Andrea Campanellab9e491b2019-02-18 17:45:01 +010089 //TODO need to obtain from the device.
Diego Garcia09ab5e22018-12-18 11:47:01 +010090 return new DefaultDeviceDescription(deviceId.uri(),
91 Device.Type.OLS,
Andrea Campanellab9e491b2019-02-18 17:45:01 +010092 "Tapi",
Diego Garcia09ab5e22018-12-18 11:47:01 +010093 "0",
94 "2.1",
95 "Unknown",
Boyuan Yan6b23b382019-06-04 11:59:35 -070096 new ChassisId(),
97 DefaultAnnotations.builder().set("protocol", "REST").build());
Diego Garcia09ab5e22018-12-18 11:47:01 +010098 } else {
99 return new DefaultDeviceDescription(device.id().uri(),
100 Device.Type.OLS,
101 device.manufacturer(),
102 device.hwVersion(),
103 device.swVersion(),
104 device.serialNumber(),
105 device.chassisId());
106 }
107 }
108
109 @Override
110 public List<PortDescription> discoverPortDetails() {
111 log.debug("Discovering port details.");
112 RestSBController controller = checkNotNull(handler().get(RestSBController.class));
113 DeviceId deviceId = handler().data().deviceId();
114
115 try {
116 InputStream inputStream = controller.get(deviceId, SIP_REQUEST_DATA_API, MediaType.APPLICATION_JSON_TYPE);
117 JsonNode jsonNode = new ObjectMapper().readTree(inputStream);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100118 if (jsonNode == null) {
119 log.error("Can't discover port details at {}", SIP_REQUEST_DATA_API);
120 return ImmutableList.of();
121 }
Diego Garcia09ab5e22018-12-18 11:47:01 +0100122 return parseTapiPorts(jsonNode);
123 } catch (IOException e) {
124 log.error("Exception discoverPortDetails() {}", did(), e);
125 return ImmutableList.of();
126 }
127 }
128
129 protected List<PortDescription> parseTapiPorts(JsonNode tapiContext) {
130 List<PortDescription> ports = Lists.newArrayList();
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100131 /*
Diego Garcia09ab5e22018-12-18 11:47:01 +0100132 This annotations are used to store persistent mapping information between TAPI SIP's uuid
133 and ONOS device portNumbers. This is needed to be publicly available at least within ODTN app
134 when connectivity services will be sent to OLS Controller.
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100135 */
Diego Garcia09ab5e22018-12-18 11:47:01 +0100136 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
Andrea Campanella3d2ba462019-08-22 16:29:21 +0200137 Iterator<JsonNode> iter = tapiContext.get(CONTEXT).get(SERVICE_INTERFACE_POINT).iterator();
Diego Garcia09ab5e22018-12-18 11:47:01 +0100138 while (iter.hasNext()) {
139 JsonNode sipAttributes = iter.next();
140 if (checkValidEndpoint(sipAttributes)) {
141 String uuid = sipAttributes.get(UUID).textValue();
Boyuan Yan8f9f6ad2019-06-12 16:54:42 -0700142 String[] uuidSeg = uuid.split("-");
143 PortNumber portNumber = PortNumber.portNumber(uuidSeg[uuidSeg.length - 1]);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100144 annotations.set(UUID, uuid);
145
Diego Garcia09ab5e22018-12-18 11:47:01 +0100146 JsonNode mcPool = sipAttributes.get(MEDIA_CHANNEL_SERVICE_INTERFACE_POINT_SPEC).get(MC_POOL);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100147 // We get the first OCH signal as reported by the device.
148 OchSignal ochSignal = getOchSignal(mcPool).iterator().next();
149 //add och port
150 ports.add(ochPortDescription(portNumber, true, OduSignalType.ODU4,
151 false, ochSignal, annotations.build()));
Diego Garcia09ab5e22018-12-18 11:47:01 +0100152
Diego Garciaaab99472019-01-10 13:53:31 +0100153
Diego Garcia09ab5e22018-12-18 11:47:01 +0100154 } else {
155 log.error("SIP {} is not valid", sipAttributes);
156 }
157 }
158 log.debug("PortList: {}", ports);
159 return ImmutableList.copyOf(ports);
160 }
161
162 /**
163 * Create a filter method to identify just valid OLS SIPs.This method must check the
164 * tapi object: "layer-protocol-name" and matching only if equals to "PHOTONIC-MEDIA" SIPs.
165 * Moreover,the filtering could be enhanced by reading also:
166 * "supported-layer-protocol-qualifier", to identify valid protocol-qualifier values such:
167 * [PHOTONIC_LAYER_QUALIFIER_NMC, PHOTONIC_LAYER_QUALIFIER_NMCA, PHOTONIC_LAYER_QUALIFIER_OTSI...]
168 **/
169 private boolean checkValidEndpoint(JsonNode sipAttributes) {
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100170 return sipAttributes.has(LAYER_PROTOCOL_NAME) &&
171 sipAttributes.get(LAYER_PROTOCOL_NAME).toString().contains(PHOTONIC_MEDIA) &&
172 sipAttributes.has(SUPPORTED_LAYER_PROTOCOL_QUALIFIER) &&
Diego Garcia09ab5e22018-12-18 11:47:01 +0100173 sipAttributes.get(SUPPORTED_LAYER_PROTOCOL_QUALIFIER).toString()
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100174 .contains(PHOTONIC_LAYER_QUALIFIER_NMC);
Diego Garcia09ab5e22018-12-18 11:47:01 +0100175 }
176
Diego Garcia09ab5e22018-12-18 11:47:01 +0100177}