Renderer and OLM update 48/73548/6
authorShweta V <sv111y@att.com>
Wed, 20 Dec 2017 10:25:52 +0000 (11:25 +0100)
committerguillaume.lambert <guillaume.lambert@orange.com>
Wed, 18 Jul 2018 13:09:17 +0000 (15:09 +0200)
- 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 <db929a@att.com>
Co-Authored-By: Shweta Vachhani <sv111y@att.com>
Co-Authored-By: Masha Dorfman <>
Co-Authored-By: Archana Soundararajan <as7463@att.com>
Co-Authored-By: Juraj Veverka <Juraj.Veverka@pantheon.tech>
Co-Authored-By: Samuel Kontri <samuel.kontris@pantheon.sk>
Co-Authored-By: Andrej Zan <andrej.zan@pantheon.sk>
Co-Authored-By: Milan Fratrik <>
Co-authored-by: Martial COULIBALY <martial.coulibaly@gfi.fr>
Change-Id: I7292e82bfecb5fe9c025f9fde8bcd5ebc3be90ba
Signed-off-by: Shweta <sv111y@att.com>
Signed-off-by: Martial COULIBALY <martial.coulibaly@gfi.fr>
55 files changed:
api/src/main/yang/olm@2017-04-18.yang
api/src/main/yang/org-transportpce-common-types@2017-09-07.yang
api/src/main/yang/renderer@2017-02-28.yang
api/src/main/yang/service_path/transportpce-pathDescription@2017-04-26.yang
olm/pom.xml
olm/src/main/java/org/opendaylight/transportpce/olm/OlmPowerServiceRpcImpl.java [new file with mode: 0644]
olm/src/main/java/org/opendaylight/transportpce/olm/OlmPowerSetupImpl.java [deleted file]
olm/src/main/java/org/opendaylight/transportpce/olm/OlmProvider.java
olm/src/main/java/org/opendaylight/transportpce/olm/power/PowerMgmt.java
olm/src/main/java/org/opendaylight/transportpce/olm/service/OlmPowerService.java [new file with mode: 0644]
olm/src/main/java/org/opendaylight/transportpce/olm/service/OlmPowerServiceImpl.java [new file with mode: 0644]
olm/src/main/java/org/opendaylight/transportpce/olm/spanloss/SpanLoss.java [deleted file]
olm/src/main/java/org/opendaylight/transportpce/olm/util/OlmUtils.java [new file with mode: 0644]
olm/src/main/java/org/opendaylight/transportpce/olm/util/OtsPmHolder.java [moved from olm/src/main/java/org/opendaylight/transportpce/olm/spanloss/OtsPmHolder.java with 96% similarity]
olm/src/main/java/org/opendaylight/transportpce/olm/util/RoadmLinks.java [new file with mode: 0644]
olm/src/main/resources/org/opendaylight/blueprint/olm-blueprint.xml
olm/src/test/java/org/opendaylight/transportpce/olm/OlmProviderTest.java [new file with mode: 0644]
renderer/pom.xml
renderer/src/main/java/org/opendaylight/transportpce/renderer/ModelMappingUtils.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/NetworkModelWavelengthService.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/NetworkModelWavelengthServiceImpl.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/NodeIdPair.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/NodeLists.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererNotificationsImpl.java
renderer/src/main/java/org/opendaylight/transportpce/renderer/RendererProvider.java
renderer/src/main/java/org/opendaylight/transportpce/renderer/ServicePathInputData.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/mapping/PortMapping.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmEthIterface.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmInterfaceFactory.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmInterfaces.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOchInterface.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOdu4Interface.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmOtu4Interface.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/openroadminterface/OpenRoadmXponderInterface.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/CrossConnect.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRenderer.java [deleted file]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererService.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRendererServiceImpl.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/DeviceRenderingResult.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/OLMRenderingResult.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperations.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/RendererServiceOperationsImpl.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/servicepath/ServiceListTopology.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/servicepath/ServicePathDirection.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/DeviceRenderingRollbackTask.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/DeviceRenderingTask.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/OlmPowerSetupRollbackTask.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/OlmPowerSetupTask.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/RollbackProcessor.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/provisiondevice/tasks/RollbackTask.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/rpcs/DeviceRendererRPCImpl.java [new file with mode: 0644]
renderer/src/main/java/org/opendaylight/transportpce/renderer/rpcs/TransportPCEServicePathRPCImpl.java [new file with mode: 0644]
renderer/src/main/resources/org/opendaylight/blueprint/renderer-blueprint.xml
renderer/src/test/java/org/opendaylight/transportpce/renderer/RollbackProcessorTest.java [new file with mode: 0644]
renderer/src/test/java/org/opendaylight/transportpce/renderer/TestRollbackTask.java [new file with mode: 0644]

index 741e05765f1f25eec0fc147d1f5e1b78f2df9ee0..541b429ccc3aca83f9ebce32a3fd493243d10fde 100644 (file)
@@ -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;
          }
        }
-  }*/
+  }
 }
index 912d548ed278f06a73806920eec27795c19e46cd..27c52c5bb8403b24f878a922a746ca1566b1a356 100644 (file)
@@ -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;
index c673b5289e2253795b0eed5dabcee31e2dd3a47c..4b3eea46008b015831b4ed983873b1058cc5777b 100644 (file)
@@ -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 {
         }
       }
     }
-  }*/
+  }
 }
index cfab2cb6beeb370966e59e8934c6efb2b611c582..7aa5e165fbfb7de48818c6fc3d494cb6282df36a 100644 (file)
@@ -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 {
index b0f2651e0f55ad4de81182b205589b9550cc5921..d5d7c9564e1e7eebfb5f65764e03d64babfcaee3 100644 (file)
@@ -21,37 +21,37 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <artifactId>transportpce-olm</artifactId>
   <version>0.2.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-artifacts</artifactId>
+        <version>1.7.3-SNAPSHOT</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.netconf</groupId>
+        <artifactId>netconf-artifacts</artifactId>
+        <version>1.4.3-SNAPSHOT</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
   <dependencies>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>transportpce-api</artifactId>
       <version>${project.version}</version>
     </dependency>
-        <dependency>
+    <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>transportpce-renderer</artifactId>
       <version>${project.version}</version>
     </dependency>
-    <dependency>
-      <groupId>${project.groupId}.ordmodels</groupId>
-      <artifactId>transportpce-ordmodels-common</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>${project.groupId}.ordmodels</groupId>
-      <artifactId>transportpce-ordmodels-network</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>${project.groupId}.ordmodels</groupId>
-      <artifactId>transportpce-ordmodels-service</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>${project.groupId}.ordmodels</groupId>
-      <artifactId>transportpce-ordmodels-device</artifactId>
-      <version>${project.version}</version>
-    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.model</groupId>
       <artifactId>model-topology</artifactId>
@@ -75,4 +75,5 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <scope>test</scope>
     </dependency>
   </dependencies>
+
 </project>
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 (file)
index 0000000..8524457
--- /dev/null
@@ -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.
+     *
+     * <p>
+     * 1. get-pm This operation traverse through current PM list and gets PM for
+     * given NodeId and Resource name
+     *
+     * <p>
+     * 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<RpcResult<GetPmOutput>> 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.
+     *
+     * <p>
+     * 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
+     *
+     * <p>
+     * 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<org.opendaylight.yangtools.yang.common.RpcResult<ServicePowerSetupOutput>> 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.
+     *
+     * <p>
+     * 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
+     *
+     * <p>
+     * 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<RpcResult<ServicePowerTurndownOutput>> 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.
+     *
+     * <p>
+     * 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
+     *
+     * <p>
+     * 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<RpcResult<CalculateSpanlossBaseOutput>> calculateSpanlossBase(CalculateSpanlossBaseInput input) {
+        return RpcResultBuilder.success(olmPowerService.calculateSpanlossBase(input)).buildFuture();
+    }
+
+    @Override
+    public Future<RpcResult<CalculateSpanlossCurrentOutput>> calculateSpanlossCurrent(
+            CalculateSpanlossCurrentInput input) {
+        return RpcResultBuilder.success(olmPowerService.calculateSpanlossCurrent(input)).buildFuture();
+    }
+
+    @Override
+    public Future<RpcResult<ServicePowerResetOutput>> 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 (file)
index 9a82ad5..0000000
+++ /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.
-     *
-     * <p>
-     * 1. get-pm This operation traverse through current PM list and gets PM for
-     * given NodeId and Resource name
-     *
-     * <p>
-     * 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<RpcResult<GetPmOutput>> 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<CurrentPmlist> currentPmsIID = InstanceIdentifier.create(CurrentPmlist.class);
-        ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
-        Optional<CurrentPmlist> currentPmList;
-        String methodName = "";
-        List<CurrentPm> currentPms = new ArrayList<>();
-        GetPmOutputBuilder pmOutputBuilder = new GetPmOutputBuilder();
-        List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm.output.Measurements>
-            measrements = new ArrayList<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418
-                .get.pm.output.Measurements>();
-        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.
-     *
-     * <p>
-     * 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
-     *
-     * <p>
-     * 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<org.opendaylight.yangtools.yang.common.RpcResult<ServicePowerSetupOutput>> servicePowerSetup(
-        ServicePowerSetupInput input) {
-        List<RoadmLinks> roadmLinks = new ArrayList<RoadmLinks>();
-        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.
-     *
-     * <p>
-     * 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
-     *
-     * <p>
-     * 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<RpcResult<ServicePowerTurndownOutput>> 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
index 6325d333d04a6384ada21eb518757833f44d8a55..36343095cab2030eb944c21a94e76a78e7450e7c 100644 (file)
@@ -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<OlmService> 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));
     }
 
     /**
index 789d2fb9c52cdc91936da776230f70fbb181d324..e7ab4f6ccf46ad6faa97604eedee6f6a99652e9e 100644 (file)
@@ -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<Topology> 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<Nodes> 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<Mapping> mappingObject = inputNode.getMapping().stream().filter(o -> o.getKey()
                             .equals(new MappingKey(destTpId))).findFirst();
                     if (mappingObject.isPresent()) {
-                        Map<String, Double> txPowerRangeMap = getXponderPowerRange(nodeId, mappingObject.get()
-                                .getSupportingCircuitPackName(),
-                                mappingObject.get().getSupportingPort(),deviceDb);
+                        Map<String, Double> 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<String, Double> rxSRGPowerRangeMap = getSRGRxPowerRange(nextNodeId, srgId, deviceDbSRG);
-                            Double powerValue = new Double(0);
+
+                            Map<String, Double> 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<Mapping> mappingObject = inputNode.getMapping().stream().filter(o -> o.getKey()
+                    Optional<Mapping> 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<Interface> 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<Interface> 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<Void, TransactionCommitFailedException> submit = writeTransaction.submit();
+        Optional<Interface> 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<MountPoint> 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<Nodes> nodesIID = InstanceIdentifier.create(Network.class)
-                .child(Nodes.class, new NodesKey(nodeId));
-        ReadOnlyTransaction readTransaction = db.newReadOnlyTransaction();
-        Optional<Nodes> 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<Optional<DeviceTransaction>> deviceTxFuture = deviceTransactionManager.getDeviceTransaction(nodeId);
+            DeviceTransaction deviceTx;
+            try {
+                Optional<DeviceTransaction> 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<Void> 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<String, Double> getXponderPowerRange(String nodeId, String circuitPackName, String portName,
-            DataBroker deviceDb) {
-        InstanceIdentifier<Ports> portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
-                CircuitPacks.class, new CircuitPacksKey(circuitPackName)).child(Ports.class, new PortsKey(portName));
-        ReadOnlyTransaction readTransaction = deviceDb.newReadOnlyTransaction();
-        Map<String, Double> powerRangeMap = new HashMap<String, Double>();
-        try {
-            LOG.info("Fetching logical Connection Point value for port " + portName + " at circuit pack "
-                + circuitPackName);
-            Optional<Ports> 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<String, Double> getXponderPowerRange(String circuitPackName, String portName, String deviceId) {
+        InstanceIdentifier<Ports> portIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
+                .child(CircuitPacks.class, new CircuitPacksKey(circuitPackName))
+                .child(Ports.class, new PortsKey(portName));
+        Map<String, Double> powerRangeMap = new HashMap<>();
+        LOG.info("Fetching logical Connection Point value for port {} at circuit pack {}", portName, circuitPackName);
+        Optional<Ports> 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<String, Double> getSRGRxPowerRange(String nodeId, String srgId, DataBroker deviceDb) {
-        Map<String, Double> powerRangeMap = new HashMap<String, Double>();
+    private Map<String, Double> getSRGRxPowerRange(String nodeId, String srgId) {
+        Map<String, Double> powerRangeMap = new HashMap<>();
         LOG.info("Coming inside Xpdr power range");
-        java.util.Optional<Mapping> mappingSRGObject = getNode(nodeId, mps, db).getMapping()
+        Optional<Mapping> 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<Ports> 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<Ports> 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<Ports> 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<Interface> interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
-                .child(Interface.class, new InterfaceKey(interfaceName));
-        rwtx.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, ochInterfaceBuilder.build());
-        CheckedFuture<Void, TransactionCommitFailedException> submit = rwtx.submit();
+        Optional<Interface> 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<Optional<DeviceTransaction>> deviceTxFuture = deviceTransactionManager.getDeviceTransaction(nodeId);
+            DeviceTransaction deviceTx;
+            try {
+                Optional<DeviceTransaction> 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<Interface> interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
+                    .child(Interface.class, new InterfaceKey(interfaceName));
+            deviceTx.put(LogicalDatastoreType.CONFIGURATION, interfacesIID, ochInterfaceBuilder.build());
+            ListenableFuture<Void> 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<RoadmConnections> 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<Optional<DeviceTransaction>> deviceTxFuture =
+                    deviceTransactionManager.getDeviceTransaction(deviceId);
+            DeviceTransaction deviceTx;
+            try {
+                Optional<DeviceTransaction> 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<RoadmConnections> roadmConnIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
+                    .child(RoadmConnections.class, new RoadmConnectionsKey(connectionNumber));
+            deviceTx.put(LogicalDatastoreType.CONFIGURATION, roadmConnIID, newRdmConn);
+            ListenableFuture<Void> 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 (file)
index 0000000..63e91cf
--- /dev/null
@@ -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.
+     *
+     * <p>
+     * 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'.
+     *
+     * <p>
+     * 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'.
+     *
+     * <p>
+     * 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.
+     *
+     * <p>
+     * 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 (file)
index 0000000..ba45572
--- /dev/null
@@ -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<Link> 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> 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<Link> networkLinks = getNetworkLinks();
+        if (networkLinks.isEmpty()) {
+            LOG.warn("Failed to get links form {} topology.", NetworkUtils.OVERLAY_NETWORK_ID);
+            return null;
+        }
+        List<RoadmLinks> 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<Link> getNetworkLinks() {
+        NetworkKey overlayTopologyKey = new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID));
+
+        InstanceIdentifier<Network1> networkIID = InstanceIdentifier.builder(Network.class, overlayTopologyKey)
+                .augmentation(Network1.class)
+                .build();
+        Optional<Network1> 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<Link> 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:
+     *
+     * <p>
+     * 1. Get OTS interface name from port mapping by TPId 2. Call getPm RPC to get OTS PM
+     *
+     * <p>
+     *
+     * @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:
+     *
+     * <p>
+     * 1. Read existing interface details
+     *
+     * <p>
+     * 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<Interface> interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
+                .child(Interface.class, new InterfaceKey(interfaceName));
+        com.google.common.base.Optional<Interface> interfaceObject;
+        try {
+            Future<Optional<DeviceTransaction>> deviceTxFuture =
+                    deviceTransactionManager.getDeviceTransaction(realNodeId);
+            java.util.Optional<DeviceTransaction> 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<Void> 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:
+     *
+     * <p>
+     * 1. Read PM measurement
+     *
+     * <p>
+     * 2. Set Spanloss value for interface
+     *
+     * @param roadmLinks reference to list of RoadmLinks
+     * @return true/false
+     */
+    private boolean getLinkSpanloss(List<RoadmLinks> 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<Node, NodeKey> mappedNodeII =
+                InstanceIdentifiers.OVERLAY_NETWORK_II.child(Node.class, new NodeKey(new NodeId(mappedNodeId)));
+        com.google.common.base.Optional<Node> 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<SupportingNode> 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 (file)
index 026c041..0000000
+++ /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:
-     *
-     * <p>
-     * 1. Get OTS interface name from port mapping by TPId 2. Call getPm RPC to
-     * get OTS PM
-     *
-     * <p>
-     *
-     * @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<RpcResult<GetPmOutput>> 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:
-     *
-     * <p>
-     * 1. Read existing interface details
-     *
-     * <p>
-     * 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<Interface> interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
-                .child(Interface.class, new InterfaceKey(interfaceName));
-        Optional<Interface> 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<Void, TransactionCommitFailedException> 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:
-     *
-     * <p>
-     * 1. Read PM measurement
-     *
-     * <p>
-     * 2. Set Spanloss value for interface
-     *
-     * @param roadmLinks
-     *            reference to list of RoadmLinks
-     * @return true/false
-     */
-    public boolean getLinkSpanloss(List<RoadmLinks> 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 (file)
index 0000000..cce3606
--- /dev/null
@@ -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<Topology> 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<Nodes> getNode(String nodeId, DataBroker db) {
+        InstanceIdentifier<Nodes> 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
+     *
+     * <p>
+     * 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<CurrentPmlist> currentPmsIID = InstanceIdentifier.create(CurrentPmlist.class);
+        Optional<CurrentPmlist> currentPmList;
+
+        currentPmList = deviceTransactionManager
+                .getDataFromDevice(input.getNodeId(), LogicalDatastoreType.OPERATIONAL, currentPmsIID,
+                        Timeouts.DEVICE_READ_TIMEOUT, Timeouts.DEVICE_READ_TIMEOUT_UNIT);
+        if (currentPmList.isPresent()) {
+            List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm.output
+                    .Measurements> 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<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm
+            .output.Measurements> extractWantedMeasurements(CurrentPmlist currentPmList,
+            ResourceTypeEnum wantedResourceType, ResourceIdentifier wantedResourceIdentifier,
+            PmGranularity wantedGranularity) {
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm
+            .output.Measurements> 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<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm
+            .output.Measurements> extractMeasurements(List<Measurements> measurementsFromDevice) {
+        List<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.get.pm.output.Measurements>
+            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<CircuitPack> circuitPackOptional = tryCastToParticularResource(CircuitPack.class, resource);
+                return circuitPackOptional.flatMap(
+                    circuitPack -> Optional.ofNullable(circuitPack.getCircuitPackName()))
+                        .map(circuitPackName -> circuitPackName.equals(wantedResourceIdentifier.getResourceName()))
+                        .orElse(false);
+            case Connection:
+                Optional<Connection> connectionOptional = tryCastToParticularResource(Connection.class, resource);
+                return connectionOptional.flatMap(
+                    connection -> Optional.ofNullable(connection.getConnectionNumber()))
+                        .map(connectionNumber -> connectionNumber.equals(wantedResourceIdentifier.getResourceName()))
+                        .orElse(false);
+            case Degree:
+                Optional<Degree> 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<Interface> interfaceOptional = tryCastToParticularResource(Interface.class, resource);
+                return interfaceOptional.flatMap(
+                    interfaceResource -> Optional.ofNullable(interfaceResource.getInterfaceName()))
+                        .map(interfaceName -> interfaceName.equals(wantedResourceIdentifier.getResourceName()))
+                        .orElse(false);
+            case InternalLink:
+                Optional<InternalLink> internalLinkOptional = tryCastToParticularResource(InternalLink.class, resource);
+                return internalLinkOptional.flatMap(
+                    internalLink -> Optional.ofNullable(internalLink.getInternalLinkName()))
+                        .map(internalLinkName -> internalLinkName.equals(wantedResourceIdentifier.getResourceName()))
+                        .orElse(false);
+            case PhysicalLink:
+                Optional<PhysicalLink> physicalLinkOptional = tryCastToParticularResource(PhysicalLink.class, resource);
+                return physicalLinkOptional.flatMap(
+                    physicalLink -> Optional.ofNullable(physicalLink.getPhysicalLinkName()))
+                        .map(physicalLinkName -> physicalLinkName.equals(wantedResourceIdentifier.getResourceName()))
+                        .orElse(false);
+            case Service:
+                Optional<Service> serviceOptional = tryCastToParticularResource(Service.class, resource);
+                return serviceOptional.flatMap(
+                    service -> Optional.ofNullable(service.getServiceName()))
+                        .map(serviceName -> serviceName.equals(wantedResourceIdentifier.getResourceName()))
+                    .orElse(false);
+            case Shelf:
+                Optional<Shelf> shelfOptional = tryCastToParticularResource(Shelf.class, resource);
+                return shelfOptional.flatMap(
+                    shelf -> Optional.ofNullable(shelf.getShelfName()))
+                        .map(shelfName -> shelfName.equals(wantedResourceIdentifier.getResourceName()))
+                        .orElse(false);
+            case SharedRiskGroup:
+                Optional<Srg> 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<Port> 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 <T extends Resource> Optional<T> tryCastToParticularResource(Class<T> 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();
+    }
+
+}
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 50f55602320c9416e2d549fbdbc1824ba063ffc9..9507ce5a0a2e235c4c3c5ad91685a58ea3d139fd 100644 (file)
@@ -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 (file)
index 0000000..6c9de8b
--- /dev/null
@@ -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;
+    }
+
+}
index b8ed3369eddd60705dbf33a4fdbffe7cd566bf01..0babd70bbebafa5a4b72d5e923c19cc413e71d0b 100644 (file)
@@ -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
 -->
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
-  xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
-  odl:use-default-for-reference-types="true">
+      xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+      odl:use-default-for-reference-types="true">
 
   <reference id="dataBroker"
-    interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
-    odl:type="default" />
-  <reference id="mountPointService"
-    interface="org.opendaylight.controller.md.sal.binding.api.MountPointService" />
+        interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+        odl:type="default" />
   <reference id="rpcProviderRegistry"
-    interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry" />
-  <bean id="provider"
-    class="org.opendaylight.transportpce.olm.OlmProvider"
-    init-method="init" destroy-method="close">
+        interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry" />
+  <reference id="openRoadmInterfaces"
+        interface="org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces" />
+  <reference id="crossConnect"
+        interface="org.opendaylight.transportpce.common.crossconnect.CrossConnect" />
+  <reference id="deviceTransactionManager"
+        interface="org.opendaylight.transportpce.common.device.DeviceTransactionManager" />
+  <reference id="portMapping"
+        interface="org.opendaylight.transportpce.common.mapping.PortMapping" />
+
+  <bean id="olmPowerServiceImpl"
+        class="org.opendaylight.transportpce.olm.service.OlmPowerServiceImpl"
+        init-method="init" destroy-method="close">
+    <argument ref="dataBroker" />
+    <argument ref="powerMgmt" />
+    <argument ref="deviceTransactionManager" />
+    <argument ref="portMapping" />
+  </bean>
+
+  <bean id="powerMgmt" class="org.opendaylight.transportpce.olm.power.PowerMgmt" >
     <argument ref="dataBroker" />
-    <argument ref="mountPointService" />
+    <argument ref="openRoadmInterfaces" />
+    <argument ref="crossConnect" />
+    <argument ref="deviceTransactionManager" />
+  </bean>
+
+  <bean id="provider"
+        class="org.opendaylight.transportpce.olm.OlmProvider"
+        init-method="init" destroy-method="close">
     <argument ref="rpcProviderRegistry" />
+    <argument ref="olmPowerServiceImpl" />
   </bean>
 
+  <service ref="olmPowerServiceImpl"
+        interface="org.opendaylight.transportpce.olm.service.OlmPowerService"/>
+
 </blueprint>
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 (file)
index 0000000..634f517
--- /dev/null
@@ -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
+    }
+
+}
index c86a9ee6522a7a6b0a08c8035a31f02d7ec1776a..1fd381688da4fe4427b1b6681edba45e9a63b133 100644 (file)
@@ -22,6 +22,25 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
   <version>0.2.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
 
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-artifacts</artifactId>
+        <version>1.7.3-SNAPSHOT</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.netconf</groupId>
+        <artifactId>netconf-artifacts</artifactId>
+        <version>1.4.3-SNAPSHOT</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
   <dependencies>
     <dependency>
       <groupId>${project.groupId}</groupId>
@@ -30,22 +49,12 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     </dependency>
     <dependency>
       <groupId>${project.groupId}.ordmodels</groupId>
-      <artifactId>transportpce-ordmodels-common</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>${project.groupId}.ordmodels</groupId>
-      <artifactId>transportpce-ordmodels-network</artifactId>
-      <version>${project.version}</version>
-    </dependency>
-    <dependency>
-      <groupId>${project.groupId}.ordmodels</groupId>
-      <artifactId>transportpce-ordmodels-service</artifactId>
+      <artifactId>transportpce-ordmodels-device</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}.ordmodels</groupId>
-      <artifactId>transportpce-ordmodels-device</artifactId>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>transportpce-common</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>
@@ -71,4 +80,5 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <scope>test</scope>
     </dependency>
   </dependencies>
+
 </project>
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 (file)
index 0000000..a9e89fd
--- /dev/null
@@ -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<Nodes> 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<RpcResult<ServiceImplementationRequestOutput>>
+        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<ZToA> iterator) {
+        Map<Integer, NodeIdPair> treeMap = new TreeMap<>();
+        List<Nodes> olmList = new ArrayList<>();
+        List<Nodes> 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<AToZ> iterator) {
+        Map<Integer, NodeIdPair> treeMap = new TreeMap<>();
+        List<Nodes> list = new ArrayList<>();
+        List<Nodes> 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 (file)
index 0000000..cf9e274
--- /dev/null
@@ -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 (file)
index 0000000..a354bda
--- /dev/null
@@ -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<NodeIdPair> atozTpIds = getAToZTpList(pathDescription);
+        List<NodeIdPair> 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<NodeIdPair> atozTpIds = getAToZTpList(pathDescription);
+        List<NodeIdPair> 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<NodeIdPair> getAToZTpList(PathDescription pathDescription) {
+        List<AToZ> 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<NodeIdPair> getZToATpList(PathDescription pathDescription) {
+        List<ZToA> 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<Node1> 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<Node1> getNode1FromDatastore(String nodeId) {
+        InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1>
+                nodeIID = createNode1IID(nodeId);
+        Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1> 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<String> nodeIds, Long wavelengthNumber) {
+        WriteTransaction nodeWriteTx = this.dataBroker.newWriteOnlyTransaction();
+        for (String nodeId : nodeIds) {
+            Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1> 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<org.opendaylight.yang.gen.v1.http.org.openroadm.degree.rev170929.degree.node.attributes
+                            .AvailableWavelengths> 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<org.opendaylight.yang.gen.v1.http.org.openroadm.srg.rev170929.srg.node.attributes
+                            .AvailableWavelengths> 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<String> nodeIds, Long wavelengthNumber) {
+        WriteTransaction nodeWriteTx = this.dataBroker.newWriteOnlyTransaction();
+        for (String nodeId : nodeIds) {
+            Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.Node1> 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<Node1> 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<TerminationPoint1> 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<TerminationPoint1> getTerminationPoint1FromDatastore(String nodeId, String tpId) {
+        InstanceIdentifier<TerminationPoint1> tpIID = createTerminationPoint1IIDBuilder(nodeId, tpId).build();
+        Optional<TerminationPoint1> 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<NodeIdPair> tpIds) {
+        WriteTransaction deleteUsedWlTx = this.dataBroker.newWriteOnlyTransaction();
+        for (NodeIdPair idPair : tpIds) {
+            Optional<TerminationPoint1> 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<TerminationPoint1> 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<String> 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<NodeIdPair> tpIds) {
+        WriteTransaction addUsedWlTx = this.dataBroker.newWriteOnlyTransaction();
+        for (NodeIdPair idPair : tpIds) {
+            Optional<TerminationPoint1> 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<UsedWavelengths> 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<UsedWavelengths> 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<UsedWavelengths> 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<org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev170929.network.node
+                            .termination.point.cp.attributes.UsedWavelengths> 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<UsedWavelength> 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<String> 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 (file)
index 0000000..0fb9f44
--- /dev/null
@@ -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 (file)
index 0000000..38ff5e8
--- /dev/null
@@ -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<Nodes> olmList;
+    private List<Nodes> list;
+
+    public NodeLists(List<Nodes> olmList, List<Nodes> list) {
+        this.olmList = olmList;
+        this.list = list;
+    }
+
+    public List<Nodes> getOlmList() {
+        return olmList;
+    }
+
+    public List<Nodes> getList() {
+        return list;
+    }
+
+}
index 6231c88732cd4b41335ee55daa96c0026a24cbd4..49778f900226361d98bcab190882754283907120 100644 (file)
@@ -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<Node> {
-
     private final DataBroker dataBroker;
     private final MountPointService mountService;
     private static final Logger LOG = LoggerFactory.getLogger(RendererNotificationsImpl.class);
     private ListenerRegistration<RendererNotificationsImpl> dataTreeChangeListenerRegistration;
-
+    private final PortMapping portMapping;
+    private final DeviceTransactionManager deviceTransactionManager;
     private final Set<String> currentMountedDevice;
     public static final InstanceIdentifier<Topology> 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<Node> {
         });
 
     public RendererNotificationsImpl(final DataBroker dataBroker, final MountPointService mountService,
-        Set<String> currentMountedDevice) {
+        Set<String> 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<Node> {
         }
     }
 
-    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<MountPoint> 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> notificationService = mountPoint.getService(
-            NotificationService.class);
+        final Optional<NotificationService> 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<Node> {
 
         // Listening to NETCONF datastream
         final String streamName = "NETCONF";
-        final Optional<RpcConsumerRegistry> service = mountPoint.getService(RpcConsumerRegistry.class);
+        final Optional<RpcConsumerRegistry> 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<Node> {
                 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<Node> {
                              * 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: {
index 2f6ede4126a7c36d9417fdea7a33f41a981a7797..4729514532aa0e65c0b0f848ac741bb72c9ef32a 100644 (file)
@@ -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<RendererService> deviceRendererRegistration;
+    private DeviceRendererRPCImpl deviceRendererRPCImpl;
+    private RpcRegistration<TransportpceServicepathService> tpceServiceRegistry;
+    private RendererServiceOperations rendererServiceOperations;
+    private RendererNotificationsImpl rendererNotificationsImpl;
     private final Set<String> 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 (file)
index 0000000..7869a9b
--- /dev/null
@@ -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 (file)
index bfdea81..0000000
+++ /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 :
-     *
-     * <p>
-     * 1. DEGn-TTP-TX, DEGn-TTP-RX, DEGn-TTP-TXRX
-     *
-     * <p>
-     * 2. SRGn-PPp-TX, SRGn-PPp-RX, SRGn-PPp-TXRX
-     *
-     * <p>
-     * 3. LINEn
-     *
-     * <p>
-     * 4. CLNTn.
-     *
-     * <p>
-     * 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<Mapping> 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<Nodes> 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<Mapping> portMapList) {
-        // Creating mapping data for degree TTP's
-        List<ConnectionPorts> 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<Ports> 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<Ports> 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<Mapping> 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<org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.srg.CircuitPacks> srgCps =
-                new ArrayList<>();
-            LOG.info("Getting CircuitPacks for Srg Number {}", srgCounter);
-            InstanceIdentifier<SharedRiskGroup> srgIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
-                SharedRiskGroup.class, new SharedRiskGroupKey(srgCounter));
-            try {
-                Optional<SharedRiskGroup> 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<CircuitPacks> cpIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
-                        CircuitPacks.class, new CircuitPacksKey(circuitPackName));
-                    Optional<CircuitPacks> 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:
-     *
-     * <p>
-     * 1. LINEn
-     *
-     * <p>
-     * 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<Mapping> portMapList) {
-        // Creating for Xponder Line and Client Ports
-        try {
-            InstanceIdentifier<OrgOpenroadmDevice> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class);
-            ReadOnlyTransaction rtx = deviceDb.newReadOnlyTransaction();
-            Optional<OrgOpenroadmDevice> 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<? extends InterfaceType> 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<Info> infoIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(Info.class);
-        try {
-            Optional<Info> 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<ConnectionPorts> getDegreePorts(DataBroker deviceDb, Info ordmInfo) {
-
-        List<ConnectionPorts> 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<Degree> deviceIID = InstanceIdentifier.create(OrgOpenroadmDevice.class).child(
-                Degree.class, new DegreeKey(degreeCounter));
-            try {
-                Optional<Degree> 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.
-     *
-     * <p>
-     * 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<Mapping> 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<Nodes> nodesList = new ArrayList<>();
-        nodesList.add(nodesBldr.build());
-        NetworkBuilder nwBldr = new NetworkBuilder();
-        nwBldr.setNodes(nodesList);
-        final WriteTransaction writeTransaction = db.newWriteOnlyTransaction();
-        InstanceIdentifier<Network> nodesIID = InstanceIdentifier.builder(Network.class).build();
-        writeTransaction.merge(LogicalDatastoreType.CONFIGURATION, nodesIID, nwBldr.build());
-        CheckedFuture<Void, TransactionCommitFailedException> 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:
-     *
-     * <p>
-     * 1. Supporting circuit pack
-     *
-     * <p>
-     * 2. Supporting port
-     *
-     * <p>
-     * 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<Mapping> portMapping = InstanceIdentifier.builder(Network.class).child(Nodes.class,
-            new NodesKey(nodeId)).child(Mapping.class, new MappingKey(logicalConnPoint)).build();
-        ReadOnlyTransaction readTx = db.newReadOnlyTransaction();
-        Optional<Mapping> 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<Node> 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<MountPoint> 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 (file)
index 9ba7673..0000000
+++ /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 (file)
index 0000000..a16fcd1
--- /dev/null
@@ -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<? extends RateIdentity> 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<? extends InterfaceType> 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 (file)
index 333177d..0000000
+++ /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.
-     *
-     * <p>
-     * Before posting the interface it checks if:
-     *
-     * <p>
-     * 1. Interface with same name does not exist
-     *
-     * <p>
-     * 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<Interface> 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<Void, TransactionCommitFailedException> 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<Interface> interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
-                .child(Interface.class, new InterfaceKey(interfaceName));
-        try {
-            Optional<Interface> 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.
-     *
-     * <p>
-     * Before deleting the method:
-     *
-     * <p>
-     * 1. Checks if interface exists
-     *
-     * <p>
-     * 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<Interface> interfacesIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
-                            .child(Interface.class, new InterfaceKey(interfaceName));
-                    final WriteTransaction writeTransaction = netconfNodeDataBroker.newWriteOnlyTransaction();
-                    writeTransaction.delete(LogicalDatastoreType.CONFIGURATION, interfacesIID);
-                    final CheckedFuture<Void, TransactionCommitFailedException> 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 (file)
index 3743d12..0000000
+++ /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<? extends RateIdentity> 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 (file)
index f3a6b92..0000000
+++ /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 (file)
index abffa1e..0000000
+++ /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 (file)
index 107bfd8..0000000
+++ /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<? extends RateIdentity> 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 (file)
index 993a6a7..0000000
+++ /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<RoadmConnections> 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<RoadmConnections> 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<RoadmConnections> 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<Void, TransactionCommitFailedException> 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<Void, TransactionCommitFailedException> 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<Void, TransactionCommitFailedException> 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<RpcConsumerRegistry> 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<RpcResult<GetConnectionPortTrailOutput>> 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 (file)
index b4bbc52..0000000
+++ /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<String> currentMountedDevice;
-    private final Set<String> nodesProvisioned;
-
-    public DeviceRenderer(DataBroker db, MountPointService mps, Set<String> 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:
-     *
-     * <p>
-     * 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.
-     *
-     * <p>
-     * 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.
-     *
-     * <p>
-     * 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<RpcResult<ServicePathOutput>> 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:
-     *
-     * <p>
-     * 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.
-     *
-     * <p>
-     * 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> 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:
-     *
-     * <p>
-     * 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.
-     *
-     * <p>
-     * 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> 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<CircuitPacks> circuitPackIID = InstanceIdentifier.create(OrgOpenroadmDevice.class)
-            .child(CircuitPacks.class, new CircuitPacksKey(circuitPack));
-        ReadOnlyTransaction readTx = deviceDb.newReadOnlyTransaction();
-        // retrieve relevent CircuitPack object
-        Optional<CircuitPacks> 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 (file)
index 0000000..7d2b73a
--- /dev/null
@@ -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.
+     *
+     * <p>
+     * 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
+     * </p>
+     *
+     * @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.
+     *
+     * <p>
+     * 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
+     * </p>
+     *
+     * @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 (file)
index 0000000..7eb030e
--- /dev/null
@@ -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> nodes = input.getNodes();
+        // Register node for suppressing alarms
+        if (!alarmSuppressionNodeRegistration(input)) {
+            LOG.warn("Alarm suppresion node registraion failed!!!!");
+        }
+
+        ConcurrentLinkedQueue<String> results = new ConcurrentLinkedQueue<>();
+        Set<NodeInterface> nodeInterfaces = Sets.newConcurrentHashSet();
+        Set<String> 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<String> createdEthInterfaces = new ArrayList<>();
+                List<String> createdOtuInterfaces = new ArrayList<>();
+                List<String> createdOduInterfaces = new ArrayList<>();
+                List<String> createdOchInterfaces = new ArrayList<>();
+                List<String> 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<String> connectionNameOpt = this.crossConnect.postCrossConnect(nodeId, waveNumber,
+                                    srcTp, destTp);
+                            if (connectionNameOpt.isPresent()) {
+                                nodesProvisioned.add(nodeId);
+                                List<Ports> 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<String> processErrorMessage(String message, ForkJoinPool forkJoinPool,
+            ConcurrentLinkedQueue<String> messages) {
+        LOG.warn(message);
+        messages.add(message);
+        forkJoinPool.shutdown();
+        return messages;
+    }
+
+    @Override
+    public ServicePathOutput deleteServicePath(ServicePathInput input) {
+        List<Nodes> nodes = input.getNodes();
+        ServicePathOutputBuilder delServBldr = new ServicePathOutputBuilder();
+
+        ConcurrentLinkedQueue<String> 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<String> 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<FailedToRollback> failedToRollbackList = new ArrayList<>();
+        for (NodeInterface nodeInterfaces : input.getNodeInterface()) {
+            List<String> 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<String> 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<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.alarmsuppression.rev171102.service
+            .nodelist.nodelist.Nodes> 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<org.opendaylight.yang.gen.v1.urn.opendaylight.params
+            .xml.ns.yang.alarmsuppression.rev171102.service.nodelist.Nodelist> 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<Void> 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<org.opendaylight.yang.gen.v1.urn.opendaylight.params
+            .xml.ns.yang.alarmsuppression.rev171102.service.nodelist.Nodelist> 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<Void> 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<Services> iid =
+                InstanceIdentifier.create(ServiceList.class).child(Services.class, serviceKey);
+        Optional<Services> services;
+        try (ReadOnlyTransaction readTx = this.dataBroker.newReadOnlyTransaction()) {
+            Future<com.google.common.base.Optional<Services>> 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 (file)
index 0000000..0fa7d4e
--- /dev/null
@@ -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<Nodes> olmList;
+    private final List<NodeInterface> renderedNodeInterfaces;
+
+    private DeviceRenderingResult(boolean success, String message, List<Nodes> olmList,
+            List<NodeInterface> 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<Nodes> getOlmList() {
+        return this.olmList;
+    }
+
+    public List<NodeInterface> getRenderedNodeInterfaces() {
+        return this.renderedNodeInterfaces;
+    }
+
+    public static DeviceRenderingResult failed(String message) {
+        return new DeviceRenderingResult(false, message, null, null);
+    }
+
+    public static DeviceRenderingResult ok(List<Nodes> olmList, List<NodeInterface> 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 (file)
index 0000000..ae8ca9e
--- /dev/null
@@ -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 (file)
index 0000000..d044237
--- /dev/null
@@ -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 (file)
index 0000000..7c3f101
--- /dev/null
@@ -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<DeviceRenderingResult> 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> 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<PathDescription> 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<RpcResult<ServicePowerTurndownOutput>> powerTurndownFuture = this.olmService.servicePowerTurndown(
+                new ServicePowerTurndownInputBuilder(servicePathInputData.getServicePathInput()).build());
+        return powerTurndownFuture.get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS).getResult();
+    }
+
+    private Optional<PathDescription> getPathDescriptionFromDatastore(String serviceName) {
+        InstanceIdentifier<PathDescription> 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<DeviceRenderingResult> deviceRendering(RollbackProcessor rollbackProcessor,
+            ServicePathInputData servicePathDataAtoZ, ServicePathInputData servicePathDataZtoA) {
+        LOG.info("Rendering devices A-Z");
+        ListenableFuture<DeviceRenderingResult> atozrenderingFuture =
+                this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataAtoZ,
+                        ServicePathDirection.A_TO_Z));
+
+        LOG.info("Rendering devices Z-A");
+        ListenableFuture<DeviceRenderingResult> ztoarenderingFuture =
+                this.executor.submit(new DeviceRenderingTask(this.deviceRenderer, servicePathDataZtoA,
+                        ServicePathDirection.Z_TO_A));
+        ListenableFuture<List<DeviceRenderingResult>> renderingCombinedFuture =
+                Futures.allAsList(atozrenderingFuture, ztoarenderingFuture);
+
+        List<DeviceRenderingResult> 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<OLMRenderingResult> olmPowerSetupFutureAtoZ
+                = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputAtoZ));
+
+        LOG.info("OLM power setup Z-A");
+        ListenableFuture<OLMRenderingResult> olmPowerSetupFutureZtoA
+                = this.executor.submit(new OlmPowerSetupTask(this.olmService, powerSetupInputZtoA));
+        ListenableFuture<List<OLMRenderingResult>> olmFutures =
+                Futures.allAsList(olmPowerSetupFutureAtoZ, olmPowerSetupFutureZtoA);
+
+        List<OLMRenderingResult> 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> 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<Measurements> 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<RpcResult<GetPmOutput>> getPmFuture = this.olmService.getPm(getPmIpBldr.build());
+            RpcResult<GetPmOutput> 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> 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 (file)
index 0000000..6ef18f7
--- /dev/null
@@ -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<AToZ> a2zTopologyList;
+    private List<ZToA> z2aTopologyList;
+    private TopologyBuilder serviceTopology;
+
+    public ServiceListTopology() {
+
+        this.a2zTopologyList = new ArrayList<>();
+        this.z2aTopologyList = new ArrayList<>();
+        this.serviceTopology = new TopologyBuilder();
+
+    }
+
+    public void updateAtoZTopologyList(List<Ports> 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> 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 (file)
index 0000000..8e1abe4
--- /dev/null
@@ -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 (file)
index 0000000..01bf58c
--- /dev/null
@@ -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<NodeInterface> renderedInterfaces;
+
+    public DeviceRenderingRollbackTask(String id, boolean isRollbackNecessary, List<NodeInterface> 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<FailedToRollback> failedRollbacks) {
+        List<String> 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 (file)
index 0000000..abe7818
--- /dev/null
@@ -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<DeviceRenderingResult> {
+
+    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<Nodes> 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 (file)
index 0000000..8b1027c
--- /dev/null
@@ -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<RpcResult<ServicePowerTurndownOutput>> powerTurndownResultFuture =
+                this.olmService.servicePowerTurndown(powerTurndownInput);
+        RpcResult<ServicePowerTurndownOutput> 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 (file)
index 0000000..aaf54a9
--- /dev/null
@@ -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<OLMRenderingResult> {
+
+    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<RpcResult<ServicePowerSetupOutput>> fr = this.olmService.servicePowerSetup(this.input);
+        RpcResult<ServicePowerSetupOutput> 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 (file)
index 0000000..709fc17
--- /dev/null
@@ -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<RollbackTask> 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 (file)
index 0000000..72e97a2
--- /dev/null
@@ -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<Void> {
+
+    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 (file)
index 0000000..f5c3549
--- /dev/null
@@ -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:
+     *
+     * <p>
+     * 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.
+     *
+     * <p>
+     * 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.
+     *
+     * <p>
+     * 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<RpcResult<ServicePathOutput>> 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<RpcResult<RendererRollbackOutput>> 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 (file)
index 0000000..4b3ec10
--- /dev/null
@@ -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<RpcResult<CancelResourceReserveOutput>> cancelResourceReserve(CancelResourceReserveInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<ServiceDeleteOutput>> serviceDelete(ServiceDeleteInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<RpcResult<ServiceImplementationRequestOutput>> serviceImplementationRequest(
+            ServiceImplementationRequestInput input) {
+        String serviceName = input.getServiceName();
+        LOG.info("Calling RPC service impl request {} {}", serviceName);
+        return ModelMappingUtils.createRpcResponse(rendererServiceOperations.serviceImplementation(input));
+    }
+
+    @Override
+    public Future<RpcResult<PathComputationRequestOutput>> pathComputationRequest(PathComputationRequestInput input) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
+
index 97260f5f949c1f9ff2b0883b5ad28aa42376a5cc..f5d667642870919b7d78a93a8c0395e2bd8c6d70 100644 (file)
@@ -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">
 
-  <reference id="dataBroker"
-    interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
-    odl:type="default" />
-  <reference id="mountPointService"
-    interface="org.opendaylight.controller.md.sal.binding.api.MountPointService" />
-  <reference id="rpcProviderRegistry"
-    interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry" />
-  <bean id="provider"
-    class="org.opendaylight.transportpce.renderer.RendererProvider"
-    init-method="init" destroy-method="close">
+  <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+        odl:type="default" />
+  <reference id="mountPointService" interface="org.opendaylight.controller.md.sal.binding.api.MountPointService" />
+  <reference id="rpcProviderRegistry" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry" />
+  <reference id="deviceTransactionManager" interface="org.opendaylight.transportpce.common.device.DeviceTransactionManager" />
+  <reference id="openRoadmInterfaces" interface="org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces" />
+  <reference id="portMapping" interface="org.opendaylight.transportpce.common.mapping.PortMapping" />
+  <reference id="crossConnect" interface="org.opendaylight.transportpce.common.crossconnect.CrossConnect" />
+
+  <odl:rpc-service id="olmService"
+      interface="org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.olm.rev170418.OlmService"/>
+
+  <bean id="openRoadmInterfaceFactory" class="org.opendaylight.transportpce.renderer.openroadminterface.OpenRoadmInterfaceFactory" >
+    <argument ref="portMapping" />
+    <argument ref="openRoadmInterfaces" />
+  </bean>
+
+  <bean id="deviceRenderer" class="org.opendaylight.transportpce.renderer.provisiondevice.DeviceRendererServiceImpl" >
+    <argument ref="dataBroker" />
+    <argument ref="deviceTransactionManager" />
+    <argument ref="openRoadmInterfaceFactory" />
+    <argument ref="openRoadmInterfaces" />
+    <argument ref="crossConnect" />
+  </bean>
+
+  <bean id="deviceRendererRPCImpl" class="org.opendaylight.transportpce.renderer.rpcs.DeviceRendererRPCImpl" >
+    <argument ref="deviceRenderer" />
+  </bean>
+
+  <bean id="networkModelWavelengthService"
+        class="org.opendaylight.transportpce.renderer.NetworkModelWavelengthServiceImpl">
+    <argument ref="dataBroker" />
+  </bean>
+
+  <bean id="rendererServiceOperations" class="org.opendaylight.transportpce.renderer.provisiondevice.RendererServiceOperationsImpl" >
+    <argument ref="deviceRenderer" />
+    <argument ref="olmService" />
     <argument ref="dataBroker" />
-    <argument ref="mountPointService" />
+    <argument ref="networkModelWavelengthService" />
+  </bean>
+
+  <bean id="rendererProvider" class="org.opendaylight.transportpce.renderer.RendererProvider"
+        init-method="init" destroy-method="close">
+    <argument ref="dataBroker"/>
+    <argument ref="mountPointService"/>
     <argument ref="rpcProviderRegistry" />
+    <argument ref="deviceRendererRPCImpl" />
+    <argument ref="rendererServiceOperations" />
+    <argument ref="portMapping" />
+    <argument ref="deviceTransactionManager" />
   </bean>
 
+  <service ref="deviceRenderer"
+           interface="org.opendaylight.transportpce.renderer.provisiondevice.DeviceRendererService" />
+
+  <service ref="rendererServiceOperations"
+           interface="org.opendaylight.transportpce.renderer.provisiondevice.RendererServiceOperations" />
+
 </blueprint>
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 (file)
index 0000000..1df295a
--- /dev/null
@@ -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 (file)
index 0000000..aaa6b12
--- /dev/null
@@ -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;
+    }
+}