blob: 2abe2a6ebe307aa960a81c7fc51e4c167789f897 [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 }
MaoLu937cf422017-03-03 23:31:46 -0800130 behaviour.switchWorkingPath(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);
MaoLu937cf422017-03-03 23:31:46 -0800206 // getTargetPortPower is not yet implemented in PowerConfig so we access store instead
Jimmy Yanda878fc2016-09-02 16:32:01 -0700207 return roadmStore.getTargetPower(deviceId, portNumber);
208 }
209
210 @Override
211 public void setAttenuation(DeviceId deviceId, PortNumber portNumber,
212 OchSignal ochSignal, long attenuation) {
213 checkNotNull(deviceId);
214 checkNotNull(portNumber);
215 checkNotNull(ochSignal);
216 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
217 if (powerConfig != null) {
218 powerConfig.setTargetPower(portNumber, ochSignal, attenuation);
219 } else {
220 log.warn("Cannot set attenuation for channel index {} on device {}",
221 ochSignal.spacingMultiplier(), deviceId);
222 }
223 }
224
225 @Override
MaoLu937cf422017-03-03 23:31:46 -0800226 public Long getAttenuation(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700227 checkNotNull(deviceId);
228 checkNotNull(portNumber);
229 checkNotNull(ochSignal);
230 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
231 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800232 Optional<Long> attenuation = powerConfig.getTargetPower(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700233 if (attenuation.isPresent()) {
234 return attenuation.get();
235 }
236 }
237 return null;
238 }
239
240 @Override
241 public Long getCurrentPortPower(DeviceId deviceId, PortNumber portNumber) {
242 checkNotNull(deviceId);
243 checkNotNull(portNumber);
244 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
245 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800246 Optional<Long> currentPower = powerConfig.currentPower(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700247 if (currentPower.isPresent()) {
248 return currentPower.get();
249 }
250 }
251 return null;
252 }
253
254 @Override
MaoLu937cf422017-03-03 23:31:46 -0800255 public Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700256 checkNotNull(deviceId);
257 checkNotNull(portNumber);
258 checkNotNull(ochSignal);
259 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
260 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800261 Optional<Long> currentPower = powerConfig.currentPower(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700262 if (currentPower.isPresent()) {
263 return currentPower.get();
264 }
265 }
266 return null;
267 }
268
269 @Override
270 public Set<OchSignal> queryLambdas(DeviceId deviceId, PortNumber portNumber) {
271 checkNotNull(deviceId);
272 checkNotNull(portNumber);
273 LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
274 if (lambdaQuery != null) {
275 return lambdaQuery.queryLambdas(portNumber);
276 }
277 return Collections.emptySet();
278 }
279
280 @Override
281 public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
MaoLu937cf422017-03-03 23:31:46 -0800282 int timeout, PortNumber inPort, PortNumber outPort, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700283 checkNotNull(deviceId);
284 checkNotNull(inPort);
285 checkNotNull(outPort);
286
MaoLu937cf422017-03-03 23:31:46 -0800287 TrafficSelector selector = DefaultTrafficSelector.builder()
288 .add(Criteria.matchInPort(inPort))
289 .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
290 .add(Criteria.matchLambda(ochSignal))
291 .build();
292 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
293 .add(Instructions.createOutput(outPort))
294 .build();
295
296 FlowRule.Builder flowBuilder = DefaultFlowRule.builder()
297 .forDevice(deviceId)
298 .fromApp(appId)
299 .withPriority(priority)
300 .withSelector(selector)
301 .withTreatment(treatment);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700302 if (isPermanent) {
303 flowBuilder.makePermanent();
304 } else {
305 flowBuilder.makeTemporary(timeout);
306 }
Jimmy Yanda878fc2016-09-02 16:32:01 -0700307
308 FlowRule flowRule = flowBuilder.build();
309 flowRuleService.applyFlowRules(flowRule);
310
311 log.info("Created connection from input port {} to output port {}",
312 inPort.toLong(), outPort.toLong());
313
314 return flowRule.id();
315 }
316
317 @Override
318 public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
319 int timeout, PortNumber inPort, PortNumber outPort,
320 OchSignal ochSignal, long attenuation) {
321 checkNotNull(deviceId);
322 checkNotNull(inPort);
323 checkNotNull(outPort);
MaoLu937cf422017-03-03 23:31:46 -0800324 FlowId flowId = createConnection(deviceId, priority, isPermanent, timeout, inPort, outPort, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700325 delayedSetAttenuation(deviceId, outPort, ochSignal, attenuation);
326 return flowId;
327 }
328
Jimmy Yanda878fc2016-09-02 16:32:01 -0700329 @Override
330 public void removeConnection(DeviceId deviceId, FlowId flowId) {
331 checkNotNull(deviceId);
332 checkNotNull(flowId);
333 for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
334 if (entry.id().equals(flowId)) {
335 flowRuleService.removeFlowRules(entry);
336 log.info("Deleted connection {}", entry.id());
337 break;
338 }
339 }
340 }
341
342 @Override
343 public boolean hasPortTargetPower(DeviceId deviceId, PortNumber portNumber) {
344 checkNotNull(deviceId);
345 checkNotNull(portNumber);
346 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
347 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800348 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700349 return range.isPresent();
350 }
351 return false;
352 }
353
354 @Override
MaoLu937cf422017-03-03 23:31:46 -0800355 public boolean portTargetPowerInRange(DeviceId deviceId, PortNumber portNumber, long power) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700356 checkNotNull(deviceId);
357 checkNotNull(portNumber);
358 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
359 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800360 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700361 return range.isPresent() && range.get().contains(power);
362 }
363 return false;
364 }
365
366 @Override
MaoLu937cf422017-03-03 23:31:46 -0800367 public boolean attenuationInRange(DeviceId deviceId, PortNumber outPort, long att) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700368 checkNotNull(deviceId);
369 checkNotNull(outPort);
370 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
371 if (powerConfig != null) {
372 OchSignal stubOch = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 0);
MaoLu937cf422017-03-03 23:31:46 -0800373 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(outPort, stubOch);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700374 return range.isPresent() && range.get().contains(att);
375 }
376 return false;
377 }
378
379 @Override
380 public boolean validInputPort(DeviceId deviceId, PortNumber portNumber) {
381 checkNotNull(deviceId);
382 checkNotNull(portNumber);
383 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
384 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800385 Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700386 return range.isPresent();
387 }
388 return false;
389 }
390
391 @Override
392 public boolean validOutputPort(DeviceId deviceId, PortNumber portNumber) {
393 return hasPortTargetPower(deviceId, portNumber);
394 }
395
396 @Override
MaoLu937cf422017-03-03 23:31:46 -0800397 public boolean validChannel(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700398 checkNotNull(deviceId);
399 checkNotNull(portNumber);
MaoLu937cf422017-03-03 23:31:46 -0800400 checkNotNull(ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700401 LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
402 if (lambdaQuery != null) {
403 Set<OchSignal> channels = lambdaQuery.queryLambdas(portNumber);
404 return channels.contains(ochSignal);
405 }
406 return false;
407 }
408
409 @Override
410 public boolean channelAvailable(DeviceId deviceId, OchSignal ochSignal) {
411 checkNotNull(deviceId);
412 checkNotNull(ochSignal);
413 for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
414 if (ChannelData.fromFlow(entry).ochSignal().equals(ochSignal)) {
415 return false;
416 }
417 }
418 return true;
419 }
420
421 @Override
MaoLu937cf422017-03-03 23:31:46 -0800422 public boolean validConnection(DeviceId deviceId, PortNumber inPort, PortNumber outPort) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700423 checkNotNull(deviceId);
424 checkNotNull(inPort);
425 checkNotNull(outPort);
426 return validInputPort(deviceId, inPort) && validOutputPort(deviceId, outPort);
427 }
428
429 @Override
430 public Range<Long> targetPortPowerRange(DeviceId deviceId, PortNumber portNumber) {
431 checkNotNull(deviceId);
432 checkNotNull(portNumber);
433 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
434 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800435 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700436 if (range.isPresent()) {
437 return range.get();
438 }
439 }
440 return null;
441 }
442
443 @Override
MaoLu937cf422017-03-03 23:31:46 -0800444 public Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700445 checkNotNull(deviceId);
446 checkNotNull(portNumber);
447 checkNotNull(ochSignal);
448 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
449 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800450 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700451 if (range.isPresent()) {
452 return range.get();
453 }
454 }
455 return null;
456 }
457
458 @Override
459 public Range<Long> inputPortPowerRange(DeviceId deviceId, PortNumber portNumber) {
460 checkNotNull(deviceId);
461 checkNotNull(portNumber);
462 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
463 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800464 Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700465 if (range.isPresent()) {
466 return range.get();
467 }
468 }
469 return null;
470 }
471
MaoLu937cf422017-03-03 23:31:46 -0800472 private PowerConfig<Object> getPowerConfig(DeviceId deviceId) {
473 Device device = deviceService.getDevice(deviceId);
474 if (device != null && device.is(PowerConfig.class)) {
475 return device.as(PowerConfig.class);
476 }
MaoLudd5a00b2017-03-14 11:19:48 -0700477 // Do not need warning here for port polling.
478 log.debug("Unable to load PowerConfig for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800479 return null;
480 }
481
482 private LambdaQuery getLambdaQuery(DeviceId deviceId) {
483 Device device = deviceService.getDevice(deviceId);
484 if (device != null && device.is(LambdaQuery.class)) {
485 return device.as(LambdaQuery.class);
486 }
MaoLudd5a00b2017-03-14 11:19:48 -0700487 // Do not need warning here for port polling.
488 log.debug("Unable to load LambdaQuery for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800489 return null;
490 }
491
492 private ProtectionConfigBehaviour getProtectionConfig(DeviceId deviceId) {
493 Device device = deviceService.getDevice(deviceId);
494 if (device != null && device.is(ProtectionConfigBehaviour.class)) {
495 return device.as(ProtectionConfigBehaviour.class);
496 }
MaoLudd5a00b2017-03-14 11:19:48 -0700497 // Do not need warning here for port polling.
498 log.debug("Unable to load ProtectionConfigBehaviour for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800499 return null;
500 }
501
502 // Initialize all devices
503 private void initDevices() {
504 for (Device device : deviceService.getDevices(Device.Type.ROADM)) {
505 initDevice(device.id());
506 //FIXME
507 // As roadm application is a optional tool for now.
508 // The target power initialization will be enhanced later,
509 // hopefully using an formal optical subsystem.
510 // setAllInitialTargetPortPowers(device.id());
511 }
512 }
513
514 // Initialize RoadmStore for a device to support target power
515 private void initDevice(DeviceId deviceId) {
516 if (!roadmStore.deviceAvailable(deviceId)) {
517 roadmStore.addDevice(deviceId);
518 }
519 log.info("Initialized device {}", deviceId);
520 }
521
522 // Sets the target port powers for a port on a device
523 // Attempts to read target powers from store. If no value is found then
524 // default value is used instead.
525 private void setInitialTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
526 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
527 if (powerConfig == null) {
528 log.warn("Unable to set default initial powers for port {} on device {}", portNumber, deviceId);
529 return;
530 }
531
532 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
533 if (!range.isPresent()) {
534 log.warn("No target power range found for port {} on device {}", portNumber, deviceId);
535 return;
536 }
537
538 Long power = roadmStore.getTargetPower(deviceId, portNumber);
539 if (power == null) {
540 // Set default to middle of the range
541 power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
542 roadmStore.setTargetPower(deviceId, portNumber, power);
543 }
544 powerConfig.setTargetPower(portNumber, Direction.ALL, power);
545 }
546
547 // Sets the target port powers for each each port on a device
548 // Attempts to read target powers from store. If no value is found then
549 // default value is used instead
550 private void setAllInitialTargetPortPowers(DeviceId deviceId) {
551 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
552 if (powerConfig == null) {
553 log.warn("Unable to set default initial powers for device {}", deviceId);
554 return;
555 }
556
557 List<Port> ports = deviceService.getPorts(deviceId);
558 for (Port port : ports) {
559 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(port.number(), Direction.ALL);
560 if (range.isPresent()) {
561 Long power = roadmStore.getTargetPower(deviceId, port.number());
562 if (power == null) {
563 // Set default to middle of the range
564 power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
565 roadmStore.setTargetPower(deviceId, port.number(), power);
566 }
567 powerConfig.setTargetPower(port.number(), Direction.ALL, power);
568 } else {
569 log.warn("No target power range found for port {} on device {}", port.number(), deviceId);
570 }
571 }
572 }
573
574 // Delay the call to setTargetPower because the flow may not be in the store yet
575 private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
576 OchSignal ochSignal, long attenuation) {
577 Runnable setAtt = () -> {
578 try {
579 TimeUnit.SECONDS.sleep(1);
580 } catch (InterruptedException e) {
581 log.warn("Thread interrupted. Setting attenuation early.");
MaoLu2846b112017-05-15 17:18:55 -0700582 Thread.currentThread().interrupt();
MaoLu937cf422017-03-03 23:31:46 -0800583 }
584 setAttenuation(deviceId, outPort, ochSignal, attenuation);
585 };
586 new Thread(setAtt).start();
587 }
588
589 // get protection endpoint states
590 private Map<ConnectPoint, ProtectedTransportEndpointState> getProtectionSwitchStates(
591 ProtectionConfigBehaviour behaviour) {
MaoLu937cf422017-03-03 23:31:46 -0800592 Map<ConnectPoint, ProtectedTransportEndpointState> map;
593 try {
MaoLu2846b112017-05-15 17:18:55 -0700594 map = behaviour.getProtectionEndpointStates().get();
MaoLu937cf422017-03-03 23:31:46 -0800595 } catch (InterruptedException e1) {
596 log.error("Interrupted.", e1);
MaoLu2846b112017-05-15 17:18:55 -0700597 Thread.currentThread().interrupt();
598 return ImmutableMap.of();
MaoLu937cf422017-03-03 23:31:46 -0800599 } catch (ExecutionException e1) {
600 log.error("Exception caught.", e1);
MaoLu2846b112017-05-15 17:18:55 -0700601 return ImmutableMap.of();
MaoLu937cf422017-03-03 23:31:46 -0800602 }
603 return map;
604 }
605
Jimmy Yanda878fc2016-09-02 16:32:01 -0700606 // Listens to device events.
607 private class InternalDeviceListener implements DeviceListener {
608 @Override
609 public void event(DeviceEvent deviceEvent) {
610 Device device = deviceEvent.subject();
611
612 switch (deviceEvent.type()) {
613 case DEVICE_ADDED:
614 case DEVICE_UPDATED:
615 initDevice(device.id());
616 break;
617 case PORT_ADDED:
618 case PORT_UPDATED:
MaoLu937cf422017-03-03 23:31:46 -0800619 //FIXME
620 // As roadm application is a optional tool for now.
621 // The target power initialization will be enhanced later,
622 // hopefully using an formal optical subsystem.
623 // setInitialTargetPortPower(device.id(), deviceEvent.port().number());
Jimmy Yanda878fc2016-09-02 16:32:01 -0700624 break;
625 default:
626 break;
627
628 }
629 }
630 }
631}