blob: 50ab094de34cee5cef086bf67d4b039f17761b62 [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 Campanella2bdf2042019-01-28 13:47:11 +010047import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.LAYER_PROTOCOL_NAME;
Andrea Campanella2bdf2042019-01-28 13:47:11 +010048import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.MC_POOL;
Andrea Campanellab9e491b2019-02-18 17:45:01 +010049import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.MEDIA_CHANNEL_SERVICE_INTERFACE_POINT_SPEC;
Andrea Campanella2bdf2042019-01-28 13:47:11 +010050import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.PHOTONIC_LAYER_QUALIFIER_NMC;
51import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.PHOTONIC_MEDIA;
52import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SERVICE_INTERFACE_POINT;
53import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.SUPPORTED_LAYER_PROTOCOL_QUALIFIER;
Andrea Campanella2bdf2042019-01-28 13:47:11 +010054import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.UUID;
Andrea Campanellab9e491b2019-02-18 17:45:01 +010055import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.getOchSignal;
Diego Garcia09ab5e22018-12-18 11:47:01 +010056import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
57import static org.slf4j.LoggerFactory.getLogger;
58
59/**
60 * Driver Implementation of the DeviceDescrption discovery for ONF Transport-API (TAPI) v2.1 based
61 * open line systems (OLS).
62 */
63
64public class TapiDeviceDescriptionDiscovery
65 extends AbstractHandlerBehaviour
66 implements DeviceDescriptionDiscovery {
67
68 private static final Logger log = getLogger(TapiDeviceDescriptionDiscovery.class);
Andrea Campanellab9e491b2019-02-18 17:45:01 +010069 private static final String SIP_REQUEST_DATA_API = "/restconf/data/tapi-common:context";
Diego Garcia09ab5e22018-12-18 11:47:01 +010070
71 /**
72 * Get the deviceId for which the methods apply.
73 *
74 * @return The deviceId as contained in the handler data
75 */
76 private DeviceId did() {
77 return handler().data().deviceId();
78 }
79
80 @Override
81 public DeviceDescription discoverDeviceDetails() {
82 log.debug("Getting device description");
83 DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
84 DeviceId deviceId = handler().data().deviceId();
85 Device device = deviceService.getDevice(deviceId);
86
87 if (device == null) {
Andrea Campanellab9e491b2019-02-18 17:45:01 +010088 //TODO need to obtain from the device.
Diego Garcia09ab5e22018-12-18 11:47:01 +010089 return new DefaultDeviceDescription(deviceId.uri(),
90 Device.Type.OLS,
Andrea Campanellab9e491b2019-02-18 17:45:01 +010091 "Tapi",
Diego Garcia09ab5e22018-12-18 11:47:01 +010092 "0",
93 "2.1",
94 "Unknown",
Boyuan Yan6b23b382019-06-04 11:59:35 -070095 new ChassisId(),
96 DefaultAnnotations.builder().set("protocol", "REST").build());
Diego Garcia09ab5e22018-12-18 11:47:01 +010097 } else {
98 return new DefaultDeviceDescription(device.id().uri(),
99 Device.Type.OLS,
100 device.manufacturer(),
101 device.hwVersion(),
102 device.swVersion(),
103 device.serialNumber(),
104 device.chassisId());
105 }
106 }
107
108 @Override
109 public List<PortDescription> discoverPortDetails() {
110 log.debug("Discovering port details.");
111 RestSBController controller = checkNotNull(handler().get(RestSBController.class));
112 DeviceId deviceId = handler().data().deviceId();
113
114 try {
115 InputStream inputStream = controller.get(deviceId, SIP_REQUEST_DATA_API, MediaType.APPLICATION_JSON_TYPE);
116 JsonNode jsonNode = new ObjectMapper().readTree(inputStream);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100117 if (jsonNode == null) {
118 log.error("Can't discover port details at {}", SIP_REQUEST_DATA_API);
119 return ImmutableList.of();
120 }
Diego Garcia09ab5e22018-12-18 11:47:01 +0100121 return parseTapiPorts(jsonNode);
122 } catch (IOException e) {
123 log.error("Exception discoverPortDetails() {}", did(), e);
124 return ImmutableList.of();
125 }
126 }
127
128 protected List<PortDescription> parseTapiPorts(JsonNode tapiContext) {
129 List<PortDescription> ports = Lists.newArrayList();
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100130 /*
Diego Garcia09ab5e22018-12-18 11:47:01 +0100131 This annotations are used to store persistent mapping information between TAPI SIP's uuid
132 and ONOS device portNumbers. This is needed to be publicly available at least within ODTN app
133 when connectivity services will be sent to OLS Controller.
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100134 */
Diego Garcia09ab5e22018-12-18 11:47:01 +0100135 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
Boyuan Yan4cebe242019-05-28 16:59:37 -0700136 Iterator<JsonNode> iter = tapiContext.get(SERVICE_INTERFACE_POINT).iterator();
Diego Garcia09ab5e22018-12-18 11:47:01 +0100137 while (iter.hasNext()) {
138 JsonNode sipAttributes = iter.next();
139 if (checkValidEndpoint(sipAttributes)) {
140 String uuid = sipAttributes.get(UUID).textValue();
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100141 PortNumber portNumber = PortNumber.portNumber(uuid.split("-")[0]);
142 annotations.set(UUID, uuid);
143
Diego Garcia09ab5e22018-12-18 11:47:01 +0100144 JsonNode mcPool = sipAttributes.get(MEDIA_CHANNEL_SERVICE_INTERFACE_POINT_SPEC).get(MC_POOL);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100145 // We get the first OCH signal as reported by the device.
146 OchSignal ochSignal = getOchSignal(mcPool).iterator().next();
147 //add och port
148 ports.add(ochPortDescription(portNumber, true, OduSignalType.ODU4,
149 false, ochSignal, annotations.build()));
Diego Garcia09ab5e22018-12-18 11:47:01 +0100150
Diego Garciaaab99472019-01-10 13:53:31 +0100151
Diego Garcia09ab5e22018-12-18 11:47:01 +0100152 } else {
153 log.error("SIP {} is not valid", sipAttributes);
154 }
155 }
156 log.debug("PortList: {}", ports);
157 return ImmutableList.copyOf(ports);
158 }
159
160 /**
161 * Create a filter method to identify just valid OLS SIPs.This method must check the
162 * tapi object: "layer-protocol-name" and matching only if equals to "PHOTONIC-MEDIA" SIPs.
163 * Moreover,the filtering could be enhanced by reading also:
164 * "supported-layer-protocol-qualifier", to identify valid protocol-qualifier values such:
165 * [PHOTONIC_LAYER_QUALIFIER_NMC, PHOTONIC_LAYER_QUALIFIER_NMCA, PHOTONIC_LAYER_QUALIFIER_OTSI...]
166 **/
167 private boolean checkValidEndpoint(JsonNode sipAttributes) {
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100168 return sipAttributes.has(LAYER_PROTOCOL_NAME) &&
169 sipAttributes.get(LAYER_PROTOCOL_NAME).toString().contains(PHOTONIC_MEDIA) &&
170 sipAttributes.has(SUPPORTED_LAYER_PROTOCOL_QUALIFIER) &&
Diego Garcia09ab5e22018-12-18 11:47:01 +0100171 sipAttributes.get(SUPPORTED_LAYER_PROTOCOL_QUALIFIER).toString()
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100172 .contains(PHOTONIC_LAYER_QUALIFIER_NMC);
Diego Garcia09ab5e22018-12-18 11:47:01 +0100173 }
174
Diego Garcia09ab5e22018-12-18 11:47:01 +0100175}