From f16a23bbe46cdff5c2f97f7229a29563090ae81e Mon Sep 17 00:00:00 2001 From: atriki Date: Fri, 4 Feb 2022 12:14:01 +0100 Subject: [PATCH] New API for GNPy - add new yang files of the api - update the code - remove node identification by IP address JIRA: TRNSPRTPCE-513 Change-Id: I530323561cb3640b7082d4b5e2f22e782b2057b2 Signed-off-by: Ahmed Triki --- api/src/main/yang/gnpy-api@2019-01-03.yang | 44 -- api/src/main/yang/gnpy-api@2022-02-21.yang | 97 +++ .../yang/gnpy-eqpt-config@2018-11-19.yang | 76 --- .../yang/gnpy-eqpt-config@2022-02-21.yang | 483 +++++++++++++ ... => gnpy-network-topology@2022-02-21.yang} | 130 +++- ...ath-computation-simplified@2020-09-09.yang | 632 ------------------ ...ath-computation-simplified@2022-02-21.yang | 612 +++++++++++++++++ .../common/fixedflex/GridConstant.java | 6 +- .../common/fixedflex/GridUtils.java | 9 + .../converter/JsonStringConverterTest.java | 18 +- .../src/test/resources/expected_string.json | 2 +- common/src/test/resources/gnpy_request.json | 6 +- .../transportpce/pce/gnpy/GnpyResult.java | 67 +- .../pce/gnpy/GnpyServiceImpl.java | 192 +++--- .../transportpce/pce/gnpy/GnpyTopoImpl.java | 217 ++---- .../pce/gnpy/GnpyUtilitiesImpl.java | 35 +- .../pce/gnpy/consumer/GnpyApiModule.java | 11 +- .../pce/gnpy/consumer/GnpyConsumer.java | 8 +- .../pce/gnpy/consumer/GnpyConsumerImpl.java | 17 +- .../pce/gnpy/consumer/GnpyResource.java | 16 +- .../pce/gnpy/consumer/GnpyStatus.java | 35 + .../pce/gnpy/consumer/JsonConfigurator.java | 8 +- ...Serializer.java => RequestSerializer.java} | 25 +- .../pce/gnpy/consumer/ResultDeserializer.java | 19 +- .../service/PathComputationServiceImpl.java | 18 +- .../pce/gnpy/consumer/GnpyConsumerTest.java | 10 +- .../pce/gnpy/consumer/GnpyStub.java | 37 +- .../PathComputationServiceImplTest.java | 25 +- pce/src/test/resources/gnpy/gnpy_request.json | 6 +- .../resources/gnpy/gnpy_result_no_path.json | 2 +- pce/src/test/resources/gnpy/gnpy_status.json | 4 + .../gnpy/openroadmTopology.json | 32 +- tests/transportpce_tests/pce/test03_gnpy.py | 15 +- tox.ini | 3 +- 34 files changed, 1702 insertions(+), 1215 deletions(-) delete mode 100644 api/src/main/yang/gnpy-api@2019-01-03.yang create mode 100644 api/src/main/yang/gnpy-api@2022-02-21.yang delete mode 100644 api/src/main/yang/gnpy-eqpt-config@2018-11-19.yang create mode 100644 api/src/main/yang/gnpy-eqpt-config@2022-02-21.yang rename api/src/main/yang/{gnpy-network-topology@2021-08-31.yang => gnpy-network-topology@2022-02-21.yang} (53%) delete mode 100644 api/src/main/yang/gnpy-path-computation-simplified@2020-09-09.yang create mode 100644 api/src/main/yang/gnpy-path-computation-simplified@2022-02-21.yang create mode 100644 pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyStatus.java rename pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/{GnpyApiSerializer.java => RequestSerializer.java} (63%) create mode 100644 pce/src/test/resources/gnpy/gnpy_status.json diff --git a/api/src/main/yang/gnpy-api@2019-01-03.yang b/api/src/main/yang/gnpy-api@2019-01-03.yang deleted file mode 100644 index e0d5348d0..000000000 --- a/api/src/main/yang/gnpy-api@2019-01-03.yang +++ /dev/null @@ -1,44 +0,0 @@ -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: - contact: - contact: - "; - 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 { - description - "Describe the topology file to connect to gnpy"; - uses gnpynt:topo; - } - container service-file { - description - "Describe the service file to connect to gnpy"; - uses gnpypc:service; - } - } -} diff --git a/api/src/main/yang/gnpy-api@2022-02-21.yang b/api/src/main/yang/gnpy-api@2022-02-21.yang new file mode 100644 index 000000000..75e530c9d --- /dev/null +++ b/api/src/main/yang/gnpy-api@2022-02-21.yang @@ -0,0 +1,97 @@ +module gnpy-api { + yang-version 1.1; + namespace "gnpy:gnpy-api"; + prefix gnpyapi; + + import gnpy-network-topology { + prefix gnpynt; + } + import gnpy-path-computation-simplified { + prefix gnpypc; + } + import gnpy-eqpt-config { + prefix gnpyeqpt; + } + + organization + "Telecom Infra Project OOPT PSE Working Group"; + contact + "WG Web: + contact: + contact: + "; + description + "YANG model for gnpy api input for path computation - + The license used for all the yang files of GNPy is BSD 3-Clause License + + BSD 3-Clause License + + Copyright (c) 2018, Telecom Infra Project + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; + + revision 2022-02-21 { + description + "draft for GNPy4TPCE preversion - non official version relevant for v2.4 GNPy file format"; + reference + "YANG model for api input for path computation with gnpy"; + } + + revision 2020-10-22 { + description + "draft for experimental/2020-candi"; + reference + "YANG model for api input for path computation with gnpy"; + } + + revision 2019-01-03 { + description + "first draft for GNPy4TPCE preversion - non official version relevant for v1.2 GNPy file format"; + reference + "YANG model for api input for path computation with gnpy"; + } + + container request { + container service { + description + "Describe the service file to connect to gnpy"; + uses gnpypc:service; + } + container topology { + description + "Describe the topology file to connect to gnpy"; + uses gnpynt:topo; + } + container equipment { + description + "Describe the equipment library to connect to gnpy"; + uses gnpyeqpt:eqpt; + } + } + + +} \ No newline at end of file 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 deleted file mode 100644 index 23fa129e7..000000000 --- a/api/src/main/yang/gnpy-eqpt-config@2018-11-19.yang +++ /dev/null @@ -1,76 +0,0 @@ -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: - contact: - contact: - "; - 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"; - description - "a unique name to ID the fiber in the JSON or Excel template topology input file"; - leaf type_variety { - type string; - } - } - list Transceiver { - key "type_variety"; - description - "a unique name to ID the transceiver in the JSON or Excel template topology input file"; - leaf type_variety { - type string; - } - } - 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-eqpt-config@2022-02-21.yang b/api/src/main/yang/gnpy-eqpt-config@2022-02-21.yang new file mode 100644 index 000000000..603d56d2a --- /dev/null +++ b/api/src/main/yang/gnpy-eqpt-config@2022-02-21.yang @@ -0,0 +1,483 @@ +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: + contact: + contact: + "; + + description + "Base YANG model for gnpy equipment library input - + The license used for all the yang files of GNPy is BSD 3-Clause License + + BSD 3-Clause License + + Copyright (c) 2018, Telecom Infra Project + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; + + revision 2022-02-21 { + description + "draft for GNPy4TPCE preversion - non official version relevant for v2.4 GNPy file format"; + reference + "YANG model for api input for path computation with gnpy"; + } + + revision 2020-10-22 { + description "draft for experimental/2020-candi"; + reference "Base YANG model for equipment library input for path computation with gnpy"; + } + + revision 2019-01-03 { + description + "first draft for GNPy4TPCE preversion - non official version relevant for v1.2 GNPy file format"; + reference + "YANG model for api input for path computation with gnpy"; + } + + identity edfa-type-def { + description "base identity for variable gain and fixed gain"; + } + + identity variable-gain{ + base edfa-type-def ; + description "'variable_gain' is a simplified model simulating a 2-coil + EDFA with internal, input and output VOAs. The NF vs gain response is calculated + accordingly based on the input parameters: nf_min, nf_max, and gain_flatmax. It + is not a simple interpolation but a 2-stage NF calculation."; + } + + identity fixed-gain{ + base edfa-type-def ; + description "'fixed_gain' is a fixed gain model. NF == Cte == nf0 if gain_min < gain < gain_flatmax"; + } + + identity fiber-variety { + description "base identity for fiber variety"; + } + + identity transceiver-variety { + description "base identity for transceiver variety"; + } + + + grouping variable-gain { + leaf nf_min { + type decimal64 { + fraction-digits 2; + } + units dB; + } + leaf nf_max { + type decimal64 { + fraction-digits 2; + } + units dB; + } + leaf out_voa_auto{ + type boolean ; + description "auto_design feature to optimize the amplifier output VOA. If true, output VOA is present + and will be used to push amplifier gain to its maximum, within EOL power margins."; + } + } + + grouping fixed-gain{ + leaf nf0 { + type decimal64 { + fraction-digits 2; + } + units dB; + } + } + + grouping no-type-def{ + leaf advanced_config_from_json { + type string ; + description " filename with json edfa"; + + } + } + + + grouping openroadm{ + leaf-list nf_coef { + type decimal64 { + fraction-digits 5; + } + //default [8.1e-4,6.142e-2,1.558,19.97] ; + } + } + + grouping dual-stage { + leaf raman { + type boolean; + } + leaf preamp_variety { + type leafref { + path "../../Edfa/type_variety"; + } + } + leaf booster_variety { + type leafref { + path "../../Edfa/type_variety"; + } + } + } + + grouping edfa-common { + leaf allowed_for_design{ + type boolean ; + description "If false, the amplifier will not be picked by auto-design but it can still be used as a + manual input (from JSON or Excel template topology files.)"; + } + leaf gain_flatmax { + type decimal64 { + fraction-digits 2; + } + units dB; + } + leaf gain_min { + type decimal64 { + fraction-digits 2; + } + units dB; + } + leaf p_max { + type decimal64 { + fraction-digits 2; + } + units dBm; + } + leaf type_def { + type identityref{ + base edfa-type-def ; + } + } + choice type_of_model { + case variable-gain { + when "type_def = 'variable-gain'"; + uses variable-gain ; + } + case fixed-gain{ + when "type_def = 'fixed-gain'"; + uses fixed-gain; + } + case no-type-def{ + when "type_def = 'no-type-def'"; + uses no-type-def; + } + case openroadm{ + when "type_def = 'openroadm'"; + uses openroadm; + } + case dual_stage { + when "type_def = 'dual_stage'"; + uses dual-stage ; + } + } + } + + grouping common-fiber { + description "common parameters for fiber and raman fiber"; + leaf type_variety { + type string ; + } + leaf dispersion{ + type decimal64 { + fraction-digits 8; + } + units s.m-1.m-1; + } + leaf gamma{ + type decimal64 { + fraction-digits 8; + } + units w-1.m-1 ; + description "2pi.n2/(lambda*Aeff) (w-2.m-1)"; + } + leaf pmd_coef{ + type decimal64 { + fraction-digits 16; + } + units s.sqrt(m)-1; + } + } + + grouping eqpt{ + 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"; + } + uses edfa-common; + } + + list Fiber { + key type_variety; + uses common-fiber; + } + + list RamanFiber { + uses common-fiber; + container raman_efficiency { + leaf-list cr { + type decimal64 { + fraction-digits 8; + } + } + leaf-list frequency_offset { + type decimal64 { + fraction-digits 8; + } + } + } + } + + list Span { + leaf power_mode { + type boolean ; + } + leaf-list delta_power_range_db { + type decimal64 { + fraction-digits 2; + } + } + leaf max_length { + type decimal64 { + fraction-digits 2; + } + units km; + default 150.0 ; + } + leaf max_loss { + type decimal64 { + fraction-digits 2; + } + units dB; + } + leaf max_fiber_lineic_loss_for_raman { + type decimal64 { + fraction-digits 2; + } + units dB.km-1; + } + leaf target_extended_gain { + type decimal64 { + fraction-digits 2; + } + units dB; + } + leaf length_units{ + type string ; + default "km"; + } + leaf padding{ + type decimal64 { + fraction-digits 2; + } + default 10.0 ; + } + leaf EOL{ + type decimal64 { + fraction-digits 2; + } + default 0.0 ; + } + leaf con_in{ + type decimal64 { + fraction-digits 2; + } + default 0.0 ; + } + leaf con_out{ + type decimal64 { + fraction-digits 2; + } + default 0.0 ; + } + } + + list Roadm { + leaf target_pch_out_db { + type decimal64 { + fraction-digits 2; + } + } + leaf add_drop_osnr { + type decimal64 { + fraction-digits 2; + } + } + leaf pmd { + type decimal64 { + fraction-digits 2; + } + } + container restrictions { + leaf-list preamp_variety_list { + type string; + } + leaf-list booster_variety_list { + type string; + } + } + } + + list SI { + leaf f_min { + type decimal64 { + fraction-digits 2; + } + } + leaf f_max { + type decimal64 { + fraction-digits 2; + } + } + leaf baud_rate { + type decimal64 { + fraction-digits 2; + } + } + leaf spacing { + type decimal64 { + fraction-digits 2; + } + } + leaf power_dbm { + type decimal64 { + fraction-digits 2; + } + } + leaf-list power_range_db { + type decimal64 { + fraction-digits 2; + } + } + leaf roll_off { + type decimal64 { + fraction-digits 2; + } + } + leaf tx_osnr { + type decimal64 { + fraction-digits 2; + } + } + leaf sys_margins { + type decimal64 { + fraction-digits 2; + } + } + } + + list Transceiver { + leaf type_variety { + type string ; + description "a unique name to ID the transceiver in the JSON or Excel template topology input file"; + } + container frequency { + leaf min { + type decimal64 { + fraction-digits 2; + } + units Hz ; + } + leaf max { + type decimal64 { + fraction-digits 2; + } + units Hz ; + } + description "Min/max frequency of transponder eg 191.35e12 and 196.1e12"; + } + list mode { + leaf format { + type string ; + description "unique name of the mode"; + } + leaf baud_rate { + type decimal64 { + fraction-digits 2; + } + units baud ; + description "baud_rate"; + } + leaf OSNR { + type decimal64 { + fraction-digits 2; + } + units dB ; + description "min required OSNR in 0.1nm (dB)"; + } + leaf tx_osnr { + type decimal64 { + fraction-digits 2; + } + units dB ; + description "min required OSNR in 0.1nm (dB)"; + } + leaf min_spacing { + type decimal64 { + fraction-digits 2; + } + units GHz ; + description "..."; + } + leaf bit_rate { + type decimal64 { + fraction-digits 2; + } + units bit/s ; + description "bit rate"; + } + leaf roll_off { + type decimal64 { + fraction-digits 2; + } + description "..."; + } + leaf cost { + type decimal64 { + fraction-digits 2; + } + description "arbitrary unit"; + } + } + } + } +} + diff --git a/api/src/main/yang/gnpy-network-topology@2021-08-31.yang b/api/src/main/yang/gnpy-network-topology@2022-02-21.yang similarity index 53% rename from api/src/main/yang/gnpy-network-topology@2021-08-31.yang rename to api/src/main/yang/gnpy-network-topology@2022-02-21.yang index b20f1ed30..390831780 100644 --- a/api/src/main/yang/gnpy-network-topology@2021-08-31.yang +++ b/api/src/main/yang/gnpy-network-topology@2022-02-21.yang @@ -1,10 +1,7 @@ module gnpy-network-topology { - yang-version 1; + yang-version 1.1; namespace "gnpy:gnpy-network-topology"; prefix gnpynt; - import ietf-inet-types { - prefix inet; - } organization "Telecom Infra Project OOPT PSE Working Group"; @@ -14,20 +11,60 @@ module gnpy-network-topology { contact: "; description - "YANG model for gnpy network input for path computation - transportPCE preversion"; + "YANG model for gnpy network input - + The license used for all the yang files of GNPy is BSD 3-Clause License + + BSD 3-Clause License + + Copyright (c) 2018, Telecom Infra Project + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. - revision 2021-08-31 { + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; + + revision 2022-02-21 { description - "Change absolute path in leafref"; + "draft for GNPy4TPCE preversion - non official version relevant for v2.4 GNPy file format"; + reference + "YANG model for api input for path computation with gnpy"; } - revision 2018-12-14 { + revision 2020-10-22 { description - "first draft"; + "draft for experimental/2020-candi"; reference "YANG model for network input for path computation with gnpy"; } + revision 2019-01-03 { + description + "first draft for GNPy4TPCE preversion - non official version relevant for v1.2 GNPy file format"; + reference + "YANG model for api input for path computation with gnpy"; + } + identity type-element { description "Base identity for element type"; @@ -42,7 +79,7 @@ module gnpy-network-topology { identity Fiber { base type-element; description - "Fiber element"; + "Fiber element (unidirectional)"; } identity Roadm { @@ -60,7 +97,9 @@ module gnpy-network-topology { identity Fused { base type-element; description - "Fused element"; + "Fused element ; non amplified connection between two fiber spans ; + can be used to model optical distribution frame, or losses due to + connectors or fused in a span"; } identity length-unit { @@ -86,16 +125,6 @@ module gnpy-network-topology { } } - 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; @@ -137,6 +166,8 @@ module gnpy-network-topology { fraction-digits 2; } mandatory true; + units db/km; + description "Loss coefficient of the fiber span (dB/km)"; } leaf length_units { type identityref { @@ -148,18 +179,21 @@ module gnpy-network-topology { type decimal64 { fraction-digits 2; } + units "dB"; mandatory true; } leaf con_in { type decimal64 { fraction-digits 2; } + units "dB"; mandatory true; } leaf con_out { type decimal64 { fraction-digits 2; } + units "dB"; mandatory true; } } @@ -168,16 +202,16 @@ module gnpy-network-topology { container operational { description "Operational values for the Edfa "; - leaf gain-target { + leaf gain_target { type decimal64 { fraction-digits 2; } units "dB"; mandatory true; description - ".."; + "gain target of the amplifier (before VOA and after att_in)"; } - leaf tilt-target { + leaf tilt_target { type decimal64 { fraction-digits 2; } @@ -185,7 +219,7 @@ module gnpy-network-topology { description ".."; } - leaf out-voa { + leaf out_voa { type decimal64 { fraction-digits 2; } @@ -194,6 +228,15 @@ module gnpy-network-topology { description ".."; } + leaf delta_p { + type decimal64 { + fraction-digits 2; + } + units "dB"; + mandatory true; + description + "per channel target output power delta with respect to power setting in SI"; + } } } @@ -206,11 +249,32 @@ module gnpy-network-topology { description ".."; } + container restrictions { + leaf-list preamp_variety_list { + type string; + description + "List of authorized preamp type-variety"; + } + leaf-list booster_variety_list { + type string; + description + "List of authorized booster type-variety"; + } + } } grouping transceiver-params; - grouping fused-params; + grouping fused-params{ + leaf loss { + type decimal64 { + fraction-digits 2; + } + units "dB"; + description + "Concentrated loss of the fused element"; + } + } grouping element-type-choice { choice element-type { @@ -220,7 +284,7 @@ module gnpy-network-topology { } case FiberRoadm { container params { - choice fiberroadm { + choice fiberroadmfused { case Fiber { when "type = 'Fiber'"; uses fiber-params; @@ -229,18 +293,20 @@ module gnpy-network-topology { when "type = 'Roadm'"; uses roadm-params; } + case Fused { + when "type = 'Fused'"; + uses fused-params; + } } } } case Transceiver { when "type = 'Transceiver'"; } - case Fused { - when "type = 'Fused'"; - } } } + grouping topo { list elements { key "uid"; @@ -266,12 +332,12 @@ module gnpy-network-topology { config false; leaf from_node { type leafref { - path ../../elements/uid; + path "../../elements/uid"; } } leaf to_node { type leafref { - path ../../elements/uid; + path "../../elements/uid"; } } } diff --git a/api/src/main/yang/gnpy-path-computation-simplified@2020-09-09.yang b/api/src/main/yang/gnpy-path-computation-simplified@2020-09-09.yang deleted file mode 100644 index 0299fbe3f..000000000 --- a/api/src/main/yang/gnpy-path-computation-simplified@2020-09-09.yang +++ /dev/null @@ -1,632 +0,0 @@ -module gnpy-path-computation-simplified { - yang-version 1; - namespace "gnpy:path"; - prefix gnpypc; - - import ietf-inet-types { - prefix inet; - } - - organization - "Telecom Infra Project OOPT PSE Working Group"; - contact - "WG Web: - contact: - contact: - "; - description - "YANG model for gnpy path computation simplified for transportPCE"; - - revision 2020-09-09 { - description - "remove key from route-object-include-exclude"; - } - revision 2020-02-02 { - description - "second draft with detailed blocking reasons"; - reference - "YANG model for path computation with gnpy inputs"; - } - - 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"; - } - - 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 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 { - type decimal64 { - fraction-digits 1; - } - units "Hz"; - mandatory true; - 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.\n"; - } - 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; - } - units "bit/s"; - mandatory true; - description - "Capacity required"; - } - } - - 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"; - } - } - } - } - } - - 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 { - 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 { - description - "Numbered and Unnumbered link/node explicit route - subobject"; - 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"; - } - } - } - case label { - description - "The Label ERO subobject"; - container label-hop { - description - "Label hop type"; - uses effective-freq-slot; - } - } - 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 { - description - "A requested bandwidth to use for path computation"; - uses gnpy-specific-parameters; - } - } - - 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 { - description - "Path computation output information"; - uses generic-path-properties; - } - - // 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"; - description - "if path computation cannot identify a path, - rpc returns no path."; - 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; - } - } - - /* 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."; - } - leaf bidirectional { - type boolean; - mandatory true; - description - "Specify the bidirectionality of the path"; - } - 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 { - description - "Path computation service."; - uses path-info; - } - } - } - } - - container result { - description - "Describe the service file to connect to gnpy"; - uses result; - } -} diff --git a/api/src/main/yang/gnpy-path-computation-simplified@2022-02-21.yang b/api/src/main/yang/gnpy-path-computation-simplified@2022-02-21.yang new file mode 100644 index 000000000..24f233757 --- /dev/null +++ b/api/src/main/yang/gnpy-path-computation-simplified@2022-02-21.yang @@ -0,0 +1,612 @@ +module gnpy-path-computation-simplified { + yang-version 1.1; + namespace "gnpy:path"; + + prefix "gnpypc"; + + organization + "Telecom Infra Project OOPT PSE Working Group"; + + contact + "WG Web: + contact: + contact: + "; + + description + "YANG model for gnpy path computation simplified - + The license used for all the yang files of GNPy is BSD 3-Clause License + + BSD 3-Clause License + + Copyright (c) 2018, Telecom Infra Project + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; + + revision 2022-02-21 { + description + "draft for GNPy4TPCE preversion - non official version relevant for v2.4 GNPy file format"; + reference + "YANG model for api input for path computation with gnpy"; + } + + revision 2020-10-22 { + description + "draft for experimental/2020-candi"; + reference + "YANG model for path computation with gnpy inputs"; + } + + revision 2019-01-03 { + description + "first draft for GNPy4TPCE preversion - non official version relevant for v1.2 GNPy file format"; + reference + "YANG model for api input for path computation with gnpy"; + } + + 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 uint32; + 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 int32; + 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 "not used yet. 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 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 { + 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."; + } + key "index"; + 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 string; + description "TE tunnel source address."; + } + leaf destination { + type string; + description "P2P tunnel destination address"; + } + leaf src-tp-id { + type string; + description "TE tunnel source termination point identifier."; + } + leaf dst-tp-id { + type string; + 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 string; + 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 string; + description "This list reports the set of M path computation requests that must be synchronized."; + } + } + } + } + + grouping path-metric { + 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"; + } + } + 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; + uses path-metric; + } + list z-a-path-metric { + key metric-type; + uses path-metric; + } + 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."; + } + } + + grouping service { + list path-request { + key "request-id"; + description "request-list"; + leaf request-id { + type string; + mandatory true; + description "Each path computation request is uniquely identified by the request-id-number."; + } + leaf bidirectional { + type boolean; + mandatory true; + description "Specify the bidirectionality of the path"; + } + + 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 string; + 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 gnpypc:result; + description + "Describe the response object to gnpy"; + } +} diff --git a/common/src/main/java/org/opendaylight/transportpce/common/fixedflex/GridConstant.java b/common/src/main/java/org/opendaylight/transportpce/common/fixedflex/GridConstant.java index efb8fb717..cc626e121 100644 --- a/common/src/main/java/org/opendaylight/transportpce/common/fixedflex/GridConstant.java +++ b/common/src/main/java/org/opendaylight/transportpce/common/fixedflex/GridConstant.java @@ -33,6 +33,9 @@ public final class GridConstant { public static final double CENTRAL_FREQUENCY = 193.1; public static final int NB_SLOTS_100G = 8; public static final int NB_SLOTS_400G = 14; + public static final double OUTPUT_POWER_100GB_DBM = 2; + public static final BigDecimal OUTPUT_POWER_100GB_W = BigDecimal.valueOf(0.0015849); + public static final BigDecimal OUTPUT_POWER_400GB_W = BigDecimal.valueOf(0.0027735); public static final BigDecimal WIDTH_80 = BigDecimal.valueOf(80); public static final BigDecimal WIDTH_75 = BigDecimal.valueOf(75); public static final BigDecimal WIDTH_40 = BigDecimal.valueOf(40); @@ -89,7 +92,7 @@ public final class GridConstant { public static final Map RATE_SPECTRAL_WIDTH_SLOT_NUMBER_MAP = Map.of( ServiceRateConstant.RATE_100, NB_SLOTS_100G, ServiceRateConstant.RATE_200, NB_SLOTS_100G, - ServiceRateConstant.RATE_300, NB_SLOTS_100G, + ServiceRateConstant.RATE_300, NB_SLOTS_400G, ServiceRateConstant.RATE_400, NB_SLOTS_400G); private GridConstant() { @@ -107,6 +110,7 @@ public final class GridConstant { private static Table initFrequencySlotWidthTable() { Table frequencyWidthTable = HashBasedTable.create(); frequencyWidthTable.put(ServiceRateConstant.RATE_100, ModulationFormat.DpQpsk, SLOT_WIDTH_50); + frequencyWidthTable.put(ServiceRateConstant.RATE_200, ModulationFormat.DpQam16, SLOT_WIDTH_50); frequencyWidthTable.put(ServiceRateConstant.RATE_200, ModulationFormat.DpQpsk, SLOT_WIDTH_87_5); frequencyWidthTable.put(ServiceRateConstant.RATE_300, ModulationFormat.DpQam8, SLOT_WIDTH_87_5); frequencyWidthTable.put(ServiceRateConstant.RATE_400, ModulationFormat.DpQam16, SLOT_WIDTH_87_5); diff --git a/common/src/main/java/org/opendaylight/transportpce/common/fixedflex/GridUtils.java b/common/src/main/java/org/opendaylight/transportpce/common/fixedflex/GridUtils.java index a38897eaa..efbe2034b 100644 --- a/common/src/main/java/org/opendaylight/transportpce/common/fixedflex/GridUtils.java +++ b/common/src/main/java/org/opendaylight/transportpce/common/fixedflex/GridUtils.java @@ -221,4 +221,13 @@ public final class GridUtils { return frequencyIndex - 284; } + /** + * Convert the power from dBm to Watt. + * @param dbm power in dBm. + * @return outputpower in Watt. + */ + public static BigDecimal convertDbmW(double dbm) { + return BigDecimal.valueOf(Math.pow(10, (dbm - 30) / 10)); + } + } diff --git a/common/src/test/java/org/opendaylight/transportpce/common/converter/JsonStringConverterTest.java b/common/src/test/java/org/opendaylight/transportpce/common/converter/JsonStringConverterTest.java index eeb972371..2085e96cd 100644 --- a/common/src/test/java/org/opendaylight/transportpce/common/converter/JsonStringConverterTest.java +++ b/common/src/test/java/org/opendaylight/transportpce/common/converter/JsonStringConverterTest.java @@ -21,7 +21,7 @@ import org.junit.Test; import org.opendaylight.transportpce.test.AbstractTest; import org.opendaylight.transportpce.test.converter.DataObjectConverter; import org.opendaylight.transportpce.test.converter.JSONDataObjectConverter; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -36,12 +36,12 @@ public class JsonStringConverterTest extends AbstractTest { try (Reader reader = new FileReader("src/test/resources/gnpy_request.json", StandardCharsets.UTF_8)) { NormalizedNode normalizedNode = dataObjectConverter .transformIntoNormalizedNode(reader).get(); - GnpyApi gnpyRequest = (GnpyApi) getDataStoreContextUtil().getBindingDOMCodecServices() - .fromNormalizedNode(YangInstanceIdentifier.of(GnpyApi.QNAME), normalizedNode).getValue(); - JsonStringConverter gnpyJsonCOnverter = new JsonStringConverter( + Request gnpyRequest = (Request) getDataStoreContextUtil().getBindingDOMCodecServices() + .fromNormalizedNode(YangInstanceIdentifier.of(Request.QNAME), normalizedNode).getValue(); + JsonStringConverter gnpyJsonConverter = new JsonStringConverter( getDataStoreContextUtil().getBindingDOMCodecServices()); - String jsonString = gnpyJsonCOnverter - .createJsonStringFromDataObject(InstanceIdentifier.builder(GnpyApi.class).build(), + String jsonString = gnpyJsonConverter + .createJsonStringFromDataObject(InstanceIdentifier.builder(Request.class).build(), gnpyRequest, JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02); assertEquals("Should be a valid request", Files.readString(Paths.get("src/test/resources/expected_string.json")), jsonString); @@ -53,10 +53,10 @@ public class JsonStringConverterTest extends AbstractTest { @Test public void createDataObjectFromJsonStringTest() throws IOException { String json = Files.readString(Paths.get("src/test/resources/expected_string.json")); - JsonStringConverter gnpyJsonCOnverter = new JsonStringConverter( + JsonStringConverter gnpyJsonCOnverter = new JsonStringConverter( getDataStoreContextUtil().getBindingDOMCodecServices()); - GnpyApi request = gnpyJsonCOnverter - .createDataObjectFromJsonString(YangInstanceIdentifier.of(GnpyApi.QNAME), json, + Request request = gnpyJsonCOnverter + .createDataObjectFromJsonString(YangInstanceIdentifier.of(Request.QNAME), json, JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02); assertNotNull("Should not be null", request); } diff --git a/common/src/test/resources/expected_string.json b/common/src/test/resources/expected_string.json index 12a2760ab..73dcdfbdb 100644 --- a/common/src/test/resources/expected_string.json +++ b/common/src/test/resources/expected_string.json @@ -1 +1 @@ -{"gnpy-api":{"service-file":{"path-request":[{"request-id":2,"src-tp-id":"c3JjVHBJZA\u003d\u003d","destination":"127.0.0.41","explicit-route-objects":{"route-object-include-exclude":[{"explicit-route-usage":"gnpy-path-computation-simplified:route-include-ero","num-unnum-hop":{"hop-type":"STRICT","link-tp-id":"1","node-id":"127.0.0.20"},"index":0},{"explicit-route-usage":"gnpy-path-computation-simplified:route-include-ero","num-unnum-hop":{"hop-type":"STRICT","link-tp-id":"1","node-id":"127.0.0.30"},"index":1}]},"bidirectional":false,"dst-tp-id":"ZHN0VHBJZA\u003d\u003d","path-constraints":{"te-bandwidth":{"technology":"flexi-grid","trx_mode":"W100G","spacing":50000000000,"trx_type":"openroadm-beta1","path_bandwidth":100,"effective-freq-slot":[{"N":0,"M":4}]}},"source":"127.0.0.11"}]},"topology-file":{"elements":[{"uid":"243.0.0.10","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.12,"att_in":0,"con_out":0,"con_in":0,"length":60,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.11","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.12,"att_in":0,"con_out":0,"con_in":0,"length":60,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.12","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.29,"att_in":0,"con_out":0,"con_in":0,"length":100,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.13","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.2127659574468085124099303584443987347185611724853515625,"att_in":0,"con_out":0,"con_in":0,"length":140,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.14","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.29,"att_in":0,"con_out":0,"con_in":0,"length":100,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"127.0.0.20","type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20},"metadata":{"location":{"region":"OpenROADM-2","latitude":0,"longitude":0}}},{"uid":"127.0.0.41","type":"gnpy-network-topology:Transceiver","metadata":{"location":{"region":"XPONDER-4","latitude":0,"longitude":0}}},{"uid":"127.0.0.40","type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20},"metadata":{"location":{"region":"OpenROADM-4","latitude":0,"longitude":0}}},{"uid":"127.0.0.21","type":"gnpy-network-topology:Transceiver","metadata":{"location":{"region":"XPONDER-2","latitude":0,"longitude":0}}},{"uid":"243.0.0.1","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.11999999999999999555910790149937383830547332763671875,"att_in":0,"con_out":0,"con_in":0,"length":100,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.3","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.12,"att_in":0,"con_out":0,"con_in":0,"length":60,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.2","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.29,"att_in":0,"con_out":0,"con_in":0,"length":100,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.5","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.12,"att_in":0,"con_out":0,"con_in":0,"length":60,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.4","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.29,"att_in":0,"con_out":0,"con_in":0,"length":100,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.7","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.29,"att_in":0,"con_out":0,"con_in":0,"length":100,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.6","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.2127659574468085124099303584443987347185611724853515625,"att_in":0,"con_out":0,"con_in":0,"length":140,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.9","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.29,"att_in":0,"con_out":0,"con_in":0,"length":100,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"243.0.0.8","type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"loss_coef":0.11999999999999999555910790149937383830547332763671875,"att_in":0,"con_out":0,"con_in":0,"length":100,"length_units":"gnpy-network-topology:km"},"metadata":{"location":{"city":"N/A","region":"N/A","latitude":0,"longitude":0}}},{"uid":"127.0.0.31","type":"gnpy-network-topology:Transceiver","metadata":{"location":{"region":"XPONDER-3","latitude":0,"longitude":0}}},{"uid":"127.0.0.30","type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20},"metadata":{"location":{"region":"OpenROADM-3","latitude":0,"longitude":0}}},{"uid":"127.0.0.51","type":"gnpy-network-topology:Transceiver","metadata":{"location":{"region":"XPONDER-5","latitude":0,"longitude":0}}},{"uid":"127.0.0.50","type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20},"metadata":{"location":{"region":"OpenROADM-5","latitude":0,"longitude":0}}},{"uid":"127.0.0.11","type":"gnpy-network-topology:Transceiver","metadata":{"location":{"region":"XPONDER-1","latitude":0,"longitude":0}}},{"uid":"127.0.0.10","type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20},"metadata":{"location":{"region":"OpenROADM-1","latitude":0,"longitude":0}}}],"connections":[{"from_node":"127.0.0.51","to_node":"127.0.0.50"},{"from_node":"127.0.0.30","to_node":"127.0.0.31"},{"from_node":"127.0.0.10","to_node":"243.0.0.1"},{"from_node":"243.0.0.1","to_node":"127.0.0.30"},{"from_node":"127.0.0.20","to_node":"127.0.0.21"},{"from_node":"127.0.0.20","to_node":"243.0.0.2"},{"from_node":"243.0.0.2","to_node":"127.0.0.10"},{"from_node":"127.0.0.20","to_node":"243.0.0.3"},{"from_node":"243.0.0.3","to_node":"127.0.0.50"},{"from_node":"127.0.0.40","to_node":"127.0.0.41"},{"from_node":"127.0.0.40","to_node":"243.0.0.4"},{"from_node":"243.0.0.4","to_node":"127.0.0.30"},{"from_node":"127.0.0.50","to_node":"243.0.0.5"},{"from_node":"243.0.0.5","to_node":"127.0.0.30"},{"from_node":"127.0.0.31","to_node":"127.0.0.30"},{"from_node":"127.0.0.50","to_node":"127.0.0.51"},{"from_node":"127.0.0.20","to_node":"243.0.0.6"},{"from_node":"243.0.0.6","to_node":"127.0.0.30"},{"from_node":"127.0.0.30","to_node":"243.0.0.7"},{"from_node":"243.0.0.7","to_node":"127.0.0.40"},{"from_node":"127.0.0.11","to_node":"127.0.0.10"},{"from_node":"127.0.0.30","to_node":"243.0.0.8"},{"from_node":"243.0.0.8","to_node":"127.0.0.10"},{"from_node":"127.0.0.40","to_node":"243.0.0.9"},{"from_node":"243.0.0.9","to_node":"127.0.0.50"},{"from_node":"127.0.0.30","to_node":"243.0.0.10"},{"from_node":"243.0.0.10","to_node":"127.0.0.50"},{"from_node":"127.0.0.50","to_node":"243.0.0.11"},{"from_node":"243.0.0.11","to_node":"127.0.0.20"},{"from_node":"127.0.0.50","to_node":"243.0.0.12"},{"from_node":"243.0.0.12","to_node":"127.0.0.40"},{"from_node":"127.0.0.21","to_node":"127.0.0.20"},{"from_node":"127.0.0.41","to_node":"127.0.0.40"},{"from_node":"127.0.0.30","to_node":"243.0.0.13"},{"from_node":"243.0.0.13","to_node":"127.0.0.20"},{"from_node":"127.0.0.10","to_node":"127.0.0.11"},{"from_node":"127.0.0.10","to_node":"243.0.0.14"},{"from_node":"243.0.0.14","to_node":"127.0.0.20"}]}}} \ No newline at end of file +{"request":{"topology":{"connections":[{"from_node":"127.0.0.51","to_node":"127.0.0.50"},{"from_node":"127.0.0.30","to_node":"127.0.0.31"},{"from_node":"127.0.0.10","to_node":"243.0.0.1"},{"from_node":"243.0.0.1","to_node":"127.0.0.30"},{"from_node":"127.0.0.20","to_node":"127.0.0.21"},{"from_node":"127.0.0.20","to_node":"243.0.0.2"},{"from_node":"243.0.0.2","to_node":"127.0.0.10"},{"from_node":"127.0.0.20","to_node":"243.0.0.3"},{"from_node":"243.0.0.3","to_node":"127.0.0.50"},{"from_node":"127.0.0.40","to_node":"127.0.0.41"},{"from_node":"127.0.0.40","to_node":"243.0.0.4"},{"from_node":"243.0.0.4","to_node":"127.0.0.30"},{"from_node":"127.0.0.50","to_node":"243.0.0.5"},{"from_node":"243.0.0.5","to_node":"127.0.0.30"},{"from_node":"127.0.0.31","to_node":"127.0.0.30"},{"from_node":"127.0.0.50","to_node":"127.0.0.51"},{"from_node":"127.0.0.20","to_node":"243.0.0.6"},{"from_node":"243.0.0.6","to_node":"127.0.0.30"},{"from_node":"127.0.0.30","to_node":"243.0.0.7"},{"from_node":"243.0.0.7","to_node":"127.0.0.40"},{"from_node":"127.0.0.11","to_node":"127.0.0.10"},{"from_node":"127.0.0.30","to_node":"243.0.0.8"},{"from_node":"243.0.0.8","to_node":"127.0.0.10"},{"from_node":"127.0.0.40","to_node":"243.0.0.9"},{"from_node":"243.0.0.9","to_node":"127.0.0.50"},{"from_node":"127.0.0.30","to_node":"243.0.0.10"},{"from_node":"243.0.0.10","to_node":"127.0.0.50"},{"from_node":"127.0.0.50","to_node":"243.0.0.11"},{"from_node":"243.0.0.11","to_node":"127.0.0.20"},{"from_node":"127.0.0.50","to_node":"243.0.0.12"},{"from_node":"243.0.0.12","to_node":"127.0.0.40"},{"from_node":"127.0.0.21","to_node":"127.0.0.20"},{"from_node":"127.0.0.41","to_node":"127.0.0.40"},{"from_node":"127.0.0.30","to_node":"243.0.0.13"},{"from_node":"243.0.0.13","to_node":"127.0.0.20"},{"from_node":"127.0.0.10","to_node":"127.0.0.11"},{"from_node":"127.0.0.10","to_node":"243.0.0.14"},{"from_node":"243.0.0.14","to_node":"127.0.0.20"}],"elements":[{"uid":"127.0.0.11","metadata":{"location":{"latitude":0,"longitude":0,"region":"XPONDER-1"}},"type":"gnpy-network-topology:Transceiver"},{"uid":"127.0.0.10","metadata":{"location":{"latitude":0,"longitude":0,"region":"OpenROADM-1"}},"type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20}},{"uid":"127.0.0.51","metadata":{"location":{"latitude":0,"longitude":0,"region":"XPONDER-5"}},"type":"gnpy-network-topology:Transceiver"},{"uid":"127.0.0.50","metadata":{"location":{"latitude":0,"longitude":0,"region":"OpenROADM-5"}},"type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20}},{"uid":"127.0.0.31","metadata":{"location":{"latitude":0,"longitude":0,"region":"XPONDER-3"}},"type":"gnpy-network-topology:Transceiver"},{"uid":"127.0.0.30","metadata":{"location":{"latitude":0,"longitude":0,"region":"OpenROADM-3"}},"type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20}},{"uid":"127.0.0.21","metadata":{"location":{"latitude":0,"longitude":0,"region":"XPONDER-2"}},"type":"gnpy-network-topology:Transceiver"},{"uid":"127.0.0.40","metadata":{"location":{"latitude":0,"longitude":0,"region":"OpenROADM-4"}},"type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20}},{"uid":"127.0.0.20","metadata":{"location":{"latitude":0,"longitude":0,"region":"OpenROADM-2"}},"type":"gnpy-network-topology:Roadm","params":{"target_pch_out_db":-20}},{"uid":"127.0.0.41","metadata":{"location":{"latitude":0,"longitude":0,"region":"XPONDER-4"}},"type":"gnpy-network-topology:Transceiver"},{"uid":"243.0.0.12","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":100,"con_out":0,"loss_coef":0.29}},{"uid":"243.0.0.11","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":60,"con_out":0,"loss_coef":0.12}},{"uid":"243.0.0.10","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":60,"con_out":0,"loss_coef":0.12}},{"uid":"243.0.0.14","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":100,"con_out":0,"loss_coef":0.29}},{"uid":"243.0.0.13","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":140,"con_out":0,"loss_coef":0.2127659574468085124099303584443987347185611724853515625}},{"uid":"243.0.0.8","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":100,"con_out":0,"loss_coef":0.11999999999999999555910790149937383830547332763671875}},{"uid":"243.0.0.9","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":100,"con_out":0,"loss_coef":0.29}},{"uid":"243.0.0.4","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":100,"con_out":0,"loss_coef":0.29}},{"uid":"243.0.0.5","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":60,"con_out":0,"loss_coef":0.12}},{"uid":"243.0.0.6","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":140,"con_out":0,"loss_coef":0.2127659574468085124099303584443987347185611724853515625}},{"uid":"243.0.0.7","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":100,"con_out":0,"loss_coef":0.29}},{"uid":"243.0.0.1","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":100,"con_out":0,"loss_coef":0.11999999999999999555910790149937383830547332763671875}},{"uid":"243.0.0.2","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":100,"con_out":0,"loss_coef":0.29}},{"uid":"243.0.0.3","metadata":{"location":{"latitude":0,"city":"N/A","longitude":0,"region":"N/A"}},"type":"gnpy-network-topology:Fiber","type_variety":"SSMF","params":{"length_units":"gnpy-network-topology:km","att_in":0,"con_in":0,"length":60,"con_out":0,"loss_coef":0.12}}]},"service":{"path-request":[{"request-id":"2","bidirectional":false,"dst-tp-id":"ZHN0VHBJZA\u003d\u003d","src-tp-id":"c3JjVHBJZA\u003d\u003d","path-constraints":{"te-bandwidth":{"spacing":50000000000,"trx_mode":"W100G","trx_type":"openroadm-beta1","effective-freq-slot":[{"N":0,"M":4}],"path_bandwidth":100,"technology":"flexi-grid"}},"source":"127.0.0.11","explicit-route-objects":{"route-object-include-exclude":[{"index":0,"num-unnum-hop":{"hop-type":"STRICT","link-tp-id":"1","node-id":"127.0.0.20"},"explicit-route-usage":"gnpy-path-computation-simplified:route-include-ero"},{"index":1,"num-unnum-hop":{"hop-type":"STRICT","link-tp-id":"1","node-id":"127.0.0.30"},"explicit-route-usage":"gnpy-path-computation-simplified:route-include-ero"}]},"destination":"127.0.0.41"}]}}} \ No newline at end of file diff --git a/common/src/test/resources/gnpy_request.json b/common/src/test/resources/gnpy_request.json index 0219eef29..272f6990a 100644 --- a/common/src/test/resources/gnpy_request.json +++ b/common/src/test/resources/gnpy_request.json @@ -1,6 +1,6 @@ { - "gnpy-api": { - "topology-file": { + "request": { + "topology": { "elements": [ { "uid": "127.0.0.40", @@ -577,7 +577,7 @@ } ] }, - "service-file": { + "service": { "path-request": [ { "request-id": 2, 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 index 36faf86e0..59cd3a02e 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyResult.java @@ -11,19 +11,15 @@ package org.opendaylight.transportpce.pce.gnpy; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import java.util.stream.Collectors; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.explicit.route.hop.type.NumUnnumHop; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.properties.path.properties.PathMetric; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.properties.path.properties.PathRouteObjects; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.Response; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.response.response.type.NoPathCase; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.response.response.type.PathCase; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.type.NumUnnumHop; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.properties.path.properties.PathMetric; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.properties.path.properties.PathRouteObjects; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.Response; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.response.response.type.NoPathCase; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.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; @@ -35,8 +31,6 @@ import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.routing 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.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.yangtools.yang.common.Uint16; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,10 +46,10 @@ public class GnpyResult { private static final Logger LOG = LoggerFactory.getLogger(GnpyResult.class); private Response response = null; - private Map mapNodeRefIp = new HashMap<>(); + private List ordNodeList = new ArrayList<>(); public GnpyResult(Result result, GnpyTopoImpl gnpyTopo) throws GnpyException { - this.mapNodeRefIp = gnpyTopo.getMapNodeRefIp(); + this.ordNodeList = gnpyTopo.getElementsList(); List responses = new ArrayList<>(result.nonnullResponse().values()); if (responses.isEmpty()) { throw new GnpyException("In GnpyResult: the response from GNpy is null!"); @@ -124,26 +118,18 @@ public class GnpyResult { int counter = 0; for (PathRouteObjects pathRouteObjects : pathRouteObjectList) { if (pathRouteObjects.getPathRouteObject().getType() instanceof NumUnnumHop) { - NumUnnumHop numUnnumHop = (org.opendaylight.yang.gen.v1.gnpy.path.rev200909.explicit.route.hop.type - .NumUnnumHop) pathRouteObjects.getPathRouteObject().getType(); - String nodeIp = numUnnumHop.getNumUnnumHop().getNodeId(); - try { - IpAddress nodeIpAddress = new IpAddress(new Ipv4Address(nodeIp)); - // find the corresponding node-id (in ord-ntw) corresponding to nodeId (in gnpy response) - String nodeId = findOrdNetworkNodeId(nodeIpAddress); - if (nodeId != null) { - 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(Uint16.valueOf(counter)).setHopType(hopType) - .build(); - orderedHopsList.add(orderedHops); - counter++; - } - } catch (IllegalArgumentException e) { - LOG.error(" in GnpyResult: the element {} is not a ipv4Address ", nodeIp, e); + NumUnnumHop numUnnumHop = (NumUnnumHop) pathRouteObjects.getPathRouteObject().getType(); + String nodeId = numUnnumHop.getNumUnnumHop().getNodeId(); + if (nodeId != null && this.ordNodeList.contains(nodeId)) { + 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(Uint16.valueOf(counter)).setHopType(hopType) + .build(); + orderedHopsList.add(orderedHops); + counter++; } } } @@ -156,17 +142,6 @@ public class GnpyResult { return hardConstraints; } - private String findOrdNetworkNodeId(IpAddress nodeIpAddress) { - Iterator> it = this.mapNodeRefIp.entrySet().iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - if (entry.getValue().equals(nodeIpAddress)) { - return entry.getKey(); - } - } - return null; - } - public Response getResponse() { return response; } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyServiceImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyServiceImpl.java index 3a23036b7..102b324ea 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyServiceImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyServiceImpl.java @@ -8,12 +8,12 @@ package org.opendaylight.transportpce.pce.gnpy; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -21,39 +21,39 @@ import java.util.Map; import java.util.Optional; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.transportpce.common.ServiceRateConstant; import org.opendaylight.transportpce.common.fixedflex.GridConstant; import org.opendaylight.transportpce.common.fixedflex.GridUtils; import org.opendaylight.transportpce.pce.constraints.PceConstraints; import org.opendaylight.transportpce.pce.constraints.PceConstraints.ResourcePair; import org.opendaylight.transportpce.pce.gnpy.utils.AToZComparator; import org.opendaylight.transportpce.pce.gnpy.utils.ZToAComparator; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.Elements; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.ElementsKey; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.RouteIncludeEro; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.TeHopType; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.TeNodeId; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.TePathDisjointness; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.TeTpId; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.common.constraints_config.TeBandwidth; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.common.constraints_config.TeBandwidthBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.explicit.route.hop.Type; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.explicit.route.hop.type.NumUnnumHopBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.explicit.route.hop.type.num.unnum.hop.NumUnnumHop; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.constraints.PathConstraints; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.constraints.PathConstraintsBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.gnpy.specific.parameters.EffectiveFreqSlot; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.gnpy.specific.parameters.EffectiveFreqSlotBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.path.route.objects.ExplicitRouteObjects; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.path.route.objects.ExplicitRouteObjectsBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.path.route.objects.explicit.route.objects.RouteObjectIncludeExclude; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.path.route.objects.explicit.route.objects.RouteObjectIncludeExcludeBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.service.PathRequest; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.service.PathRequestBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.service.PathRequestKey; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.synchronization.info.Synchronization; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.synchronization.info.SynchronizationBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.synchronization.info.synchronization.Svec; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.synchronization.info.synchronization.SvecBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.Elements; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.ElementsKey; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.RouteIncludeEro; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.TeHopType; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.TePathDisjointness; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.common.constraints_config.TeBandwidth; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.common.constraints_config.TeBandwidthBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.Type; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.type.NumUnnumHopBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.type.num.unnum.hop.NumUnnumHop; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.constraints.PathConstraints; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.constraints.PathConstraintsBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.gnpy.specific.parameters.EffectiveFreqSlot; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.gnpy.specific.parameters.EffectiveFreqSlotBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.ExplicitRouteObjects; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.ExplicitRouteObjectsBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.explicit.route.objects.RouteObjectIncludeExclude; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.explicit.route.objects.RouteObjectIncludeExcludeBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.path.route.objects.explicit.route.objects.RouteObjectIncludeExcludeKey; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.service.PathRequest; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.service.PathRequestBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.service.PathRequestKey; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.Synchronization; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.SynchronizationBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.synchronization.Svec; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.synchronization.SvecBuilder; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.PathComputationRequestInput; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.FrequencyTHz; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev181019.ModulationFormat; @@ -62,11 +62,11 @@ import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdes import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.atoz.direction.AToZ; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ztoa.direction.ZToA; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.Resource; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; import org.opendaylight.yangtools.yang.common.Uint32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + /** * Class to create the service corresponding to GNPy requirements. * @@ -76,21 +76,32 @@ import org.slf4j.LoggerFactory; public class GnpyServiceImpl { private static final Logger LOG = LoggerFactory.getLogger(GnpyServiceImpl.class); - private static final Comparator ROUTE_OBJECT_COMPARATOR = - Comparator.comparing(RouteObjectIncludeExclude::getIndex); private Map pathRequest = new HashMap<>(); private List synchronization = new ArrayList<>(); private Map mapDisgNodeRefNode = new HashMap<>(); - private Map mapNodeRefIp = new HashMap<>(); private Map> mapLinkFiber = new HashMap<>(); - private Map mapFiberIp = new HashMap<>(); private List trxList = new ArrayList<>(); private Map elements = new HashMap<>(); - private List routeObjectIncludeExcludes = new ArrayList<>(); - private IpAddress currentNodeIpAddress = null; + private Map routeObjectIncludeExcludes = new HashMap<>(); + private String currentNodeId = null; private AToZComparator atoZComparator = new AToZComparator(); private ZToAComparator ztoAComparator = new ZToAComparator(); + private static final Table TRX_MODE_TABLE = initTrxModeTable(); + + private static Table initTrxModeTable() { + Table trxModeTable = HashBasedTable.create(); + trxModeTable.put(ServiceRateConstant.RATE_100, GridConstant.SLOT_WIDTH_50, "100 Gbit/s, 27.95 Gbaud, DP-QPSK"); + trxModeTable.put(ServiceRateConstant.RATE_200, GridConstant.SLOT_WIDTH_50, "200 Gbit/s, 31.57 Gbaud, DP-16QAM"); + trxModeTable.put(ServiceRateConstant.RATE_200, GridConstant.SLOT_WIDTH_87_5, "200 Gbit/s, DP-QPSK"); + trxModeTable.put(ServiceRateConstant.RATE_300, GridConstant.SLOT_WIDTH_87_5, "300 Gbit/s, DP-8QAM"); + trxModeTable.put(ServiceRateConstant.RATE_400, GridConstant.SLOT_WIDTH_87_5, "400 Gbit/s, DP-16QAM"); + return trxModeTable; + } + + public static final Map RATE_OUTPUTPOWER = Map.of( + ServiceRateConstant.RATE_100, GridConstant.OUTPUT_POWER_100GB_W, + ServiceRateConstant.RATE_400, GridConstant.OUTPUT_POWER_400GB_W); /* * Construct the GnpyServiceImpl @@ -99,9 +110,7 @@ public class GnpyServiceImpl { GnpyTopoImpl gnpyTopo, PceConstraints pceHardConstraints) throws GnpyException { this.elements = gnpyTopo.getElements(); this.mapDisgNodeRefNode = gnpyTopo.getMapDisgNodeRefNode(); - this.mapNodeRefIp = gnpyTopo.getMapNodeRefIp(); this.mapLinkFiber = gnpyTopo.getMapLinkFiber(); - this.mapFiberIp = gnpyTopo.getMapFiberIp(); this.trxList = gnpyTopo.getTrxList(); try { this.pathRequest = extractPathRequest(input, atoz, requestId.toJava(), pceHardConstraints); @@ -115,9 +124,7 @@ public class GnpyServiceImpl { GnpyTopoImpl gnpyTopo, PceConstraints pceHardConstraints) throws GnpyException { this.elements = gnpyTopo.getElements(); this.mapDisgNodeRefNode = gnpyTopo.getMapDisgNodeRefNode(); - this.mapNodeRefIp = gnpyTopo.getMapNodeRefIp(); this.mapLinkFiber = gnpyTopo.getMapLinkFiber(); - this.mapFiberIp = gnpyTopo.getMapFiberIp(); this.trxList = gnpyTopo.getTrxList(); try { pathRequest = extractPathRequest(input, ztoa, requestId.toJava(), pceHardConstraints); @@ -140,14 +147,13 @@ public class GnpyServiceImpl { // Create explicitRouteObjects List listAtoZ = new ArrayList<>(atoz.nonnullAToZ().values()); - if (!listAtoZ.isEmpty()) { + if (listAtoZ.isEmpty()) { + extractHardConstraints(pceHardConstraints); + } else { Collections.sort(listAtoZ, atoZComparator); extractRouteObjectIcludeAtoZ(listAtoZ); - } else { - extractHardConstraints(pceHardConstraints); } - Collections.sort(routeObjectIncludeExcludes, ROUTE_OBJECT_COMPARATOR); ExplicitRouteObjects explicitRouteObjects = new ExplicitRouteObjectsBuilder() .setRouteObjectIncludeExclude(routeObjectIncludeExcludes).build(); //Create Path Constraint @@ -158,10 +164,11 @@ public class GnpyServiceImpl { // Create the path request Map pathRequestMap = new HashMap<>(); - PathRequest pathRequestEl = new PathRequestBuilder().setRequestId(Uint32.valueOf(requestId)) - .setSource(this.mapNodeRefIp.get(sourceNode)).setDestination(this.mapNodeRefIp.get(destNode)) - .setSrcTpId("srcTpId".getBytes(StandardCharsets.UTF_8)) - .setDstTpId("dstTpId".getBytes(StandardCharsets.UTF_8)) + PathRequest pathRequestEl = new PathRequestBuilder().setRequestId(requestId.toString()) + .setSource(sourceNode) + .setDestination(destNode) + .setSrcTpId(sourceNode) + .setDstTpId(destNode) .setBidirectional(false).setPathConstraints(pathConstraints).setPathConstraints(pathConstraints) .setExplicitRouteObjects(explicitRouteObjects).build(); pathRequestMap.put(pathRequestEl.key(),pathRequestEl); @@ -180,13 +187,13 @@ public class GnpyServiceImpl { } // Create explicitRouteObjects @NonNull List listZtoA = new ArrayList<>(ztoa.nonnullZToA().values()); - if (!listZtoA.isEmpty()) { + if (listZtoA.isEmpty()) { + extractHardConstraints(pceHardConstraints); + } else { Collections.sort(listZtoA, ztoAComparator); extractRouteObjectIcludeZtoA(listZtoA); - } else { - extractHardConstraints(pceHardConstraints); } - Collections.sort(routeObjectIncludeExcludes, ROUTE_OBJECT_COMPARATOR); + ExplicitRouteObjects explicitRouteObjects = new ExplicitRouteObjectsBuilder() .setRouteObjectIncludeExclude(routeObjectIncludeExcludes).build(); //Create Path Constraint @@ -195,12 +202,13 @@ public class GnpyServiceImpl { ztoa.getZToAMinFrequency(), ztoa.getZToAMaxFrequency()); - // Create the path request + //Create the path request Map pathRequestMap = new HashMap<>(); - PathRequest pathRequestEl = new PathRequestBuilder().setRequestId(Uint32.valueOf(requestId)) - .setSource(this.mapNodeRefIp.get(sourceNode)).setDestination(this.mapNodeRefIp.get(destNode)) - .setSrcTpId("srcTpId".getBytes(StandardCharsets.UTF_8)) - .setDstTpId("dstTpId".getBytes(StandardCharsets.UTF_8)) + PathRequest pathRequestEl = new PathRequestBuilder().setRequestId(requestId.toString()) + .setSource(sourceNode) + .setDestination(destNode) + .setSrcTpId(sourceNode) + .setDstTpId(destNode) .setBidirectional(false).setPathConstraints(pathConstraints) .setExplicitRouteObjects(explicitRouteObjects).build(); pathRequestMap.put(pathRequestEl.key(),pathRequestEl); @@ -266,7 +274,7 @@ public class GnpyServiceImpl { } } - // Create the list of nodes to include + //Create the list of nodes to include private List getListToInclude(PceConstraints pceHardConstraints) { List listNodeToInclude = new ArrayList<>(); if (pceHardConstraints != null) { @@ -285,18 +293,14 @@ public class GnpyServiceImpl { //Add a node to the route object private Long addNodeToRouteObject(String nodeRef, Long index) throws GnpyException { Long idx = index; - IpAddress ipAddress = this.mapNodeRefIp.get(nodeRef); - if (ipAddress == null) { - throw new GnpyException(String.format("In gnpyServiceImpl : NodeRef %s does not exist", nodeRef)); - } - for (Elements element : this.elements.values()) { - if (element.getUid().equals(ipAddress.getIpv4Address().getValue())) { - if ((this.currentNodeIpAddress == null) || (!this.currentNodeIpAddress.equals(ipAddress))) { - this.currentNodeIpAddress = ipAddress; - RouteObjectIncludeExclude routeObjectIncludeExclude = addRouteObjectIncludeExclude(ipAddress, + if (element.getUid().equals(nodeRef)) { + if ((this.currentNodeId == null) || (!this.currentNodeId.equals(nodeRef))) { + this.currentNodeId = nodeRef; + RouteObjectIncludeExclude routeObjectIncludeExclude = addRouteObjectIncludeExclude(nodeRef, Uint32.valueOf(1), idx); - routeObjectIncludeExcludes.add(routeObjectIncludeExclude); + RouteObjectIncludeExcludeKey key = new RouteObjectIncludeExcludeKey(Uint32.valueOf(idx)); + routeObjectIncludeExcludes.put(key, routeObjectIncludeExclude); idx += 1; } return idx; @@ -320,27 +324,21 @@ public class GnpyServiceImpl { throw new GnpyException(String.format("In gnpyServiceImpl addNodeRouteObject : no sublink in %s",linkId)); } for (String subLink : listSubLink) { - IpAddress fiberIp = this.mapFiberIp.get(subLink); - if (fiberIp == null) { - throw new GnpyException(String.format("In gnpyServiceImpl addNodeRouteObject : fiberIp of %s is null", - subLink)); - } RouteObjectIncludeExclude routeObjectIncludeExclude = - addRouteObjectIncludeExclude(fiberIp, Uint32.valueOf(1),idx); - routeObjectIncludeExcludes.add(routeObjectIncludeExclude); + addRouteObjectIncludeExclude(subLink, Uint32.valueOf(1),idx); + RouteObjectIncludeExcludeKey key = new RouteObjectIncludeExcludeKey(Uint32.valueOf(idx)); + routeObjectIncludeExcludes.put(key, routeObjectIncludeExclude); idx += 1; } return idx; } // Add routeObjectIncludeExclude - private RouteObjectIncludeExclude addRouteObjectIncludeExclude(IpAddress ipAddress, Uint32 teTpValue, Long index) { - TeNodeId teNodeId = new TeNodeId(ipAddress); - TeTpId teTpId = new TeTpId(teTpValue); - NumUnnumHop numUnnumHop = new org.opendaylight.yang.gen.v1.gnpy.path.rev200909.explicit.route.hop.type.num + private RouteObjectIncludeExclude addRouteObjectIncludeExclude(String nodeId, Uint32 teTpValue, Long index) { + NumUnnumHop numUnnumHop = new org.opendaylight.yang.gen.v1.gnpy.path.rev220221.explicit.route.hop.type.num .unnum.hop.NumUnnumHopBuilder() - .setNodeId(teNodeId.getIpv4Address().getValue()) - .setLinkTpId(teTpId.getUint32().toString()) + .setNodeId(nodeId) + .setLinkTpId(teTpValue.toString()) .setHopType(TeHopType.STRICT).build(); Type type1 = new NumUnnumHopBuilder().setNumUnnumHop(numUnnumHop).build(); // Create routeObjectIncludeExclude element @@ -357,26 +355,29 @@ public class GnpyServiceImpl { if (minFrequency != null && maxFrequency != null && modulationFormat != null) { LOG.info("Creating path constraints for rate {}, modulationFormat {}, min freq {}, max freq {}", rate, modulationFormat, minFrequency, maxFrequency); - FrequencyTHz centralFrequency = GridUtils - .getCentralFrequency(minFrequency.getValue(), maxFrequency.getValue()); - int centralFrequencyBitSetIndex = GridUtils.getIndexFromFrequency(centralFrequency.getValue()); - mvalue = GridConstant.RATE_SPECTRAL_WIDTH_SLOT_NUMBER_MAP.getOrDefault(Uint32.valueOf(rate), - GridConstant.NB_SLOTS_100G); - nvalue = GridUtils.getNFromFrequencyIndex(centralFrequencyBitSetIndex); ModulationFormat mformat = ModulationFormat.DpQpsk; Optional optionalModulationFormat = ModulationFormat.forName(modulationFormat); if (optionalModulationFormat.isPresent()) { mformat = optionalModulationFormat.get(); } spacing = GridConstant.FREQUENCY_SLOT_WIDTH_TABLE.get(Uint32.valueOf(rate), mformat); - + FrequencyTHz centralFrequency = GridUtils + .getCentralFrequency(minFrequency.getValue(), maxFrequency.getValue()); + int centralFrequencyBitSetIndex = GridUtils.getIndexFromFrequency(centralFrequency.getValue()); + mvalue = (int) Math.ceil(spacing.doubleValue() / (GridConstant.GRANULARITY)); + nvalue = GridUtils.getNFromFrequencyIndex(centralFrequencyBitSetIndex); } LOG.info("Creating path constraints for rate {}, mvalue {}, nvalue {}, spacing {}", rate, mvalue, nvalue, spacing); - EffectiveFreqSlot effectiveFreqSlot = new EffectiveFreqSlotBuilder().setM(mvalue / 2).setN(nvalue).build(); - // TODO : TrxMode is today hardcoded to W100G. - TeBandwidth teBandwidth = new TeBandwidthBuilder().setPathBandwidth(BigDecimal.valueOf(rate)) - .setTechnology("flexi-grid").setTrxType("openroadm-beta1").setTrxMode("W100G") + EffectiveFreqSlot effectiveFreqSlot = new EffectiveFreqSlotBuilder() + .setM(Uint32.valueOf(mvalue / 2)).setN(nvalue).build(); + + TeBandwidth teBandwidth = new TeBandwidthBuilder() + .setPathBandwidth(BigDecimal.valueOf(rate * 1e9)) + .setTechnology("flexi-grid").setTrxType("OpenROADM MSA ver. 5.0") + .setTrxMode(TRX_MODE_TABLE.get(Uint32.valueOf(rate), spacing)) + .setOutputPower(GridUtils.convertDbmW(GridConstant.OUTPUT_POWER_100GB_DBM + + 10 * Math.log10(mvalue / (double)GridConstant.NB_SLOTS_100G))) .setEffectiveFreqSlot(Map.of(effectiveFreqSlot.key(), effectiveFreqSlot)) .setSpacing(spacing.multiply(BigDecimal.valueOf(1e9))).build(); return new PathConstraintsBuilder().setTeBandwidth(teBandwidth).build(); @@ -385,14 +386,15 @@ public class GnpyServiceImpl { //Create the synchronization private List extractSynchronization(Uint32 requestId) { // Create RequestIdNumber - List requestIdNumber = new ArrayList<>(); - requestIdNumber.add(requestId); + List requestIdNumber = new ArrayList<>(); + requestIdNumber.add(requestId.toString()); // Create a synchronization Svec svec = new SvecBuilder().setRelaxable(true) .setDisjointness(new TePathDisjointness(true, true, false)) .setRequestIdNumber(requestIdNumber).build(); List synchro = new ArrayList<>(); - Synchronization synchronization1 = new SynchronizationBuilder().setSynchronizationId(Uint32.valueOf(0)) + Synchronization synchronization1 = new SynchronizationBuilder() + .setSynchronizationId(Uint32.valueOf(0).toString()) .setSvec(svec).build(); synchro.add(synchronization1); return (synchro); diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyTopoImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyTopoImpl.java index a50bfd4d0..7fef96e0c 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyTopoImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyTopoImpl.java @@ -15,35 +15,34 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; -import java.util.regex.Pattern; import java.util.stream.IntStream; import org.opendaylight.mdsal.common.api.LogicalDatastoreType; import org.opendaylight.transportpce.common.NetworkUtils; import org.opendaylight.transportpce.common.network.NetworkTransactionService; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.Coordinate; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.Km; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.edfa.params.Operational; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.edfa.params.OperationalBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.Edfa; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.EdfaBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.FiberRoadmBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.Transceiver; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.TransceiverBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.fiberroadm.Params; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.fiberroadm.ParamsBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.fiberroadm.params.fiberroadm.Fiber; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.fiberroadm.params.fiberroadm.FiberBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.fiberroadm.params.fiberroadm.Roadm; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.element.type.choice.element.type.fiberroadm.params.fiberroadm.RoadmBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.location.attributes.Location; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.location.attributes.LocationBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.Connections; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.ConnectionsBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.Elements; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.ElementsBuilder; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.ElementsKey; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.elements.Metadata; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.elements.MetadataBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.Coordinate; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.Km; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.edfa.params.Operational; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.edfa.params.OperationalBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.Edfa; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.EdfaBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.FiberRoadmBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.Transceiver; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.TransceiverBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.fiberroadm.Params; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.fiberroadm.ParamsBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.fiberroadm.params.fiberroadmfused.Fiber; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.fiberroadm.params.fiberroadmfused.FiberBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.fiberroadm.params.fiberroadmfused.Roadm; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.element.type.choice.element.type.fiberroadm.params.fiberroadmfused.RoadmBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.location.attributes.Location; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.location.attributes.LocationBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.Connections; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.ConnectionsBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.Elements; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.ElementsBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.ElementsKey; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.elements.Metadata; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.elements.MetadataBuilder; import org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev200529.Link1; import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev200529.SpanAttributes; import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev200529.amplified.link.attributes.AmplifiedLink; @@ -53,8 +52,6 @@ import org.opendaylight.yang.gen.v1.http.org.openroadm.link.rev200529.span.attri import org.opendaylight.yang.gen.v1.http.org.openroadm.network.rev200529.Node1; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev200529.networks.network.link.OMSAttributes; import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev200529.OpenroadmLinkType; -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; @@ -80,22 +77,14 @@ public class GnpyTopoImpl { //List of elements private Map elements = new HashMap<>(); private List connections = new ArrayList<>(); + private List elementsList = new ArrayList<>(); //Mapping elements //Mapping between the ord-topo and ord-ntw node private Map mapDisgNodeRefNode = new HashMap<>(); - //Mapping between the ord-ntw and node ip - private Map mapNodeRefIp = new HashMap<>(); //Mapping between the ROADM-ROADM linkId/secElement and the linkId private Map> mapLinkFiber = new HashMap<>(); - //Mapping between the ROADM-ROADM linkId/secElement and ipAddress - private Map mapFiberIp = new HashMap<>(); //List of Xponders private List trxList = new ArrayList<>(); - //Initialize the 32 bit identifiers for the edfa and the fiber. - //These 32-bit identifiers are not ipv4 addresses (despite having ipv4Adresses format, dotted-decimal notation). - //They are imposed by the GNPy yang model to identify network elements and not used for any routing purposes. - private Ipv4Address edfaId; - private Ipv4Address fiberId; private static final double LATITUDE = 0; private static final double LONGITUTE = 0; private static final String REGION = "N/A"; @@ -108,10 +97,6 @@ public class GnpyTopoImpl { */ public GnpyTopoImpl(final NetworkTransactionService networkTransactionService) throws GnpyException { this.networkTransactionService = networkTransactionService; - //32-bit identifier for the fiber. The dotted decimal notation has the format 243.x.x.x (0<=x<=255) - fiberId = new Ipv4Address("243.0.0.1"); - //32-bit identifier for the edfa. The dotted decimal notation has the format 244.x.x.x (0<=x<=255) - edfaId = new Ipv4Address("244.0.0.1"); try { extractTopo(); } catch (NullPointerException e) { @@ -120,8 +105,7 @@ public class GnpyTopoImpl { } /* - * extract the topology: all the elements have ipAddress as uid and maintain - * a mapping structure to map between the nodeId and the ipAddress (uid) + * extract the topology * */ private void extractTopo() throws GnpyException { @@ -164,7 +148,6 @@ public class GnpyTopoImpl { // Create the list of nodes Collection openRoadmNetNodeList = openRoadmNet.get().nonnullNode().values(); Collection openRoadmTopoNodeList = openRoadmTopo.get().nonnullNode().values(); - List nodesList = new ArrayList<>(); if (openRoadmTopoNodeList.isEmpty() || openRoadmNetNodeList.isEmpty()) { throw new GnpyException("In gnpyTopoImpl: no nodes in the openradm topology or openroadm network"); @@ -178,7 +161,6 @@ public class GnpyTopoImpl { if (!supportingNode.getNetworkRef().getValue().equals("openroadm-network")) { continue; } - IpAddress ipAddress = null; String nodeRef = supportingNode.getNodeRef().getValue(); if (nodeRef == null) { throw new GnpyException("In gnpyTopoImpl: nodeRef is null"); @@ -193,12 +175,6 @@ public class GnpyTopoImpl { openRoadmNetNode1 = openRoadmNetNode.augmentation(Node1.class); commonNetworkNode1 = openRoadmNetNode.augmentation(org.opendaylight.yang.gen.v1 .http.org.openroadm.common.network.rev200529.Node1.class); - ipAddress = openRoadmNetNode1.getIp(); - if (ipAddress == null) { - throw new GnpyException(String.format( - "In gnpyTopoImpl: ipAddress of node %s is null",nodeRef)); - } - mapNodeRefIp.put(nodeRef, ipAddress); break; } } @@ -206,18 +182,18 @@ public class GnpyTopoImpl { throw new GnpyException(String.format("In gnpyTopoImpl: the node type of %s is null",nodeRef)); } if (commonNetworkNode1.getNodeType().getName().equals("ROADM")) { - if (!nodesList.contains(nodeRef)) { + if (!elementsList.contains(nodeRef)) { Elements element = createElementsRoadm(LATITUDE, LONGITUTE, nodeRef, - openRoadmNetNode1.getShelf(),TARGET_PCH_OUT_DB, ipAddress.getIpv4Address().getValue()); + openRoadmNetNode1.getShelf(),TARGET_PCH_OUT_DB, nodeRef); this.elements.put(element.key(),element); - nodesList.add(nodeRef); + elementsList.add(nodeRef); } } else if (commonNetworkNode1.getNodeType().getName().equals("XPONDER")) { - if (!nodesList.contains(nodeRef)) { + if (!elementsList.contains(nodeRef)) { Elements element = createElementsTransceiver(LATITUDE, LONGITUTE, nodeRef, - openRoadmNetNode1.getShelf(),ipAddress.getIpv4Address().getValue()); + openRoadmNetNode1.getShelf(), nodeRef); this.elements.put(element.key(),element); - nodesList.add(nodeRef); + elementsList.add(nodeRef); trxList.add(nodeRef); } } else { @@ -257,10 +233,8 @@ public class GnpyTopoImpl { } String srcId = mapDisgNodeRefNode.get(link.getSource().getSourceNode().getValue()); - IpAddress srcIp = mapNodeRefIp.get(srcId); String linkId = link.getLinkId().getValue(); String destId = null; - IpAddress destIp = null; if (linkType == OpenroadmLinkType.ROADMTOROADM.getIntValue()) { OMSAttributes omsAttributes = openroadmNetworkLink1.getOMSAttributes(); if (omsAttributes == null) { @@ -269,82 +243,76 @@ public class GnpyTopoImpl { } //Case of amplified link if (omsAttributes.getAmplifiedLink() != null) { - srcIp = extractAmplifiedLink(omsAttributes, linkId, srcIp); + srcId = extractAmplifiedLink(omsAttributes, linkId, srcId); } //Case of one span link if (omsAttributes.getSpan() != null) { - srcIp = extractSpanLink(omsAttributes, linkId, srcIp); + srcId = extractSpanLink(omsAttributes, linkId, srcId); } } // Create a new link destId = mapDisgNodeRefNode.get(link.getDestination().getDestNode().getValue()); - destIp = mapNodeRefIp.get(destId); - createNewConnection(srcIp,destIp); + createNewConnection(srcId,destId); } } - private IpAddress extractAmplifiedLink(OMSAttributes omsAttributes, String linkId, IpAddress srcIp) + private String extractAmplifiedLink(OMSAttributes omsAttributes, String linkId, String srcId) throws GnpyException { List amplifiedLinkList = new ArrayList<>(omsAttributes.getAmplifiedLink() .nonnullAmplifiedLink().values()); - IpAddress destIp = null; + String destId = null; if (!amplifiedLinkList.isEmpty()) { for (AmplifiedLink amplifiedLink: amplifiedLinkList) { String secElt = amplifiedLink .getSectionEltNumber().toString(); //Case of ILA if (amplifiedLink.getSectionElement().getSectionElement() instanceof Ila) { Ila ila = (Ila) amplifiedLink.getSectionElement().getSectionElement(); - destIp = extractILAFromAmpLink(ila); + destId = extractILAFromAmpLink(ila); } //Case of Span if (amplifiedLink.getSectionElement().getSectionElement() instanceof Span) { Span span = (Span) amplifiedLink.getSectionElement().getSectionElement(); - destIp = extractSpan(span.getSpan(), linkId, secElt); + destId = extractSpan(span.getSpan(), linkId, secElt); } // Create a new link - if (createNewConnection(srcIp,destIp)) { - srcIp = destIp; + if (createNewConnection(srcId,destId)) { + srcId = destId; } } } - return srcIp; + return srcId; } - private IpAddress extractSpanLink(OMSAttributes omsAttributes, String linkId, IpAddress srcIp) + private String extractSpanLink(OMSAttributes omsAttributes, String linkId, String srcId) throws GnpyException { SpanAttributes span = omsAttributes.getSpan(); - IpAddress destIp = extractSpan(span, linkId, linkId); - if (createNewConnection(srcIp, destIp)) { - return destIp; + String destId = extractSpan(span, linkId, linkId); + if (createNewConnection(srcId, destId)) { + return destId; } - return srcIp; + return srcId; } - private IpAddress extractILAFromAmpLink(Ila ila) throws GnpyException { + private String extractILAFromAmpLink(Ila ila) throws GnpyException { String nodeId = ila.getNodeId().getValue(); - IpAddress ipEdfa = new IpAddress(edfaId); - edfaId = incrementIdentifier(edfaId); mapDisgNodeRefNode.put(nodeId, nodeId); - mapNodeRefIp.put(nodeId, ipEdfa); Elements element = createElementsEdfa(LATITUDE, LONGITUTE, REGION, CITY, ila.getGain().getValue(), ila.getTilt().getValue(), ila.getOutVoaAtt().getValue(), "std_medium_gain", - ipEdfa.getIpv4Address().getValue()); + nodeId); this.elements.put(element.key(),element); - return ipEdfa; + return nodeId; } - private IpAddress extractSpan(SpanAttributes span, String linkId, String subLinkId) throws GnpyException { - IpAddress ipFiber = new IpAddress(fiberId); - + private String extractSpan(SpanAttributes span, String linkId, String subLinkId) throws GnpyException { if (!mapLinkFiber.containsKey(linkId)) { mapLinkFiber.put(linkId, new ArrayList<>()); } mapLinkFiber.get(linkId).add(subLinkId); - mapFiberIp.put(subLinkId, ipFiber); - fiberId = incrementIdentifier(fiberId); + //mapFiberIp.put(subLinkId, ipFiber); + //fiberId = incrementIdentifier(fiberId); double attIn = 0; double connIn = 0; double connOut = 0; @@ -362,10 +330,9 @@ public class GnpyTopoImpl { } double lossCoef = span.getSpanlossCurrent().getValue().doubleValue() / length; Elements element = createElementsFiber(LATITUDE, LONGITUTE, REGION, CITY, - ipFiber.getIpv4Address().getValue(), length, attIn, lossCoef, connIn, connOut, typeVariety); + subLinkId, length, attIn, lossCoef, connIn, connOut, typeVariety); this.elements.put(element.key(),element); - return ipFiber; - + return subLinkId; } /* @@ -383,9 +350,9 @@ public class GnpyTopoImpl { .setAttIn(BigDecimal.valueOf(attIn)).setLossCoef(BigDecimal.valueOf(lossCoef)) .setConIn(BigDecimal.valueOf(connIn)) .setConOut(BigDecimal.valueOf(connOut)).build(); - Params params1 = new ParamsBuilder().setFiberroadm(fiber).build(); + Params params1 = new ParamsBuilder().setFiberroadmfused(fiber).build(); return new ElementsBuilder().setUid(uidFiber) - .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.Fiber.class) + .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.Fiber.class) .setTypeVariety(typeVariety).setMetadata(metadata1) .setElementType(new FiberRoadmBuilder().setParams(params1).build()).build(); } @@ -406,7 +373,7 @@ public class GnpyTopoImpl { Edfa edfa = new EdfaBuilder() .setOperational(operational).build(); return new ElementsBuilder().setUid(uidEdfa) - .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.Edfa.class) + .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.Edfa.class) .setMetadata(metadata1).setElementType(edfa).setTypeVariety(typeVariety).build(); } @@ -422,9 +389,9 @@ public class GnpyTopoImpl { .build(); Metadata metadata1 = new MetadataBuilder().setLocation(location1).build(); Roadm roadm = new RoadmBuilder().setTargetPchOutDb(BigDecimal.valueOf(targetPchOutDb)).build(); - Params params1 = new ParamsBuilder().setFiberroadm(roadm).build(); + Params params1 = new ParamsBuilder().setFiberroadmfused(roadm).build(); return new ElementsBuilder().setUid(uidRoadm) - .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.Roadm.class) + .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.Roadm.class) .setMetadata(metadata1).setElementType(new FiberRoadmBuilder().setParams(params1).build()).build(); } @@ -440,19 +407,17 @@ public class GnpyTopoImpl { Metadata metadata1 = new MetadataBuilder().setLocation(location1).build(); Transceiver transceiver = new TransceiverBuilder().build(); return new ElementsBuilder().setUid(uidTrans) - .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.Transceiver.class) + .setType(org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.Transceiver.class) .setMetadata(metadata1).setElementType(transceiver).build(); } /* * Method to create Connection */ - private boolean createNewConnection(IpAddress srcIp, IpAddress destIp) throws GnpyException { - if (srcIp == null || destIp == null) { + private boolean createNewConnection(String fromNode, String toNode) throws GnpyException { + if (fromNode == null || toNode == null) { throw new GnpyException("create new connection : null node IpAddress"); } - String fromNode = srcIp.getIpv4Address().getValue(); - String toNode = destIp.getIpv4Address().getValue(); if (fromNode.equals(toNode)) { return false; } @@ -461,38 +426,6 @@ public class GnpyTopoImpl { return true; } - /* - * Increment 32-bit identifier - */ - private Ipv4Address incrementIdentifier(Ipv4Address id) throws GnpyException { - String ips = id.getValue(); - String [] fields = ips.split(Pattern.quote(".")); - int intF1 = Integer.parseInt(fields[1]); - int intF2 = Integer.parseInt(fields[2]); - int intF3 = Integer.parseInt(fields[3]); - if (intF3 < 255) { - intF3++; - } else { - if (intF2 < 255) { - intF2++; - intF3 = 0; - } else { - if (intF1 < 255) { - intF1++; - intF2 = 0; - intF3 = 0; - } else { - throw new GnpyException("GnpyTopoImpl : the topology is not supported by gnpy"); - } - fields[1] = Integer.toString(intF1); - } - fields[2] = Integer.toString(intF2); - } - fields[3] = Integer.toString(intF3); - String nidString = fields[0] + "." + fields[1] + "." + fields[2] + "." + fields[3]; - return new Ipv4Address(nidString); - } - public Map getElements() { return elements; } @@ -509,20 +442,20 @@ public class GnpyTopoImpl { this.connections = connections; } - public Map getMapDisgNodeRefNode() { - return mapDisgNodeRefNode; + public List getElementsList() { + return elementsList; } - public void setMapDisgNodeRefNode(Map mapDisgNodeRefNode) { - this.mapDisgNodeRefNode = mapDisgNodeRefNode; + public void setElementsList(List elementsList) { + this.elementsList = elementsList; } - public Map getMapNodeRefIp() { - return mapNodeRefIp; + public Map getMapDisgNodeRefNode() { + return mapDisgNodeRefNode; } - public void setMapNodeRefIp(Map mapNodeRefIp) { - this.mapNodeRefIp = mapNodeRefIp; + public void setMapDisgNodeRefNode(Map mapDisgNodeRefNode) { + this.mapDisgNodeRefNode = mapDisgNodeRefNode; } public Map> getMapLinkFiber() { @@ -533,14 +466,6 @@ public class GnpyTopoImpl { this.mapLinkFiber = mapLinkFiber; } - public Map getMapFiberIp() { - return mapFiberIp; - } - - public void setMapFiberIp(Map mapFiberIp) { - this.mapFiberIp = mapFiberIp; - } - public List getTrxList() { return trxList; } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyUtilitiesImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyUtilitiesImpl.java index d50f97080..97aae94c3 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyUtilitiesImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/GnpyUtilitiesImpl.java @@ -14,16 +14,15 @@ import java.util.stream.Collectors; import org.opendaylight.transportpce.common.network.NetworkTransactionService; import org.opendaylight.transportpce.pce.constraints.PceConstraints; import org.opendaylight.transportpce.pce.gnpy.consumer.GnpyConsumer; -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.rev210831.topo.Connections; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev210831.topo.Elements; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.properties.path.properties.PathRouteObjects; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.service.PathRequest; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.synchronization.info.Synchronization; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.RequestBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.request.ServiceBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.request.TopologyBuilder; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.Connections; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.network.topology.rev220221.topo.Elements; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.properties.path.properties.PathRouteObjects; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.service.PathRequest; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.synchronization.info.Synchronization; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.PathComputationRequestInput; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirection; import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirectionBuilder; @@ -115,19 +114,19 @@ public class GnpyUtilitiesImpl { } public Result getGnpyResponse(List elementsList, List connectionsList, - List pathRequestList, List synchronizationList) { - GnpyApi gnpyApi = new GnpyApiBuilder() - .setTopologyFile( - new TopologyFileBuilder() + List pathRequestList, List synchronizationList) { + + return gnpyConsumer.computePaths(new RequestBuilder() + .setTopology( + new TopologyBuilder() .setElements(elementsList.stream().collect(Collectors.toMap(Elements::key, element -> element))) .setConnections(connectionsList).build()) - .setServiceFile( - new ServiceFileBuilder() + .setService( + new ServiceBuilder() .setPathRequest(pathRequestList.stream() .collect(Collectors.toMap(PathRequest::key, pathRequest -> pathRequest))) .build()) - .build(); - return gnpyConsumer.computePaths(gnpyApi); + .build()); } public GnpyResult getGnpyAtoZ() { diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyApiModule.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyApiModule.java index 549b95deb..f750005cc 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyApiModule.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyApiModule.java @@ -10,8 +10,10 @@ package org.opendaylight.transportpce.pce.gnpy.consumer; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.PackageVersion; import org.opendaylight.transportpce.common.converter.JsonStringConverter; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; + + //This class is a temporary workaround while waiting jackson //support in yang tools https://git.opendaylight.org/gerrit/c/yangtools/+/94852 @@ -19,10 +21,9 @@ public class GnpyApiModule extends SimpleModule { private static final long serialVersionUID = 1L; - public GnpyApiModule(JsonStringConverter gnpyApiConverter, JsonStringConverter resultConverter) { + public GnpyApiModule(JsonStringConverter requestConverter, JsonStringConverter resultConverter) { super(PackageVersion.VERSION); - addSerializer(GnpyApi.class, new GnpyApiSerializer(gnpyApiConverter)); + addSerializer(Request.class, new RequestSerializer(requestConverter)); addDeserializer(Result.class, new ResultDeserializer(resultConverter)); } - } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumer.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumer.java index 5c69347a1..b45a3880f 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumer.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumer.java @@ -7,8 +7,10 @@ */ package org.opendaylight.transportpce.pce.gnpy.consumer; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; + +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; + public interface GnpyConsumer { @@ -23,6 +25,6 @@ public interface GnpyConsumer { * @param request GnpyApi. * @return Result the result of pat computation. */ - Result computePaths(GnpyApi request); + Result computePaths(Request request); } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumerImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumerImpl.java index 4913624a5..cd4b6eb69 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumerImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumerImpl.java @@ -17,8 +17,8 @@ import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.logging.LoggingFeature; import org.opendaylight.mdsal.binding.dom.codec.spi.BindingDOMCodecServices; import org.opendaylight.transportpce.common.converter.JsonStringConverter; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,14 +26,15 @@ public class GnpyConsumerImpl implements GnpyConsumer { private static final Logger LOG = LoggerFactory.getLogger(GnpyConsumerImpl.class); private GnpyResource api; - private JsonStringConverter gnpyApiConverter; - private JsonStringConverter resultConverter; + JsonStringConverter gnpyRequestConverter; + JsonStringConverter resultConverter; public GnpyConsumerImpl(String baseUrl, String username, String password, BindingDOMCodecServices bindingDOMCodecServices) { - gnpyApiConverter = new JsonStringConverter<>(bindingDOMCodecServices); + gnpyRequestConverter = new JsonStringConverter<>(bindingDOMCodecServices); resultConverter = new JsonStringConverter<>(bindingDOMCodecServices); - JsonConfigurator jsonConfigurator = new JsonConfigurator(gnpyApiConverter, resultConverter); + + JsonConfigurator jsonConfigurator = new JsonConfigurator(gnpyRequestConverter, resultConverter); Client client = ClientBuilder.newClient(); HttpAuthenticationFeature authFeature = HttpAuthenticationFeature.basic(username, password); client.register(authFeature); @@ -45,7 +46,7 @@ public class GnpyConsumerImpl implements GnpyConsumer { @Override public boolean isAvailable() { try { - api.checkStatus(); + api.getStatus(); LOG.info("GNPy is available"); return true; } catch (WebApplicationException | ProcessingException e) { @@ -55,7 +56,7 @@ public class GnpyConsumerImpl implements GnpyConsumer { } @Override - public Result computePaths(GnpyApi request) { + public Result computePaths(Request request) { try { return api.computePathRequest(request); } catch (WebApplicationException | ProcessingException e) { diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyResource.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyResource.java index 5b7377490..a30112c8a 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyResource.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyResource.java @@ -8,23 +8,31 @@ package org.opendaylight.transportpce.pce.gnpy.consumer; import javax.ws.rs.Consumes; +import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; -@Path("/gnpy/api/v1.0/files") + +@Path("/api/v1") public interface GnpyResource { @HEAD String checkStatus(); @POST + @Path("/path-computation") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) - Result computePathRequest(GnpyApi request); + Result computePathRequest(Request request); + + @GET + @Path("/status") + @Produces(MediaType.APPLICATION_JSON) + GnpyStatus getStatus(); } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyStatus.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyStatus.java new file mode 100644 index 000000000..2c3ceb406 --- /dev/null +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyStatus.java @@ -0,0 +1,35 @@ +/* + * Copyright © 2022 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.consumer; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GnpyStatus { + + @JsonProperty("version") + private String version; + + @JsonProperty("status") + private String status; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/JsonConfigurator.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/JsonConfigurator.java index 9e051d15d..9bc373295 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/JsonConfigurator.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/JsonConfigurator.java @@ -13,21 +13,21 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import javax.ws.rs.ext.ContextResolver; import org.opendaylight.transportpce.common.converter.JsonStringConverter; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; public class JsonConfigurator implements ContextResolver { private final ObjectMapper mapper; - public JsonConfigurator(JsonStringConverter gnpyApiConverter, + public JsonConfigurator(JsonStringConverter requestConverter, JsonStringConverter resultConverter) { mapper = new ObjectMapper(); mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - mapper.registerModule(new GnpyApiModule(gnpyApiConverter, resultConverter)); + mapper.registerModule(new GnpyApiModule(requestConverter, resultConverter)); } @Override diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyApiSerializer.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/RequestSerializer.java similarity index 63% rename from pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyApiSerializer.java rename to pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/RequestSerializer.java index 29cd17c4e..4dd687cc4 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyApiSerializer.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/RequestSerializer.java @@ -12,7 +12,7 @@ import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; import org.opendaylight.transportpce.common.converter.JsonStringConverter; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier; import org.slf4j.Logger; @@ -21,26 +21,25 @@ import org.slf4j.LoggerFactory; //This class is a temporary workaround while waiting jackson //support in yang tools https://git.opendaylight.org/gerrit/c/yangtools/+/94852 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "temporary class") -public class GnpyApiSerializer extends StdSerializer { + +public class RequestSerializer extends StdSerializer { private static final long serialVersionUID = 1L; - private static final Logger LOG = LoggerFactory.getLogger(GnpyApiSerializer.class); - private JsonStringConverter converter; - private InstanceIdentifier idGnpyApi = InstanceIdentifier.builder(GnpyApi.class).build(); + private static final Logger LOG = LoggerFactory.getLogger(RequestSerializer.class); + private JsonStringConverter converter; + private InstanceIdentifier idRequest = InstanceIdentifier.builder(Request.class).build(); - public GnpyApiSerializer(JsonStringConverter converter) { - super(GnpyApi.class); + public RequestSerializer(JsonStringConverter converter) { + super(Request.class); this.converter = converter; } @Override - public void serialize(GnpyApi value, JsonGenerator gen, SerializerProvider provider) throws IOException { - String requestStr = converter - .createJsonStringFromDataObject(idGnpyApi, value, + public void serialize(Request value, JsonGenerator gen, SerializerProvider provider) throws IOException { + String requestStr = this.converter + .createJsonStringFromDataObject(this.idRequest, value, JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02); - requestStr = requestStr.replace("gnpy-eqpt-config:", "") - .replace("gnpy-path-computation-simplified:", "").replace("gnpy-network-topology:", ""); + requestStr = requestStr.replace("gnpy-network-topology:", ""); LOG.info("Serialized request {}", requestStr); gen.writeRaw(requestStr); } - } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/ResultDeserializer.java b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/ResultDeserializer.java index 222be701d..8ddbb417e 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/ResultDeserializer.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/gnpy/consumer/ResultDeserializer.java @@ -12,33 +12,36 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; import org.opendaylight.transportpce.common.converter.JsonStringConverter; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + //This class is a temporary workaround while waiting jackson //support in yang tools https://git.opendaylight.org/gerrit/c/yangtools/+/94852 @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "temporary class") public class ResultDeserializer extends StdDeserializer { + private static final Logger LOG = LoggerFactory.getLogger(ResultDeserializer.class); private static final long serialVersionUID = 1L; - private JsonStringConverter converter; - private YangInstanceIdentifier yangId; + private JsonStringConverter converter; + private YangInstanceIdentifier yangId; public ResultDeserializer(JsonStringConverter converter) { super(Result.class); this.converter = converter; - QName pathQname = QName.create("gnpy:path", "2020-09-09", "result"); + QName pathQname = Result.QNAME; + LOG.info("QName of the first result class {}", pathQname); yangId = YangInstanceIdentifier.of(pathQname); } @Override public Result deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException { - return converter - .createDataObjectFromJsonString(yangId, - parser.readValueAsTree().toString(), - JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02); + return converter.createDataObjectFromJsonString(yangId,parser.readValueAsTree().toString(), + JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02); } } diff --git a/pce/src/main/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImpl.java b/pce/src/main/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImpl.java index 519f057f1..7b4b99074 100644 --- a/pce/src/main/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImpl.java +++ b/pce/src/main/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImpl.java @@ -24,7 +24,7 @@ import org.opendaylight.transportpce.pce.PceComplianceCheckResult; import org.opendaylight.transportpce.pce.PceSendingPceRPCs; import org.opendaylight.transportpce.pce.gnpy.GnpyResult; import org.opendaylight.transportpce.pce.gnpy.consumer.GnpyConsumer; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.Response; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.Response; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.CancelResourceReserveInput; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.CancelResourceReserveOutput; import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.pce.rev210701.CancelResourceReserveOutputBuilder; @@ -239,26 +239,26 @@ public class PathComputationServiceImpl implements PathComputationService { ResponseType respType = null; boolean feasible = true; if (responseGnpy != null) { - if (responseGnpy.getResponseType() instanceof org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result + if (responseGnpy.getResponseType() instanceof org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result .response.response.type.NoPathCase) { LOG.info("GNPy : path is not feasible"); - org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.response.response.type.NoPathCase - noPathGnpy = (org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.response.response.type + org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.response.response.type.NoPathCase + noPathGnpy = (org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.response.response.type .NoPathCase) responseGnpy.getResponseType(); NoPathCase noPathCase = new NoPathCaseBuilder().setNoPath(noPathGnpy.getNoPath()).build(); respType = noPathCase; feasible = false; - } else if (responseGnpy.getResponseType() instanceof org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result + } else if (responseGnpy.getResponseType() instanceof org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result .response.response.type.PathCase) { LOG.info("GNPy : path is feasible"); - org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.response.response.type.PathCase pathCase = - (org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.response.response.type.PathCase) + org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.response.response.type.PathCase pathCase = + (org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.response.response.type.PathCase) responseGnpy.getResponseType(); - List pathMetricList = new ArrayList<>(pathCase.getPathProperties().getPathMetric().values()); List gnpyPathMetricList = new ArrayList<>(); - for (org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.properties.path.properties.PathMetric + for (org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.properties.path.properties.PathMetric pathMetricGnpy : pathMetricList) { PathMetric pathMetric = new PathMetricBuilder().setMetricType(pathMetricGnpy.getMetricType()) .setAccumulativeValue(pathMetricGnpy.getAccumulativeValue()).build(); diff --git a/pce/src/test/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumerTest.java b/pce/src/test/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumerTest.java index 074f8d459..c8fae69da 100644 --- a/pce/src/test/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumerTest.java +++ b/pce/src/test/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyConsumerTest.java @@ -19,8 +19,8 @@ import org.glassfish.jersey.test.JerseyTest; import org.junit.Test; import org.opendaylight.transportpce.common.converter.JsonStringConverter; import org.opendaylight.transportpce.test.AbstractTest; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.Result; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.Result; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier; @@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory; public class GnpyConsumerTest extends JerseyTest { private static final Logger LOG = LoggerFactory.getLogger(GnpyConsumerTest.class); - private JsonStringConverter gnpyApiConverter; + private JsonStringConverter gnpyApiConverter; @Override protected Application configure() { @@ -53,9 +53,9 @@ public class GnpyConsumerTest extends JerseyTest { "mylogin", "mypassword", AbstractTest.getDataStoreContextUtil().getBindingDOMCodecServices()); - QName pathQname = QName.create("gnpy:gnpy-api", "2019-01-03", "gnpy-api"); + QName pathQname = Request.QNAME; YangInstanceIdentifier yangId = YangInstanceIdentifier.of(pathQname); - GnpyApi request = gnpyApiConverter + Request request = gnpyApiConverter .createDataObjectFromJsonString(yangId, Files.readString(Paths.get("src/test/resources/gnpy/gnpy_request.json")), JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02); diff --git a/pce/src/test/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyStub.java b/pce/src/test/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyStub.java index 43d6db88a..aa6e86065 100644 --- a/pce/src/test/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyStub.java +++ b/pce/src/test/java/org/opendaylight/transportpce/pce/gnpy/consumer/GnpyStub.java @@ -14,22 +14,24 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import javax.ws.rs.Consumes; +import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.opendaylight.transportpce.common.converter.JsonStringConverter; import org.opendaylight.transportpce.test.AbstractTest; -import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev190103.GnpyApi; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.service.PathRequest; +import org.opendaylight.yang.gen.v1.gnpy.gnpy.api.rev220221.Request; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.service.PathRequest; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Path("/gnpy/api/v1.0/files") +@Path("/api/v1") public class GnpyStub { private static final Logger LOG = LoggerFactory.getLogger(GnpyStub.class); @@ -38,30 +40,43 @@ public class GnpyStub { return Response.ok().build(); } + @GET + @Path("/status") + @Produces(MediaType.APPLICATION_JSON) + public Response getStatus() { + try { + String response = Files.readString(Paths.get("src", "test", "resources", "gnpy", "gnpy_status.json")); + return Response.ok(response).build(); + } catch (IOException e) { + LOG.error("Cannot manage request", e); + return Response.serverError().build(); + } + } + @POST @Produces({ "application/json" }) @Consumes({ "application/json" }) + @Path("/path-computation") public Response computePath(String request) { LOG.info("Received path request {}", request); - URI location = URI.create("http://127.0.0.1:9998/gnpy/api/v1.0/files"); + URI location = URI.create("http://127.0.0.1:9998/api/v1/path-computation"); // TODO: return different response based on body data - QName pathQname = QName.create("gnpy:gnpy-api", "2019-01-03", "gnpy-api"); + QName pathQname = Request.QNAME; YangInstanceIdentifier yangId = YangInstanceIdentifier.of(pathQname); - JsonStringConverter converter = new JsonStringConverter<>( + JsonStringConverter converter = new JsonStringConverter<>( AbstractTest.getDataStoreContextUtil().getBindingDOMCodecServices()); try { String response = null; request = request.replace("Transceiver", "gnpy-network-topology:Transceiver") .replace("Roadm", "gnpy-network-topology:Roadm") .replace("Fiber", "gnpy-network-topology:Fiber") - .replace("km", "gnpy-network-topology:km") - .replace("route-include-ero", "gnpy-path-computation-simplified:route-include-ero"); - GnpyApi data = converter.createDataObjectFromJsonString(yangId, + .replace("km", "gnpy-network-topology:km"); + Request data = converter.createDataObjectFromJsonString(yangId, request, JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02); LOG.info("Converted request {}", data); - List pathRequest = new ArrayList<>(data.getServiceFile().nonnullPathRequest().values()); + List pathRequest = new ArrayList<>(data.getService().nonnullPathRequest().values()); // this condition is totally arbitrary and could be modified - if (!pathRequest.isEmpty() && "127.0.0.31".contentEquals(pathRequest.get(0).getSource().stringValue())) { + if (!pathRequest.isEmpty() && "XPONDER-3".contentEquals(pathRequest.get(0).getSource())) { response = Files .readString(Paths.get("src", "test", "resources", "gnpy", "gnpy_result_with_path.json")); } else { diff --git a/pce/src/test/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImplTest.java b/pce/src/test/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImplTest.java index 2bea3e823..c021fe29f 100644 --- a/pce/src/test/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImplTest.java +++ b/pce/src/test/java/org/opendaylight/transportpce/pce/service/PathComputationServiceImplTest.java @@ -21,17 +21,16 @@ import org.opendaylight.transportpce.pce.gnpy.GnpyTopoImpl; import org.opendaylight.transportpce.pce.utils.PceTestData; import org.opendaylight.transportpce.test.AbstractTest; import org.opendaylight.transportpce.test.DataStoreContext; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.PathBandwidth; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.properties.PathPropertiesBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.properties.path.properties.PathMetric; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.generic.path.properties.path.properties.PathMetricBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.no.path.info.NoPathBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.Response; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.ResponseBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.ResponseKey; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.response.response.type.NoPathCaseBuilder; -import org.opendaylight.yang.gen.v1.gnpy.path.rev200909.result.response.response.type.PathCaseBuilder; -import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.PathBandwidth; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.properties.PathPropertiesBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.properties.path.properties.PathMetric; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.generic.path.properties.path.properties.PathMetricBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.no.path.info.NoPathBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.Response; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.ResponseBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.ResponseKey; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.response.response.type.NoPathCaseBuilder; +import org.opendaylight.yang.gen.v1.gnpy.path.rev220221.result.response.response.type.PathCaseBuilder; public class PathComputationServiceImplTest extends AbstractTest { @@ -64,7 +63,7 @@ public class PathComputationServiceImplTest extends AbstractTest { @Test public void testPathComputationRequestNoPath() { Response response = new ResponseBuilder() - .withKey(new ResponseKey(Uint32.valueOf(1))).setResponseType(new NoPathCaseBuilder() + .withKey(new ResponseKey("responseId")).setResponseType(new NoPathCaseBuilder() .setNoPath(new NoPathBuilder().setNoPath("no path").build()).build()).build(); pathComputationServiceImpl.generateGnpyResponse(response,"path"); @@ -79,7 +78,7 @@ public class PathComputationServiceImplTest extends AbstractTest { .setAccumulativeValue(new BigDecimal(21)) .setMetricType(PathBandwidth.class).build(); Response response = new ResponseBuilder() - .withKey(new ResponseKey(Uint32.valueOf(1))).setResponseType(new PathCaseBuilder() + .withKey(new ResponseKey("responseId")).setResponseType(new PathCaseBuilder() .setPathProperties(new PathPropertiesBuilder().setPathMetric(Map.of(pathMetric.key(),pathMetric)) .build()).build()).build(); diff --git a/pce/src/test/resources/gnpy/gnpy_request.json b/pce/src/test/resources/gnpy/gnpy_request.json index 0219eef29..25916095a 100644 --- a/pce/src/test/resources/gnpy/gnpy_request.json +++ b/pce/src/test/resources/gnpy/gnpy_request.json @@ -1,6 +1,6 @@ { - "gnpy-api": { - "topology-file": { + "request": { + "topology": { "elements": [ { "uid": "127.0.0.40", @@ -577,7 +577,7 @@ } ] }, - "service-file": { + "service": { "path-request": [ { "request-id": 2, diff --git a/pce/src/test/resources/gnpy/gnpy_result_no_path.json b/pce/src/test/resources/gnpy/gnpy_result_no_path.json index d0b58860d..21983b2de 100644 --- a/pce/src/test/resources/gnpy/gnpy_result_no_path.json +++ b/pce/src/test/resources/gnpy/gnpy_result_no_path.json @@ -8,7 +8,7 @@ "path-properties": { "path-metric": [ { - "metric-type": "SNR-bandwidth", + "gnpy-path:metric-type": "SNR-bandwidth", "accumulative-value": 13.06 }, { diff --git a/pce/src/test/resources/gnpy/gnpy_status.json b/pce/src/test/resources/gnpy/gnpy_status.json new file mode 100644 index 000000000..5f32751aa --- /dev/null +++ b/pce/src/test/resources/gnpy/gnpy_status.json @@ -0,0 +1,4 @@ +{ + "status": "ok", + "version": "v1" +} \ No newline at end of file diff --git a/tests/sample_configs/gnpy/openroadmTopology.json b/tests/sample_configs/gnpy/openroadmTopology.json index 239f7bbbe..3029dcacc 100644 --- a/tests/sample_configs/gnpy/openroadmTopology.json +++ b/tests/sample_configs/gnpy/openroadmTopology.json @@ -590,8 +590,8 @@ "fiber-type": "smf" } ], - "spanloss-current": 29, - "engineered-spanloss": 30.2, + "spanloss-current": 20, + "engineered-spanloss": 20.2, "auto-spanloss": true } }, @@ -652,8 +652,8 @@ "fiber-type": "smf" } ], - "spanloss-current": 29, - "engineered-spanloss": 30.2, + "spanloss-current": 20, + "engineered-spanloss": 20.2, "auto-spanloss": true } }, @@ -678,12 +678,12 @@ "link-concatenation": [ { "SRLG-Id": 0, - "SRLG-length": 140000, + "SRLG-length": 133000, "pmd": 0.5, "fiber-type": "smf" } ], - "spanloss-current": 29, + "spanloss-current": 27.93, "engineered-spanloss": 30.2, "auto-spanloss": true } @@ -771,12 +771,12 @@ "link-concatenation": [ { "SRLG-Id": 0, - "SRLG-length": 140000, + "SRLG-length": 133000, "pmd": 0.5, "fiber-type": "smf" } ], - "spanloss-current": 29, + "spanloss-current": 27.93, "engineered-spanloss": 30.2, "auto-spanloss": true } @@ -838,8 +838,8 @@ "fiber-type": "smf" } ], - "spanloss-current": 29, - "engineered-spanloss": 30.2, + "spanloss-current": 20, + "engineered-spanloss": 20.2, "auto-spanloss": true } }, @@ -869,8 +869,8 @@ "fiber-type": "smf" } ], - "spanloss-current": 29, - "engineered-spanloss": 30.2, + "spanloss-current": 20, + "engineered-spanloss": 20.2, "auto-spanloss": true } }, @@ -900,8 +900,8 @@ "fiber-type": "smf" } ], - "spanloss-current": 29, - "engineered-spanloss": 30.2, + "spanloss-current": 20, + "engineered-spanloss": 20.2, "auto-spanloss": true } }, @@ -931,8 +931,8 @@ "fiber-type": "smf" } ], - "spanloss-current": 29, - "engineered-spanloss": 30.2, + "spanloss-current": 20, + "engineered-spanloss": 20.2, "auto-spanloss": true } }, diff --git a/tests/transportpce_tests/pce/test03_gnpy.py b/tests/transportpce_tests/pce/test03_gnpy.py index 21b9b42b3..57e129620 100644 --- a/tests/transportpce_tests/pce/test03_gnpy.py +++ b/tests/transportpce_tests/pce/test03_gnpy.py @@ -74,7 +74,7 @@ class TransportGNPYtesting(unittest.TestCase): print('starting GNPy REST server...') # pylint: disable=consider-using-with test_utils.process_list.append(subprocess.Popen( - ['path_requests_run.py', '--rest'], stdout=outfile, stderr=outfile, stdin=None)) + ['gnpy-rest'], stdout=outfile, stderr=outfile, stdin=None)) cls.processes = test_utils.start_tpce() @classmethod @@ -196,15 +196,14 @@ class TransportGNPYtesting(unittest.TestCase): # Not found path by PCE and GNPy cannot find another one def test_07_path_computation_FoundByPCE_NotFeasibleByGnpy(self): response = test_utils.path_computation_request("request-4", "service-4", - {"node-id": "XPONDER-1", "service-rate": "100", + {"node-id": "XPONDER-1", "service-rate": "400", "service-format": "Ethernet", "clli": "Node1"}, - {"node-id": "XPONDER-4", "service-rate": "100", - "service-format": "Ethernet", "clli": "Node5"}, + {"node-id": "XPONDER-4", "service-rate": "400", + "service-format": "Ethernet", "clli": "Node4"}, {"include_": {"ordered-hops": [ - {"hop-number": "0", "hop-type": {"node-id": "OpenROADM-2"}}, - {"hop-number": "1", "hop-type": {"node-id": "OpenROADM-3"}}, - {"hop-number": "2", "hop-type": {"node-id": "OpenROADM-4"}}, - {"hop-number": "3", "hop-type": {"node-id": "OpenROADM-3"}}]} + {"hop-number": "0", "hop-type": {"node-id": "OpenROADM-3"}}, + {"hop-number": "1", "hop-type": {"node-id": "OpenROADM-2"}}, + {"hop-number": "2", "hop-type": {"node-id": "OpenROADM-5"}}]} }) self.assertEqual(response.status_code, requests.codes.ok) res = response.json() diff --git a/tox.ini b/tox.ini index 059b847c7..76c6b76cc 100644 --- a/tox.ini +++ b/tox.ini @@ -64,9 +64,10 @@ deps = -r{toxinidir}/tests/requirements.txt -r{toxinidir}/tests/test-requirements.txt setuptools>=7.0 - gnpy4tpce==1.2.1 + gnpy4tpce==2.4.2 whitelist_externals = launch_tests.sh passenv = LAUNCHER USE_LIGHTY USE_ODL_RESTCONF_VERSION +basepython = python3.8 #setenv = # USE_LIGHTY=True commands = -- 2.36.6