blob: d5bd501a796657d2d47c7d5e08163567e53c4978 [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;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
26import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
28import org.onosproject.net.ChannelSpacing;
MaoLu937cf422017-03-03 23:31:46 -080029import org.onosproject.net.ConnectPoint;
Jimmy Yanda878fc2016-09-02 16:32:01 -070030import org.onosproject.net.Device;
31import org.onosproject.net.DeviceId;
32import org.onosproject.net.Direction;
33import org.onosproject.net.OchSignal;
34import org.onosproject.net.OchSignalType;
35import org.onosproject.net.Port;
36import org.onosproject.net.PortNumber;
37import org.onosproject.net.behaviour.LambdaQuery;
38import org.onosproject.net.behaviour.PowerConfig;
MaoLu937cf422017-03-03 23:31:46 -080039import org.onosproject.net.behaviour.protection.ProtectionConfigBehaviour;
40import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointState;
41import org.onosproject.net.behaviour.protection.TransportEndpointState;
Jimmy Yanda878fc2016-09-02 16:32:01 -070042import org.onosproject.net.device.DeviceEvent;
43import org.onosproject.net.device.DeviceListener;
44import org.onosproject.net.device.DeviceService;
45import org.onosproject.net.flow.DefaultFlowRule;
46import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
48import org.onosproject.net.flow.FlowEntry;
49import org.onosproject.net.flow.FlowId;
50import org.onosproject.net.flow.FlowRule;
51import org.onosproject.net.flow.FlowRuleService;
52import org.onosproject.net.flow.TrafficSelector;
53import org.onosproject.net.flow.TrafficTreatment;
54import org.onosproject.net.flow.criteria.Criteria;
55import org.onosproject.net.flow.instructions.Instructions;
MaoLu937cf422017-03-03 23:31:46 -080056
Jimmy Yanda878fc2016-09-02 16:32:01 -070057import org.slf4j.Logger;
58import org.slf4j.LoggerFactory;
59
60import java.util.Collections;
61import java.util.List;
MaoLu937cf422017-03-03 23:31:46 -080062import java.util.Map;
Jimmy Yanda878fc2016-09-02 16:32:01 -070063import java.util.Optional;
64import java.util.Set;
MaoLu937cf422017-03-03 23:31:46 -080065import java.util.concurrent.ExecutionException;
Jimmy Yanda878fc2016-09-02 16:32:01 -070066import java.util.concurrent.TimeUnit;
67
68import static com.google.common.base.Preconditions.checkNotNull;
MaoLu2846b112017-05-15 17:18:55 -070069import static org.onosproject.net.optical.OpticalAnnotations.INPUT_PORT_STATUS;
70import static org.onosproject.roadm.RoadmUtil.OPS_OPT_AUTO;
71import static org.onosproject.roadm.RoadmUtil.OPS_OPT_FORCE;
72import static org.onosproject.roadm.RoadmUtil.OPS_OPT_MANUAL;
Jimmy Yanda878fc2016-09-02 16:32:01 -070073
74/**
75 * Application for monitoring and configuring ROADM devices.
76 */
77@Component(immediate = true)
78@Service
79public class RoadmManager implements RoadmService {
80
81 private static final String APP_NAME = "org.onosproject.roadm";
82 private ApplicationId appId;
83
84 private final Logger log = LoggerFactory.getLogger(getClass());
85
86 private DeviceListener deviceListener = new InternalDeviceListener();
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected RoadmStore roadmStore;
90
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected CoreService coreService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected DeviceService deviceService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected FlowRuleService flowRuleService;
99
100 @Activate
101 protected void activate() {
102 appId = coreService.registerApplication(APP_NAME);
103 deviceService.addListener(deviceListener);
104 initDevices();
105
106 log.info("Started");
107 }
108
109 @Deactivate
110 protected void deactivate() {
111 deviceService.removeListener(deviceListener);
112
113 log.info("Stopped");
114 }
115
MaoLu2846b112017-05-15 17:18:55 -0700116 @Deprecated
MaoLu937cf422017-03-03 23:31:46 -0800117 @Override
118 public void setProtectionSwitchWorkingPath(DeviceId deviceId, int index) {
119 checkNotNull(deviceId);
120 ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
121 if (behaviour == null) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700122 return;
123 }
MaoLu937cf422017-03-03 23:31:46 -0800124 Map<ConnectPoint, ProtectedTransportEndpointState> map = getProtectionSwitchStates(behaviour);
125 if (map == null) {
126 log.warn("Failed to get protected transport endpoint state in device {}", deviceId);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700127 return;
128 }
MaoLu937cf422017-03-03 23:31:46 -0800129 if (map.isEmpty()) {
130 log.warn("No protected transport endpoint state found in device {}", deviceId);
131 return;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700132 }
MaoLu937cf422017-03-03 23:31:46 -0800133 behaviour.switchWorkingPath(map.keySet().toArray(new ConnectPoint[0])[0], index);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700134 }
135
MaoLu2846b112017-05-15 17:18:55 -0700136 @Deprecated
MaoLu937cf422017-03-03 23:31:46 -0800137 @Override
138 public String getProtectionSwitchPortState(DeviceId deviceId, PortNumber portNumber) {
139 checkNotNull(deviceId);
140 ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
141 if (behaviour == null) {
142 return null;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700143 }
MaoLu937cf422017-03-03 23:31:46 -0800144 Map<ConnectPoint, ProtectedTransportEndpointState> map = getProtectionSwitchStates(behaviour);
145 if (map == null) {
146 log.warn("Failed to get protected transport endpoint state in device {}", deviceId);
147 return null;
148 }
149 for (ProtectedTransportEndpointState state : map.values()) {
150 for (TransportEndpointState element : state.pathStates()) {
151 if (element.description().output().connectPoint().port().equals(portNumber)) {
MaoLu2846b112017-05-15 17:18:55 -0700152 return element.attributes().get(INPUT_PORT_STATUS);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700153 }
Jimmy Yanda878fc2016-09-02 16:32:01 -0700154 }
155 }
MaoLudd5a00b2017-03-14 11:19:48 -0700156 // Do not need warning here for port polling.
157 log.debug("Unable to get port status, device: {}, port: {}", deviceId, portNumber);
MaoLu937cf422017-03-03 23:31:46 -0800158 return null;
Jimmy Yanda878fc2016-09-02 16:32:01 -0700159 }
160
161 @Override
MaoLu2846b112017-05-15 17:18:55 -0700162 public void configProtectionSwitch(DeviceId deviceId, String operation, ConnectPoint identifier, int index) {
163 checkNotNull(deviceId);
164 ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
165 if (behaviour == null) {
166 return;
167 }
168 // automatic operation
169 if (OPS_OPT_AUTO.equals(operation)) {
170 behaviour.switchToAutomatic(identifier);
171 return;
172 }
173 // force or manual operation
174 if (OPS_OPT_MANUAL.equals(operation)) {
175 behaviour.switchToManual(identifier, index);
176 } else if (OPS_OPT_FORCE.equals(operation)) {
177 behaviour.switchToForce(identifier, index);
178 }
179 }
180
181 @Override
182 public Map<ConnectPoint, ProtectedTransportEndpointState> getProtectionSwitchStates(DeviceId deviceId) {
183 checkNotNull(deviceId);
184 ProtectionConfigBehaviour behaviour = getProtectionConfig(deviceId);
185 if (behaviour == null) {
186 return ImmutableMap.of();
187 }
188 return getProtectionSwitchStates(behaviour);
189 }
190
191
192 @Override
Jimmy Yanda878fc2016-09-02 16:32:01 -0700193 public void setTargetPortPower(DeviceId deviceId, PortNumber portNumber, long power) {
194 checkNotNull(deviceId);
195 checkNotNull(portNumber);
196 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
197 if (powerConfig != null) {
198 roadmStore.setTargetPower(deviceId, portNumber, power);
199 powerConfig.setTargetPower(portNumber, Direction.ALL, power);
200 } else {
201 log.warn("Unable to set target port power for device {}", deviceId);
202 }
203 }
204
205 @Override
206 public Long getTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
207 checkNotNull(deviceId);
208 checkNotNull(portNumber);
MaoLu937cf422017-03-03 23:31:46 -0800209 // getTargetPortPower is not yet implemented in PowerConfig so we access store instead
Jimmy Yanda878fc2016-09-02 16:32:01 -0700210 return roadmStore.getTargetPower(deviceId, portNumber);
211 }
212
213 @Override
214 public void setAttenuation(DeviceId deviceId, PortNumber portNumber,
215 OchSignal ochSignal, long attenuation) {
216 checkNotNull(deviceId);
217 checkNotNull(portNumber);
218 checkNotNull(ochSignal);
219 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
220 if (powerConfig != null) {
221 powerConfig.setTargetPower(portNumber, ochSignal, attenuation);
222 } else {
223 log.warn("Cannot set attenuation for channel index {} on device {}",
224 ochSignal.spacingMultiplier(), deviceId);
225 }
226 }
227
228 @Override
MaoLu937cf422017-03-03 23:31:46 -0800229 public Long getAttenuation(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700230 checkNotNull(deviceId);
231 checkNotNull(portNumber);
232 checkNotNull(ochSignal);
233 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
234 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800235 Optional<Long> attenuation = powerConfig.getTargetPower(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700236 if (attenuation.isPresent()) {
237 return attenuation.get();
238 }
239 }
240 return null;
241 }
242
243 @Override
244 public Long getCurrentPortPower(DeviceId deviceId, PortNumber portNumber) {
245 checkNotNull(deviceId);
246 checkNotNull(portNumber);
247 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
248 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800249 Optional<Long> currentPower = powerConfig.currentPower(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700250 if (currentPower.isPresent()) {
251 return currentPower.get();
252 }
253 }
254 return null;
255 }
256
257 @Override
MaoLu937cf422017-03-03 23:31:46 -0800258 public Long getCurrentChannelPower(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700259 checkNotNull(deviceId);
260 checkNotNull(portNumber);
261 checkNotNull(ochSignal);
262 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
263 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800264 Optional<Long> currentPower = powerConfig.currentPower(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700265 if (currentPower.isPresent()) {
266 return currentPower.get();
267 }
268 }
269 return null;
270 }
271
272 @Override
273 public Set<OchSignal> queryLambdas(DeviceId deviceId, PortNumber portNumber) {
274 checkNotNull(deviceId);
275 checkNotNull(portNumber);
276 LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
277 if (lambdaQuery != null) {
278 return lambdaQuery.queryLambdas(portNumber);
279 }
280 return Collections.emptySet();
281 }
282
283 @Override
284 public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
MaoLu937cf422017-03-03 23:31:46 -0800285 int timeout, PortNumber inPort, PortNumber outPort, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700286 checkNotNull(deviceId);
287 checkNotNull(inPort);
288 checkNotNull(outPort);
289
MaoLu937cf422017-03-03 23:31:46 -0800290 TrafficSelector selector = DefaultTrafficSelector.builder()
291 .add(Criteria.matchInPort(inPort))
292 .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
293 .add(Criteria.matchLambda(ochSignal))
294 .build();
295 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
296 .add(Instructions.createOutput(outPort))
297 .build();
298
299 FlowRule.Builder flowBuilder = DefaultFlowRule.builder()
300 .forDevice(deviceId)
301 .fromApp(appId)
302 .withPriority(priority)
303 .withSelector(selector)
304 .withTreatment(treatment);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700305 if (isPermanent) {
306 flowBuilder.makePermanent();
307 } else {
308 flowBuilder.makeTemporary(timeout);
309 }
Jimmy Yanda878fc2016-09-02 16:32:01 -0700310
311 FlowRule flowRule = flowBuilder.build();
312 flowRuleService.applyFlowRules(flowRule);
313
314 log.info("Created connection from input port {} to output port {}",
315 inPort.toLong(), outPort.toLong());
316
317 return flowRule.id();
318 }
319
320 @Override
321 public FlowId createConnection(DeviceId deviceId, int priority, boolean isPermanent,
322 int timeout, PortNumber inPort, PortNumber outPort,
323 OchSignal ochSignal, long attenuation) {
324 checkNotNull(deviceId);
325 checkNotNull(inPort);
326 checkNotNull(outPort);
MaoLu937cf422017-03-03 23:31:46 -0800327 FlowId flowId = createConnection(deviceId, priority, isPermanent, timeout, inPort, outPort, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700328 delayedSetAttenuation(deviceId, outPort, ochSignal, attenuation);
329 return flowId;
330 }
331
Jimmy Yanda878fc2016-09-02 16:32:01 -0700332 @Override
333 public void removeConnection(DeviceId deviceId, FlowId flowId) {
334 checkNotNull(deviceId);
335 checkNotNull(flowId);
336 for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
337 if (entry.id().equals(flowId)) {
338 flowRuleService.removeFlowRules(entry);
339 log.info("Deleted connection {}", entry.id());
340 break;
341 }
342 }
343 }
344
345 @Override
346 public boolean hasPortTargetPower(DeviceId deviceId, PortNumber portNumber) {
347 checkNotNull(deviceId);
348 checkNotNull(portNumber);
349 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
350 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800351 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700352 return range.isPresent();
353 }
354 return false;
355 }
356
357 @Override
MaoLu937cf422017-03-03 23:31:46 -0800358 public boolean portTargetPowerInRange(DeviceId deviceId, PortNumber portNumber, long power) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700359 checkNotNull(deviceId);
360 checkNotNull(portNumber);
361 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
362 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800363 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700364 return range.isPresent() && range.get().contains(power);
365 }
366 return false;
367 }
368
369 @Override
MaoLu937cf422017-03-03 23:31:46 -0800370 public boolean attenuationInRange(DeviceId deviceId, PortNumber outPort, long att) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700371 checkNotNull(deviceId);
372 checkNotNull(outPort);
373 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
374 if (powerConfig != null) {
375 OchSignal stubOch = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 0);
MaoLu937cf422017-03-03 23:31:46 -0800376 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(outPort, stubOch);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700377 return range.isPresent() && range.get().contains(att);
378 }
379 return false;
380 }
381
382 @Override
383 public boolean validInputPort(DeviceId deviceId, PortNumber portNumber) {
384 checkNotNull(deviceId);
385 checkNotNull(portNumber);
386 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
387 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800388 Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700389 return range.isPresent();
390 }
391 return false;
392 }
393
394 @Override
395 public boolean validOutputPort(DeviceId deviceId, PortNumber portNumber) {
396 return hasPortTargetPower(deviceId, portNumber);
397 }
398
399 @Override
MaoLu937cf422017-03-03 23:31:46 -0800400 public boolean validChannel(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700401 checkNotNull(deviceId);
402 checkNotNull(portNumber);
MaoLu937cf422017-03-03 23:31:46 -0800403 checkNotNull(ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700404 LambdaQuery lambdaQuery = getLambdaQuery(deviceId);
405 if (lambdaQuery != null) {
406 Set<OchSignal> channels = lambdaQuery.queryLambdas(portNumber);
407 return channels.contains(ochSignal);
408 }
409 return false;
410 }
411
412 @Override
413 public boolean channelAvailable(DeviceId deviceId, OchSignal ochSignal) {
414 checkNotNull(deviceId);
415 checkNotNull(ochSignal);
416 for (FlowEntry entry : flowRuleService.getFlowEntries(deviceId)) {
417 if (ChannelData.fromFlow(entry).ochSignal().equals(ochSignal)) {
418 return false;
419 }
420 }
421 return true;
422 }
423
424 @Override
MaoLu937cf422017-03-03 23:31:46 -0800425 public boolean validConnection(DeviceId deviceId, PortNumber inPort, PortNumber outPort) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700426 checkNotNull(deviceId);
427 checkNotNull(inPort);
428 checkNotNull(outPort);
429 return validInputPort(deviceId, inPort) && validOutputPort(deviceId, outPort);
430 }
431
432 @Override
433 public Range<Long> targetPortPowerRange(DeviceId deviceId, PortNumber portNumber) {
434 checkNotNull(deviceId);
435 checkNotNull(portNumber);
436 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
437 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800438 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700439 if (range.isPresent()) {
440 return range.get();
441 }
442 }
443 return null;
444 }
445
446 @Override
MaoLu937cf422017-03-03 23:31:46 -0800447 public Range<Long> attenuationRange(DeviceId deviceId, PortNumber portNumber, OchSignal ochSignal) {
Jimmy Yanda878fc2016-09-02 16:32:01 -0700448 checkNotNull(deviceId);
449 checkNotNull(portNumber);
450 checkNotNull(ochSignal);
451 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
452 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800453 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, ochSignal);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700454 if (range.isPresent()) {
455 return range.get();
456 }
457 }
458 return null;
459 }
460
461 @Override
462 public Range<Long> inputPortPowerRange(DeviceId deviceId, PortNumber portNumber) {
463 checkNotNull(deviceId);
464 checkNotNull(portNumber);
465 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
466 if (powerConfig != null) {
MaoLu937cf422017-03-03 23:31:46 -0800467 Optional<Range<Long>> range = powerConfig.getInputPowerRange(portNumber, Direction.ALL);
Jimmy Yanda878fc2016-09-02 16:32:01 -0700468 if (range.isPresent()) {
469 return range.get();
470 }
471 }
472 return null;
473 }
474
MaoLu937cf422017-03-03 23:31:46 -0800475 private PowerConfig<Object> getPowerConfig(DeviceId deviceId) {
476 Device device = deviceService.getDevice(deviceId);
477 if (device != null && device.is(PowerConfig.class)) {
478 return device.as(PowerConfig.class);
479 }
MaoLudd5a00b2017-03-14 11:19:48 -0700480 // Do not need warning here for port polling.
481 log.debug("Unable to load PowerConfig for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800482 return null;
483 }
484
485 private LambdaQuery getLambdaQuery(DeviceId deviceId) {
486 Device device = deviceService.getDevice(deviceId);
487 if (device != null && device.is(LambdaQuery.class)) {
488 return device.as(LambdaQuery.class);
489 }
MaoLudd5a00b2017-03-14 11:19:48 -0700490 // Do not need warning here for port polling.
491 log.debug("Unable to load LambdaQuery for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800492 return null;
493 }
494
495 private ProtectionConfigBehaviour getProtectionConfig(DeviceId deviceId) {
496 Device device = deviceService.getDevice(deviceId);
497 if (device != null && device.is(ProtectionConfigBehaviour.class)) {
498 return device.as(ProtectionConfigBehaviour.class);
499 }
MaoLudd5a00b2017-03-14 11:19:48 -0700500 // Do not need warning here for port polling.
501 log.debug("Unable to load ProtectionConfigBehaviour for {}", deviceId);
MaoLu937cf422017-03-03 23:31:46 -0800502 return null;
503 }
504
505 // Initialize all devices
506 private void initDevices() {
507 for (Device device : deviceService.getDevices(Device.Type.ROADM)) {
508 initDevice(device.id());
509 //FIXME
510 // As roadm application is a optional tool for now.
511 // The target power initialization will be enhanced later,
512 // hopefully using an formal optical subsystem.
513 // setAllInitialTargetPortPowers(device.id());
514 }
515 }
516
517 // Initialize RoadmStore for a device to support target power
518 private void initDevice(DeviceId deviceId) {
519 if (!roadmStore.deviceAvailable(deviceId)) {
520 roadmStore.addDevice(deviceId);
521 }
522 log.info("Initialized device {}", deviceId);
523 }
524
525 // Sets the target port powers for a port on a device
526 // Attempts to read target powers from store. If no value is found then
527 // default value is used instead.
528 private void setInitialTargetPortPower(DeviceId deviceId, PortNumber portNumber) {
529 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
530 if (powerConfig == null) {
531 log.warn("Unable to set default initial powers for port {} on device {}", portNumber, deviceId);
532 return;
533 }
534
535 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(portNumber, Direction.ALL);
536 if (!range.isPresent()) {
537 log.warn("No target power range found for port {} on device {}", portNumber, deviceId);
538 return;
539 }
540
541 Long power = roadmStore.getTargetPower(deviceId, portNumber);
542 if (power == null) {
543 // Set default to middle of the range
544 power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
545 roadmStore.setTargetPower(deviceId, portNumber, power);
546 }
547 powerConfig.setTargetPower(portNumber, Direction.ALL, power);
548 }
549
550 // Sets the target port powers for each each port on a device
551 // Attempts to read target powers from store. If no value is found then
552 // default value is used instead
553 private void setAllInitialTargetPortPowers(DeviceId deviceId) {
554 PowerConfig<Object> powerConfig = getPowerConfig(deviceId);
555 if (powerConfig == null) {
556 log.warn("Unable to set default initial powers for device {}", deviceId);
557 return;
558 }
559
560 List<Port> ports = deviceService.getPorts(deviceId);
561 for (Port port : ports) {
562 Optional<Range<Long>> range = powerConfig.getTargetPowerRange(port.number(), Direction.ALL);
563 if (range.isPresent()) {
564 Long power = roadmStore.getTargetPower(deviceId, port.number());
565 if (power == null) {
566 // Set default to middle of the range
567 power = (range.get().lowerEndpoint() + range.get().upperEndpoint()) / 2;
568 roadmStore.setTargetPower(deviceId, port.number(), power);
569 }
570 powerConfig.setTargetPower(port.number(), Direction.ALL, power);
571 } else {
572 log.warn("No target power range found for port {} on device {}", port.number(), deviceId);
573 }
574 }
575 }
576
577 // Delay the call to setTargetPower because the flow may not be in the store yet
578 private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
579 OchSignal ochSignal, long attenuation) {
580 Runnable setAtt = () -> {
581 try {
582 TimeUnit.SECONDS.sleep(1);
583 } catch (InterruptedException e) {
584 log.warn("Thread interrupted. Setting attenuation early.");
MaoLu2846b112017-05-15 17:18:55 -0700585 Thread.currentThread().interrupt();
MaoLu937cf422017-03-03 23:31:46 -0800586 }
587 setAttenuation(deviceId, outPort, ochSignal, attenuation);
588 };
589 new Thread(setAtt).start();
590 }
591
592 // get protection endpoint states
593 private Map<ConnectPoint, ProtectedTransportEndpointState> getProtectionSwitchStates(
594 ProtectionConfigBehaviour behaviour) {
MaoLu937cf422017-03-03 23:31:46 -0800595 Map<ConnectPoint, ProtectedTransportEndpointState> map;
596 try {
MaoLu2846b112017-05-15 17:18:55 -0700597 map = behaviour.getProtectionEndpointStates().get();
MaoLu937cf422017-03-03 23:31:46 -0800598 } catch (InterruptedException e1) {
599 log.error("Interrupted.", e1);
MaoLu2846b112017-05-15 17:18:55 -0700600 Thread.currentThread().interrupt();
601 return ImmutableMap.of();
MaoLu937cf422017-03-03 23:31:46 -0800602 } catch (ExecutionException e1) {
603 log.error("Exception caught.", e1);
MaoLu2846b112017-05-15 17:18:55 -0700604 return ImmutableMap.of();
MaoLu937cf422017-03-03 23:31:46 -0800605 }
606 return map;
607 }
608
Jimmy Yanda878fc2016-09-02 16:32:01 -0700609 // Listens to device events.
610 private class InternalDeviceListener implements DeviceListener {
611 @Override
612 public void event(DeviceEvent deviceEvent) {
613 Device device = deviceEvent.subject();
614
615 switch (deviceEvent.type()) {
616 case DEVICE_ADDED:
617 case DEVICE_UPDATED:
618 initDevice(device.id());
619 break;
620 case PORT_ADDED:
621 case PORT_UPDATED:
MaoLu937cf422017-03-03 23:31:46 -0800622 //FIXME
623 // As roadm application is a optional tool for now.
624 // The target power initialization will be enhanced later,
625 // hopefully using an formal optical subsystem.
626 // setInitialTargetPortPower(device.id(), deviceEvent.port().number());
Jimmy Yanda878fc2016-09-02 16:32:01 -0700627 break;
628 default:
629 break;
630
631 }
632 }
633 }
634}