From: Shweta V Date: Wed, 20 Dec 2017 10:25:52 +0000 (+0100) Subject: Renderer and OLM update X-Git-Tag: v0.2.0~59 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=transportpce.git;a=commitdiff_plain;h=80f9070187cb60c40f057df83bd2ecd123b84b5d Renderer and OLM update - Supports multiple threads configuring devices simulatneously rather than sequentially earlier. - It is now updating service-list topology with port-trail details. - Performs service activation test by checking pre-FEC BER values at a-end and z-end transponders and compares it to a threshold. - Rollback: - Rollback based on device provision failure - Rollback based on powerset failure - Rollback based on ber test failure - Alarm management: - Alarm parsing and logging for fault detection - Alarm suppression at the time of service-request - Alarm inventory - Simultaneous power control on A-Z and Z-A direction - New RPC for calculating span loss base and current based on network model. Co-Authored-By: Dhruv Bhardwaj Co-Authored-By: Shweta Vachhani Co-Authored-By: Masha Dorfman <> Co-Authored-By: Archana Soundararajan Co-Authored-By: Juraj Veverka Co-Authored-By: Samuel Kontri Co-Authored-By: Andrej Zan Co-Authored-By: Milan Fratrik <> Co-authored-by: Martial COULIBALY Change-Id: I7292e82bfecb5fe9c025f9fde8bcd5ebc3be90ba Signed-off-by: Shweta Signed-off-by: Martial COULIBALY --- diff --git a/api/src/main/yang/olm@2017-04-18.yang b/api/src/main/yang/olm@2017-04-18.yang index 741e05765..541b429cc 100644 --- a/api/src/main/yang/olm@2017-04-18.yang +++ b/api/src/main/yang/olm@2017-04-18.yang @@ -8,6 +8,11 @@ module olm { revision-date 2017-09-07; } + import ietf-network-topology { + prefix ietf-network-topology; + revision-date 2015-06-08; + } + organization "transportPCE"; contact @@ -71,7 +76,7 @@ module olm { } } } - /*rpc service-power-reset{ + rpc service-power-reset{ description "This RPC re-calculates and re-sets power for all nodes part of a service given in input"; @@ -131,5 +136,5 @@ module olm { type string; } } - }*/ + } } diff --git a/api/src/main/yang/org-transportpce-common-types@2017-09-07.yang b/api/src/main/yang/org-transportpce-common-types@2017-09-07.yang index 912d548ed..27c52c5bb 100644 --- a/api/src/main/yang/org-transportpce-common-types@2017-09-07.yang +++ b/api/src/main/yang/org-transportpce-common-types@2017-09-07.yang @@ -53,11 +53,11 @@ module org-transportpce-common-types { mandatory true; } leaf resource-type { - type string; + type org-openroadm-resource-types:resource-type-enum; description "Type of the PM resource"; mandatory true; } - //container resource-identifier { + container resource-identifier { leaf resource-name { type string; description "Identifier of particular resource of given type"; @@ -71,9 +71,9 @@ module org-transportpce-common-types { mandatory true; } - //} + } leaf granularity { - type string; + type org-openroadm-pm-types:pm-granularity; description "Granularity of PM bin can be notApplicable,15min,24Hour"; mandatory true; diff --git a/api/src/main/yang/renderer@2017-02-28.yang b/api/src/main/yang/renderer@2017-02-28.yang index c673b5289..4b3eea460 100644 --- a/api/src/main/yang/renderer@2017-02-28.yang +++ b/api/src/main/yang/renderer@2017-02-28.yang @@ -37,31 +37,7 @@ module renderer { } } } - leaf service-name { - type string; - } - leaf wave-number { - type uint32; - } - list nodes { - ordered-by user; - key "node-id"; - leaf node-id { - type string; - description "Gloabally unique identifier - for the node"; - } - leaf src-tp { - type string; - description "Source termination point "; - mandatory true; - } - leaf dest-tp { - type string; - description "Destination termination point "; - mandatory true; - } - } + uses org-transportpce-common-types:olm-renderer-input; } output{ leaf success { @@ -74,7 +50,7 @@ module renderer { } } - /*rpc renderer-rollback { + rpc renderer-rollback { input { uses org-transportpce-common-types:node-interfaces; } @@ -92,5 +68,5 @@ module renderer { } } } - }*/ + } } diff --git a/api/src/main/yang/service_path/transportpce-pathDescription@2017-04-26.yang b/api/src/main/yang/service_path/transportpce-pathDescription@2017-04-26.yang index cfab2cb6b..7aa5e165f 100644 --- a/api/src/main/yang/service_path/transportpce-pathDescription@2017-04-26.yang +++ b/api/src/main/yang/service_path/transportpce-pathDescription@2017-04-26.yang @@ -50,41 +50,41 @@ module transportpce-pathDescription { } grouping PCE-resource { - description - "This resource identifier is intended to provide a generic identifer - for any resource that can be used without specific knowledge of - the resource."; - container resource { - choice resource { - case termination-point { - container termination-point-identifier { - leaf tp-id { - type string; //to be clarified with topology model - } - leaf node-id { - type string; //to be clarified with topology model - } + description + "This resource identifier is intended to provide a generic identifer + for any resource that can be used without specific knowledge of + the resource."; + container resource { + choice resource { + case termination-point { + container termination-point-identifier { + leaf tp-id { + type string; //to be clarified with topology model + } + leaf node-id { + type string; //to be clarified with topology model } } + } - case link { - container link-identifier { - leaf link-id { - type string; //to be clarified with topology model - } + case link { + container link-identifier { + leaf link-id { + type string; //to be clarified with topology model } } + } - case node { - container node-identifier { - leaf node-id { - type string; // to be clarified with topology model - } + case node { + container node-identifier { + leaf node-id { + type string; // to be clarified with topology model } } } } } + } grouping path-description { diff --git a/olm/pom.xml b/olm/pom.xml index b0f2651e0..d5d7c9564 100644 --- a/olm/pom.xml +++ b/olm/pom.xml @@ -21,37 +21,37 @@ and is available at http://www.eclipse.org/legal/epl-v10.html transportpce-olm 0.2.0-SNAPSHOT bundle + + + + + org.opendaylight.controller + mdsal-artifacts + 1.7.3-SNAPSHOT + import + pom + + + org.opendaylight.netconf + netconf-artifacts + 1.4.3-SNAPSHOT + import + pom + + + + ${project.groupId} transportpce-api ${project.version} - + ${project.groupId} transportpce-renderer ${project.version} - - ${project.groupId}.ordmodels - transportpce-ordmodels-common - ${project.version} - - - ${project.groupId}.ordmodels - transportpce-ordmodels-network - ${project.version} - - - ${project.groupId}.ordmodels - transportpce-ordmodels-service - ${project.version} - - - ${project.groupId}.ordmodels - transportpce-ordmodels-device - ${project.version} - org.opendaylight.controller.model model-topology @@ -75,4 +75,5 @@ and is available at http://www.eclipse.org/legal/epl-v10.html test + diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/OlmPowerServiceRpcImpl.java b/olm/src/main/java/org/opendaylight/transportpce/olm/OlmPowerServiceRpcImpl.java new file mode 100644 index 000000000..85244577c --- /dev/null +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/OlmPowerServiceRpcImpl.java @@ -0,0 +1,148 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.olm; + +import java.util.concurrent.Future; +import org.opendaylight.transportpce.olm.service.OlmPowerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossBaseInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossBaseOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossCurrentInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossCurrentOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.OlmService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerResetInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerResetOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownOutput; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; + +/** + * The Class OlmPowerServiceRpcImpl. + */ +public class OlmPowerServiceRpcImpl implements OlmService { + private final OlmPowerService olmPowerService; + + public OlmPowerServiceRpcImpl(OlmPowerService olmPowerService) { + this.olmPowerService = olmPowerService; + } + + /** + * This method is the implementation of the 'get-pm' RESTCONF service, which + * is one of the external APIs into the olm application. + * + *

+ * 1. get-pm This operation traverse through current PM list and gets PM for + * given NodeId and Resource name + * + *

+ * The signature for this method was generated by yang tools from the + * olm API model. + * + * @param input + * Input parameter from the olm yang model + * + * @return Result of the request + */ + @Override + public Future> getPm(GetPmInput input) { + return RpcResultBuilder.success(olmPowerService.getPm(input)).buildFuture(); + } + + /** + * This method is the implementation of the 'service-power-setup' RESTCONF service, which + * is one of the external APIs into the olm application. + * + *

+ * 1. service-power-setup: This operation performs following steps: + * Step1: Calculate Spanloss on all links which are part of service. + * TODO Step2: Calculate power levels for each Tp-Id + * TODO Step3: Post power values on roadm connections + * + *

+ * The signature for this method was generated by yang tools from the + * olm API model. + * + * @param input + * Input parameter from the olm yang model + * Input will contain nodeId and termination point + * + * @return Result of the request + */ + @Override + public Future> servicePowerSetup( + ServicePowerSetupInput input) { + return RpcResultBuilder.success(olmPowerService.servicePowerSetup(input)).buildFuture(); + } + + /** + * This method is the implementation of the 'service-power-trundown' RESTCONF service, which + * is one of the external APIs into the olm application. + * + *

+ * 1. service-power-turndown: This operation performs following steps: + * Step1: For each TP within Node sets interface outofservice . + * Step2: For each roam-connection sets power to -60dbm + * Step3: Turns power mode off + * + *

+ * The signature for this method was generated by yang tools from the + * olm API model. + * + * @param input + * Input parameter from the olm yang model + * Input will contain nodeId and termination point + * + * @return Result of the request + */ + @Override + public Future> servicePowerTurndown(ServicePowerTurndownInput input) { + return RpcResultBuilder.success(olmPowerService.servicePowerTurndown(input)).buildFuture(); + } + + /** + * This method calculates Spanloss for all Roadm to Roadm links, + * part of active inventory in Network Model or for newly added links + * based on input src-type. + * + *

+ * 1. Calculate-Spanloss-Base: This operation performs following steps: + * Step1: Read all Roadm-to-Roadm links from network model or get data for given linkID. + * Step2: Retrieve PMs for each end point for OTS interface + * Step3: Calculates Spanloss + * Step4: Posts calculated spanloss in Device and in network model + * + *

+ * The signature for this method was generated by yang tools from the + * renderer API model. + * + * @param input + * Input parameter from the olm yang model + * Input will contain SourceType and linkId if srcType is Link + * + * @return Result of the request + */ + @Override + public Future> calculateSpanlossBase(CalculateSpanlossBaseInput input) { + return RpcResultBuilder.success(olmPowerService.calculateSpanlossBase(input)).buildFuture(); + } + + @Override + public Future> calculateSpanlossCurrent( + CalculateSpanlossCurrentInput input) { + return RpcResultBuilder.success(olmPowerService.calculateSpanlossCurrent(input)).buildFuture(); + } + + @Override + public Future> servicePowerReset(ServicePowerResetInput input) { + return RpcResultBuilder.success(olmPowerService.servicePowerReset(input)).buildFuture(); + } +} \ No newline at end of file diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/OlmPowerSetupImpl.java b/olm/src/main/java/org/opendaylight/transportpce/olm/OlmPowerSetupImpl.java deleted file mode 100644 index 9a82ad5ef..000000000 --- a/olm/src/main/java/org/opendaylight/transportpce/olm/OlmPowerSetupImpl.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.transportpce.olm; - -import com.google.common.base.Optional; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.transportpce.olm.power.PowerMgmt; -import org.opendaylight.transportpce.olm.spanloss.RoadmLinks; -import org.opendaylight.transportpce.olm.spanloss.SpanLoss; -import org.opendaylight.transportpce.renderer.mapping.PortMapping; -import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.rev161014.CurrentPmlist; -import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.rev161014.current.pm.Measurements; -import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.rev161014.currentpmlist.CurrentPm; -import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmNamesEnum; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.OlmService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupOutputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownOutputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm.output.MeasurementsBuilder; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.common.RpcResultBuilder; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The Class OlmPowerSetupImpl. - */ -public class OlmPowerSetupImpl implements OlmService { - - /** The Constant LOG. */ - private static final Logger LOG = LoggerFactory.getLogger(OlmPowerSetupImpl.class); - - /** The db. */ - private final DataBroker db; - - /** The mps. */ - private final MountPointService mps; - - /** - * Instantiates a new olm power setup impl. - * - * @param db - * the db - * @param mps - * the mps - */ - public OlmPowerSetupImpl(DataBroker db, MountPointService mps) { - this.db = db; - this.mps = mps; - } - - /** - * This method is the implementation of the 'get-pm' RESTCONF service, which - * is one of the external APIs into the olm application. - * - *

- * 1. get-pm This operation traverse through current PM list and gets PM for - * given NodeId and Resource name - * - *

- * The signature for this method was generated by yang tools from the - * renderer API model. - * - * @param input - * Input parameter from the olm yang model - * - * @return Result of the request - */ - @Override - public Future> getPm(GetPmInput input) { - LOG.info("Getting PM Data for NodeId: {} ResouceType: {} ResourceName: {}", - input.getNodeId(),input.getResourceType(),input.getResourceName()); - new PortMapping(db, mps, input.getNodeId()); - DataBroker deviceDb = PortMapping.getDeviceDataBroker(input.getNodeId(), mps); - InstanceIdentifier currentPmsIID = InstanceIdentifier.create(CurrentPmlist.class); - ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction(); - Optional currentPmList; - String methodName = ""; - List currentPms = new ArrayList<>(); - GetPmOutputBuilder pmOutputBuilder = new GetPmOutputBuilder(); - List - measrements = new ArrayList(); - try { - currentPmList = rtx.read(LogicalDatastoreType.OPERATIONAL, currentPmsIID).get(); - if (currentPmList.isPresent()) { - currentPms.addAll(currentPmList.get().getCurrentPm()); - for (CurrentPm pm : currentPms) { - MeasurementsBuilder measurement = new MeasurementsBuilder(); - if (pm.getResource().getResourceType().getType().toString().equals(input.getResourceType())) { - - switch (pm.getResource().getResourceType().getType()) { - case CircuitPack: - methodName = "getCircuitPackName"; - break; - case Connection: - methodName = "getConnectionNumber"; - break; - case Degree: - methodName = "getDegreeNumber"; - break; - case Interface: - methodName = "getInterfaceName"; - break; - case InternalLink: - methodName = "getInternalLinkName"; - break; - case PhysicalLink: - methodName = "getPhysicalLinkName"; - break; - case Service: - methodName = "getServiceName"; - break; - case Shelf: - methodName = "getShelfName"; - break; - case SharedRiskGroup: - methodName = "getSrgNumber"; - break; - default: - methodName = "getPort"; - break; - } - try { - - String pmResourceId = pm.getResource().getResource().getResource().getImplementedInterface() - .getMethod(methodName).invoke(pm.getResource().getResource().getResource()).toString(); - if (pmResourceId.equals(input.getResourceName()) && pm.getGranularity() != null) { - if (pm.getGranularity().getName().equals(input.getGranularity())) { - for (Measurements measure : pm.getMeasurements()) { - if (!measure.getMeasurement().getPmParameterName().getType().equals( - PmNamesEnum.VendorExtension)) { - measurement.setPmparameterName(measure.getMeasurement().getPmParameterName() - .getType().toString()); - measurement.setPmparameterValue(measure.getMeasurement() - .getPmParameterValue().getDecimal64().toString()); - measrements.add(measurement.build()); - } - } - } - } - - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException - | NoSuchMethodException | SecurityException ex) { - LOG.warn("Unable to find PM for NodeID: {} ResourceName: {} ",input.getNodeId(), - input.getResourceName(),ex); - } - } - } - if (measrements.size() > 0) { - pmOutputBuilder.setNodeId(input.getNodeId()).setResourceType(input.getResourceType()).setResourceId( - input.getResourceName()).setGranularity(input.getGranularity()).setMeasurements(measrements); - } - - } else { - LOG.info("Device PM Data is not available"); - } - - } catch (InterruptedException | ExecutionException ex) { - LOG.warn("Unable to get currentPmList for NodeID: {}",input.getNodeId(),ex); - } - LOG.info("PM Data found successfully for {}-{}",pmOutputBuilder.getNodeId(),pmOutputBuilder.getResourceId()); - return RpcResultBuilder.success(pmOutputBuilder).buildFuture(); - } - - - /** - * This method is the implementation of the 'service-power-setup' RESTCONF service, which - * is one of the external APIs into the olm application. - * - *

- * 1. service-power-setup: This operation performs following steps: - * Step1: Calculate Spanloss on all links which are part of service. - * TODO Step2: Calculate power levels for each Tp-Id - * TODO Step3: Post power values on roadm connections - * - *

- * The signature for this method was generated by yang tools from the - * renderer API model. - * - * @param input - * Input parameter from the olm yang model - * Input will contain nodeId and termination point - * - * @return Result of the request - */ - @Override - public Future> servicePowerSetup( - ServicePowerSetupInput input) { - List roadmLinks = new ArrayList(); - ServicePowerSetupOutputBuilder output = new ServicePowerSetupOutputBuilder(); - //Finds degree TpID from node and generates a list of links - for (int i = 0; i < input.getNodes().size(); i++) { - if (input.getNodes().get(i).getDestTp().toLowerCase().contains("deg")) { - RoadmLinks rdmLink = new RoadmLinks(); - rdmLink.setSrcNodeId(input.getNodes().get(i).getNodeId()); - rdmLink.setSrcTpId(input.getNodes().get(i).getDestTp()); - rdmLink.setDestNodeId(input.getNodes().get(i + 1).getNodeId()); - rdmLink.setDestTpid(input.getNodes().get(i + 1).getSrcTp()); - roadmLinks.add(rdmLink); - } - } - boolean successValSpanCalculation = new SpanLoss(db, mps).getLinkSpanloss(roadmLinks); - boolean successValPowerCalculation = new PowerMgmt(db,mps).setPower(input); - - if (successValSpanCalculation && successValPowerCalculation) { - output.setResult("Success"); - } else { - output.setResult("Failed"); - } - - return RpcResultBuilder.success(output).buildFuture(); - } - - - /** - * This method is the implementation of the 'service-power-trundown' RESTCONF service, which - * is one of the external APIs into the olm application. - * - *

- * 1. service-power-turndown: This operation performs following steps: - * Step1: For each TP within Node sets interface outofservice . - * Step2: For each roam-connection sets power to -60dbm - * Step3: Turns power mode off - * - *

- * The signature for this method was generated by yang tools from the - * renderer API model. - * - * @param input - * Input parameter from the olm yang model - * Input will contain nodeId and termination point - * - * @return Result of the request - */ - @Override - public Future> servicePowerTurndown(ServicePowerTurndownInput input) { - ServicePowerTurndownOutputBuilder output = new ServicePowerTurndownOutputBuilder(); - if (new PowerMgmt(db,mps).powerTurnDown(input)) { - output.setResult("Success"); - } else { - output.setResult("Failed"); - } - return RpcResultBuilder.success(output).buildFuture(); - } -} \ No newline at end of file diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/OlmProvider.java b/olm/src/main/java/org/opendaylight/transportpce/olm/OlmProvider.java index 6325d333d..36343095c 100644 --- a/olm/src/main/java/org/opendaylight/transportpce/olm/OlmProvider.java +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/OlmProvider.java @@ -8,10 +8,9 @@ package org.opendaylight.transportpce.olm; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.transportpce.olm.service.OlmPowerService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.OlmService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,40 +19,21 @@ import org.slf4j.LoggerFactory; * The Class OlmProvider. */ public class OlmProvider { - - /** The Constant LOG. */ private static final Logger LOG = LoggerFactory.getLogger(OlmProvider.class); - - /** The data broker. */ - private final DataBroker dataBroker; - - /** The mount point service. */ - private final MountPointService mountPointService; - - /** The rpc provider registry. */ private final RpcProviderRegistry rpcProviderRegistry; - - /** The get pm registration. */ + private final OlmPowerService olmPowerService; private RpcRegistration olmRPCRegistration; /** * Instantiates a new olm provider. - * - * @param dataBroker - * the data broker - * @param mountPointService - * the mount point service + * @param olmPowerService + * implementation of OlmService * @param rpcProviderRegistry * the rpc provider registry */ - public OlmProvider(final DataBroker dataBroker, final MountPointService mountPointService, - final RpcProviderRegistry rpcProviderRegistry) { - this.dataBroker = dataBroker; - this.mountPointService = mountPointService; + public OlmProvider(final RpcProviderRegistry rpcProviderRegistry, final OlmPowerService olmPowerService) { this.rpcProviderRegistry = rpcProviderRegistry; - if (mountPointService == null) { - LOG.error("Mount service is null"); - } + this.olmPowerService = olmPowerService; } /** @@ -62,8 +42,8 @@ public class OlmProvider { public void init() { LOG.info("OlmProvider Session Initiated"); // Initializing Notification module - olmRPCRegistration = rpcProviderRegistry.addRpcImplementation(OlmService.class, new OlmPowerSetupImpl( - dataBroker,mountPointService)); + olmRPCRegistration = rpcProviderRegistry.addRpcImplementation(OlmService.class, new OlmPowerServiceRpcImpl( + this.olmPowerService)); } /** diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmt.java b/olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmt.java index 789d2fb9c..e7ab4f6cc 100644 --- a/olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmt.java +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmt.java @@ -8,22 +8,24 @@ package org.opendaylight.transportpce.olm.power; -import com.google.common.base.Optional; -import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.ListenableFuture; + import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPoint; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaces; -import org.opendaylight.transportpce.renderer.provisiondevice.CrossConnect; +import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.transportpce.common.crossconnect.CrossConnect; +import org.opendaylight.transportpce.common.device.DeviceTransaction; +import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +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.openroadm.common.types.rev161014.NodeTypes; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.OpticalControlMode; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.PowerDBm; @@ -35,42 +37,36 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfac import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.RoadmConnections; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.RoadmConnectionsBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.RoadmConnectionsKey; import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev161014.AdminStates; import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.Interface1Builder; import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.och.container.OchBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.Interface1; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.Network; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.NodesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.Mapping; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.MappingKey; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PowerMgmt { private static final Logger LOG = LoggerFactory.getLogger(PowerMgmt.class); + private static final long DATA_STORE_READ_TIMEOUT = 120; private final DataBroker db; - private final MountPointService mps; - public static final InstanceIdentifier NETCONF_TOPO_IID = - InstanceIdentifier - .create(NetworkTopology.class) - .child(Topology.class, - new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); + private final OpenRoadmInterfaces openRoadmInterfaces; + private final CrossConnect crossConnect; + private final DeviceTransactionManager deviceTransactionManager; - public PowerMgmt(DataBroker db, MountPointService mps) { + public PowerMgmt(DataBroker db, OpenRoadmInterfaces openRoadmInterfaces, + CrossConnect crossConnect, DeviceTransactionManager deviceTransactionManager) { this.db = db; - this.mps = mps; + this.openRoadmInterfaces = openRoadmInterfaces; + this.crossConnect = crossConnect; + this.deviceTransactionManager = deviceTransactionManager; } /** @@ -89,52 +85,51 @@ public class PowerMgmt { String nodeId = input.getNodes().get(i).getNodeId(); String srcTpId = input.getNodes().get(i).getSrcTp(); String destTpId = input.getNodes().get(i).getDestTp(); - DataBroker deviceDb = getDeviceDataBroker(nodeId , mps); - Nodes inputNode = getNode(nodeId, mps, db); - LOG.info("Getting data from input node {}",inputNode.getNodeType()); - LOG.info("Getting mapping data for node is {}",inputNode.getMapping().stream().filter(o -> o.getKey() - .equals(new MappingKey(destTpId))).findFirst().toString()); + Optional inputNodeOptional = OlmUtils.getNode(nodeId, db); // If node type is transponder - if (inputNode.getNodeType() != null && inputNode.getNodeType().equals(NodeTypes.Xpdr)) { + if (inputNodeOptional.isPresent() + && inputNodeOptional.get().getNodeType() != null + && inputNodeOptional.get().getNodeType().equals(NodeTypes.Xpdr)) { + + Nodes inputNode = inputNodeOptional.get(); + LOG.info("Getting data from input node {}", inputNode.getNodeType()); + LOG.info("Getting mapping data for node is {}", inputNode.getMapping().stream().filter(o -> o.getKey() + .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.getKey() .equals(new MappingKey(destTpId))).findFirst(); if (mappingObject.isPresent()) { - Map txPowerRangeMap = getXponderPowerRange(nodeId, mappingObject.get() - .getSupportingCircuitPackName(), - mappingObject.get().getSupportingPort(),deviceDb); + Map txPowerRangeMap = getXponderPowerRange(mappingObject.get() + .getSupportingCircuitPackName(), mappingObject.get().getSupportingPort(), nodeId); 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(); - DataBroker deviceDbSRG = getDeviceDataBroker(nextNodeId , mps); - Map rxSRGPowerRangeMap = getSRGRxPowerRange(nextNodeId, srgId, deviceDbSRG); - Double powerValue = new Double(0); + + Map rxSRGPowerRangeMap = getSRGRxPowerRange(nextNodeId, srgId); + double powerValue = 0; if (!rxSRGPowerRangeMap.isEmpty()) { LOG.info("SRG Rx Power range exists for nodeId: {}", nodeId); - if (txPowerRangeMap.get("MaxTx").doubleValue() - <= rxSRGPowerRangeMap.get("MaxRx").doubleValue()) { - powerValue = txPowerRangeMap.get("MaxTx").doubleValue(); - } else if (rxSRGPowerRangeMap.get("MaxRx").doubleValue() - < txPowerRangeMap.get("MaxTx").doubleValue()) { - powerValue = rxSRGPowerRangeMap.get("MaxRx").doubleValue(); + 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); - if (setTransponderPower(nodeId, destTpId, destTpId + "-" + input.getWaveNumber(), - new BigDecimal(powerValue), deviceDb)) { - LOG.info("Transponder OCH connection: {} power updated ", - destTpId + "-" + input.getWaveNumber()); + String interfaceName = destTpId + "-" + input.getWaveNumber(); + if (setTransponderPower(nodeId, interfaceName, new BigDecimal(powerValue))) { + LOG.info("Transponder OCH connection: {} power updated ", interfaceName); try { LOG.info("Now going in sleep mode"); - Thread.sleep(180000); + Thread.sleep(120000); } catch (InterruptedException e) { - LOG.info("Transponder warmup failed for OCH connection: {}", - destTpId + "-" + input.getWaveNumber(), e); + LOG.info("Transponder warmup failed for OCH connection: {}", interfaceName, e); } } else { - LOG.info("Transponder OCH connection: {} power update failed ", - destTpId + "-" + input.getWaveNumber()); + LOG.info("Transponder OCH connection: {} power update failed ", interfaceName); } } else { LOG.info("SRG Power Range not found"); @@ -142,20 +137,17 @@ public class PowerMgmt { } else { LOG.info("Tranponder range not available seting to default " + "power for nodeId: {}", nodeId); - if (setTransponderPower(nodeId, destTpId, destTpId + "-" + input.getWaveNumber(), - new BigDecimal(-5), deviceDb)) { - LOG.info("Transponder OCH connection: {} power updated ", - destTpId + "-" + input.getWaveNumber()); + String interfaceName = destTpId + "-" + input.getWaveNumber(); + if (setTransponderPower(nodeId, interfaceName, new BigDecimal(-5))) { + LOG.info("Transponder OCH connection: {} power updated ", interfaceName); try { - Thread.sleep(180000); + Thread.sleep(120000); } catch (InterruptedException e) { // TODO Auto-generated catch block - LOG.info("Transponder warmup failed for OCH connection: {}", - destTpId + "-" + input.getWaveNumber(), e); + LOG.info("Transponder warmup failed for OCH connection: {}", interfaceName, e); } } else { - LOG.info("Transponder OCH connection: {} power update failed ", - destTpId + "-" + input.getWaveNumber()); + LOG.info("Transponder OCH connection: {} power update failed ", interfaceName); } } } else { @@ -165,45 +157,64 @@ public class PowerMgmt { } else { LOG.info("{} is a drop node. Net power settings needed", nodeId); } - } else if (inputNode.getNodeType() != null && inputNode.getNodeType().equals(NodeTypes.Rdm)) { - // If Degree is transmitting end then set power + } else if (inputNodeOptional.isPresent() + && inputNodeOptional.get().getNodeType() != null + && inputNodeOptional.get().getNodeType().equals(NodeTypes.Rdm)) { + // If Degree is transmitting end then set power + Nodes inputNode = inputNodeOptional.get(); + LOG.info("This is a roadm device "); + String connectionNumber = srcTpId + "-" + destTpId + "-" + input.getWaveNumber(); + LOG.info("Connection number is {}", connectionNumber); if (destTpId.toLowerCase().contains("deg")) { - java.util.Optional mappingObject = inputNode.getMapping().stream().filter(o -> o.getKey() + Optional mappingObjectOptional = inputNode.getMapping().stream().filter(o -> o.getKey() .equals(new MappingKey(destTpId))).findFirst(); - Mapping portMapping = mappingObject.get(); - if (portMapping != null && deviceDb != null) { - BigDecimal spanLossTx = new OpenRoadmInterfaces(db, mps, nodeId, destTpId) - .getInterface(portMapping.getSupportingOts()).getAugmentation(Interface1.class).getOts() - .getSpanLossTransmit().getValue(); - Double powerValue = Math.min(spanLossTx.doubleValue() - 9 , 2); - CrossConnect roadmCrossConnect = new CrossConnect(deviceDb, srcTpId - + "-" + destTpId + "-" + input.getWaveNumber()); + if (mappingObjectOptional.isPresent()) { + LOG.info("Dest point is Degree {}", mappingObjectOptional.get()); + Mapping portMapping = mappingObjectOptional.get(); + Optional interfaceOpt; try { - Boolean setXconnPowerSuccessVal = roadmCrossConnect.setPowerLevel(OpticalControlMode.Power, - new PowerDBm(BigDecimal.valueOf(powerValue))); - if (setXconnPowerSuccessVal) { - LOG.info("Roadm-connection: {} updated "); - //TODO - commented code because one vendor is not supporting - //GainLoss with target-output-power - Thread.sleep(20000); - roadmCrossConnect.setPowerLevel(OpticalControlMode.GainLoss, - new PowerDBm(BigDecimal.valueOf(powerValue))); - } else { - LOG.info("Set Power failed for Roadm-connection: {} on Node: {}", - srcTpId + "-" + destTpId + "-" + input.getWaveNumber(), nodeId); + interfaceOpt = openRoadmInterfaces.getInterface(nodeId, portMapping.getSupportingOts()); + } catch (OpenRoadmInterfaceException ex) { + LOG.error("Failed to get interface {} from node {}!", portMapping.getSupportingOts(), + nodeId, ex); + return false; + } + if (interfaceOpt.isPresent()) { + BigDecimal spanLossTx = interfaceOpt.get().getAugmentation(Interface1.class).getOts() + .getSpanLossTransmit().getValue(); + LOG.info("Spanloss TX is {}", spanLossTx); + BigDecimal powerValue = BigDecimal.valueOf(Math.min(spanLossTx.doubleValue() - 9, 2)); + LOG.info("Power Value is {}", powerValue); + try { + Boolean setXconnPowerSuccessVal = setPowerLevel(nodeId, + OpticalControlMode.Power, powerValue, connectionNumber); + LOG.info("Success Value is {}", setXconnPowerSuccessVal); + if (setXconnPowerSuccessVal) { + LOG.info("Roadm-connection: {} updated "); + //TODO - commented code because one vendor is not supporting + //GainLoss with target-output-power + Thread.sleep(20000); + 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; } - } catch (InterruptedException e) { - LOG.error("Olm-setPower wait failed {}",e); + } else { + LOG.error("Interface {} on node {} is not present!", portMapping.getSupportingOts(), + nodeId); return false; } } // If Drop node leave node is power mode } else if (destTpId.toLowerCase().contains("srg")) { LOG.info("Setting power at drop node"); - CrossConnect roadmDropCrossConnect = new CrossConnect(deviceDb, srcTpId + "-" - + destTpId + "-" + input.getWaveNumber()); - roadmDropCrossConnect.setPowerLevel(OpticalControlMode.Power, null); + setPowerLevel(nodeId, OpticalControlMode.Power, null, connectionNumber); } } } @@ -232,43 +243,36 @@ public class PowerMgmt { */ public Boolean powerTurnDown(ServicePowerTurndownInput input) { LOG.info("Olm-powerTurnDown initiated"); - /**Starting with last element into the list Z -> A for - turning down A -> Z **/ + /*Starting with last element into the list Z -> A for + turning down A -> Z */ 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(); - DataBroker deviceDb = getDeviceDataBroker(nodeId , mps); - if (!setInterfaceOutOfService(nodeId, srcTpId, - srcTpId + "-" + wlNumber, deviceDb)) { - LOG.warn("Out of service status update failed for interface {} ", - srcTpId + "-" + wlNumber); - return false; - } - if (!setInterfaceOutOfService(nodeId, destTpId, - destTpId + "-" + wlNumber, deviceDb)) { - LOG.warn("Out of service status update failed for interface {} ", - destTpId + "-" + wlNumber); - return false; - } - CrossConnect roadmCrossConnect = new CrossConnect(deviceDb, srcTpId - + "-" + destTpId + "-" + wlNumber); + String srcInterfaceName = srcTpId + "-" + wlNumber; + //if (!setInterfaceOutOfService(nodeId, srcTpId, srcInterfaceName, deviceDb)) { + // LOG.warn("Out of service status update failed for interface {} ", srcInterfaceName); + // return false; + //} + String destInterfaceName = destTpId + "-" + wlNumber; + //if (!setInterfaceOutOfService(nodeId, destTpId, destInterfaceName, deviceDb)) { + // LOG.warn("Out of service status update failed for interface {} ", destInterfaceName); + // return false; + //} + String connectionNumber = srcTpId + "-" + destTpId + "-" + wlNumber; if (destTpId.toLowerCase().contains("srg")) { - roadmCrossConnect.setPowerLevel(OpticalControlMode.Off, null); + setPowerLevel(nodeId, OpticalControlMode.Off, null, connectionNumber); } else if (destTpId.toLowerCase().contains("deg")) { try { - if (!roadmCrossConnect.setPowerLevel(OpticalControlMode.Power, - new PowerDBm(new BigDecimal(-60)))) { - LOG.warn("Power down failed for Roadm-connection: {}", srcTpId - + "-" + destTpId + "-" + wlNumber); + if (!setPowerLevel(nodeId, OpticalControlMode.Power, new BigDecimal(-60), + connectionNumber)) { + LOG.warn("Power down failed for Roadm-connection: {}", connectionNumber); return false; } Thread.sleep(20000); - if (!roadmCrossConnect.setPowerLevel(OpticalControlMode.Off, - null)) { - LOG.warn("Setting power-control mode off failed for Roadm-connection: {}", - srcTpId + "-" + destTpId + "-" + wlNumber); + if (!setPowerLevel(nodeId, OpticalControlMode.Off, null, connectionNumber)) { + LOG.warn("Setting power-control mode off failed for Roadm-connection: {}", connectionNumber); return false; } } catch (InterruptedException e) { @@ -291,145 +295,83 @@ public class PowerMgmt { * Termination point of mounted netconf - node * @param interfaceName * Name of interface which needs status update - * @param deviceDb - * Reference to device data broker * @return true/false based on status of operation */ - public Boolean setInterfaceOutOfService(String nodeId, String tpId, - String interfaceName, DataBroker deviceDb) { + private Boolean setInterfaceOutOfService(String nodeId, String tpId, String interfaceName) { InstanceIdentifier interfacesIID = InstanceIdentifier .create(OrgOpenroadmDevice.class) .child(Interface.class, new InterfaceKey(interfaceName)); - Interface nodeInterface = new OpenRoadmInterfaces(db, mps, nodeId, tpId) - .getInterface(interfaceName); - InterfaceBuilder intfBuilder = new InterfaceBuilder(nodeInterface); - intfBuilder.setAdministrativeState(AdminStates.OutOfService); - final WriteTransaction writeTransaction = deviceDb.newWriteOnlyTransaction(); - writeTransaction.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, intfBuilder.build()); - final CheckedFuture submit = writeTransaction.submit(); + Optional nodeInterfaceOpt; try { - submit.checkedGet(); - LOG.info("Successfully posted interface {}" , interfaceName); - return true; - } catch (TransactionCommitFailedException ex) { - LOG.warn("Failed to post {} ", interfaceName ,ex); + nodeInterfaceOpt = openRoadmInterfaces.getInterface(nodeId, interfaceName); + } catch (OpenRoadmInterfaceException ex) { + LOG.error("Failed to get interface {} from node {}!", interfaceName, nodeId, ex); return false; } - } - - /** - * This static method returns the DataBroker for a netconf node. - * - * @param nodeId - * Unique identifier for the mounted netconf- node - * @param mps - * Reference to mount service - * @return Databroker for the given device - */ - public static DataBroker getDeviceDataBroker(String nodeId, MountPointService mps) { - MountPoint netconfNode = getDeviceMountPoint(nodeId, mps); - if (netconfNode != null) { - DataBroker netconfNodeDataBroker = netconfNode.getService(DataBroker.class).get(); - return netconfNodeDataBroker; - } else { - LOG.info("Device Data broker not found for :" + nodeId); - return null; - } - } - - /** - * This static method returns the Mountpoint for a netconf node. - * - * @param nodeId - * Unique identifier for the mounted netconf- node - * @param mps - * Reference to mount service - * @return MountPoint for the given device - */ - public static MountPoint getDeviceMountPoint(String nodeId, MountPointService mps) { - final Optional netconfNodeOptional = mps.getMountPoint(NETCONF_TOPO_IID - .child(Node.class, new NodeKey(new NodeId(nodeId)))); - // Get mount point for specified device - if (netconfNodeOptional.isPresent()) { - MountPoint netconfNode = netconfNodeOptional.get(); - return netconfNode; - } else { - LOG.info("Mount Point not found for :" + nodeId); - return null; - } - - } - - /** - * This static method returns the DataBroker for a netconf node. - * - * @param nodeId - * Unique identifier for the mounted netconf- node - * @param mps - * Reference to mount service - * @param db - * Databroker - * @return Nodes from portMapping for given nodeId - */ - public static Nodes getNode(String nodeId, MountPointService mps, DataBroker db) { - InstanceIdentifier nodesIID = InstanceIdentifier.create(Network.class) - .child(Nodes.class, new NodesKey(nodeId)); - ReadOnlyTransaction readTransaction = db.newReadOnlyTransaction(); - Optional nodeObject; - try { - nodeObject = readTransaction.read(LogicalDatastoreType.CONFIGURATION, nodesIID).get(); - if (nodeObject.isPresent()) { - LOG.info("Found Node in Portmapping for nodeId {}", nodeObject.get().getNodeId()); - return nodeObject.get(); - } else { - LOG.info("Could not find Portmapping for nodeId {}", nodeId); - return null; + if (nodeInterfaceOpt.isPresent()) { + InterfaceBuilder intfBuilder = new InterfaceBuilder(nodeInterfaceOpt.get()); + intfBuilder.setAdministrativeState(AdminStates.OutOfService); + Future> deviceTxFuture = deviceTransactionManager.getDeviceTransaction(nodeId); + DeviceTransaction deviceTx; + try { + Optional deviceTxOpt = deviceTxFuture.get(); + if (deviceTxOpt.isPresent()) { + deviceTx = deviceTxOpt.get(); + } else { + LOG.error("Transaction for device {} was not found!", nodeId); + return false; + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Unable to get transaction for device {}!", nodeId, e); + return false; } - } catch (InterruptedException | ExecutionException ex) { - LOG.info("Unable to read Portmapping for nodeId {}", nodeId, ex); + deviceTx.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, intfBuilder.build()); + ListenableFuture submit = deviceTx.submit(Timeouts.DEVICE_WRITE_TIMEOUT, + Timeouts.DEVICE_WRITE_TIMEOUT_UNIT); + try { + submit.get(); + LOG.info("Successfully posted interface {}", interfaceName); + return true; + } catch (InterruptedException | ExecutionException ex) { + LOG.warn("Failed to post {} ", interfaceName, ex); + return false; + } + } else { + LOG.error("Interface {} on node {} is not present!", interfaceName, nodeId); + return false; } - return null; } /** * This method provides Transponder transmit power range. * - * @param nodeId - * Unique identifier for the mounted netconf- node * @param circuitPackName * Transponder circuitPack name * @param portName * Transponder port name - * @param deviceDb + * @param deviceId * Databroker for the given device * @return HashMap holding Min and Max transmit power for given port */ - public Map getXponderPowerRange(String nodeId, String circuitPackName, String portName, - DataBroker deviceDb) { - InstanceIdentifier portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child( - CircuitPacks.class, new CircuitPacksKey(circuitPackName)).child(Ports.class, new PortsKey(portName)); - ReadOnlyTransaction readTransaction = deviceDb.newReadOnlyTransaction(); - Map powerRangeMap = new HashMap(); - try { - LOG.info("Fetching logical Connection Point value for port " + portName + " at circuit pack " - + circuitPackName); - Optional portObject = readTransaction.read(LogicalDatastoreType.OPERATIONAL, portIID).get(); - if (portObject.isPresent()) { - Ports port = portObject.get(); - if (port.getTransponderPort() != null) { - powerRangeMap.put("MaxTx", port.getTransponderPort().getPortPowerCapabilityMaxTx() - .getValue().doubleValue()); - powerRangeMap.put("MinTx", port.getTransponderPort().getPortPowerCapabilityMinTx() - .getValue().doubleValue()); - } else { - LOG.warn("Logical Connection Point value missing for " + circuitPackName + " " + port - .getPortName()); - } + private Map getXponderPowerRange(String circuitPackName, String portName, String deviceId) { + InstanceIdentifier portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) + .child(CircuitPacks.class, new CircuitPacksKey(circuitPackName)) + .child(Ports.class, new PortsKey(portName)); + Map powerRangeMap = new HashMap<>(); + LOG.info("Fetching logical Connection Point value for port {} at circuit pack {}", portName, circuitPackName); + Optional portObject = + deviceTransactionManager.getDataFromDevice(deviceId, LogicalDatastoreType.OPERATIONAL, portIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + if (portObject.isPresent()) { + Ports port = portObject.get(); + if (port.getTransponderPort().getPortPowerCapabilityMaxTx() != null) { + powerRangeMap.put("MaxTx", port.getTransponderPort().getPortPowerCapabilityMaxTx().getValue() + .doubleValue()); + powerRangeMap.put("MinTx", port.getTransponderPort().getPortPowerCapabilityMinTx().getValue() + .doubleValue()); + } else { + LOG.warn("Logical Connection Point value missing for {} {}", circuitPackName, port.getPortName()); } - } catch (InterruptedException | ExecutionException ex) { - LOG.warn("Read failed for Logical Connection Point value missing for " + circuitPackName + " " - + portName,ex); - return powerRangeMap; } return powerRangeMap; } @@ -441,48 +383,43 @@ public class PowerMgmt { * Unique identifier for the mounted netconf- node * @param srgId * SRG Id connected to transponder - * @param deviceDb - * Databroker for the given device * @return HashMap holding Min and Max transmit power for given port */ - public Map getSRGRxPowerRange(String nodeId, String srgId, DataBroker deviceDb) { - Map powerRangeMap = new HashMap(); + private Map getSRGRxPowerRange(String nodeId, String srgId) { + Map powerRangeMap = new HashMap<>(); LOG.info("Coming inside Xpdr power range"); - java.util.Optional mappingSRGObject = getNode(nodeId, mps, db).getMapping() + Optional mappingSRGOptional = OlmUtils.getNode(nodeId, db).flatMap(node -> node.getMapping() .stream().filter(o -> o.getKey() - .equals(new MappingKey(srgId))).findFirst(); - if (mappingSRGObject.isPresent()) { + .equals(new MappingKey(srgId))).findFirst()); + if (mappingSRGOptional.isPresent()) { LOG.info("Mapping object exists."); - String circuitPackName = mappingSRGObject.get().getSupportingCircuitPackName(); - String portName = mappingSRGObject.get().getSupportingPort(); + String circuitPackName = mappingSRGOptional.get().getSupportingCircuitPackName(); + String portName = mappingSRGOptional.get().getSupportingPort(); InstanceIdentifier portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) .child(CircuitPacks.class, new CircuitPacksKey(circuitPackName)) .child(Ports.class, new PortsKey(portName)); - try { - LOG.info("Fetching logical Connection Point value for port " + portName + " at circuit pack " - + circuitPackName + portIID); - ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction(); - Optional portObject = rtx.read(LogicalDatastoreType.OPERATIONAL, portIID).get(); - if (portObject.isPresent()) { - Ports port = portObject.get(); - if (port.getRoadmPort() != null) { - LOG.info("Port found on the node ID"); - powerRangeMap.put("MinRx", port.getRoadmPort() - .getPortPowerCapabilityMinRx().getValue().doubleValue()); - powerRangeMap.put("MaxRx", port.getRoadmPort() - .getPortPowerCapabilityMaxRx().getValue().doubleValue()); - return powerRangeMap; - } else { - LOG.warn("Roadm ports power value is missing for " + circuitPackName + " " + port - .getPortName()); - } + + LOG.info("Fetching logical Connection Point value for port {} at circuit pack {}{}", portName, + circuitPackName, portIID); + Optional portObject = + deviceTransactionManager.getDataFromDevice(nodeId, LogicalDatastoreType.OPERATIONAL, portIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + if (portObject.isPresent()) { + Ports port = portObject.get(); + if (port.getRoadmPort() != null) { + LOG.info("Port found on the node ID"); + powerRangeMap.put("MinRx", port.getRoadmPort() + .getPortPowerCapabilityMinRx().getValue().doubleValue()); + powerRangeMap.put("MaxRx", port.getRoadmPort() + .getPortPowerCapabilityMaxRx().getValue().doubleValue()); + return powerRangeMap; } else { - LOG.info("Port not found"); + LOG.warn("Roadm ports power value is missing for {} {}", circuitPackName, port.getPortName()); } - } catch (InterruptedException | ExecutionException ex) { - LOG.warn("Read failed for Logical Connection Point value missing for " + circuitPackName + " " - + portName,ex); + } else { + LOG.info("Port not found"); } + } else { LOG.info("Port mapping not found for nodeId: {} and srgId: {} ", nodeId, srgId); @@ -497,43 +434,126 @@ public class PowerMgmt { * * @param nodeId * Unique identifier for the mounted netconf- node - * @param tpId - * Termination port for transponder connected to SRG * @param interfaceName * OCH interface name carrying WL * @param txPower * Calculated transmit power - * @param deviceDb - * Databroker for the given device * @return true/false based on status of operation */ - public boolean setTransponderPower(String nodeId, String tpId, String interfaceName, BigDecimal txPower, - DataBroker deviceDb) { + private boolean setTransponderPower(String nodeId, String interfaceName, BigDecimal txPower) { LOG.info("Setting target-power for transponder nodeId: {} InterfaceName: {}", nodeId, interfaceName); - InterfaceBuilder ochInterfaceBuilder = new InterfaceBuilder( - new OpenRoadmInterfaces(db, mps, nodeId, tpId) - .getInterface(interfaceName)); - OchBuilder ochBuilder = new OchBuilder(ochInterfaceBuilder - .getAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.optical - .channel.interfaces.rev161014.Interface1.class).getOch()); - ochBuilder.setTransmitPower(new PowerDBm(txPower)); - ochInterfaceBuilder.addAugmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.optical - .channel.interfaces.rev161014.Interface1.class, - new Interface1Builder().setOch(ochBuilder.build()).build()); - ReadWriteTransaction rwtx = deviceDb.newReadWriteTransaction(); - InstanceIdentifier interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(Interface.class, new InterfaceKey(interfaceName)); - rwtx.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, ochInterfaceBuilder.build()); - CheckedFuture submit = rwtx.submit(); + Optional interfaceOptional; try { - submit.checkedGet(); - LOG.info("Power update is submitted"); - return true; - } catch (TransactionCommitFailedException e) { - LOG.info("Setting transponder power failed {}" ,e); + interfaceOptional = openRoadmInterfaces.getInterface(nodeId, interfaceName); + } catch (OpenRoadmInterfaceException ex) { + LOG.error("Failed to get interface {} from node {}!", interfaceName, nodeId, ex); + return false; + } + if (interfaceOptional.isPresent()) { + InterfaceBuilder ochInterfaceBuilder = + new InterfaceBuilder(interfaceOptional.get()); + OchBuilder ochBuilder = new OchBuilder(ochInterfaceBuilder.getAugmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014 + .Interface1.class).getOch()); + ochBuilder.setTransmitPower(new PowerDBm(txPower)); + ochInterfaceBuilder.addAugmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014 + .Interface1.class, new Interface1Builder().setOch(ochBuilder.build()).build()); + + Future> deviceTxFuture = deviceTransactionManager.getDeviceTransaction(nodeId); + DeviceTransaction deviceTx; + try { + Optional deviceTxOpt = deviceTxFuture.get(); + if (deviceTxOpt.isPresent()) { + deviceTx = deviceTxOpt.get(); + } else { + LOG.error("Transaction for device {} was not found!", nodeId); + return false; + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Unable to get transaction for device {}!", nodeId, e); + return false; + } + + InstanceIdentifier interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) + .child(Interface.class, new InterfaceKey(interfaceName)); + deviceTx.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, ochInterfaceBuilder.build()); + ListenableFuture submit = deviceTx.submit(Timeouts.DEVICE_WRITE_TIMEOUT, + Timeouts.DEVICE_WRITE_TIMEOUT_UNIT); + try { + submit.get(); + LOG.info("Power update is submitted"); + return true; + } catch (InterruptedException | ExecutionException e) { + LOG.error("Setting transponder power failed {}", e); + } + } else { + LOG.error("Interface {} on node {} is not present!", interfaceName, nodeId); + } + return false; + } + + /** + * 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 deviceId + * Device id. + * @param mode + * Optical control modelcan be off, power or gainLoss. + * @param powerValue + * Power value in DBm. + * @param connectionNumber + * Name of the cross connect. + * @return true/false based on status of operation. + */ + private boolean setPowerLevel(String deviceId, OpticalControlMode mode, BigDecimal powerValue, + String connectionNumber) { + Optional rdmConnOpt = crossConnect.getCrossConnect(deviceId, connectionNumber); + if (rdmConnOpt.isPresent()) { + RoadmConnectionsBuilder rdmConnBldr = new RoadmConnectionsBuilder(rdmConnOpt.get()); + rdmConnBldr.setOpticalControlMode(mode); + if (powerValue != null) { + rdmConnBldr.setTargetOutputPower(new PowerDBm(powerValue)); + } + RoadmConnections newRdmConn = rdmConnBldr.build(); + + Future> deviceTxFuture = + deviceTransactionManager.getDeviceTransaction(deviceId); + DeviceTransaction deviceTx; + try { + Optional deviceTxOpt = deviceTxFuture.get(); + if (deviceTxOpt.isPresent()) { + deviceTx = deviceTxOpt.get(); + } else { + LOG.error("Transaction for device {} was not found!", deviceId); + return false; + } + } catch (InterruptedException | ExecutionException e) { + LOG.error("Unable to get transaction for device {}!", deviceId, e); + return false; + } + + // post the cross connect on the device + InstanceIdentifier roadmConnIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) + .child(RoadmConnections.class, new RoadmConnectionsKey(connectionNumber)); + deviceTx.put(LogicalDatastoreType.CONFIGURATION, roadmConnIID, newRdmConn); + ListenableFuture submit = deviceTx.submit(Timeouts.DEVICE_WRITE_TIMEOUT, + Timeouts.DEVICE_WRITE_TIMEOUT_UNIT); + try { + submit.get(); + LOG.info("Roadm connection power level successfully set "); + return true; + } catch (InterruptedException | ExecutionException ex) { + LOG.warn("Failed to post {}", newRdmConn, ex); + } + + } else { + LOG.warn("Roadm-Connection is null in set power level ({})", connectionNumber); } return false; } -} \ No newline at end of file +} diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/service/OlmPowerService.java b/olm/src/main/java/org/opendaylight/transportpce/olm/service/OlmPowerService.java new file mode 100644 index 000000000..63e91cf83 --- /dev/null +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/service/OlmPowerService.java @@ -0,0 +1,98 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.olm.service; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossBaseInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossBaseOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossCurrentInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossCurrentOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerResetInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerResetOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownOutput; + +public interface OlmPowerService { + + /** + * This method is the implementation of the 'get-pm' service. + * + *

+ * 1. get-pm This operation traverse through current PM list and gets PM for + * given NodeId and Resource name + * + * @param input + * Input parameter from the olm yang model + * + * @return Result of the request + */ + GetPmOutput getPm(GetPmInput input); + + /** + * This method is the implementation of the 'service-power-setup'. + * + *

+ * 1. service-power-setup: This operation performs following steps: + * Step1: Calculate Spanloss on all links which are part of service. + * TODO Step2: Calculate power levels for each Tp-Id + * TODO Step3: Post power values on roadm connections + * + * @param input + * Input parameter from the olm yang model + * Input will contain nodeId and termination point + * + * @return Result of the request + */ + ServicePowerSetupOutput servicePowerSetup(ServicePowerSetupInput input); + + /** + * This method is the implementation of the 'service-power-trundown'. + * + *

+ * 1. service-power-turndown: This operation performs following steps: + * Step1: For each TP within Node sets interface outofservice . + * Step2: For each roam-connection sets power to -60dbm + * Step3: Turns power mode off + * + * @param input + * Input parameter from the olm yang model + * Input will contain nodeId and termination point + * + * @return Result of the request + */ + ServicePowerTurndownOutput servicePowerTurndown(ServicePowerTurndownInput input); + + /** + * This method calculates Spanloss for all Roadm to Roadm links, + * part of active inventory in Network Model or for newly added links + * based on input src-type. + * + *

+ * 1. Calculate-Spanloss-Base: This operation performs following steps: + * Step1: Read all Roadm-to-Roadm links from network model or get data for given linkID. + * Step2: Retrieve PMs for each end point for OTS interface + * Step3: Calculates Spanloss + * Step4: Posts calculated spanloss in Device and in network model + * + * @param input + * Input parameter from the olm yang model + * Input will contain SourceType and linkId if srcType is Link + * + * @return Result of the request + */ + CalculateSpanlossBaseOutput calculateSpanlossBase(CalculateSpanlossBaseInput input); + + CalculateSpanlossCurrentOutput calculateSpanlossCurrent( + CalculateSpanlossCurrentInput input); + + ServicePowerResetOutput servicePowerReset(ServicePowerResetInput input); +} diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/service/OlmPowerServiceImpl.java b/olm/src/main/java/org/opendaylight/transportpce/olm/service/OlmPowerServiceImpl.java new file mode 100644 index 000000000..ba455724b --- /dev/null +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/service/OlmPowerServiceImpl.java @@ -0,0 +1,461 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.olm.service; + +import com.google.common.base.Strings; +import com.google.common.util.concurrent.ListenableFuture; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.transportpce.common.InstanceIdentifiers; +import org.opendaylight.transportpce.common.NetworkUtils; +import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.transportpce.common.device.DeviceTransaction; +import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.transportpce.common.mapping.PortMapping; +import org.opendaylight.transportpce.olm.power.PowerMgmt; +import org.opendaylight.transportpce.olm.util.OlmUtils; +import org.opendaylight.transportpce.olm.util.OtsPmHolder; +import org.opendaylight.transportpce.olm.util.RoadmLinks; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.RatioDB; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.Interface; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Link1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmLinkType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.Interface1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.Interface1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.ots.container.Ots; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.ots.container.OtsBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.get.pm.input.ResourceIdentifierBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NodeId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.Node; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NodeKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.node.SupportingNode; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Network1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.Link; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossBaseInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossBaseOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossBaseOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossCurrentInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossCurrentOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.CalculateSpanlossCurrentOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerResetInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerResetOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm.output.Measurements; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.Mapping; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OlmPowerServiceImpl implements OlmPowerService { + private static final Logger LOG = LoggerFactory.getLogger(OlmPowerServiceImpl.class); + private static final String SUCCESS = "Success"; + private static final String FAILED = "Failed"; + private final DataBroker dataBroker; + private final PowerMgmt powerMgmt; + private final DeviceTransactionManager deviceTransactionManager; + private final PortMapping portMapping; + + public OlmPowerServiceImpl(DataBroker dataBroker, PowerMgmt powerMgmt, + DeviceTransactionManager deviceTransactionManager, PortMapping portMapping) { + this.dataBroker = dataBroker; + this.powerMgmt = powerMgmt; + this.portMapping = portMapping; + this.deviceTransactionManager = deviceTransactionManager; + } + + public void init() { + LOG.info("init ..."); + } + + public void close() { + LOG.info("close ..."); + } + + + @Override + public GetPmOutput getPm(GetPmInput pmInput) { + GetPmOutputBuilder pmOutputBuilder = OlmUtils.pmFetch(pmInput, deviceTransactionManager); + return pmOutputBuilder.build(); + } + + @Override + public ServicePowerSetupOutput servicePowerSetup(ServicePowerSetupInput powerSetupInput) { + ServicePowerSetupOutputBuilder powerSetupOutput = new ServicePowerSetupOutputBuilder(); + boolean successValPowerCalculation = powerMgmt.setPower(powerSetupInput); + + if (successValPowerCalculation) { + powerSetupOutput.setResult(SUCCESS); + } else { + powerSetupOutput.setResult(FAILED); + } + return powerSetupOutput.build(); + } + + @Override + public ServicePowerTurndownOutput servicePowerTurndown( + ServicePowerTurndownInput powerTurndownInput) { + + ServicePowerTurndownOutputBuilder powerTurnDownOutput = new ServicePowerTurndownOutputBuilder(); + // TODO add flag or return failure instead of string + if (powerMgmt.powerTurnDown(powerTurndownInput)) { + powerTurnDownOutput.setResult(SUCCESS); + } else { + powerTurnDownOutput.setResult(FAILED); + } + return powerTurnDownOutput.build(); + } + + @Override + public CalculateSpanlossBaseOutput calculateSpanlossBase(CalculateSpanlossBaseInput spanlossBaseInput) { + + LOG.info("CalculateSpanlossBase Request received for source type {}", spanlossBaseInput.getSrcType()); + + List networkLinks = getNetworkLinks(); + if (networkLinks.isEmpty()) { + LOG.warn("Failed to get links form {} topology.", NetworkUtils.OVERLAY_NETWORK_ID); + return new CalculateSpanlossBaseOutputBuilder().setResult(FAILED).build(); + } + + if (! CalculateSpanlossBaseInput.SrcType.All.equals(spanlossBaseInput.getSrcType())) { + networkLinks = networkLinks.stream() + .filter(link -> link.getLinkId().equals(spanlossBaseInput.getLinkId())) + .collect(Collectors.toList()); + } + + List roadmLinks = new ArrayList<>(); + for (Link link : networkLinks) { + Link1 roadmLinkAugmentation = link.getAugmentation(Link1.class); + if (roadmLinkAugmentation == null) { + LOG.debug("Missing OpenRoadm link augmentation in link {} from {} topology.", + link.getLinkId().getValue(), NetworkUtils.OVERLAY_NETWORK_ID); + continue; + } + if (OpenroadmLinkType.ROADMTOROADM.equals(roadmLinkAugmentation.getLinkType())) { + // Only calculate spanloss for Roadm-to-Roadm links + RoadmLinks roadmLink = new RoadmLinks(); + roadmLink.setSrcNodeId(link.getSource().getSourceNode().getValue()); + roadmLink.setSrcTpId(link.getSource().getSourceTp().toString()); + roadmLink.setDestNodeId(link.getDestination().getDestNode().getValue()); + roadmLink.setDestTpid(link.getDestination().getDestTp().toString()); + roadmLinks.add(roadmLink); + } + } + + if (roadmLinks.isEmpty()) { + LOG.warn("Topology {} does not have any Roadm-to-Roadm links.", NetworkUtils.OVERLAY_NETWORK_ID); + return new CalculateSpanlossBaseOutputBuilder().setResult(FAILED).build(); + } + + boolean spanLossResult = getLinkSpanloss(roadmLinks); + CalculateSpanlossBaseOutputBuilder spanLossBaseBuilder = new CalculateSpanlossBaseOutputBuilder(); + if (spanLossResult) { + spanLossBaseBuilder.setResult(SUCCESS); + return spanLossBaseBuilder.build(); + } else { + LOG.warn("Spanloss calculation failed"); + spanLossBaseBuilder.setResult(FAILED); + return spanLossBaseBuilder.build(); + } + + } + + @Override + public CalculateSpanlossCurrentOutput calculateSpanlossCurrent(CalculateSpanlossCurrentInput input) { + LOG.info("calculateSpanlossCurrent Request received for all links in network model."); + List networkLinks = getNetworkLinks(); + if (networkLinks.isEmpty()) { + LOG.warn("Failed to get links form {} topology.", NetworkUtils.OVERLAY_NETWORK_ID); + return null; + } + List roadmLinks = new ArrayList<>(); + for (Link link : networkLinks) { + Link1 roadmLinkAugmentation = link.getAugmentation(Link1.class); + if (roadmLinkAugmentation == null) { + LOG.debug("Missing OpenRoadm link augmentation in link {} from {} topology.", + link.getLinkId().getValue(), NetworkUtils.OVERLAY_NETWORK_ID); + continue; + } + if (OpenroadmLinkType.ROADMTOROADM.equals(roadmLinkAugmentation.getLinkType())) { + // Only calculate spanloss for Roadm-to-Roadm links + RoadmLinks roadmLink = new RoadmLinks(); + roadmLink.setSrcNodeId(link.getSource().getSourceNode().toString()); + roadmLink.setSrcTpId(link.getSource().getSourceTp().toString()); + roadmLink.setDestNodeId(link.getDestination().getDestNode().toString()); + roadmLink.setDestTpid(link.getDestination().getDestTp().toString()); + roadmLinks.add(roadmLink); + } + } + + if (roadmLinks.isEmpty()) { + LOG.warn("Topology {} does not have any Roadm-to-Roadm links.", NetworkUtils.OVERLAY_NETWORK_ID); + return null; + } + + boolean spanLossResult = getLinkSpanloss(roadmLinks); + CalculateSpanlossCurrentOutputBuilder spanLossCurrentBuilder = new CalculateSpanlossCurrentOutputBuilder(); + if (spanLossResult) { + spanLossCurrentBuilder.setResult(SUCCESS); + return spanLossCurrentBuilder.build(); + } else { + LOG.error("Spanloss Current calculation failed"); + spanLossCurrentBuilder.setResult(FAILED); + return spanLossCurrentBuilder.build(); + } + } + + @Override + public ServicePowerResetOutput servicePowerReset(ServicePowerResetInput input) { + // TODO + return null; + } + + private List getNetworkLinks() { + NetworkKey overlayTopologyKey = new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID)); + + InstanceIdentifier networkIID = InstanceIdentifier.builder(Network.class, overlayTopologyKey) + .augmentation(Network1.class) + .build(); + Optional networkOptional; + try (ReadOnlyTransaction rtx = dataBroker.newReadOnlyTransaction()) { + //TODO change to constant from Timeouts class when it will be merged. + networkOptional = rtx.read(LogicalDatastoreType.CONFIGURATION, networkIID).get(Timeouts.DATASTORE_READ, + TimeUnit.MILLISECONDS).toJavaUtil(); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("Read of {} topology failed", NetworkUtils.OVERLAY_NETWORK_ID); + return Collections.emptyList(); + } + + if (! networkOptional.isPresent()) { + LOG.warn("Network augmentation with links data is not present in {} topology.", + NetworkUtils.OVERLAY_NETWORK_ID); + return Collections.emptyList(); + } + + List networkLinks = networkOptional.get().getLink(); + if (networkLinks == null || networkLinks.isEmpty()) { + LOG.warn("Links are not present in {} topology.", NetworkUtils.OVERLAY_NETWORK_ID); + return Collections.emptyList(); + } + return networkLinks; + } + + /** + * This method retrieves OTS PM from current PM list by nodeId and TPId: Steps: + * + *

+ * 1. Get OTS interface name from port mapping by TPId 2. Call getPm RPC to get OTS PM + * + *

+ * + * @param nodeId Node-id of the NE. + * @param tpID Termination point Name. + * @param pmName PM name which need to be retrieved + * @return reference to OtsPmHolder + */ + private OtsPmHolder getPmMeasurements(String nodeId, String tpID, String pmName) { + String realNodeId = getRealNodeId(nodeId); + Mapping mapping = portMapping.getMapping(realNodeId, tpID); + if (mapping == null) { + return null; + } + GetPmInput getPmInput = new GetPmInputBuilder().setNodeId(realNodeId) + .setResourceType(ResourceTypeEnum.Interface).setGranularity(PmGranularity._15min) + .setResourceIdentifier( + new ResourceIdentifierBuilder().setResourceName(mapping.getSupportingOts()).build()) + .build(); + GetPmOutput otsPmOutput = getPm(getPmInput); + + if (otsPmOutput == null) { + LOG.info("OTS PM not found for NodeId: {} TP Id:{} PMName:{}", realNodeId, tpID, pmName); + return null; + } + try { + for (Measurements measurement : otsPmOutput.getMeasurements()) { + if (pmName.equals(measurement.getPmparameterName())) { + return new OtsPmHolder(pmName, Double.parseDouble(measurement.getPmparameterValue()), + mapping.getSupportingOts()); + } + } + } catch (NumberFormatException e) { + LOG.warn("Unable to get PM for NodeId: {} TP Id:{} PMName:{}", realNodeId, tpID, pmName, e); + } + return null; + } + + /** + * This method Sets Spanloss on A-End and Z-End OTS interface: Steps: + * + *

+ * 1. Read existing interface details + * + *

+ * 2. Set spanloss + * + * @param nodeId nodeId of NE on which spanloss need to be updated + * @param interfaceName OTS interface for NE on which spanloss is cacluated + * @param spanLoss calculated spanloss value + * @param direction for which spanloss is calculated.It can be either Tx or Rx + * @return true/false + */ + private boolean setSpanLoss(String nodeId, String interfaceName, BigDecimal spanLoss, String direction) { + String realNodeId = getRealNodeId(nodeId); + LOG.info("Setting Spanloss in device for {}, InterfaceName: {}", realNodeId, interfaceName); + InstanceIdentifier interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) + .child(Interface.class, new InterfaceKey(interfaceName)); + com.google.common.base.Optional interfaceObject; + try { + Future> deviceTxFuture = + deviceTransactionManager.getDeviceTransaction(realNodeId); + java.util.Optional deviceTxOpt = deviceTxFuture.get(); + DeviceTransaction deviceTx; + if (deviceTxOpt.isPresent()) { + deviceTx = deviceTxOpt.get(); + } else { + LOG.error("Device transaction for device {} was not found!", nodeId); + return false; + } + interfaceObject = deviceTx.read(LogicalDatastoreType.CONFIGURATION, interfacesIID).get(); + BigDecimal initialSpanloss = new BigDecimal(0); + RatioDB spanLossRx = new RatioDB(initialSpanloss); + RatioDB spanLossTx = new RatioDB(initialSpanloss); + if (interfaceObject.isPresent()) { + Interface intf = interfaceObject.get(); + InterfaceBuilder interfaceBuilder = new InterfaceBuilder(intf); + OtsBuilder otsBuilder = new OtsBuilder(); + if (intf.getAugmentation(Interface1.class) != null + && intf.getAugmentation(Interface1.class).getOts() != null) { + Ots ots = intf.getAugmentation(Interface1.class).getOts(); + otsBuilder.setFiberType(ots.getFiberType()); + spanLossRx = ots.getSpanLossReceive(); + spanLossTx = ots.getSpanLossTransmit(); + } else { + spanLossRx = new RatioDB(spanLoss); + spanLossTx = new RatioDB(spanLoss); + } + Interface1Builder intf1Builder = new Interface1Builder(); + if (direction.equals("TX")) { + otsBuilder.setSpanLossTransmit(new RatioDB(spanLoss)); + otsBuilder.setSpanLossReceive(spanLossRx); + } else { + otsBuilder.setSpanLossTransmit(spanLossTx).setSpanLossReceive(new RatioDB(spanLoss)); + } + interfaceBuilder.addAugmentation(Interface1.class, intf1Builder.setOts(otsBuilder.build()).build()); + deviceTx.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, interfaceBuilder.build()); + ListenableFuture submit = + deviceTx.submit(Timeouts.DEVICE_WRITE_TIMEOUT, Timeouts.DEVICE_WRITE_TIMEOUT_UNIT); + submit.get(); + LOG.info("Spanloss Value update completed successfully"); + return true; + } + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Unable to set spanloss", e); + } + return false; + } + + /** + * This method calculates Spanloss by TranmistPower - Receive Power Steps: + * + *

+ * 1. Read PM measurement + * + *

+ * 2. Set Spanloss value for interface + * + * @param roadmLinks reference to list of RoadmLinks + * @return true/false + */ + private boolean getLinkSpanloss(List roadmLinks) { + LOG.info("Executing GetLinkSpanLoss"); + BigDecimal spanLoss = new BigDecimal(0); + for (int i = 0; i < roadmLinks.size(); i++) { + + OtsPmHolder srcOtsPmHoler = getPmMeasurements(roadmLinks.get(i).getSrcNodeId(), + roadmLinks.get(i).getSrcTpId(), "OpticalPowerOutput"); + OtsPmHolder destOtsPmHoler = getPmMeasurements(roadmLinks.get(i).getDestNodeId(), + roadmLinks.get(i).getDestTpid(), "OpticalPowerInput"); + spanLoss = new BigDecimal(srcOtsPmHoler.getOtsParameterVal() - destOtsPmHoler.getOtsParameterVal()) + .setScale(0, RoundingMode.HALF_UP); + LOG.info("Spanloss Calculated as :" + spanLoss + "=" + srcOtsPmHoler.getOtsParameterVal() + "-" + + destOtsPmHoler.getOtsParameterVal()); + if (spanLoss.doubleValue() < 28 && spanLoss.doubleValue() > 0) { + if (!setSpanLoss(roadmLinks.get(i).getSrcNodeId(), srcOtsPmHoler.getOtsInterfaceName(), spanLoss, + "TX")) { + LOG.info("Setting spanLoss failed for " + roadmLinks.get(i).getSrcNodeId()); + return false; + } + if (!setSpanLoss(roadmLinks.get(i).getDestNodeId(), destOtsPmHoler.getOtsInterfaceName(), spanLoss, + "RX")) { + LOG.info("Setting spanLoss failed for " + roadmLinks.get(i).getDestNodeId()); + return false; + } + } + } + return true; + } + + private String getRealNodeId(String mappedNodeId) { + KeyedInstanceIdentifier mappedNodeII = + InstanceIdentifiers.OVERLAY_NETWORK_II.child(Node.class, new NodeKey(new NodeId(mappedNodeId))); + com.google.common.base.Optional realNode; + try (ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction()) { + realNode = readOnlyTransaction.read(LogicalDatastoreType.CONFIGURATION, mappedNodeII).get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error(e.getMessage(), e); + throw new IllegalStateException(e); + } + if (!realNode.isPresent() || realNode.get().getSupportingNode() == null) { + throw new IllegalArgumentException( + String.format("Could not find node %s, or supporting node is not present", mappedNodeId)); + } + List collect = realNode.get().getSupportingNode().stream() + .filter(node -> node.getNetworkRef() != null + && NetworkUtils.UNDERLAY_NETWORK_ID.equals(node.getNetworkRef().getValue()) + && node.getNodeRef() != null && !Strings.isNullOrEmpty(node.getNodeRef().getValue())) + .collect(Collectors.toList()); + if (collect.isEmpty() || collect.size() > 1) { + throw new IllegalArgumentException(String.format("Invalid support node count [%d] was found for node %s", + collect.size(), mappedNodeId)); + } + return collect.iterator().next().getNodeRef().getValue(); + } + +} diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/spanloss/SpanLoss.java b/olm/src/main/java/org/opendaylight/transportpce/olm/spanloss/SpanLoss.java deleted file mode 100644 index 026c041fe..000000000 --- a/olm/src/main/java/org/opendaylight/transportpce/olm/spanloss/SpanLoss.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.transportpce.olm.spanloss; - -import com.google.common.base.Optional; -import com.google.common.util.concurrent.CheckedFuture; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.transportpce.olm.OlmPowerSetupImpl; -import org.opendaylight.transportpce.renderer.mapping.PortMapping; -import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.RatioDB; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.Interface; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.Interface1; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.Interface1Builder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.ots.container.Ots; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.transport.interfaces.rev161014.ots.container.OtsBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmInputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm.output.Measurements; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.Mapping; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SpanLoss { - private static final Logger LOG = LoggerFactory.getLogger(SpanLoss.class); - private final DataBroker db; - private final MountPointService mps; - - /** - * Instantiates a new span loss. - * - * @param db - * the db - * @param mps - * the mps - */ - public SpanLoss(DataBroker db, MountPointService mps) { - this.db = db; - this.mps = mps; - } - - /** - * This method retrieves OTS PM from current PM list by nodeId and TPId: - * Steps: - * - *

- * 1. Get OTS interface name from port mapping by TPId 2. Call getPm RPC to - * get OTS PM - * - *

- * - * @param nodeId - * Node-id of the NE. - * @param tpID - * Termination point Name. - * @param pmName - * PM name which need to be retrieved - * @return reference to OtsPmHolder - */ - public OtsPmHolder getPmMeasurements(String nodeId, String tpID, String pmName) { - GetPmInputBuilder otsPmInputBuilder = new GetPmInputBuilder(); - new PortMapping(db, mps, nodeId); - Mapping portMapping = PortMapping.getMapping(nodeId, tpID, db); - if (portMapping != null) { - otsPmInputBuilder.setNodeId(nodeId).setResourceType("Interface").setGranularity("15min") - .setResourceName(portMapping.getSupportingOts()); - Future> otsPmOutput = new OlmPowerSetupImpl(db, mps) - .getPm(otsPmInputBuilder.build()); - if (otsPmOutput != null) { - try { - for (Measurements measurement : otsPmOutput.get().getResult().getMeasurements()) { - if (measurement.getPmparameterName().equals(pmName)) { - return new OtsPmHolder(pmName,Double.parseDouble(measurement.getPmparameterValue()), - portMapping.getSupportingOts()); - } - } - } catch (NumberFormatException | InterruptedException | ExecutionException e) { - LOG.warn("Unable to get PM for NodeId: {} TP Id:{} PMName:{}", nodeId, tpID, pmName, e); - } - } else { - LOG.info("OTS PM not found for NodeId: {} TP Id:{} PMName:{}", nodeId, tpID, pmName); - } - } - return null; - } - - /** - * This method Sets Spanloss on A-End and Z-End OTS interface: Steps: - * - *

- * 1. Read existing interface details - * - *

- * 2. Set spanloss - * - * @param nodeId - * nodeId of NE on which spanloss need to be updated - * @param interfaceName - * OTS interface for NE on which spanloss is cacluated - * @param spanLoss - * calculated spanloss value - * @param direction - * for which spanloss is calculated.It can be either Tx or Rx - * @return true/false - */ - public boolean setSpanLoss(String nodeId, String interfaceName, BigDecimal spanLoss, String direction) { - LOG.info("Setting Spanloss in device for:" + nodeId + " InterfaceName:" + interfaceName); - InstanceIdentifier interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(Interface.class, new InterfaceKey(interfaceName)); - Optional interfaceObject; - try { - DataBroker deviceDb = PortMapping.getDeviceDataBroker(nodeId, mps); - ReadWriteTransaction rwtx = deviceDb.newReadWriteTransaction(); - interfaceObject = rwtx.read(LogicalDatastoreType.CONFIGURATION, interfacesIID).get(); - if (interfaceObject.isPresent()) { - Interface intf = interfaceObject.get(); - InterfaceBuilder interfaceBuilder = new InterfaceBuilder(intf); - Ots ots = intf.getAugmentation(Interface1.class).getOts(); - Interface1Builder intf1Builder = new Interface1Builder(); - OtsBuilder otsBuilder = new OtsBuilder(); - otsBuilder.setFiberType(ots.getFiberType()); - if (direction.equals("TX")) { - otsBuilder.setSpanLossTransmit(new RatioDB(spanLoss)).setSpanLossReceive(ots.getSpanLossReceive()); - } else { - otsBuilder.setSpanLossTransmit(ots.getSpanLossTransmit()).setSpanLossReceive(new RatioDB(spanLoss)); - } - interfaceBuilder.addAugmentation(Interface1.class, intf1Builder.setOts(otsBuilder.build()).build()); - rwtx.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, interfaceBuilder.build()); - CheckedFuture submit = rwtx.submit(); - submit.checkedGet(); - LOG.info("Spanloss Value update completed successfully"); - return true; - } - } catch (InterruptedException | ExecutionException | TransactionCommitFailedException e) { - LOG.warn("Unable to set spanloss", e); - } - return false; - } - - /** - * This method calculates Spanloss by TranmistPower - Receive Power Steps: - * - *

- * 1. Read PM measurement - * - *

- * 2. Set Spanloss value for interface - * - * @param roadmLinks - * reference to list of RoadmLinks - * @return true/false - */ - public boolean getLinkSpanloss(List roadmLinks) { - LOG.info("Executing GetLinkSpanLoss"); - BigDecimal spanLoss = new BigDecimal(0); - for (int i = 0; i < roadmLinks.size(); i++) { - OtsPmHolder srcOtsPmHoler = getPmMeasurements(roadmLinks.get(i).getSrcNodeId(), - roadmLinks.get(i).getSrcTpId(), "OpticalPowerOutput"); - OtsPmHolder destOtsPmHoler = getPmMeasurements(roadmLinks.get(i).getDestNodeId(), - roadmLinks.get(i).getDestTpid(), "OpticalPowerInput"); - spanLoss = new BigDecimal(srcOtsPmHoler.getOtsParameterVal() - destOtsPmHoler.getOtsParameterVal()) - .setScale(0, RoundingMode.HALF_UP); - LOG.info("Spanloss Calculated as :" + spanLoss + "=" + srcOtsPmHoler.getOtsParameterVal() + "-" - + destOtsPmHoler.getOtsParameterVal()); - if (spanLoss.doubleValue() < 28 && spanLoss.doubleValue() > 0) { - if (!setSpanLoss(roadmLinks.get(i).getSrcNodeId(), srcOtsPmHoler.getOtsInterfaceName(), spanLoss, - "TX")) { - LOG.info("Setting spanLoss failed for " + roadmLinks.get(i).getSrcNodeId()); - return false; - } - if (!setSpanLoss(roadmLinks.get(i).getDestNodeId(), destOtsPmHoler.getOtsInterfaceName(), spanLoss, - "RX")) { - LOG.info("Setting spanLoss failed for " + roadmLinks.get(i).getDestNodeId()); - return false; - } - } - } - return true; - } -} \ No newline at end of file diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/util/OlmUtils.java b/olm/src/main/java/org/opendaylight/transportpce/olm/util/OlmUtils.java new file mode 100644 index 000000000..cce360654 --- /dev/null +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/util/OlmUtils.java @@ -0,0 +1,292 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.olm.util; + +import com.google.common.base.Strings; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.rev161014.CurrentPmlist; +import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.rev161014.current.pm.Measurements; +import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.rev161014.currentpmlist.CurrentPm; +import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity; +import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmNamesEnum; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.Resource; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.CircuitPack; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.Connection; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.Degree; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.Interface; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.InternalLink; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.PhysicalLink; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.Port; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.Service; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.Shelf; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.Srg; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.get.pm.input.ResourceIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm.output.MeasurementsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.Network; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.NodesKey; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; +import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OlmUtils { + + private static final Logger LOG = LoggerFactory.getLogger(OlmUtils.class); + private static long DATABROKER_READ_TIMEOUT_SECONDS = 120; + private static final InstanceIdentifier NETCONF_TOPO_IID = + InstanceIdentifier + .create(NetworkTopology.class) + .child(Topology.class, + new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); + + /** + * This static method returns the port mapping {@link Nodes} for node. + * + * @param nodeId + * Unique identifier for the mounted netconf node + * @param db + * Databroker used to read data from data store. + * @return {@link Nodes } from portMapping for given nodeId + */ + public static Optional getNode(String nodeId, DataBroker db) { + InstanceIdentifier nodesIID = InstanceIdentifier.create(Network.class) + .child(Nodes.class, new NodesKey(nodeId)); + try (ReadOnlyTransaction readTransaction = db.newReadOnlyTransaction()) { + return readTransaction.read(LogicalDatastoreType.CONFIGURATION, nodesIID) + .get(DATABROKER_READ_TIMEOUT_SECONDS, TimeUnit.SECONDS).toJavaUtil(); + } catch (InterruptedException | ExecutionException | TimeoutException ex) { + LOG.info("Unable to read Portmapping for nodeId {}", nodeId, ex); + return Optional.empty(); + } + } + + /** + * This method retrieves list of current PMs for given nodeId, + * resourceType, resourceName and Granularity.Currently vendorExtentions + * are excluded but can be added back based on requirement + * + *

+ * 1. pmFetch This operation traverse through current PM list and gets PM for + * given NodeId and Resource name + * + * @param input + * Input parameter from the olm yang model get-pm rpc + * @param deviceTransactionManager + * Device tx manager + * + * @return Result of the request list of PM readings + */ + public static GetPmOutputBuilder pmFetch(GetPmInput input, DeviceTransactionManager deviceTransactionManager) { + LOG.info("Getting PM Data for NodeId: {} ResourceType: {} ResourceName: {}", input.getNodeId(), + input.getResourceType(), input.getResourceIdentifier()); + GetPmOutputBuilder pmOutputBuilder = new GetPmOutputBuilder(); + InstanceIdentifier currentPmsIID = InstanceIdentifier.create(CurrentPmlist.class); + Optional currentPmList; + + currentPmList = deviceTransactionManager + .getDataFromDevice(input.getNodeId(), LogicalDatastoreType.OPERATIONAL, currentPmsIID, + Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT); + if (currentPmList.isPresent()) { + List measurements = extractWantedMeasurements(currentPmList.get(), + input.getResourceType(), input.getResourceIdentifier(), input.getGranularity()); + if (measurements.isEmpty()) { + LOG.error("No Matching PM data found for node: {}, " + "resource type: {}, resource name: {}", + input.getNodeId(), input.getResourceType(), + getResourceIdentifierAsString(input.getResourceIdentifier())); + } else { + pmOutputBuilder.setNodeId(input.getNodeId()).setResourceType(input.getResourceType()) + .setResourceIdentifier(input.getResourceIdentifier()).setGranularity(input.getGranularity()) + .setMeasurements(measurements); + LOG.info("PM Data found successfully for node: {}, resource type: {}, " + "resource name {}", + input.getNodeId(), input.getResourceType(), + getResourceIdentifierAsString(input.getResourceIdentifier())); + } + + } else { + LOG.info("Device PM Data for node: {} is not available", input.getNodeId()); + } + + return pmOutputBuilder; + } + + private static String getResourceIdentifierAsString(ResourceIdentifier resourceIdentifier) { + if (Strings.isNullOrEmpty(resourceIdentifier.getCircuitPackName())) { + return resourceIdentifier.getResourceName(); + } else { + return resourceIdentifier.getResourceName() + ", circuit pack name: " + + resourceIdentifier.getCircuitPackName(); + } + } + + private static List extractWantedMeasurements(CurrentPmlist currentPmList, + ResourceTypeEnum wantedResourceType, ResourceIdentifier wantedResourceIdentifier, + PmGranularity wantedGranularity) { + List measurements = new ArrayList<>(); + for (CurrentPm pm : currentPmList.getCurrentPm()) { + ResourceTypeEnum currentResourceType = pm.getResource().getResourceType().getType(); + if (currentResourceType.equals(wantedResourceType)) { + Resource currentResource = pm.getResource().getResource().getResource(); + PmGranularity currentGranularity = pm.getGranularity(); + boolean isWantedPowerMeasure = isWantedPowerMeasure(currentResource, currentGranularity, + wantedResourceType, wantedResourceIdentifier, wantedGranularity); + if (isWantedPowerMeasure) { + measurements.addAll(extractMeasurements(pm.getMeasurements())); + } + } + } + return measurements; + } + + private static List extractMeasurements(List measurementsFromDevice) { + List + extractedMeasurements = new ArrayList<>(); + for (Measurements measure : measurementsFromDevice) { + MeasurementsBuilder measurement = new MeasurementsBuilder(); + if (!measure.getMeasurement().getPmParameterName().getType().equals(PmNamesEnum.VendorExtension)) { + measurement.setPmparameterName(measure.getMeasurement().getPmParameterName().getType().toString()); + } else { + measurement.setPmparameterName(measure.getMeasurement().getPmParameterName().getExtension()); + } + + if (measure.getMeasurement().getPmParameterValue().getDecimal64() != null) { + measurement.setPmparameterValue(measure.getMeasurement().getPmParameterValue().getDecimal64() + .toPlainString()); + } else if (measure.getMeasurement().getPmParameterValue().getUint64() != null) { + measurement.setPmparameterValue(measure.getMeasurement().getPmParameterValue().getUint64().toString()); + } + extractedMeasurements.add(measurement.build()); + } + return extractedMeasurements; + } + + private static boolean isWantedPowerMeasure(Resource resource, PmGranularity granularity, + ResourceTypeEnum wantedResourceType, ResourceIdentifier wantedResourceIdentifier, + PmGranularity wantedGranularity) { + boolean identifiersAreEqual = compareResourceIdentifiers(resource, wantedResourceType, + wantedResourceIdentifier); + return identifiersAreEqual && granularity != null && granularity.equals(wantedGranularity); + } + + private static boolean compareResourceIdentifiers(Resource resource, ResourceTypeEnum wantedResourceType, + ResourceIdentifier wantedResourceIdentifier) { + switch (wantedResourceType) { + case CircuitPack: + Optional circuitPackOptional = tryCastToParticularResource(CircuitPack.class, resource); + return circuitPackOptional.flatMap( + circuitPack -> Optional.ofNullable(circuitPack.getCircuitPackName())) + .map(circuitPackName -> circuitPackName.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case Connection: + Optional connectionOptional = tryCastToParticularResource(Connection.class, resource); + return connectionOptional.flatMap( + connection -> Optional.ofNullable(connection.getConnectionNumber())) + .map(connectionNumber -> connectionNumber.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case Degree: + Optional degreeOptional = tryCastToParticularResource(Degree.class, resource); + return degreeOptional.flatMap( + degree -> Optional.ofNullable(degree.getDegreeNumber())) + .flatMap(degreeInteger -> Optional.of(degreeInteger.toString())) + .map(degreeNumberAsString -> + degreeNumberAsString.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case Interface: + Optional interfaceOptional = tryCastToParticularResource(Interface.class, resource); + return interfaceOptional.flatMap( + interfaceResource -> Optional.ofNullable(interfaceResource.getInterfaceName())) + .map(interfaceName -> interfaceName.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case InternalLink: + Optional internalLinkOptional = tryCastToParticularResource(InternalLink.class, resource); + return internalLinkOptional.flatMap( + internalLink -> Optional.ofNullable(internalLink.getInternalLinkName())) + .map(internalLinkName -> internalLinkName.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case PhysicalLink: + Optional physicalLinkOptional = tryCastToParticularResource(PhysicalLink.class, resource); + return physicalLinkOptional.flatMap( + physicalLink -> Optional.ofNullable(physicalLink.getPhysicalLinkName())) + .map(physicalLinkName -> physicalLinkName.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case Service: + Optional serviceOptional = tryCastToParticularResource(Service.class, resource); + return serviceOptional.flatMap( + service -> Optional.ofNullable(service.getServiceName())) + .map(serviceName -> serviceName.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case Shelf: + Optional shelfOptional = tryCastToParticularResource(Shelf.class, resource); + return shelfOptional.flatMap( + shelf -> Optional.ofNullable(shelf.getShelfName())) + .map(shelfName -> shelfName.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case SharedRiskGroup: + Optional sharedRiskGroupOptional = tryCastToParticularResource(Srg.class, resource); + return sharedRiskGroupOptional.flatMap( + sharedRiskGroup -> Optional.ofNullable(sharedRiskGroup.getSrgNumber())) + .flatMap(sharedRiskGroupNumberInteger -> Optional.of(sharedRiskGroupNumberInteger.toString())) + .map(srgNumberAsString -> srgNumberAsString.equals(wantedResourceIdentifier.getResourceName())) + .orElse(false); + case Port: + Optional portContainerOptional = tryCastToParticularResource(Port.class, resource); + return portContainerOptional.flatMap( + portContainer -> Optional.ofNullable(portContainer.getPort())) + .map(port -> { + String portName = port.getPortName(); + String circuitPackName = port.getCircuitPackName(); + return portName != null + && circuitPackName != null + && portName.equals(wantedResourceIdentifier.getResourceName()) + && circuitPackName.equals(wantedResourceIdentifier.getCircuitPackName()); + }) + .orElse(false); + default: + LOG.warn("Unknown resource type {}", wantedResourceType); + return false; + } + } + + @SuppressWarnings("unchecked") + private static Optional tryCastToParticularResource(Class resourceClass, + Resource resource) { + if (resource == null) { + LOG.warn("Resource is null."); + } else if (! resourceClass.isInstance(resource)) { + LOG.warn("Resource implement different type than expected. Expected {}, actual {}.", + resourceClass.getSimpleName(), resource.getClass().getSimpleName()); + } else { + return Optional.of((T) resource); + } + return Optional.empty(); + } + +} diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/spanloss/OtsPmHolder.java b/olm/src/main/java/org/opendaylight/transportpce/olm/util/OtsPmHolder.java similarity index 96% rename from olm/src/main/java/org/opendaylight/transportpce/olm/spanloss/OtsPmHolder.java rename to olm/src/main/java/org/opendaylight/transportpce/olm/util/OtsPmHolder.java index 50f556023..9507ce5a0 100644 --- a/olm/src/main/java/org/opendaylight/transportpce/olm/spanloss/OtsPmHolder.java +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/util/OtsPmHolder.java @@ -5,7 +5,7 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.transportpce.olm.spanloss; +package org.opendaylight.transportpce.olm.util; /** * The Class OtsPmHolder. diff --git a/olm/src/main/java/org/opendaylight/transportpce/olm/util/RoadmLinks.java b/olm/src/main/java/org/opendaylight/transportpce/olm/util/RoadmLinks.java new file mode 100644 index 000000000..6c9de8b2e --- /dev/null +++ b/olm/src/main/java/org/opendaylight/transportpce/olm/util/RoadmLinks.java @@ -0,0 +1,98 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.olm.util; +/** + * The Class RoadmLinks. + */ +public class RoadmLinks { + + /** The src node id. */ + private String srcNodeId; + + /** The src tp id. */ + private String srcTpId; + + /** The dest node id. */ + private String destNodeId; + + /** The dest tpid. */ + private String destTpid; + + /** + * Gets the src node id. + * + * @return the src node id + */ + public String getSrcNodeId() { + return srcNodeId; + } + + /** + * Sets the src node id. + * + * @param srcNodeId the new src node id + */ + public void setSrcNodeId(String srcNodeId) { + this.srcNodeId = srcNodeId; + } + + /** + * Gets the src tp id. + * + * @return the src tp id + */ + public String getSrcTpId() { + return srcTpId; + } + + /** + * Sets the src tp id. + * + * @param srcTpId the new src tp id + */ + public void setSrcTpId(String srcTpId) { + this.srcTpId = srcTpId; + } + + /** + * Gets the dest node id. + * + * @return the dest node id + */ + public String getDestNodeId() { + return destNodeId; + } + + /** + * Sets the dest node id. + * + * @param destNodeId the new dest node id + */ + public void setDestNodeId(String destNodeId) { + this.destNodeId = destNodeId; + } + + /** + * Gets the dest tpid. + * + * @return the dest tpid + */ + public String getDestTpid() { + return destTpid; + } + + /** + * Sets the dest tpid. + * + * @param destTpid the new dest tpid + */ + public void setDestTpid(String destTpid) { + this.destTpid = destTpid; + } + +} diff --git a/olm/src/main/resources/org/opendaylight/blueprint/olm-blueprint.xml b/olm/src/main/resources/org/opendaylight/blueprint/olm-blueprint.xml index b8ed3369e..0babd70bb 100644 --- a/olm/src/main/resources/org/opendaylight/blueprint/olm-blueprint.xml +++ b/olm/src/main/resources/org/opendaylight/blueprint/olm-blueprint.xml @@ -8,22 +8,47 @@ terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html --> + xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" + odl:use-default-for-reference-types="true"> - + interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" + odl:type="default" /> - + interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry" /> + + + + + + + + + + + + + - + + + + + + + + + diff --git a/olm/src/test/java/org/opendaylight/transportpce/olm/OlmProviderTest.java b/olm/src/test/java/org/opendaylight/transportpce/olm/OlmProviderTest.java new file mode 100644 index 000000000..634f517c4 --- /dev/null +++ b/olm/src/test/java/org/opendaylight/transportpce/olm/OlmProviderTest.java @@ -0,0 +1,18 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.olm; + +import org.junit.Test; + +public class OlmProviderTest { + @Test + public void init() throws Exception { + //TODO implement test + } + +} diff --git a/renderer/pom.xml b/renderer/pom.xml index c86a9ee65..1fd381688 100644 --- a/renderer/pom.xml +++ b/renderer/pom.xml @@ -22,6 +22,25 @@ and is available at http://www.eclipse.org/legal/epl-v10.html 0.2.0-SNAPSHOT bundle + + + + org.opendaylight.controller + mdsal-artifacts + 1.7.3-SNAPSHOT + import + pom + + + org.opendaylight.netconf + netconf-artifacts + 1.4.3-SNAPSHOT + import + pom + + + + ${project.groupId} @@ -30,22 +49,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html ${project.groupId}.ordmodels - transportpce-ordmodels-common - ${project.version} - - - ${project.groupId}.ordmodels - transportpce-ordmodels-network - ${project.version} - - - ${project.groupId}.ordmodels - transportpce-ordmodels-service + transportpce-ordmodels-device ${project.version} - ${project.groupId}.ordmodels - transportpce-ordmodels-device + ${project.groupId} + transportpce-common ${project.version} @@ -71,4 +80,5 @@ and is available at http://www.eclipse.org/legal/epl-v10.html test + diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/ModelMappingUtils.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/ModelMappingUtils.java new file mode 100644 index 000000000..a9e89fd62 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/ModelMappingUtils.java @@ -0,0 +1,283 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.Future; + +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev161014.configuration.response.common.ConfigurationResponseCommon; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev161014.configuration.response.common.ConfigurationResponseCommonBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceDeleteInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.PathDescription; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.atoz.direction.AToZ; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ztoa.direction.ZToA; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.resource.resource.TerminationPoint; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteOutputBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestOutputBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.Nodes; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.NodesBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.NodesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathInputBuilder; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class ModelMappingUtils { + + private static final Logger LOG = LoggerFactory.getLogger(ModelMappingUtils.class); + private static final String TERMINATION_POINT = "TerminationPoint"; + + private ModelMappingUtils() { + } + + public static ServicePowerSetupInput createServicePowerSetupInput(List olmList, + ServiceImplementationRequestInput input) { + ServicePowerSetupInputBuilder olmSetupBldr = new ServicePowerSetupInputBuilder(); + olmSetupBldr.setNodes(olmList); + olmSetupBldr.setWaveNumber(input.getPathDescription().getAToZDirection().getAToZWavelengthNumber()); + return olmSetupBldr.build(); + } + + public static ServiceImplementationRequestOutput createServiceImplResponse(String responseCode, String message) { + ServiceImplementationRequestOutputBuilder outputBldr = new ServiceImplementationRequestOutputBuilder(); + outputBldr.setConfigurationResponseCommon(createCommonResponse(responseCode, message)); + return outputBldr.build(); + } + + public static ServiceDeleteOutput createServiceDeleteResponse(String responseCode, String message) { + ServiceDeleteOutputBuilder outputBldr = new ServiceDeleteOutputBuilder(); + outputBldr.setConfigurationResponseCommon(createCommonResponse(responseCode, message)); + return outputBldr.build(); + } + + public static ConfigurationResponseCommon createCommonResponse(String responseCode, String message) { + ConfigurationResponseCommonBuilder cmBldr = new ConfigurationResponseCommonBuilder(); + cmBldr.setResponseMessage(message); + cmBldr.setResponseCode(responseCode); + return cmBldr.build(); + } + + public static Future> + createRpcResponse(ServiceImplementationRequestOutput payload) { + return RpcResultBuilder.success(payload).buildFuture(); + } + + public static ServicePathInputData rendererCreateServiceInputAToZ(String serviceName, + PathDescription pathDescription) { + ServicePathInputBuilder servicePathInputBuilder = new ServicePathInputBuilder(); + servicePathInputBuilder.setServiceName(serviceName); + NodeLists nodeLists = getNodesListAToZ(pathDescription.getAToZDirection().getAToZ().iterator()); + servicePathInputBuilder.setServiceName(serviceName); + servicePathInputBuilder.setOperation(ServicePathInput.Operation.Create); + servicePathInputBuilder.setWaveNumber(new Long(pathDescription.getAToZDirection().getAToZWavelengthNumber())); + servicePathInputBuilder.setNodes(nodeLists.getList()); + return new ServicePathInputData(servicePathInputBuilder.build(), nodeLists); + } + + public static ServicePathInputData rendererCreateServiceInputZToA(String serviceName, + PathDescription pathDescription) { + ServicePathInputBuilder servicePathInputBuilder = new ServicePathInputBuilder(); + NodeLists nodeLists = getNodesListZtoA(pathDescription.getZToADirection().getZToA().iterator()); + servicePathInputBuilder.setOperation(ServicePathInput.Operation.Create); + servicePathInputBuilder.setServiceName(serviceName); + servicePathInputBuilder.setWaveNumber(new Long(pathDescription.getZToADirection().getZToAWavelengthNumber())); + servicePathInputBuilder.setNodes(nodeLists.getList()); + return new ServicePathInputData(servicePathInputBuilder.build(), nodeLists); + } + + public static ServicePathInput rendererDeleteServiceInput(String serviceName, + ServiceDeleteInput serviceDeleteInput) { + ServicePathInputBuilder servicePathInput = new ServicePathInputBuilder(); + servicePathInput.setServiceName(serviceName); + //TODO: finish model-model mapping + return servicePathInput.build(); + } + + public static NodeLists getNodesListZtoA(Iterator iterator) { + Map treeMap = new TreeMap<>(); + List olmList = new ArrayList<>(); + List list = new ArrayList<>(); + String resourceType; + TerminationPoint tp; + String tpID = ""; + String nodeID = ""; + String sortId = ""; + while (iterator.hasNext()) { + ZToA pathDesObj = iterator.next(); + resourceType = pathDesObj.getResource().getResource().getImplementedInterface().getSimpleName(); + LOG.info("Inside AtoZ {}", resourceType); + + try { + if (TERMINATION_POINT.equals(resourceType)) { + tp = (TerminationPoint) pathDesObj.getResource().getResource(); + LOG.info(" TP is {} {}", tp.getTerminationPointIdentifier().getTpId(), + tp.getTerminationPointIdentifier().getNodeId()); + tpID = tp.getTerminationPointIdentifier().getTpId(); + nodeID = tp.getTerminationPointIdentifier().getNodeId(); + sortId = pathDesObj.getId(); + + //TODO: do not rely on ID to be in certain format + if (tpID.contains("CTP") || tpID.contains("CP")) { + continue; + } + if (!tpID.contains("TTP") && !tpID.contains("PP") && !tpID.contains("NETWORK") + && !tpID.contains("CLIENT")) { + continue; + } + + int[] pos = findTheLongestSubstring(nodeID, tpID); + //TODO: do not rely on nodeId to be integer + int id = Integer.parseInt(sortId); + treeMap.put(id, new NodeIdPair(nodeID.substring(0, pos[0] - 1), tpID)); + } else if (resourceType.equals("Link")) { + LOG.info("The type is link"); + } else { + LOG.info("The type is not indentified: {}", resourceType); + } + } catch (IllegalArgumentException | SecurityException e) { + // TODO Auto-generated catch block + LOG.error("Dont find the getResource method", e); + } + } + + String desID = null; + String srcID = null; + for (NodeIdPair values : treeMap.values()) { + if (srcID == null) { + srcID = values.getTpID(); + } else if (desID == null) { + desID = values.getTpID(); + NodesBuilder nb = new NodesBuilder(); + nb.setKey(new NodesKey(values.getNodeID())); + nb.setDestTp(desID); + nb.setSrcTp(srcID); + list.add(nb.build()); + + NodesBuilder olmNb = new NodesBuilder(); + olmNb.setNodeId(values.getNodeID()); + olmNb.setDestTp(desID); + olmNb.setSrcTp(srcID); + olmList.add(olmNb.build()); + srcID = null; + desID = null; + } else { + LOG.warn("both, the source and destination id are null!"); + } + } + return new NodeLists(olmList, list); + } + + public static NodeLists getNodesListAToZ(Iterator iterator) { + Map treeMap = new TreeMap<>(); + List list = new ArrayList<>(); + List olmList = new ArrayList<>(); + String resourceType; + TerminationPoint tp; + String tpID = ""; + String nodeID = ""; + String sortId = ""; + + while (iterator.hasNext()) { + AToZ pathDesObj = iterator.next(); + resourceType = pathDesObj.getResource().getResource().getImplementedInterface().getSimpleName(); + LOG.info("Inside AtoZ {}", resourceType); + try { + if (TERMINATION_POINT.equals(resourceType)) { + tp = (TerminationPoint) pathDesObj.getResource().getResource(); + LOG.info(" TP is {} {}", tp.getTerminationPointIdentifier().getTpId(), + tp.getTerminationPointIdentifier().getNodeId()); + tpID = tp.getTerminationPointIdentifier().getTpId(); + nodeID = tp.getTerminationPointIdentifier().getNodeId(); + sortId = pathDesObj.getId(); + + //TODO: do not rely on ID to be in certain format + if (tpID.contains("CTP") || tpID.contains("CP")) { + continue; + } + if (!tpID.contains("TTP") && !tpID.contains("PP") && !tpID.contains("NETWORK") + && !tpID.contains("CLIENT")) { + continue; + } + + int[] pos = findTheLongestSubstring(nodeID, tpID); + //TODO: do not rely on nodeId to be integer + int id = Integer.parseInt(sortId); + treeMap.put(id, new NodeIdPair(nodeID.substring(0, pos[0] - 1), tpID)); + } else if (resourceType.equals("Link")) { + LOG.info("The type is link"); + } else { + LOG.info("The type is not indentified: {}", resourceType); + } + } catch (IllegalArgumentException | SecurityException e) { + //TODO: Auto-generated catch block + LOG.error("Dont find the getResource method", e); + } + } + + String desID = null; + String srcID = null; + for (NodeIdPair values : treeMap.values()) { + if (srcID == null) { + srcID = values.getTpID(); + } else if (desID == null) { + desID = values.getTpID(); + NodesBuilder nb = new NodesBuilder(); + nb.setKey(new NodesKey(values.getNodeID())); + nb.setDestTp(desID); + nb.setSrcTp(srcID); + list.add(nb.build()); + + NodesBuilder olmNb = new NodesBuilder(); + olmNb.setNodeId(values.getNodeID()); + olmNb.setDestTp(desID); + olmNb.setSrcTp(srcID); + olmList.add(olmNb.build()); + srcID = null; + desID = null; + } else { + LOG.warn("both, the source and destination id are null!"); + } + } + return new NodeLists(olmList, list); + } + + public static int[] findTheLongestSubstring(String s1, String s2) { + if (s1 == null || s2 == null) { + return null; + } + int[][] dp = new int[s1.length() + 1][s2.length() + 1]; + int maxLen = 0; + int endPos = 0; + for (int i = 1; i < dp.length; i++) { + for (int j = 1; j < dp[0].length; j++) { + char ch1 = s1.charAt(i - 1); + char ch2 = s2.charAt(j - 1); + if (ch1 == ch2) { + dp[i][j] = dp[i - 1][j - 1] + 1; + if (dp[i][j] >= maxLen) { + maxLen = dp[i][j]; + endPos = i; + } + } + } + } + return new int[] { endPos - maxLen, endPos }; + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/NetworkModelWavelengthService.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/NetworkModelWavelengthService.java new file mode 100644 index 000000000..cf9e27426 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/NetworkModelWavelengthService.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer; + +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.PathDescription; + +public interface NetworkModelWavelengthService { + + /** + * Remove wavelength from available and add it to used wavelength list. + * + * @param pathDescription + * path description containing a-to-z and z-to-a path + */ + void useWavelengths(PathDescription pathDescription); + + /** + * Remove wavelength from used and add it to available wavelength list. + * + * @param pathDescription + * path description containing a-to-z and z-to-a path + */ + void freeWavelengths(PathDescription pathDescription); + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/NetworkModelWavelengthServiceImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/NetworkModelWavelengthServiceImpl.java new file mode 100644 index 000000000..a354bdab6 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/NetworkModelWavelengthServiceImpl.java @@ -0,0 +1,578 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer; + +import com.google.common.base.Optional; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.Collectors; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.transportpce.common.NetworkUtils; +import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node.attributes.AvailableWavelengthsKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.used.wavelengths.UsedWavelengths; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.used.wavelengths.UsedWavelengthsBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.used.wavelengths.UsedWavelengthsKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.TerminationPoint1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.DegreeAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.DegreeAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.SrgAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.SrgAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.CpAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.CpAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.CtpAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.CtpAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.PpAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.PpAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.RxTtpAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.RxTtpAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.TxTtpAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.TxTtpAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrClientAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrClientAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrNetworkAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrNetworkAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrPortAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.XpdrPortAttributesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.pp.attributes.UsedWavelength; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.pp.attributes.UsedWavelengthBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node.termination.point.pp.attributes.UsedWavelengthKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev170929.OpenroadmTpType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes.AvailableWavelengthsBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev170929.xpdr.port.connection.attributes.Wavelength; +import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev170929.xpdr.port.connection.attributes.WavelengthBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.PathDescription; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.atoz.direction.AToZ; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.path.description.ztoa.direction.ZToA; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.resource.resource.TerminationPoint; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev170426.pce.resource.resource.resource.termination.point.TerminationPointIdentifier; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.Network; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NetworkKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.NodeId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.Node; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network.NodeKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.TpId; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.network.node.TerminationPointKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NetworkModelWavelengthServiceImpl implements NetworkModelWavelengthService { + + private static final Logger LOG = LoggerFactory.getLogger(NetworkModelWavelengthServiceImpl.class); + private final DataBroker dataBroker; + + public NetworkModelWavelengthServiceImpl(DataBroker dataBroker) { + this.dataBroker = dataBroker; + } + + @Override + public void useWavelengths(PathDescription pathDescription) { + + List atozTpIds = getAToZTpList(pathDescription); + List ztoaTpIds = getZToATpList(pathDescription); + + deleteAvailableWL(atozTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()), + pathDescription.getAToZDirection().getAToZWavelengthNumber()); + deleteAvailableWL(ztoaTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()), + pathDescription.getZToADirection().getZToAWavelengthNumber()); + + addUsedWL(pathDescription.getAToZDirection().getAToZWavelengthNumber(), atozTpIds); + addUsedWL(pathDescription.getZToADirection().getZToAWavelengthNumber(), ztoaTpIds); + } + + @Override + public void freeWavelengths(PathDescription pathDescription) { + List atozTpIds = getAToZTpList(pathDescription); + List ztoaTpIds = getZToATpList(pathDescription); + + deleteUsedWL(pathDescription.getAToZDirection().getAToZWavelengthNumber(), atozTpIds); + deleteUsedWL(pathDescription.getZToADirection().getZToAWavelengthNumber(), ztoaTpIds); + + addAvailableWL(atozTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()), + pathDescription.getAToZDirection().getAToZWavelengthNumber()); + addAvailableWL(ztoaTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()), + pathDescription.getZToADirection().getZToAWavelengthNumber()); + } + + private List getAToZTpList(PathDescription pathDescription) { + List atozList = pathDescription.getAToZDirection().getAToZ(); + return atozList.stream() + .filter(aToZ -> { + if ((aToZ.getResource() == null) || (aToZ.getResource().getResource() == null)) { + LOG.warn("Resource of AToZ node {} is null! Skipping this node!", aToZ.getId()); + return false; + } + return aToZ.getResource().getResource() instanceof TerminationPoint; + }).filter(aToZ -> { + TerminationPoint tp = (TerminationPoint) aToZ.getResource().getResource(); + if ((tp.getTerminationPointIdentifier() == null) + || (tp.getTerminationPointIdentifier().getNodeId() == null) + || (tp.getTerminationPointIdentifier().getTpId() == null)) { + LOG.warn("Termination point in AToZ node {} contains nulls! Skipping this node!", aToZ.getId()); + return false; + } + return true; + }).map(aToZ -> { + TerminationPointIdentifier tp = + ((TerminationPoint) aToZ.getResource().getResource()).getTerminationPointIdentifier(); + return new NodeIdPair(tp.getNodeId(), tp.getTpId()); + }).collect(Collectors.toList()); + } + + private List getZToATpList(PathDescription pathDescription) { + List ztoaList = pathDescription.getZToADirection().getZToA(); + return ztoaList.stream() + .filter(zToA -> { + if ((zToA.getResource() == null) || (zToA.getResource().getResource() == null)) { + LOG.warn("Resource of ZToA node {} is null! Skipping this node!", zToA.getId()); + return false; + } + return zToA.getResource().getResource() instanceof TerminationPoint; + }).filter(zToA -> { + TerminationPoint tp = (TerminationPoint) zToA.getResource().getResource(); + if ((tp.getTerminationPointIdentifier() == null) + || (tp.getTerminationPointIdentifier().getNodeId() == null) + || (tp.getTerminationPointIdentifier().getTpId() == null)) { + LOG.warn("Termination point in ZToA node {} contains nulls! Skipping this node!", zToA.getId()); + return false; + } + return true; + }) + .map(zToA -> { + TerminationPointIdentifier tp = + ((TerminationPoint) zToA.getResource().getResource()).getTerminationPointIdentifier(); + return new NodeIdPair(tp.getNodeId(), tp.getTpId()); + }).collect(Collectors.toList()); + } + + private InstanceIdentifier createNode1IID(String nodeId) { + return InstanceIdentifier + .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608 + .network.Node.class, new NodeKey(new NodeId(nodeId))) + .augmentation(org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929 + .Node1.class) + .build(); + } + + private Optional getNode1FromDatastore(String nodeId) { + InstanceIdentifier + nodeIID = createNode1IID(nodeId); + Optional nodeOpt; + try (ReadOnlyTransaction nodeReadTx = this.dataBroker.newReadOnlyTransaction()) { + nodeOpt = nodeReadTx.read(LogicalDatastoreType.CONFIGURATION, nodeIID) + .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("Exception while getting node from {} topology!", NetworkUtils.OVERLAY_NETWORK_ID, e); + nodeOpt = Optional.absent(); + } + return nodeOpt; + } + + private void addAvailableWL(List nodeIds, Long wavelengthNumber) { + WriteTransaction nodeWriteTx = this.dataBroker.newWriteOnlyTransaction(); + for (String nodeId : nodeIds) { + Optional nodeOpt = + getNode1FromDatastore(nodeId); + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1 node; + if (nodeOpt.isPresent()) { + node = nodeOpt.get(); + } else { + LOG.error("Unable to get node {} from topology {}! Skipping addition of available wavelength for this" + + "node.", nodeId, NetworkUtils.OVERLAY_NETWORK_ID); + continue; + } + + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1Builder + node1Builder = new org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929 + .Node1Builder(node); + + switch (node.getNodeType()) { + case DEGREE: + DegreeAttributes degreeAttributes = node.getDegreeAttributes(); + DegreeAttributesBuilder degreeAttributesBuilder; + if (degreeAttributes == null) { + degreeAttributesBuilder = new DegreeAttributesBuilder(); + } else { + degreeAttributesBuilder = new DegreeAttributesBuilder(degreeAttributes); + } + List availableDegreeWLs = + degreeAttributesBuilder.getAvailableWavelengths(); + if (availableDegreeWLs == null) { + availableDegreeWLs = new ArrayList<>(); + degreeAttributesBuilder.setAvailableWavelengths(availableDegreeWLs); + } + availableDegreeWLs.add(new org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree + .node.attributes.AvailableWavelengthsBuilder().setIndex(wavelengthNumber).build()); + node1Builder.setDegreeAttributes(degreeAttributesBuilder.build()); + break; + case SRG: + SrgAttributes srgAttributes = node.getSrgAttributes(); + SrgAttributesBuilder srgAttributesBuilder; + if (srgAttributes == null) { + srgAttributesBuilder = new SrgAttributesBuilder(); + } else { + srgAttributesBuilder = new SrgAttributesBuilder(srgAttributes); + } + List availableSrgWLs = srgAttributesBuilder.getAvailableWavelengths(); + if (availableSrgWLs == null) { + availableSrgWLs = new ArrayList<>(); + srgAttributesBuilder.setAvailableWavelengths(availableSrgWLs); + } + availableSrgWLs.add(new AvailableWavelengthsBuilder().setIndex(wavelengthNumber).build()); + node1Builder.setSrgAttributes(srgAttributesBuilder.build()); + break; + + default: + // TODO skip for now + continue; + } + nodeWriteTx.put(LogicalDatastoreType.CONFIGURATION, createNode1IID(nodeId), node1Builder.build(), true); + } + try { + nodeWriteTx.submit().get(Timeouts.DATASTORE_DELETE, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.error("Unable to add available WL {} for nodes {}!", wavelengthNumber, String.join(", ", nodeIds), e); + } + } + + private void deleteAvailableWL(List nodeIds, Long wavelengthNumber) { + WriteTransaction nodeWriteTx = this.dataBroker.newWriteOnlyTransaction(); + for (String nodeId : nodeIds) { + Optional nodeOpt = + getNode1FromDatastore(nodeId); + org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1 node; + if (nodeOpt.isPresent()) { + node = nodeOpt.get(); + } else { + LOG.error("Unable to get node {} from topology {}! Skipping addition of available wavelength for this" + + "node.", nodeId, NetworkUtils.OVERLAY_NETWORK_ID); + continue; + } + + InstanceIdentifierBuilder nodeIIDBuilder = InstanceIdentifier + .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .child(Node.class, new NodeKey(new NodeId(nodeId))).augmentation(Node1.class); + InstanceIdentifier availableWlIID; + + switch (node.getNodeType()) { + case DEGREE: + availableWlIID = nodeIIDBuilder.child(DegreeAttributes.class) + .child(org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node + .attributes.AvailableWavelengths.class, + new AvailableWavelengthsKey(wavelengthNumber)) + .build(); + break; + case SRG: + availableWlIID = nodeIIDBuilder.child(SrgAttributes.class) + .child(org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes + .AvailableWavelengths.class, + new org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node + .attributes.AvailableWavelengthsKey(wavelengthNumber)) + .build(); + break; + + default: + // TODO skip for now + continue; + } + nodeWriteTx.delete(LogicalDatastoreType.CONFIGURATION, availableWlIID); + } + try { + nodeWriteTx.submit().get(Timeouts.DATASTORE_DELETE, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.error("Unable to delete available WL {} for nodes {}!", wavelengthNumber, String.join(", ", nodeIds), + e); + } + } + + private InstanceIdentifierBuilder createTerminationPoint1IIDBuilder(String nodeId, String tpId) { + return InstanceIdentifier + .builder(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev150608.network + .Node.class, new NodeKey(new NodeId(nodeId))).augmentation( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608.Node1.class) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev150608 + .network.node.TerminationPoint.class, + new TerminationPointKey(new TpId(tpId))).augmentation(TerminationPoint1.class); + } + + private Optional getTerminationPoint1FromDatastore(String nodeId, String tpId) { + InstanceIdentifier tpIID = createTerminationPoint1IIDBuilder(nodeId, tpId).build(); + Optional tpOpt; + try (ReadOnlyTransaction readTx = this.dataBroker.newReadOnlyTransaction()) { + tpOpt = readTx.read(LogicalDatastoreType.CONFIGURATION, tpIID) + .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("Exception while getting termination point from {} topology!", NetworkUtils.OVERLAY_NETWORK_ID, + e); + tpOpt = Optional.absent(); + } + return tpOpt; + } + + private void deleteUsedWL(long wavelengthIndex, List tpIds) { + WriteTransaction deleteUsedWlTx = this.dataBroker.newWriteOnlyTransaction(); + for (NodeIdPair idPair : tpIds) { + Optional tpOpt = getTerminationPoint1FromDatastore(idPair.getNodeID(), idPair.getTpID()); + + OpenroadmTpType tpType; + if (tpOpt.isPresent()) { + tpType = tpOpt.get().getTpType(); + } else { + LOG.error("Unable to get termination point {} from topology {}! Skipping removal of used wavelength" + + " for this node.", idPair.getTpID(), NetworkUtils.OVERLAY_NETWORK_ID); + continue; + } + InstanceIdentifier.InstanceIdentifierBuilder usedWlIIDBuilder = + createTerminationPoint1IIDBuilder(idPair.getNodeID(), idPair.getTpID()); + InstanceIdentifier usedWlIID; + switch (tpType) { + case DEGREETXTTP: + case DEGREETXRXTTP: + usedWlIID = usedWlIIDBuilder.child(TxTtpAttributes.class).child(UsedWavelengths.class, + new UsedWavelengthsKey(wavelengthIndex)).build(); + break; + + case DEGREERXTTP: + usedWlIID = usedWlIIDBuilder.child(RxTtpAttributes.class).child(UsedWavelengths.class, + new UsedWavelengthsKey(wavelengthIndex)).build(); + break; + + case DEGREETXCTP: + case DEGREERXCTP: + case DEGREETXRXCTP: + usedWlIID = usedWlIIDBuilder.child(CtpAttributes.class).child(UsedWavelengths.class, + new UsedWavelengthsKey(wavelengthIndex)).build(); + break; + + case SRGTXCP: + case SRGRXCP: + case SRGTXRXCP: + usedWlIID = usedWlIIDBuilder.child(CpAttributes.class).child(org.opendaylight.yang.gen.v1.http.org + .openroadm.network.topology.rev170929.network.node.termination.point.cp.attributes + .UsedWavelengths.class, + new org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node + .termination.point.cp.attributes.UsedWavelengthsKey( + wavelengthIndex)).build(); + break; + + case SRGTXRXPP: + case SRGRXPP: + case SRGTXPP: + usedWlIID = usedWlIIDBuilder.child(PpAttributes.class).child(UsedWavelength.class, + new UsedWavelengthKey(wavelengthIndex)).build(); + break; + + case XPONDERNETWORK: + usedWlIID = usedWlIIDBuilder.child(XpdrNetworkAttributes.class).child(Wavelength.class).build(); + break; + case XPONDERCLIENT: + usedWlIID = usedWlIIDBuilder.child(XpdrClientAttributes.class).child(Wavelength.class).build(); + break; + case XPONDERPORT: + usedWlIID = usedWlIIDBuilder.child(XpdrPortAttributes.class).child(Wavelength.class).build(); + break; + + default: + // TODO skip for now + continue; + } + deleteUsedWlTx.delete(LogicalDatastoreType.CONFIGURATION, usedWlIID); + } + try { + deleteUsedWlTx.submit().get(Timeouts.DATASTORE_DELETE, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + List tpIdsString = tpIds.stream().map(NodeIdPair::toString).collect(Collectors.toList()); + LOG.error("Unable to delete used WL {} from TPs {}!", wavelengthIndex, String.join(", ", tpIdsString), e); + } + } + + private void addUsedWL(long wavelengthIndex, List tpIds) { + WriteTransaction addUsedWlTx = this.dataBroker.newWriteOnlyTransaction(); + for (NodeIdPair idPair : tpIds) { + Optional tpOpt = getTerminationPoint1FromDatastore(idPair.getNodeID(), idPair.getTpID()); + + TerminationPoint1 tp; + if (tpOpt.isPresent()) { + tp = tpOpt.get(); + } else { + LOG.error("Unable to get termination point {} from topology {}! Skipping removal of used wavelength" + + " for this node.", idPair.getTpID(), NetworkUtils.OVERLAY_NETWORK_ID); + continue; + } + + TerminationPoint1Builder tp1Builder = new TerminationPoint1Builder(tp); + + switch (tp.getTpType()) { + case DEGREETXTTP: + case DEGREETXRXTTP: + TxTtpAttributes txTtpAttributes = tp.getTxTtpAttributes(); + TxTtpAttributesBuilder txTtpAttributesBuilder; + if (txTtpAttributes == null) { + txTtpAttributesBuilder = new TxTtpAttributesBuilder(); + } else { + txTtpAttributesBuilder = new TxTtpAttributesBuilder(txTtpAttributes); + } + List usedDegreeTxTtpWls = txTtpAttributesBuilder.getUsedWavelengths(); + if (usedDegreeTxTtpWls == null) { + usedDegreeTxTtpWls = new ArrayList<>(); + txTtpAttributesBuilder.setUsedWavelengths(usedDegreeTxTtpWls); + } + usedDegreeTxTtpWls.add(new UsedWavelengthsBuilder().setIndex(wavelengthIndex).build()); + tp1Builder.setTxTtpAttributes(txTtpAttributesBuilder.build()); + break; + + case DEGREERXTTP: + RxTtpAttributes rxTtpAttributes = tp.getRxTtpAttributes(); + RxTtpAttributesBuilder rxTtpAttributesBuilder; + if (rxTtpAttributes == null) { + rxTtpAttributesBuilder = new RxTtpAttributesBuilder(); + } else { + rxTtpAttributesBuilder = new RxTtpAttributesBuilder(rxTtpAttributes); + } + List usedDegreeRxTtpWls = rxTtpAttributesBuilder.getUsedWavelengths(); + if (usedDegreeRxTtpWls == null) { + usedDegreeRxTtpWls = new ArrayList<>(); + rxTtpAttributesBuilder.setUsedWavelengths(usedDegreeRxTtpWls); + } + usedDegreeRxTtpWls.add(new UsedWavelengthsBuilder().setIndex(wavelengthIndex).build()); + tp1Builder.setRxTtpAttributes(rxTtpAttributesBuilder.build()); + break; + + case DEGREETXCTP: + case DEGREERXCTP: + case DEGREETXRXCTP: + CtpAttributes ctpAttributes = tp.getCtpAttributes(); + CtpAttributesBuilder ctpAttributesBuilder; + if (ctpAttributes == null) { + ctpAttributesBuilder = new CtpAttributesBuilder(); + } else { + ctpAttributesBuilder = new CtpAttributesBuilder(ctpAttributes); + } + List usedDegreeCtpWls = ctpAttributesBuilder.getUsedWavelengths(); + if (usedDegreeCtpWls == null) { + usedDegreeCtpWls = new ArrayList<>(); + ctpAttributesBuilder.setUsedWavelengths(usedDegreeCtpWls); + } + usedDegreeCtpWls.add(new UsedWavelengthsBuilder().setIndex(wavelengthIndex).build()); + tp1Builder.setCtpAttributes(ctpAttributesBuilder.build()); + break; + + case SRGTXCP: + case SRGRXCP: + case SRGTXRXCP: + CpAttributes cpAttributes = tp.getCpAttributes(); + CpAttributesBuilder cpAttributesBuilder; + if (cpAttributes == null) { + cpAttributesBuilder = new CpAttributesBuilder(); + } else { + cpAttributesBuilder = new CpAttributesBuilder(cpAttributes); + } + List usedDegreeCpWls = + cpAttributesBuilder.getUsedWavelengths(); + if (usedDegreeCpWls == null) { + usedDegreeCpWls = new ArrayList<>(); + cpAttributesBuilder.setUsedWavelengths(usedDegreeCpWls); + } + usedDegreeCpWls.add(new org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929 + .network.node.termination.point.cp.attributes.UsedWavelengthsBuilder() + .setIndex(wavelengthIndex).build()); + tp1Builder.setCpAttributes(cpAttributesBuilder.build()); + break; + + case SRGTXRXPP: + case SRGRXPP: + case SRGTXPP: + PpAttributes ppAttributes = tp.getPpAttributes(); + PpAttributesBuilder ppAttributesBuilder; + if (ppAttributes == null) { + ppAttributesBuilder = new PpAttributesBuilder(); + } else { + ppAttributesBuilder = new PpAttributesBuilder(ppAttributes); + } + List usedDegreePpWls = ppAttributesBuilder.getUsedWavelength(); + if (usedDegreePpWls == null) { + usedDegreePpWls = new ArrayList<>(); + ppAttributesBuilder.setUsedWavelength(usedDegreePpWls); + } + usedDegreePpWls.add(new UsedWavelengthBuilder().setIndex(wavelengthIndex).build()); + tp1Builder.setPpAttributes(ppAttributesBuilder.build()); + break; + + case XPONDERNETWORK: + XpdrNetworkAttributes xpdrNetworkAttributes = tp.getXpdrNetworkAttributes(); + XpdrNetworkAttributesBuilder xpdrNetworkAttributesBuilder; + if (xpdrNetworkAttributes == null) { + xpdrNetworkAttributesBuilder = new XpdrNetworkAttributesBuilder(); + } else { + xpdrNetworkAttributesBuilder = new XpdrNetworkAttributesBuilder(xpdrNetworkAttributes); + } + Wavelength usedXpdrNetworkWl = new WavelengthBuilder().setIndex(wavelengthIndex).build(); + tp1Builder.setXpdrNetworkAttributes(xpdrNetworkAttributesBuilder + .setWavelength(usedXpdrNetworkWl) + .build()); + break; + case XPONDERCLIENT: + XpdrClientAttributes xpdrClientAttributes = tp.getXpdrClientAttributes(); + XpdrClientAttributesBuilder xpdrClientAttributesBuilder; + if (xpdrClientAttributes == null) { + xpdrClientAttributesBuilder = new XpdrClientAttributesBuilder(); + } else { + xpdrClientAttributesBuilder = new XpdrClientAttributesBuilder(xpdrClientAttributes); + } + Wavelength usedXpdrClientWl = new WavelengthBuilder().setIndex(wavelengthIndex).build(); + tp1Builder.setXpdrClientAttributes(xpdrClientAttributesBuilder + .setWavelength(usedXpdrClientWl) + .build()); + break; + case XPONDERPORT: + XpdrPortAttributes xpdrPortAttributes = tp.getXpdrPortAttributes(); + XpdrPortAttributesBuilder xpdrPortAttributesBuilder; + if (xpdrPortAttributes == null) { + xpdrPortAttributesBuilder = new XpdrPortAttributesBuilder(); + } else { + xpdrPortAttributesBuilder = new XpdrPortAttributesBuilder(xpdrPortAttributes); + } + Wavelength usedXpdrPortWl = new WavelengthBuilder().setIndex(wavelengthIndex).build(); + tp1Builder.setXpdrPortAttributes(xpdrPortAttributesBuilder + .setWavelength(usedXpdrPortWl) + .build()); + break; + + default: + // TODO skip for now + continue; + } + addUsedWlTx.put(LogicalDatastoreType.CONFIGURATION, createTerminationPoint1IIDBuilder(idPair.getNodeID(), + idPair.getTpID()).build(), tp1Builder.build(), true); + } + try { + addUsedWlTx.submit().get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + List tpIdsString = tpIds.stream().map(NodeIdPair::toString).collect(Collectors.toList()); + LOG.error("Unable to add used WL {} for TPs {}!", wavelengthIndex, String.join(", ", tpIdsString), e); + } + } +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/NodeIdPair.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/NodeIdPair.java new file mode 100644 index 000000000..0fb9f44a2 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/NodeIdPair.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer; + +public class NodeIdPair { + + private String nodeID; + private String tpID; + + public NodeIdPair(String nodeID, String tpID) { + this.nodeID = nodeID; + this.tpID = tpID; + } + + public String getNodeID() { + return this.nodeID; + } + + public String getTpID() { + return this.tpID; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if ((object == null) || (getClass() != object.getClass())) { + return false; + } + + NodeIdPair that = (NodeIdPair) object; + + if (this.nodeID != null ? !this.nodeID.equals(that.nodeID) : that.nodeID != null) { + return false; + } + return this.tpID != null ? this.tpID.equals(that.tpID) : that.tpID == null; + } + + @Override + public int hashCode() { + int result = this.nodeID != null ? this.nodeID.hashCode() : 0; + result = (31 * result) + (this.tpID != null ? this.tpID.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "NodeIdPair{" + "nodeID='" + this.nodeID + '\'' + ", tpID='" + this.tpID + '\'' + '}'; + } +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/NodeLists.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/NodeLists.java new file mode 100644 index 000000000..38ff5e8af --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/NodeLists.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer; + +import java.util.List; + +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.Nodes; + +public class NodeLists { + + private List olmList; + private List list; + + public NodeLists(List olmList, List list) { + this.olmList = olmList; + this.list = list; + } + + public List getOlmList() { + return olmList; + } + + public List getList() { + return list; + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererNotificationsImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererNotificationsImpl.java index 6231c8873..49778f900 100644 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererNotificationsImpl.java +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererNotificationsImpl.java @@ -7,15 +7,17 @@ */ package org.opendaylight.transportpce.renderer; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; + import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; import org.opendaylight.controller.md.sal.binding.api.DataObjectModification.ModificationType; @@ -27,12 +29,13 @@ import org.opendaylight.controller.md.sal.binding.api.MountPointService; import org.opendaylight.controller.md.sal.binding.api.NotificationService; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry; +import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.transportpce.common.mapping.PortMapping; import org.opendaylight.transportpce.renderer.listeners.AlarmNotificationListener; import org.opendaylight.transportpce.renderer.listeners.DeOperationsListener; import org.opendaylight.transportpce.renderer.listeners.DeviceListener; import org.opendaylight.transportpce.renderer.listeners.LldpListener; import org.opendaylight.transportpce.renderer.listeners.TcaListener; -import org.opendaylight.transportpce.renderer.mapping.PortMapping; import org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev161014.AlarmNotification; import org.opendaylight.yang.gen.v1.http.org.openroadm.alarm.rev161014.OrgOpenroadmAlarmListener; import org.opendaylight.yang.gen.v1.http.org.openroadm.de.operations.rev161014.OrgOpenroadmDeOperationsListener; @@ -59,12 +62,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RendererNotificationsImpl implements DataTreeChangeListener { - private final DataBroker dataBroker; private final MountPointService mountService; private static final Logger LOG = LoggerFactory.getLogger(RendererNotificationsImpl.class); private ListenerRegistration dataTreeChangeListenerRegistration; - + private final PortMapping portMapping; + private final DeviceTransactionManager deviceTransactionManager; private final Set currentMountedDevice; public static final InstanceIdentifier NETCONF_TOPO_IID = InstanceIdentifier.create(NetworkTopology.class) .child(Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))); @@ -78,13 +81,20 @@ public class RendererNotificationsImpl implements DataTreeChangeListener { }); public RendererNotificationsImpl(final DataBroker dataBroker, final MountPointService mountService, - Set currentMountedDevice) { + Set currentMountedDevice, PortMapping portMapping,DeviceTransactionManager deviceTransactionManager) { this.dataBroker = dataBroker; this.mountService = mountService; this.currentMountedDevice = currentMountedDevice; + this.portMapping = portMapping; + this.deviceTransactionManager = deviceTransactionManager; + if (portMapping == null) { + LOG.error("Portmapping is null !"); + } + if (deviceTransactionManager == null) { + LOG.error("deviceTransactionManager is null"); + } if (mountService == null) { LOG.error("Mount service is null"); - } if (dataBroker != null) { this.dataTreeChangeListenerRegistration = dataBroker.registerDataTreeChangeListener( @@ -92,15 +102,23 @@ public class RendererNotificationsImpl implements DataTreeChangeListener { } } - private void registerNotificationListener(final NodeId nodeId) { + private void registerNotificationListener(final String nodeId) { - MountPoint mountPoint = PortMapping.getDeviceMountPoint(nodeId.getValue(), this.mountService); + LOG.info("onDeviceConnected: {}", nodeId); + Optional mountPointOpt = this.deviceTransactionManager.getDeviceMountPoint(nodeId); + MountPoint mountPoint; + if (mountPointOpt.isPresent()) { + mountPoint = mountPointOpt.get(); + } else { + LOG.error("Failed to get mount point for node {}", nodeId); + return; + } - // Register notification service - final Optional notificationService = mountPoint.getService( - NotificationService.class); + final Optional notificationService = + mountPoint.getService(NotificationService.class).toJavaUtil(); if (!notificationService.isPresent()) { - LOG.error("Failed to get RpcService for node {}", nodeId.getValue()); + LOG.error("Failed to get RpcService for node {}", nodeId); + return; } final OrgOpenroadmAlarmListener alarmListener; @@ -130,9 +148,9 @@ public class RendererNotificationsImpl implements DataTreeChangeListener { // Listening to NETCONF datastream final String streamName = "NETCONF"; - final Optional service = mountPoint.getService(RpcConsumerRegistry.class); + final Optional service = mountPoint.getService(RpcConsumerRegistry.class).toJavaUtil(); if (!service.isPresent()) { - LOG.error("Failed to get RpcService for node {}", nodeId.getValue()); + LOG.error("Failed to get RpcService for node {}", nodeId); } final NotificationsService rpcService = service.get().getRpcService(NotificationsService.class); @@ -168,7 +186,6 @@ public class RendererNotificationsImpl implements DataTreeChangeListener { String nodeid = rootNode.getDataBefore().getKey().getNodeId().getValue(); LOG.info("Node {} removed...", nodeid); this.currentMountedDevice.remove(nodeid); - new PortMapping(this.dataBroker, this.mountService, nodeid).deleteMappingData(); } if (nnode != null) { @@ -192,9 +209,9 @@ public class RendererNotificationsImpl implements DataTreeChangeListener { * TODO: check for required capabilities to listen * for notifications */ - registerNotificationListener(rootNode.getDataAfter().getNodeId()); + registerNotificationListener(nodeId); this.currentMountedDevice.add(nodeId); - new PortMapping(this.dataBroker, this.mountService, nodeId).createMappingData(); + this.portMapping.createMappingData(nodeId); break; } case Connecting: { diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererProvider.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererProvider.java index 2f6ede412..472951453 100644 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererProvider.java +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererProvider.java @@ -5,7 +5,6 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ - package org.opendaylight.transportpce.renderer; import java.util.HashSet; @@ -15,7 +14,12 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.MountPointService; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; -import org.opendaylight.transportpce.renderer.provisiondevice.DeviceRenderer; +import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.transportpce.common.mapping.PortMapping; +import org.opendaylight.transportpce.renderer.provisiondevice.RendererServiceOperations; +import org.opendaylight.transportpce.renderer.rpcs.DeviceRendererRPCImpl; +import org.opendaylight.transportpce.renderer.rpcs.TransportPCEServicePathRPCImpl; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.TransportpceServicepathService; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,19 +30,27 @@ public class RendererProvider { private final DataBroker dataBroker; private final MountPointService mountPointService; private final RpcProviderRegistry rpcProviderRegistry; - private RendererNotificationsImpl rendererNotificationImpl; + private final PortMapping portMapping; + private final DeviceTransactionManager deviceTransactionManager; private RpcRegistration deviceRendererRegistration; + private DeviceRendererRPCImpl deviceRendererRPCImpl; + private RpcRegistration tpceServiceRegistry; + private RendererServiceOperations rendererServiceOperations; + private RendererNotificationsImpl rendererNotificationsImpl; private final Set currentMountedDevice; - public RendererProvider(final DataBroker dataBroker, final MountPointService mountPointService, - final RpcProviderRegistry rpcProviderRegistry) { + public RendererProvider(RpcProviderRegistry rpcProviderRegistry, DeviceRendererRPCImpl deviceRendererRPCImpl, + RendererServiceOperations rendererServiceOperations,DataBroker dataBroker, + MountPointService mountPointService, PortMapping portMapping, + DeviceTransactionManager deviceTransactionManager) { + this.rpcProviderRegistry = rpcProviderRegistry; + this.deviceRendererRPCImpl = deviceRendererRPCImpl; + this.rendererServiceOperations = rendererServiceOperations; this.dataBroker = dataBroker; this.mountPointService = mountPointService; - this.rpcProviderRegistry = rpcProviderRegistry; this.currentMountedDevice = new HashSet<>(); - if (mountPointService == null) { - LOG.error("Mount service is null"); - } + this.portMapping = portMapping; + this.deviceTransactionManager = deviceTransactionManager; } /** @@ -46,12 +58,14 @@ public class RendererProvider { */ public void init() { LOG.info("RendererProvider Session Initiated"); - // Initializing Notification module - rendererNotificationImpl = new RendererNotificationsImpl(dataBroker, mountPointService, - currentMountedDevice); - //Register REST API RPC implementation for Renderer Service - deviceRendererRegistration = rpcProviderRegistry.addRpcImplementation(RendererService.class, new DeviceRenderer( - dataBroker, mountPointService, currentMountedDevice)); + TransportPCEServicePathRPCImpl transportPCEServicePathRPCImpl = + new TransportPCEServicePathRPCImpl(this.rendererServiceOperations); + this.deviceRendererRegistration = this.rpcProviderRegistry + .addRpcImplementation(RendererService.class, this.deviceRendererRPCImpl); + this.tpceServiceRegistry = this.rpcProviderRegistry + .addRpcImplementation(TransportpceServicepathService.class, transportPCEServicePathRPCImpl); + this.rendererNotificationsImpl = new RendererNotificationsImpl(this.dataBroker, this.mountPointService, + this.currentMountedDevice,this.portMapping,this.deviceTransactionManager); } /** @@ -59,13 +73,16 @@ public class RendererProvider { */ public void close() { LOG.info("RendererProvider Closed"); - // Clean up the RPC service registration - if (deviceRendererRegistration != null) { - deviceRendererRegistration.close(); + if (this.deviceRendererRegistration != null) { + this.deviceRendererRegistration.close(); + } + if (this.tpceServiceRegistry != null) { + this.tpceServiceRegistry.close(); } // Clean up the RendererNotificationsImpl - if (rendererNotificationImpl != null) { - rendererNotificationImpl.close(); + if (this.rendererNotificationsImpl != null) { + this.rendererNotificationsImpl.close(); } } -} \ No newline at end of file + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/ServicePathInputData.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/ServicePathInputData.java new file mode 100644 index 000000000..7869a9b7b --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/ServicePathInputData.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathInput; + +public class ServicePathInputData { + + private ServicePathInput servicePathInput; + private NodeLists nodeLists; + + public ServicePathInputData(ServicePathInput servicePathInput, NodeLists nodeLists) { + this.servicePathInput = servicePathInput; + this.nodeLists = nodeLists; + } + + public ServicePathInput getServicePathInput() { + return servicePathInput; + } + + public NodeLists getNodeLists() { + return nodeLists; + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/mapping/PortMapping.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/mapping/PortMapping.java deleted file mode 100644 index bfdea816d..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/mapping/PortMapping.java +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.mapping; - -import com.google.common.base.Optional; -import com.google.common.util.concurrent.CheckedFuture; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPoint; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaces; -import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.NodeTypes; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.Ports; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.pack.PortsKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacksKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.degree.ConnectionPorts; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Degree; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.DegreeKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.Info; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.SharedRiskGroup; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.SharedRiskGroupKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.port.Interfaces; -import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.InterfaceType; -import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OpenROADMOpticalMultiplex; -import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OpticalTransport; -import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.network.topology.topology.topology.types.TopologyNetconf; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.Network; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.NetworkBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.Nodes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.NodesBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.NodesKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.Mapping; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.MappingBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.MappingKey; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node; -import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PortMapping { - - private static final Logger LOG = LoggerFactory.getLogger(PortMapping.class); - private final DataBroker db; - private final MountPointService mps; - private final String nodeId; - - public PortMapping(DataBroker db, MountPointService mps, String nodeId) { - this.db = db; - this.mps = mps; - this.nodeId = nodeId; - - } - - /** - * This method creates logical to physical port mapping for a given device. - * Instead of parsing all the circuit packs/ports in the device this methods - * does a selective read operation on degree/srg subtree to get circuit - * packs/ports that map to : - * - *

- * 1. DEGn-TTP-TX, DEGn-TTP-RX, DEGn-TTP-TXRX - * - *

- * 2. SRGn-PPp-TX, SRGn-PPp-RX, SRGn-PPp-TXRX - * - *

- * 3. LINEn - * - *

- * 4. CLNTn. - * - *

- * If the port is Mw it also store the OMS, OTS interface provisioned on the - * port. It skips the logical ports that are internal. If operation is - * successful the mapping gets stored in datastore corresponding to - * portmapping.yang data model. - * - * @return true/false based on status of operation - */ - public boolean createMappingData() { - - LOG.info("Create Mapping Data for node " + nodeId); - DataBroker deviceDb = getDeviceDataBroker(nodeId, mps); - List portMapList = new ArrayList<>(); - Info deviceInfo; - Integer nodeType = 1; - if (deviceDb != null) { - deviceInfo = getDeviceInfo(deviceDb); - if (deviceInfo != null) { - if (deviceInfo.getNodeType() == null) { - LOG.info("Node type mandatory field is missing"); - return false; - } - nodeType = deviceInfo.getNodeType().getIntValue(); - // Create Mapping for Roadm Node - if (nodeType == 1) { - // Get TTP port mapping - if (!createTtpPortMapping(deviceDb, deviceInfo, portMapList)) { - // return false if mapping creation for TTP's failed - LOG.info("Unable to create mapping for TTP's"); - return false; - } - - // Get PP port mapping - if (!createPpPortMapping(deviceDb, deviceInfo, portMapList)) { - // return false if mapping creation for PP's failed - LOG.info("Unable tp create mapping for PP's"); - return false; - } - } - // Create Mapping for Xponder Node - if (nodeType == 2) { - if (!createXpdrPortMapping(deviceDb, deviceInfo, portMapList)) { - LOG.info("Unable to create mapping for Xponder"); - return false; - } - } - } else { - LOG.info("Device info subtree is absent for " + nodeId); - return false; - } - - } else { - LOG.info("Unable to get Data broker for node " + nodeId); - return false; - } - return postPortMapping(deviceInfo, portMapList, nodeType); - } - - /** - * This method removes mapping data from the datastore after disconnecting - * ODL from a Netconf device. - */ - public void deleteMappingData() { - LOG.info("Deleting Mapping Data corresponding at node " + nodeId); - WriteTransaction rw = db.newWriteOnlyTransaction(); - InstanceIdentifier nodesIID = InstanceIdentifier.create(Network.class) - .child(Nodes.class, new NodesKey(nodeId)); - rw.delete(LogicalDatastoreType.CONFIGURATION, nodesIID); - try { - rw.submit().get(1, TimeUnit.SECONDS); - LOG.info("Port mapping removal for node " + nodeId); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - LOG.error("Error for removing port mapping infos for node " + nodeId); - } - } - - /** - * This private method gets the list of external ports on a degree. For each - * port in the degree, it does a get on port subtree with - * circuit-pack-name/port-name as key in order to get the logical connection - * point name corresponding to it. - * - * @param deviceDb - * Reference to device's databroker - * @param deviceInfo - * Info subtree read from the device - * @param portMapList - * Reference to the list containing the mapping to be pushed to - * MD-SAL - * - * @return true/false based on status of operation - */ - private boolean createTtpPortMapping(DataBroker deviceDb, Info deviceInfo, List portMapList) { - // Creating mapping data for degree TTP's - List degreeConPorts = getDegreePorts(deviceDb, deviceInfo); - - // Getting circuit-pack-name/port-name corresponding to TTP's - for (ConnectionPorts cp : degreeConPorts) { - String circuitPackName = cp.getCircuitPackName(); - String portName = cp.getPortName().toString(); - InstanceIdentifier portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child( - CircuitPacks.class, new CircuitPacksKey(circuitPackName)).child(Ports.class, new PortsKey(portName)); - try { - LOG.info("Fetching logical Connection Point value for port {} at circuit pack {}", portName, - circuitPackName); - ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction(); - Optional portObject = rtx.read(LogicalDatastoreType.OPERATIONAL, portIID).get(); - if (portObject.isPresent()) { - Ports port = portObject.get(); - if (port.getLogicalConnectionPoint() != null) { - LOG.info("Logical Connection Point for {} {} is {}", circuitPackName, portName, port - .getLogicalConnectionPoint()); - portMapList.add(createMappingObject(port, circuitPackName, port.getLogicalConnectionPoint(), - deviceDb)); - } else { - - LOG.warn("Logical Connection Point value missing for {} {}", circuitPackName, port - .getPortName()); - } - } - } catch (InterruptedException | ExecutionException ex) { - LOG.warn("Read failed for Logical Connection Point value missing for " + circuitPackName + " " - + portName, ex); - return false; - } - } - return true; - } - - /** - * This private method gets the list of circuit packs on an Srg. For each - * circuit pack on an Srg, it does a get on circuit-pack subtree with - * circuit-pack-name as key in order to get the list of ports. It then - * iterates over the list of ports to get ports with port-qual as - * roadm-external. It appends a TX,RX,TXRX to the logical connection point - * name based on the direction of the port. - * - * @param deviceDb - * Reference to device's databroker - * @param deviceInfo - * Info subtree read from the device - * @param portMapList - * Reference to the list containing the mapping to be pushed to - * MD-SAL - * - * @return true/false based on status of operation - */ - - private boolean createPpPortMapping(DataBroker deviceDb, Info deviceInfo, List portMapList) { - // Creating mapping data for degree PP's - - ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction(); - Integer maxSrg; - // Get value for max Srg from subtree, required for iteration - // if it is not defined in the netconf node then set maxSrg to 20 - if (deviceInfo.getMaxSrgs() != null) { - maxSrg = deviceInfo.getMaxSrgs(); - } else { - maxSrg = 20; - } - - Integer srgCounter = 1; - Integer nbSrg = 0; - while (srgCounter <= maxSrg) { - List srgCps = - new ArrayList<>(); - LOG.info("Getting CircuitPacks for Srg Number {}", srgCounter); - InstanceIdentifier srgIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child( - SharedRiskGroup.class, new SharedRiskGroupKey(srgCounter)); - try { - Optional ordmSrgObject = rtx.read(LogicalDatastoreType.CONFIGURATION, srgIID).get(); - - if (ordmSrgObject.isPresent()) { - srgCps.addAll(new ArrayList<>(ordmSrgObject.get().getCircuitPacks())); - nbSrg++; - } - } catch (InterruptedException | ExecutionException ex) { - LOG.warn("Failed to read Srg {}", srgCounter, ex); - break; - } - - for (org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg.CircuitPacks cps : srgCps) { - String circuitPackName = cps.getCircuitPackName(); - try { - InstanceIdentifier cpIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child( - CircuitPacks.class, new CircuitPacksKey(circuitPackName)); - Optional circuitPackObject = rtx.read(LogicalDatastoreType.OPERATIONAL, cpIID).get(); - - if (circuitPackObject.isPresent()) { - CircuitPacks cp = circuitPackObject.get(); - if (cp.getPorts() == null) { - LOG.warn("No port found for {} {}", deviceInfo.getNodeId(), circuitPackName); - } else if (!cp.getPorts().isEmpty()) { - for (Ports port : cp.getPorts()) { - - if (port.getLogicalConnectionPoint() != null && port.getPortQual().getIntValue() == 2) { - String logicalConnectionPoint = null; - if (port.getPortDirection().getIntValue() == 1) { - // Port direction is transmit - if (!port.getLogicalConnectionPoint().contains("SRG")) { - logicalConnectionPoint = "SRG" + srgCounter + "-" + port - .getLogicalConnectionPoint() + "-TX"; - } else { - logicalConnectionPoint = port.getLogicalConnectionPoint() + "-TX"; - } - } - if (port.getPortDirection().getIntValue() == 2) { - // Port direction is receive - if (!port.getLogicalConnectionPoint().contains("SRG")) { - logicalConnectionPoint = "SRG" + srgCounter + "-" + port - .getLogicalConnectionPoint() + "-RX"; - } else { - logicalConnectionPoint = port.getLogicalConnectionPoint() + "-RX"; - } - } - if (port.getPortDirection().getIntValue() == 3) { - // port is bi-directional - if (!port.getLogicalConnectionPoint().contains("SRG")) { - logicalConnectionPoint = "SRG" + srgCounter + "-" + port - .getLogicalConnectionPoint() + "-TXRX"; - } else { - logicalConnectionPoint = port.getLogicalConnectionPoint() + "-TXRX"; - } - } - - LOG.info("Logical Connection Point for {} {} is {}", circuitPackName, port - .getPortName(), logicalConnectionPoint); - - portMapList.add(createMappingObject(port, circuitPackName, logicalConnectionPoint, - deviceDb)); - - } else if (port.getPortQual().getIntValue() == 1) { - - LOG.info("Port is internal, skipping Logical Connection Point missing for " - + circuitPackName + " " + port.getPortName()); - - } else if (port.getLogicalConnectionPoint() == null) { - - LOG.info("Value missing, Skipping Logical Connection Point missing for {} {}", - circuitPackName, port.getPortName()); - } - - } - - } - - } - } catch (InterruptedException | ExecutionException ex) { - LOG.warn("Read failed for {}", circuitPackName, ex); - return false; - } - } - srgCounter++; - } - LOG.info("Device has {} Srg", nbSrg); - return true; - } - - /** - * This private method gets the list of circuit packs on a xponder. For each - * circuit pack on a Xponder, it does a get on circuit-pack subtree with - * circuit-pack-name as key in order to get the list of ports. It then - * iterates over the list of ports to get ports with port-qual as - * xpdr-network/xpdr-client. The line and client ports are saved as: - * - *

- * 1. LINEn - * - *

- * 2. CLNTn - * - * @param deviceDb - * Reference to device's databroker - * @param deviceInfo - * Info subtree read from the device - * @param portMapList - * Reference to the list containing the mapping to be pushed to - * MD-SAL - * - * @return true/false based on status of operation - */ - - private boolean createXpdrPortMapping(DataBroker deviceDb, Info deviceInfo, List portMapList) { - // Creating for Xponder Line and Client Ports - try { - InstanceIdentifier deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class); - ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction(); - Optional deviceObject = rtx.read(LogicalDatastoreType.OPERATIONAL, deviceIID).get(); - - // Variable to keep track of number of line ports - int line = 1; - // Variable to keep track of number of client ports - int client = 1; - if (deviceObject.isPresent()) { - for (CircuitPacks cp : deviceObject.get().getCircuitPacks()) { - String circuitPackName = cp.getCircuitPackName(); - if (cp.getPorts() == null) { - LOG.warn("No port found for {}, circuit pack {}", deviceInfo.getNodeId(), circuitPackName); - } else { - for (Ports port : cp.getPorts()) { - if (port.getPortQual() != null) { - if (port.getPortQual().getIntValue() == 3) { - // Port is xpdr-network - portMapList.add(createMappingObject(port, circuitPackName, "XPDR-LINE" - + line, deviceDb)); - LOG.info("Logical Connection Point for {} {} is XPDR-LINE{}", circuitPackName, port - .getPortName(), line); - line++; - } - if (port.getPortQual().getIntValue() == 4) { - // port is xpdr-client - portMapList.add(createMappingObject(port, circuitPackName, "XPDR-CLNT" - + client, deviceDb)); - LOG.info("Logical Connection Point for {} {} is XPDR-CLNT{}", circuitPackName, port - .getPortName(), client); - client++; - } - } else { - LOG.info("no PortQual for port {} of circuit pack {}", port.getPortName(), cp - .getCircuitPackName()); - } - } - } - } - } else { - LOG.info("No deviceObject present for {}", nodeId); - return false; - } - - } catch (InterruptedException | ExecutionException ex) { - LOG.warn("Read failed for CircuitPacks of {}", nodeId, ex); - return false; - } - return true; - } - - /** - * This private method builds the mapping object to be pushed in MD-SAL in - * order to save port mapping. In case of TTP ports, it also saves the - * OTS,OMS interfaces provisioned on the port. - * - * @param port - * Reference to device's port subtree object. - * @param circuitPackName - * Name of cp where port exists. - * @param logicalConnectionPoint - * logical name of the port. - * @param deviceDb - * Reference to device's databroker. - * - * @return true/false based on status of operation - */ - - private Mapping createMappingObject(Ports port, String circuitPackName, String logicalConnectionPoint, - DataBroker deviceDb) { - MappingBuilder mpBldr = new MappingBuilder(); - mpBldr.setKey(new MappingKey(logicalConnectionPoint)).setLogicalConnectionPoint(logicalConnectionPoint) - .setSupportingCircuitPackName(circuitPackName).setSupportingPort(port.getPortName()); - - // Get OMS and OTS interface provisioned on the TTP's - if (logicalConnectionPoint.contains("TTP") && port.getInterfaces() != null) { - for (Interfaces interfaces : port.getInterfaces()) { - Class interfaceType = new OpenRoadmInterfaces(db, mps, nodeId, - logicalConnectionPoint).getInterface(interfaces.getInterfaceName()).getType(); - // Check if interface type is OMS or OTS - if (interfaceType.equals(OpenROADMOpticalMultiplex.class)) { - String omsInterfaceName = interfaces.getInterfaceName(); - mpBldr.setSupportingOms(omsInterfaceName); - } - if (interfaceType.equals(OpticalTransport.class)) { - String otsInterfaceName = interfaces.getInterfaceName(); - mpBldr.setSupportingOts(otsInterfaceName); - } - } - } - return mpBldr.build(); - } - - /** - * This method does a get operation on info subtree of the netconf device's - * configuration datastore and returns info object.It is required to get - * device attributes such as maxDegrees,maxSrgs and node-type. - * - * @param deviceDb - * Reference to device's databroker - * @return Info object - * - */ - private Info getDeviceInfo(DataBroker deviceDb) { - ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction(); - InstanceIdentifier infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class); - try { - Optional ordmInfoObject = rtx.read(LogicalDatastoreType.OPERATIONAL, infoIID).get(); - if (ordmInfoObject.isPresent()) { - LOG.info("Info subtree is present {}", ordmInfoObject.get()); - return ordmInfoObject.get(); - } else { - LOG.error("Info subtree is not present"); - } - } catch (NullPointerException ex) { - LOG.warn("Try to get Info from a non Open ROADM device {}", deviceDb); - return null; - } catch (InterruptedException | ExecutionException ex) { - LOG.error("Read failed on info subtree ", ex); - return null; - } - return null; - } - - /** - * This method does a get operation on degree subtree of the netconf - * device's config datastore and returns a list of all connection port - * objects. It is required for doing a selective get on ports that - * correspond to logical connection points of interest. - * - * @param deviceDb - * Reference to device's databroker - * @param ordmInfo - * Info subtree from the device - * @return List of connection ports object belonging to- degree subtree - */ - private List getDegreePorts(DataBroker deviceDb, Info ordmInfo) { - - List degreeConPorts = new ArrayList<>(); - ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction(); - Integer maxDegree; - - // Get value for max degree from info subtree, required for iteration - // if not present assume to be 20 (temporary) - if (ordmInfo.getMaxDegrees() != null) { - maxDegree = ordmInfo.getMaxDegrees(); - } else { - maxDegree = 20; - } - Integer degreeCounter = 1; - while (degreeCounter <= maxDegree) { - LOG.info("Getting Connection ports for Degree Number " + degreeCounter); - InstanceIdentifier deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child( - Degree.class, new DegreeKey(degreeCounter)); - try { - Optional ordmDegreeObject = rtx.read(LogicalDatastoreType.CONFIGURATION, deviceIID).get(); - - if (ordmDegreeObject.isPresent()) { - degreeConPorts.addAll(new ArrayList<>(ordmDegreeObject.get().getConnectionPorts())); - - } else { - LOG.info("Device has " + (degreeCounter - 1) + " degree"); - break; - } - } catch (InterruptedException | ExecutionException ex) { - LOG.error("Failed to read degree " + degreeCounter, ex); - break; - - } - degreeCounter++; - } - return degreeConPorts; - } - - /** - * This method for ports the portMapping corresponding to the - * portmapping.yang file to the MD-SAL datastore. - * - *

- * 1. Supporting circuit pack 2. Supporting port 3. Supporting OMS interface - * (if port on ROADM) - * - * @param deviceInfo - * Info subtree from the device. - * @param portMapList - * Reference to the list containing the mapping to be pushed to - * MD-SAL. - * - * @return Result true/false based on status of operation. - */ - private boolean postPortMapping(Info deviceInfo, List portMapList, Integer nodeType) { - - NodesBuilder nodesBldr = new NodesBuilder(); - nodesBldr.setKey(new NodesKey(deviceInfo.getNodeId())).setNodeId(deviceInfo.getNodeId()); - nodesBldr.setNodeType(NodeTypes.forValue(nodeType)); - nodesBldr.setMapping(portMapList); - List nodesList = new ArrayList<>(); - nodesList.add(nodesBldr.build()); - NetworkBuilder nwBldr = new NetworkBuilder(); - nwBldr.setNodes(nodesList); - final WriteTransaction writeTransaction = db.newWriteOnlyTransaction(); - InstanceIdentifier nodesIID = InstanceIdentifier.builder(Network.class).build(); - writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodesIID, nwBldr.build()); - CheckedFuture submit = writeTransaction.submit(); - try { - submit.checkedGet(); - return true; - - } catch (TransactionCommitFailedException e) { - LOG.warn("Failed to post {} ", nwBldr.build(), e); - return false; - - } - } - - /** - * This method for a given node's termination point returns the Mapping - * object based on portmapping.yang model stored in the MD-SAL data store - * which is created when the node is connected for the first time. The - * mapping object basically contains the following attributes of interest: - * - *

- * 1. Supporting circuit pack - * - *

- * 2. Supporting port - * - *

- * 3. Supporting OMS interface (if port on ROADM) 4. Supporting OTS - * interface (if port on ROADM) - * - * @param nodeId - * Unique Identifier for the node of interest. - * @param logicalConnPoint - * Name of the logical point - * @param db - * Databroker / MD-SAL data store - * - * @return Result Mapping object if success otherwise null. - */ - public static Mapping getMapping(String nodeId, String logicalConnPoint, DataBroker db) { - - /* - * Getting physical mapping corresponding to logical connection point - */ - InstanceIdentifier portMapping = InstanceIdentifier.builder(Network.class).child(Nodes.class, - new NodesKey(nodeId)).child(Mapping.class, new MappingKey(logicalConnPoint)).build(); - ReadOnlyTransaction readTx = db.newReadOnlyTransaction(); - Optional mapObject; - try { - mapObject = readTx.read(LogicalDatastoreType.CONFIGURATION, portMapping).get(); - if (mapObject.isPresent()) { - LOG.info("Found mapping for the logical port " + mapObject.get().toString()); - return mapObject.get(); - } else { - LOG.info("Could not find mapping for logical connection point : " + logicalConnPoint + " for nodeId " - + nodeId); - return null; - } - } catch (InterruptedException | ExecutionException ex) { - LOG.error("Unable to read mapping for logical connection point : " + logicalConnPoint + " for nodeId " - + nodeId, ex); - } - return null; - } - - /** - * This static method returns the DataBroker for a netconf node. - * - * @param nodeId - * Unique identifier for the mounted netconf- node - * @param mps - * Reference to mount service - * @return Databroker for the given device - */ - public static DataBroker getDeviceDataBroker(String nodeId, MountPointService mps) { - MountPoint netconfNode = getDeviceMountPoint(nodeId, mps); - if (netconfNode != null) { - DataBroker netconfNodeDataBroker = netconfNode.getService(DataBroker.class).get(); - return netconfNodeDataBroker; - } else { - LOG.error("Device Data broker not found for :" + nodeId); - return null; - } - } - - public static MountPoint getDeviceMountPoint(String nodeId, MountPointService mps) { - InstanceIdentifier netconfNodeIID = InstanceIdentifier.builder(NetworkTopology.class).child( - Topology.class, new TopologyKey(new TopologyId(TopologyNetconf.QNAME.getLocalName()))).child(Node.class, - new NodeKey(new NodeId(nodeId))).build(); - - // Get mount point for specified device - final Optional netconfNodeOptional = mps.getMountPoint(netconfNodeIID); - if (netconfNodeOptional.isPresent()) { - MountPoint netconfNode = netconfNodeOptional.get(); - return netconfNode; - } else { - LOG.error("Mount Point not found for :" + nodeId); - return null; - } - - } -} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmEthIterface.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmEthIterface.java deleted file mode 100644 index 9ba76734a..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmEthIterface.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.openroadminterface; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.EthAttributes.AutoNegotiation; -import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.EthAttributes.Duplex; -import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.EthAttributes.Fec; -import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.Interface1; -import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.Interface1Builder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.ethernet.container.EthernetBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.EthernetCsmacd; - -public class OpenRoadmEthIterface extends OpenRoadmInterfaces { - - public OpenRoadmEthIterface(DataBroker db, MountPointService mps, String nodeId, String logicalConnPoint, - String serviceName) { - super(db, mps, nodeId, logicalConnPoint, serviceName); - - } - - public String createInterface() { - InterfaceBuilder ethInterfaceBldr = getIntfBuilder(portMap); - ethInterfaceBldr.setType(EthernetCsmacd.class); - ethInterfaceBldr.setName(logicalConnPoint + "-ETHERNET"); - ethInterfaceBldr.setKey(new InterfaceKey(logicalConnPoint + "-ETHERNET")); - - // Ethernet interface specific data - EthernetBuilder ethIfBuilder = new EthernetBuilder(); - ethIfBuilder.setAutoNegotiation(AutoNegotiation.Enabled); - ethIfBuilder.setDuplex(Duplex.Full); - ethIfBuilder.setFec(Fec.Off); - ethIfBuilder.setSpeed(new Long(100000)); - ethIfBuilder.setMtu(new Long(9000)); - - // Create Interface1 type object required for adding as augmentation - Interface1Builder ethIf1Builder = new Interface1Builder(); - ethInterfaceBldr.addAugmentation(Interface1.class, ethIf1Builder.setEthernet(ethIfBuilder.build()).build()); - - // Post interface on the device - if (postInterface(ethInterfaceBldr)) { - return ethInterfaceBldr.getName(); - } else { - return null; - } - - } - -} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmInterfaceFactory.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmInterfaceFactory.java new file mode 100644 index 000000000..a16fcd1bb --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmInterfaceFactory.java @@ -0,0 +1,251 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.renderer.openroadminterface; + +import java.math.BigDecimal; + +import org.opendaylight.transportpce.common.mapping.PortMapping; +import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException; +import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.PowerDBm; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; +import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev161014.AdminStates; +import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.EthAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.Interface1; +import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.Interface1Builder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev161014.ethernet.container.EthernetBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.EthernetCsmacd; +import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.InterfaceType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OpticalChannel; +import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OtnOdu; +import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OtnOtu; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.OchAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.RateIdentity; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.och.container.OchBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.ODU4; +import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.OduAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.odu.container.OduBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.opu.OpuBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.OTU4; +import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.OtuAttributes; +import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.otu.container.OtuBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.Mapping; + +public class OpenRoadmInterfaceFactory { + + private final PortMapping portMapping; + private final OpenRoadmInterfaces openRoadmInterfaces; + + public OpenRoadmInterfaceFactory(PortMapping portMapping, OpenRoadmInterfaces openRoadmInterfaces) { + this.portMapping = portMapping; + this.openRoadmInterfaces = openRoadmInterfaces; + } + + public String createOpenRoadmEthInterface(String nodeId, + String logicalConnPoint) throws OpenRoadmInterfaceException { + Mapping portMap = this.portMapping.getMapping(nodeId, logicalConnPoint); + if (portMap == null) { + throw new OpenRoadmInterfaceException(String.format("Unable to get mapping from PortMapping for node % and" + + " logical connection port %s", nodeId, logicalConnPoint)); + } + + // Ethernet interface specific data + EthernetBuilder ethIfBuilder = new EthernetBuilder(); + ethIfBuilder.setAutoNegotiation(EthAttributes.AutoNegotiation.Enabled); + ethIfBuilder.setDuplex(EthAttributes.Duplex.Full); + ethIfBuilder.setFec(EthAttributes.Fec.Off); + ethIfBuilder.setSpeed(100000L); + ethIfBuilder.setMtu(9000L); + + InterfaceBuilder ethInterfaceBldr = createGenericInterfaceBuilder(portMap, EthernetCsmacd.class, + logicalConnPoint + "-ETHERNET"); + + // Create Interface1 type object required for adding as augmentation + Interface1Builder ethIf1Builder = new Interface1Builder(); + ethInterfaceBldr.addAugmentation(Interface1.class, ethIf1Builder.setEthernet(ethIfBuilder.build()).build()); + + // Post interface on the device + this.openRoadmInterfaces.postInterface(nodeId, ethInterfaceBldr); + return ethInterfaceBldr.getName(); + } + + /** + * This methods creates an OCH interface on the given termination point on + * Roadm. + * + * @param waveNumber + * wavelength number of the OCH interface. + * + * @return Name of the interface if successful, otherwise return null. + */ + + public String createOpenRoadmOchInterface(String nodeId, String logicalConnPoint, Long waveNumber) throws + OpenRoadmInterfaceException { + Mapping portMap = this.portMapping.getMapping(nodeId, logicalConnPoint); + if (portMap == null) { + throw new OpenRoadmInterfaceException(String.format("Unable to get mapping from PortMapping for node %s and" + + " logical connection port %s", nodeId, logicalConnPoint)); + } + // Create generic interface + InterfaceBuilder ochInterfaceBldr = createGenericInterfaceBuilder(portMap, OpticalChannel.class, + createOpenRoadmOchInterfaceName(logicalConnPoint, waveNumber)); + + // OCH interface specific data + OchBuilder ocIfBuilder = new OchBuilder(); + ocIfBuilder.setWavelengthNumber(waveNumber); + + // Add supporting OMS interface + if (portMap.getSupportingOms() != null) { + ochInterfaceBldr.setSupportingInterface(portMap.getSupportingOms()); + } + // Create Interface1 type object required for adding as augmentation + // TODO look at imports of different versions of class + org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.Interface1Builder + ochIf1Builder = new org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces + .rev161014.Interface1Builder(); + ochInterfaceBldr.addAugmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.Interface1.class, + ochIf1Builder.setOch(ocIfBuilder.build()).build()); + + // Post interface on the device + this.openRoadmInterfaces.postInterface(nodeId, ochInterfaceBldr); + return ochInterfaceBldr.getName(); + } + + public String createOpenRoadmOchInterface(String nodeId, String logicalConnPoint, Long waveNumber, + Class rate, OchAttributes.ModulationFormat format) throws OpenRoadmInterfaceException { + Mapping portMap = this.portMapping.getMapping(nodeId, logicalConnPoint); + if (portMap == null) { + throw new OpenRoadmInterfaceException(String.format("Unable to get mapping from PortMapping for node %s and" + + " logical connection port %s", nodeId, logicalConnPoint)); + } + + // OCH interface specific data + OchBuilder ocIfBuilder = new OchBuilder(); + ocIfBuilder.setWavelengthNumber(waveNumber); + ocIfBuilder.setModulationFormat(format); + ocIfBuilder.setRate(rate); + ocIfBuilder.setTransmitPower(new PowerDBm(new BigDecimal("-5"))); + + // Create Interface1 type object required for adding as augmentation + // TODO look at imports of different versions of class + org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.Interface1Builder + ochIf1Builder = new org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces + .rev161014.Interface1Builder(); + // Create generic interface + InterfaceBuilder ochInterfaceBldr = createGenericInterfaceBuilder(portMap, OpticalChannel.class, + createOpenRoadmOchInterfaceName(logicalConnPoint, waveNumber)); + ochInterfaceBldr.addAugmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.Interface1.class, + ochIf1Builder.setOch(ocIfBuilder.build()).build()); + + // Post interface on the device + this.openRoadmInterfaces.postInterface(nodeId, ochInterfaceBldr); + return ochInterfaceBldr.getName(); + } + + public String createOpenRoadmOchInterfaceName(String logicalConnectionPoint, Long waveNumber) { + return logicalConnectionPoint + "-" + waveNumber; + } + + /** + * This methods creates an ODU interface on the given termination point. + * + * + * @return Name of the interface if successful, otherwise return null. + */ + + public String createOpenRoadmOdu4Interface(String nodeId, String logicalConnPoint, String supportingOtuInterface) + throws OpenRoadmInterfaceException { + Mapping portMap = this.portMapping.getMapping(nodeId, logicalConnPoint); + if (portMap == null) { + throw new OpenRoadmInterfaceException(String.format("Unable to get mapping from PortMapping for node % and" + + " logical connection port %s", nodeId, logicalConnPoint)); + } + InterfaceBuilder oduInterfaceBldr = createGenericInterfaceBuilder(portMap, OtnOdu.class, + logicalConnPoint + "-ODU"); + oduInterfaceBldr.setSupportingInterface(supportingOtuInterface); + + // ODU interface specific data + OduBuilder oduIfBuilder = new OduBuilder(); + oduIfBuilder.setRate(ODU4.class); + oduIfBuilder.setMonitoringMode(OduAttributes.MonitoringMode.Terminated); + + //Set Opu attributes + OpuBuilder opuBldr = new OpuBuilder(); + opuBldr.setPayloadType("07"); + opuBldr.setExpPayloadType("07"); + oduIfBuilder.setOpu(opuBldr.build()); + + + // Create Interface1 type object required for adding as augmentation + // TODO look at imports of different versions of class + org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.Interface1Builder oduIf1Builder = + new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.Interface1Builder(); + oduInterfaceBldr.addAugmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.Interface1.class, + oduIf1Builder.setOdu(oduIfBuilder.build()).build()); + + // Post interface on the device + this.openRoadmInterfaces.postInterface(nodeId, oduInterfaceBldr); + return oduInterfaceBldr.getName(); + } + + /** + * This methods creates an OTU interface on the given termination point. + * + * + * @return Name of the interface if successful, otherwise return null. + */ + + public String createOpenRoadmOtu4Interface(String nodeId, String logicalConnPoint, String supportOchInterface) + throws OpenRoadmInterfaceException { + Mapping portMap = this.portMapping.getMapping(nodeId, logicalConnPoint); + if (portMap == null) { + throw new OpenRoadmInterfaceException(String.format("Unable to get mapping from PortMapping for node % and" + + " logical connection port %s", nodeId, logicalConnPoint)); + } + // Create generic interface + InterfaceBuilder otuInterfaceBldr = createGenericInterfaceBuilder(portMap, OtnOtu.class, + logicalConnPoint + "-OTU"); + otuInterfaceBldr.setSupportingInterface(supportOchInterface); + + // OTU interface specific data + OtuBuilder otuIfBuilder = new OtuBuilder(); + otuIfBuilder.setFec(OtuAttributes.Fec.Scfec); + otuIfBuilder.setRate(OTU4.class); + + // Create Interface1 type object required for adding as augmentation + // TODO look at imports of different versions of class + org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.Interface1Builder otuIf1Builder = + new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.Interface1Builder(); + otuInterfaceBldr.addAugmentation( + org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.Interface1.class, + otuIf1Builder.setOtu(otuIfBuilder.build()).build()); + + // Post interface on the device + this.openRoadmInterfaces.postInterface(nodeId, otuInterfaceBldr); + return otuInterfaceBldr.getName(); + } + + private InterfaceBuilder createGenericInterfaceBuilder(Mapping portMap, Class type, + String key) { + InterfaceBuilder interfaceBuilder = new InterfaceBuilder(); + interfaceBuilder.setDescription(" TBD "); + interfaceBuilder.setCircuitId(" TBD "); + interfaceBuilder.setSupportingCircuitPackName(portMap.getSupportingCircuitPackName()); + interfaceBuilder.setSupportingPort(portMap.getSupportingPort()); + interfaceBuilder.setAdministrativeState(AdminStates.InService); + interfaceBuilder.setType(type); + interfaceBuilder.setName(key); + interfaceBuilder.setKey(new InterfaceKey(key)); + return interfaceBuilder; + } +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmInterfaces.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmInterfaces.java deleted file mode 100644 index 333177d43..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmInterfaces.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.openroadminterface; - -import com.google.common.base.Optional; -import com.google.common.util.concurrent.CheckedFuture; - -import java.util.concurrent.ExecutionException; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.transportpce.renderer.mapping.PortMapping; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.Interface; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev161014.AdminStates; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.portmapping.rev170228.network.nodes.Mapping; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class OpenRoadmInterfaces { - - protected final DataBroker db; - protected final DataBroker netconfNodeDataBroker; - protected final String nodeId; - protected final MountPointService mps; - protected final Mapping portMap; - protected final String logicalConnPoint; - private final String serviceName; - private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmInterfaces.class); - - public OpenRoadmInterfaces(DataBroker db, MountPointService mps, String nodeId, String logicalConnPoint) { - this.db = db; - this.mps = mps; - this.logicalConnPoint = logicalConnPoint; - this.nodeId = nodeId; - if (logicalConnPoint != null) { - this.portMap = PortMapping.getMapping(nodeId, logicalConnPoint, db); - } else { - this.portMap = null; - } - this.serviceName = null; - netconfNodeDataBroker = PortMapping.getDeviceDataBroker(nodeId, mps); - } - - public OpenRoadmInterfaces(DataBroker db, MountPointService mps, String nodeId, String logicalConnPoint, - String serviceName) { - this.db = db; - this.mps = mps; - this.logicalConnPoint = logicalConnPoint; - this.nodeId = nodeId; - if (logicalConnPoint != null) { - this.portMap = PortMapping.getMapping(nodeId, logicalConnPoint, db); - } else { - this.portMap = null; - } - this.serviceName = serviceName; - netconfNodeDataBroker = PortMapping.getDeviceDataBroker(nodeId, mps); - } - - /** - * This methods creates a generic interface builder object to set the value that - * are common irrespective of the interface type. - * - * @param portMap - * Mapping object containing attributes required to create interface - * on the device. - * - * @return InterfaceBuilder object with the data. - */ - public InterfaceBuilder getIntfBuilder(Mapping portMap) { - - InterfaceBuilder ifBuilder = new InterfaceBuilder(); - ifBuilder.setDescription(" TBD "); - ifBuilder.setCircuitId(" TBD "); - ifBuilder.setSupportingCircuitPackName(portMap.getSupportingCircuitPackName()); - ifBuilder.setSupportingPort(portMap.getSupportingPort()); - ifBuilder.setAdministrativeState(AdminStates.InService); - return ifBuilder; - } - - /** - * This methods does an edit-config operation on the openROADM device in order - * to create the given interface. - * - *

- * Before posting the interface it checks if: - * - *

- * 1. Interface with same name does not exist - * - *

- * 2. If exists then admin state of interface is outOfState/Maintenance - * - * @param ifBuilder - * Builder object containing the data to post. - * - * @return Result of operation true/false based on success/failure. - */ - public boolean postInterface(InterfaceBuilder ifBuilder) { - String intf2Post = ifBuilder.getName(); - Interface intf2PostCheck = getInterface(intf2Post); - if (intf2PostCheck != null && intf2PostCheck.getAdministrativeState() == AdminStates.InService) { - LOG.info("Interface with same name in service already exists on node " + nodeId); - return true; - } - - // Post interface with its specific augmentation to the device - if (netconfNodeDataBroker != null) { - InstanceIdentifier interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(Interface.class, new InterfaceKey(ifBuilder.getName())); - final WriteTransaction writeTransaction = netconfNodeDataBroker.newWriteOnlyTransaction(); - writeTransaction.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, ifBuilder.build()); - final CheckedFuture submit = writeTransaction.submit(); - try { - submit.checkedGet(); - LOG.info("Successfully posted interface " + ifBuilder.getName() + " on node " + nodeId); - return true; - } catch (TransactionCommitFailedException ex) { - LOG.warn("Failed to post {} ", ifBuilder.getName() + " on node " + nodeId, ex); - return false; - } - - } else { - return false; - } - } - - /** - * This private does a get on the interface subtree of the device with the - * interface name as the key and return the class corresponding to the interface - * type. - * - * @param interfaceName - * Name of the interface - * - * @return true/false based on status of operation - */ - - public Interface getInterface(String interfaceName) { - ReadOnlyTransaction rtx = netconfNodeDataBroker.newReadOnlyTransaction(); - InstanceIdentifier interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(Interface.class, new InterfaceKey(interfaceName)); - try { - Optional interfaceObject = rtx.read(LogicalDatastoreType.CONFIGURATION, interfacesIID).get(); - if (interfaceObject.isPresent()) { - return interfaceObject.get(); - } else { - LOG.info("Interface subtree is not present for " + interfaceName + " on node " + nodeId); - } - } catch (InterruptedException | ExecutionException ex) { - LOG.info("Read failed on interface subtree for" + interfaceName + " on node " + nodeId, ex); - return null; - } - return null; - } - - /** - * This methods does an edit-config operation on the openROADM device in order - * to delete the given interface. - * - *

- * Before deleting the method: - * - *

- * 1. Checks if interface exists - * - *

- * 2. If exists then changes the state of interface to outOfService - * - * @param interfaceName - * Name of the interface to delete. - * - * @return Result of operation true/false based on success/failure. - */ - public boolean deleteInterface(String interfaceName) { - // Post interface with its specific augmentation to the device - if (netconfNodeDataBroker != null) { - Interface intf2Delete = getInterface(interfaceName); - if (intf2Delete != null) { - // State admin state to out of service - InterfaceBuilder ifBuilder = new InterfaceBuilder(intf2Delete); - ifBuilder.setAdministrativeState(AdminStates.OutOfService); - // post interface with updated admin state - if (postInterface(ifBuilder)) { - InstanceIdentifier interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(Interface.class, new InterfaceKey(interfaceName)); - final WriteTransaction writeTransaction = netconfNodeDataBroker.newWriteOnlyTransaction(); - writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, interfacesIID); - final CheckedFuture submit = writeTransaction.submit(); - - try { - submit.checkedGet(); - LOG.info("Successfully deleted " + interfaceName + " on node " + nodeId); - return true; - - } catch (TransactionCommitFailedException ex) { - LOG.error("Failed to delete interface " + interfaceName + " on node " + nodeId); - return false; - } - - } else { - - LOG.error("Error changing the state of interface " + interfaceName + " on node " + nodeId); - return false; - } - } else { - LOG.info("Interface does not exist, cannot delete on node " + nodeId); - return false; - } - - } else { - - LOG.info("Device databroker not found on node " + nodeId); - return false; - } - } -} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOchInterface.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOchInterface.java deleted file mode 100644 index 3743d1251..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOchInterface.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.openroadminterface; - -import java.math.BigDecimal; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.PowerDBm; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OpticalChannel; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.Interface1; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.Interface1Builder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.OchAttributes.ModulationFormat; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.RateIdentity; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.och.container.OchBuilder; - -public class OpenRoadmOchInterface extends OpenRoadmInterfaces { - - public OpenRoadmOchInterface(DataBroker db, MountPointService mps, String nodeId, String logicalConnPoint, - String serviceName) { - super(db, mps, nodeId, logicalConnPoint, serviceName); - } - - /** - * This methods creates an OCH interface on the given termination point on - * Roadm. - * - * @param waveNumber - * wavelength number of the OCH interface. - * - * @return Name of the interface if successful, otherwise return null. - */ - - public String createInterface(Long waveNumber) { - - // Create generic interface - InterfaceBuilder ochInterfaceBldr = getIntfBuilder(portMap); - ochInterfaceBldr.setType(OpticalChannel.class); - ochInterfaceBldr.setName(logicalConnPoint + "-" + waveNumber); - ochInterfaceBldr.setKey(new InterfaceKey(logicalConnPoint + "-" + waveNumber)); - - // OCH interface specific data - OchBuilder ocIfBuilder = new OchBuilder(); - ocIfBuilder.setWavelengthNumber(waveNumber); - - // Add supporting OMS interface - if (portMap.getSupportingOms() != null) { - ochInterfaceBldr.setSupportingInterface(portMap.getSupportingOms()); - } - // Create Interface1 type object required for adding as augmentation - Interface1Builder ochIf1Builder = new Interface1Builder(); - ochInterfaceBldr.addAugmentation(Interface1.class, ochIf1Builder.setOch(ocIfBuilder.build()).build()); - - // Post interface on the device - if (postInterface(ochInterfaceBldr)) { - return ochInterfaceBldr.getName(); - } else { - return null; - } - } - - public String createInterface(Long waveNumber, Class rate, ModulationFormat format) { - - // Create generic interface - InterfaceBuilder ochInterfaceBldr = getIntfBuilder(portMap); - ochInterfaceBldr.setType(OpticalChannel.class); - ochInterfaceBldr.setName(logicalConnPoint + "-" + waveNumber); - ochInterfaceBldr.setKey(new InterfaceKey(logicalConnPoint + "-" + waveNumber)); - - // OCH interface specific data - OchBuilder ocIfBuilder = new OchBuilder(); - ocIfBuilder.setWavelengthNumber(waveNumber); - ocIfBuilder.setModulationFormat(format); - ocIfBuilder.setRate(rate); - ocIfBuilder.setTransmitPower(new PowerDBm(new BigDecimal("-5"))); - - // Create Interface1 type object required for adding as augmentation - Interface1Builder ochIf1Builder = new Interface1Builder(); - ochInterfaceBldr.addAugmentation(Interface1.class, ochIf1Builder.setOch(ocIfBuilder.build()).build()); - - // Post interface on the device - if (postInterface(ochInterfaceBldr)) { - return ochInterfaceBldr.getName(); - } else { - return null; - } - } - -} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOdu4Interface.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOdu4Interface.java deleted file mode 100644 index f3a6b927c..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOdu4Interface.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.openroadminterface; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OtnOdu; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.Interface1; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.Interface1Builder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.ODU4; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.OduAttributes.MonitoringMode; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev161014.odu.container.OduBuilder; - -public class OpenRoadmOdu4Interface extends OpenRoadmInterfaces { - - public OpenRoadmOdu4Interface(DataBroker db, MountPointService mps, String nodeId, String logicalConnPoint, - String serviceName) { - super(db, mps, nodeId, logicalConnPoint, serviceName); - - } - - /** - * This methods creates an ODU interface on the given termination point. - * - * @param supportingOtuInterface - * supporting Otu Interface - * - * @return Name of the interface if successful, otherwise return null. - */ - - public String createInterface(String supportingOtuInterface) { - - InterfaceBuilder oduInterfaceBldr = getIntfBuilder(portMap); - oduInterfaceBldr.setType(OtnOdu.class); - oduInterfaceBldr.setSupportingInterface(supportingOtuInterface); - oduInterfaceBldr.setName(logicalConnPoint + "-ODU"); - oduInterfaceBldr.setKey(new InterfaceKey(logicalConnPoint + "-ODU")); - - // ODU interface specific data - OduBuilder oduIfBuilder = new OduBuilder(); - oduIfBuilder.setRate(ODU4.class); - oduIfBuilder.setMonitoringMode(MonitoringMode.Monitored); - - // Create Interface1 type object required for adding as augmentation - Interface1Builder oduIf1Builder = new Interface1Builder(); - oduInterfaceBldr.addAugmentation(Interface1.class, oduIf1Builder.setOdu(oduIfBuilder.build()).build()); - - // Post interface on the device - if (postInterface(oduInterfaceBldr)) { - return oduInterfaceBldr.getName(); - } else { - return null; - } - } -} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOtu4Interface.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOtu4Interface.java deleted file mode 100644 index abffa1ee5..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOtu4Interface.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.openroadminterface; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.interfaces.grp.InterfaceKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev161014.OtnOtu; - -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.Interface1; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.Interface1Builder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.OTU4; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.OtuAttributes.Fec; -import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev161014.otu.container.OtuBuilder; - -public class OpenRoadmOtu4Interface extends OpenRoadmInterfaces { - - public OpenRoadmOtu4Interface(DataBroker db, MountPointService mps, String nodeId, String logicalConnPoint, - String serviceName) { - super(db, mps, nodeId, logicalConnPoint, serviceName); - - } - - /** - * This methods creates an OTU interface on the given termination point. - * - * @param supportOchInterface - * support Och Interface - * - * @return Name of the interface if successful, otherwise return null. - */ - - public String createInterface(String supportOchInterface) { - // Create generic interface - InterfaceBuilder otuInterfaceBldr = getIntfBuilder(portMap); - otuInterfaceBldr.setType(OtnOtu.class); - otuInterfaceBldr.setSupportingInterface(supportOchInterface); - otuInterfaceBldr.setName(logicalConnPoint + "-OTU"); - otuInterfaceBldr.setKey(new InterfaceKey(logicalConnPoint + "-OTU")); - - // OTU interface specific data - OtuBuilder otuIfBuilder = new OtuBuilder(); - otuIfBuilder.setFec(Fec.Scfec); - otuIfBuilder.setRate(OTU4.class); - - // Create Interface1 type object required for adding as augmentation - Interface1Builder otuIf1Builder = new Interface1Builder(); - otuInterfaceBldr.addAugmentation(Interface1.class, otuIf1Builder.setOtu(otuIfBuilder.build()).build()); - - // Post interface on the device - if (postInterface(otuInterfaceBldr)) { - return otuInterfaceBldr.getName(); - } else { - return null; - } - } -} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmXponderInterface.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmXponderInterface.java deleted file mode 100644 index 107bfd817..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmXponderInterface.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.openroadminterface; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.OchAttributes.ModulationFormat; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.RateIdentity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class OpenRoadmXponderInterface extends OpenRoadmInterfaces { - - private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmXponderInterface.class); - private final String serviceName; - - public OpenRoadmXponderInterface(DataBroker db, MountPointService mps, String nodeId, String logicalConnPoint, - String serviceName) { - super(db, mps, nodeId, logicalConnPoint,serviceName); - this.serviceName = serviceName; - - } - - public boolean createLineInterfaces(Long waveNumber, Class rate, ModulationFormat format) { - - String supportOchInterface = new OpenRoadmOchInterface(db, mps, nodeId, logicalConnPoint,serviceName) - .createInterface(waveNumber, rate, format); - String supportingOtuInterface; - String supportingOduInterface; - - if (supportOchInterface != null) { - supportingOtuInterface = new OpenRoadmOtu4Interface(db, mps, nodeId, logicalConnPoint,serviceName) - .createInterface(supportOchInterface); - } else { - LOG.error("Unable to create OCH interface on the transponder"); - return false; - } - if (supportingOtuInterface != null) { - supportingOduInterface = new OpenRoadmOdu4Interface(db, mps, nodeId, logicalConnPoint,serviceName) - .createInterface(supportingOtuInterface); - } else { - LOG.error("Unable to create OTU interface on the transponder"); - return false; - } - if (supportingOduInterface != null) { - return true; - } else { - LOG.error("Unable to create ODU interface on the transponder"); - return false; - } - } - - public boolean createClientInterfaces() { - - if (new OpenRoadmEthIterface(db, mps, nodeId, logicalConnPoint,serviceName).createInterface() != null) { - return true; - } - return false; - } -} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/CrossConnect.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/CrossConnect.java deleted file mode 100644 index 993a6a762..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/CrossConnect.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.provisiondevice; - -import com.google.common.base.Optional; -import com.google.common.util.concurrent.CheckedFuture; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPoint; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; -import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry; -import org.opendaylight.transportpce.renderer.mapping.PortMapping; -import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.OpticalControlMode; -import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev161014.PowerDBm; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.GetConnectionPortTrailInputBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.GetConnectionPortTrailOutput; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.OrgOpenroadmDeviceService; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.connection.DestinationBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.connection.SourceBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.get.connection.port.trail.output.Ports; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.RoadmConnections; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.RoadmConnectionsBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.org.openroadm.device.RoadmConnectionsKey; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CrossConnect { - - private final DataBroker deviceDb; - private static final Logger LOG = LoggerFactory.getLogger(CrossConnect.class); - private final String connectionNumber; - private final InstanceIdentifier rdmConnectionIID; - - public CrossConnect(DataBroker deviceDb) { - this.deviceDb = deviceDb; - connectionNumber = null; - rdmConnectionIID = null; - } - - public CrossConnect(DataBroker deviceDb, String connectionNumber) { - this.deviceDb = deviceDb; - this.connectionNumber = connectionNumber; - rdmConnectionIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(RoadmConnections.class, - new RoadmConnectionsKey(connectionNumber)); - } - - /** - * This method return the RoadmConnection subtree for a given connection - * number. - * - * @return Roadm connection subtree from the device. - */ - public RoadmConnections getCrossConnect() { - - if (deviceDb != null && connectionNumber != null) { - ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction(); - Optional roadmConnectionsObject; - try { - roadmConnectionsObject = rtx.read(LogicalDatastoreType.OPERATIONAL, rdmConnectionIID).get(); - if (roadmConnectionsObject.isPresent()) { - return roadmConnectionsObject.get(); - } - } catch (InterruptedException | ExecutionException ex) { - LOG.info("Error getting roadm-connection subtree from the device for " + connectionNumber, ex); - return null; - } - } - return null; - } - - /** - * This method does a post(edit-config) on roadm connection subtree for a - * given connection number. - * - * @param waveNumber - * Wavelength number. - * @param srcTp - * Name of source termination point. - * @param destTp - * Name of destination termination point. - * @return true/false based on status of operation. - */ - public boolean postCrossConnect(Long waveNumber, String srcTp, String destTp) { - - RoadmConnectionsBuilder rdmConnBldr = new RoadmConnectionsBuilder(); - rdmConnBldr.setConnectionNumber(srcTp + "-" + destTp + "-" + waveNumber); - rdmConnBldr.setWavelengthNumber(waveNumber); - rdmConnBldr.setOpticalControlMode(OpticalControlMode.Off); - rdmConnBldr.setSource(new SourceBuilder().setSrcIf(srcTp + "-" + waveNumber.toString()).build()); - rdmConnBldr.setDestination(new DestinationBuilder().setDstIf(destTp + "-" + waveNumber.toString()).build()); - InstanceIdentifier rdmConnectionIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(RoadmConnections.class, new RoadmConnectionsKey(rdmConnBldr.getConnectionNumber())); - - if (deviceDb != null) { - final WriteTransaction writeTransaction = deviceDb.newWriteOnlyTransaction(); - // post the cross connect on the device - writeTransaction.put(LogicalDatastoreType.CONFIGURATION, rdmConnectionIID, rdmConnBldr.build()); - final CheckedFuture submit = writeTransaction.submit(); - try { - submit.checkedGet(); - LOG.info("Roadm-connection successfully created: " + srcTp + "-" + destTp + "-" + waveNumber); - return true; - } catch (TransactionCommitFailedException ex) { - LOG.info("Failed to post {} ", rdmConnBldr.build(), ex); - return false; - } - } else { - LOG.error("Invalid device databroker"); - return false; - } - } - - - - /** - * This method does a delete(edit-config) on roadm connection subtree for a - * given connection number. - * - * @return true/false based on status of operation. - */ - - public boolean deleteCrossConnect() { - - //Check if cross connect exists before delete - if (getCrossConnect() == null) { - LOG.info("Cross connect does not exist, halting delete"); - return false; - } - if (deviceDb != null) { - final WriteTransaction writeTransaction = deviceDb.newWriteOnlyTransaction(); - // post the cross connect on the device - writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, rdmConnectionIID); - final CheckedFuture submit = writeTransaction.submit(); - try { - submit.checkedGet(); - LOG.info("Roadm connection successfully deleted "); - return true; - } catch (TransactionCommitFailedException ex) { - LOG.info("Failed to delete {} ", connectionNumber, ex); - return false; - } - } else { - LOG.error("Invalid device databroker"); - return false; - } - } - - - - /** - * 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 mode - * Optical control modelcan be off, power or gainLoss. - * @param value - * Power value in DBm. - * @return true/false based on status of operation. - */ - public boolean setPowerLevel(OpticalControlMode mode, PowerDBm value) { - - RoadmConnections rdmConn = getCrossConnect(); - if (rdmConn != null) { - RoadmConnectionsBuilder rdmConnBldr = new RoadmConnectionsBuilder(rdmConn); - rdmConnBldr.setOpticalControlMode(mode); - rdmConnBldr.setTargetOutputPower(value); - if (deviceDb != null) { - final WriteTransaction writeTransaction = deviceDb.newWriteOnlyTransaction(); - // post the cross connect on the device - writeTransaction.put(LogicalDatastoreType.CONFIGURATION, rdmConnectionIID, rdmConnBldr.build()); - final CheckedFuture submit = writeTransaction.submit(); - try { - submit.checkedGet(); - LOG.info("Roadm connection power level successfully set "); - return true; - } catch (TransactionCommitFailedException ex) { - LOG.info("Failed to post {} ", rdmConnBldr.build(), ex); - return false; - } - } else { - LOG.error("Invalid device databroker"); - return false; - } - } else { - LOG.info("Roadm-Connection does not exist"); - return false; - } - } - - /** - * This public method returns the list of ports (port-trail) for a roadm's - * cross connect. It calls rpc get-port-trail on device. To be used store - * detailed path description. - * - * @param nodeId - * node-id of NE. - * @param mountService - * Reference to mount point service. - * @param waveNumber - * Wavelength number. - * @param srcTp - * Source logical connection point. - * @param destTp - * Destination logical connection point. - * - * @return list of Ports object type. - */ - public Ports getConnectionPortTrail(String nodeId, MountPointService mountService, Long waveNumber, String srcTp, - String destTp) { - - String connectionName = srcTp + "-" + destTp + "-" + waveNumber; - MountPoint mountPoint = PortMapping.getDeviceMountPoint(nodeId, mountService); - - final Optional service = mountPoint.getService(RpcConsumerRegistry.class); - if (!service.isPresent()) { - LOG.error("Failed to get RpcService for node {}", nodeId); - } - final OrgOpenroadmDeviceService rpcService = service.get().getRpcService(OrgOpenroadmDeviceService.class); - final GetConnectionPortTrailInputBuilder portTrainInputBuilder = new GetConnectionPortTrailInputBuilder(); - portTrainInputBuilder.setConnectionNumber(connectionName); - final Future> portTrailOutput = rpcService.getConnectionPortTrail( - portTrainInputBuilder.build()); - if (portTrailOutput != null) { - try { - LOG.info("Getting port trail for node " + nodeId + "'s connection number " + connectionName); - for (Ports ports : portTrailOutput.get().getResult().getPorts()) { - LOG.info(nodeId + " - " + "Circuit pack " + ports.getCircuitPackName() + "- Port " + ports - .getPortName()); - } - } catch (InterruptedException | ExecutionException e) { - LOG.info("Exception caught", e); - } - } else { - LOG.info("Port trail is null"); - } - return null; - } -} \ No newline at end of file diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRenderer.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRenderer.java deleted file mode 100644 index b4bbc52f1..000000000 --- a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRenderer.java +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright © 2017 AT&T and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.transportpce.renderer.provisiondevice; - -import com.google.common.base.Optional; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.MountPointService; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.transportpce.renderer.mapping.PortMapping; -import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaces; -import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmOchInterface; -import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmXponderInterface; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacks; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacksBuilder; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.circuit.packs.CircuitPacksKey; -import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice; -import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev161014.States; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.OchAttributes.ModulationFormat; -import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.R100G; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathInput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathOutput; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathOutputBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.service.path.input.Nodes; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.common.RpcResult; -import org.opendaylight.yangtools.yang.common.RpcResultBuilder; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DeviceRenderer implements RendererService { - - private final DataBroker db; - private final MountPointService mps; - private static final Logger LOG = LoggerFactory.getLogger(RendererService.class); - private final Set currentMountedDevice; - private final Set nodesProvisioned; - - public DeviceRenderer(DataBroker db, MountPointService mps, Set currentMountedDevice) { - this.db = db; - this.mps = mps; - this.currentMountedDevice = currentMountedDevice; - this.nodesProvisioned = new HashSet<>(); - } - - /** - * This method is the implementation of the 'service-path' RESTCONF service, - * which is one of the external APIs into the renderer application. The - * service provides two functions: - * - *

- * 1. Create This operation results in provisioning the device for a given - * wavelength and a list of nodes with each node listing its termination - * points. - * - *

- * 2. Delete This operation results in de-provisioning the device for a - * given wavelength and a list of nodes with each node listing its - * termination points. - * - *

- * The signature for this method was generated by yang tools from the - * renderer API model. - * - * @param input - * Input parameter from the service-path yang model - * - * @return Result of the request - */ - @Override - public Future> servicePath(ServicePathInput input) { - - if (input.getOperation().getIntValue() == 1) { - LOG.info("Create operation request received"); - return RpcResultBuilder.success(setupServicePath(input)).buildFuture(); - } else if (input.getOperation().getIntValue() == 2) { - LOG.info("Delete operation request received"); - return RpcResultBuilder.success(deleteServicePath(input)).buildFuture(); - } - return RpcResultBuilder.success(new ServicePathOutputBuilder().setResult("Invalid operation")).buildFuture(); - } - - /** - * This method set's wavelength path based on the following steps. - * For each node: - * - *

- * 1. Create Och interface on source termination point. 2. Create Och - * interface on destination termination point. 3. Create cross connect - * between source and destination tps created in step 1 and 2. - * - *

- * Naming convention used for OCH interfaces name : tp-wavenumber Naming - * convention used for cross connect name : src-dest-wavenumber - * - * @param input - * Input parameter from the service-path yang model - * - * @return Result list of all nodes if request successful otherwise specific - * reason of failure. - */ - public ServicePathOutputBuilder setupServicePath(ServicePathInput input) { - - String serviceName = input.getServiceName(); - List nodes = input.getNodes(); - ServicePathOutputBuilder setServBldr = new ServicePathOutputBuilder(); - LOG.info(currentMountedDevice.toString()); - int crossConnectFlag; - for (Nodes n : nodes) { - LOG.info("Starting provisioning for node : {}", n.getNodeId()); - crossConnectFlag = 0; - String nodeId = n.getNodeId(); - // if the node is currently mounted then proceed - if (currentMountedDevice.contains(n.getNodeId())) { - String srcTp = n.getSrcTp(); - String destTp = n.getDestTp(); - - Long waveNumber = input.getWaveNumber(); - String mf = input.getModulationFormat(); - if (destTp.contains("LINE")) { - crossConnectFlag++; - - ModulationFormat modulationFormat = null; - for (int i = 0; i < ModulationFormat.values().length; i++) { - ModulationFormat smodulationFormat = ModulationFormat.forValue(i); - if (smodulationFormat.getName().equals(mf)) { - modulationFormat = smodulationFormat; - } - } - try { - LOG.info("Modulation Format {} configured exists.", modulationFormat.getName()); - } catch (NullPointerException e) { - LOG.error("{} modulation format does not exist.",mf); - } - - if (!new OpenRoadmXponderInterface(db, mps, nodeId, destTp, serviceName) - .createLineInterfaces(waveNumber, R100G.class, modulationFormat)) { - - return setServBldr.setResult("Unable to LINE interface on " + nodeId + " at " + destTp); - } - if (!activateService(nodeId, destTp, mps, true)) { - return setServBldr - .setResult("Unable to activate Equipment State on " + nodeId + " for " + destTp); - } - } - if (srcTp.contains("CLNT")) { - crossConnectFlag++; - if (!new OpenRoadmXponderInterface(db, mps, nodeId, srcTp, serviceName).createClientInterfaces()) { - return setServBldr.setResult("Unable to Client interface on " + nodeId + " at " + srcTp); - } - } - String srcIf; - String dstIf; - if (srcTp.contains("TTP") || srcTp.contains("PP")) { - srcIf = new OpenRoadmOchInterface(db, mps, nodeId, srcTp, serviceName).createInterface(waveNumber); - // if source interface creation was successful - // then proceed otherwise return. - if (srcIf == null) { - LOG.warn("Unable to create OCH interface on {} at {}", nodeId, srcTp); - return setServBldr.setResult("Unable to create OCH interface on " + nodeId + " at " + srcTp); - } - } - if (destTp.contains("TTP") || destTp.contains("PP")) { - dstIf = new OpenRoadmOchInterface(db, mps, nodeId, destTp, serviceName).createInterface(waveNumber); - // if destination interface creation was successful - // then proceed otherwise return. - if (dstIf == null) { - LOG.warn("Unable to create OCH interface on {} at {}", nodeId, destTp); - return setServBldr.setResult("Unable to create OCH interface on " + nodeId + " at " + destTp); - } - } - if (crossConnectFlag < 1) { - LOG.info("Creating cross connect between source :{} destination {} for node {}", srcTp, destTp, - n.getNodeId()); - DataBroker netconfNodeDataBroker = PortMapping.getDeviceDataBroker(nodeId, mps); - String crossConnectName = srcTp + "-" + destTp + "-" + waveNumber; - CrossConnect roadmConnections = new CrossConnect(netconfNodeDataBroker); - if (roadmConnections.postCrossConnect(waveNumber, srcTp, destTp)) { - nodesProvisioned.add(nodeId); - roadmConnections.getConnectionPortTrail(nodeId, mps, waveNumber, srcTp, destTp); - } else { - return setServBldr.setResult("Unable to post Roadm-connection for node " + nodeId); - } - } - } else { - LOG.warn("{} is not mounted on the controller", nodeId); - return setServBldr.setResult(nodeId + " is not mounted on the controller"); - } - } - return setServBldr.setResult("Roadm-connection successfully created for nodes " + nodesProvisioned.toString()); - } - - /** - * This method removes wavelength path based on following steps: For each - * node: - * - *

- * 1. Delete Cross connect between source and destination tps. - * 2. Delete Och interface on source termination point. - * 3. Delete Och interface on destination termination point. - * - *

- * Naming convention used for OCH interfaces name : tp-wavenumber Naming - * convention used for cross connect name : src-dest-wavenumber - * - * @param input - * Input parameter from the service-path yang model - * - * @return Result result of the request. - */ - public ServicePathOutputBuilder deleteServicePath(ServicePathInput input) { - List nodes = input.getNodes(); - ServicePathOutputBuilder delServBldr = new ServicePathOutputBuilder(); - LOG.info(currentMountedDevice.toString()); - for (Nodes n : nodes) { - - String nodeId = n.getNodeId(); - LOG.info("Deleting service setup on node {}", nodeId); - String srcTp = n.getSrcTp(); - String destTp = n.getDestTp(); - Long waveNumber = input.getWaveNumber(); - - // if the node is currently mounted then proceed. - if (currentMountedDevice.contains(nodeId)) { - - if (destTp.contains("LINE")) { - if (!activateService(nodeId, destTp, mps, false)) { - LOG.error("Unable to desactivate Equipment State on {} for {}", nodeId, destTp); - } - if (new OpenRoadmInterfaces(db, mps, nodeId, destTp) - .deleteInterface(destTp + "-ODU") == false) { - LOG.error("Failed to delete interface {}-ODU on {}", destTp, nodeId); - } - if (new OpenRoadmInterfaces(db, mps, nodeId, destTp) - .deleteInterface(destTp + "-OTU") == false) { - LOG.error("Failed to delete interface {}-OTU on {}", destTp, nodeId); - } - if (new OpenRoadmInterfaces(db, mps, nodeId, destTp) - .deleteInterface(destTp + "-" + waveNumber) == false) { - LOG.error("Failed to delete interface {}-{} on {}", destTp, waveNumber, nodeId); - } - } - if (srcTp.contains("CLNT")) { - // Deleting interface on source termination point - if (new OpenRoadmInterfaces(db, mps, nodeId, srcTp) - .deleteInterface(srcTp + "-ETHERNET") == false) { - LOG.error("Failed to delete Ethernet interface on {} on {}", srcTp, nodeId); - } - continue; - } - String connectionNumber = srcTp + "-" + destTp + "-" + waveNumber; - CrossConnect roadmConnection = new CrossConnect(PortMapping.getDeviceDataBroker(nodeId, mps), - connectionNumber); - if (!roadmConnection.deleteCrossConnect()) { - LOG.error("Failed to delete {} on {}", connectionNumber, nodeId); - } - // Deleting interface on source termination point - if (!new OpenRoadmInterfaces(db, mps, nodeId, srcTp) - .deleteInterface(srcTp + "-" + waveNumber.toString())) { - LOG.error("Failed to delete interface {}-{} on {}", srcTp, waveNumber.toString(), nodeId); - } - - // Deleting interface on destination termination point - if (!new OpenRoadmInterfaces(db, mps, nodeId, destTp) - .deleteInterface(destTp + "-" + waveNumber.toString())) { - LOG.error("Failed to delete interface {}-{} on {}", destTp, waveNumber.toString(), nodeId); - } - } else { - LOG.warn("{} is not mounted on the controller", nodeId); - return delServBldr.setResult(nodeId + " is not mounted on the controller"); - } - } - return delServBldr.setResult("Request processed"); - } - - /** - * This method does a post(edit-config) on a given circuit-packs subtree to - * change its equipment-state. - * - * @param nodeId - * Netconf device. - * @param logicalConnPoint - * Logical Connection point resulting from PortMapping to - * retrieve associated circuit-pack. - * @param mps - * Mount point service. - * @param activate - * true to configure the circuit-pack to "NotReservedInuse". - * false to configure the circuit-pack to "NotReservedAvailable". - * @return true/false based on status of operation. - */ - private boolean activateService(String nodeId, String logicalConnPoint, MountPointService mps, boolean activate) { - DataBroker deviceDb = PortMapping.getDeviceDataBroker(nodeId, mps); - String circuitPack = PortMapping.getMapping(nodeId, logicalConnPoint, db).getSupportingCircuitPackName(); - - InstanceIdentifier circuitPackIID = InstanceIdentifier.create(OrgOpenroadmDevice.class) - .child(CircuitPacks.class, new CircuitPacksKey(circuitPack)); - ReadOnlyTransaction readTx = deviceDb.newReadOnlyTransaction(); - // retrieve relevent CircuitPack object - Optional cpObject; - CircuitPacks cp = null; - try { - cpObject = readTx.read(LogicalDatastoreType.CONFIGURATION, circuitPackIID).get(); - if (cpObject.isPresent()) { - cp = cpObject.get(); - } else { - LOG.info("Could not find CircuitPack {} in equipment config datastore for nodeId {}", circuitPack, - nodeId); - return false; - } - - } catch (InterruptedException | ExecutionException ex) { - LOG.error("Issue reading config datastore on node {}", nodeId, ex); - } - CircuitPacksBuilder cpBldr = new CircuitPacksBuilder(cp); - if (activate) { - cpBldr.setEquipmentState(States.NotReservedInuse); - } else { - cpBldr.setEquipmentState(States.NotReservedAvailable); - } - WriteTransaction wt = deviceDb.newWriteOnlyTransaction(); - wt.put(LogicalDatastoreType.CONFIGURATION, circuitPackIID, cpBldr.build()); - try { - wt.submit().get(15, TimeUnit.SECONDS); - LOG.info("Successfully posted Equipment State on circuit pack {} on node {}", circuitPack, nodeId); - return true; - } catch (InterruptedException | ExecutionException | TimeoutException e) { - LOG.warn("Failed to post {} on node {}", circuitPack, nodeId, e); - return false; - } - } -} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererService.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererService.java new file mode 100644 index 000000000..7d2b73a77 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererService.java @@ -0,0 +1,68 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.renderer.provisiondevice; + +import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathOutput; + +public interface DeviceRendererService { + + /** + * This method set's wavelength path based on following steps. + * + *

+ * For each node: + * 1. Create Och interface on source termination point. + * 2. Create Och interface on destination termination point. + * 3. Create cross connect between source and destination tps created in step 1 + * and 2. + * + * Naming convention used for OCH interfaces name : tp-wavenumber Naming + * convention used for cross connect name : src-dest-wavenumber + *

+ * + * @param input + * Input parameter from the service-path yang model + * + * @return Result list of all nodes if request successful otherwise specific + * reason of failure. + */ + ServicePathOutput setupServicePath(ServicePathInput input, ServicePathDirection direction); + + /** + * This method removes wavelength path based on following steps. + * + *

+ * For each node: + * 1. Delete Cross connect between source and destination tps. + * 2. Delete Och interface on source termination point. + * 3. Delete Och interface on destination termination point. + * + * Naming convention used for OCH interfaces name : tp-wavenumber Naming + * convention used for cross connect name : src-dest-wavenumber + *

+ * + * @param input + * Input parameter from the service-path yang model + * + * @return Result result of the request. + */ + ServicePathOutput deleteServicePath(ServicePathInput input); + + /** + * Rollback created interfaces and cross connects specified by input. + * + * @param input Lists of created interfaces and connections per node + * @return Success flag and nodes which failed to rollback + */ + RendererRollbackOutput rendererRollback(RendererRollbackInput input); +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java new file mode 100644 index 000000000..7eb030ed3 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java @@ -0,0 +1,485 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.renderer.provisiondevice; + +import com.google.common.collect.Sets; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.transportpce.common.crossconnect.CrossConnect; +import org.opendaylight.transportpce.common.device.DeviceTransactionManager; +import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException; +import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces; +import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfacesImpl; +import org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory; +import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServiceListTopology; +import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev161014.service.Topology; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.get.connection.port.trail.output.Ports; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.OchAttributes.ModulationFormat; +import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev161014.R100G; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.ServiceList; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.list.Services; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.list.ServicesBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.service.rev161014.service.list.ServicesKey; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.node.interfaces.NodeInterface; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.node.interfaces.NodeInterfaceBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.node.interfaces.NodeInterfaceKey; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.alarmsuppression.rev171102.ServiceNodelist; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.alarmsuppression.rev171102.service.nodelist.NodelistBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.alarmsuppression.rev171102.service.nodelist.NodelistKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.renderer.rollback.output.FailedToRollback; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.renderer.rollback.output.FailedToRollbackBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.renderer.rollback.output.FailedToRollbackKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeviceRendererServiceImpl implements DeviceRendererService { + + private static final Logger LOG = LoggerFactory.getLogger(DeviceRendererServiceImpl.class); + + private final DataBroker dataBroker; + private final DeviceTransactionManager deviceTransactionManager; + private final OpenRoadmInterfaceFactory openRoadmInterfaceFactory; + private final OpenRoadmInterfaces openRoadmInterfaces; + private final CrossConnect crossConnect; + + public DeviceRendererServiceImpl(DataBroker dataBroker, DeviceTransactionManager deviceTransactionManager, + OpenRoadmInterfaceFactory openRoadmInterfaceFactory, OpenRoadmInterfaces openRoadmInterfaces, + CrossConnect crossConnect) { + this.dataBroker = dataBroker; + this.deviceTransactionManager = deviceTransactionManager; + this.openRoadmInterfaceFactory = openRoadmInterfaceFactory; + this.openRoadmInterfaces = openRoadmInterfaces; + this.crossConnect = crossConnect; + } + + @Override + public ServicePathOutput setupServicePath(ServicePathInput input, ServicePathDirection direction) { + List nodes = input.getNodes(); + // Register node for suppressing alarms + if (!alarmSuppressionNodeRegistration(input)) { + LOG.warn("Alarm suppresion node registraion failed!!!!"); + } + + ConcurrentLinkedQueue results = new ConcurrentLinkedQueue<>(); + Set nodeInterfaces = Sets.newConcurrentHashSet(); + Set nodesProvisioned = Sets.newConcurrentHashSet(); + ServiceListTopology topology = new ServiceListTopology(); + AtomicBoolean success = new AtomicBoolean(true); + + ForkJoinPool forkJoinPool = new ForkJoinPool(); + ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> + nodes.parallelStream().forEach(node -> { + String nodeId = node.getNodeId(); + LOG.info("Starting provisioning for node : {}", nodeId); + List createdEthInterfaces = new ArrayList<>(); + List createdOtuInterfaces = new ArrayList<>(); + List createdOduInterfaces = new ArrayList<>(); + List createdOchInterfaces = new ArrayList<>(); + List createdConnections = new ArrayList<>(); + int crossConnectFlag = 0; + + try { + // if the node is currently mounted then proceed + if (this.deviceTransactionManager.isDeviceMounted(nodeId)) { + String srcTp = node.getSrcTp(); + String destTp = node.getDestTp(); + + Long waveNumber = input.getWaveNumber(); + if ((destTp != null) && destTp.contains(OpenRoadmInterfacesImpl.NETWORK_TOKEN)) { + crossConnectFlag++; + // create OpenRoadm Xponder Line Interfaces + String supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface( + nodeId, destTp, waveNumber, R100G.class, ModulationFormat.DpQpsk); + createdOchInterfaces.add(supportingOchInterface); + + String supportingOtuInterface = this.openRoadmInterfaceFactory.createOpenRoadmOtu4Interface( + nodeId, destTp, supportingOchInterface); + createdOtuInterfaces.add(supportingOtuInterface); + + createdOduInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOdu4Interface( + nodeId, destTp,supportingOtuInterface)); + } + if ((srcTp != null) && srcTp.contains(OpenRoadmInterfacesImpl.CLIENT_TOKEN)) { + crossConnectFlag++; + // create OpenRoadm Xponder Client Interfaces + createdEthInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(nodeId, + srcTp)); + + + } + if ((srcTp != null) && srcTp.contains(OpenRoadmInterfacesImpl.NETWORK_TOKEN)) { + crossConnectFlag++; + // create OpenRoadm Xponder Line Interfaces + String supportingOchInterface = this.openRoadmInterfaceFactory.createOpenRoadmOchInterface( + nodeId, srcTp, waveNumber, R100G.class, ModulationFormat.DpQpsk); + createdOchInterfaces.add(supportingOchInterface); + + String supportingOtuInterface = this.openRoadmInterfaceFactory.createOpenRoadmOtu4Interface( + nodeId, srcTp, supportingOchInterface); + createdOtuInterfaces.add(supportingOtuInterface); + + createdOduInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOdu4Interface( + nodeId, srcTp, supportingOtuInterface)); + } + if ((destTp != null) && destTp.contains(OpenRoadmInterfacesImpl.CLIENT_TOKEN)) { + crossConnectFlag++; + // create OpenRoadm Xponder Client Interfaces + createdEthInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmEthInterface(nodeId, + destTp)); + + + } + if ((srcTp != null) && (srcTp.contains(OpenRoadmInterfacesImpl.TTP_TOKEN) + || srcTp.contains(OpenRoadmInterfacesImpl.PP_TOKEN))) { + createdOchInterfaces.add(this.openRoadmInterfaceFactory .createOpenRoadmOchInterface(nodeId, + srcTp, waveNumber)); + } + if ((destTp != null) && (destTp.contains(OpenRoadmInterfacesImpl.TTP_TOKEN) + || destTp.contains(OpenRoadmInterfacesImpl.PP_TOKEN))) { + createdOchInterfaces.add(this.openRoadmInterfaceFactory.createOpenRoadmOchInterface(nodeId, + destTp, waveNumber)); + } + if (crossConnectFlag < 1) { + LOG.info("Creating cross connect between source {} and destination {} for node {}", + srcTp, destTp, nodeId); + Optional connectionNameOpt = this.crossConnect.postCrossConnect(nodeId, waveNumber, + srcTp, destTp); + if (connectionNameOpt.isPresent()) { + nodesProvisioned.add(nodeId); + List ports = this.crossConnect.getConnectionPortTrail(nodeId, waveNumber, srcTp, + destTp); + if (ServicePathDirection.A_TO_Z.equals(direction)) { + topology.updateAtoZTopologyList(ports, nodeId); + } + if (ServicePathDirection.Z_TO_A.equals(direction)) { + topology.updateZtoATopologyList(ports, nodeId); + + } + createdConnections.add(connectionNameOpt.get()); + } else { + processErrorMessage("Unable to post Roadm-connection for node " + nodeId, forkJoinPool, + results); + success.set(false); + } + } + } else { + processErrorMessage(nodeId + " is not mounted on the controller", forkJoinPool, results); + success.set(false); + } + } catch (OpenRoadmInterfaceException ex) { + processErrorMessage("Setup service path failed! Exception:" + ex.toString(), forkJoinPool, results); + success.set(false); + } + + NodeInterfaceBuilder nodeInterfaceBuilder = new NodeInterfaceBuilder(); + nodeInterfaceBuilder.setKey(new NodeInterfaceKey(nodeId)); + nodeInterfaceBuilder.setNodeId(nodeId); + nodeInterfaceBuilder.setConnectionId(createdConnections); + nodeInterfaceBuilder.setEthInterfaceId(createdEthInterfaces); + nodeInterfaceBuilder.setOtuInterfaceId(createdOtuInterfaces); + nodeInterfaceBuilder.setOduInterfaceId(createdOduInterfaces); + nodeInterfaceBuilder.setOchInterfaceId(createdOchInterfaces); + nodeInterfaces.add(nodeInterfaceBuilder.build()); + }) + ); + + try { + forkJoinTask.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Error while setting up service paths!", e); + } + + forkJoinPool.shutdown(); + + if (success.get()) { + results.add("Roadm-connection successfully created for nodes: " + String.join(", ", nodesProvisioned)); + } + ServicePathOutputBuilder setServBldr = new ServicePathOutputBuilder(); + setServBldr.setNodeInterface(new ArrayList<>(nodeInterfaces)); + setServBldr.setSuccess(success.get()); + setServBldr.setResult(String.join("\n", results)); + + //setting topology in the service list data store + try { + setTopologyForService(input.getServiceName(), topology.getTopology()); + } catch (InterruptedException | TimeoutException | ExecutionException e) { + LOG.warn("Failed to write topologies for service {}.", input.getServiceName(), e); + } + + if (!alarmSuppressionNodeRemoval(input.getServiceName())) { + LOG.error("Alarm suppresion node removal failed!!!!"); + } + + return setServBldr.build(); + } + + private ConcurrentLinkedQueue processErrorMessage(String message, ForkJoinPool forkJoinPool, + ConcurrentLinkedQueue messages) { + LOG.warn(message); + messages.add(message); + forkJoinPool.shutdown(); + return messages; + } + + @Override + public ServicePathOutput deleteServicePath(ServicePathInput input) { + List nodes = input.getNodes(); + ServicePathOutputBuilder delServBldr = new ServicePathOutputBuilder(); + + ConcurrentLinkedQueue results = new ConcurrentLinkedQueue<>(); + if (!alarmSuppressionNodeRegistration(input)) { + LOG.warn("Alarm suppresion node registraion failed!!!!"); + } + ForkJoinPool forkJoinPool = new ForkJoinPool(); + ForkJoinTask forkJoinTask = forkJoinPool.submit(() -> + nodes.parallelStream().forEach(node -> { + List interfacesToDelete = new LinkedList<>(); + String nodeId = node.getNodeId(); + LOG.info("Deleting service setup on node {}", nodeId); + String srcTp = node.getSrcTp(); + String destTp = node.getDestTp(); + Long waveNumber = input.getWaveNumber(); + + if ((srcTp == null) || (destTp == null)) { + LOG.error("Source ({}) or destination ({}) termination point is null.", srcTp, destTp); + return; + } + + // if the node is currently mounted then proceed. + if (this.deviceTransactionManager.isDeviceMounted(nodeId)) { + if (destTp.contains(OpenRoadmInterfacesImpl.NETWORK_TOKEN) + || srcTp.contains(OpenRoadmInterfacesImpl.CLIENT_TOKEN)) { + if (destTp.contains(OpenRoadmInterfacesImpl.NETWORK_TOKEN)) { + interfacesToDelete.add(destTp + "-ODU"); + interfacesToDelete.add(destTp + "-OTU"); + interfacesToDelete.add( + this.openRoadmInterfaceFactory.createOpenRoadmOchInterfaceName(destTp, waveNumber)); + } + if (srcTp.contains(OpenRoadmInterfacesImpl.CLIENT_TOKEN)) { + interfacesToDelete.add(srcTp + "-ETHERNET"); + } + } else { + String connectionNumber = srcTp + "-" + destTp + "-" + waveNumber; + if (!this.crossConnect.deleteCrossConnect(nodeId, connectionNumber)) { + LOG.error("Failed to delete cross connect {}", srcTp + "-" + destTp + "-" + waveNumber); + } + interfacesToDelete.add( + this.openRoadmInterfaceFactory.createOpenRoadmOchInterfaceName(srcTp, waveNumber)); + interfacesToDelete.add( + this.openRoadmInterfaceFactory.createOpenRoadmOchInterfaceName(destTp, waveNumber)); + } + } else { + String result = nodeId + " is not mounted on the controller"; + results.add(result); + LOG.warn(result); + forkJoinPool.shutdown(); + return; // TODO should deletion end here? + } + + for (String interfaceId : interfacesToDelete) { + try { + this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId); + } catch (OpenRoadmInterfaceException e) { + String result = String.format("Failed to delete interface %s on node %s!", interfaceId, nodeId); + LOG.error(result, e); + results.add(result); + } + } + }) + ); + + try { + forkJoinTask.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.error("Error while deleting service paths!", e); + } + + forkJoinPool.shutdown(); + if (!alarmSuppressionNodeRemoval(input.getServiceName())) { + LOG.error("Alarm suppresion node removal failed!!!!"); + } + if (results.isEmpty()) { + return delServBldr.setResult("Request processed").build(); + } else { + return delServBldr.setResult(String.join("\n", results)).build(); + } + } + + @Override + public RendererRollbackOutput rendererRollback(RendererRollbackInput input) { + boolean success = true; + List failedToRollbackList = new ArrayList<>(); + for (NodeInterface nodeInterfaces : input.getNodeInterface()) { + List failedInterfaces = new ArrayList<>(); + String nodeId = nodeInterfaces.getNodeId(); + for (String connectionId : nodeInterfaces.getConnectionId()) { + if (this.crossConnect.deleteCrossConnect(nodeId, connectionId)) { + LOG.info("Cross connect {} on node {} successfully deleted.", connectionId, nodeId); + } else { + LOG.error("Failed to delete cross connect {} on node {}!", connectionId, nodeId); + success = false; + failedInterfaces.add(connectionId); + } + } + // Interfaces needs to be in specific order to delete. Order is: + // 1. ODU interfaces + // 2. OTU interfaces + // 3. OCH interfaces + // 4. ETH interfaces + LinkedList interfacesToDelete = new LinkedList<>(); + if (nodeInterfaces.getOduInterfaceId() != null) { + interfacesToDelete.addAll(nodeInterfaces.getOduInterfaceId()); + } + if (nodeInterfaces.getOtuInterfaceId() != null) { + interfacesToDelete.addAll(nodeInterfaces.getOtuInterfaceId()); + } + if (nodeInterfaces.getOchInterfaceId() != null) { + interfacesToDelete.addAll(nodeInterfaces.getOchInterfaceId()); + } + if (nodeInterfaces.getEthInterfaceId() != null) { + interfacesToDelete.addAll(nodeInterfaces.getEthInterfaceId()); + } + + LOG.info("Going to execute rollback on node {}. Interfaces to rollback: {}", nodeId, + String.join(", ", interfacesToDelete)); + + for (String interfaceId : interfacesToDelete) { + try { + this.openRoadmInterfaces.deleteInterface(nodeId, interfaceId); + LOG.info("Interface {} on node {} successfully deleted.", interfaceId, nodeId); + } catch (OpenRoadmInterfaceException e) { + LOG.error("Failed to delete interface {} on node {}!", interfaceId, nodeId); + success = false; + failedInterfaces.add(interfaceId); + } + } + failedToRollbackList.add(new FailedToRollbackBuilder() + .setKey(new FailedToRollbackKey(nodeId)) + .setNodeId(nodeId) + .setInterface(failedInterfaces) + .build() + ); + } + return new RendererRollbackOutputBuilder() + .setSuccess(success) + .setFailedToRollback(failedToRollbackList) + .build(); + } + + private boolean alarmSuppressionNodeRegistration(ServicePathInput input) { + NodelistBuilder nodeListBuilder = new NodelistBuilder(); + nodeListBuilder.setKey(new NodelistKey(input.getServiceName())); + nodeListBuilder.setServiceName(input.getServiceName()); + List nodeList = new ArrayList<>(); + for (Nodes node: input.getNodes()) { + nodeList.add(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns + .yang.alarmsuppression.rev171102.service.nodelist.nodelist.NodesBuilder() + .setNodeId(node.getNodeId()).build()); + } + nodeListBuilder.setNodes(nodeList); + InstanceIdentifier nodeListIID = + InstanceIdentifier.create(ServiceNodelist.class).child(org.opendaylight.yang.gen.v1.urn + .opendaylight.params.xml.ns.yang.alarmsuppression.rev171102.service.nodelist.Nodelist.class, + new NodelistKey(input.getServiceName())); + final WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction(); + writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodeListIID, nodeListBuilder.build()); + Future submit = writeTransaction.submit(); + try { + submit.get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS); + LOG.info("Nodes are register for alarm suppression for service: {}", + input.getServiceName()); + return true; + + } catch (ExecutionException | InterruptedException | TimeoutException e) { + LOG.warn("Failed to alarm suppresslist for service: {}", input.getServiceName(), e); + return false; + } + } + + private boolean alarmSuppressionNodeRemoval(String serviceName) { + InstanceIdentifier nodeListIID = + InstanceIdentifier.create(ServiceNodelist.class).child(org.opendaylight.yang.gen.v1.urn + .opendaylight.params.xml.ns.yang.alarmsuppression.rev171102.service.nodelist.Nodelist.class, + new NodelistKey(serviceName)); + final WriteTransaction writeTransaction = this.dataBroker.newWriteOnlyTransaction(); + writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, nodeListIID); + Future submit = writeTransaction.submit(); + try { + submit.get(Timeouts.DATASTORE_DELETE, TimeUnit.MILLISECONDS); + LOG.info("Nodes are unregister for alarm suppression for service: {}", serviceName); + return true; + + } catch (InterruptedException | TimeoutException | ExecutionException e) { + LOG.warn("Failed to alarm suppresslist for service: {}", serviceName, e); + return false; + } + } + + private void setTopologyForService(String serviceName, Topology topo) + throws InterruptedException, ExecutionException, TimeoutException { + + ServicesBuilder servicesBuilder; + //Get the service from the service list inventory + + ServicesKey serviceKey = new ServicesKey(serviceName); + InstanceIdentifier iid = + InstanceIdentifier.create(ServiceList.class).child(Services.class, serviceKey); + Optional services; + try (ReadOnlyTransaction readTx = this.dataBroker.newReadOnlyTransaction()) { + Future> future = readTx.read(LogicalDatastoreType.OPERATIONAL, + iid); + services = future.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).toJavaUtil(); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + throw e; + } + + if (services.isPresent()) { + servicesBuilder = new ServicesBuilder(services.get()); + } else { + servicesBuilder = new ServicesBuilder(); + servicesBuilder.setKey(serviceKey); + } + servicesBuilder.setTopology(topo); + + WriteTransaction writeTx = this.dataBroker.newWriteOnlyTransaction(); + writeTx.merge(LogicalDatastoreType.OPERATIONAL, iid, servicesBuilder.build()); + writeTx.submit().get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS); + + } +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRenderingResult.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRenderingResult.java new file mode 100644 index 000000000..0fa7d4e72 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRenderingResult.java @@ -0,0 +1,53 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice; + +import java.util.Collections; +import java.util.List; +import org.opendaylight.transportpce.common.OperationResult; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.node.interfaces.NodeInterface; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.Nodes; + +public class DeviceRenderingResult extends OperationResult { + + private final List olmList; + private final List renderedNodeInterfaces; + + private DeviceRenderingResult(boolean success, String message, List olmList, + List renderedNodeInterfaces) { + super(success, message); + if (olmList != null) { + this.olmList = Collections.unmodifiableList(olmList); + } else { + this.olmList = Collections.emptyList(); + } + + if (renderedNodeInterfaces != null) { + this.renderedNodeInterfaces = Collections.unmodifiableList(renderedNodeInterfaces); + } else { + this.renderedNodeInterfaces = Collections.emptyList(); + } + } + + public List getOlmList() { + return this.olmList; + } + + public List getRenderedNodeInterfaces() { + return this.renderedNodeInterfaces; + } + + public static DeviceRenderingResult failed(String message) { + return new DeviceRenderingResult(false, message, null, null); + } + + public static DeviceRenderingResult ok(List olmList, List renderedNodeInterfaces) { + return new DeviceRenderingResult(true, "", olmList, renderedNodeInterfaces); + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/OLMRenderingResult.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/OLMRenderingResult.java new file mode 100644 index 000000000..ae8ca9ee1 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/OLMRenderingResult.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice; + +import org.opendaylight.transportpce.common.OperationResult; + +public class OLMRenderingResult extends OperationResult { + + private OLMRenderingResult(boolean success, String message) { + super(success, message); + } + + public static OLMRenderingResult failed(String message) { + return new OLMRenderingResult(false, message); + } + + public static OLMRenderingResult ok() { + return new OLMRenderingResult(true, ""); + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperations.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperations.java new file mode 100644 index 000000000..d04423770 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperations.java @@ -0,0 +1,21 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice; + +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestOutput; + +public interface RendererServiceOperations { + + ServiceImplementationRequestOutput serviceImplementation(ServiceImplementationRequestInput input); + + ServiceDeleteOutput serviceDelete(ServiceDeleteInput input); + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java new file mode 100644 index 000000000..7c3f101dc --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java @@ -0,0 +1,361 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.transportpce.common.ResponseCodes; +import org.opendaylight.transportpce.common.Timeouts; +import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfacesImpl; +import org.opendaylight.transportpce.renderer.ModelMappingUtils; +import org.opendaylight.transportpce.renderer.NetworkModelWavelengthService; +import org.opendaylight.transportpce.renderer.ServicePathInputData; +import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection; +import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingRollbackTask; +import org.opendaylight.transportpce.renderer.provisiondevice.tasks.DeviceRenderingTask; +import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupRollbackTask; +import org.opendaylight.transportpce.renderer.provisiondevice.tasks.OlmPowerSetupTask; +import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor; +import org.opendaylight.yang.gen.v1.http.org.openroadm.pm.types.rev161014.PmGranularity; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.service.types.rev170426.service.path.PathDescription; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServicePathList; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.service.path.list.ServicePaths; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.service.path.list.ServicePathsKey; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.get.pm.input.ResourceIdentifierBuilder; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.GetPmOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.OlmService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm.output.Measurements; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class RendererServiceOperationsImpl implements RendererServiceOperations { + + private static final Logger LOG = LoggerFactory.getLogger(RendererServiceOperationsImpl.class); + private static final String FAILED = "Failed"; + private static final String OPERATION_FAILED = "Operation Failed"; + private static final String OPERATION_SUCCESSFUL = "Operation Successful"; + private static final int NUMBER_OF_THREADS = 4; + + private final DeviceRendererService deviceRenderer; + private final OlmService olmService; + private final DataBroker dataBroker; + private ListeningExecutorService executor; + private NetworkModelWavelengthService networkModelWavelengthService; + + public RendererServiceOperationsImpl(DeviceRendererService deviceRenderer, OlmService olmService, + DataBroker dataBroker, NetworkModelWavelengthService networkModelWavelengthService) { + this.deviceRenderer = deviceRenderer; + this.olmService = olmService; + this.dataBroker = dataBroker; + this.networkModelWavelengthService = networkModelWavelengthService; + this.executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(NUMBER_OF_THREADS)); + } + + @Override + public ServiceImplementationRequestOutput serviceImplementation(ServiceImplementationRequestInput input) { + LOG.info("Calling service impl request {} {}", input.getServiceName()); + RollbackProcessor rollbackProcessor = new RollbackProcessor(); + + ServicePathInputData servicePathInputDataAtoZ + = ModelMappingUtils.rendererCreateServiceInputAToZ(input.getServiceName(), + input.getPathDescription()); + ServicePathInputData servicePathInputDataZtoA + = ModelMappingUtils.rendererCreateServiceInputZToA(input.getServiceName(), + input.getPathDescription()); + List renderingResults = deviceRendering(rollbackProcessor, servicePathInputDataAtoZ, + servicePathInputDataZtoA); + if (rollbackProcessor.rollbackAllIfNecessary() > 0) { + return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); + } + + ServicePowerSetupInput olmPowerSetupInputAtoZ = ModelMappingUtils.createServicePowerSetupInput( + renderingResults.get(0).getOlmList(), input); + ServicePowerSetupInput olmPowerSetupInputZtoA = ModelMappingUtils.createServicePowerSetupInput( + renderingResults.get(1).getOlmList(), input); + olmPowerSetup(rollbackProcessor, olmPowerSetupInputAtoZ, olmPowerSetupInputZtoA); + if (rollbackProcessor.rollbackAllIfNecessary() > 0) { + return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); + } + + // run service activation test twice - once on source node and once on destination node + List nodes = servicePathInputDataAtoZ.getServicePathInput().getNodes(); + Nodes sourceNode = nodes.get(0); + Nodes destNode = nodes.get(nodes.size() - 1); + + String srcNetworkTp; + String dstNetowrkTp; + + if (sourceNode.getDestTp().contains(OpenRoadmInterfacesImpl.NETWORK_TOKEN)) { + srcNetworkTp = sourceNode.getDestTp(); + } else { + srcNetworkTp = sourceNode.getSrcTp(); + } + if (destNode.getDestTp().contains(OpenRoadmInterfacesImpl.NETWORK_TOKEN)) { + dstNetowrkTp = destNode.getDestTp(); + } else { + dstNetowrkTp = destNode.getSrcTp(); + } + + if (!isServiceActivated(sourceNode.getNodeId(), srcNetworkTp) + || !isServiceActivated(destNode.getNodeId(), dstNetowrkTp)) { + rollbackProcessor.rollbackAll(); + return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); + } + + //If Service activation is success update Network ModelMappingUtils + this.networkModelWavelengthService.useWavelengths(input.getPathDescription()); + + return ModelMappingUtils.createServiceImplResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL); + } + + @Override + public ServiceDeleteOutput serviceDelete(ServiceDeleteInput input) { + String serviceName = input.getServiceName(); + + // Obtain path description + Optional pathDescriptionOpt = getPathDescriptionFromDatastore(serviceName); + PathDescription pathDescription; + if (pathDescriptionOpt.isPresent()) { + pathDescription = pathDescriptionOpt.get(); + } else { + LOG.error("Unable to get path description for service {}!", serviceName); + return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); + } + + ServicePathInputData servicePathInputDataAtoZ + = ModelMappingUtils.rendererCreateServiceInputAToZ(serviceName, pathDescription); + ServicePathInputData servicePathInputDataZtoA + = ModelMappingUtils.rendererCreateServiceInputZToA(serviceName, pathDescription); + + // OLM turn down power + try { + LOG.debug("Turning down power on A-to-Z path"); + ServicePowerTurndownOutput atozPowerTurndownOutput = olmPowerTurndown(servicePathInputDataAtoZ); + // TODO add some flag rather than string + if (FAILED.equals(atozPowerTurndownOutput.getResult())) { + LOG.error("Service power turndown failed on A-to-Z path for service {}!", serviceName); + return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); + } + + LOG.debug("Turning down power on Z-to-A path"); + ServicePowerTurndownOutput ztoaPowerTurndownOutput = olmPowerTurndown(servicePathInputDataZtoA); + // TODO add some flag rather than string + if (FAILED.equals(ztoaPowerTurndownOutput.getResult())) { + LOG.error("Service power turndown failed on Z-to-A path for service {}!", serviceName); + return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); + } + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.error("Error while turning down power!", e); + return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_FAILED, OPERATION_FAILED); + } + + // delete service path with renderer + LOG.debug("Deleting service path via renderer"); + this.deviceRenderer.deleteServicePath(servicePathInputDataAtoZ.getServicePathInput()); + this.deviceRenderer.deleteServicePath(servicePathInputDataZtoA.getServicePathInput()); + + this.networkModelWavelengthService.freeWavelengths(pathDescription); + + return ModelMappingUtils.createServiceDeleteResponse(ResponseCodes.RESPONSE_OK, OPERATION_SUCCESSFUL); + } + + private ServicePowerTurndownOutput olmPowerTurndown(ServicePathInputData servicePathInputData) + throws InterruptedException, ExecutionException, TimeoutException { + LOG.debug("Turning down power on A-to-Z path"); + Future> powerTurndownFuture = this.olmService.servicePowerTurndown( + new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build()); + return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult(); + } + + private Optional getPathDescriptionFromDatastore(String serviceName) { + InstanceIdentifier pathDescriptionIID = InstanceIdentifier.create(ServicePathList.class) + .child(ServicePaths.class, new ServicePathsKey(serviceName)).child(PathDescription.class); + ReadOnlyTransaction pathDescReadTx = this.dataBroker.newReadOnlyTransaction(); + try { + LOG.debug("Getting path description for service {}", serviceName); + return pathDescReadTx.read(LogicalDatastoreType.OPERATIONAL, pathDescriptionIID) + .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("Exception while getting path description from datastore {} for service {}!", pathDescriptionIID, + serviceName, e); + return Optional.absent(); + } + } + + private List deviceRendering(RollbackProcessor rollbackProcessor, + ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) { + LOG.info("Rendering devices A-Z"); + ListenableFuture atozrenderingFuture = + this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ, + ServicePathDirection.A_TO_Z)); + + LOG.info("Rendering devices Z-A"); + ListenableFuture ztoarenderingFuture = + this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA, + ServicePathDirection.Z_TO_A)); + ListenableFuture> renderingCombinedFuture = + Futures.allAsList(atozrenderingFuture, ztoarenderingFuture); + + List renderingResults = new ArrayList<>(2); + try { + LOG.info("Waiting for A-Z and Z-A device renderers ..."); + renderingResults = renderingCombinedFuture.get(Timeouts.RENDERING_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("Device rendering was not successful! Rendering will be rolled back.", e); + //FIXME we can't do rollback here, because we don't have rendering results. + //rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask", true)); + //rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask", true)); + return renderingResults; + } + + rollbackProcessor.addTask(new DeviceRenderingRollbackTask("AtoZDeviceTask", + ! renderingResults.get(0).isSuccess(), renderingResults.get(0).getRenderedNodeInterfaces(), + this.deviceRenderer)); + rollbackProcessor.addTask(new DeviceRenderingRollbackTask("ZtoADeviceTask", + ! renderingResults.get(1).isSuccess(), renderingResults.get(1).getRenderedNodeInterfaces(), + this.deviceRenderer)); + return renderingResults; + } + + private void olmPowerSetup(RollbackProcessor rollbackProcessor, ServicePowerSetupInput powerSetupInputAtoZ, + ServicePowerSetupInput powerSetupInputZtoA) { + LOG.info("Olm power setup A-Z"); + ListenableFuture olmPowerSetupFutureAtoZ + = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ)); + + LOG.info("OLM power setup Z-A"); + ListenableFuture olmPowerSetupFutureZtoA + = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA)); + ListenableFuture> olmFutures = + Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA); + + List olmResults; + try { + LOG.info("Waiting for A-Z and Z-A OLM power setup ..."); + olmResults = olmFutures.get(Timeouts.OLM_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.warn("OLM power setup was not successful! Rendering and OLM will be rolled back.", e); + rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", true, + this.olmService, powerSetupInputAtoZ)); + rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", true, + this.olmService, powerSetupInputZtoA)); + return; + } + + rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("AtoZOLMTask", ! olmResults.get(0).isSuccess(), + this.olmService, powerSetupInputAtoZ)); + rollbackProcessor.addTask(new OlmPowerSetupRollbackTask("ZtoAOLMTask", ! olmResults.get(1).isSuccess(), + this.olmService, powerSetupInputZtoA)); + } + + private boolean isServiceActivated(String nodeId, String tpId) { + LOG.info("Starting service activation test on node {} and tp {}", nodeId, tpId); + for (int i = 0; i < 3; i++) { + List measurements = getMeasurements(nodeId, tpId); + if ((measurements != null) && verifyPreFecBer(measurements)) { + return true; + } else if (measurements == null) { + LOG.warn("Device {} is not reporting PreFEC on TP: {}", nodeId, tpId); + return true; + } else { + try { + Thread.sleep(Timeouts.SERVICE_ACTIVATION_TEST_RETRY_TIME); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + LOG.error("Service activation test failed on node {} and termination point {}!", nodeId, tpId); + return false; + } + + private List getMeasurements(String nodeId, String tp) { + GetPmInputBuilder getPmIpBldr = new GetPmInputBuilder(); + getPmIpBldr.setNodeId(nodeId); + getPmIpBldr.setGranularity(PmGranularity._15min); + ResourceIdentifierBuilder rsrcBldr = new ResourceIdentifierBuilder(); + rsrcBldr.setResourceName(tp + "-OTU"); + getPmIpBldr.setResourceIdentifier(rsrcBldr.build()); + getPmIpBldr.setResourceType(ResourceTypeEnum.Interface); + + try { + Future> getPmFuture = this.olmService.getPm(getPmIpBldr.build()); + RpcResult getPmRpcResult = getPmFuture.get(); + GetPmOutput getPmOutput = getPmRpcResult.getResult(); + if ((getPmOutput != null) && (getPmOutput.getNodeId() != null)) { + LOG.info("successfully finished calling OLM's get PM"); + return getPmOutput.getMeasurements(); // may return null + + } else { + LOG.warn("OLM's get PM failed for node {} and tp {}", nodeId, tp); + } + + } catch (ExecutionException | InterruptedException e) { + LOG.warn("Error occurred while getting PM for node {} and tp {}", nodeId, tp, e); + } + return null; + } + + + private boolean verifyPreFecBer(List measurements) { + double preFecCorrectedErrors = Double.MIN_VALUE; + double fecUncorrectableBlocks = Double.MIN_VALUE; + + for (Measurements measurement : measurements) { + if (measurement.getPmparameterName().equals("preFECCorrectedErrors")) { + preFecCorrectedErrors = Double.parseDouble(measurement.getPmparameterValue()); + } + if (measurement.getPmparameterName().equals("FECUncorrectableBlocks")) { + fecUncorrectableBlocks = Double.parseDouble(measurement.getPmparameterValue()); + } + } + + LOG.info("Measurements: preFECCorrectedErrors = {}; FECUncorrectableBlocks = {}", preFecCorrectedErrors, + fecUncorrectableBlocks); + + if (fecUncorrectableBlocks > Double.MIN_VALUE) { + LOG.error("Data has uncorrectable errors, BER test failed"); + return false; + } else { + double numOfBitsPerSecond = 112000000000d; + double threshold = 0.00002d; + double result = preFecCorrectedErrors / numOfBitsPerSecond; + LOG.info("PreFEC value is {}", Double.toString(result)); + return result <= threshold; + } + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/servicepath/ServiceListTopology.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/servicepath/ServiceListTopology.java new file mode 100644 index 000000000..6ef18f73a --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/servicepath/ServiceListTopology.java @@ -0,0 +1,164 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice.servicepath; + +import java.util.ArrayList; +import java.util.List; + +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev161014.service.Topology; +import org.opendaylight.yang.gen.v1.http.org.openroadm.common.service.types.rev161014.service.TopologyBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.get.connection.port.trail.output.Ports; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.DeviceBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.ResourceBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.ResourceTypeBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource.port.PortBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.resource.types.rev161014.ResourceTypeEnum; +import org.opendaylight.yang.gen.v1.http.org.openroadm.topology.rev161014.Hop.HopType; +import org.opendaylight.yang.gen.v1.http.org.openroadm.topology.rev161014.topology.AToZ; +import org.opendaylight.yang.gen.v1.http.org.openroadm.topology.rev161014.topology.AToZBuilder; +import org.opendaylight.yang.gen.v1.http.org.openroadm.topology.rev161014.topology.ZToA; +import org.opendaylight.yang.gen.v1.http.org.openroadm.topology.rev161014.topology.ZToABuilder; + +public class ServiceListTopology { + + + private List a2zTopologyList; + private List z2aTopologyList; + private TopologyBuilder serviceTopology; + + public ServiceListTopology() { + + this.a2zTopologyList = new ArrayList<>(); + this.z2aTopologyList = new ArrayList<>(); + this.serviceTopology = new TopologyBuilder(); + + } + + public void updateAtoZTopologyList(List ports, String nodeId) { + + String circuitPackName = ""; + String portName = ""; + + int id = this.a2zTopologyList.size(); + + DeviceBuilder deviceBldr = new DeviceBuilder(); + deviceBldr.setNodeId(nodeId); + + + for (Ports port : ports) { + + id = id + 1; + + //Get circuitpack name + circuitPackName = port.getCircuitPackName(); + + //Get port name + portName = port.getPortName().toString(); + + AToZBuilder a2zBldr = new AToZBuilder(); + + //Set Resource Id + a2zBldr.setId(Integer.toString(id)); + + //Set device Node-id + a2zBldr.setDevice(deviceBldr.build()); + + //Set hop type to internal + a2zBldr.setHopType(HopType.NodeInternal); + + //Set Resource Type to port + ResourceTypeBuilder rsrcTypeBldr = new ResourceTypeBuilder(); + rsrcTypeBldr.setType(ResourceTypeEnum.Port); + a2zBldr.setResourceType(rsrcTypeBldr.build()); + + //building port resource + PortBuilder portBldr = new PortBuilder(); + portBldr.setCircuitPackName(circuitPackName); + portBldr.setPortName(portName); + org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource + .PortBuilder portCase = + new org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource + .PortBuilder(); + portCase.setPort(portBldr.build()); + ResourceBuilder rsrcBldr = new ResourceBuilder(); + rsrcBldr.setResource(portCase.build()); + a2zBldr.setResource(rsrcBldr.build()); + + //Add port resource to the list + this.a2zTopologyList.add(a2zBldr.build()); + + } + + //update Topology + this.serviceTopology.setAToZ(this.a2zTopologyList); + + } + + public void updateZtoATopologyList(List ports, String nodeId) { + + String circuitPackName = ""; + String portName = ""; + + int id = this.a2zTopologyList.size(); + + DeviceBuilder deviceBldr = new DeviceBuilder(); + deviceBldr.setNodeId(nodeId); + + for (Ports port : ports) { + + id = id + 1; + + //Get circuitpack name + circuitPackName = port.getCircuitPackName(); + + //Get port name + portName = port.getPortName().toString(); + + ZToABuilder z2aBldr = new ZToABuilder(); + + //Set Resource Id + z2aBldr.setId(Integer.toString(id)); + + //Set device Node-id + z2aBldr.setDevice(deviceBldr.build()); + + //Set hop type to internal + z2aBldr.setHopType(HopType.NodeInternal); + + //Set Resource Type to port + ResourceTypeBuilder rsrcTypeBldr = new ResourceTypeBuilder(); + rsrcTypeBldr.setType(ResourceTypeEnum.Port); + z2aBldr.setResourceType(rsrcTypeBldr.build()); + + //building port resource + PortBuilder portBldr = new PortBuilder(); + portBldr.setCircuitPackName(circuitPackName); + portBldr.setPortName(portName); + org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource + .PortBuilder portCase = + new org.opendaylight.yang.gen.v1.http.org.openroadm.resource.rev161014.resource.resource.resource + .PortBuilder(); + portCase.setPort(portBldr.build()); + ResourceBuilder rsrcBldr = new ResourceBuilder(); + rsrcBldr.setResource(portCase.build()); + z2aBldr.setResource(rsrcBldr.build()); + + //Add port resource to the list + this.z2aTopologyList.add(z2aBldr.build()); + + } + + } + + public Topology getTopology() { + this.serviceTopology.setAToZ(this.a2zTopologyList); + this.serviceTopology.setZToA(this.z2aTopologyList); + return this.serviceTopology.build(); + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/servicepath/ServicePathDirection.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/servicepath/ServicePathDirection.java new file mode 100644 index 000000000..8e1abe4a8 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/servicepath/ServicePathDirection.java @@ -0,0 +1,14 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.renderer.provisiondevice.servicepath; + +public enum ServicePathDirection { + A_TO_Z, + Z_TO_A +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/DeviceRenderingRollbackTask.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/DeviceRenderingRollbackTask.java new file mode 100644 index 000000000..01bf58cb3 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/DeviceRenderingRollbackTask.java @@ -0,0 +1,65 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice.tasks; + +import java.util.ArrayList; +import java.util.List; +import org.opendaylight.transportpce.renderer.provisiondevice.DeviceRendererService; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.node.interfaces.NodeInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.renderer.rollback.output.FailedToRollback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeviceRenderingRollbackTask extends RollbackTask { + + private static final Logger LOG = LoggerFactory.getLogger(DeviceRenderingRollbackTask.class); + private final boolean isRollbackNecessary; + private final DeviceRendererService rendererService; + private final List renderedInterfaces; + + public DeviceRenderingRollbackTask(String id, boolean isRollbackNecessary, List renderedInterfaces, + DeviceRendererService rendererService) { + super(id); + this.isRollbackNecessary = isRollbackNecessary; + this.rendererService = rendererService; + this.renderedInterfaces = renderedInterfaces; + } + + @Override + public boolean isRollbackNecessary() { + return isRollbackNecessary; + } + + @Override + public Void call() throws Exception { + RendererRollbackInput rollbackInput = new RendererRollbackInputBuilder() + .setNodeInterface(this.renderedInterfaces) + .build(); + RendererRollbackOutput rollbackOutput = this.rendererService.rendererRollback(rollbackInput); + if (! rollbackOutput.isSuccess()) { + LOG.warn("Device rendering rollback of {} was not successful! Failed rollback on {}.", this.getId(), + createErrorMessage(rollbackOutput.getFailedToRollback())); + } else { + LOG.info("Device rollback of {} successful.", this.getId()); + } + return null; + } + + private String createErrorMessage(List failedRollbacks) { + List failedRollbackNodes = new ArrayList<>(); + failedRollbacks.forEach(failedRollback -> { + String nodeId = failedRollback.getNodeId(); + failedRollbackNodes.add(nodeId + ": " + String.join(", ", failedRollback.getInterface())); + }); + return String.join(System.lineSeparator(), failedRollbackNodes); + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/DeviceRenderingTask.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/DeviceRenderingTask.java new file mode 100644 index 000000000..abe78185e --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/DeviceRenderingTask.java @@ -0,0 +1,50 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice.tasks; + +import java.util.List; +import java.util.concurrent.Callable; + +import org.opendaylight.transportpce.renderer.ServicePathInputData; +import org.opendaylight.transportpce.renderer.provisiondevice.DeviceRendererService; +import org.opendaylight.transportpce.renderer.provisiondevice.DeviceRenderingResult; +import org.opendaylight.transportpce.renderer.provisiondevice.servicepath.ServicePathDirection; +import org.opendaylight.yang.gen.v1.http.org.transportpce.common.types.rev170907.olm.renderer.input.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathOutput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeviceRenderingTask implements Callable { + + private static final Logger LOG = LoggerFactory.getLogger(DeviceRenderingTask.class); + + private final DeviceRendererService deviceRenderer; + private final ServicePathInputData servicePathInputData; + private final ServicePathDirection direction; + + public DeviceRenderingTask(DeviceRendererService deviceRenderer, ServicePathInputData servicePathInputData, + ServicePathDirection direction) { + this.deviceRenderer = deviceRenderer; + this.servicePathInputData = servicePathInputData; + this.direction = direction; + } + + @Override + public DeviceRenderingResult call() throws Exception { + ServicePathOutput output = this.deviceRenderer.setupServicePath(this.servicePathInputData.getServicePathInput(), + this.direction); + if (! output.isSuccess()) { + LOG.warn("Device rendering not successfully finished."); + return DeviceRenderingResult.failed("Operation Failed"); + } + List olmList = this.servicePathInputData.getNodeLists().getOlmList(); + LOG.info("Device rendering finished successfully."); + return DeviceRenderingResult.ok(olmList, output.getNodeInterface()); + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/OlmPowerSetupRollbackTask.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/OlmPowerSetupRollbackTask.java new file mode 100644 index 000000000..8b1027ccf --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/OlmPowerSetupRollbackTask.java @@ -0,0 +1,59 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice.tasks; + +import java.util.concurrent.Future; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.OlmService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerTurndownOutput; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OlmPowerSetupRollbackTask extends RollbackTask { + + private static final Logger LOG = LoggerFactory.getLogger(OlmPowerSetupRollbackTask.class); + private static final String FAILED = "Failed"; + private final boolean isRollbackNecessary; + private final OlmService olmService; + private final ServicePowerSetupInput powerSetupInput; + + public OlmPowerSetupRollbackTask(String id, boolean isRollbackNecessary, OlmService olmService, + ServicePowerSetupInput powerSetupInput) { + super(id); + this.isRollbackNecessary = isRollbackNecessary; + this.olmService = olmService; + this.powerSetupInput = powerSetupInput; + } + + @Override + public boolean isRollbackNecessary() { + return isRollbackNecessary; + } + + @Override + public Void call() throws Exception { + ServicePowerTurndownInput powerTurndownInput = new ServicePowerTurndownInputBuilder() + .setNodes(this.powerSetupInput.getNodes()) + .setServiceName(this.powerSetupInput.getServiceName()) + .setWaveNumber(this.powerSetupInput.getWaveNumber()) + .build(); + + Future> powerTurndownResultFuture = + this.olmService.servicePowerTurndown(powerTurndownInput); + RpcResult powerTurndownResult = powerTurndownResultFuture.get(); + if (FAILED.equals(powerTurndownResult.getResult().getResult())) { + LOG.warn("Olmp power setup rollback for {} was not successful!", this.getId()); + } else { + LOG.info("Olm power setup rollback for {} was successful."); + } + return null; + } +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/OlmPowerSetupTask.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/OlmPowerSetupTask.java new file mode 100644 index 000000000..aaf54a9a7 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/OlmPowerSetupTask.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice.tasks; + +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +import org.opendaylight.transportpce.renderer.provisiondevice.OLMRenderingResult; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.OlmService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.ServicePowerSetupOutput; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OlmPowerSetupTask implements Callable { + + private static final Logger LOG = LoggerFactory.getLogger(OlmPowerSetupTask.class); + + private final OlmService olmService; + private final ServicePowerSetupInput input; + + public OlmPowerSetupTask(OlmService olmService, ServicePowerSetupInput input) { + this.olmService = olmService; + this.input = input; + } + + @Override + public OLMRenderingResult call() throws Exception { + Future> fr = this.olmService.servicePowerSetup(this.input); + RpcResult result = fr.get(); + if (result == null) { + LOG.warn("Result is NULL"); + return OLMRenderingResult.failed("Operation Failed"); + } + + LOG.debug("Result: {}", result.getResult()); + if (result.isSuccessful()) { + LOG.info("OLM power setup finished successfully"); + return OLMRenderingResult.ok(); + } else { + LOG.warn("OLM power setup not successfully finished"); + return OLMRenderingResult.failed("Operation Failed"); + } + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/RollbackProcessor.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/RollbackProcessor.java new file mode 100644 index 000000000..709fc170a --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/RollbackProcessor.java @@ -0,0 +1,91 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice.tasks; + +import java.util.Deque; +import java.util.LinkedList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class collects tasks for later rollback. + * This implementation is not thread safe, it must be called from single orchestration thread. + * Rollback order is: last added task is rolled back first. + * After rollback, each task is removed from rollback processor. + * All rollback tasks are executed in single thread. + */ +public class RollbackProcessor { + + private static final Logger LOG = LoggerFactory.getLogger(RollbackProcessor.class); + + private final Deque tasks; + + public RollbackProcessor() { + this.tasks = new LinkedList<>(); + } + + /** + * Add task to the rollback processor. + * @param task the task to add + */ + public void addTask(RollbackTask task) { + this.tasks.add(task); + } + + /** + * Check if any previously added task requires rollback. + * Rollback is necessary if just single task requires rollback. + * @return + * true if any of added tasks requires rollback. false if none of added tasks requires rollback. + */ + public boolean isRollbackNecessary() { + for (RollbackTask task: this.tasks) { + if (task.isRollbackNecessary()) { + return true; + } + } + return false; + } + + /** + * Rollback all tasks previously added to this processor. + * It does not matter if any of the tasks requires rollback. + * All previously added tasks will be rolled back and removed from this processor. + * @return + * number of tasks rolled back + */ + public int rollbackAll() { + int rollbackCounter = 0; + while (this.tasks.size() > 0) { + RollbackTask task = this.tasks.pollLast(); + rollbackCounter++; + try { + LOG.info("rolling back: {}", task.getId()); + task.call(); + } catch (Exception e) { + LOG.error("ERROR: Rollback task {} has failed", task.getId(), e); + } + } + return rollbackCounter; + } + + /** + * Rollback all tasks in case any task has failed. + * If rollback is necessary, all previously added tasks will be rolled back and removed from this processor. + * @return + * number of tasks rolled back + */ + public int rollbackAllIfNecessary() { + if (!isRollbackNecessary()) { + return 0; + } + return rollbackAll(); + } + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/RollbackTask.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/RollbackTask.java new file mode 100644 index 000000000..72e97a26d --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/RollbackTask.java @@ -0,0 +1,43 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.provisiondevice.tasks; + +import java.util.concurrent.Callable; + +public abstract class RollbackTask implements Callable { + + private final String id; + + public RollbackTask(String id) { + this.id = id; + } + + public String getId() { + return this.id; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if ((object == null) || (getClass() != object.getClass())) { + return false; + } + RollbackTask that = (RollbackTask) object; + return this.id.equals(that.id); + } + + @Override + public int hashCode() { + return this.id.hashCode(); + } + + public abstract boolean isRollbackNecessary(); + +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/rpcs/DeviceRendererRPCImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/rpcs/DeviceRendererRPCImpl.java new file mode 100644 index 000000000..f5c35496f --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/rpcs/DeviceRendererRPCImpl.java @@ -0,0 +1,80 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.transportpce.renderer.rpcs; + +import java.util.concurrent.Future; + +import org.opendaylight.transportpce.renderer.provisiondevice.DeviceRendererService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererRollbackOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.RendererService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.renderer.rev170228.ServicePathOutputBuilder; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeviceRendererRPCImpl implements RendererService { + + private static final Logger LOG = LoggerFactory.getLogger(DeviceRendererRPCImpl.class); + private DeviceRendererService deviceRenderer; + + public DeviceRendererRPCImpl(DeviceRendererService deviceRenderer) { + this.deviceRenderer = deviceRenderer; + } + + /** + * This method is the implementation of the 'service-path' RESTCONF service, + * which is one of the external APIs into the renderer application. The + * service provides two functions: + * + *

+ * 1. Create This operation results in provisioning the device for a given + * wavelength and a list of nodes with each node listing its termination + * points. + * + *

+ * 2. Delete This operation results in de-provisioning the device for a + * given wavelength and a list of nodes with each node listing its + * termination points. + * + *

+ * The signature for this method was generated by yang tools from the + * renderer API model. + * + * @param input + * Input parameter from the service-path yang model + * + * @return Result of the request + */ + @Override + public Future> servicePath(ServicePathInput input) { + if (input.getOperation().getIntValue() == 1) { + LOG.info("Create operation request received"); + return RpcResultBuilder.success(deviceRenderer.setupServicePath(input, null)).buildFuture(); + } else if (input.getOperation().getIntValue() == 2) { + LOG.info("Delete operation request received"); + return RpcResultBuilder.success(deviceRenderer.deleteServicePath(input)).buildFuture(); + } + return RpcResultBuilder.success(new ServicePathOutputBuilder().setResult("Invalid operation")).buildFuture(); + } + + /** + * Rollback created interfaces and cross connects specified by input. + * + * @param input Lists of created interfaces and connections per node + * @return Success flag and nodes which failed to rollback + */ + @Override + public Future> rendererRollback(RendererRollbackInput input) { + return RpcResultBuilder.success(deviceRenderer.rendererRollback(input)).buildFuture(); + } +} diff --git a/renderer/src/main/java/org/opendaylight/transportpce/renderer/rpcs/TransportPCEServicePathRPCImpl.java b/renderer/src/main/java/org/opendaylight/transportpce/renderer/rpcs/TransportPCEServicePathRPCImpl.java new file mode 100644 index 000000000..4b3ec1074 --- /dev/null +++ b/renderer/src/main/java/org/opendaylight/transportpce/renderer/rpcs/TransportPCEServicePathRPCImpl.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer.rpcs; + +import java.util.concurrent.Future; + +import org.opendaylight.transportpce.renderer.ModelMappingUtils; +import org.opendaylight.transportpce.renderer.provisiondevice.RendererServiceOperations; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.CancelResourceReserveInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.CancelResourceReserveOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.PathComputationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.PathComputationRequestOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceDeleteOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestInput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.ServiceImplementationRequestOutput; +import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.servicepath.rev170426.TransportpceServicepathService; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TransportPCEServicePathRPCImpl implements TransportpceServicepathService { + + private static final Logger LOG = LoggerFactory.getLogger(TransportPCEServicePathRPCImpl.class); + + private final RendererServiceOperations rendererServiceOperations; + + public TransportPCEServicePathRPCImpl(RendererServiceOperations rendererServiceOperations) { + this.rendererServiceOperations = rendererServiceOperations; + } + + @Override + public Future> cancelResourceReserve(CancelResourceReserveInput input) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Future> serviceDelete(ServiceDeleteInput input) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Future> serviceImplementationRequest( + ServiceImplementationRequestInput input) { + String serviceName = input.getServiceName(); + LOG.info("Calling RPC service impl request {} {}", serviceName); + return ModelMappingUtils.createRpcResponse(rendererServiceOperations.serviceImplementation(input)); + } + + @Override + public Future> pathComputationRequest(PathComputationRequestInput input) { + // TODO Auto-generated method stub + return null; + } + +} + diff --git a/renderer/src/main/resources/org/opendaylight/blueprint/renderer-blueprint.xml b/renderer/src/main/resources/org/opendaylight/blueprint/renderer-blueprint.xml index 97260f5f9..f5d667642 100644 --- a/renderer/src/main/resources/org/opendaylight/blueprint/renderer-blueprint.xml +++ b/renderer/src/main/resources/org/opendaylight/blueprint/renderer-blueprint.xml @@ -11,19 +11,62 @@ and is available at http://www.eclipse.org/legal/epl-v10.html xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" odl:use-default-for-reference-types="true"> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + diff --git a/renderer/src/test/java/org/opendaylight/transportpce/renderer/RollbackProcessorTest.java b/renderer/src/test/java/org/opendaylight/transportpce/renderer/RollbackProcessorTest.java new file mode 100644 index 000000000..1df295a8b --- /dev/null +++ b/renderer/src/test/java/org/opendaylight/transportpce/renderer/RollbackProcessorTest.java @@ -0,0 +1,46 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer; + +import org.junit.Assert; +import org.junit.Test; +import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackProcessor; + +public class RollbackProcessorTest { + + @Test + public void rollbackIfNecessaryTest() throws Exception { + int rolledBack = -1; + RollbackProcessor rollbackProcessor = new RollbackProcessor(); + rollbackProcessor.addTask(new TestRollbackTask("task1", false)); + rollbackProcessor.addTask(new TestRollbackTask("task2", false)); + rolledBack = rollbackProcessor.rollbackAllIfNecessary(); + Assert.assertTrue(rolledBack == 0); + rollbackProcessor.addTask(new TestRollbackTask("task3", true)); + rollbackProcessor.addTask(new TestRollbackTask("task4", false)); + rolledBack = rollbackProcessor.rollbackAllIfNecessary(); + Assert.assertTrue(rolledBack == 4); + rolledBack = rollbackProcessor.rollbackAllIfNecessary(); + Assert.assertTrue(rolledBack == 0); + } + + @Test + public void rollbackAllTest() throws Exception { + RollbackProcessor rollbackProcessor = new RollbackProcessor(); + rollbackProcessor.addTask(new TestRollbackTask("task1", false)); + rollbackProcessor.addTask(new TestRollbackTask("task2", false)); + rollbackProcessor.addTask(new TestRollbackTask("task3", false)); + rollbackProcessor.addTask(new TestRollbackTask("task4", false)); + int rolledBack = -1; + rolledBack = rollbackProcessor.rollbackAll(); + Assert.assertTrue(rolledBack == 4); + rolledBack = rollbackProcessor.rollbackAll(); + Assert.assertTrue(rolledBack == 0); + } + +} diff --git a/renderer/src/test/java/org/opendaylight/transportpce/renderer/TestRollbackTask.java b/renderer/src/test/java/org/opendaylight/transportpce/renderer/TestRollbackTask.java new file mode 100644 index 000000000..aaa6b12f5 --- /dev/null +++ b/renderer/src/test/java/org/opendaylight/transportpce/renderer/TestRollbackTask.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2017 AT&T and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.transportpce.renderer; + +import org.opendaylight.transportpce.renderer.provisiondevice.tasks.RollbackTask; + +public class TestRollbackTask extends RollbackTask { + + private boolean rollbackNecessary; + + public TestRollbackTask(String id, boolean rollbackNecessary) { + super(id); + this.rollbackNecessary = rollbackNecessary; + } + + @Override + public boolean isRollbackNecessary() { + return rollbackNecessary; + } + + @Override + public Void call() throws Exception { + return null; + } +}