exchange with GNPy to check path feasibility 85/81785/26
authorAhmed Triki <ahmed.triki@orange.com>
Thu, 25 Apr 2019 13:38:59 +0000 (15:38 +0200)
committerGuillaume Lambert <guillaume.lambert@orange.com>
Tue, 11 Jun 2019 09:58:35 +0000 (09:58 +0000)
- add gnpy data model in api module
- add package in pce to connect to gnpy
- modify PCESendingPceRPC to support gnpy
- move test-common DataStoreContext and binding converter classes to
  transportpce-common, adapt pom files dependencies

JIRA: TRNSPRTPCE-87
Change-Id: Ia93fbe0665427530afe33b623ee9aeb3d9f121bb
Signed-off-by: Ahmed Triki <ahmed.triki@orange.com>
Co-authored-by: Esther Le Rouzic <esther.lerouzic@orange.com>
23 files changed:
api/src/main/yang/gnpy-api@2019-01-03.yang [new file with mode: 0644]
api/src/main/yang/gnpy-eqpt-config@2018-11-19.yang [new file with mode: 0644]
api/src/main/yang/gnpy-network-topology@2018-12-14.yang [new file with mode: 0644]
api/src/main/yang/gnpy-path-computation-simplified@2019-05-02.yang [new file with mode: 0644]
common/pom.xml
common/src/main/java/org/opendaylight/transportpce/common/DataStoreContext.java [moved from test-common/src/main/java/org/opendaylight/transportpce/test/common/DataStoreContext.java with 95% similarity]
common/src/main/java/org/opendaylight/transportpce/common/DataStoreContextImpl.java [moved from test-common/src/main/java/org/opendaylight/transportpce/test/common/DataStoreContextImpl.java with 99% similarity]
common/src/main/java/org/opendaylight/transportpce/common/converter/AbstractDataObjectConverter.java [moved from test-common/src/main/java/org/opendaylight/transportpce/binding/converter/AbstractDataObjectConverter.java with 97% similarity]
common/src/main/java/org/opendaylight/transportpce/common/converter/JSONDataObjectConverter.java [moved from test-common/src/main/java/org/opendaylight/transportpce/binding/converter/JSONDataObjectConverter.java with 96% similarity]
common/src/main/java/org/opendaylight/transportpce/common/converter/XMLDataObjectConverter.java [moved from test-common/src/main/java/org/opendaylight/transportpce/binding/converter/XMLDataObjectConverter.java with 98% similarity]
common/src/main/java/org/opendaylight/transportpce/common/converter/api/DataObjectConverter.java [moved from test-common/src/main/java/org/opendaylight/transportpce/binding/converter/api/DataObjectConverter.java with 98% similarity]
pce/pom.xml
pce/src/main/java/org/opendaylight/transportpce/pce/PceGraph.java
pce/src/main/java/org/opendaylight/transportpce/pce/PceSendingPceRPCs.java
pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ConnectToGnpyServer.java [new file with mode: 0644]
pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ExtractTopoDataStoreImpl.java [new file with mode: 0644]
pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java [new file with mode: 0644]
pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperations.java [new file with mode: 0644]
pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java [new file with mode: 0644]
pce/src/test/java/org/opendaylight/transportpce/pce/utils/PceTestUtils.java
test-common/pom.xml
test-common/src/main/java/org/opendaylight/transportpce/test/AbstractTest.java
test-common/src/main/java/org/opendaylight/transportpce/test/DeviceWrapper.java

diff --git a/api/src/main/yang/gnpy-api@2019-01-03.yang b/api/src/main/yang/gnpy-api@2019-01-03.yang
new file mode 100644 (file)
index 0000000..b837c27
--- /dev/null
@@ -0,0 +1,44 @@
+module gnpy-api {
+  yang-version 1;
+  namespace "gnpy:gnpy-api";
+
+  prefix "gnpyapi";
+
+  import gnpy-network-topology  {
+    prefix "gnpynt";
+  }
+  import gnpy-path-computation-simplified  {
+    prefix "gnpypc";
+  }
+
+  organization
+    "Telecom Infra Project OOPT PSE Working Group";
+
+  contact
+    "WG Web:   <https://github.com/Telecominfraproject/oopt-gnpy>
+     contact:  <mailto:ahmed.triki@orange.com>
+     contact:  <mailto:esther.lerouzic@orange.com>
+   ";
+
+  description "YANG model for gnpy api input for path computation - TransportPCE preversion";
+
+  revision "2019-01-03" {
+    description "first draft";
+    reference "YANG model for api input for path computation with gnpy";
+  }
+
+  container gnpy-api{
+      description "This is the structure of the body of the request to gnpy";
+      container topology-file{
+          uses gnpynt:topo;
+          description
+              "Describe the topology file to connect to gnpy";
+      }
+  container service-file{
+          uses gnpypc:service;
+          description
+              "Describe the service file to connect to gnpy";
+      }
+  }
+
+}
diff --git a/api/src/main/yang/gnpy-eqpt-config@2018-11-19.yang b/api/src/main/yang/gnpy-eqpt-config@2018-11-19.yang
new file mode 100644 (file)
index 0000000..93f13b0
--- /dev/null
@@ -0,0 +1,88 @@
+module gnpy-eqpt-config {
+  yang-version 1;
+  namespace "gnpy:gnpy-eqpt-config";
+
+  prefix "gnpyeqpt";
+
+  organization
+    "Telecom Infra Project OOPT PSE
+     Working Group";
+
+  contact
+    "WG Web:   <https://github.com/Telecominfraproject/oopt-gnpy>
+     contact:  <mailto:ahmed.triki@orange.com>
+     contact:  <mailto:esther.lerouzic@orange.com>
+   ";
+
+  description "Base YANG model for gnpy equipment library input for path computation - transportPCE preversion";
+
+  revision "2018-11-19" {
+    description "first draft";
+    reference "Base YANG model for equipment library input for path computation with gnpy";
+  }
+
+  /*
+   * Identities
+
+
+  identity edfa-variety {
+    description "edfa variety" ;
+  }
+
+  identity fiber-variety {
+    description "base identity for fiber variety" ;
+  }
+
+  identity transceiver-variety {
+    description "base identity for transceiver variety" ;
+  }
+
+  */
+
+  list Edfa {
+    key type_variety;
+    leaf type_variety {
+      type string;
+      description "a unique name to ID the amplifier in the JSON/Excel template topology input file" ;
+    }
+  }
+
+
+  list Fiber {
+    key type_variety ;
+    leaf type_variety {
+      type string ;
+      }
+      description "a unique name to ID the fiber in the JSON or Excel template topology input file" ;
+    }
+  }
+
+  list Transceiver{
+    key type_variety ;
+    leaf type_variety {
+      type string ;
+      }
+      description "a unique name to ID the transceiver in the JSON or Excel template topology input file" ;
+    }
+    list mode {
+      key format ;
+      leaf format {
+        type string ;
+        description "unique name of the mode" ;
+      }
+    }
+  }
+
+  container Spans {
+
+  }
+
+  container Roadms {
+
+  }
+
+  container SI {
+
+  }
+}
+
diff --git a/api/src/main/yang/gnpy-network-topology@2018-12-14.yang b/api/src/main/yang/gnpy-network-topology@2018-12-14.yang
new file mode 100644 (file)
index 0000000..c49d4f1
--- /dev/null
@@ -0,0 +1,278 @@
+module gnpy-network-topology {
+  yang-version 1;
+  namespace "gnpy:gnpy-network-topology";
+
+  prefix "gnpynt";
+
+
+  import gnpy-eqpt-config {
+    prefix "geqpt";
+  }
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  organization
+    "Telecom Infra Project OOPT PSE Working Group";
+
+  contact
+    "WG Web:   <https://github.com/Telecominfraproject/oopt-gnpy>
+     contact:  <mailto:ahmed.triki@orange.com>
+     contact:  <mailto:esther.lerouzic@orange.com>
+   ";
+
+  description "YANG model for gnpy network input for path computation - transportPCE preversion";
+
+  revision "2018-12-14" {
+    description "first draft";
+    reference "YANG model for network input for path computation with gnpy";
+  }
+
+  identity type-element {
+    description
+      "Base identity for element type";
+  }
+
+  identity Transceiver {
+    base type-element;
+    description
+      " Transceiver element";
+  }
+
+  identity Fiber {
+    base type-element;
+    description
+      "Fiber element";
+  }
+
+  identity Roadm {
+    base type-element;
+    description
+      "Roadm element";
+  }
+
+  identity Edfa {
+    base type-element;
+    description
+      "Edfa element";
+  }
+
+  identity Fused {
+    base type-element;
+    description
+      "Fused element";
+  }
+
+  identity length-unit {
+    description "length unit" ;
+  }
+
+  identity km {
+    base length-unit ;
+    description "kilometers" ;
+  }
+
+  identity m{
+    base length-unit ;
+    description "meter" ;
+  }
+  typedef Coordinate {
+    type  decimal64 {
+      fraction-digits 6;
+    }
+  }
+
+  typedef te-node-id {
+    type inet:ip-address;
+    description
+          "An identifier for a node in a topology.
+           The identifier is represented as 32-bit unsigned integer in
+           the dotted-quad notation.
+           This attribute is mapped to Router ID in
+           RFC3630, RFC5329, RFC5305, and RFC6119.";
+   }
+
+  typedef Coef {
+    type decimal64 {
+      fraction-digits 2;
+    }
+  }
+
+
+  grouping location-attributes {
+      container location {
+        leaf city {
+          type string;
+          mandatory true ;
+        }
+        leaf region {
+          type string;
+          mandatory true ;
+        }
+        leaf latitude {
+          type Coordinate;
+          mandatory true ;
+        }
+        leaf longitude {
+          type Coordinate;
+          mandatory true ;
+        }
+    }
+  }
+
+  grouping fiber-params {
+    description "....." ;
+    leaf length {
+      mandatory true ;
+      type decimal64 {
+        fraction-digits 2;
+      }
+    }
+    leaf loss_coef{
+      mandatory true ;
+      type decimal64 {
+        fraction-digits 2;
+      }
+    }
+    leaf length_units{
+      type identityref {
+        base length-unit ;
+      }
+      mandatory true ;
+    }
+    leaf att_in{
+      type decimal64 {
+        fraction-digits 2;
+      }
+      mandatory true ;
+    }
+    leaf con_in{
+      type decimal64 {
+        fraction-digits 2;
+      }
+      mandatory true ;
+    }
+    leaf con_out{
+      type decimal64 {
+        fraction-digits 2;
+      }
+      mandatory true ;
+    }
+  }
+
+  grouping edfa-params {
+    container operational {
+      leaf gain-target {
+        type decimal64 {
+          fraction-digits 2;
+        }
+        mandatory true ;
+        units dB ;
+        description ".." ;
+      }
+      leaf tilt-target {
+        type decimal64 {
+          fraction-digits 2;
+        }
+        mandatory true ;
+        description ".." ;
+      }
+      leaf out-voa {
+        type decimal64 {
+          fraction-digits 2;
+        }
+        mandatory true ;
+        units dB ;
+        description ".." ;
+      }
+      description "Operational values for the Edfa " ;
+    }
+  }
+
+  grouping roadm-params{
+    leaf  target_pch_out_db{
+      type decimal64 {
+        fraction-digits 2;
+      }
+      units dB ;
+      description ".." ;
+    }
+  }
+
+  grouping transceiver-params{
+
+  }
+
+  grouping fused-params{
+
+  }
+
+  grouping element-type-choice{
+    choice element-type{
+      case Edfa{
+        when "type = 'Edfa'" ;
+        uses edfa-params ;
+      }
+      case FiberRoadm{
+        container params {
+          choice fiberroadm{
+            case Fiber{
+              when "type = 'Fiber'" ;
+              uses fiber-params ;
+            }
+            case Roadm{
+              when "type = 'Roadm'" ;
+              uses roadm-params ;
+            }
+          }
+        }
+      }
+      case Transceiver{
+        when "type = 'Transceiver'" ;
+      }
+
+      case Fused{
+        when "type = 'Fused'" ;
+      }
+    }
+  }
+
+  grouping topo {
+      list elements {
+        key uid;
+        leaf uid {
+            type string;
+        }
+        leaf type {
+          type identityref {
+            base type-element ;
+          }
+          mandatory true ;
+        }
+        leaf type_variety {
+            type string ;
+            mandatory false ;
+          }
+        container metadata {
+          uses location-attributes ;
+        }
+
+        uses element-type-choice ;
+      }
+
+      list connections {
+        config false ;
+        leaf from_node {
+          type leafref{
+            path "/topo/elements/uid" ;
+          }
+        }
+        leaf to_node {
+          type leafref{
+            path "/topo/elements/uid" ;
+          }
+        }
+      }
+  }
+}
diff --git a/api/src/main/yang/gnpy-path-computation-simplified@2019-05-02.yang b/api/src/main/yang/gnpy-path-computation-simplified@2019-05-02.yang
new file mode 100644 (file)
index 0000000..64979b5
--- /dev/null
@@ -0,0 +1,595 @@
+module gnpy-path-computation-simplified {
+  yang-version 1;
+  namespace "gnpy:path";
+
+  prefix "gnpypc";
+
+  import ietf-yang-types {
+    prefix "yang-types";
+  }
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+    organization
+    "Telecom Infra Project OOPT PSE Working Group";
+
+  contact
+    "WG Web:   <https://github.com/Telecominfraproject/oopt-gnpy>
+     contact:  <mailto:ahmed.triki@orange.com>
+     contact:  <mailto:esther.lerouzic@orange.com>
+   ";
+
+  description "YANG model for gnpy path computation simplified for transportPCE";
+
+  revision "2019-05-02" {
+    description "second draft with detailed blocking reasons";
+    reference "YANG model for path computation with gnpy inputs";
+  }
+
+  grouping effective-freq-slot{
+         /* content copied from ietf-flexi-grid-media-channel, because only M and N are needed
+            from the initial grouping.
+         */
+         description "The effective frequency slot is an attribute
+            of a media channel and, being a frequency slot, it is
+            described by its nominal central frequency and slot
+            width";
+         reference "rfc7698";
+            leaf N {
+               type int32;
+               description
+                  "Is used to determine the Nominal Central
+                  Frequency. The set of nominal central frequencies
+                  can be built using the following expression:
+                     f = 193.1 THz + n x 0.00625 THz,
+                  where 193.1 THz is ITU-T ''anchor frequency'' for
+                  transmission over the C band, n is a positive or
+                  negative integer including 0.";
+               reference "rfc7698";
+            }
+            leaf M {
+               type int32;
+               description
+                  "Is used to determine the slot width. A slot width
+                  is constrained to be M x SWG (that is, M x 12.5 GHz),
+                  where M is an integer greater than or equal to 1.";
+               reference "rfc7698";
+    }
+  }
+
+  grouping gnpy-specific-parameters{
+    description
+      "This grouping defines the gnpy specific parameters for requests.";
+        leaf technology {
+            type string;
+            default "flexi-grid";
+            description
+          "Data plane technology type.";
+          }
+      leaf trx_type {
+        type string ;
+        mandatory true;
+        description "name of the transponder type (to be read from equipment library";
+
+      }
+      leaf trx_mode {
+        type string ;
+        description "name of the transponder mode (to be read from equipment library";
+
+      }
+      list effective-freq-slot {
+        key "N";
+        uses effective-freq-slot ;
+      }
+      leaf spacing {
+        mandatory true;
+        type decimal64 {
+          fraction-digits 1;
+        }
+        units Hz;
+        description
+          "It is the spacing between channels assuming full load with
+          same channels as the requested one. multiple of 12.5 GHz";
+
+      }
+      leaf max-nb-of-channel{
+        type uint32 ;
+        description "Nb of channel to take into account for the full load case.
+        ";
+
+      }
+      leaf output-power{
+        type decimal64 {
+          fraction-digits 5;
+        }
+        units W;
+        description "optical power setting to be used for the propagation";
+
+      }
+      leaf path_bandwidth{
+        type decimal64 {
+          fraction-digits 5;
+        }
+        mandatory true;
+        units bit/s;
+        description "Capacity required";
+      }
+  }
+
+  identity SNR-bandwidth {
+    base path-metric-type;
+    description
+      "A metric that records SNR in signal bandwidth";
+  }
+
+  identity OSNR-bandwidth {
+    base path-metric-type;
+    description
+      "A metric that records OSNR in signal bandwidth";
+  }
+
+  identity SNR-0.1nm {
+    base path-metric-type;
+    description
+      "A metric that records SNR in 0.1nm";
+  }
+
+  identity OSNR-0.1nm {
+    base path-metric-type;
+    description
+      "A metric that records OSNR in 0.1nm";
+  }
+
+  identity reference_power {
+    base path-metric-type;
+    description
+      "to be revised";
+  }
+
+  identity path_bandwidth {
+     base path-metric-type;
+     description
+       "to be revised";
+  }
+
+  grouping transponder{
+        leaf transponder-type {
+        type string ;
+        description
+          "transponder type.";
+          }
+      leaf transponder-mode {
+        type string ;
+        description
+          "transponder mode.";
+          }
+  }
+
+  grouping hop-attribute{
+    description
+      "This grouping defines the hop attribute parameters for request or response";
+    choice hop-type{
+      case tsp {
+        container transponder{
+          uses transponder ;
+        }
+      }
+      case regen {
+        container regenerator{
+          leaf regenerator-id{
+            type string ;
+          }
+          uses transponder ;
+        }
+      }
+      case pow {
+        container optical-power{
+          leaf optical-power{
+            type decimal64 {
+              fraction-digits 5;
+            }
+            units W;
+            description "hop output (input??) power";
+          }
+        }
+      }
+    }
+
+  }
+
+  identity path-metric-type {
+    description
+      "Base identity for path metric type";
+  }
+
+  identity route-usage-type {
+    description
+      "Base identity for route usage";
+  }
+
+  identity route-include-ero {
+    base route-usage-type;
+    description
+      "Include ERO from route";
+  }
+
+  identity route-exclude-ero {
+    base route-usage-type;
+    description
+      "Exclude ERO from route";
+  }
+
+  identity route-exclude-srlg {
+    base route-usage-type;
+    description
+      "Exclude SRLG from route";
+  }
+
+  typedef te-hop-type {
+    type enumeration {
+      enum LOOSE {
+        description
+          "loose hop in an explicit path";
+      }
+      enum STRICT {
+        description
+          "strict hop in an explicit path";
+      }
+    }
+    description
+     "enumerated type for specifying loose or strict
+      paths";
+    reference "RFC3209: section-4.3.2";
+  }
+
+  typedef te-path-disjointness {
+    type bits {
+      bit node {
+        position 0;
+        description "Node disjoint.";
+      }
+      bit link {
+        position 1;
+        description "Link disjoint.";
+      }
+      bit srlg {
+        position 2;
+        description "SRLG (Shared Risk Link Group) disjoint.";
+      }
+    }
+    description
+      "Type of the resource disjointness for a TE tunnel path.";
+    reference
+      "RFC4872: RSVP-TE Extensions in Support of End-to-End
+       Generalized Multi-Protocol Label Switching (GMPLS)
+       Recovery";
+  } // te-path-disjointness
+
+  typedef te-node-id {
+    type inet:ip-address;
+    description
+      "An identifier for a node in a topology.
+       The identifier is represented as 32-bit unsigned integer in
+       the dotted-quad notation.
+       This attribute is mapped to Router ID in
+       RFC3630, RFC5329, RFC5305, and RFC6119.";
+  }
+
+  typedef te-tp-id {
+    type union {
+      type uint32;          // Unnumbered
+      type inet:ip-address; // IPv4 or IPv6 address
+    }
+    description
+      "An identifier for a TE link endpoint on a node.
+       This attribute is mapped to local or remote link identifier in
+       RFC3630 and RFC5305.";
+  }
+
+    typedef accumulated-metric-type {
+      type union {
+        type uint64;
+        type decimal64 {
+          fraction-digits 2;
+        }
+      }
+      description
+          "type useable for accumulative-value";
+  }
+
+  grouping path-route-objects {
+    description
+      "List of EROs to be included or excluded when performing
+       the path computation.";
+    container explicit-route-objects {
+      description
+        "Container for the route object list";
+      list route-object-include-exclude {
+        key index;
+        description
+          "List of explicit route objects to include or
+           exclude in path computation";
+        leaf explicit-route-usage {
+          type identityref {
+            base route-usage-type;
+          }
+          description "Explicit-route usage.";
+        }
+        uses explicit-route-hop ;
+      }
+    }
+  }
+
+  grouping generic-path-disjointness {
+    description "Path disjointness grouping";
+    leaf disjointness {
+      type te-path-disjointness;
+      description
+        "The type of resource disjointness.
+         Under primary path, disjointness level applies to
+         all secondary LSPs. Under secondary, disjointness
+         level overrides the one under primary";
+    }
+  }
+
+  grouping common-path-constraints-attributes {
+    description
+      "Common path constraints configuration grouping";
+    uses common-constraints_config;
+  }
+
+  grouping generic-path-constraints {
+    description
+      "Global named path constraints configuration
+      grouping";
+    container path-constraints {
+      description "TE named path constraints container";
+      uses common-path-constraints-attributes;
+    }
+  }
+
+
+  grouping explicit-route-hop {
+    description
+      "The explicit route subobject grouping";
+    leaf index {
+      type uint32;
+      description "ERO subobject index";
+    }
+    choice type {
+      description
+        "The explicit route subobject type";
+      case num-unnum-hop {
+        container num-unnum-hop {
+          leaf node-id {
+            //type te-node-id;
+            type string;
+            description
+              "The identifier of a node in the TE topology.";
+          }
+          leaf link-tp-id {
+            //type te-tp-id;
+            type string;
+            description
+              "TE link termination point identifier. The combination
+              of TE link ID and the TE node ID is used to identify an
+              unnumbered TE link.";
+          }
+          leaf hop-type {
+            type te-hop-type;
+            description "strict or loose hop";
+          }
+          description
+            "Numbered and Unnumbered link/node explicit route
+            subobject";
+        }
+      }
+      case label {
+        container label-hop {
+          description "Label hop type";
+          uses effective-freq-slot;
+        }
+        description
+          "The Label ERO subobject";
+      }
+      case hop-attribute{
+        uses gnpypc:hop-attribute ;
+      }
+    }
+  }
+
+  grouping common-constraints_config {
+    description
+      "Common constraints grouping that can be set on
+       a constraint set or directly on the tunnel";
+
+    container te-bandwidth {
+      uses gnpy-specific-parameters ;
+      description
+        "A requested bandwidth to use for path computation";
+    }
+  }
+
+  grouping end-points {
+    description
+      "Common grouping to define the TE tunnel end-points";
+
+    leaf source {
+      type inet:ip-address;
+      description "TE tunnel source address.";
+    }
+    leaf destination {
+      type inet:ip-address;
+      description "P2P tunnel destination address";
+    }
+    leaf src-tp-id {
+      type binary;
+      description "TE tunnel source termination point identifier.";
+    }
+    leaf dst-tp-id {
+      type binary;
+
+      description "TE tunnel destination termination point
+identifier.";
+    }
+  }
+
+  grouping synchronization-info {
+    description "Information for sync";
+    list synchronization {
+      key "synchronization-id";
+      description "sync list";
+      leaf synchronization-id {
+        type uint32;
+        description "index";
+      }
+      container svec {
+        description
+         "Synchronization VECtor";
+        leaf relaxable {
+          type boolean;
+          default true;
+          description
+           "If this leaf is true, path computation process is free
+to ignore svec content.
+            otherwise it must take into account this svec.";
+        }
+        uses generic-path-disjointness;
+        leaf-list request-id-number {
+          type uint32;
+          description "This list reports the set of M path computation requests that must be synchronized.";
+        }
+      }
+    }
+  }
+
+  grouping generic-path-properties {
+    description "TE generic path properties grouping";
+    container path-properties {
+      config false;
+      description "The TE path properties";
+      list path-metric {
+        key metric-type;
+        description "TE path metric type";
+        leaf metric-type {
+          type identityref {
+            base path-metric-type;
+          }
+          description "TE path metric type";
+        }
+        leaf accumulative-value {
+          type decimal64 {
+              fraction-digits 2;
+          }
+          description "TE path metric accumulative value";
+        }
+      }
+//      container path-route-objects {
+//        description
+//          "Container for the list of route objects either returned by
+//           the computation engine or actually used by an LSP";
+//        list path-route-object {
+//          key index;
+//          description
+//            "List of route objects either returned by the computation
+//             engine or actually used by an LSP";
+//          uses explicit-route-hop;
+//        }
+//      }
+      list path-route-objects {
+          description
+            "Container for the list of route objects either returned by
+             the computation engine or actually used by an LSP";
+          container path-route-object {
+            description
+              "List of route objects either returned by the computation
+               engine or actually used by an LSP";
+            uses explicit-route-hop;
+          }
+        }
+    }
+  }
+
+  grouping path-info {
+    uses generic-path-properties;
+    description "Path computation output information";
+  }
+
+// adding some blocking reasons and info on path in case of blocking
+
+  grouping no-path-info {
+    description "no-path-info";
+    container no-path {
+      presence "Response without path information, due to failure
+        performing the path computation";
+      leaf no-path {
+        type string;
+        mandatory true ;
+        description
+          "returned blocking reasons:
+            NO_PATH
+            NO_COMPUTED_SNR
+            NO_FEASIBLE_BAUDRATE_WITH_SPACING
+            NO_PATH_WITH_CONSTRAINT
+            NO_FEASIBLE_MODE
+            MODE_NOT_FEASIBLE
+            NO_SPECTRUM
+          ";
+        }
+      uses generic-path-properties ;
+      description "if path computation cannot identify a path,
+        rpc returns no path.";
+    }
+  }
+
+  /* TODO : correct the following with good trees:
+  *  te:tunnels-rpc/te:input/te:tunnel-info
+  *  te:tunnels-rpc/te:output/te:result
+  */
+   grouping service {
+     list path-request {
+       key "request-id";
+       description "request-list";
+       leaf request-id {
+         type uint32;
+         mandatory true;
+         description "Each path computation request is uniquely identified by the request-id-number.";
+       }
+
+       uses end-points;
+       uses path-route-objects;
+       uses generic-path-constraints;
+     }
+     uses synchronization-info;
+   }
+
+   grouping result {
+     list response {
+       key response-id;
+       config false;
+       description "response";
+       leaf response-id {
+         type uint32;
+         description
+         "The list key that has to reuse request-id-number.";
+       }
+       choice response-type {
+         config false;
+         description "response-type";
+         case no-path-case {
+           uses no-path-info;
+         }
+         case path-case {
+           uses path-info;
+           description "Path computation service.";
+         }
+       }
+     }
+   }
+   container result {
+     uses result;
+     description
+     "Describe the service file to connect to gnpy";
+   }
+}
index 17f0ecd223c5fe50366d4e55c8a977c0ce4482d6..38dbb864be83137583df15f6f8964b448ff5e7e7 100644 (file)
@@ -8,9 +8,9 @@
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
-        <groupId>org.opendaylight.odlparent</groupId>
-        <artifactId>bundle-parent</artifactId>
-        <version>4.0.10</version>
+        <groupId>org.opendaylight.mdsal</groupId>
+        <artifactId>binding-parent</artifactId>
+        <version>3.0.8</version>
         <relativePath />
     </parent>
 
             <version>${project.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-codec-xml</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-codec-gson</artifactId>
+        </dependency>
+
         <!-- Testing Dependencies -->
         <dependency>
             <groupId>junit</groupId>
similarity index 95%
rename from test-common/src/main/java/org/opendaylight/transportpce/test/common/DataStoreContext.java
rename to common/src/main/java/org/opendaylight/transportpce/common/DataStoreContext.java
index 11235124037d0593405a7f5c37b06b51da41d704..b6eaf86c1fee1c362ce755fdca8b4e6dbaed8639 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.test.common;
+package org.opendaylight.transportpce.common;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
similarity index 99%
rename from test-common/src/main/java/org/opendaylight/transportpce/test/common/DataStoreContextImpl.java
rename to common/src/main/java/org/opendaylight/transportpce/common/DataStoreContextImpl.java
index 2b7a4d27b1b086860e34572d08820087e195a51f..2b470112ffffeb2e563afa7f39b63ffc27ac9e19 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.test.common;
+package org.opendaylight.transportpce.common;
 
 import com.google.common.collect.ClassToInstanceMap;
 import com.google.common.collect.ImmutableMap;
similarity index 97%
rename from test-common/src/main/java/org/opendaylight/transportpce/binding/converter/AbstractDataObjectConverter.java
rename to common/src/main/java/org/opendaylight/transportpce/common/converter/AbstractDataObjectConverter.java
index 6a44ebfe8360b92800c179fa89e25a5aa7cc2d6b..924dad513e5450bdce0c4b4219ad164ef13a61bd 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.binding.converter;
+package org.opendaylight.transportpce.common.converter;
 
 import com.google.common.base.Preconditions;
 import java.util.Map;
@@ -13,7 +13,7 @@ import java.util.Map.Entry;
 import java.util.Optional;
 import javax.annotation.Nonnull;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
-import org.opendaylight.transportpce.binding.converter.api.DataObjectConverter;
+import org.opendaylight.transportpce.common.converter.api.DataObjectConverter;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
similarity index 96%
rename from test-common/src/main/java/org/opendaylight/transportpce/binding/converter/JSONDataObjectConverter.java
rename to common/src/main/java/org/opendaylight/transportpce/common/converter/JSONDataObjectConverter.java
index c0fc3256fe88bbecf1588fcdc89b725b2778ebef..8e992b707c93da3825fc04e324a241e49a85aca3 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.binding.converter;
+package org.opendaylight.transportpce.common.converter;
 
 import com.google.gson.stream.JsonReader;
 import com.google.gson.stream.JsonWriter;
@@ -18,8 +18,8 @@ import java.io.Writer;
 import java.util.Optional;
 import javax.annotation.Nonnull;
 import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.transportpce.binding.converter.api.DataObjectConverter;
-import org.opendaylight.transportpce.test.common.DataStoreContext;
+import org.opendaylight.transportpce.common.DataStoreContext;
+import org.opendaylight.transportpce.common.converter.api.DataObjectConverter;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
similarity index 98%
rename from test-common/src/main/java/org/opendaylight/transportpce/binding/converter/XMLDataObjectConverter.java
rename to common/src/main/java/org/opendaylight/transportpce/common/converter/XMLDataObjectConverter.java
index 40c8420ed210013c55f22e3ce04ca2b7aa1832c8..5afbb407571ee08efe25fd5671a10667c375234f 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.binding.converter;
+package org.opendaylight.transportpce.common.converter;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -24,7 +24,7 @@ import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
-import org.opendaylight.transportpce.test.common.DataStoreContext;
+import org.opendaylight.transportpce.common.DataStoreContext;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
similarity index 98%
rename from test-common/src/main/java/org/opendaylight/transportpce/binding/converter/api/DataObjectConverter.java
rename to common/src/main/java/org/opendaylight/transportpce/common/converter/api/DataObjectConverter.java
index d70606f1d2122a68d92244bed1936fd55c60dac6..fcd2bda63aead60cf30c2e2e3f74a29cc81920a2 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.binding.converter.api;
+package org.opendaylight.transportpce.common.converter.api;
 
 import java.io.InputStream;
 import java.io.Reader;
index 8dd6f3abe69758b63b2b2697eab31a88916611cb..b0f5c056cbb8c63e045565e24082ba578cd600d8 100644 (file)
@@ -15,9 +15,9 @@ Author: Martial Coulibaly <martial.coulibaly@gfi.com> on behalf of Orange
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
-    <groupId>org.opendaylight.odlparent</groupId>
-    <artifactId>bundle-parent</artifactId>
-    <version>4.0.10</version>
+    <groupId>org.opendaylight.mdsal</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>3.0.8</version>
     <relativePath/>
   </parent>
 
@@ -55,6 +55,11 @@ Author: Martial Coulibaly <martial.coulibaly@gfi.com> on behalf of Orange
       <artifactId>transportpce-networkmodel</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>transportpce-common</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.controller.thirdparty</groupId>
       <artifactId>net.sf.jung2</artifactId>
@@ -72,6 +77,7 @@ Author: Martial Coulibaly <martial.coulibaly@gfi.com> on behalf of Orange
       <artifactId>mockito-core</artifactId>
       <scope>test</scope>
     </dependency>
+
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>test-common</artifactId>
@@ -84,7 +90,10 @@ Author: Martial Coulibaly <martial.coulibaly@gfi.com> on behalf of Orange
       <version>1.9.2-SNAPSHOT</version>
       <scope>test</scope>
     </dependency>
-
+    <dependency>
+      <groupId>org.opendaylight.mdsal</groupId>
+      <artifactId>mdsal-binding-dom-codec</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
index 390a7ddb716423d0b12d3fea25f713981dabb1fb..89013ca2643dc46d4dcd00cbeccb7b29241862b1 100644 (file)
@@ -158,25 +158,17 @@ public class PceGraph {
     private boolean populateGraph(Map<NodeId, PceNode> allNodes) {
 
         cleanupGraph();
-
         Iterator<Map.Entry<NodeId, PceNode>> nodes = allNodes.entrySet().iterator();
         while (nodes.hasNext()) {
-
             Map.Entry<NodeId, PceNode> node = nodes.next();
-
             PceNode pcenode = node.getValue();
             List<PceLink> links = pcenode.getOutgoingLinks();
-
             LOG.info("In populateGraph: use node for graph {}", pcenode.toString());
-
             for (PceLink link : links) {
                 LOG.info("In populateGraph: add edge to graph {}", link.toString());
                 addLinkToGraph(link);
-
             }
-
         }
-
         return true;
     }
 
@@ -186,13 +178,10 @@ public class PceGraph {
 
         for (PceNode node : allNodes) {
             List<PceLink> links = node.getOutgoingLinks();
-
             LOG.debug("In populateGraph: use node for graph {}", node.toString());
-
             for (PceLink link : links) {
                 LOG.debug("In populateGraph: add edge to graph {}", link.toString());
                 addLinkToGraph(link);
-
             }
 
         }
index 324b022608b51b717c0d5a5c9f6abccabf4bed87..bada4cb4b0cd626f560e104724419de6aede3396 100644 (file)
@@ -8,13 +8,28 @@
 
 package org.opendaylight.transportpce.pce;
 
+import java.util.List;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.transportpce.pce.PceResult.LocalCause;
+import org.opendaylight.transportpce.pce.gnpy.ConnectToGnpyServer;
+import org.opendaylight.transportpce.pce.gnpy.ExtractTopoDataStoreImpl;
+import org.opendaylight.transportpce.pce.gnpy.GnpyResult;
+import org.opendaylight.transportpce.pce.gnpy.ServiceDataStoreOperationsImpl;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApiBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.gnpy.api.ServiceFileBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.gnpy.api.TopologyFileBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Connections;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Elements;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.service.PathRequest;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.Synchronization;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.PathComputationRequestInput;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.service.path.rpc.result.PathDescriptionBuilder;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.AToZDirection;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirection;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.RoutingConstraintsSp.PceMetric;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,16 +53,14 @@ public class PceSendingPceRPCs {
      * <code>false</code> cancelresourcereserve .
      */
     private PathDescriptionBuilder pathDescription;
-
     private PathComputationRequestInput input;
     private DataBroker dataBroker;
-
     private PceConstraints pceHardConstraints = new PceConstraints();
     private PceConstraints pceSoftConstraints = new PceConstraints();
+    private Long gnpyRequestId = new Long(0);
 
     public PceSendingPceRPCs() {
         setPathDescription(null);
-
         this.input = null;
         this.dataBroker = null;
     }
@@ -70,80 +83,135 @@ public class PceSendingPceRPCs {
         LOG.info("cancelResourceReserve ...");
     }
 
-    public void pathComputation() {
+    public void pathComputation() throws Exception {
+        // Comput the path according to the constraints of PCE
+        rc = pathComputationPCE();
+
+        LOG.info("setPathDescription ...");
+        AToZDirection atoz = rc.getAtoZDirection();
+        ZToADirection ztoa = rc.getZtoADirection();
+        ConnectToGnpyServer connectToGnpy = new ConnectToGnpyServer();
+        if ((atoz == null) || (atoz.getAToZ() == null)) {
+            rc.setRC("400");
+            LOG.warn("In PCE pathComputation: empty atoz path after description: result = {}", rc.toString());
+            return;
+        } else {
+            // Send the computed path A-to-Z to GNPY tool
+            if (connectToGnpy.isGnpyURLExist()) {
+                ExtractTopoDataStoreImpl xtrTopo = new ExtractTopoDataStoreImpl(dataBroker, input, atoz, gnpyRequestId);
+                gnpyRequestId++;
+                List<Elements> elementsList1 = xtrTopo.getElements();
+                List<Connections> connectionsList1 = xtrTopo.getConnections();
+                List<PathRequest> pathRequestList1 = xtrTopo.getPathRequest();
+                List<Synchronization> synchronizationList1 = xtrTopo.getSynchronization();
+                String gnpyResponse1 = getGnpyResponse(elementsList1, connectionsList1, pathRequestList1,
+                    synchronizationList1);
+                // Analyze the response
+                if (gnpyResponse1 != null) {
+                    GnpyResult gnpyResult = new GnpyResult(gnpyResponse1);
+                    LOG.debug("GNPy result created");
+                    gnpyResult.analyzeResult();
+                } else {
+                    LOG.error("No response from the GNPy server");
+                }
+            }
+        }
+
+        if ((ztoa == null) || (ztoa.getZToA() == null)) {
+            rc.setRC("400");
+            LOG.error("In pathComputation empty ztoa path after description: result = {}", rc.toString());
+            return;
+        } else {
+            // Send the computed path Z-to-A to GNPY tool
+            if (connectToGnpy.isGnpyURLExist()) {
+                ExtractTopoDataStoreImpl xtrTopo = new ExtractTopoDataStoreImpl(dataBroker, input, ztoa, gnpyRequestId);
+                gnpyRequestId++;
+                List<Elements> elementsList2 = xtrTopo.getElements();
+                List<Connections> connectionsList2 = xtrTopo.getConnections();
+                List<PathRequest> pathRequestList2 = xtrTopo.getPathRequest();
+                List<Synchronization> synchronizationList2 = xtrTopo.getSynchronization();
+                String gnpyResponse2 = getGnpyResponse(elementsList2, connectionsList2, pathRequestList2,
+                        synchronizationList2);
+                // Analyze the response
+                if (gnpyResponse2 != null) {
+                    GnpyResult gnpyResult = new GnpyResult(gnpyResponse2);
+                    LOG.debug("GNPy result created");
+                    gnpyResult.analyzeResult();
+                } else {
+                    LOG.info("No response from the GNPy server");
+                }
+            }
+        }
+        // Set the description of the path
+        setPathDescription(new PathDescriptionBuilder().setAToZDirection(atoz).setZToADirection(ztoa));
+        LOG.info("In pathComputation Graph is Found");
+    }
+
+    public PceResult pathComputationPCE() {
         LOG.info("PathComputation ...");
 
         PceConstraintsCalc constraints = new PceConstraintsCalc(input, dataBroker);
         pceHardConstraints = constraints.getPceHardConstraints();
         pceSoftConstraints = constraints.getPceSoftConstraints();
 
-
         LOG.info("nwAnalizer ...");
-        PceCalculation nwAnalizer = new PceCalculation(input, dataBroker,
-                pceHardConstraints, pceSoftConstraints, rc);
+        PceCalculation nwAnalizer = new PceCalculation(input, dataBroker, pceHardConstraints, pceSoftConstraints, rc);
         nwAnalizer.calcPath();
         rc = nwAnalizer.getReturnStructure();
         if (!rc.getStatus()) {
             LOG.error("In pathComputation nwAnalizer: result = {}", rc.toString());
-            return;
+            return null;
         }
 
         LOG.info("PceGraph ...");
         LOG.warn("PathComputation: aPceNode '{}' - zPceNode '{}'", nwAnalizer.getaPceNode(), nwAnalizer.getzPceNode());
-        PceGraph graph = new PceGraph(
-                nwAnalizer.getaPceNode(),
-                nwAnalizer.getzPceNode(),
-                nwAnalizer.getAllPceNodes(),
+        PceGraph graph = new PceGraph(nwAnalizer.getaPceNode(), nwAnalizer.getzPceNode(), nwAnalizer.getAllPceNodes(),
                 pceHardConstraints, pceSoftConstraints, rc);
         graph.calcPath();
         rc = graph.getReturnStructure();
         if (!rc.getStatus()) {
-
             LOG.warn("In pathComputation : Graph return without Path ");
-
             // TODO fix. This is quick workaround for algorithm problem
             if ((rc.getLocalCause() == LocalCause.TOO_HIGH_LATENCY)
-                && (pceHardConstraints.getPceMetrics() == PceMetric.HopCount)
-                && (pceHardConstraints.getMaxLatency() != -1)) {
-
+                    && (pceHardConstraints.getPceMetrics() == PceMetric.HopCount)
+                    && (pceHardConstraints.getMaxLatency() != -1)) {
                 pceHardConstraints.setPceMetrics(PceMetric.PropagationDelay);
                 graph = patchRerunGraph(graph);
             }
-
             if (!rc.getStatus()) {
                 LOG.error("In pathComputation graph.calcPath: result = {}", rc.toString());
-                return;
+                return null;
             }
         }
 
         LOG.info("PcePathDescription ...");
-        PcePathDescription description = new PcePathDescription(
-                graph.getPathAtoZ(),
-                nwAnalizer.getAllPceLinks(), rc);
+        PcePathDescription description = new PcePathDescription(graph.getPathAtoZ(), nwAnalizer.getAllPceLinks(), rc);
         description.buildDescriptions();
         rc = description.getReturnStructure();
         if (!rc.getStatus()) {
             LOG.error("In pathComputation description: result = {}", rc.toString());
-            return;
+            return null;
         }
+        return rc;
+    }
 
-        LOG.info("setPathDescription ...");
-        AToZDirection atoz = rc.getAtoZDirection();
-        ZToADirection ztoa = rc.getZtoADirection();
-        if ((atoz == null) || (atoz.getAToZ() == null)) {
-            rc.setRC("400");
-            LOG.error("In pathComputation empty atoz path after description: result = {}", rc.toString());
-            return;
-        }
-        if ((ztoa == null) || (ztoa.getZToA() == null)) {
-            rc.setRC("400");
-            LOG.error("In pathComputation empty ztoa path after description: result = {}", rc.toString());
-            return;
-        }
-        setPathDescription(new PathDescriptionBuilder()
-                .setAToZDirection(atoz)
-                .setZToADirection(ztoa));
-        LOG.info("In pathComputation Graph is Found");
+    private String getGnpyResponse(List<Elements> elementsList, List<Connections> connectionsList,
+            List<PathRequest> pathRequestList, List<Synchronization> synchronizationList) throws Exception {
+        GnpyApi gnpyApi = new GnpyApiBuilder()
+                .setTopologyFile(
+                        new TopologyFileBuilder().setElements(elementsList).setConnections(connectionsList).build())
+                .setServiceFile(new ServiceFileBuilder().setPathRequest(pathRequestList).build()).build();
+        InstanceIdentifier<GnpyApi> idGnpyApi = InstanceIdentifier.builder(GnpyApi.class).build();
+        String gnpyJson;
+        ServiceDataStoreOperationsImpl sd = new ServiceDataStoreOperationsImpl(dataBroker);
+        gnpyJson = sd.createJsonStringFromDataObject(idGnpyApi, gnpyApi);
+        LOG.debug("GNPy  Id: {} / json created : {}", idGnpyApi, gnpyJson);
+        ConnectToGnpyServer connect = new ConnectToGnpyServer();
+        String gnpyJsonModified = gnpyJson.replace("gnpy-eqpt-config:", "")
+                .replace("gnpy-path-computation-simplified:", "").replace("gnpy-network-topology:", "");
+        //sd.writeStringFile(gnpyJsonModified);
+        String gnpyResponse = connect.gnpyCnx(gnpyJsonModified);
+        return gnpyResponse;
     }
 
     private PceGraph patchRerunGraph(PceGraph graph) {
diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ConnectToGnpyServer.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ConnectToGnpyServer.java
new file mode 100644 (file)
index 0000000..6a6a0d8
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright © 2019 Orange, Inc. 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.pce.gnpy;
+
+import com.google.common.io.CharStreams;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class to connect to GNPy tool.
+ *
+ * @author Ahmed Triki ( ahmed.triki@orange.com )
+ *
+ */
+
+public class ConnectToGnpyServer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ConnectToGnpyServer.class);
+    static final String URL_GNPY = "http://127.0.0.1:5000/gnpy/api/v1.0/files";
+
+    public String gnpyCnx(String jsonTxt) {
+        String jsonRespTxt = null;
+        try {
+            URL url = new URL(URL_GNPY);
+            String userCredentials = "gnpy:gnpy";
+            String basicAuth = "Basic " + new String(java.util.Base64.getEncoder().encode(userCredentials.getBytes()));
+
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            conn.setDoOutput(true);
+            conn.setRequestMethod("POST");
+            conn.setRequestProperty("Authorization", basicAuth);
+            conn.setRequestProperty("Content-Type", "application/json");
+
+            // Send the request to the GNPy
+            OutputStream os = conn.getOutputStream();
+            os.write(jsonTxt.getBytes());
+            os.flush();
+            if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
+                throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
+            }
+            InputStreamReader response = new InputStreamReader((conn.getInputStream()));
+            if (response != null) {
+                jsonRespTxt = null;
+                try {
+                    jsonRespTxt = CharStreams.toString(response);
+                } catch (IOException e1) {
+                    LOG.warn("Could not read characters of GNPy response: {}", e1.getMessage());
+                }
+            }
+            conn.disconnect();
+        } catch (MalformedURLException e) {
+            LOG.warn("Exception : Malformed GNPy URL");
+        } catch (IOException e) {
+            LOG.warn("IOException when connecting to GNPy server: {}", e.getMessage());
+        }
+        return jsonRespTxt;
+    }
+
+    public boolean isGnpyURLExist() {
+        boolean exist = false;
+        try {
+            URL url = new URL(URL_GNPY);
+            String userCredentials = "gnpy:gnpy";
+            String basicAuth = "Basic " + new String(java.util.Base64.getEncoder().encode(userCredentials.getBytes()));
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            conn.setDoOutput(true);
+            conn.setRequestMethod("HEAD");
+            conn.setRequestProperty("Authorization", basicAuth);
+            conn.setRequestProperty("Content-Type", "application/json");
+            conn.connect();
+            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                exist = true;
+            }
+            conn.disconnect();
+        }
+        catch (IOException e) {
+            LOG.warn("Could not connect to GNPy server");
+        }
+        return exist;
+    }
+
+    public String readResponse(InputStreamReader response) {
+        String output = null;
+        BufferedReader br = new BufferedReader(response);
+        String line;
+        StringBuilder sb = new StringBuilder();
+        try {
+            while ((line = br.readLine()) != null) {
+                sb.append(line);
+            }
+            output = sb.toString();
+        } catch (IOException e) {
+            LOG.warn("IOException when reading GNPy response: {}", e.getMessage());
+        }
+        return output;
+    }
+}
diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ExtractTopoDataStoreImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ExtractTopoDataStoreImpl.java
new file mode 100644 (file)
index 0000000..31417ba
--- /dev/null
@@ -0,0 +1,854 @@
+/*
+ * Copyright © 2018 Orange, Inc. 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.pce.gnpy;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.IntStream;
+
+import org.eclipse.jdt.annotation.Nullable;
+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.NetworkUtils;
+//import org.opendaylight.yang.gen.v1.gnpy.gnpy.eqpt.config.rev181119.EdfaVariety;
+//import org.opendaylight.yang.gen.v1.gnpy.gnpy.eqpt.config.rev181119.FiberVariety;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.Coordinate;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.Km;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.edfa.params.Operational;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.edfa.params.OperationalBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.Edfa;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.EdfaBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.FiberRoadmBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.Transceiver;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.TransceiverBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.fiberroadm.Params;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.fiberroadm.ParamsBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.fiberroadm.params.fiberroadm.Fiber;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.fiberroadm.params.fiberroadm.FiberBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.fiberroadm.params.fiberroadm.Roadm;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.element.type.choice.element.type.fiberroadm.params.fiberroadm.RoadmBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.location.attributes.Location;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.location.attributes.LocationBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Connections;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.ConnectionsBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.Elements;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.ElementsBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.elements.Metadata;
+import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.topo.elements.MetadataBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.RouteIncludeEro;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.TeHopType;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.TeNodeId;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.TePathDisjointness;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.TeTpId;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.common.constraints_config.TeBandwidth;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.common.constraints_config.TeBandwidthBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.Type;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.type.NumUnnumHopBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.type.num.unnum.hop.NumUnnumHop;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.generic.path.constraints.PathConstraints;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.generic.path.constraints.PathConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.gnpy.specific.parameters.EffectiveFreqSlot;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.gnpy.specific.parameters.EffectiveFreqSlotBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.path.route.objects.ExplicitRouteObjects;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.path.route.objects.ExplicitRouteObjectsBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.path.route.objects.explicit.route.objects.RouteObjectIncludeExclude;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.path.route.objects.explicit.route.objects.RouteObjectIncludeExcludeBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.service.PathRequest;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.service.PathRequestBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.Synchronization;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.SynchronizationBuilder;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.synchronization.Svec;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.synchronization.info.synchronization.SvecBuilder;
+import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.PathComputationRequestInput;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.amplified.link.attributes.AmplifiedLink;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.amplified.link.attributes.amplified.link.section.element.section.element.Span;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.amplified.link.attributes.amplified.link.section.element.section.element.ila.Ila;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev181130.span.attributes.LinkConcatenation;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev181130.Node1;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.Link1;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130.networks.network.link.OMSAttributes;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.AToZDirection;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ZToADirection;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.atoz.direction.AToZ;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.ztoa.direction.ZToA;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.Networks;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.Node;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.network.node.SupportingNode;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.Network1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev180226.networks.network.Link;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class to create the topology corresponding to GNPy requirements.
+ *
+ * @author Ahmed Triki ( ahmed.triki@orange.com )
+ *
+ */
+
+public class ExtractTopoDataStoreImpl {
+    private static final Logger LOG = LoggerFactory.getLogger(ExtractTopoDataStoreImpl.class);
+    private final DataBroker dataBroker;
+    // private final OpenRoadmTopology openRoadmTopology;
+    // private final OpenRoadmInterfaces openRoadmInterfaces;
+    private List<Elements> elements = new ArrayList<>();
+    private List<Connections> connections = new ArrayList<>();
+    private List<PathRequest> pathRequest = new ArrayList<>();
+    private List<Synchronization> synchronization = new ArrayList<>();
+    private Map<String, String> mapDisgNodeRefNode = new HashMap<String, String>();
+    private Map<String, IpAddress> mapNodeRefIp = new HashMap<String, IpAddress>();
+    private Map<String, String> mapLinkFiber = new HashMap<String, String>();
+    private Map<String, IpAddress> mapFiberIp = new HashMap<String, IpAddress>();
+    private static int convertKmM = 1000;
+
+    /*
+     * Construct the ExtractTopoDataStoreImpl.
+     */
+    @SuppressWarnings("unchecked")
+    public ExtractTopoDataStoreImpl(final DataBroker dataBroker, PathComputationRequestInput input, AToZDirection atoz,
+            Long requestId) {
+        this.dataBroker = dataBroker;
+        Map<String, List<?>> map = extractTopo();
+        if (map.containsKey("Elements")) {
+            elements = (List<Elements>) map.get("Elements");
+        } else {
+            elements = null;
+        }
+        if (map.containsKey("Elements")) {
+            connections = (List<Connections>) map.get("Connections");
+        } else {
+            connections = null;
+        }
+        pathRequest = extractPathRequest(input, atoz, requestId);
+        synchronization = extractSynchronization(requestId);
+    }
+
+    public ExtractTopoDataStoreImpl(final DataBroker dataBroker, PathComputationRequestInput input, ZToADirection ztoa,
+            Long requestId) {
+        this.dataBroker = dataBroker;
+        Map<String, List<?>> map = extractTopo();
+        if (map.containsKey("Elements")) {
+            elements = (List<Elements>) map.get("Elements");
+        } else {
+            elements = null;
+        }
+        if (map.containsKey("Elements")) {
+            connections = (List<Connections>) map.get("Connections");
+        } else {
+            connections = null;
+        }
+        pathRequest = extractPathRequest(input, ztoa, requestId);
+        synchronization = extractSynchronization(requestId);
+    }
+
+    /*
+     * extract the topology: all the elements have ipAddress as uid and maintain
+     * a mapping structure to map between the nodeId and the ipAddress (uid)
+     *
+     */
+    public Map<String, List<?>> extractTopo() {
+        Map<String, List<?>> map = new HashMap<String, List<?>>();
+        // Define the elements
+        List<Elements> topoElements = new ArrayList<>();
+        // Define the connections
+        List<Connections> topoConnections = new ArrayList<>();
+        // Define the instance identifier of the OpenRoadm topology
+        InstanceIdentifier<Network> insIdOpenRoadmTopo = InstanceIdentifier
+                .builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
+        // Define the instance identifier of the OpenRoadm network
+        InstanceIdentifier<Network> insIdrOpenRoadmNet = InstanceIdentifier
+                .builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.UNDERLAY_NETWORK_ID))).build();
+        ReadOnlyTransaction readOnlyTransaction = this.dataBroker.newReadOnlyTransaction();
+        // Read the data broker
+        try {
+            // Initialize the reading of the data broker
+            // read the configuration part of the data broker that concerns
+            // the openRoadm topology and get all the nodes
+            java.util.Optional<Network> openRoadmTopo = readOnlyTransaction
+                    .read(LogicalDatastoreType.CONFIGURATION, insIdOpenRoadmTopo).get().toJavaUtil();
+            java.util.Optional<Network> openRoadmNet = readOnlyTransaction
+                    .read(LogicalDatastoreType.CONFIGURATION, insIdrOpenRoadmNet).get().toJavaUtil();
+            if (openRoadmNet.isPresent()) {
+                List<Node> openRoadmNetNodeList = openRoadmNet.get().getNode();
+                if (openRoadmTopo.isPresent()) {
+                    List<Node> openRoadmTopoNodeList = openRoadmTopo.get().getNode();
+                    List<String> nodesList = new ArrayList<>();
+                    // Create the list of nodes
+                    if (!openRoadmTopoNodeList.isEmpty()) {
+                        // Create elements
+                        for (Node openRoadmTopoNode : openRoadmTopoNodeList) {
+                            // Retrieve the supporting node and the type of the
+                            // node in openRoadm network
+                            List<SupportingNode> supportingNodeList = openRoadmTopoNode.getSupportingNode();
+                            for (SupportingNode supportingNode : supportingNodeList) {
+                                String nodeRef = supportingNode.getNodeRef().getValue();
+                                IpAddress ipAddress = null;
+                                // Retrieve the mapping between the openRoadm
+                                // topology and openRoadm network
+                                mapDisgNodeRefNode.put(openRoadmTopoNode.getNodeId().getValue(), nodeRef);
+                                Node1 openRoadmNetNode1 = null;
+                                for (Node openRoadmNetNode : openRoadmNetNodeList) {
+                                    if (openRoadmNetNode.getNodeId().getValue().equals(nodeRef)) {
+                                        openRoadmNetNode1 = openRoadmNetNode.augmentation(Node1.class);
+                                        ipAddress = openRoadmNetNode1.getIp();
+                                        mapNodeRefIp.put(nodeRef, ipAddress);
+                                        break;
+                                    }
+                                }
+                                if (openRoadmNetNode1.getNodeType().getName().equals("ROADM")) {
+                                    if (!nodesList.contains(nodeRef)) {
+                                        Elements element = addElementsRoadm(2, 0, nodeRef, openRoadmNetNode1.getShelf(),
+                                                -20, ipAddress.getIpv4Address().getValue().toString());
+                                        topoElements.add(element);
+                                        nodesList.add(nodeRef);
+                                    }
+                                } else if (openRoadmNetNode1.getNodeType().getName().equals("XPONDER")) {
+                                    if (!nodesList.contains(nodeRef)) {
+                                        Elements element = addElementsTransceiver(2, 0, nodeRef,
+                                                openRoadmNetNode1.getShelf(),
+                                                ipAddress.getIpv4Address().getValue().toString());
+                                        topoElements.add(element);
+                                        nodesList.add(nodeRef);
+                                    }
+                                } else {
+                                    LOG.warn("the type is not implemented");
+                                }
+                            }
+                        }
+                    } else {
+                        LOG.warn("no nodes in the network");
+                    }
+
+                    // Create the list of connections
+                    Network1 nw1 = openRoadmTopo.get().augmentation(Network1.class);
+                    List<Link> linksList = nw1.getLink();
+                    // 1:EXPRESS-LINK ; 2:ADD-LINK ; 3:DROP-LINK ;
+                    // 4:ROADM-To-ROADM ; 5:XPONDER-INPUT ; 6:XPONDER-OUTPUT
+                    int[] externalLink = {4,5,6};
+                    int idFiber = 0;
+                    int nbEDFA = 0;
+                    if (!linksList.isEmpty()) {
+                        LOG.warn("The link list is not empty");
+                        for (Link link : linksList) {
+                            Link1 link1 = link.augmentation(Link1.class);
+                            int linkType = link1.getLinkType().getIntValue();
+                            if (IntStream.of(externalLink).anyMatch(x -> x == linkType)) {
+                                // Verify if the node is a ROADM
+                                String srcId = mapDisgNodeRefNode.get(link.getSource().getSourceNode().getValue());
+                                IpAddress srcIp = mapNodeRefIp.get(srcId);
+                                String destId = null;
+                                IpAddress destIp = null;
+                                // Add the links between amplifiers
+                                OMSAttributes omsAttributes = link1.getOMSAttributes();
+                                if (omsAttributes != null) {
+                                    if (omsAttributes.getAmplifiedLink() != null) {
+                                        List<AmplifiedLink> amplifiedLinkList = omsAttributes.getAmplifiedLink()
+                                                .getAmplifiedLink();
+                                        if (!amplifiedLinkList.isEmpty()) {
+                                            for (AmplifiedLink amplifiedLink : amplifiedLinkList) {
+                                                Elements element1 = null;
+                                                if (amplifiedLink.getSectionElement()
+                                                        .getSectionElement() instanceof Ila) {
+                                                    Ila ila = (Ila) amplifiedLink.getSectionElement()
+                                                            .getSectionElement();
+                                                    String nodeId = ila.getNodeId().getValue();
+                                                    IpAddress ipEdfa = new IpAddress(
+                                                            new Ipv4Address("1.1.1." + nbEDFA));
+                                                    nbEDFA++;
+                                                    mapDisgNodeRefNode.put(nodeId, nodeId);
+                                                    mapNodeRefIp.put(nodeId, ipEdfa);
+                                                    // class std_medium_gain
+                                                    // implements EdfaVariety {}
+                                                    element1 = addElementsEdfa(2, 0, "RLD", "Lannion_CAS",
+                                                            ila.getGain().getValue(), ila.getTilt().getValue(),
+                                                            ila.getOutVoaAtt().getValue(), "std_medium_gain",
+                                                            ipEdfa.getIpv4Address().getValue().toString());
+                                                } else if (amplifiedLink.getSectionElement()
+                                                        .getSectionElement() instanceof Span) {
+                                                    // Create the location
+                                                    Span span = (Span) amplifiedLink.getSectionElement()
+                                                            .getSectionElement();
+                                                    String clfi = span.getSpan().getClfi();
+                                                    IpAddress ipFiber = new IpAddress(
+                                                            new Ipv4Address("2.2.2." + idFiber));
+                                                    mapLinkFiber.put(link.getLinkId().getValue(), clfi);
+                                                    mapFiberIp.put(clfi, ipFiber);
+                                                    idFiber++;
+                                                    // class SSMF implements
+                                                    // FiberVariety {}
+                                                    element1 = addElementsFiber(2, 0, "RLD", "Lannion_CAS",
+                                                            ipFiber.getIpv4Address().getValue(), 20, 0, 0.2, 0, 0,
+                                                            "SSMF");
+                                                }
+                                                if (element1 != null) {
+                                                    topoElements.add(element1);
+                                                    destId = element1.getUid();
+                                                    destIp = null;
+                                                    // Create a new link
+                                                    if (srcId != destId) {
+                                                        Connections connection = createNewConnection(srcId, srcIp,
+                                                                destId, destIp);
+                                                        topoConnections.add(connection);
+                                                        srcId = destId;
+                                                        srcIp = destIp;
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    } else if (omsAttributes.getSpan() != null) {
+                                        org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev181130
+                                            .networks.network.link.oms.attributes.@Nullable Span span
+                                                = omsAttributes.getSpan();
+
+                                        String clfi = span.getClfi();
+                                        IpAddress ipFiber = new IpAddress(new Ipv4Address("2.2.2." + idFiber));
+                                        mapLinkFiber.put(link.getLinkId().getValue(), clfi);
+                                        mapFiberIp.put(clfi, ipFiber);
+                                        idFiber++;
+
+                                        double attIn = span.getSpanlossCurrent().getValue().doubleValue();
+                                        double lossCoef = 0.2;
+                                        double connIn = 0;
+                                        double connOut = 0;
+                                        String typeVariety = "SSMF";
+
+                                        double length = 0; //convert to kilometer
+                                        // Compute the length of the link
+                                        List<LinkConcatenation> linkConcatenationList = span.getLinkConcatenation();
+                                        for (LinkConcatenation linkConcatenation : linkConcatenationList) {
+                                            double srlgLength = linkConcatenation.getSRLGLength();
+                                            length += srlgLength / convertKmM; //convert to kilometer
+                                        }
+
+                                        Elements element1 = addElementsFiber(2, 0, "RLD", "Lannion_CAS",
+                                                ipFiber.getIpv4Address().getValue(), length, attIn, lossCoef, connIn,
+                                                connOut, typeVariety);
+
+                                        topoElements.add(element1);
+                                        // Create a new link
+                                        destId = element1.getUid();
+                                        destIp = null;
+                                        if (srcId != destId) {
+                                            Connections connection = createNewConnection(srcId, srcIp, destId, destIp);
+                                            topoConnections.add(connection);
+                                            srcId = destId;
+                                            srcIp = destIp;
+                                        }
+                                    } else {
+                                        // Add a fiber
+                                        String clfi = "Fiber" + idFiber;
+                                        IpAddress ipFiber = new IpAddress(new Ipv4Address("2.2.2." + idFiber));
+                                        mapLinkFiber.put(link.getLinkId().getValue(), clfi);
+                                        mapFiberIp.put(clfi, ipFiber);
+                                        idFiber++;
+                                        // Create a new element
+                                        // class SSMF implements FiberVariety {}
+                                        Elements element1 = addElementsFiber(2, 0, "RLD", "Lannion_CAS",
+                                                ipFiber.getIpv4Address().getValue(), 20, 0, 0.2, 0, 0, "SSMF");
+                                        topoElements.add(element1);
+                                        // Create a new link
+                                        destId = element1.getUid();
+                                        destIp = null;
+                                        if (srcId != destId) {
+                                            Connections connection = createNewConnection(srcId, srcIp, destId, destIp);
+                                            topoConnections.add(connection);
+                                            srcId = destId;
+                                            srcIp = destIp;
+                                        }
+                                    }
+                                } else {
+                                    LOG.warn("The oms attributes is null!");
+                                }
+                                // Create a new link
+                                destId = mapDisgNodeRefNode.get(link.getDestination().getDestNode().getValue());
+                                destIp = mapNodeRefIp.get(destId);
+                                Connections connection = createNewConnection(srcId, srcIp, destId, destIp);
+                                topoConnections.add(connection);
+                            }
+                        }
+                    } else {
+                        LOG.warn("no links in the network");
+                    }
+                } else {
+                    LOG.warn("No nodes in the selected network ...");
+                }
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error reading the topology", e);
+            readOnlyTransaction.close();
+        }
+        readOnlyTransaction.close();
+        map.put("Elements", topoElements);
+        map.put("Connections", topoConnections);
+        return map;
+    }
+
+    /*
+     * Create the pathRequest
+     */
+    public List<PathRequest> extractPathRequest(PathComputationRequestInput input, AToZDirection atoz, Long requestId) {
+        // List of A to Z
+        List<AToZ> listAtoZ = atoz.getAToZ();
+        int atozSize = listAtoZ.size();
+        // String modulationFormat = atoz.getModulationFormat();
+        // Create the path request
+        List<PathRequest> pathRequestList = new ArrayList<>();
+        // Define the instance identifier
+        // InstanceIdentifier<Network> nwInstanceIdentifier = InstanceIdentifier
+        // .builder(Network.class, new NetworkKey(new
+        // NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
+
+        // read the configuration part of the data broker that concerns the
+        // nodes ID and get all the nodes
+        // java.util.Optional<Network> networkObject = readOnlyTransaction
+        // .read(LogicalDatastoreType.CONFIGURATION,
+        // nwInstanceIdentifier).get().toJavaUtil();
+        // 1.1 Create explicitRouteObjects
+        // 1.1.1. create RouteObjectIncludeExclude list
+        List<RouteObjectIncludeExclude> routeObjectIncludeExcludes = new ArrayList<>();
+        IpAddress ipAddressCurrent = null;
+        Long index = (long) 0;
+        //ReadOnlyTransaction readOnlyTransaction = this.dataBroker.newReadOnlyTransaction();
+        for (int i = 0; i < atozSize; i++) {
+            // String idAtoZ = listAtoZ.get(i).getId();
+            String nodeId = null;
+            if (listAtoZ.get(i).getResource()
+                    .getResource() instanceof org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface
+                    .pathdescription.rev171017.pce.resource.resource.resource.Node) {
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                    .resource.resource.resource.Node node = (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c
+                            ._interface.pathdescription.rev171017.pce.resource.resource.resource.Node) listAtoZ
+                        .get(i).getResource().getResource();
+                nodeId = node.getNodeId();
+                if (nodeId != null) {
+                    String nodeRef = mapDisgNodeRefNode.get(nodeId);
+                    IpAddress ipAddress = mapNodeRefIp.get(nodeRef);
+                    for (Elements element : elements) {
+                        if (element.getUid().contains(ipAddress.getIpv4Address().getValue().toString())) {
+                            String type = element.getType().getName();
+                            if ((ipAddressCurrent == null) || (ipAddressCurrent != ipAddress)) {
+                                ipAddressCurrent = ipAddress;
+                                // Fill in routeObjectIncludeExcludes
+                                RouteObjectIncludeExclude routeObjectIncludeExclude1 = addRouteObjectIncludeExclude(
+                                        ipAddress, 1, index);
+                                routeObjectIncludeExcludes.add(routeObjectIncludeExclude1);
+                                index++;
+                            }
+                            break;
+                        }
+                    }
+                } else {
+                    LOG.warn("node ID is null");
+                }
+            } else if (listAtoZ.get(i).getResource()
+                    .getResource() instanceof org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface
+                    .pathdescription.rev171017.pce.resource.resource.resource.TerminationPoint) {
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                        .resource.resource.resource.TerminationPoint tp = (org.opendaylight.yang.gen.v1.http.org
+                        .transportpce.b.c._interface.pathdescription.rev171017.pce.resource.resource.resource
+                        .TerminationPoint) listAtoZ.get(i).getResource().getResource();
+                // Not used in this version
+            } else if (listAtoZ.get(i).getResource()
+                    .getResource() instanceof org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface
+                    .pathdescription.rev171017.pce.resource.resource.resource.Link) {
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                    .resource.resource.resource.Link link = (org.opendaylight.yang.gen.v1.http.org.transportpce
+                            .b.c._interface.pathdescription.rev171017.pce.resource.resource.resource.Link) listAtoZ
+                        .get(i).getResource().getResource();
+                String clfi = mapLinkFiber.get(link.getLinkId());
+                IpAddress fiberIp = mapFiberIp.get(clfi);
+                if (clfi != null) {
+                    RouteObjectIncludeExclude routeObjectIncludeExclude1 = addRouteObjectIncludeExclude(fiberIp, 1,
+                            index);
+                    routeObjectIncludeExcludes.add(routeObjectIncludeExclude1);
+                    index++;
+                }
+            }
+        }
+        // Create ExplicitRouteObjects
+        ExplicitRouteObjects explicitRouteObjects = new ExplicitRouteObjectsBuilder()
+                .setRouteObjectIncludeExclude(routeObjectIncludeExcludes).build();
+
+        // 1. Create the path request element 1
+        // Find parameters
+        // String serviceName = input.getServiceName();
+        String sourceNode = input.getServiceAEnd().getNodeId();
+        String destNode = input.getServiceZEnd().getNodeId();
+
+        // 1.2 Create a path constraints
+        Long rate = atoz.getRate();
+        // Long wavelengthNumber = atoz.getAToZWavelengthNumber();
+        // Create EffectiveFreqSlot
+        List<EffectiveFreqSlot> effectiveFreqSlot = new ArrayList<>();
+        EffectiveFreqSlot effectiveFreqSlot1 = new EffectiveFreqSlotBuilder().setM(5).setN(8).build();
+        effectiveFreqSlot.add(effectiveFreqSlot1);
+        // Create Te-Bandwidth
+        TeBandwidth teBandwidth = new TeBandwidthBuilder().setPathBandwidth(new BigDecimal(rate))
+                .setTechnology("flexi-grid").setTrxType("openroadm-beta1").setTrxMode("W100G")
+                .setEffectiveFreqSlot(effectiveFreqSlot).setSpacing(new BigDecimal(50000000000.0)).build();
+        // .setMaxNbOfChannel(new Long(80)).setOutputPower(new
+        // BigDecimal(0.0012589254117941673))
+        PathConstraints pathConstraints = new PathConstraintsBuilder().setTeBandwidth(teBandwidth).build();
+        // PathRequest pathRequest1 = new
+        // PathRequestBuilder().setRequestId(new
+        // Long(0)).setSource(mapNodeRefIp.get(sourceNode))
+        // .setDestination(mapNodeRefIp.get(destNode)).setSrcTpId(input.getServiceAEnd().getTxDirection()
+        //      .getPort().getPortName().getBytes())
+        // .setDstTpId(input.getServiceAEnd().getRxDirection().getPort().getPortName().getBytes())
+        //      .setPathConstraints(pathConstraints)
+        // .setExplicitRouteObjects(explicitRouteObjects).build();
+        PathRequest pathRequest1 = new PathRequestBuilder().setRequestId(requestId)
+                .setSource(mapNodeRefIp.get(sourceNode)).setDestination(mapNodeRefIp.get(destNode))
+                .setSrcTpId("srcTpId".getBytes()).setDstTpId("dstTpId".getBytes()).setPathConstraints(pathConstraints)
+                .setExplicitRouteObjects(explicitRouteObjects).build();
+        pathRequestList.add(pathRequest1);
+        //readOnlyTransaction.close();
+        return pathRequestList;
+    }
+
+    public List<PathRequest> extractPathRequest(PathComputationRequestInput input, ZToADirection ztoa, Long requestId) {
+        // List of A to Z
+        List<ZToA> listZToA = ztoa.getZToA();
+        int ztoaSize = listZToA.size();
+        // String modulationFormat = ztoa.getModulationFormat();
+        // Create the path request
+        List<PathRequest> servicePathRequest = new ArrayList<>();
+        // Define the instance identifier
+        InstanceIdentifier<Network> nwInstanceIdentifier = InstanceIdentifier
+                .builder(Networks.class)
+                .child(Network.class, new NetworkKey(new NetworkId(NetworkUtils.OVERLAY_NETWORK_ID))).build();
+        //ReadOnlyTransaction readOnlyTransaction = this.dataBroker.newReadOnlyTransaction();
+
+        // read the configuration part of the data broker that concerns the
+        // nodes ID and get all the nodes
+        // java.util.Optional<Network> networkObject = readOnlyTransaction
+        // .read(LogicalDatastoreType.CONFIGURATION,
+        // nwInstanceIdentifier).get().toJavaUtil();
+        // 1.1 Create explicitRouteObjects
+        // 1.1.1. create RouteObjectIncludeExclude list
+        List<RouteObjectIncludeExclude> routeObjectIncludeExcludes = new ArrayList<>();
+        IpAddress ipAddressCurrent = null;
+        Long index = (long) 0;
+        for (int i = 0; i < ztoaSize; i++) {
+            // String idZtoA = listZToA.get(i).getId();
+            String nodeId = null;
+            if (listZToA.get(i).getResource()
+                    .getResource() instanceof org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface
+                    .pathdescription.rev171017.pce.resource.resource.resource.Node) {
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                    .resource.resource.resource.Node node = (org.opendaylight.yang.gen.v1.http.org.transportpce.b.c
+                    ._interface.pathdescription.rev171017.pce.resource.resource.resource.Node) listZToA.get(i)
+                    .getResource().getResource();
+                nodeId = node.getNodeId();
+                if (nodeId != null) {
+                    String nodeRef = mapDisgNodeRefNode.get(nodeId);
+                    IpAddress ipAddress = mapNodeRefIp.get(nodeRef);
+                    for (Elements element : elements) {
+                        if (element.getUid().contains(ipAddress.getIpv4Address().getValue().toString())) {
+                            // String type = element.getType().getName();
+                            if ((ipAddressCurrent == null) || (ipAddressCurrent != ipAddress)) {
+                                ipAddressCurrent = ipAddress;
+                                // Fill in routeObjectIncludeExcludes
+                                RouteObjectIncludeExclude routeObjectIncludeExclude1 = addRouteObjectIncludeExclude(
+                                        ipAddress, 1, index);
+                                routeObjectIncludeExcludes.add(routeObjectIncludeExclude1);
+                                index++;
+                            }
+                            break;
+                        }
+                    }
+                } else {
+                    LOG.warn("node ID is null");
+                }
+            } else if (listZToA.get(i).getResource()
+                    .getResource() instanceof org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface
+                    .pathdescription.rev171017.pce.resource.resource.resource.TerminationPoint) {
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                    .resource.resource.resource.TerminationPoint tp = (org.opendaylight.yang.gen.v1.http.org
+                    .transportpce.b.c._interface.pathdescription.rev171017.pce.resource.resource.resource
+                    .TerminationPoint) listZToA.get(i).getResource().getResource();
+                // Not used in this version
+            } else if (listZToA.get(i).getResource()
+                    .getResource() instanceof org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface
+                    .pathdescription.rev171017.pce.resource.resource.resource.Link) {
+                org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce
+                    .resource.resource.resource.Link link = (org.opendaylight.yang.gen.v1.http.org.transportpce
+                    .b.c._interface.pathdescription.rev171017.pce.resource.resource.resource.Link) listZToA.get(i)
+                    .getResource().getResource();
+                String clfi = mapLinkFiber.get(link.getLinkId());
+                IpAddress fiberIp = mapFiberIp.get(clfi);
+                if (clfi != null) {
+                    RouteObjectIncludeExclude routeObjectIncludeExclude1 = addRouteObjectIncludeExclude(fiberIp, 1,
+                            index);
+                    routeObjectIncludeExcludes.add(routeObjectIncludeExclude1);
+                    index++;
+                }
+            }
+        }
+        // Create ExplicitRouteObjects
+        ExplicitRouteObjects explicitRouteObjects = new ExplicitRouteObjectsBuilder()
+                .setRouteObjectIncludeExclude(routeObjectIncludeExcludes).build();
+
+        // 1. Create the path request element 1
+        // Find parameters
+        // String serviceName = input.getServiceName();
+        String sourceNode = input.getServiceZEnd().getNodeId();
+        String destNode = input.getServiceAEnd().getNodeId();
+
+        // 1.2 Create a path constraints
+        Long rate = ztoa.getRate();
+        // Long wavelengthNumber = ztoa.getZToAWavelengthNumber();
+        // Create EffectiveFreqSlot
+        List<EffectiveFreqSlot> effectiveFreqSlot = new ArrayList<>();
+        EffectiveFreqSlot effectiveFreqSlot1 = new EffectiveFreqSlotBuilder().setM(5).setN(8).build();
+        effectiveFreqSlot.add(effectiveFreqSlot1);
+        // Create Te-Bandwidth
+        TeBandwidth teBandwidth = new TeBandwidthBuilder().setPathBandwidth(new BigDecimal(rate))
+                .setTechnology("flexi-grid").setTrxType("openroadm-beta1").setTrxMode("W100G")
+                .setEffectiveFreqSlot(effectiveFreqSlot).setSpacing(new BigDecimal(50000000000.0)).build();
+        // .setMaxNbOfChannel(new Long(80)).setOutputPower(new
+        // BigDecimal(0.0012589254117941673))
+        PathConstraints pathConstraints = new PathConstraintsBuilder().setTeBandwidth(teBandwidth).build();
+        // PathRequest pathRequest1 = new
+        // PathRequestBuilder().setRequestId(new
+        // Long(0)).setSource(mapNodeRefIp.get(sourceNode))
+        // .setDestination(mapNodeRefIp.get(destNode)).setSrcTpId(input.getServiceAEnd().getTxDirection()
+        //      .getPort().getPortName().getBytes())
+        // .setDstTpId(input.getServiceAEnd().getRxDirection().getPort().getPortName().getBytes())
+        //      .setPathConstraints(pathConstraints)
+        // .setExplicitRouteObjects(explicitRouteObjects).build();
+        PathRequest pathRequest1 = new PathRequestBuilder().setRequestId(requestId)
+                .setSource(mapNodeRefIp.get(sourceNode)).setDestination(mapNodeRefIp.get(destNode))
+                .setSrcTpId("srcTpId".getBytes()).setDstTpId("dstTpId".getBytes()).setPathConstraints(pathConstraints)
+                .setExplicitRouteObjects(explicitRouteObjects).build();
+        servicePathRequest.add(pathRequest1);
+        //readOnlyTransaction.close();
+        return servicePathRequest;
+    }
+
+    /*
+     * Create the synchronization
+     */
+    public List<Synchronization> extractSynchronization(Long requestId) {
+        // Create RequestIdNumber
+        List<Long> requestIdNumber = new ArrayList<>();
+        requestIdNumber.add(0, new Long(0));
+        // Create a synchronization
+        Svec svec = new SvecBuilder().setRelaxable(true).setDisjointness(new TePathDisjointness(true, true, false))
+                .setRequestIdNumber(requestIdNumber).build();
+        List<Synchronization> synchro = new ArrayList<>();
+        Synchronization synchronization1 = new SynchronizationBuilder().setSynchronizationId(new Long(0)).setSvec(svec)
+                .build();
+        synchro.add(synchronization1);
+        return (synchro);
+    }
+
+    /*
+     * Method to add Fiber
+     */
+    private Elements addElementsFiber(double latitude, double longitude, String region, String city, String clfi,
+            double length, double attIn, double lossCoef, double connIn, double connOut, String typeVariety) {
+        // Create an amplifier after the roadm
+        Coordinate c1 = new Coordinate(new BigDecimal(latitude));
+        Coordinate c2 = new Coordinate(new BigDecimal(longitude));
+        Location location1 = new LocationBuilder().setRegion(region).setCity(city).setLatitude(c1).setLongitude(c2)
+                .build();
+        Metadata metadata1 = new MetadataBuilder().setLocation(location1).build();
+        Fiber fiber = new FiberBuilder().setLength(new BigDecimal(length)).setLengthUnits(Km.class)
+                .setAttIn(new BigDecimal(attIn)).setLossCoef(new BigDecimal(lossCoef)).setConIn(new BigDecimal(connIn))
+                .setConOut(new BigDecimal(connOut)).build();
+        Params params1 = new ParamsBuilder().setFiberroadm(fiber).build();
+        // TypeElement Fiber = ; //new TypeElement(Fiber);
+        Elements element1 = new ElementsBuilder().setUid(clfi)
+                .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.Fiber.class)
+                .setTypeVariety(typeVariety).setMetadata(metadata1)
+                .setElementType(new FiberRoadmBuilder().setParams(params1).build()).build();
+        return element1;
+    }
+
+    /*
+     * Method to add Edfa
+     */
+    private Elements addElementsEdfa(double latitude, double longitude, String region, String city,
+            BigDecimal gainTarget, BigDecimal tiltTarget, BigDecimal outVoa, String typeVariety, String uidEdfa) {
+        // Create an amplifier after the roadm
+        Coordinate c1 = new Coordinate(new BigDecimal(latitude));
+        Coordinate c2 = new Coordinate(new BigDecimal(longitude));
+        Location location1 = new LocationBuilder().setRegion(region).setCity(city).setLatitude(c1).setLongitude(c2)
+                .build();
+        Metadata metadata1 = new MetadataBuilder().setLocation(location1).build();
+        Operational operational = new OperationalBuilder().setGainTarget(gainTarget).setTiltTarget(tiltTarget)
+                .setOutVoa(outVoa).build();
+        Edfa edfa = new EdfaBuilder()
+                // .setTypeVariety(typeVariety)
+                .setOperational(operational).build();
+        Elements element1 = new ElementsBuilder().setUid(uidEdfa) // Choose an
+                                                                  // ip
+                                                                  // address
+                .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.Edfa.class)
+                .setMetadata(metadata1).setElementType(edfa).setTypeVariety(typeVariety).build();
+        return element1;
+    }
+
+    /*
+     * Method to add ROADM
+     */
+    private Elements addElementsRoadm(double latitude, double longitude, String region, String city,
+            double targetPchOutDb, String uidRoadm) {
+
+        Coordinate c1 = new Coordinate(new BigDecimal(latitude));
+        Coordinate c2 = new Coordinate(new BigDecimal(longitude));
+        Location location1 = new LocationBuilder().setRegion(region).setCity(city).setLatitude(c1).setLongitude(c2)
+                .build();
+        Metadata metadata1 = new MetadataBuilder().setLocation(location1).build();
+        // Create the roadm
+        Roadm roadm = new RoadmBuilder().setTargetPchOutDb(new BigDecimal(targetPchOutDb)).build();
+        Params params1 = new ParamsBuilder().setFiberroadm(roadm).build();
+        Elements element1 = new ElementsBuilder().setUid(uidRoadm)
+                .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.Roadm.class)
+                .setMetadata(metadata1).setElementType(new FiberRoadmBuilder().setParams(params1).build()).build();
+        return element1;
+    }
+
+    /*
+     * Method to add Transceiver
+     */
+    private Elements addElementsTransceiver(double latitude, double longitude, String region, String city,
+            String uidTrans) {
+        Coordinate c1 = new Coordinate(new BigDecimal(latitude));
+        Coordinate c2 = new Coordinate(new BigDecimal(longitude));
+        Location location1 = new LocationBuilder().setRegion(region).setCity(city).setLatitude(c1).setLongitude(c2)
+                .build();
+        Metadata metadata1 = new MetadataBuilder().setLocation(location1).build();
+        Transceiver transceiver = new TransceiverBuilder().build();
+        Elements element1 = new ElementsBuilder().setUid(uidTrans)
+                .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev181214.Transceiver.class)
+                .setMetadata(metadata1).setElementType(transceiver).build();
+        return element1;
+    }
+
+    /*
+     * Add routeObjectIncludeExclude
+     */
+    private RouteObjectIncludeExclude addRouteObjectIncludeExclude(IpAddress ipAddress, long teTpValue, long index) {
+        TeNodeId teNodeId = new TeNodeId(ipAddress);
+        TeTpId teTpId = new TeTpId(teTpValue);
+        NumUnnumHop numUnnumHop = new org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.type.num
+            .unnum.hop.NumUnnumHopBuilder()
+            .setNodeId(teNodeId.getIpv4Address().getValue().toString()).setLinkTpId(teTpId.getUint32().toString())
+            .setHopType(TeHopType.STRICT).build();
+        Type type1 = new NumUnnumHopBuilder().setNumUnnumHop(numUnnumHop).build();
+        // Create routeObjectIncludeExclude element 1
+        RouteObjectIncludeExclude routeObjectIncludeExclude1 = new RouteObjectIncludeExcludeBuilder().setIndex(index)
+                .setExplicitRouteUsage(RouteIncludeEro.class).setType(type1).build();
+        return routeObjectIncludeExclude1;
+    }
+
+    private String fromToNodeForConnection(String id, IpAddress ip) {
+        String fromToNode = id;
+        if (ip != null) {
+            fromToNode = ip.getIpv4Address().getValue().toString();
+        }
+        return (fromToNode);
+    }
+
+    private Connections createNewConnection(String srcId, IpAddress srcIp, String destId, IpAddress destIp) {
+        String fromNode = srcId;
+        String toNode = destId;
+        if (srcIp != null) {
+            fromNode = srcIp.getIpv4Address().getValue().toString();
+        }
+        if (destIp != null) {
+            toNode = destIp.getIpv4Address().getValue().toString();
+        }
+        Connections connection1 = new ConnectionsBuilder().setFromNode(fromNode).setToNode(toNode).build();
+        return (connection1);
+    }
+
+    public List<Elements> getElements() {
+        return elements;
+    }
+
+    public void setElements(List<Elements> elements) {
+        this.elements = elements;
+    }
+
+    public List<Connections> getConnections() {
+        return connections;
+    }
+
+    public void setConnections(List<Connections> connections) {
+        this.connections = connections;
+    }
+
+    public List<PathRequest> getPathRequest() {
+        return pathRequest;
+    }
+
+    public void setPathRequest(List<PathRequest> pathRequest) {
+        this.pathRequest = pathRequest;
+    }
+
+    public List<Synchronization> getSynchronization() {
+        return synchronization;
+    }
+
+    public void setSynchronization(List<Synchronization> synchronization) {
+        this.synchronization = synchronization;
+    }
+
+    public List<PathRequest> createEmptyPathRequest(PathComputationRequestInput input, AToZDirection atoz) {
+        // List of A to Z
+        // List<AToZ> listAtoZ = atoz.getAToZ();
+        // int atozSize = listAtoZ.size();
+
+        // Create the path request
+        List<PathRequest> pathRequestList = new ArrayList<>();
+
+        // 1. Create the path request element 1
+        // Find parameters
+        // String serviceName = input.getServiceName();
+        String sourceNode = input.getServiceAEnd().getNodeId();
+        String destNode = input.getServiceZEnd().getNodeId();
+
+        // 1.2 Create a path constraints
+        Long rate = atoz.getRate();
+
+        // Create EffectiveFreqSlot
+        List<EffectiveFreqSlot> effectiveFreqSlot = new ArrayList<>();
+        EffectiveFreqSlot effectiveFreqSlot1 = new EffectiveFreqSlotBuilder().setM(5).setN(8).build();
+        effectiveFreqSlot.add(effectiveFreqSlot1);
+
+        // Create Te-Bandwidth
+        TeBandwidth teBandwidth = new TeBandwidthBuilder().setPathBandwidth(new BigDecimal(rate))
+                .setTechnology("flexi-grid").setTrxType("openroadm-beta1").setTrxMode("W100G")
+                .setEffectiveFreqSlot(effectiveFreqSlot).setSpacing(new BigDecimal(50000000000.0)).build();
+        PathConstraints pathConstraints = new PathConstraintsBuilder().setTeBandwidth(teBandwidth).build();
+        PathRequest pathRequest1 = new PathRequestBuilder().setRequestId(new Long(0))
+                .setSource(mapNodeRefIp.get(sourceNode)).setDestination(mapNodeRefIp.get(destNode))
+                .setSrcTpId("srcTpId".getBytes()).setDstTpId("dstTpId".getBytes()).setPathConstraints(pathConstraints)
+                .build();
+        pathRequestList.add(pathRequest1);
+        return pathRequestList;
+    }
+
+}
diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java
new file mode 100644 (file)
index 0000000..0067102
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright © 2018 Orange, Inc. 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.pce.gnpy;
+
+import com.google.common.base.Preconditions;
+import com.google.gson.stream.JsonReader;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javassist.ClassPool;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.mdsal.binding.dom.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.Result;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.explicit.route.hop.type.num.unnum.hop.NumUnnumHop;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.generic.path.properties.path.properties.PathMetric;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.generic.path.properties.path.properties.PathRouteObjects;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.result.Response;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.result.response.response.type.NoPathCase;
+import org.opendaylight.yang.gen.v1.gnpy.path.rev190502.result.response.response.type.PathCase;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.constraints.sp.co.routing.or.general.General;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.constraints.sp.co.routing.or.general.GeneralBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.constraints.sp.co.routing.or.general.general.Include;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.constraints.sp.co.routing.or.general.general.IncludeBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.constraints.sp.co.routing.or.general.general.include_.OrderedHops;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.constraints.sp.co.routing.or.general.general.include_.OrderedHopsBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.ordered.constraints.sp.HopType;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.ordered.constraints.sp.HopTypeBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.ordered.constraints.sp.hop.type.hop.type.NodeBuilder;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.routing.constraints.sp.HardConstraints;
+import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017.routing.constraints.sp.HardConstraintsBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodes;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class for analyzing the result sent by GNPy.
+ *
+ * @author Ahmed Triki ( ahmed.triki@orange.com )
+ *
+ */
+
+public class GnpyResult {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GnpyResult.class);
+    private Response response = null;
+
+    public GnpyResult(String gnpyResponseString) throws Exception {
+
+        // try {
+        // Optional<DataObject> dataObject;
+        // Create the schema context
+        final ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create();
+        Iterable<? extends YangModuleInfo> moduleInfos;
+        moduleInfos = Collections.singleton(BindingReflections.getModuleInfo(Result.class));
+        moduleContext.addModuleInfos(moduleInfos);
+        SchemaContext schemaContext = moduleContext.tryToCreateSchemaContext().get();
+
+        // Create the binding binding normalized node codec registry
+        BindingRuntimeContext bindingRuntimeContext = BindingRuntimeContext.create(moduleContext, schemaContext);
+        final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(
+                StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault())));
+        codecRegistry.onBindingRuntimeContextUpdated(bindingRuntimeContext);
+
+        // Create the data object
+        QName pathQname = QName.create("gnpy:path", "2019-05-02", "result");
+        LOG.debug("the Qname is {} / namesapce {} ; module {}; ", pathQname.toString(), pathQname.getNamespace(),
+                pathQname.getModule());
+        YangInstanceIdentifier yangId = YangInstanceIdentifier.of(pathQname);
+        DataObject dataObject = null;
+        //Create the object response
+        //Create JsonReader from String
+        InputStream streamGnpyRespnse = new ByteArrayInputStream(gnpyResponseString.getBytes(StandardCharsets.UTF_8));
+        InputStreamReader gnpyResultReader = new InputStreamReader(streamGnpyRespnse);
+        JsonReader jsonReader = new JsonReader(gnpyResultReader);
+        Optional<NormalizedNode<? extends PathArgument, ?>> transformIntoNormalizedNode = parseInputJSON(jsonReader,
+                Result.class);
+        NormalizedNode<? extends PathArgument, ?> normalizedNode = transformIntoNormalizedNode.get();
+        if (codecRegistry.fromNormalizedNode(yangId, normalizedNode) != null) {
+            LOG.debug("The key of the generated object",
+                    codecRegistry.fromNormalizedNode(yangId, normalizedNode).getKey());
+            dataObject = codecRegistry.fromNormalizedNode(yangId, normalizedNode).getValue();
+        } else {
+            LOG.warn("The codec registry from the normalized node is null!");
+        }
+        List<Response> responses = null;
+        responses = ((Result) dataObject).getResponse();
+        if (responses != null) {
+            LOG.info("The response id is {}; ", responses.get(0).getResponseId());
+        } else {
+            LOG.warn("The response is null!");
+        }
+        this.response = responses.get(0);
+        analyzeResult();
+    }
+
+    public boolean getPathFeasibility() {
+        boolean isFeasible = false;
+        if (response != null) {
+            if (response.getResponseType() instanceof NoPathCase) {
+                isFeasible = false;
+                LOG.info("The path is not feasible ");
+            } else if (response.getResponseType() instanceof PathCase) {
+                isFeasible = true;
+                LOG.info("The path is feasible ");
+            }
+        }
+        return isFeasible;
+    }
+
+    public void analyzeResult() {
+        if (response != null) {
+            Long responseId = response.getResponseId();
+            LOG.info("Response-Id {}", responseId);
+            if (response.getResponseType() instanceof NoPathCase) {
+                NoPathCase noPathCase = (NoPathCase) response.getResponseType();
+                String noPathType = noPathCase.getNoPath().getNoPath();
+                LOG.info("GNPy: No path - {}",noPathType);
+                if (((noPathType == "NO_FEASIBLE_BAUDRATE_WITH_SPACING") && (noPathType == "NO_FEASIBLE_MODE"))
+                        && ((noPathType ==  "MODE_NOT_FEASIBLE") && (noPathType == "NO_SPECTRUM"))) {
+                    List<PathMetric> pathMetricList = noPathCase.getNoPath().getPathProperties().getPathMetric();
+                    LOG.info("GNPy : path is not feasible : {}", noPathType);
+                    for (PathMetric pathMetric : pathMetricList) {
+                        String metricType = pathMetric.getMetricType().getSimpleName();
+                        BigDecimal accumulativeValue = pathMetric.getAccumulativeValue();
+                        LOG.info("Metric type {} // AccumulatriveValue {}", metricType, accumulativeValue);
+                    }
+                }
+            } else if (response.getResponseType() instanceof PathCase) {
+                LOG.info("GNPy : path is feasible");
+                PathCase pathCase = (PathCase) response.getResponseType();
+                List<PathMetric> pathMetricList = pathCase.getPathProperties().getPathMetric();
+                for (PathMetric pathMetric : pathMetricList) {
+                    String metricType = pathMetric.getMetricType().getSimpleName();
+                    BigDecimal accumulativeValue = pathMetric.getAccumulativeValue();
+                    LOG.info("Metric type {} // AccumulatriveValue {}", metricType, accumulativeValue);
+                }
+            }
+        }
+    }
+
+    public HardConstraints analyzeGnpyPath() {
+        HardConstraints hardConstraints = null;
+        if (response != null) {
+            Long responseId = response.getResponseId();
+            LOG.info("Response-Id {}", responseId);
+            if (response.getResponseType() instanceof NoPathCase) {
+                NoPathCase noPathCase = (NoPathCase) response.getResponseType();
+                LOG.info("No path feasible {}", noPathCase.toString());
+            } else if (response.getResponseType() instanceof PathCase) {
+                PathCase pathCase = (PathCase) response.getResponseType();
+                List<PathMetric> pathMetricList = pathCase.getPathProperties().getPathMetric();
+                for (PathMetric pathMetric : pathMetricList) {
+                    String metricType = pathMetric.getMetricType().getSimpleName();
+                    BigDecimal accumulativeValue = pathMetric.getAccumulativeValue();
+                    LOG.info("Metric type {} // AccumulatriveValue {}", metricType, accumulativeValue);
+                }
+
+                // Includes the list of nodes in the GNPy computed path as constraints for the PCE
+                List<OrderedHops> orderedHopsList = null;
+                List<PathRouteObjects> pathRouteObjectList = pathCase.getPathProperties().getPathRouteObjects();
+                int counter = 0;
+                for (PathRouteObjects pathRouteObjects : pathRouteObjectList) {
+                    if (pathRouteObjects.getPathRouteObject().getType() instanceof NumUnnumHop) {
+                        NumUnnumHop numUnnumHop = (NumUnnumHop) pathRouteObjects.getPathRouteObject().getType();
+                        String nodeId = numUnnumHop.getNodeId();
+                        org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing.constraints.rev171017
+                                .ordered.constraints.sp.hop.type.hop.type.Node node = new NodeBuilder()
+                                .setNodeId(nodeId).build();
+                        HopType hopType = new HopTypeBuilder().setHopType(node).build();
+                        OrderedHops orderedHops = new OrderedHopsBuilder().setHopNumber(counter).setHopType(hopType)
+                                .build();
+                        LOG.info("- gnpyResult class : Hard Constraint: {} // - Hop Node {}", counter, nodeId);
+                        orderedHopsList.add(orderedHops);
+                        counter++;
+                    }
+                }
+                Include include = new IncludeBuilder().setOrderedHops(orderedHopsList).build();
+                General general = new GeneralBuilder().setInclude(include).build();
+                hardConstraints = new HardConstraintsBuilder().setCoRoutingOrGeneral(general).build();
+            }
+        }
+        return hardConstraints;
+    }
+
+    /**
+     * Parses the input json with concrete implementation of
+     * {@link JsonParserStream}.
+     *
+     * @param reader
+     *            of the given JSON
+     * @throws Exception
+     *
+     */
+    private Optional<NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?>> parseInputJSON(JsonReader reader,
+            Class<? extends DataObject> objectClass) throws Exception {
+        NormalizedNodeResult result = new NormalizedNodeResult();
+        SchemaContext schemaContext = getSchemaContext(objectClass);
+        try (NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+                JsonParserStream jsonParser = JsonParserStream.create(streamWriter, schemaContext, schemaContext);) {
+            LOG.debug("GNPy: the path to the reader {}", reader.getPath());
+            LOG.debug("GNPy: the reader {}", reader.toString());
+            LOG.debug("GNPy: the jsonParser class {} // jsonParser to string {}", jsonParser.getClass(),
+                    jsonParser.toString());
+            jsonParser.parse(reader);
+        } catch (IOException e) {
+            LOG.warn("GNPy: exception {} occured during parsing Json input stream", e.getMessage());
+            return Optional.empty();
+        }
+        return Optional.ofNullable(result.getResult());
+    }
+
+    private SchemaContext getSchemaContext(Class<? extends DataObject> objectClass) throws Exception {
+        final ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create();
+        Iterable<? extends YangModuleInfo> moduleInfos;
+        SchemaContext schemaContext = null;
+        moduleInfos = Collections.singleton(BindingReflections.getModuleInfo(objectClass));
+        moduleContext.addModuleInfos(moduleInfos);
+        schemaContext = moduleContext.tryToCreateSchemaContext().get();
+        return schemaContext;
+    }
+
+    private String readResultFromFile(String fileName) {
+        BufferedReader br = null;
+        FileReader fr = null;
+        StringBuilder sb = new StringBuilder();
+        String gnpyResponse;
+
+        try {
+            fr = new FileReader(fileName);
+            br = new BufferedReader(fr);
+            String currentLine;
+            while ((currentLine = br.readLine()) != null) {
+                LOG.info(currentLine);
+                sb.append(currentLine);
+            }
+            fr.close();
+        } catch (IOException e) {
+            LOG.warn("GNPy: exception {} occured during the reading of results", e.getMessage());
+        }
+        gnpyResponse = sb.toString();
+        return gnpyResponse;
+    }
+
+    /**
+     * Transforms the given input {@link NormalizedNode} into the given
+     * {@link DataObject}.
+     *
+     * @param normalizedNode
+     *            normalized node you want to convert
+     * @param rootNode
+     *            {@link QName} of converted normalized node root
+     *
+     *            <p>
+     *            The input object should be {@link ContainerNode}
+     *            </p>
+     */
+    public <T extends DataObject> Optional<T> getDataObject(@Nonnull NormalizedNode<?, ?> normalizedNode,
+            @Nonnull QName rootNode, BindingNormalizedNodeSerializer codecRegistry) {
+        if (normalizedNode != null) {
+            LOG.debug("GNPy: The codecRegistry is ", codecRegistry.toString());
+        } else {
+            LOG.warn("GNPy: The codecRegistry is null");
+        }
+        Preconditions.checkNotNull(normalizedNode);
+        if (normalizedNode instanceof ContainerNode) {
+            YangInstanceIdentifier.PathArgument directChildIdentifier = YangInstanceIdentifier.of(rootNode)
+                    .getLastPathArgument();
+            Optional<NormalizedNode<?, ?>> directChild = NormalizedNodes.getDirectChild(normalizedNode,
+                    directChildIdentifier);
+            if (!directChild.isPresent()) {
+                throw new IllegalStateException(String.format("Could not get the direct child of %s", rootNode));
+            }
+            normalizedNode = directChild.get();
+            LOG.debug("GNPy: the normalized node is ", normalizedNode.getNodeType());
+        }
+        YangInstanceIdentifier rootNodeYangInstanceIdentifier = YangInstanceIdentifier.of(rootNode);
+        LOG.debug("GNPy: the root Node Yang Instance Identifier is ", rootNodeYangInstanceIdentifier.toString());
+        Map.Entry<?, ?> bindingNodeEntry = codecRegistry.fromNormalizedNode(rootNodeYangInstanceIdentifier,
+                normalizedNode);
+        if (bindingNodeEntry == null) {
+            LOG.debug("The binding Node Entry is null");
+            return Optional.empty();
+        }
+        return Optional.ofNullable((T) bindingNodeEntry.getValue());
+    }
+}
diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperations.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperations.java
new file mode 100644 (file)
index 0000000..11489dc
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2018 Orange, Inc. 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.pce.gnpy;
+
+import org.opendaylight.transportpce.common.DataStoreContext;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface ServiceDataStoreOperations {
+
+    void createXMLFromDevice(DataStoreContext dataStoreContextUtil, OrgOpenroadmDevice device, String output);
+
+    String createJsonStringFromDataObject(InstanceIdentifier<?> id, DataObject object) throws Exception;
+
+    void writeStringFile(String jsonString, String fileName);
+}
diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/ServiceDataStoreOperationsImpl.java
new file mode 100644 (file)
index 0000000..4771b5c
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2018 Orange, Inc. 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.pce.gnpy;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.Optional;
+
+import javassist.ClassPool;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.dom.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.transportpce.common.DataStoreContext;
+import org.opendaylight.transportpce.common.converter.XMLDataObjectConverter;
+import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev170206.org.openroadm.device.container.OrgOpenroadmDevice;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactory;
+import org.opendaylight.yangtools.yang.data.codec.gson.JSONNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.codec.gson.JsonWriterFactory;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ServiceDataStoreOperationsImpl implements ServiceDataStoreOperations {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ServiceDataStoreOperationsImpl.class);
+    private final DataBroker dataBroker;
+
+    public ServiceDataStoreOperationsImpl(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+    }
+
+    public void createXMLFromDevice(DataStoreContext dataStoreContextUtil, OrgOpenroadmDevice device, String output) {
+        if (device != null) {
+            Optional<NormalizedNode<?, ?>> transformIntoNormalizedNode = null;
+            XMLDataObjectConverter cwDsU = XMLDataObjectConverter.createWithDataStoreUtil(dataStoreContextUtil);
+            transformIntoNormalizedNode = cwDsU.toNormalizedNodes(device, OrgOpenroadmDevice.class);
+            if (!transformIntoNormalizedNode.isPresent()) {
+                throw new IllegalStateException(
+                        String.format("Could not transform the input %s into normalized nodes", device));
+            }
+            Writer writerFromDataObject =
+                cwDsU.writerFromDataObject(device, OrgOpenroadmDevice.class,cwDsU.dataContainer());
+            try {
+                BufferedWriter writer = new BufferedWriter(new FileWriter(output));
+                writer.write(writerFromDataObject.toString());
+                writer.close();
+            } catch (IOException e) {
+                LOG.error("Bufferwriter error ");
+            }
+            LOG.debug("GNPy: device xml : {}", writerFromDataObject.toString());
+        }
+    }
+
+    public String createJsonStringFromDataObject(final InstanceIdentifier<?> id, DataObject object) throws Exception {
+
+        // See this link for more info :
+        // https://github.com/opendaylight/fpc/blob/master/impl/src/main/java/org/opendaylight/fpc/utils/FpcCodecUtils.java
+        final SchemaPath scPath = SchemaPath
+                .create(FluentIterable.from(id.getPathArguments()).transform(new Function<PathArgument, QName>() {
+                    @Override
+                    public QName apply(final PathArgument input) {
+                        return BindingReflections.findQName(input.getType());
+                    }
+                }), true);
+        final Writer writer = new StringWriter();
+        NormalizedNodeStreamWriter domWriter;
+
+        try {
+            // Prepare the variables
+            final ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create();
+            Iterable<? extends YangModuleInfo> moduleInfos = Collections
+                    .singleton(BindingReflections.getModuleInfo(object.getClass()));// TransportpceGnpyData.class));
+            moduleContext.addModuleInfos(moduleInfos);
+            SchemaContext schemaContext = moduleContext.tryToCreateSchemaContext().get();
+            BindingRuntimeContext bindingContext;
+            bindingContext = BindingRuntimeContext.create(moduleContext, schemaContext);
+            final BindingNormalizedNodeCodecRegistry bindingStreamCodecs = new BindingNormalizedNodeCodecRegistry(
+                    StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault())));
+            bindingStreamCodecs.onBindingRuntimeContextUpdated(bindingContext);
+            BindingNormalizedNodeCodecRegistry codecRegistry = bindingStreamCodecs;
+
+            /*
+             * This function needs : - context - scPath.getParent() -
+             * scPath.getLastComponent().getNamespace(), -
+             * JsonWriterFactory.createJsonWriter(writer)
+             */
+            domWriter = JSONNormalizedNodeStreamWriter.createExclusiveWriter(
+                    JSONCodecFactory.createSimple(schemaContext), scPath.getParent(),
+                    scPath.getLastComponent().getNamespace(), JsonWriterFactory.createJsonWriter(writer, 2));
+            // The write part
+            final BindingStreamEventWriter bindingWriter = codecRegistry.newWriter(id, domWriter);
+            codecRegistry.getSerializer(id.getTargetType()).serialize(object, bindingWriter);
+            // file.write(writer.toString());
+            // file.close();
+            writer.close();
+        } catch (IOException e) {
+            LOG.error("GNPy: writer error ");
+        } catch (YangSyntaxErrorException e) {
+            LOG.warn("GNPy: exception {} occured during json file creation", e.getMessage(), e);
+        } catch (ReactorException e) {
+            LOG.warn("GNPy: exception {} occured during json file creation", e.getMessage(), e);
+//        } catch (Exception e) {
+//            LOG.warn("An error {} occured during json file creation", e.getMessage(), e);
+        }
+        return writer.toString();
+    }
+
+    // Write the json as a string in a file
+    public void writeStringFile(String jsonString, String fileName) {
+        try {
+            FileWriter file = new FileWriter(fileName);
+            file.write(jsonString);
+            file.close();
+        } catch (IOException e) {
+            LOG.error("GNPy: writer error ");
+        }
+    }
+}
index c53b96aa325e1bac730eea9cf7a14a247392e1c8..0d94866d2eba8491227bfb304992935298b214e1 100644 (file)
@@ -16,10 +16,10 @@ import org.junit.Assert;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.transportpce.binding.converter.XMLDataObjectConverter;
-import org.opendaylight.transportpce.binding.converter.api.DataObjectConverter;
+import org.opendaylight.transportpce.common.DataStoreContext;
 import org.opendaylight.transportpce.common.NetworkUtils;
-import org.opendaylight.transportpce.test.common.DataStoreContext;
+import org.opendaylight.transportpce.common.converter.XMLDataObjectConverter;
+import org.opendaylight.transportpce.common.converter.api.DataObjectConverter;
 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev171017.PathComputationRequestOutput;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.path.description.atoz.direction.AToZ;
 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev171017.pce.resource.resource.resource.Node;
index 3c598ee58e891ff3ea40a38c2eab7c40b2bf74b5..d33967f1d4b238dc41e4443c5119b76e68c56d84 100644 (file)
             <artifactId>yang-data-codec-gson</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>transportpce-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 </project>
index bfc2d8a97ffa80467dbe385588c1c2860e949ba3..76682adbadb44f3c6e2032741f31e6e408c75eee 100644 (file)
@@ -11,8 +11,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.transportpce.test.common.DataStoreContext;
-import org.opendaylight.transportpce.test.common.DataStoreContextImpl;
+import org.opendaylight.transportpce.common.DataStoreContext;
+import org.opendaylight.transportpce.common.DataStoreContextImpl;
 
 public abstract class AbstractTest {
 
index 833de2289f0f8bfde9773d4d99454df8b3512c00..861cb948d75c4c12d7b2f3c68ffa58004bd7b039 100644 (file)
@@ -21,10 +21,10 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.transportpce.binding.converter.XMLDataObjectConverter;
-import org.opendaylight.transportpce.binding.converter.api.DataObjectConverter;
-import org.opendaylight.transportpce.test.common.DataStoreContext;
-import org.opendaylight.transportpce.test.common.DataStoreContextImpl;
+import org.opendaylight.transportpce.common.DataStoreContext;
+import org.opendaylight.transportpce.common.DataStoreContextImpl;
+import org.opendaylight.transportpce.common.converter.XMLDataObjectConverter;
+import org.opendaylight.transportpce.common.converter.api.DataObjectConverter;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;