blob: e04bad9dcd4bacff1d1eb86111f8215b82afed38 [file] [log] [blame]
Jimmy Yanda878fc2016-09-02 16:32:01 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jimmy Yanda878fc2016-09-02 16:32:01 -07003 *
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 */
16package org.onosproject.roadm;
17
MaoLu2846b112017-05-15 17:18:55 -070018import com.google.common.collect.ImmutableMap;
Jimmy Yanda878fc2016-09-02 16:32:01 -070019import com.google.common.collect.Range;
Jimmy Yanda878fc2016-09-02 16:32:01 -070020import org.onosproject.core.ApplicationId;
21import org.onosproject.core.CoreService;
22import org.onosproject.net.ChannelSpacing;
MaoLu937cf422017-03-03 23:31:46 -080023import org.onosproject.net.ConnectPoint;
Jimmy Yanda878fc2016-09-02 16:32:01 -070024import org.onosproject.net.Device;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.Direction;
27import org.onosproject.net.OchSignal;
28import org.onosproject.net.OchSignalType;
29import org.onosproject.net.Port;
30import org.onosproject.net.PortNumber;
31import org.onosproject.net.behaviour.LambdaQuery;
32import org.onosproject.net.behaviour.PowerConfig;
MaoLu937cf422017-03-03 23:31:46 -080033import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointState;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070034import org.onosproject.net.behaviour.protection.ProtectionConfigBehaviour;
MaoLu937cf422017-03-03 23:31:46 -080035import org.onosproject.net.behaviour.protection.TransportEndpointState;
Jimmy Yanda878fc2016-09-02 16:32:01 -070036import org.onosproject.net.device.DeviceEvent;
37import org.onosproject.net.device.DeviceListener;
38import org.onosproject.net.device.DeviceService;
39import org.onosproject.net.flow.DefaultFlowRule;
40import org.onosproject.net.flow.DefaultTrafficSelector;
41import org.onosproject.net.flow.DefaultTrafficTreatment;
42import org.onosproject.net.flow.FlowEntry;
43import org.onosproject.net.flow.FlowId;
44import org.onosproject.net.flow.FlowRule;
45import org.onosproject.net.flow.FlowRuleService;
46import org.onosproject.net.flow.TrafficSelector;
47import org.onosproject.net.flow.TrafficTreatment;
48import org.onosproject.net.flow.criteria.Criteria;
49import org.onosproject.net.flow.instructions.Instructions;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070050import org.osgi.service.component.annotations.Activate;
51import org.osgi.service.component.annotations.Component;
52import org.osgi.service.component.annotations.Deactivate;
53import org.osgi.service.component.annotations.Reference;
54import org.osgi.service.component.annotations.ReferenceCardinality;
Jimmy Yanda878fc2016-09-02 16:32:01 -070055import org.slf4j.Logger;
56import org.slf4j.LoggerFactory;
57
58import java.util.Collections;
59import java.util.List;
MaoLu937cf422017-03-03 23:31:46 -080060import java.util.Map;
Jimmy Yanda878fc2016-09-02 16:32:01 -070061import java.util.Optional;
62import java.util.Set;
MaoLu937cf422017-03-03 23:31:46 -080063import java.util.concurrent.ExecutionException;
Jimmy Yanda878fc2016-09-02 16:32:01 -070064import java.util.concurrent.TimeUnit;
65
66import static com.google.common.base.Preconditions.checkNotNull;
MaoLu2846b112017-05-15 17:18:55 -070067import static org.onosproject.net.optical.OpticalAnnotations.INPUT_PORT_STATUS;
68import static org.onosproject.roadm.RoadmUtil.OPS_OPT_AUTO;
69import static org.onosproject.roadm.RoadmUtil.OPS_OPT_FORCE;
70import static org.onosproject.roadm.RoadmUtil.OPS_OPT_MANUAL;
Jimmy Yanda878fc2016-09-02 16:32:01 -070071
72/**
73 * Application for monitoring and configuring ROADM devices.
74 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070075@Component(immediate = true, service = RoadmService.class)
Jimmy Yanda878fc2016-09-02 16:32:01 -070076public class RoadmManager implements RoadmService {
77
78 private static final String APP_NAME = "org.onosproject.roadm";
79 private ApplicationId appId;
80
81 private final Logger log = LoggerFactory.getLogger(getClass());
82
83 private DeviceListener deviceListener = new InternalDeviceListener();
84
Ray Milkeyd84f89b2018-08-17 14:54:17 -070085 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jimmy Yanda878fc2016-09-02 16:32:01 -070086 protected RoadmStore roadmStore;
87
Ray Milkeyd84f89b2018-08-17 14:54:17 -070088 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jimmy Yanda878fc2016-09-02 16:32:01 -070089 protected CoreService coreService;
90
Ray Milkeyd84f89b2018-08-17 14:54:17 -070091 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jimmy Yanda878fc2016-09-02 16:32:01 -070092 protected DeviceService deviceService;
93
Ray Milkeyd84f89b2018-08-17 14:54:17 -070094 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Jimmy Yanda878fc2016-09-02 16:32:01 -070095 protected FlowRuleService flowRuleService;
96
97 @Activate
98 protected void activate() {
99 appId = coreService.registerApplication(APP_NAME);
100 deviceService.addListener(deviceListener);
101 initDevices();
102
103 log.info("Started");
104 }
105
106 @Deactivate
107 protected void deactivate() {
108 deviceService.removeListener(deviceListener);
109
110 log.info("Stopped");
111 }
112
MaoLu2846b112017-05-15 17:18:55 -0700113 @Deprecated
MaoLu937cf422017-03-03 23:31:46 -0800114 @Override
115 public void setProtectionSwitchWorkingPath(DeviceId deviceId, int index) {
116 checkNotNull(deviceId);
117 ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
118 if (behaviour == null) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700119 return;
120 }
MaoLu937cf422017-03-03 23:31:46 -0800121 Map<ConnectPoint, ProtectedTransportEndpointState> map = getProtectionSwitchStates(behaviour);
122 if (map == null) {
123 log.warn("Failed to get protected transport endpoint state in device {}", deviceId);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700124 return;
125 }
MaoLu937cf422017-03-03 23:31:46 -0800126 if (map.isEmpty()) {
127 log.warn("No protected transport endpoint state found in device {}", deviceId);
128 return;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700129 }
Ray Milkey4f7e3632019-02-19 15:35:20 -0800130 behaviour.switchToManual(map.keySet().toArray(new ConnectPoint[0])[0], index);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700131 }
132
MaoLu2846b112017-05-15 17:18:55 -0700133 @Deprecated
MaoLu937cf422017-03-03 23:31:46 -0800134 @Override
135 public String getProtectionSwitchPortState(DeviceId deviceId, PortNumber portNumber) {
136 checkNotNull(deviceId);
137 ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
138 if (behaviour == null) {
139 return null;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700140 }
MaoLu937cf422017-03-03 23:31:46 -0800141 Map<ConnectPoint, ProtectedTransportEndpointState> map = getProtectionSwitchStates(behaviour);
142 if (map == null) {
143 log.warn("Failed to get protected transport endpoint state in device {}", deviceId);
144 return null;
145 }
146 for (ProtectedTransportEndpointState state : map.values()) {
147 for (TransportEndpointState element : state.pathStates()) {
148 if (element.description().output().connectPoint().port().equals(portNumber)) {
MaoLu2846b112017-05-15 17:18:55 -0700149 return element.attributes().get(INPUT_PORT_STATUS);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700150 }
Jimmy Yanda878fc2016-09-02 16:32:01 -0700151 }
152 }
MaoLudd5a00b2017-03-14 11:19:48 -0700153 // Do not need warning here for port polling.
154 log.debug("Unable to get port status, device: {}, port: {}", deviceId, portNumber);
MaoLu937cf422017-03-03 23:31:46 -0800155 return null;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700156 }
157
158 @Override
MaoLu2846b112017-05-15 17:18:55 -0700159 public void configProtectionSwitch(DeviceId deviceId, String operation, ConnectPoint identifier, int index) {
160 checkNotNull(deviceId);
161 ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
162 if (behaviour == null) {
163 return;
164 }
165 // automatic operation
166 if (OPS_OPT_AUTO.equals(operation)) {
167 behaviour.switchToAutomatic(identifier);
168 return;
169 }
170 // force or manual operation
171 if (OPS_OPT_MANUAL.equals(operation)) {
172 behaviour.switchToManual(identifier, index);
173 } else if (OPS_OPT_FORCE.equals(operation)) {
174 behaviour.switchToForce(identifier, index);
175 }
176 }
177
178 @Override
179 public Map<ConnectPoint, ProtectedTransportEndpointState> getProtectionSwitchStates(DeviceId deviceId) {
180 checkNotNull(deviceId);
181 ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
182 if (behaviour == null) {
183 return ImmutableMap.of();
184 }
185 return getProtectionSwitchStates(behaviour);
186 }
187
188
189 @Override
Jimmy Yanda878fc2016-09-02 16:32:01 -0700190 public void setTargetPortPower(DeviceId deviceId, PortNumber portNumber, long power) {
191 checkNotNull(deviceId);
192 checkNotNull(portNumber);
193 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
194 if (powerConfig != null) {
195 roadmStore.setTargetPower(deviceId, portNumber, power);
196 powerConfig.setTargetPower(portNumber, Direction.ALL, power);
197 } else {
198 log.warn("Unable to set target port power for device {}", deviceId);
199 }
200 }
201
202 @Override
203 public Long getTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
204 checkNotNull(deviceId);
205 checkNotNull(portNumber);
Boyuan Yanf3f6a8d2019-05-26 18:35:54 -0700206 // Request target port power when it doesn't exist. Inactive updating mode.
207 Long power = roadmStore.getTargetPower(deviceId, portNumber);
208 if (power == null) {
209 return syncTargetPortPower(deviceId, portNumber);
210 }
211 return power;
212 }
213
214 @Override
215 public Long syncTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
216 checkNotNull(deviceId);
217 checkNotNull(portNumber);
218 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
219 if (powerConfig != null) {
220 Optional<Long> pl = powerConfig.getTargetPower(portNumber, Direction.ALL);
221 if (pl.isPresent()) {
222 roadmStore.setTargetPower(deviceId, portNumber, pl.get());
223 return pl.get();
224 } else {
225 roadmStore.removeTargetPower(deviceId, portNumber);
226 }
227 }
228 return null;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700229 }
230
231 @Override
232 public void setAttenuation(DeviceId deviceId, PortNumber portNumber,
233 OchSignal ochSignal, long attenuation) {
234 checkNotNull(deviceId);
235 checkNotNull(portNumber);
236 checkNotNull(ochSignal);
237 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
238 if (powerConfig != null) {
239 powerConfig.setTargetPower(portNumber, ochSignal, attenuation);
240 } else {
241 log.warn("Cannot set attenuation for channel index {} on device {}",
242 ochSignal.spacingMultiplier(), deviceId);
243 }
244 }
245
246 @Override
MaoLu937cf422017-03-03 23:31:46 -0800247 public Long getAttenuation(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700248 checkNotNull(deviceId);
249 checkNotNull(portNumber);
250 checkNotNull(ochSignal);
251 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
252 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800253 Optional<Long> attenuation = powerConfig.getTargetPower(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700254 if (attenuation.isPresent()) {
255 return attenuation.get();
256 }
257 }
258 return null;
259 }
260
261 @Override
262 public Long getCurrentPortPower(DeviceId deviceId, PortNumber portNumber) {
263 checkNotNull(deviceId);
264 checkNotNull(portNumber);
265 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
266 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800267 Optional<Long> currentPower = powerConfig.currentPower(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700268 if (currentPower.isPresent()) {
269 return currentPower.get();
270 }
271 }
272 return null;
273 }
274
275 @Override
MaoLu937cf422017-03-03 23:31:46 -0800276 public Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700277 checkNotNull(deviceId);
278 checkNotNull(portNumber);
279 checkNotNull(ochSignal);
280 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
281 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800282 Optional<Long> currentPower = powerConfig.currentPower(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700283 if (currentPower.isPresent()) {
284 return currentPower.get();
285 }
286 }
287 return null;
288 }
289
290 @Override
291 public Set<OchSignal> queryLambdas(DeviceId deviceId, PortNumber portNumber) {
292 checkNotNull(deviceId);
293 checkNotNull(portNumber);
294 LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
295 if (lambdaQuery != null) {
296 return lambdaQuery.queryLambdas(portNumber);
297 }
298 return Collections.emptySet();
299 }
300
301 @Override
302 public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
MaoLu937cf422017-03-03 23:31:46 -0800303 int timeout, PortNumber inPort, PortNumber outPort, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700304 checkNotNull(deviceId);
305 checkNotNull(inPort);
306 checkNotNull(outPort);
307
MaoLu937cf422017-03-03 23:31:46 -0800308 TrafficSelector selector = DefaultTrafficSelector.builder()
309 .add(Criteria.matchInPort(inPort))
310 .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
311 .add(Criteria.matchLambda(ochSignal))
312 .build();
313 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
alessioc6f054b2019-07-22 11:05:07 +0200314 .add(Instructions.modL0Lambda(ochSignal))
MaoLu937cf422017-03-03 23:31:46 -0800315 .add(Instructions.createOutput(outPort))
316 .build();
317
318 FlowRule.Builder flowBuilder = DefaultFlowRule.builder()
319 .forDevice(deviceId)
320 .fromApp(appId)
321 .withPriority(priority)
322 .withSelector(selector)
323 .withTreatment(treatment);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700324 if (isPermanent) {
325 flowBuilder.makePermanent();
326 } else {
327 flowBuilder.makeTemporary(timeout);
328 }
Jimmy Yanda878fc2016-09-02 16:32:01 -0700329
330 FlowRule flowRule = flowBuilder.build();
331 flowRuleService.applyFlowRules(flowRule);
332
333 log.info("Created connection from input port {} to output port {}",
334 inPort.toLong(), outPort.toLong());
335
336 return flowRule.id();
337 }
338
339 @Override
340 public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
341 int timeout, PortNumber inPort, PortNumber outPort,
342 OchSignal ochSignal, long attenuation) {
343 checkNotNull(deviceId);
344 checkNotNull(inPort);
345 checkNotNull(outPort);
MaoLu937cf422017-03-03 23:31:46 -0800346 FlowId flowId = createConnection(deviceId, priority, isPermanent, timeout, inPort, outPort, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700347 delayedSetAttenuation(deviceId, outPort, ochSignal, attenuation);
348 return flowId;
349 }
350
Jimmy Yanda878fc2016-09-02 16:32:01 -0700351 @Override
352 public void removeConnection(DeviceId deviceId, FlowId flowId) {
353 checkNotNull(deviceId);
354 checkNotNull(flowId);
355 for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
356 if (entry.id().equals(flowId)) {
357 flowRuleService.removeFlowRules(entry);
358 log.info("Deleted connection {}", entry.id());
359 break;
360 }
361 }
362 }
363
364 @Override
365 public boolean hasPortTargetPower(DeviceId deviceId, PortNumber portNumber) {
366 checkNotNull(deviceId);
367 checkNotNull(portNumber);
368 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
369 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800370 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700371 return range.isPresent();
372 }
373 return false;
374 }
375
376 @Override
MaoLu937cf422017-03-03 23:31:46 -0800377 public boolean portTargetPowerInRange(DeviceId deviceId, PortNumber portNumber, long power) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700378 checkNotNull(deviceId);
379 checkNotNull(portNumber);
380 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
381 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800382 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700383 return range.isPresent() && range.get().contains(power);
384 }
385 return false;
386 }
387
388 @Override
MaoLu937cf422017-03-03 23:31:46 -0800389 public boolean attenuationInRange(DeviceId deviceId, PortNumber outPort, long att) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700390 checkNotNull(deviceId);
391 checkNotNull(outPort);
392 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
393 if (powerConfig != null) {
394 OchSignal stubOch = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 0);
MaoLu937cf422017-03-03 23:31:46 -0800395 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(outPort, stubOch);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700396 return range.isPresent() && range.get().contains(att);
397 }
398 return false;
399 }
400
401 @Override
402 public boolean validInputPort(DeviceId deviceId, PortNumber portNumber) {
403 checkNotNull(deviceId);
404 checkNotNull(portNumber);
405 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
406 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800407 Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700408 return range.isPresent();
409 }
410 return false;
411 }
412
413 @Override
414 public boolean validOutputPort(DeviceId deviceId, PortNumber portNumber) {
415 return hasPortTargetPower(deviceId, portNumber);
416 }
417
418 @Override
MaoLu937cf422017-03-03 23:31:46 -0800419 public boolean validChannel(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700420 checkNotNull(deviceId);
421 checkNotNull(portNumber);
MaoLu937cf422017-03-03 23:31:46 -0800422 checkNotNull(ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700423 LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
424 if (lambdaQuery != null) {
425 Set<OchSignal> channels = lambdaQuery.queryLambdas(portNumber);
426 return channels.contains(ochSignal);
427 }
428 return false;
429 }
430
431 @Override
432 public boolean channelAvailable(DeviceId deviceId, OchSignal ochSignal) {
433 checkNotNull(deviceId);
434 checkNotNull(ochSignal);
435 for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
436 if (ChannelData.fromFlow(entry).ochSignal().equals(ochSignal)) {
437 return false;
438 }
439 }
440 return true;
441 }
442
443 @Override
MaoLu937cf422017-03-03 23:31:46 -0800444 public boolean validConnection(DeviceId deviceId, PortNumber inPort, PortNumber outPort) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700445 checkNotNull(deviceId);
446 checkNotNull(inPort);
447 checkNotNull(outPort);
448 return validInputPort(deviceId, inPort) && validOutputPort(deviceId, outPort);
449 }
450
451 @Override
452 public Range<Long> targetPortPowerRange(DeviceId deviceId, PortNumber portNumber) {
453 checkNotNull(deviceId);
454 checkNotNull(portNumber);
455 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
456 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800457 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700458 if (range.isPresent()) {
459 return range.get();
460 }
461 }
462 return null;
463 }
464
465 @Override
MaoLu937cf422017-03-03 23:31:46 -0800466 public Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700467 checkNotNull(deviceId);
468 checkNotNull(portNumber);
469 checkNotNull(ochSignal);
470 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
471 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800472 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700473 if (range.isPresent()) {
474 return range.get();
475 }
476 }
477 return null;
478 }
479
480 @Override
481 public Range<Long> inputPortPowerRange(DeviceId deviceId, PortNumber portNumber) {
482 checkNotNull(deviceId);
483 checkNotNull(portNumber);
484 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
485 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800486 Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700487 if (range.isPresent()) {
488 return range.get();
489 }
490 }
491 return null;
492 }
493
MaoLu937cf422017-03-03 23:31:46 -0800494 private PowerConfig<Object> getPowerConfig(DeviceId deviceId) {
495 Device device = deviceService.getDevice(deviceId);
496 if (device != null && device.is(PowerConfig.class)) {
497 return device.as(PowerConfig.class);
498 }
MaoLudd5a00b2017-03-14 11:19:48 -0700499 // Do not need warning here for port polling.
500 log.debug("Unable to load PowerConfig for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800501 return null;
502 }
503
504 private LambdaQuery getLambdaQuery(DeviceId deviceId) {
505 Device device = deviceService.getDevice(deviceId);
506 if (device != null && device.is(LambdaQuery.class)) {
507 return device.as(LambdaQuery.class);
508 }
MaoLudd5a00b2017-03-14 11:19:48 -0700509 // Do not need warning here for port polling.
510 log.debug("Unable to load LambdaQuery for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800511 return null;
512 }
513
514 private ProtectionConfigBehaviour getProtectionConfig(DeviceId deviceId) {
515 Device device = deviceService.getDevice(deviceId);
516 if (device != null && device.is(ProtectionConfigBehaviour.class)) {
517 return device.as(ProtectionConfigBehaviour.class);
518 }
MaoLudd5a00b2017-03-14 11:19:48 -0700519 // Do not need warning here for port polling.
520 log.debug("Unable to load ProtectionConfigBehaviour for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800521 return null;
522 }
523
524 // Initialize all devices
525 private void initDevices() {
526 for (Device device : deviceService.getDevices(Device.Type.ROADM)) {
527 initDevice(device.id());
528 //FIXME
529 // As roadm application is a optional tool for now.
530 // The target power initialization will be enhanced later,
531 // hopefully using an formal optical subsystem.
532 // setAllInitialTargetPortPowers(device.id());
533 }
534 }
535
536 // Initialize RoadmStore for a device to support target power
537 private void initDevice(DeviceId deviceId) {
538 if (!roadmStore.deviceAvailable(deviceId)) {
539 roadmStore.addDevice(deviceId);
540 }
541 log.info("Initialized device {}", deviceId);
542 }
543
544 // Sets the target port powers for a port on a device
545 // Attempts to read target powers from store. If no value is found then
546 // default value is used instead.
547 private void setInitialTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
548 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
549 if (powerConfig == null) {
550 log.warn("Unable to set default initial powers for port {} on device {}", portNumber, deviceId);
551 return;
552 }
553
554 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
555 if (!range.isPresent()) {
556 log.warn("No target power range found for port {} on device {}", portNumber, deviceId);
557 return;
558 }
559
560 Long power = roadmStore.getTargetPower(deviceId, portNumber);
561 if (power == null) {
562 // Set default to middle of the range
563 power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
564 roadmStore.setTargetPower(deviceId, portNumber, power);
565 }
566 powerConfig.setTargetPower(portNumber, Direction.ALL, power);
567 }
568
569 // Sets the target port powers for each each port on a device
570 // Attempts to read target powers from store. If no value is found then
571 // default value is used instead
572 private void setAllInitialTargetPortPowers(DeviceId deviceId) {
573 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
574 if (powerConfig == null) {
575 log.warn("Unable to set default initial powers for device {}", deviceId);
576 return;
577 }
578
579 List<Port> ports = deviceService.getPorts(deviceId);
580 for (Port port : ports) {
581 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(port.number(), Direction.ALL);
582 if (range.isPresent()) {
583 Long power = roadmStore.getTargetPower(deviceId, port.number());
584 if (power == null) {
585 // Set default to middle of the range
586 power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
587 roadmStore.setTargetPower(deviceId, port.number(), power);
588 }
589 powerConfig.setTargetPower(port.number(), Direction.ALL, power);
590 } else {
591 log.warn("No target power range found for port {} on device {}", port.number(), deviceId);
592 }
593 }
594 }
595
596 // Delay the call to setTargetPower because the flow may not be in the store yet
alessio1bf2a632019-06-04 15:47:39 +0200597 // Tested with Lumentum ROADM-20 1 seconds was not enough, increased to 5 seconds
MaoLu937cf422017-03-03 23:31:46 -0800598 private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
599 OchSignal ochSignal, long attenuation) {
600 Runnable setAtt = () -> {
601 try {
alessio1bf2a632019-06-04 15:47:39 +0200602 TimeUnit.SECONDS.sleep(5);
MaoLu937cf422017-03-03 23:31:46 -0800603 } catch (InterruptedException e) {
604 log.warn("Thread interrupted. Setting attenuation early.");
MaoLu2846b112017-05-15 17:18:55 -0700605 Thread.currentThread().interrupt();
MaoLu937cf422017-03-03 23:31:46 -0800606 }
607 setAttenuation(deviceId, outPort, ochSignal, attenuation);
608 };
609 new Thread(setAtt).start();
610 }
611
612 // get protection endpoint states
613 private Map<ConnectPoint, ProtectedTransportEndpointState> getProtectionSwitchStates(
614 ProtectionConfigBehaviour behaviour) {
MaoLu937cf422017-03-03 23:31:46 -0800615 Map<ConnectPoint, ProtectedTransportEndpointState> map;
616 try {
MaoLu2846b112017-05-15 17:18:55 -0700617 map = behaviour.getProtectionEndpointStates().get();
MaoLu937cf422017-03-03 23:31:46 -0800618 } catch (InterruptedException e1) {
619 log.error("Interrupted.", e1);
MaoLu2846b112017-05-15 17:18:55 -0700620 Thread.currentThread().interrupt();
621 return ImmutableMap.of();
MaoLu937cf422017-03-03 23:31:46 -0800622 } catch (ExecutionException e1) {
623 log.error("Exception caught.", e1);
MaoLu2846b112017-05-15 17:18:55 -0700624 return ImmutableMap.of();
MaoLu937cf422017-03-03 23:31:46 -0800625 }
626 return map;
627 }
628
Jimmy Yanda878fc2016-09-02 16:32:01 -0700629 // Listens to device events.
630 private class InternalDeviceListener implements DeviceListener {
631 @Override
632 public void event(DeviceEvent deviceEvent) {
633 Device device = deviceEvent.subject();
634
635 switch (deviceEvent.type()) {
636 case DEVICE_ADDED:
637 case DEVICE_UPDATED:
638 initDevice(device.id());
639 break;
640 case PORT_ADDED:
641 case PORT_UPDATED:
MaoLu937cf422017-03-03 23:31:46 -0800642 //FIXME
643 // As roadm application is a optional tool for now.
644 // The target power initialization will be enhanced later,
645 // hopefully using an formal optical subsystem.
646 // setInitialTargetPortPower(device.id(), deviceEvent.port().number());
Jimmy Yanda878fc2016-09-02 16:32:01 -0700647 break;
648 default:
649 break;
650
651 }
652 }
653 }
654}