blob: a98b2520c950a2577e6c1148e914d67778ab7bca [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()
314 .add(Instructions.createOutput(outPort))
315 .build();
316
317 FlowRule.Builder flowBuilder = DefaultFlowRule.builder()
318 .forDevice(deviceId)
319 .fromApp(appId)
320 .withPriority(priority)
321 .withSelector(selector)
322 .withTreatment(treatment);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700323 if (isPermanent) {
324 flowBuilder.makePermanent();
325 } else {
326 flowBuilder.makeTemporary(timeout);
327 }
Jimmy Yanda878fc2016-09-02 16:32:01 -0700328
329 FlowRule flowRule = flowBuilder.build();
330 flowRuleService.applyFlowRules(flowRule);
331
332 log.info("Created connection from input port {} to output port {}",
333 inPort.toLong(), outPort.toLong());
334
335 return flowRule.id();
336 }
337
338 @Override
339 public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
340 int timeout, PortNumber inPort, PortNumber outPort,
341 OchSignal ochSignal, long attenuation) {
342 checkNotNull(deviceId);
343 checkNotNull(inPort);
344 checkNotNull(outPort);
MaoLu937cf422017-03-03 23:31:46 -0800345 FlowId flowId = createConnection(deviceId, priority, isPermanent, timeout, inPort, outPort, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700346 delayedSetAttenuation(deviceId, outPort, ochSignal, attenuation);
347 return flowId;
348 }
349
Jimmy Yanda878fc2016-09-02 16:32:01 -0700350 @Override
351 public void removeConnection(DeviceId deviceId, FlowId flowId) {
352 checkNotNull(deviceId);
353 checkNotNull(flowId);
354 for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
355 if (entry.id().equals(flowId)) {
356 flowRuleService.removeFlowRules(entry);
357 log.info("Deleted connection {}", entry.id());
358 break;
359 }
360 }
361 }
362
363 @Override
364 public boolean hasPortTargetPower(DeviceId deviceId, PortNumber portNumber) {
365 checkNotNull(deviceId);
366 checkNotNull(portNumber);
367 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
368 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800369 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700370 return range.isPresent();
371 }
372 return false;
373 }
374
375 @Override
MaoLu937cf422017-03-03 23:31:46 -0800376 public boolean portTargetPowerInRange(DeviceId deviceId, PortNumber portNumber, long power) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700377 checkNotNull(deviceId);
378 checkNotNull(portNumber);
379 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
380 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800381 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700382 return range.isPresent() && range.get().contains(power);
383 }
384 return false;
385 }
386
387 @Override
MaoLu937cf422017-03-03 23:31:46 -0800388 public boolean attenuationInRange(DeviceId deviceId, PortNumber outPort, long att) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700389 checkNotNull(deviceId);
390 checkNotNull(outPort);
391 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
392 if (powerConfig != null) {
393 OchSignal stubOch = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 0);
MaoLu937cf422017-03-03 23:31:46 -0800394 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(outPort, stubOch);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700395 return range.isPresent() && range.get().contains(att);
396 }
397 return false;
398 }
399
400 @Override
401 public boolean validInputPort(DeviceId deviceId, PortNumber portNumber) {
402 checkNotNull(deviceId);
403 checkNotNull(portNumber);
404 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
405 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800406 Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700407 return range.isPresent();
408 }
409 return false;
410 }
411
412 @Override
413 public boolean validOutputPort(DeviceId deviceId, PortNumber portNumber) {
414 return hasPortTargetPower(deviceId, portNumber);
415 }
416
417 @Override
MaoLu937cf422017-03-03 23:31:46 -0800418 public boolean validChannel(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700419 checkNotNull(deviceId);
420 checkNotNull(portNumber);
MaoLu937cf422017-03-03 23:31:46 -0800421 checkNotNull(ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700422 LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
423 if (lambdaQuery != null) {
424 Set<OchSignal> channels = lambdaQuery.queryLambdas(portNumber);
425 return channels.contains(ochSignal);
426 }
427 return false;
428 }
429
430 @Override
431 public boolean channelAvailable(DeviceId deviceId, OchSignal ochSignal) {
432 checkNotNull(deviceId);
433 checkNotNull(ochSignal);
434 for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
435 if (ChannelData.fromFlow(entry).ochSignal().equals(ochSignal)) {
436 return false;
437 }
438 }
439 return true;
440 }
441
442 @Override
MaoLu937cf422017-03-03 23:31:46 -0800443 public boolean validConnection(DeviceId deviceId, PortNumber inPort, PortNumber outPort) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700444 checkNotNull(deviceId);
445 checkNotNull(inPort);
446 checkNotNull(outPort);
447 return validInputPort(deviceId, inPort) && validOutputPort(deviceId, outPort);
448 }
449
450 @Override
451 public Range<Long> targetPortPowerRange(DeviceId deviceId, PortNumber portNumber) {
452 checkNotNull(deviceId);
453 checkNotNull(portNumber);
454 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
455 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800456 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700457 if (range.isPresent()) {
458 return range.get();
459 }
460 }
461 return null;
462 }
463
464 @Override
MaoLu937cf422017-03-03 23:31:46 -0800465 public Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700466 checkNotNull(deviceId);
467 checkNotNull(portNumber);
468 checkNotNull(ochSignal);
469 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
470 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800471 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700472 if (range.isPresent()) {
473 return range.get();
474 }
475 }
476 return null;
477 }
478
479 @Override
480 public Range<Long> inputPortPowerRange(DeviceId deviceId, PortNumber portNumber) {
481 checkNotNull(deviceId);
482 checkNotNull(portNumber);
483 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
484 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800485 Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700486 if (range.isPresent()) {
487 return range.get();
488 }
489 }
490 return null;
491 }
492
MaoLu937cf422017-03-03 23:31:46 -0800493 private PowerConfig<Object> getPowerConfig(DeviceId deviceId) {
494 Device device = deviceService.getDevice(deviceId);
495 if (device != null && device.is(PowerConfig.class)) {
496 return device.as(PowerConfig.class);
497 }
MaoLudd5a00b2017-03-14 11:19:48 -0700498 // Do not need warning here for port polling.
499 log.debug("Unable to load PowerConfig for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800500 return null;
501 }
502
503 private LambdaQuery getLambdaQuery(DeviceId deviceId) {
504 Device device = deviceService.getDevice(deviceId);
505 if (device != null && device.is(LambdaQuery.class)) {
506 return device.as(LambdaQuery.class);
507 }
MaoLudd5a00b2017-03-14 11:19:48 -0700508 // Do not need warning here for port polling.
509 log.debug("Unable to load LambdaQuery for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800510 return null;
511 }
512
513 private ProtectionConfigBehaviour getProtectionConfig(DeviceId deviceId) {
514 Device device = deviceService.getDevice(deviceId);
515 if (device != null && device.is(ProtectionConfigBehaviour.class)) {
516 return device.as(ProtectionConfigBehaviour.class);
517 }
MaoLudd5a00b2017-03-14 11:19:48 -0700518 // Do not need warning here for port polling.
519 log.debug("Unable to load ProtectionConfigBehaviour for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800520 return null;
521 }
522
523 // Initialize all devices
524 private void initDevices() {
525 for (Device device : deviceService.getDevices(Device.Type.ROADM)) {
526 initDevice(device.id());
527 //FIXME
528 // As roadm application is a optional tool for now.
529 // The target power initialization will be enhanced later,
530 // hopefully using an formal optical subsystem.
531 // setAllInitialTargetPortPowers(device.id());
532 }
533 }
534
535 // Initialize RoadmStore for a device to support target power
536 private void initDevice(DeviceId deviceId) {
537 if (!roadmStore.deviceAvailable(deviceId)) {
538 roadmStore.addDevice(deviceId);
539 }
540 log.info("Initialized device {}", deviceId);
541 }
542
543 // Sets the target port powers for a port on a device
544 // Attempts to read target powers from store. If no value is found then
545 // default value is used instead.
546 private void setInitialTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
547 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
548 if (powerConfig == null) {
549 log.warn("Unable to set default initial powers for port {} on device {}", portNumber, deviceId);
550 return;
551 }
552
553 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
554 if (!range.isPresent()) {
555 log.warn("No target power range found for port {} on device {}", portNumber, deviceId);
556 return;
557 }
558
559 Long power = roadmStore.getTargetPower(deviceId, portNumber);
560 if (power == null) {
561 // Set default to middle of the range
562 power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
563 roadmStore.setTargetPower(deviceId, portNumber, power);
564 }
565 powerConfig.setTargetPower(portNumber, Direction.ALL, power);
566 }
567
568 // Sets the target port powers for each each port on a device
569 // Attempts to read target powers from store. If no value is found then
570 // default value is used instead
571 private void setAllInitialTargetPortPowers(DeviceId deviceId) {
572 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
573 if (powerConfig == null) {
574 log.warn("Unable to set default initial powers for device {}", deviceId);
575 return;
576 }
577
578 List<Port> ports = deviceService.getPorts(deviceId);
579 for (Port port : ports) {
580 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(port.number(), Direction.ALL);
581 if (range.isPresent()) {
582 Long power = roadmStore.getTargetPower(deviceId, port.number());
583 if (power == null) {
584 // Set default to middle of the range
585 power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
586 roadmStore.setTargetPower(deviceId, port.number(), power);
587 }
588 powerConfig.setTargetPower(port.number(), Direction.ALL, power);
589 } else {
590 log.warn("No target power range found for port {} on device {}", port.number(), deviceId);
591 }
592 }
593 }
594
595 // Delay the call to setTargetPower because the flow may not be in the store yet
alessio1bf2a632019-06-04 15:47:39 +0200596 // Tested with Lumentum ROADM-20 1 seconds was not enough, increased to 5 seconds
MaoLu937cf422017-03-03 23:31:46 -0800597 private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
598 OchSignal ochSignal, long attenuation) {
599 Runnable setAtt = () -> {
600 try {
alessio1bf2a632019-06-04 15:47:39 +0200601 TimeUnit.SECONDS.sleep(5);
MaoLu937cf422017-03-03 23:31:46 -0800602 } catch (InterruptedException e) {
603 log.warn("Thread interrupted. Setting attenuation early.");
MaoLu2846b112017-05-15 17:18:55 -0700604 Thread.currentThread().interrupt();
MaoLu937cf422017-03-03 23:31:46 -0800605 }
606 setAttenuation(deviceId, outPort, ochSignal, attenuation);
607 };
608 new Thread(setAtt).start();
609 }
610
611 // get protection endpoint states
612 private Map<ConnectPoint, ProtectedTransportEndpointState> getProtectionSwitchStates(
613 ProtectionConfigBehaviour behaviour) {
MaoLu937cf422017-03-03 23:31:46 -0800614 Map<ConnectPoint, ProtectedTransportEndpointState> map;
615 try {
MaoLu2846b112017-05-15 17:18:55 -0700616 map = behaviour.getProtectionEndpointStates().get();
MaoLu937cf422017-03-03 23:31:46 -0800617 } catch (InterruptedException e1) {
618 log.error("Interrupted.", e1);
MaoLu2846b112017-05-15 17:18:55 -0700619 Thread.currentThread().interrupt();
620 return ImmutableMap.of();
MaoLu937cf422017-03-03 23:31:46 -0800621 } catch (ExecutionException e1) {
622 log.error("Exception caught.", e1);
MaoLu2846b112017-05-15 17:18:55 -0700623 return ImmutableMap.of();
MaoLu937cf422017-03-03 23:31:46 -0800624 }
625 return map;
626 }
627
Jimmy Yanda878fc2016-09-02 16:32:01 -0700628 // Listens to device events.
629 private class InternalDeviceListener implements DeviceListener {
630 @Override
631 public void event(DeviceEvent deviceEvent) {
632 Device device = deviceEvent.subject();
633
634 switch (deviceEvent.type()) {
635 case DEVICE_ADDED:
636 case DEVICE_UPDATED:
637 initDevice(device.id());
638 break;
639 case PORT_ADDED:
640 case PORT_UPDATED:
MaoLu937cf422017-03-03 23:31:46 -0800641 //FIXME
642 // As roadm application is a optional tool for now.
643 // The target power initialization will be enhanced later,
644 // hopefully using an formal optical subsystem.
645 // setInitialTargetPortPower(device.id(), deviceEvent.port().number());
Jimmy Yanda878fc2016-09-02 16:32:01 -0700646 break;
647 default:
648 break;
649
650 }
651 }
652 }
653}