blob: f2f47394fae54cd000f5cb4fa6513cd99a1aaf30 [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",
95 new ChassisId());
96 } else {
97 return new DefaultDeviceDescription(device.id().uri(),
98 Device.Type.OLS,
99 device.manufacturer(),
100 device.hwVersion(),
101 device.swVersion(),
102 device.serialNumber(),
103 device.chassisId());
104 }
105 }
106
107 @Override
108 public List<PortDescription> discoverPortDetails() {
109 log.debug("Discovering port details.");
110 RestSBController controller = checkNotNull(handler().get(RestSBController.class));
111 DeviceId deviceId = handler().data().deviceId();
112
113 try {
114 InputStream inputStream = controller.get(deviceId, SIP_REQUEST_DATA_API, MediaType.APPLICATION_JSON_TYPE);
115 JsonNode jsonNode = new ObjectMapper().readTree(inputStream);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100116 if (jsonNode == null) {
117 log.error("Can't discover port details at {}", SIP_REQUEST_DATA_API);
118 return ImmutableList.of();
119 }
Diego Garcia09ab5e22018-12-18 11:47:01 +0100120 return parseTapiPorts(jsonNode);
121 } catch (IOException e) {
122 log.error("Exception discoverPortDetails() {}", did(), e);
123 return ImmutableList.of();
124 }
125 }
126
127 protected List<PortDescription> parseTapiPorts(JsonNode tapiContext) {
128 List<PortDescription> ports = Lists.newArrayList();
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100129 /*
Diego Garcia09ab5e22018-12-18 11:47:01 +0100130 This annotations are used to store persistent mapping information between TAPI SIP's uuid
131 and ONOS device portNumbers. This is needed to be publicly available at least within ODTN app
132 when connectivity services will be sent to OLS Controller.
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100133 */
Diego Garcia09ab5e22018-12-18 11:47:01 +0100134 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
Boyuan Yan4cebe242019-05-28 16:59:37 -0700135 Iterator<JsonNode> iter = tapiContext.get(SERVICE_INTERFACE_POINT).iterator();
Diego Garcia09ab5e22018-12-18 11:47:01 +0100136 while (iter.hasNext()) {
137 JsonNode sipAttributes = iter.next();
138 if (checkValidEndpoint(sipAttributes)) {
139 String uuid = sipAttributes.get(UUID).textValue();
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100140 PortNumber portNumber = PortNumber.portNumber(uuid.split("-")[0]);
141 annotations.set(UUID, uuid);
142
Diego Garcia09ab5e22018-12-18 11:47:01 +0100143 JsonNode mcPool = sipAttributes.get(MEDIA_CHANNEL_SERVICE_INTERFACE_POINT_SPEC).get(MC_POOL);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100144 // We get the first OCH signal as reported by the device.
145 OchSignal ochSignal = getOchSignal(mcPool).iterator().next();
146 //add och port
147 ports.add(ochPortDescription(portNumber, true, OduSignalType.ODU4,
148 false, ochSignal, annotations.build()));
Diego Garcia09ab5e22018-12-18 11:47:01 +0100149
Diego Garciaaab99472019-01-10 13:53:31 +0100150
Diego Garcia09ab5e22018-12-18 11:47:01 +0100151 } else {
152 log.error("SIP {} is not valid", sipAttributes);
153 }
154 }
155 log.debug("PortList: {}", ports);
156 return ImmutableList.copyOf(ports);
157 }
158
159 /**
160 * Create a filter method to identify just valid OLS SIPs.This method must check the
161 * tapi object: "layer-protocol-name" and matching only if equals to "PHOTONIC-MEDIA" SIPs.
162 * Moreover,the filtering could be enhanced by reading also:
163 * "supported-layer-protocol-qualifier", to identify valid protocol-qualifier values such:
164 * [PHOTONIC_LAYER_QUALIFIER_NMC, PHOTONIC_LAYER_QUALIFIER_NMCA, PHOTONIC_LAYER_QUALIFIER_OTSI...]
165 **/
166 private boolean checkValidEndpoint(JsonNode sipAttributes) {
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100167 return sipAttributes.has(LAYER_PROTOCOL_NAME) &&
168 sipAttributes.get(LAYER_PROTOCOL_NAME).toString().contains(PHOTONIC_MEDIA) &&
169 sipAttributes.has(SUPPORTED_LAYER_PROTOCOL_QUALIFIER) &&
Diego Garcia09ab5e22018-12-18 11:47:01 +0100170 sipAttributes.get(SUPPORTED_LAYER_PROTOCOL_QUALIFIER).toString()
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100171 .contains(PHOTONIC_LAYER_QUALIFIER_NMC);
Diego Garcia09ab5e22018-12-18 11:47:01 +0100172 }
173
Diego Garcia09ab5e22018-12-18 11:47:01 +0100174}