blob: edbe3101f9bb36870bf0bff56cb631a7771dab6a [file] [log] [blame]
Thomas Vachuska9252bc32014-10-23 02:33:25 -07001/*
Ray Milkey34c95902015-04-15 09:47:53 -07002 * Copyright 2014-2015 Open Networking Laboratory
Thomas Vachuska9252bc32014-10-23 02:33:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska9252bc32014-10-23 02:33:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska9252bc32014-10-23 02:33:25 -070015 */
Jonathan Hart9bb32ab2015-05-05 18:17:31 -070016package org.onosproject.rest.resources;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070017
18import com.fasterxml.jackson.databind.JsonNode;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070019import com.google.common.collect.Lists;
Ayaka Koshibeae541732015-05-19 13:37:27 -070020
Thomas Vachuskac40d4632015-04-09 16:55:03 -070021import org.onlab.packet.ChassisId;
22import org.onlab.packet.IpAddress;
23import org.onlab.packet.MacAddress;
24import org.onlab.packet.VlanId;
Ayaka Koshibeae541732015-05-19 13:37:27 -070025import org.onlab.util.Frequency;
26import org.onosproject.net.ChannelSpacing;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.net.ConnectPoint;
28import org.onosproject.net.DefaultAnnotations;
29import org.onosproject.net.Device;
30import org.onosproject.net.DeviceId;
Ayaka Koshibeae541732015-05-19 13:37:27 -070031import org.onosproject.net.GridType;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.Host;
33import org.onosproject.net.HostId;
34import org.onosproject.net.HostLocation;
35import org.onosproject.net.Link;
36import org.onosproject.net.MastershipRole;
Ayaka Koshibeae541732015-05-19 13:37:27 -070037import org.onosproject.net.OchPort;
38import org.onosproject.net.OchSignal;
39import org.onosproject.net.OduCltPort;
40import org.onosproject.net.OduSignalType;
41import org.onosproject.net.OmsPort;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.Port;
43import org.onosproject.net.SparseAnnotations;
44import org.onosproject.net.device.DefaultDeviceDescription;
45import org.onosproject.net.device.DefaultPortDescription;
46import org.onosproject.net.device.DeviceDescription;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070047import org.onosproject.net.device.DeviceEvent;
48import org.onosproject.net.device.DeviceListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.net.device.DeviceProvider;
50import org.onosproject.net.device.DeviceProviderRegistry;
51import org.onosproject.net.device.DeviceProviderService;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070052import org.onosproject.net.device.DeviceService;
Ayaka Koshibeae541732015-05-19 13:37:27 -070053import org.onosproject.net.device.OchPortDescription;
54import org.onosproject.net.device.OduCltPortDescription;
55import org.onosproject.net.device.OmsPortDescription;
Brian O'Connorabafb502014-12-02 22:26:20 -080056import org.onosproject.net.device.PortDescription;
57import org.onosproject.net.host.DefaultHostDescription;
58import org.onosproject.net.host.HostProvider;
59import org.onosproject.net.host.HostProviderRegistry;
60import org.onosproject.net.host.HostProviderService;
61import org.onosproject.net.link.DefaultLinkDescription;
62import org.onosproject.net.link.LinkProvider;
63import org.onosproject.net.link.LinkProviderRegistry;
64import org.onosproject.net.link.LinkProviderService;
65import org.onosproject.net.provider.ProviderId;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070066import org.slf4j.Logger;
67import org.slf4j.LoggerFactory;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070068
69import java.net.URI;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070070import java.util.ArrayList;
Thomas Vachuskaece59ee2014-11-19 19:06:11 -080071import java.util.HashSet;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070072import java.util.Iterator;
Thomas Vachuskad16ce182014-10-29 17:25:29 -070073import java.util.List;
Thomas Vachuskaece59ee2014-11-19 19:06:11 -080074import java.util.Set;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070075import java.util.concurrent.CountDownLatch;
76import java.util.concurrent.TimeUnit;
77import java.util.stream.Collectors;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070078
79import static com.google.common.base.Preconditions.checkNotNull;
Brian O'Connorabafb502014-12-02 22:26:20 -080080import static org.onosproject.net.DeviceId.deviceId;
81import static org.onosproject.net.PortNumber.portNumber;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070082import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
83import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
Thomas Vachuska9252bc32014-10-23 02:33:25 -070084
85/**
86 * Provider of devices and links parsed from a JSON configuration structure.
87 */
88class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider {
89
Thomas Vachuskac40d4632015-04-09 16:55:03 -070090 private final Logger log = LoggerFactory.getLogger(getClass());
91
Thomas Vachuska9252bc32014-10-23 02:33:25 -070092 private static final ProviderId PID =
Brian O'Connorabafb502014-12-02 22:26:20 -080093 new ProviderId("cfg", "org.onosproject.rest", true);
Thomas Vachuska9252bc32014-10-23 02:33:25 -070094
Thomas Vachuskac40d4632015-04-09 16:55:03 -070095 private static final String UNKNOWN = "unknown";
96
Ayaka Koshibeae541732015-05-19 13:37:27 -070097 private static final Frequency CENTER = Frequency.ofTHz(193.1);
98 // C-band has 4.4 THz (4,400 GHz) total bandwidth
99 private static final Frequency TOTAL = Frequency.ofTHz(4.4);
100
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700101 private CountDownLatch deviceLatch;
102
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700103 private final JsonNode cfg;
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700104 private final DeviceService deviceService;
105
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700106 private final DeviceProviderRegistry deviceProviderRegistry;
107 private final LinkProviderRegistry linkProviderRegistry;
108 private final HostProviderRegistry hostProviderRegistry;
109
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700110 private DeviceProviderService deviceProviderService;
111 private LinkProviderService linkProviderService;
112 private HostProviderService hostProviderService;
113
114 private DeviceListener deviceEventCounter = new DeviceEventCounter();
115 private List<ConnectPoint> connectPoints = Lists.newArrayList();
116
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700117 /**
118 * Creates a new configuration provider.
119 *
120 * @param cfg JSON configuration
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700121 * @param deviceService device service
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700122 * @param deviceProviderRegistry device provider registry
123 * @param linkProviderRegistry link provider registry
124 * @param hostProviderRegistry host provider registry
125 */
126 ConfigProvider(JsonNode cfg,
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700127 DeviceService deviceService,
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700128 DeviceProviderRegistry deviceProviderRegistry,
129 LinkProviderRegistry linkProviderRegistry,
130 HostProviderRegistry hostProviderRegistry) {
131 this.cfg = checkNotNull(cfg, "Configuration cannot be null");
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700132 this.deviceService = checkNotNull(deviceService, "Device service cannot be null");
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700133 this.deviceProviderRegistry = checkNotNull(deviceProviderRegistry, "Device provider registry cannot be null");
134 this.linkProviderRegistry = checkNotNull(linkProviderRegistry, "Link provider registry cannot be null");
135 this.hostProviderRegistry = checkNotNull(hostProviderRegistry, "Host provider registry cannot be null");
136 }
137
138 /**
139 * Parses the given JSON and provides links as configured.
140 */
141 void parse() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700142 try {
143 register();
144 parseDevices();
145 parseLinks();
146 parseHosts();
147 addMissingPorts();
148 } finally {
149 unregister();
150 }
151 }
152
153 private void register() {
154 deviceProviderService = deviceProviderRegistry.register(this);
155 linkProviderService = linkProviderRegistry.register(this);
156 hostProviderService = hostProviderRegistry.register(this);
157 }
158
159 private void unregister() {
160 deviceProviderRegistry.unregister(this);
161 linkProviderRegistry.unregister(this);
162 hostProviderRegistry.unregister(this);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700163 }
164
165 // Parses the given JSON and provides devices.
166 private void parseDevices() {
167 try {
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700168 JsonNode nodes = cfg.get("devices");
169 if (nodes != null) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700170 prepareForDeviceEvents(nodes.size());
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700171 for (JsonNode node : nodes) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700172 parseDevice(node);
Thomas Vachuska3b84c862015-04-28 12:09:48 -0700173
174 // FIXME: hack to make sure device attributes take
175 // This will be fixed when GossipDeviceStore uses ECM
176 parseDevice(node);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700177 }
178 }
179 } finally {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700180 waitForDeviceEvents();
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700181 }
182 }
183
184 // Parses the given node with device data and supplies the device.
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700185 private void parseDevice(JsonNode node) {
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700186 URI uri = URI.create(get(node, "uri"));
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700187 Device.Type type = Device.Type.valueOf(get(node, "type", "SWITCH"));
188 String mfr = get(node, "mfr", UNKNOWN);
189 String hw = get(node, "hw", UNKNOWN);
190 String sw = get(node, "sw", UNKNOWN);
191 String serial = get(node, "serial", UNKNOWN);
192 ChassisId cid = new ChassisId(get(node, "mac", "000000000000"));
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700193 SparseAnnotations annotations = annotations(node.get("annotations"));
194
195 DeviceDescription desc =
196 new DefaultDeviceDescription(uri, type, mfr, hw, sw, serial,
197 cid, annotations);
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700198 DeviceId deviceId = deviceId(uri);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700199 deviceProviderService.deviceConnected(deviceId, desc);
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700200
201 JsonNode ports = node.get("ports");
202 if (ports != null) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700203 parsePorts(deviceId, ports);
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700204 }
205 }
206
207 // Parses the given node with list of device ports.
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700208 private void parsePorts(DeviceId deviceId, JsonNode nodes) {
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700209 List<PortDescription> ports = new ArrayList<>();
210 for (JsonNode node : nodes) {
211 ports.add(parsePort(node));
212 }
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700213 deviceProviderService.updatePorts(deviceId, ports);
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700214 }
215
216 // Parses the given node with port information.
217 private PortDescription parsePort(JsonNode node) {
218 Port.Type type = Port.Type.valueOf(node.path("type").asText("COPPER"));
Ayaka Koshibeae541732015-05-19 13:37:27 -0700219 switch (type) {
220 case COPPER:
221 return new DefaultPortDescription(portNumber(node.path("port").asLong(0)),
222 node.path("enabled").asBoolean(true),
223 type, node.path("speed").asLong(1_000));
224 case FIBER:
225 // Currently, assume OMS when FIBER. Provide sane defaults.
226 return new OmsPortDescription(portNumber(node.path("port").asLong(0)),
227 node.path("enabled").asBoolean(true),
228 CENTER,
229 CENTER.add(TOTAL),
230 Frequency.ofGHz(100));
231 default:
232 log.warn("{}: Unsupported Port Type");
233 }
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700234 return new DefaultPortDescription(portNumber(node.path("port").asLong(0)),
235 node.path("enabled").asBoolean(true),
236 type, node.path("speed").asLong(1_000));
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700237 }
238
239 // Parses the given JSON and provides links as configured.
240 private void parseLinks() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700241 JsonNode nodes = cfg.get("links");
242 if (nodes != null) {
243 for (JsonNode node : nodes) {
244 parseLink(node, false);
245 if (!node.has("halfplex")) {
246 parseLink(node, true);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700247 }
248 }
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700249 }
250 }
251
252 // Parses the given node with link data and supplies the link.
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700253 private void parseLink(JsonNode node, boolean reverse) {
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700254 ConnectPoint src = connectPoint(get(node, "src"));
255 ConnectPoint dst = connectPoint(get(node, "dst"));
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700256 Link.Type type = Link.Type.valueOf(get(node, "type", "DIRECT"));
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700257 SparseAnnotations annotations = annotations(node.get("annotations"));
Ayaka Koshibeae541732015-05-19 13:37:27 -0700258 // take annotations to update optical ports with correct attributes.
259 updatePorts(src, dst, annotations);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700260 DefaultLinkDescription desc = reverse ?
261 new DefaultLinkDescription(dst, src, type, annotations) :
262 new DefaultLinkDescription(src, dst, type, annotations);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700263 linkProviderService.linkDetected(desc);
264
265 connectPoints.add(src);
266 connectPoints.add(dst);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700267 }
268
Ayaka Koshibeae541732015-05-19 13:37:27 -0700269 private void updatePorts(ConnectPoint src, ConnectPoint dst, SparseAnnotations annotations) {
270 DeviceId srcId = src.deviceId();
271 DeviceId dstId = dst.deviceId();
272 Port srcPort = deviceService.getPort(srcId, src.port());
273 Port dstPort = deviceService.getPort(dstId, dst.port());
274
275 final String linkType = annotations.value("optical.type");
276 if ("cross-connect".equals(linkType)) {
277 String value = annotations.value("bandwidth").trim();
278 try {
279 double bw = Double.parseDouble(value);
280 updateOchPort(bw, srcPort, dstPort, srcId, dstId);
281 } catch (NumberFormatException e) {
282 log.warn("Invalid bandwidth ({}), can't configure port(s)", value);
283 return;
284 }
285 } else if ("WDM".equals(linkType)) {
286 String value = annotations.value("optical.waves").trim();
287 try {
288 int numChls = Integer.parseInt(value);
289 updateOMSPorts(numChls, srcPort, dstPort, srcId, dstId);
290 } catch (NumberFormatException e) {
291 log.warn("Invalid channel ({}), can't configure port(s)", value);
292 return;
293 }
294 }
295 }
296
297 // uses 'bandwidth' annotation to determine the channel spacing.
298 private void updateOchPort(double bw, Port srcPort, Port dstPort, DeviceId srcId, DeviceId dstId) {
299 Device src = deviceService.getDevice(srcId);
300 Device dst = deviceService.getDevice(dstId);
301 // bandwidth in MHz (assuming Hz - linc is not clear if Hz or b).
302 Frequency spacing = Frequency.ofMHz(bw);
303 // channel bandwidth is smaller than smallest standard channel spacing.
304 ChannelSpacing chsp = null;
305 if (spacing.compareTo(ChannelSpacing.CHL_6P25GHZ.frequency()) <= 0) {
306 chsp = ChannelSpacing.CHL_6P25GHZ;
307 }
308 for (int i = 1; i < ChannelSpacing.values().length; i++) {
309 Frequency val = ChannelSpacing.values()[i].frequency();
310 // pick the next highest or equal channel interval.
311 if (val.isLessThan(spacing)) {
312 chsp = ChannelSpacing.values()[i - 1];
313 break;
314 }
315 }
316 if (chsp == null) {
317 log.warn("Invalid channel spacing ({}), can't configure port(s)", spacing);
318 return;
319 }
320 OchSignal signal = new OchSignal(GridType.DWDM, chsp, 1, 1);
321 if (src.type() == Device.Type.ROADM) {
322 PortDescription portDesc = new OchPortDescription(srcPort.number(), srcPort.isEnabled(),
323 OduSignalType.ODU4, true, signal);
324 deviceProviderService.portStatusChanged(srcId, portDesc);
325 }
326 if (dst.type() == Device.Type.ROADM) {
327 PortDescription portDesc = new OchPortDescription(dstPort.number(), dstPort.isEnabled(),
328 OduSignalType.ODU4, true, signal);
329 deviceProviderService.portStatusChanged(dstId, portDesc);
330 }
331 }
332
333 private void updateOMSPorts(int numChls, Port srcPort, Port dstPort, DeviceId srcId, DeviceId dstId) {
334 // round down to largest slot that allows numChl channels to fit into C
335 // band range
336 ChannelSpacing chl = null;
337 Frequency perChl = TOTAL.floorDivision(numChls);
338 for (int i = 0; i < ChannelSpacing.values().length; i++) {
339 Frequency val = ChannelSpacing.values()[i].frequency();
340 if (val.isLessThan(perChl)) {
341 chl = ChannelSpacing.values()[i];
342 break;
343 }
344 }
345 if (chl == null) {
346 chl = ChannelSpacing.CHL_6P25GHZ;
347 }
348
349 // if true, there was less channels than can be tightly packed.
350 Frequency grid = (chl == null) ? Frequency.ofGHz(100) : chl.frequency();
351 // say Linc's 1st slot starts at CENTER and goes up from there.
352 Frequency min = CENTER.add(grid);
353 Frequency max = CENTER.add(grid.multiply(numChls));
354
355 PortDescription srcPortDesc = new OmsPortDescription(srcPort.number(), srcPort.isEnabled(), min, max, grid);
356 PortDescription dstPortDesc = new OmsPortDescription(dstPort.number(), dstPort.isEnabled(), min, max, grid);
357 deviceProviderService.portStatusChanged(srcId, srcPortDesc);
358 deviceProviderService.portStatusChanged(dstId, dstPortDesc);
359 }
360
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700361 // Parses the given JSON and provides hosts as configured.
362 private void parseHosts() {
363 try {
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700364 JsonNode nodes = cfg.get("hosts");
365 if (nodes != null) {
366 for (JsonNode node : nodes) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700367 parseHost(node);
Thomas Vachuska3b84c862015-04-28 12:09:48 -0700368
369 // FIXME: hack to make sure host attributes take
370 // This will be fixed when GossipHostStore uses ECM
371 parseHost(node);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700372 }
373 }
374 } finally {
375 hostProviderRegistry.unregister(this);
376 }
377 }
378
379 // Parses the given node with host data and supplies the host.
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700380 private void parseHost(JsonNode node) {
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700381 MacAddress mac = MacAddress.valueOf(get(node, "mac"));
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700382 VlanId vlanId = VlanId.vlanId((short) node.get("vlan").asInt(VlanId.UNTAGGED));
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700383 HostId hostId = HostId.hostId(mac, vlanId);
384 SparseAnnotations annotations = annotations(node.get("annotations"));
385 HostLocation location = new HostLocation(connectPoint(get(node, "location")), 0);
Thomas Vachuskaece59ee2014-11-19 19:06:11 -0800386
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700387 String[] ipStrings = get(node, "ip", "").split(",");
Thomas Vachuskaece59ee2014-11-19 19:06:11 -0800388 Set<IpAddress> ips = new HashSet<>();
389 for (String ip : ipStrings) {
390 ips.add(IpAddress.valueOf(ip.trim()));
391 }
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700392
393 DefaultHostDescription desc =
Thomas Vachuskaece59ee2014-11-19 19:06:11 -0800394 new DefaultHostDescription(mac, vlanId, location, ips, annotations);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700395 hostProviderService.hostDetected(hostId, desc);
396
397 connectPoints.add(location);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700398 }
399
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700400 // Adds any missing device ports for configured links and host locations.
401 private void addMissingPorts() {
402 deviceService.getDevices().forEach(this::addMissingPorts);
403 }
404
405 // Adds any missing device ports.
406 private void addMissingPorts(Device device) {
407 List<Port> ports = deviceService.getPorts(device.id());
408 Set<ConnectPoint> existing = ports.stream()
409 .map(p -> new ConnectPoint(device.id(), p.number()))
410 .collect(Collectors.toSet());
411 Set<ConnectPoint> missing = connectPoints.stream()
412 .filter(cp -> !existing.contains(cp))
413 .collect(Collectors.toSet());
414
415 if (!missing.isEmpty()) {
416 List<PortDescription> newPorts = Lists.newArrayList();
417 ports.forEach(p -> newPorts.add(description(p)));
418 missing.forEach(cp -> newPorts.add(description(cp)));
419 deviceProviderService.updatePorts(device.id(), newPorts);
420 }
421 }
422
423 // Creates a port description from the specified port.
424 private PortDescription description(Port p) {
Ayaka Koshibeae541732015-05-19 13:37:27 -0700425 switch (p.type()) {
426 case OMS:
427 OmsPort op = (OmsPort) p;
428 return new OmsPortDescription(
429 op.number(), op.isEnabled(), op.minFrequency(), op.maxFrequency(), op.grid());
430 case OCH:
431 OchPort ochp = (OchPort) p;
432 return new OchPortDescription(
433 ochp.number(), ochp.isEnabled(), ochp.signalType(), ochp.isTunable(), ochp.lambda());
434 case ODUCLT:
435 OduCltPort odup = (OduCltPort) p;
436 return new OduCltPortDescription(
437 odup.number(), odup.isEnabled(), odup.signalType());
438 default:
439 return new DefaultPortDescription(p.number(), p.isEnabled(), p.type(), p.portSpeed());
440 }
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700441 }
442
443 // Creates a port description from the specified connection point.
444 private PortDescription description(ConnectPoint cp) {
Ayaka Koshibeae541732015-05-19 13:37:27 -0700445 Port p = deviceService.getPort(cp.deviceId(), cp.port());
446 if (p == null) {
447 return new DefaultPortDescription(cp.port(), true);
448 }
449 return description(p);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700450 }
451
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700452 // Produces set of annotations from the given JSON node.
453 private SparseAnnotations annotations(JsonNode node) {
454 if (node == null) {
455 return null;
456 }
457
458 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
459 Iterator<String> it = node.fieldNames();
460 while (it.hasNext()) {
461 String k = it.next();
462 builder.set(k, node.get(k).asText());
463 }
464 return builder.build();
465 }
466
467 // Produces a connection point from the specified uri/port text.
468 private ConnectPoint connectPoint(String text) {
469 int i = text.lastIndexOf("/");
470 return new ConnectPoint(deviceId(text.substring(0, i)),
471 portNumber(text.substring(i + 1)));
472 }
473
474 // Returns string form of the named property in the given JSON object.
475 private String get(JsonNode node, String name) {
476 return node.path(name).asText();
477 }
478
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700479 // Returns string form of the named property in the given JSON object.
480 private String get(JsonNode node, String name, String defaultValue) {
481 return node.path(name).asText(defaultValue);
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700482 }
483
484 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700485 public void roleChanged(DeviceId device, MastershipRole newRole) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700486 deviceProviderService.receivedRoleReply(device, newRole, newRole);
487 }
488
489 @Override
490 public void triggerProbe(DeviceId deviceId) {
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700491 }
492
493 @Override
494 public void triggerProbe(Host host) {
495 }
496
497 @Override
498 public ProviderId id() {
499 return PID;
500 }
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700501
502 @Override
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700503 public boolean isReachable(DeviceId device) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700504 return true;
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700505 }
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700506
507 /**
508 * Prepares to count device added/available/removed events.
509 *
510 * @param count number of events to count
511 */
512 protected void prepareForDeviceEvents(int count) {
513 deviceLatch = new CountDownLatch(count);
514 deviceService.addListener(deviceEventCounter);
515 }
516
517 /**
518 * Waits for all expected device added/available/removed events.
519 */
520 protected void waitForDeviceEvents() {
521 try {
522 deviceLatch.await(2, TimeUnit.SECONDS);
523 } catch (InterruptedException e) {
524 log.warn("Device events did not arrive in time");
525 }
526 deviceService.removeListener(deviceEventCounter);
527 }
528
529 // Counts down number of device added/available/removed events.
530 private class DeviceEventCounter implements DeviceListener {
531 @Override
532 public void event(DeviceEvent event) {
533 DeviceEvent.Type type = event.type();
534 if (type == DEVICE_ADDED || type == DEVICE_AVAILABILITY_CHANGED) {
535 deviceLatch.countDown();
536 }
537 }
538 }
539
Thomas Vachuska9252bc32014-10-23 02:33:25 -0700540}