X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=olm%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Ftransportpce%2Folm%2Fpower%2FPowerMgmtImpl.java;h=dda3592b2009a2f8af1404e7c4385e8dd87de256;hb=24d436f1b7a0909804660afcfc2758d8c5cadc6a;hp=8b637cbfea8c8d41e7371965ba6c11b5948f79bd;hpb=99e77cc8ba73a8e765eafdf0ba4e41d6a36b730f;p=transportpce.git diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmtImpl.java b/olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmtImpl.java index 8b637cbfe..dda3592b2 100644 --- a/olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmtImpl.java +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmtImpl.java @@ -7,76 +7,96 @@ */ package org.opendaylight.transportpce.olm.power; + import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import java.util.Arrays; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Optional; -import org.opendaylight.mdsal.binding.api.DataBroker; +import java.util.stream.Collectors; import org.opendaylight.transportpce.common.crossconnect.CrossConnect; import org.opendaylight.transportpce.common.device.DeviceTransactionManager; import org.opendaylight.transportpce.common.fixedflex.GridConstant; +import org.opendaylight.transportpce.common.mapping.PortMapping; import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException; import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces; -import org.opendaylight.transportpce.olm.util.OlmUtils; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerSetupInput; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev210618.ServicePowerTurndownInput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220114.OpenroadmNodeVersion; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220114.mapping.Mapping; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220114.mapping.MappingKey; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220114.network.Nodes; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.OpenroadmNodeVersion; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.mapping.Mapping; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.mapping.MappingKey; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.network.Nodes; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.OpticalControlMode; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.Interface; import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.Interface1; +import org.opendaylight.yangtools.yang.common.Decimal64; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Component(configurationPid = "org.opendaylight.transportpce") public class PowerMgmtImpl implements PowerMgmt { + + @ObjectClassDefinition + public @interface Configuration { + @AttributeDefinition + long timer1() default 120000; + @AttributeDefinition + long timer2() default 20000; + } private static final Logger LOG = LoggerFactory.getLogger(PowerMgmtImpl.class); - private final DataBroker db; private final OpenRoadmInterfaces openRoadmInterfaces; private final CrossConnect crossConnect; private final DeviceTransactionManager deviceTransactionManager; + private final PortMapping portMapping; private static final BigDecimal DEFAULT_TPDR_PWR_100G = new BigDecimal(-5); private static final BigDecimal DEFAULT_TPDR_PWR_400G = new BigDecimal(0); private static final String INTERFACE_NOT_PRESENT = "Interface {} on node {} is not present!"; + private static final double MC_WIDTH_GRAN = 2 * GridConstant.GRANULARITY; - private long timer1 = 120000; + private long timer1; // openroadm spec value is 120000, functest value is 3000 - private long timer2 = 20000; + private long timer2; // openroadm spec value is 20000, functest value is 2000 - public PowerMgmtImpl(DataBroker db, OpenRoadmInterfaces openRoadmInterfaces, - CrossConnect crossConnect, DeviceTransactionManager deviceTransactionManager) { - this.db = db; - this.openRoadmInterfaces = openRoadmInterfaces; - this.crossConnect = crossConnect; - this.deviceTransactionManager = deviceTransactionManager; + @Activate + public PowerMgmtImpl(@Reference OpenRoadmInterfaces openRoadmInterfaces, + @Reference CrossConnect crossConnect, + @Reference DeviceTransactionManager deviceTransactionManager, + @Reference PortMapping portMapping, final Configuration configuration) { + this(openRoadmInterfaces, crossConnect, deviceTransactionManager, portMapping, configuration.timer1(), + configuration.timer2()); } - public PowerMgmtImpl(DataBroker db, OpenRoadmInterfaces openRoadmInterfaces, + public PowerMgmtImpl(OpenRoadmInterfaces openRoadmInterfaces, CrossConnect crossConnect, DeviceTransactionManager deviceTransactionManager, - String timer1, String timer2) { - this.db = db; + PortMapping portMapping, long timer1, long timer2) { this.openRoadmInterfaces = openRoadmInterfaces; this.crossConnect = crossConnect; this.deviceTransactionManager = deviceTransactionManager; + this.portMapping = portMapping; try { - this.timer1 = Long.parseLong(timer1); + this.timer1 = Long.valueOf(timer1); } catch (NumberFormatException e) { this.timer1 = 120000; LOG.warn("Failed to retrieve Olm timer1 value from configuration - using default value {}", this.timer1, e); } try { - this.timer2 = Long.parseLong(timer2); + this.timer2 = Long.valueOf(timer2); } catch (NumberFormatException e) { this.timer2 = 20000; LOG.warn("Failed to retrieve Olm timer2 value from configuration - using default value {}", this.timer2, e); } + LOG.debug("PowerMgmtImpl instantiated with olm timers = {} - {}", this.timer1, this.timer2); } /** @@ -95,16 +115,18 @@ public class PowerMgmtImpl implements PowerMgmt { String spectralSlotName = String.join(GridConstant.SPECTRAL_SLOT_SEPARATOR, input.getLowerSpectralSlotNumber().toString(), input.getHigherSpectralSlotNumber().toString()); + if (input.getNodes() == null) { + LOG.error("No Nodes to configure"); + return false; + } for (int i = 0; i < input.getNodes().size(); i++) { String nodeId = input.getNodes().get(i).getNodeId(); String destTpId = input.getNodes().get(i).getDestTp(); - Optional inputNodeOptional = OlmUtils.getNode(nodeId, this.db); - if (inputNodeOptional.isEmpty() - || inputNodeOptional.get().getNodeInfo().getNodeType() == null) { - LOG.error("OLM-PowerMgmtImpl : Error node type cannot be retrieved for node {}", nodeId); - continue; + Nodes inputNode = this.portMapping.getNode(nodeId); + if (inputNode == null || inputNode.getNodeInfo() == null) { + LOG.error("OLM-PowerMgmtImpl : Error retrieving mapping node for {}", nodeId); + return false; } - Nodes inputNode = inputNodeOptional.get(); OpenroadmNodeVersion openroadmVersion = inputNode.getNodeInfo().getOpenroadmVersion(); switch (inputNode.getNodeInfo().getNodeType()) { @@ -169,17 +191,18 @@ public class PowerMgmtImpl implements PowerMgmt { } // TODO can it be return false rather than continue? // in that case, mappingObjectOptional could be moved inside method getSpanLossTx() - LOG.info("Dest point is Degree {}", mappingObjectOptional.get()); - BigDecimal spanLossTx = getSpanLossTx(mappingObjectOptional.get().getSupportingOts(), + LOG.info("Dest point is Degree {}", mappingObjectOptional.orElseThrow()); + BigDecimal spanLossTx = getSpanLossTx(mappingObjectOptional.orElseThrow().getSupportingOts(), destTpId, nodeId, openroadmVersion.getIntValue()); LOG.info("Spanloss TX is {}", spanLossTx); - if (spanLossTx == null || spanLossTx.intValue() <= 0 || spanLossTx.intValue() > 28) { - LOG.error("Power Value is null: spanLossTx null or out of openROADM range ]0,28] {}", - spanLossTx); + // TODO: The span-loss limits should be obtained from optical specifications + if (spanLossTx == null || spanLossTx.intValue() < 0 || spanLossTx.intValue() > 27) { + LOG.error("Power Value is null: spanLossTx null or out of openROADM range [0,27] {}", + spanLossTx); return false; } - BigDecimal powerValue = getRdmPowerValue(spanLossTx, input); + Decimal64 powerValue = Decimal64.valueOf(getRdmPowerValue(spanLossTx, input)); try { if (!crossConnect.setPowerLevel(nodeId, OpticalControlMode.Power.getName(), powerValue, connectionNumber)) { @@ -227,8 +250,8 @@ public class PowerMgmtImpl implements PowerMgmt { // TODO Align protections with getSRGRxPowerRangeMap } - String circuitPackName = mappingObject.get().getSupportingCircuitPackName(); - String portName = mappingObject.get().getSupportingPort(); + String circuitPackName = mappingObject.orElseThrow().getSupportingCircuitPackName(); + String portName = mappingObject.orElseThrow().getSupportingPort(); switch (openroadmVersion) { case 1: return PowerMgmtVersion121.getXponderPowerRange(circuitPackName, portName, @@ -249,22 +272,19 @@ public class PowerMgmtImpl implements PowerMgmt { private Map getSRGRxPowerRangeMap(String srgId, String nodeId, Integer openroadmVersion) { - Optional inputNode = OlmUtils.getNode(nodeId, this.db); - int rdmOpenroadmVersion = - inputNode.isPresent() - ? inputNode.get().getNodeInfo().getOpenroadmVersion().getIntValue() - : openroadmVersion; - Optional mappingObject = inputNode - .flatMap(node -> node.nonnullMapping().values().stream() - .filter(o -> o.key().equals(new MappingKey(srgId))).findFirst()); + Nodes inputNode = this.portMapping.getNode(nodeId); + int rdmOpenroadmVersion = inputNode.getNodeInfo().getOpenroadmVersion().getIntValue(); + Optional mappingObject = inputNode.nonnullMapping().values().stream() + .filter(o -> o.key().equals(new MappingKey(srgId))) + .findFirst(); if (mappingObject.isEmpty()) { return new HashMap<>(); // FIXME shouldn't it lead to a return false in setPower() ? } - String circuitPackName = mappingObject.get().getSupportingCircuitPackName(); - String portName = mappingObject.get().getSupportingPort(); + String circuitPackName = mappingObject.orElseThrow().getSupportingCircuitPackName(); + String portName = mappingObject.orElseThrow().getSupportingPort(); switch (rdmOpenroadmVersion) { case 1: return PowerMgmtVersion121.getSRGRxPowerRange(nodeId, srgId, @@ -293,14 +313,14 @@ public class PowerMgmtImpl implements PowerMgmt { LOG.error(INTERFACE_NOT_PRESENT, supportingOts, nodeId); return null; } - if (interfaceOpt.get().augmentation(Interface1.class).getOts() + if (interfaceOpt.orElseThrow().augmentation(Interface1.class).getOts() .getSpanLossTransmit() == null) { - LOG.error("interface {} has no spanloss value", interfaceOpt.get().getName()); + LOG.error("interface {} has no spanloss value", interfaceOpt.orElseThrow().getName()); return null; } - return interfaceOpt.get() + return interfaceOpt.orElseThrow() .augmentation(Interface1.class) - .getOts().getSpanLossTransmit().getValue(); + .getOts().getSpanLossTransmit().getValue().decimalValue(); case 2: Optional interfaceOpt1 = @@ -309,16 +329,16 @@ public class PowerMgmtImpl implements PowerMgmt { LOG.error(INTERFACE_NOT_PRESENT, supportingOts, nodeId); return null; } - if (interfaceOpt1.get().augmentation(org.opendaylight.yang.gen.v1.http.org + if (interfaceOpt1.orElseThrow().augmentation(org.opendaylight.yang.gen.v1.http.org .openroadm.optical.transport.interfaces.rev181019.Interface1.class).getOts() .getSpanLossTransmit() == null) { - LOG.error("interface {} has no spanloss value", interfaceOpt1.get().getName()); + LOG.error("interface {} has no spanloss value", interfaceOpt1.orElseThrow().getName()); return null; } - return interfaceOpt1.get() + return interfaceOpt1.orElseThrow() .augmentation(org.opendaylight.yang.gen.v1.http.org .openroadm.optical.transport.interfaces.rev181019.Interface1.class) - .getOts().getSpanLossTransmit().getValue(); + .getOts().getSpanLossTransmit().getValue().decimalValue(); // TODO no case 3 ? default: return null; @@ -369,22 +389,42 @@ public class PowerMgmtImpl implements PowerMgmt { private BigDecimal getRdmPowerValue(BigDecimal spanLossTx, ServicePowerSetupInput input) { - BigDecimal powerValue = spanLossTx.subtract(BigDecimal.valueOf(9)).min(BigDecimal.valueOf(2)); + // TODO: These values will be obtained from the specifications + // power-value here refers to the Pin[50GHz] + BigDecimal powerValue; + if (spanLossTx.doubleValue() >= 23.0) { + powerValue = BigDecimal.valueOf(2.0); + } else if (spanLossTx.doubleValue() >= 8.0) { + powerValue = BigDecimal.valueOf(- (8.0 - spanLossTx.doubleValue()) / 3.0 - 3.0); + } else if (spanLossTx.doubleValue() >= 6.0) { + powerValue = BigDecimal.valueOf(-3.0); + } else { + powerValue = spanLossTx.subtract(BigDecimal.valueOf(9)); + } + BigDecimal mcWidth = new BigDecimal(50); // we work at constant power spectral density (50 GHz channel width @-20dBm=37.5GHz) // 87.5 GHz channel width @-20dBm=75GHz if (input.getMcWidth() != null) { - LOG.debug("Input Gridsize is {}",input.getMcWidth().getValue()); - if (input.getMcWidth().getValue().equals(GridConstant.WIDTH_80)) { - powerValue = powerValue.add(BigDecimal.valueOf(3)); - } else if (input.getMcWidth().getValue().equals(GridConstant.SLOT_WIDTH_87_5)) { - BigDecimal logVal = GridConstant.SLOT_WIDTH_87_5.divide(new BigDecimal(50)); - double pdsVal = 10 * Math.log10(logVal.doubleValue()); - powerValue = powerValue.add(new BigDecimal(pdsVal, new MathContext(3, RoundingMode.HALF_EVEN))); - } + // Units of MC-width are in GHz, meaning it should be 40/50/87.5GHz + // TODO: Should we validate this units before proceeding? + LOG.debug("Input Grid size is {}", input.getMcWidth().getValue()); + + // We round-off the mc-width to the nearest grid-value based on the granularity of 12.5 GHz + double nbrMcSlots = Math.ceil(input.getMcWidth().getValue().doubleValue() / MC_WIDTH_GRAN); + LOG.debug("Nearest (ceil) number of slots {}", nbrMcSlots); + mcWidth = new BigDecimal(MC_WIDTH_GRAN * nbrMcSlots); + LOG.debug("Given mc-width={}, Rounded mc-width={}", input.getMcWidth().getValue(), mcWidth); + + BigDecimal logVal = mcWidth.divide(new BigDecimal(50)); + double pdsVal = 10 * Math.log10(logVal.doubleValue()); + // Addition of PSD value will give Pin[87.5 GHz] + powerValue = powerValue.add(new BigDecimal(pdsVal, new MathContext(3, RoundingMode.HALF_EVEN))); } // FIXME compliancy with OpenROADM MSA and approximations used -- should be addressed with powermask update // cf JIRA ticket https://jira.opendaylight.org/browse/TRNSPRTPCE-494 - LOG.info("Power Value is {}", powerValue); + powerValue = powerValue.setScale(2, RoundingMode.CEILING); + // target-output-power yang precision is 2, so we limit here to 2 + LOG.info("The power value is P1[{}GHz]={} dB for spanloss {}", mcWidth, powerValue, spanLossTx); return powerValue; } @@ -422,8 +462,8 @@ public class PowerMgmtImpl implements PowerMgmt { input.getNodes().get(i).getSrcTp(), destTpId, spectralSlotName); try { if (destTpId.toUpperCase(Locale.getDefault()).contains("DEG")) { - if (!crossConnect.setPowerLevel(nodeId, OpticalControlMode.Power.getName(), new BigDecimal(-60), - connectionNumber)) { + if (!crossConnect.setPowerLevel(nodeId, OpticalControlMode.Power.getName(), + Decimal64.valueOf("-60"), connectionNumber)) { LOG.warn("Power down failed for Roadm-connection: {}", connectionNumber); return false; } @@ -475,7 +515,7 @@ public class PowerMgmtImpl implements PowerMgmt { return false; } powerSetupResult = PowerMgmtVersion121.setTransponderPower(nodeId, interfaceName, - txPower, deviceTransactionManager, interfaceOptional121.get()); + txPower, deviceTransactionManager, interfaceOptional121.orElseThrow()); break; case 2: Optional