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=acd5c6d10f91bff8828731543df28f75d7287966;hb=268165cb2822b6ce4c55f00cac63eed2bb222ec7;hp=0f6c81106792f71c98ef6f0c6545d19e7e8b4456;hpb=b115d446ae97ff4e7def0ad5c96beaa13191e5b0;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 0f6c81106..acd5c6d10 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,26 +7,27 @@ */ package org.opendaylight.transportpce.olm.power; - import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.Optional; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.mdsal.binding.api.DataBroker; 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.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.rev170418.ServicePowerSetupInput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.olm.rev170418.ServicePowerTurndownInput; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev190702.network.Nodes; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev190702.network.nodes.Mapping; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev190702.network.nodes.MappingKey; -import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev190702.network.nodes.NodeInfo.OpenroadmVersion; +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.rev220316.OpenroadmNodeVersion; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220316.mapping.Mapping; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220316.mapping.MappingKey; +import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220316.network.Nodes; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.OpticalControlMode; -import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev181019.NodeTypes; 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.slf4j.Logger; @@ -38,6 +39,15 @@ public class PowerMgmtImpl implements PowerMgmt { private final OpenRoadmInterfaces openRoadmInterfaces; private final CrossConnect crossConnect; private final DeviceTransactionManager deviceTransactionManager; + 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; + // openroadm spec value is 120000, functest value is 3000 + private long timer2 = 20000; + // openroadm spec value is 20000, functest value is 2000 public PowerMgmtImpl(DataBroker db, OpenRoadmInterfaces openRoadmInterfaces, CrossConnect crossConnect, DeviceTransactionManager deviceTransactionManager) { @@ -47,6 +57,29 @@ public class PowerMgmtImpl implements PowerMgmt { this.deviceTransactionManager = deviceTransactionManager; } + public PowerMgmtImpl(DataBroker db, OpenRoadmInterfaces openRoadmInterfaces, + CrossConnect crossConnect, DeviceTransactionManager deviceTransactionManager, + String timer1, String timer2) { + this.db = db; + this.openRoadmInterfaces = openRoadmInterfaces; + this.crossConnect = crossConnect; + this.deviceTransactionManager = deviceTransactionManager; + try { + this.timer1 = Long.parseLong(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); + } catch (NumberFormatException e) { + this.timer2 = 20000; + LOG.warn("Failed to retrieve Olm timer2 value from configuration - using default value {}", + this.timer2, e); + } + } + /** * This methods measures power requirement for turning up a WL * from the Spanloss at OTS transmit direction and update @@ -59,237 +92,324 @@ public class PowerMgmtImpl implements PowerMgmt { */ //TODO Need to Case Optical Power mode/NodeType in case of 2.2 devices public Boolean setPower(ServicePowerSetupInput input) { - LOG.info("Olm-setPower initiated"); + LOG.info("Olm-setPower initiated for input {}", input); + String spectralSlotName = String.join(GridConstant.SPECTRAL_SLOT_SEPARATOR, + input.getLowerSpectralSlotNumber().toString(), + input.getHigherSpectralSlotNumber().toString()); for (int i = 0; i < input.getNodes().size(); i++) { String nodeId = input.getNodes().get(i).getNodeId(); - String srcTpId = input.getNodes().get(i).getSrcTp(); String destTpId = input.getNodes().get(i).getDestTp(); Optional inputNodeOptional = OlmUtils.getNode(nodeId, this.db); - // If node type is transponder - if (inputNodeOptional.isPresent() - && (inputNodeOptional.get().getNodeInfo().getNodeType() != null) - && inputNodeOptional.get().getNodeInfo().getNodeType().equals(NodeTypes.Xpdr)) { - - Nodes inputNode = inputNodeOptional.get(); - OpenroadmVersion openroadmVersion = inputNode.getNodeInfo().getOpenroadmVersion(); - LOG.info("Getting data from input node {}", inputNode.getNodeInfo().getNodeType()); - LOG.info("Getting mapping data for node is {}", inputNode.getMapping().stream().filter(o -> o.key() - .equals(new MappingKey(destTpId))).findFirst().toString()); - // If its A-End transponder - if (destTpId.toLowerCase().contains("network")) { - java.util.Optional mappingObject = inputNode.getMapping().stream().filter(o -> o.key() - .equals(new MappingKey(destTpId))).findFirst(); - if (mappingObject.isPresent()) { - String circuitPackName = mappingObject.get().getSupportingCircuitPackName(); - String portName = mappingObject.get().getSupportingPort(); - Map txPowerRangeMap = new HashMap<>(); - if (openroadmVersion.getIntValue() == 1) { - txPowerRangeMap = PowerMgmtVersion121.getXponderPowerRange(circuitPackName, portName, - nodeId, deviceTransactionManager); - } else if (openroadmVersion.getIntValue() == 2) { - txPowerRangeMap = PowerMgmtVersion221.getXponderPowerRange(circuitPackName, portName, - nodeId, deviceTransactionManager); - } - if (!txPowerRangeMap.isEmpty()) { - LOG.info("Transponder range exists for nodeId: {}", nodeId); - String srgId = input.getNodes().get(i + 1).getSrcTp(); - String nextNodeId = input.getNodes().get(i + 1).getNodeId(); - Map rxSRGPowerRangeMap = new HashMap<>(); - Optional mappingObjectSRG = OlmUtils.getNode(nextNodeId, db) - .flatMap(node -> node.getMapping() - .stream().filter(o -> o.key() - .equals(new MappingKey(srgId))).findFirst()); - if (mappingObjectSRG.isPresent()) { - - if (openroadmVersion.getIntValue() == 1) { - rxSRGPowerRangeMap = PowerMgmtVersion121.getSRGRxPowerRange(nextNodeId, srgId, - deviceTransactionManager, mappingObjectSRG.get() - .getSupportingCircuitPackName(), - mappingObjectSRG.get().getSupportingPort()); - } else if (openroadmVersion.getIntValue() == 2) { - rxSRGPowerRangeMap = PowerMgmtVersion221.getSRGRxPowerRange(nextNodeId, srgId, - deviceTransactionManager, mappingObjectSRG.get() - .getSupportingCircuitPackName(), - mappingObjectSRG.get().getSupportingPort()); - } - } - double powerValue = 0; - if (!rxSRGPowerRangeMap.isEmpty()) { - LOG.info("SRG Rx Power range exists for nodeId: {}", nodeId); - if (txPowerRangeMap.get("MaxTx") - <= rxSRGPowerRangeMap.get("MaxRx")) { - powerValue = txPowerRangeMap.get("MaxTx"); - } else if (rxSRGPowerRangeMap.get("MaxRx") - < txPowerRangeMap.get("MaxTx")) { - powerValue = rxSRGPowerRangeMap.get("MaxRx"); - } - LOG.info("Calculated Transponder Power value is {}" , powerValue); - String interfaceName = destTpId + "-" + input.getWaveNumber(); - if (callSetTransponderPower(nodeId, interfaceName, new BigDecimal(powerValue), - openroadmVersion)) { - LOG.info("Transponder OCH connection: {} power updated ", interfaceName); - try { - LOG.info("Now going in sleep mode"); - Thread.sleep(OlmUtils.OLM_TIMER_1); - } catch (InterruptedException e) { - LOG.info("Transponder warmup failed for OCH connection: {}", interfaceName, e); - } - } else { - LOG.info("Transponder OCH connection: {} power update failed ", interfaceName); - } - } else { - LOG.info("SRG Power Range not found"); - } - } else { - LOG.info("Tranponder range not available setting to default power for nodeId: {}", nodeId); - String interfaceName = destTpId + "-" + input.getWaveNumber(); - if (callSetTransponderPower(nodeId, interfaceName, new BigDecimal(-5),openroadmVersion)) { - LOG.info("Transponder OCH connection: {} power updated ", interfaceName); - try { - Thread.sleep(OlmUtils.OLM_TIMER_1); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LOG.info("Transponder warmup failed for OCH connection: {}", interfaceName, e); - } - } else { - LOG.info("Transponder OCH connection: {} power update failed ", interfaceName); - } - } - } else { - LOG.info("Mapping object not found for nodeId: {}", nodeId); + if (inputNodeOptional.isEmpty() + || inputNodeOptional.get().getNodeInfo().getNodeType() == null) { + LOG.error("OLM-PowerMgmtImpl : Error node type cannot be retrieved for node {}", nodeId); + continue; + } + Nodes inputNode = inputNodeOptional.get(); + OpenroadmNodeVersion openroadmVersion = inputNode.getNodeInfo().getOpenroadmVersion(); + + switch (inputNode.getNodeInfo().getNodeType()) { + case Xpdr: + if (destTpId == null) { + continue; + } + LOG.info("Getting data from input node {}", inputNode.getNodeInfo().getNodeType()); + LOG.info("Getting mapping data for node is {}", + inputNode.nonnullMapping().values().stream().filter(o -> o.key() + .equals(new MappingKey(destTpId))).findFirst().toString()); + // If its not A-End transponder + if (!destTpId.toUpperCase(Locale.getDefault()).contains("NETWORK")) { + LOG.info("{} is a drop node. Net power settings needed", nodeId); + continue; + } + + BigDecimal powerVal = getXpdrPowerValue( + inputNode, destTpId, nodeId, openroadmVersion.getIntValue(), + input.getNodes().get(i + 1).getSrcTp(), input.getNodes().get(i + 1).getNodeId()); + if (powerVal == null) { return false; } - } else { - LOG.info("{} is a drop node. Net power settings needed", nodeId); - } - } else if (inputNodeOptional.isPresent() - && (inputNodeOptional.get().getNodeInfo().getNodeType() != null) - && inputNodeOptional.get().getNodeInfo().getNodeType().equals(NodeTypes.Rdm)) { - // If Degree is transmitting end then set power - Nodes inputNode = inputNodeOptional.get(); - OpenroadmVersion openroadmVersion = inputNode.getNodeInfo().getOpenroadmVersion(); - LOG.info("This is a roadm {} device", openroadmVersion.getName()); - String connectionNumber = srcTpId + "-" + destTpId + "-" + input.getWaveNumber(); - LOG.info("Connection number is {}", connectionNumber); - if (destTpId.toLowerCase().contains("deg")) { - Optional mappingObjectOptional = inputNode.getMapping().stream().filter(o -> o.key() + + String interfaceName = String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, + destTpId, spectralSlotName); + if (!callSetTransponderPower(nodeId, interfaceName, powerVal, openroadmVersion)) { + LOG.info("Transponder OCH connection: {} power update failed ", interfaceName); + continue; + } + LOG.info("Transponder OCH connection: {} power updated ", interfaceName); + try { + LOG.info("Now going in sleep mode"); + Thread.sleep(timer1); + } catch (InterruptedException e) { + LOG.info("Transponder warmup failed for OCH connection: {}", interfaceName, e); + // FIXME shouldn't it be LOG.warn or LOG.error? + // or maybe this try/catch block can simply be removed + } + break; + case Rdm: + LOG.info("This is a roadm {} device", openroadmVersion.getName()); + String connectionNumber = String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, + input.getNodes().get(i).getSrcTp(), destTpId, spectralSlotName); + LOG.info("Connection number is {}", connectionNumber); + + // If Drop node leave node is power mode + if (destTpId.toUpperCase(Locale.getDefault()).contains("SRG")) { + LOG.info("Setting power at drop node"); + crossConnect.setPowerLevel(nodeId, OpticalControlMode.Power.getName(), null, connectionNumber); + continue; + } + if (!destTpId.toUpperCase(Locale.getDefault()).contains("DEG")) { + continue; + } + // If Degree is transmitting end then set power + Optional mappingObjectOptional = inputNode.nonnullMapping() + .values().stream().filter(o -> o.key() .equals(new MappingKey(destTpId))).findFirst(); - if (mappingObjectOptional.isPresent()) { - BigDecimal spanLossTx = null; - LOG.info("Dest point is Degree {}", mappingObjectOptional.get()); - Mapping portMapping = mappingObjectOptional.get(); - // debut reprise - if (openroadmVersion.getIntValue() == 1) { - Optional interfaceOpt; - try { - interfaceOpt = - this.openRoadmInterfaces.getInterface(nodeId, portMapping.getSupportingOts()); - } catch (OpenRoadmInterfaceException ex) { - LOG.error("Failed to get interface {} from node {}!", portMapping.getSupportingOts(), - nodeId, ex); - return false; - } catch (IllegalArgumentException ex) { - LOG.error("Failed to get non existing interface {} from node {}!", - portMapping.getSupportingOts(), nodeId); - return false; - } - if (interfaceOpt.isPresent()) { - if (interfaceOpt.get().augmentation(Interface1.class).getOts() - .getSpanLossTransmit() != null) { - spanLossTx = interfaceOpt.get().augmentation(Interface1.class).getOts() - .getSpanLossTransmit().getValue(); - LOG.info("Spanloss TX is {}", spanLossTx); - } else { - LOG.error("interface {} has no spanloss value", interfaceOpt.get().getName()); - } - } else { - LOG.error("Interface {} on node {} is not present!", portMapping.getSupportingOts(), - nodeId); - return false; - } - } else if (openroadmVersion.getIntValue() == 2) { - Optional interfaceOpt; - try { - interfaceOpt = - this.openRoadmInterfaces.getInterface(nodeId, portMapping.getSupportingOts()); - } catch (OpenRoadmInterfaceException ex) { - LOG.error("Failed to get interface {} from node {}!", portMapping.getSupportingOts(), - nodeId, ex); - return false; - } catch (IllegalArgumentException ex) { - LOG.error("Failed to get non existing interface {} from node {}!", - portMapping.getSupportingOts(), nodeId); - return false; - } - if (interfaceOpt.isPresent()) { - if (interfaceOpt.get().augmentation(org.opendaylight.yang.gen.v1.http.org - .openroadm.optical.transport.interfaces.rev181019.Interface1.class).getOts() - .getSpanLossTransmit() != null) { - spanLossTx = interfaceOpt.get().augmentation(org.opendaylight.yang.gen.v1.http.org - .openroadm.optical.transport.interfaces.rev181019.Interface1.class).getOts() - .getSpanLossTransmit().getValue(); - LOG.info("Spanloss TX is {}", spanLossTx); - } else { - LOG.error("interface {} has no spanloss value", interfaceOpt.get().getName()); - } - } else { - LOG.error("Interface {} on node {} is not present!", portMapping.getSupportingOts(), - nodeId); - return false; - } - } + if (mappingObjectOptional.isEmpty()) { + continue; + } + // 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(), + destTpId, nodeId, openroadmVersion.getIntValue()); - BigDecimal powerValue = null; - if (spanLossTx != null && spanLossTx.intValue() <= 28 && spanLossTx.intValue() > 0) { - powerValue = BigDecimal.valueOf(Math.min(spanLossTx.doubleValue() - 9, 2)); - LOG.info("Power Value is {}", powerValue); - } else if (spanLossTx.intValue() > 28) { - LOG.error( - "Power Value is null - spanLossTx > 28dB not compliant with openROADM specifications"); - return false; - } else if (spanLossTx.intValue() <= 0) { - LOG.error( - "Power Value is null - spanLossTx <= 0 dB not compliant with openROADM specifications"); - return false; - } else { - LOG.error("Power Value is null - spanLossTx is null"); + LOG.info("Spanloss TX is {}", 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); + try { + if (!crossConnect.setPowerLevel(nodeId, OpticalControlMode.Power.getName(), powerValue, + connectionNumber)) { + LOG.info("Set Power failed for Roadm-connection: {} on Node: {}", + connectionNumber, nodeId); + // FIXME shouldn't it be LOG.error return false; } - try { - Boolean setXconnPowerSuccessVal = crossConnect.setPowerLevel(nodeId, - OpticalControlMode.Power, powerValue, connectionNumber); - LOG.info("Success Value is {}", setXconnPowerSuccessVal); - if (setXconnPowerSuccessVal) { - LOG.info("Roadm-connection: {} updated "); - //The value recommended by the white paper is 20 seconds and not 60. - //TODO - commented code because one vendor is not supporting - //GainLoss with target-output-power - Thread.sleep(OlmUtils.OLM_TIMER_1); - crossConnect.setPowerLevel(nodeId, OpticalControlMode.GainLoss, powerValue, - connectionNumber); - } else { - LOG.info("Set Power failed for Roadm-connection: {} on Node: {}", connectionNumber, - nodeId); - return false; - } - } catch (InterruptedException e) { - LOG.error("Olm-setPower wait failed {}", e); - return false; + LOG.info("Roadm-connection: {} updated ", connectionNumber); + Thread.sleep(timer2); + // TODO make this timer value configurable via OSGi blueprint + // although the value recommended by the white paper is 20 seconds. + // At least one vendor product needs 60 seconds + // because it is not supporting GainLoss with target-output-power. + + if (!crossConnect.setPowerLevel(nodeId, OpticalControlMode.GainLoss.getName(), powerValue, + connectionNumber)) { + LOG.warn("Setting power-control mode off failed for Roadm-connection: {}", + connectionNumber); + // FIXME no return false in that case? } + } catch (InterruptedException e) { + LOG.error("Olm-setPower wait failed :", e); + return false; } - // If Drop node leave node is power mode - } else if (destTpId.toLowerCase().contains("srg")) { - LOG.info("Setting power at drop node"); - crossConnect.setPowerLevel(nodeId, OpticalControlMode.Power, null, connectionNumber); - } - } else { - LOG.error("OLM-PowerMgmtImpl : Error with node type for node {}", nodeId); + break; + default : + LOG.error("OLM-PowerMgmtImpl : Error with node type for node {}", nodeId); + break; } } return true; } + private Map getTxPowerRangeMap(Nodes inputNode, String destTpId, String nodeId, + Integer openroadmVersion) { + + Optional mappingObject = inputNode.nonnullMapping().values().stream() + .filter(o -> o.key().equals(new MappingKey(destTpId))).findFirst(); + if (mappingObject.isEmpty()) { + LOG.info("Mapping object not found for nodeId: {}", nodeId); + // FIXME shouldn't it be LOG.error ? + return null; + // return null here means return false in setPower() + // TODO Align protections with getSRGRxPowerRangeMap + } + + String circuitPackName = mappingObject.get().getSupportingCircuitPackName(); + String portName = mappingObject.get().getSupportingPort(); + switch (openroadmVersion) { + case 1: + return PowerMgmtVersion121.getXponderPowerRange(circuitPackName, portName, + nodeId, deviceTransactionManager); + case 2: + return PowerMgmtVersion221.getXponderPowerRange(circuitPackName, portName, + nodeId, deviceTransactionManager); + case 3: + return PowerMgmtVersion710.getXponderPowerRange(circuitPackName, portName, + nodeId, deviceTransactionManager); + default: + LOG.error("Unrecognized OpenRoadm version"); + return new HashMap<>(); + // FIXME shouldn't it lead to a return false in setPower()? + } + } + + + 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()); + + 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(); + switch (rdmOpenroadmVersion) { + case 1: + return PowerMgmtVersion121.getSRGRxPowerRange(nodeId, srgId, + deviceTransactionManager, circuitPackName, portName); + case 2: + return PowerMgmtVersion221.getSRGRxPowerRange(nodeId, srgId, + deviceTransactionManager, circuitPackName, portName); + case 3: + return PowerMgmtVersion710.getSRGRxPowerRange(nodeId, srgId, + deviceTransactionManager, circuitPackName, portName); + default: + LOG.error("Unrecognized OpenRoadm version"); + return null; + //return null here means return false in setPower() + // TODO Align protections with getTxPowerRangeMap + } + } + + private BigDecimal getSpanLossTx(String supportingOts, String destTpId, String nodeId, Integer openroadmVersion) { + try { + switch (openroadmVersion) { + case 1: + Optional interfaceOpt = + this.openRoadmInterfaces.getInterface(nodeId, supportingOts); + if (interfaceOpt.isEmpty()) { + LOG.error(INTERFACE_NOT_PRESENT, supportingOts, nodeId); + return null; + } + if (interfaceOpt.get().augmentation(Interface1.class).getOts() + .getSpanLossTransmit() == null) { + LOG.error("interface {} has no spanloss value", interfaceOpt.get().getName()); + return null; + } + return interfaceOpt.get() + .augmentation(Interface1.class) + .getOts().getSpanLossTransmit().getValue(); + case 2: + Optional interfaceOpt1 = + this.openRoadmInterfaces.getInterface(nodeId, supportingOts); + if (interfaceOpt1.isEmpty()) { + LOG.error(INTERFACE_NOT_PRESENT, supportingOts, nodeId); + return null; + } + if (interfaceOpt1.get().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()); + return null; + } + return interfaceOpt1.get() + .augmentation(org.opendaylight.yang.gen.v1.http.org + .openroadm.optical.transport.interfaces.rev181019.Interface1.class) + .getOts().getSpanLossTransmit().getValue(); + // TODO no case 3 ? + default: + return null; + } + } catch (OpenRoadmInterfaceException ex) { + LOG.error("Failed to get interface {} from node {}!", + supportingOts, nodeId, ex); + return null; + } catch (IllegalArgumentException ex) { + LOG.error("Failed to get non existing interface {} from node {}!", + supportingOts, nodeId); + return null; + } + } + + private BigDecimal getXpdrPowerValue(Nodes inputNode, String destTpId, String nodeId, Integer openroadmVersion, + String srgId, String nextNodeId) { + + Map txPowerRangeMap = getTxPowerRangeMap(inputNode, destTpId, nodeId, openroadmVersion); + if (txPowerRangeMap == null) { + return null; + // return null here means return false in setPower() + } + BigDecimal powerVal = + openroadmVersion == 3 ? DEFAULT_TPDR_PWR_400G : DEFAULT_TPDR_PWR_100G; + if (txPowerRangeMap.isEmpty()) { + LOG.info("Tranponder range not available setting to default power for nodeId: {}", nodeId); + return powerVal; + } + + Map rxSRGPowerRangeMap = getSRGRxPowerRangeMap(srgId, nextNodeId, openroadmVersion); + if (rxSRGPowerRangeMap == null) { + return null; + // return null here means return false in setPower() + // TODO empty txPowerRangeMap + null rxSRGPowerRangeMap is allowed + // => confirm this behavior is OK + } + if (rxSRGPowerRangeMap.isEmpty()) { + LOG.info("SRG Power Range not found, setting the Transponder range to default"); + return powerVal; + } + + powerVal = new BigDecimal(txPowerRangeMap.get("MaxTx")) + .min(new BigDecimal(rxSRGPowerRangeMap.get("MaxRx"))); + LOG.info("Calculated Transponder Power value is {}" , powerVal); + return powerVal; + } + + + private BigDecimal getRdmPowerValue(BigDecimal spanLossTx, ServicePowerSetupInput input) { + // 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) { + // 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 + 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; + } + /** * This methods turns down power a WL by performing * following steps: @@ -311,152 +431,44 @@ public class PowerMgmtImpl implements PowerMgmt { * @return true/false based on status of operation */ public Boolean powerTurnDown(ServicePowerTurndownInput input) { - LOG.info("Olm-powerTurnDown initiated"); + LOG.info("Olm-powerTurnDown initiated for input {}", input); /*Starting with last element into the list Z -> A for turning down A -> Z */ + String spectralSlotName = String.join(GridConstant.SPECTRAL_SLOT_SEPARATOR, + input.getLowerSpectralSlotNumber().toString(), + input.getHigherSpectralSlotNumber().toString()); for (int i = input.getNodes().size() - 1; i >= 0; i--) { String nodeId = input.getNodes().get(i).getNodeId(); - String srcTpId = input.getNodes().get(i).getSrcTp(); String destTpId = input.getNodes().get(i).getDestTp(); - Long wlNumber = input.getWaveNumber(); - String connectionNumber = srcTpId + "-" + destTpId + "-" + wlNumber; - if (destTpId.toLowerCase().contains("srg")) { - crossConnect.setPowerLevel(nodeId, OpticalControlMode.Off, null, connectionNumber); - } else if (destTpId.toLowerCase().contains("deg")) { - try { - if (!crossConnect.setPowerLevel(nodeId, OpticalControlMode.Power , new BigDecimal(-60), + String connectionNumber = String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, + 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)) { LOG.warn("Power down failed for Roadm-connection: {}", connectionNumber); return false; } - Thread.sleep(OlmUtils.OLM_TIMER_2); - if (! crossConnect.setPowerLevel(nodeId, OpticalControlMode.Off , null, connectionNumber)) { + Thread.sleep(timer2); + if (!crossConnect.setPowerLevel(nodeId, OpticalControlMode.Off.getName(), null, connectionNumber)) { LOG.warn("Setting power-control mode off failed for Roadm-connection: {}", connectionNumber); return false; } - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LOG.error("Olm-powerTurnDown wait failed {}",e); - return false; + } else if (destTpId.toUpperCase(Locale.getDefault()).contains("SRG")) { + if (!crossConnect.setPowerLevel(nodeId, OpticalControlMode.Off.getName(), null, connectionNumber)) { + LOG.warn("Setting power-control mode off failed for Roadm-connection: {}", connectionNumber); + // FIXME a return false would allow sync with DEG case but makes current Unit tests fail + } } + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LOG.error("Olm-powerTurnDown wait failed: ",e); + return false; } } return true; } - /* - * This method does an edit-config on roadm connection subtree for a given - * connection number in order to set power level for use by the optical - * power control. - * - * @param inputNode - * PortMapping network node. - * @param destTpId - * Destination termination point. - * @param srgId - * SRG Id to which network port is connected to. - * @param nextNodeId - * Next roadm connect. - * @param waveLength - * WaveLength number part of request - * @return true/false based on status of operation. - */ - /*private boolean setTransponderPowerTx(Nodes inputNode, String destTpId, String srgId, - String nextNodeId, Long waveLength) { - Map txPowerRangeMap = null; - Map rxSRGPowerRangeMap = null; - OpenroadmVersion openroadmVersion; - Optional mappingObject = inputNode.getMapping().stream().filter(o -> o.key() - .equals(new MappingKey(destTpId))).findFirst(); - String nodeId = inputNode.getNodeId(); - if (mappingObject.isPresent()) { - String circuitPackName = mappingObject.get().getSupportingCircuitPackName(); - String portName = mappingObject.get().getSupportingPort(); - openroadmVersion = inputNode.getNodeInfo().getOpenroadmVersion(); - if (openroadmVersion.getIntValue() == 1) { - txPowerRangeMap = PowerMgmtVersion121.getXponderPowerRange(circuitPackName, portName, - nodeId, deviceTransactionManager); - } else if (openroadmVersion.getIntValue() == 2) { - txPowerRangeMap = PowerMgmtVersion221.getXponderPowerRange(circuitPackName, portName, - nodeId, deviceTransactionManager); - } - LOG.info("Transponder power range is fine"); - if (!txPowerRangeMap.isEmpty()) { - LOG.info("Transponder power range is not null {}, {}", nextNodeId,srgId); - //Transponder range is not empty then check SRG Range - - Optional mappingObjectSRG = OlmUtils.getNode(nextNodeId, db) - .flatMap(node -> node.getMapping() - .stream().filter(o -> o.key() - .equals(new MappingKey(srgId))).findFirst()); - if (mappingObjectSRG.isPresent()) { - LOG.info("Transponder range exists for nodeId: {}", nodeId); - if (openroadmVersion.getIntValue() == 1) { - rxSRGPowerRangeMap = PowerMgmtVersion121.getSRGRxPowerRange(nextNodeId, srgId, - deviceTransactionManager, mappingObjectSRG.get().getSupportingCircuitPackName(), - mappingObjectSRG.get().getSupportingPort()); - } else if (openroadmVersion.getIntValue() == 2) { - rxSRGPowerRangeMap = PowerMgmtVersion221.getSRGRxPowerRange(nextNodeId, srgId, - deviceTransactionManager, mappingObjectSRG.get().getSupportingCircuitPackName(), - mappingObjectSRG.get().getSupportingPort()); - } - } - double powerValue = 0; - if (!rxSRGPowerRangeMap.isEmpty()) { - LOG.debug("SRG Rx Power range exists for nodeId: {}", nodeId); - if (txPowerRangeMap.get("MaxTx") - <= rxSRGPowerRangeMap.get("MaxRx")) { - powerValue = txPowerRangeMap.get("MaxTx"); - } else if (rxSRGPowerRangeMap.get("MaxRx") - < txPowerRangeMap.get("MaxTx")) { - powerValue = rxSRGPowerRangeMap.get("MaxRx"); - } - LOG.debug("Calculated Transponder Power value is {}" , powerValue); - String interfaceName = destTpId + "-" + waveLength; - if (callSetTransponderPower(nodeId,interfaceName,new BigDecimal(powerValue), - openroadmVersion)) { - LOG.info("Transponder OCH connection: {} power updated ", interfaceName); - try { - LOG.info("Now going in sleep mode"); - Thread.sleep(90000); - return true; - } catch (InterruptedException e) { - LOG.info("Transponder warmup failed for OCH connection: {}", interfaceName, e); - return false; - } - } else { - LOG.info("Transponder OCH connection: {} power update failed ", interfaceName); - return false; - } - } else { - LOG.info("Transponder Range exists but SRG Power Range not found"); - return false; - } - } else { - LOG.info("Tranponder range not available seting to default power for nodeId: {}", nodeId); - String interfaceName = destTpId + "-" + waveLength; - if (callSetTransponderPower(nodeId,interfaceName,new BigDecimal(-5), - openroadmVersion)) { - LOG.info("Transponder OCH connection: {} power updated ", interfaceName); - try { - Thread.sleep(OlmUtils.OLM_TIMER_1); - return true; - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LOG.info("Transponder warmup failed for OCH connection: {}", interfaceName, e); - return false; - } - } else { - LOG.info("Transponder OCH connection: {} power update failed ", interfaceName); - return false; - } - } - } else { - LOG.info("Mapping object not found for nodeId: {}", nodeId); - return false; - } - }*/ - /** * This method retrieves transponder OCH interface and * sets power. @@ -472,128 +484,59 @@ public class PowerMgmtImpl implements PowerMgmt { * @return true/false based on status of operation */ private boolean callSetTransponderPower(String nodeId, String interfaceName, BigDecimal txPower, - OpenroadmVersion openroadmVersion) { + OpenroadmNodeVersion openroadmVersion) { + boolean powerSetupResult = false; try { - if (openroadmVersion.getIntValue() == 1) { - Optional interfaceOptional; - interfaceOptional = openRoadmInterfaces.getInterface(nodeId, interfaceName); - if (interfaceOptional.isPresent()) { + switch (openroadmVersion.getIntValue()) { + case 1: + Optional interfaceOptional121 = + openRoadmInterfaces.getInterface(nodeId, interfaceName); + if (interfaceOptional121.isEmpty()) { + LOG.error(INTERFACE_NOT_PRESENT, interfaceName, nodeId); + return false; + } powerSetupResult = PowerMgmtVersion121.setTransponderPower(nodeId, interfaceName, - txPower, deviceTransactionManager, interfaceOptional.get()); - } else { - LOG.error("Interface {} on node {} is not present!", interfaceName, nodeId); - return false; - } - } else if (openroadmVersion.getIntValue() == 2) { - Optional interfaceOptional; - interfaceOptional = openRoadmInterfaces.getInterface(nodeId, interfaceName); - if (interfaceOptional.isPresent()) { + txPower, deviceTransactionManager, interfaceOptional121.get()); + break; + case 2: + Optional interfaceOptional221 = + openRoadmInterfaces.getInterface(nodeId, interfaceName); + if (interfaceOptional221.isEmpty()) { + LOG.error(INTERFACE_NOT_PRESENT, interfaceName, nodeId); + return false; + } powerSetupResult = PowerMgmtVersion221.setTransponderPower(nodeId, interfaceName, - txPower, deviceTransactionManager, interfaceOptional.get()); - } else { - LOG.error("Interface {} on node {} is not present!", interfaceName, nodeId); + txPower, deviceTransactionManager, interfaceOptional221.get()); + break; + case 3: + Optional interfaceOptional710 = + openRoadmInterfaces.getInterface(nodeId, interfaceName); + if (interfaceOptional710.isEmpty()) { + LOG.error(INTERFACE_NOT_PRESENT, interfaceName, nodeId); + return false; + } + powerSetupResult = PowerMgmtVersion710.setTransponderPower(nodeId, interfaceName, + txPower, deviceTransactionManager, interfaceOptional710.get()); + break; + default: + LOG.error("Unrecognized OpenRoadm version"); return false; - } } } catch (OpenRoadmInterfaceException ex) { LOG.error("Failed to get interface {} from node {}!", interfaceName, nodeId, ex); return false; } - if (powerSetupResult) { - LOG.debug("Transponder power set up completed successfully for nodeId {} and interface {}", - nodeId,interfaceName); - return powerSetupResult; - } else { + if (!powerSetupResult) { LOG.debug("Transponder power setup failed for nodeId {} on interface {}", nodeId, interfaceName); - return powerSetupResult; - } - } - - /* - * This method retrieves transponder OCH interface and - * sets power. - * - * @param nodeId - * Unique identifier for the mounted netconf- node - * @param interfaceName - * OCH interface name carrying WL - * @param openroadmVersion - * Version of openRoadm device software - * @param wavelength - * Wavelength Number * - * @return true/false based on status of operation - */ - /*private boolean callSetRoadmPowerTx(String nodeId, String interfaceName, - OpenroadmVersion openroadmVersion, - Long wavelength, String connectionNumber) { - if (interfaceName == null) { - crossConnect.setPowerLevel(nodeId, - OpticalControlMode.Power , null,connectionNumber); - return true; - } - try { - if (openroadmVersion.getIntValue() == 1) { - Optional interfaceOpt; - interfaceOpt = openRoadmInterfaces.getInterface(nodeId, interfaceName); - if (interfaceOpt.isPresent()) { - BigDecimal spanLossTx = interfaceOpt.get().augmentation(Interface1.class).getOts() - .getSpanLossTransmit().getValue(); - LOG.debug("Spanloss TX is {}", spanLossTx); - BigDecimal powerValue = BigDecimal.valueOf(Math.min(spanLossTx.doubleValue() - 9, 2)); - LOG.debug("Power Value is {}", powerValue); - Boolean setXconnPowerSuccessVal = crossConnect.setPowerLevel(nodeId, - OpticalControlMode.Power, powerValue,connectionNumber); - if (setXconnPowerSuccessVal) { - LOG.info("Roadm-connection: {} updated "); - //TODO - commented code because one vendor is not supporting - //GainLoss with target-output-power - Thread.sleep(OlmUtils.OLM_TIMER_2); - crossConnect.setPowerLevel(nodeId, - OpticalControlMode.GainLoss, powerValue,connectionNumber); - return true; - } else { - LOG.info("Set Power failed for Roadm-connection: {} on Node: {}", connectionNumber, nodeId); - return false; - } - } else { - LOG.error("Interface {} on node {} is not present!", interfaceName, nodeId); - return false; - } - } else if (openroadmVersion.getIntValue() == 2) { - Optional interfaceOpt; - interfaceOpt = openRoadmInterfaces.getInterface(nodeId, interfaceName); - if (interfaceOpt.isPresent()) { - BigDecimal spanLossTx = interfaceOpt.get().augmentation(org.opendaylight.yang.gen.v1.http - .org.openroadm.optical.transport.interfaces.rev181019.Interface1.class).getOts() - .getSpanLossTransmit().getValue(); - LOG.debug("Spanloss TX is {}", spanLossTx); - BigDecimal powerValue = BigDecimal.valueOf(Math.min(spanLossTx.doubleValue() - 9, 2)); - LOG.debug("Power Value is {}", powerValue); - Boolean setXconnPowerSuccessVal = crossConnect.setPowerLevel(nodeId, - OpticalControlMode.Power, powerValue,connectionNumber); - if (setXconnPowerSuccessVal) { - LOG.info("Roadm-connection: {} updated "); - //TODO - commented code because one vendor is not supporting - //GainLoss with target-output-power - Thread.sleep(OlmUtils.OLM_TIMER_2); - crossConnect.setPowerLevel(nodeId, - OpticalControlMode.GainLoss, powerValue,connectionNumber); - return true; - } else { - LOG.info("Set Power failed for Roadm-connection: {} on Node: {}", connectionNumber, nodeId); - return false; - } - } - } - } catch (OpenRoadmInterfaceException | InterruptedException ex) { - LOG.error("Error during power setup on Roadm nodeId: {} for connection: {}", nodeId, connectionNumber, ex); return false; } - return false; - }*/ + LOG.debug("Transponder power set up completed successfully for nodeId {} and interface {}", + nodeId,interfaceName); + return true; + } }