blob: 71e338e4a885b4a41c93c8a4502d5694c5de741f [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;
Andrea Campanellae4b2c682019-08-23 15:42:55 +020057import static org.onosproject.drivers.odtn.tapi.TapiDeviceHelper.removeInitalConnectivityServices;
Diego Garcia09ab5e22018-12-18 11:47:01 +010058import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
59import static org.slf4j.LoggerFactory.getLogger;
60
61/**
62 * Driver Implementation of the DeviceDescrption discovery for ONF Transport-API (TAPI) v2.1 based
63 * open line systems (OLS).
64 */
65
66public class TapiDeviceDescriptionDiscovery
67 extends AbstractHandlerBehaviour
68 implements DeviceDescriptionDiscovery {
69
70 private static final Logger log = getLogger(TapiDeviceDescriptionDiscovery.class);
Andrea Campanellab9e491b2019-02-18 17:45:01 +010071 private static final String SIP_REQUEST_DATA_API = "/restconf/data/tapi-common:context";
Diego Garcia09ab5e22018-12-18 11:47:01 +010072
73 /**
74 * Get the deviceId for which the methods apply.
75 *
76 * @return The deviceId as contained in the handler data
77 */
78 private DeviceId did() {
79 return handler().data().deviceId();
80 }
81
82 @Override
83 public DeviceDescription discoverDeviceDetails() {
84 log.debug("Getting device description");
85 DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
86 DeviceId deviceId = handler().data().deviceId();
87 Device device = deviceService.getDevice(deviceId);
88
89 if (device == null) {
Andrea Campanellab9e491b2019-02-18 17:45:01 +010090 //TODO need to obtain from the device.
Diego Garcia09ab5e22018-12-18 11:47:01 +010091 return new DefaultDeviceDescription(deviceId.uri(),
92 Device.Type.OLS,
Andrea Campanellab9e491b2019-02-18 17:45:01 +010093 "Tapi",
Diego Garcia09ab5e22018-12-18 11:47:01 +010094 "0",
95 "2.1",
96 "Unknown",
Boyuan Yan6b23b382019-06-04 11:59:35 -070097 new ChassisId(),
98 DefaultAnnotations.builder().set("protocol", "REST").build());
Diego Garcia09ab5e22018-12-18 11:47:01 +010099 } else {
100 return new DefaultDeviceDescription(device.id().uri(),
101 Device.Type.OLS,
102 device.manufacturer(),
103 device.hwVersion(),
104 device.swVersion(),
105 device.serialNumber(),
106 device.chassisId());
107 }
108 }
109
110 @Override
111 public List<PortDescription> discoverPortDetails() {
112 log.debug("Discovering port details.");
113 RestSBController controller = checkNotNull(handler().get(RestSBController.class));
114 DeviceId deviceId = handler().data().deviceId();
115
116 try {
117 InputStream inputStream = controller.get(deviceId, SIP_REQUEST_DATA_API, MediaType.APPLICATION_JSON_TYPE);
118 JsonNode jsonNode = new ObjectMapper().readTree(inputStream);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100119 if (jsonNode == null) {
120 log.error("Can't discover port details at {}", SIP_REQUEST_DATA_API);
121 return ImmutableList.of();
122 }
Andrea Campanellae4b2c682019-08-23 15:42:55 +0200123 List<PortDescription> ports = parseTapiPorts(jsonNode);
124 //Removing any initial connectivity services
125 removeInitalConnectivityServices(deviceId, handler());
126 return ports;
Diego Garcia09ab5e22018-12-18 11:47:01 +0100127 } catch (IOException e) {
128 log.error("Exception discoverPortDetails() {}", did(), e);
Andrea Campanellae4b2c682019-08-23 15:42:55 +0200129 removeInitalConnectivityServices(deviceId, handler());
Diego Garcia09ab5e22018-12-18 11:47:01 +0100130 return ImmutableList.of();
131 }
132 }
133
134 protected List<PortDescription> parseTapiPorts(JsonNode tapiContext) {
135 List<PortDescription> ports = Lists.newArrayList();
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100136 /*
Diego Garcia09ab5e22018-12-18 11:47:01 +0100137 This annotations are used to store persistent mapping information between TAPI SIP's uuid
138 and ONOS device portNumbers. This is needed to be publicly available at least within ODTN app
139 when connectivity services will be sent to OLS Controller.
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100140 */
Diego Garcia09ab5e22018-12-18 11:47:01 +0100141 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
Andrea Campanella3d2ba462019-08-22 16:29:21 +0200142 Iterator<JsonNode> iter = tapiContext.get(CONTEXT).get(SERVICE_INTERFACE_POINT).iterator();
Diego Garcia09ab5e22018-12-18 11:47:01 +0100143 while (iter.hasNext()) {
144 JsonNode sipAttributes = iter.next();
145 if (checkValidEndpoint(sipAttributes)) {
146 String uuid = sipAttributes.get(UUID).textValue();
Boyuan Yan8f9f6ad2019-06-12 16:54:42 -0700147 String[] uuidSeg = uuid.split("-");
148 PortNumber portNumber = PortNumber.portNumber(uuidSeg[uuidSeg.length - 1]);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100149 annotations.set(UUID, uuid);
150
Diego Garcia09ab5e22018-12-18 11:47:01 +0100151 JsonNode mcPool = sipAttributes.get(MEDIA_CHANNEL_SERVICE_INTERFACE_POINT_SPEC).get(MC_POOL);
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100152 // We get the first OCH signal as reported by the device.
153 OchSignal ochSignal = getOchSignal(mcPool).iterator().next();
154 //add och port
155 ports.add(ochPortDescription(portNumber, true, OduSignalType.ODU4,
156 false, ochSignal, annotations.build()));
Diego Garcia09ab5e22018-12-18 11:47:01 +0100157
Diego Garciaaab99472019-01-10 13:53:31 +0100158
Diego Garcia09ab5e22018-12-18 11:47:01 +0100159 } else {
160 log.error("SIP {} is not valid", sipAttributes);
161 }
162 }
163 log.debug("PortList: {}", ports);
164 return ImmutableList.copyOf(ports);
165 }
166
167 /**
168 * Create a filter method to identify just valid OLS SIPs.This method must check the
169 * tapi object: "layer-protocol-name" and matching only if equals to "PHOTONIC-MEDIA" SIPs.
170 * Moreover,the filtering could be enhanced by reading also:
171 * "supported-layer-protocol-qualifier", to identify valid protocol-qualifier values such:
172 * [PHOTONIC_LAYER_QUALIFIER_NMC, PHOTONIC_LAYER_QUALIFIER_NMCA, PHOTONIC_LAYER_QUALIFIER_OTSI...]
173 **/
174 private boolean checkValidEndpoint(JsonNode sipAttributes) {
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100175 return sipAttributes.has(LAYER_PROTOCOL_NAME) &&
176 sipAttributes.get(LAYER_PROTOCOL_NAME).toString().contains(PHOTONIC_MEDIA) &&
177 sipAttributes.has(SUPPORTED_LAYER_PROTOCOL_QUALIFIER) &&
Diego Garcia09ab5e22018-12-18 11:47:01 +0100178 sipAttributes.get(SUPPORTED_LAYER_PROTOCOL_QUALIFIER).toString()
Andrea Campanellab9e491b2019-02-18 17:45:01 +0100179 .contains(PHOTONIC_LAYER_QUALIFIER_NMC);
Diego Garcia09ab5e22018-12-18 11:47:01 +0100180 }
181
Diego Garcia09ab5e22018-12-18 11:47:01 +0100182}