41 Commits
v1.8 ... v2.0

Author SHA1 Message Date
Jan Kundrát
99f44a597b Merge remote-tracking branch 'origin/develop' 2019-11-13 19:59:35 +01:00
Jan Kundrát
a21f3fe6ee Merge pull request #312 from jktjkt/fixes
Small refactoring for itufs/utifl
2019-10-16 05:38:37 +00:00
Jan Kundrát
0ccbb2960c Merge pull request #277 from Orange-OpenSource/capacity_planning-part1
Capacity planning part1
2019-10-16 05:36:56 +00:00
EstherLerouzic
87cc3dac00 Corrections with respect to second review
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 19:09:39 +01:00
EstherLerouzic
89e28cc7be Correct bug in parser: csv header comparison
previous comparison was done on the result from .sort(), ie None.
list.sort() method modifies the list in-place and returns None.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
2ba29a78c5 Bug: constraint not correctly interpreted
if name of the constraint input from user is not part of networks names
(typically in the case of excel input), then the program try to find a
name that is clode to the user name and  that is in the network list of
names. This list must not include trnasponder names (because transponder
end points are already listed as constraints and transponder in the
middle of a path are not supported yet)
This will be improved in the PR Ila names in constraints #278
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
f990a6c1be Correct some remaining strict loose into STRICT LOOSE
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
424e5a4786 change variable n to nel to conform to '[a-z_][a-z0-9_]{2,30}$' pattern
from codacy report

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
6a7a04ebb1 syntax correction
reordering imports call according to pylint3 + extra line removed

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
0366fc2956 Adding a no-path case for test coverage
add a no path case (request 6) in requests and expected responses.
response is also generated if path is not feasible: checks
that it is correctly handled in csv and json responses

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
48b7d71f02 add a test on json response generation
create a json response based on test file and compare it to expected
response.
comparison first checks that there is no missing or extra key
and then compares keys

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
715baf2a1c correct compare response header test to support any order
previous test assumed same order for header fields.
order the headers in the same way in order to support different
types of order

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
e55cea776e improve code quality
remove unused import, use correct indents, remove extra spaces
add function description

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
b388d143fd change assert to raise AssertionError
use
  if not condition:
  raise AssertionError()
instead of
  assert condition
according to codacy recommendation

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
c592c572d8 adding a test for the csv creation
using pandas package to have an easy ordering of response column:
- test that the generated header is as expected
- read the response. In order to support different orders wrt
  response answer and field answer, test function frst orders lines
  according to response index and then to columns (fields of the answer).
check that the answers are as expected

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
dfa0a26a28 changes to improve quality
minor name refactor
indent corrections
minor fixes for spacing

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
609cd94798 Remove @ in path-metric names and extend type to decimal64
@ character not correctly read with OpenDayLight yang tool used
for transportPCE project.
https://docs.opendaylight.org/en/stable-nitrogen/developer-guide/yang-tools.html#working-with-yang-model.
Changed the names of path metrics from osnr@ to osnr-

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
022f743db1 Change the exception handling if sync vector is absent
previous try section encompass errors that should not be silently
ignored. Correction pointed a default in a test file.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
1957beb1b6 Remove the filtering on transponders for correcting explicit route
anytype supported including transponder in order to accept well formed
route list from user (if user enters 'trx Lannion_CAS' this should be
accepted even if it repeats the source name)

A later PR better handles route list names

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
9ca72d6105 Correct csv creation in case of no path
previously reported the requested bandwidth, now fill it with an
empty string, same as the other fields.

This will be updated in a later PR when different kind of blocking
will be supported

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
e8e126a6ce update existing test files and examples according to ietf yang model
- 'loose' and 'strict' changed to 'LOOSE' and 'STRICT'
    - n, m changed to N, M
    - unused objects removed
    - ...
Also correct templates for service and response

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
7849782173 Change content of source and destination to transponder end-points
previously contained the user-given source name in excel file,
but could differ from effective transponder source/destination

now both source and src-tp-id contain the same info (gnpy does
not make difference between node and ports)

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
149a0da8c9 update csv creation according to all model changes
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
1e7c70a59b remove the restriction on fiber for the constraint
restriction was placed on fiber type because when using excel input
autodesign create fiber names with syntax not explicit to the user, so that
entering a node name as constraint may end up to a wrong interpretation eg
aa -bb  -> create names such as 'fiber aa to bb', fiber bb to aa' .
If user constraint is bb there is a ambiguity on the fiber direction.
However this is not a problem for user using json format.
So I preferred to removed this constraint now.
a later PR solves this naming ambiguity

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
c9d8282e7f enable power and nch to be optional in requests definition
since empty attributes have been removed from the requests with
previous changes, some aditional tests are needed to continue supporting
optional power and nch. (previous objects were created with null
or default values)
user may enter requests without specifying these fields, in this
case the object 'output-power' or 'max-nb-of-channel' do not exist.
the try /except form handles the corresponding exception and
default values are kept else.

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:42 +01:00
EstherLerouzic
e7084a2c29 correction to support empty vectors of constraints
change the naming according to model update +
previous changes authorize empty list of nodes.
This new test supports this case

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
d79d2e0724 change the way transponder and mode are returned in the response
previous way used a wrong interpretation of hop-type. in ietf model,
hop-type is reserved for LOOSE or STRICT constraint description.
Instead, transponder info , according to ietf usual way, should be
included aas a new path-route-object type. such object is not yet
defined in IETF so this is a GNPY proposal to use a 'transponder' object
with type and mode attributes.
this is what has been ecncoded in reques.py for requests and for answers

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
402155c225 change the 'no path' case answer
in case no path could be computed, the answer is changed according to
ietf path-computation model to a simple 'no-path' object

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
e5ec669419 applying changes in the request dict creation
+ removing (currently) unused direction attribute.
This will be added again in a later PR when it will be used

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
8f424e8c9d correction of json generation: removing unused objects
- removing empty objects (if no content , removes the object),
    especially
  - removing empty synchronization vector if no disjunction
    constraint exists
  - removing optional power and nb of channel fields, if user
    did not specify any
when reading, first try if the object exists : try:/except to catch
this case
Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
EstherLerouzic
fea2b84bb9 correction of the json generation for path computation
- changes concerning names due to ietf path-computation draft changes:
        - 'unnumbered-hop' changed to 'num-unnum-hop'
        - suppression of 'label-hop'
        - 'link-diverse' and 'node-diverse' changed to 'disjointness'
      - correction because of previously wrong interpretation of the model:
        - detailed succession on include nodes moved from
          'optimisation /explicit-route-include-objects'
          to 'route-object-include-exclude'
          in 'explicit-route-objects' attribute
      - correction of keywords
        - n and m replaced by N and M
        - strict and loose replaces by STRICT and LOOSE strings
        - change the name of respponse from 'path' to 'response'
    example service file  corrected accordingly

Signed-off-by: EstherLerouzic <esther.lerouzic@orange.com>
2019-10-09 15:38:41 +01:00
Jan Kundrát
0c918940c4 Merge pull request #313 from jktjkt/codacy-assert
codacy: do not complain about asserts in the test suite
2019-10-06 21:49:22 +00:00
Jan Kundrát
a63a6ac0ec codacy: do not complain about asserts in the test suite
Writing an explicit comparison followed by argument printing *and*
handling the final error is just backwards. Let the tool be quiet, this
nonsense does not really add any value.
2019-10-06 23:12:09 +02:00
Jan Kundrát
9f58b914d2 Merge pull request #308 from jktjkt/osnr-bw-printing
Rework OSNR printing
2019-10-06 19:17:46 +00:00
Jan Kundrát
029bac4b03 utils: more descriptive name for itufl
This might have nothing to do with the ITU frequency grid (it's really
just about a uniform distribution), so let's give it a more readable
name and more readable parameters.
2019-10-06 20:43:50 +02:00
Jan Kundrát
a27ad57220 Do not use confusing default values
This looks like the root cause of bug #243, the default values suggested
that this function works in THz.

These defaults are not used anywhere, so let's get rid of something
which adds no value and actively confuses people.
2019-10-06 20:38:31 +02:00
Jan Kundrát
8d31d924f2 Remove unused function 2019-10-06 20:37:24 +02:00
Jan Kundrát
8c3b514f90 Only print out "pretty summary" when not doing the power sweep 2019-10-01 15:24:40 +02:00
Jan Kundrát
3df27fe315 Print both ASE-OSNR and final GSNR for both 0.1nm and signal-bw in power sweep
As agreed upon during today's coders call, this is something that is
needed by actual users in the field, so let's prioritize their needs
over clarity of output for demo purposes.
2019-10-01 15:21:34 +02:00
Jan Kundrát
a6087ce354 Highlight OSNR @ 0.1nm
Esther and Jonas pointed out that it is much more common to work with
OSNR measurements per 0.1nm rather than per signal bandwidth. This is in
line with what OSAs usually report and what transponder datasheets
specify.

cc #307
2019-09-27 09:22:08 +02:00
Jan Kundrát
aae0382523 docs: show a DOI
As per Alessio's request, this adds a DOI and makes this software
citeable. DOIs are assigned automatically via Zenodo in a process that's
integrated with GitHub.
2019-09-23 18:11:44 +01:00
18 changed files with 1613 additions and 736 deletions

1
.bandit Normal file
View File

@@ -0,0 +1 @@
skips: ['B101']

View File

@@ -7,7 +7,7 @@
`gnpy`: mesh optical network route planning and optimization library `gnpy`: mesh optical network route planning and optimization library
==================================================================== ====================================================================
|docs| |build| |docs| |build| |doi|
**`gnpy` is an open-source, community-developed library for building route **`gnpy` is an open-source, community-developed library for building route
planning and optimization tools in real-world mesh optical networks.** planning and optimization tools in real-world mesh optical networks.**
@@ -601,6 +601,11 @@ implementations.
:alt: Build Status :alt: Build Status
:scale: 100% :scale: 100%
.. |doi| image:: https://zenodo.org/badge/96894149.svg
:target: https://zenodo.org/badge/latestdoi/96894149
:alt: DOI
:scale: 100%
TIP OOPT/PSE & PSE WG Charter TIP OOPT/PSE & PSE WG Charter
----------------------------- -----------------------------

View File

@@ -2,8 +2,8 @@
"path-request": [ "path-request": [
{ {
"request-id": "0", "request-id": "0",
"source": "Lorient_KMA", "source": "trx Lorient_KMA",
"destination": "Vannes_KBE", "destination": "trx Vannes_KBE",
"src-tp-id": "trx Lorient_KMA", "src-tp-id": "trx Lorient_KMA",
"dst-tp-id": "trx Vannes_KBE", "dst-tp-id": "trx Vannes_KBE",
"path-constraints": { "path-constraints": {
@@ -13,8 +13,8 @@
"trx_mode": null, "trx_mode": null,
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 50000000000.0, "spacing": 50000000000.0,
@@ -22,15 +22,12 @@
"output-power": 0.0012589254117941673, "output-power": 0.0012589254117941673,
"path_bandwidth": 100000000000.0 "path_bandwidth": 100000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "1", "request-id": "1",
"source": "Brest_KLA", "source": "trx Brest_KLA",
"destination": "Vannes_KBE", "destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA", "src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE", "dst-tp-id": "trx Vannes_KBE",
"path-constraints": { "path-constraints": {
@@ -40,8 +37,8 @@
"trx_mode": "mode 1", "trx_mode": "mode 1",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 50000000000.0, "spacing": 50000000000.0,
@@ -50,66 +47,42 @@
"path_bandwidth": 200000000000.0 "path_bandwidth": 200000000000.0
} }
}, },
"optimizations": { "explicit-route-objects": {
"explicit-route-include-objects": [ "route-object-include-exclude": [
{ {
"explicit-route-usage": "route-include-ero",
"index": 0, "index": 0,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm Brest_KLA", "node-id": "roadm Brest_KLA",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 1, "index": 1,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm Lannion_CAS", "node-id": "roadm Lannion_CAS",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 2, "index": 2,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm Lorient_KMA", "node-id": "roadm Lorient_KMA",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 3, "index": 3,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm Vannes_KBE", "node-id": "roadm Vannes_KBE",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
} }
] ]
@@ -117,8 +90,8 @@
}, },
{ {
"request-id": "3", "request-id": "3",
"source": "Lannion_CAS", "source": "trx Lannion_CAS",
"destination": "Rennes_STA", "destination": "trx Rennes_STA",
"src-tp-id": "trx Lannion_CAS", "src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Rennes_STA", "dst-tp-id": "trx Rennes_STA",
"path-constraints": { "path-constraints": {
@@ -128,8 +101,8 @@
"trx_mode": "mode 1", "trx_mode": "mode 1",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 50000000000.0, "spacing": 50000000000.0,
@@ -137,15 +110,12 @@
"output-power": null, "output-power": null,
"path_bandwidth": 60000000000.0 "path_bandwidth": 60000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "4", "request-id": "4",
"source": "Rennes_STA", "source": "trx Rennes_STA",
"destination": "Lannion_CAS", "destination": "trx Lannion_CAS",
"src-tp-id": "trx Rennes_STA", "src-tp-id": "trx Rennes_STA",
"dst-tp-id": "trx Lannion_CAS", "dst-tp-id": "trx Lannion_CAS",
"path-constraints": { "path-constraints": {
@@ -155,8 +125,8 @@
"trx_mode": null, "trx_mode": null,
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 75000000000.0, "spacing": 75000000000.0,
@@ -164,15 +134,12 @@
"output-power": 0.0019952623149688794, "output-power": 0.0019952623149688794,
"path_bandwidth": 150000000000.0 "path_bandwidth": 150000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "5", "request-id": "5",
"source": "Rennes_STA", "source": "trx Rennes_STA",
"destination": "Lannion_CAS", "destination": "trx Lannion_CAS",
"src-tp-id": "trx Rennes_STA", "src-tp-id": "trx Rennes_STA",
"dst-tp-id": "trx Lannion_CAS", "dst-tp-id": "trx Lannion_CAS",
"path-constraints": { "path-constraints": {
@@ -182,8 +149,8 @@
"trx_mode": "mode 2", "trx_mode": "mode 2",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 75000000000.0, "spacing": 75000000000.0,
@@ -191,15 +158,12 @@
"output-power": 0.0019952623149688794, "output-power": 0.0019952623149688794,
"path_bandwidth": 20000000000.0 "path_bandwidth": 20000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "6", "request-id": "6",
"source": "Lannion_CAS", "source": "trx Lannion_CAS",
"destination": "Lorient_KMA", "destination": "trx Lorient_KMA",
"src-tp-id": "trx Lannion_CAS", "src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Lorient_KMA", "dst-tp-id": "trx Lorient_KMA",
"path-constraints": { "path-constraints": {
@@ -209,8 +173,8 @@
"trx_mode": "mode 1", "trx_mode": "mode 1",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 50000000000.0, "spacing": 50000000000.0,
@@ -218,15 +182,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "7", "request-id": "7",
"source": "Lannion_CAS", "source": "trx Lannion_CAS",
"destination": "Lorient_KMA", "destination": "trx Lorient_KMA",
"src-tp-id": "trx Lannion_CAS", "src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Lorient_KMA", "dst-tp-id": "trx Lorient_KMA",
"path-constraints": { "path-constraints": {
@@ -236,8 +197,8 @@
"trx_mode": "mode 1", "trx_mode": "mode 1",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 50000000000.0, "spacing": 50000000000.0,
@@ -245,15 +206,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 400000000000.0 "path_bandwidth": 400000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "7b", "request-id": "7b",
"source": "Lannion_CAS", "source": "trx Lannion_CAS",
"destination": "Lorient_KMA", "destination": "trx Lorient_KMA",
"src-tp-id": "trx Lannion_CAS", "src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Lorient_KMA", "dst-tp-id": "trx Lorient_KMA",
"path-constraints": { "path-constraints": {
@@ -263,8 +221,8 @@
"trx_mode": "mode 1", "trx_mode": "mode 1",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 75000000000.0, "spacing": 75000000000.0,
@@ -272,9 +230,6 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 400000000000.0 "path_bandwidth": 400000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
} }
], ],
@@ -282,9 +237,8 @@
{ {
"synchronization-id": "3", "synchronization-id": "3",
"svec": { "svec": {
"relaxable": "False", "relaxable": "false",
"link-diverse": "True", "disjointness": "node link",
"node-diverse": "True",
"request-id-number": [ "request-id-number": [
"3", "3",
"1" "1"
@@ -294,9 +248,8 @@
{ {
"synchronization-id": "4", "synchronization-id": "4",
"svec": { "svec": {
"relaxable": "False", "relaxable": "false",
"link-diverse": "True", "disjointness": "node link",
"node-diverse": "True",
"request-id-number": [ "request-id-number": [
"4", "4",
"5" "5"

View File

@@ -55,16 +55,18 @@ def requests_from_json(json_data,equipment):
# init all params from request # init all params from request
params = {} params = {}
params['request_id'] = req['request-id'] params['request_id'] = req['request-id']
params['source'] = req['src-tp-id'] params['source'] = req['source']
params['destination'] = req['dst-tp-id'] params['destination'] = req['destination']
params['trx_type'] = req['path-constraints']['te-bandwidth']['trx_type'] params['trx_type'] = req['path-constraints']['te-bandwidth']['trx_type']
params['trx_mode'] = req['path-constraints']['te-bandwidth']['trx_mode'] params['trx_mode'] = req['path-constraints']['te-bandwidth']['trx_mode']
params['format'] = params['trx_mode'] params['format'] = params['trx_mode']
nd_list = req['optimizations']['explicit-route-include-objects']
params['nodes_list'] = [n['unnumbered-hop']['node-id'] for n in nd_list]
params['loose_list'] = [n['unnumbered-hop']['hop-type'] for n in nd_list]
params['spacing'] = req['path-constraints']['te-bandwidth']['spacing'] params['spacing'] = req['path-constraints']['te-bandwidth']['spacing']
try :
nd_list = req['explicit-route-objects']['route-object-include-exclude']
except KeyError:
nd_list = []
params['nodes_list'] = [n['num-unnum-hop']['node-id'] for n in nd_list]
params['loose_list'] = [n['num-unnum-hop']['hop-type'] for n in nd_list]
# recover trx physical param (baudrate, ...) from type and mode # recover trx physical param (baudrate, ...) from type and mode
# in trx_mode_params optical power is read from equipment['SI']['default'] and # in trx_mode_params optical power is read from equipment['SI']['default'] and
# nb_channel is computed based on min max frequency and spacing # nb_channel is computed based on min max frequency and spacing
@@ -73,20 +75,24 @@ def requests_from_json(json_data,equipment):
# print(trx_params['min_spacing']) # print(trx_params['min_spacing'])
# optical power might be set differently in the request. if it is indicated then the # optical power might be set differently in the request. if it is indicated then the
# params['power'] is updated # params['power'] is updated
if req['path-constraints']['te-bandwidth']['output-power']: try:
params['power'] = req['path-constraints']['te-bandwidth']['output-power'] if req['path-constraints']['te-bandwidth']['output-power']:
params['power'] = req['path-constraints']['te-bandwidth']['output-power']
except KeyError:
pass
# same process for nb-channel # same process for nb-channel
f_min = params['f_min'] f_min = params['f_min']
f_max_from_si = params['f_max'] f_max_from_si = params['f_max']
if req['path-constraints']['te-bandwidth']['max-nb-of-channel'] is not None : try:
nch = req['path-constraints']['te-bandwidth']['max-nb-of-channel'] if req['path-constraints']['te-bandwidth']['max-nb-of-channel'] is not None:
params['nb_channel'] = nch nch = req['path-constraints']['te-bandwidth']['max-nb-of-channel']
spacing = params['spacing'] params['nb_channel'] = nch
params['f_max'] = f_min + nch*spacing spacing = params['spacing']
else : params['f_max'] = f_min + nch*spacing
else :
params['nb_channel'] = automatic_nch(f_min,f_max_from_si,params['spacing'])
except KeyError:
params['nb_channel'] = automatic_nch(f_min,f_max_from_si,params['spacing']) params['nb_channel'] = automatic_nch(f_min,f_max_from_si,params['spacing'])
consistency_check(params, f_max_from_si) consistency_check(params, f_max_from_si)
try : try :
@@ -122,15 +128,20 @@ def consistency_check(params, f_max_from_si):
def disjunctions_from_json(json_data): def disjunctions_from_json(json_data):
disjunctions_list = [] disjunctions_list = []
try:
temp_test = json_data['synchronization']
except KeyError:
temp_test = []
if temp_test:
for snc in json_data['synchronization']:
params = {}
params['disjunction_id'] = snc['synchronization-id']
params['relaxable'] = snc['svec']['relaxable']
params['link_diverse'] = 'link' in snc['svec']['disjointness']
params['node_diverse'] = 'node' in snc['svec']['disjointness']
params['disjunctions_req'] = snc['svec']['request-id-number']
disjunctions_list.append(Disjunction(**params))
for snc in json_data['synchronization']:
params = {}
params['disjunction_id'] = snc['synchronization-id']
params['relaxable'] = snc['svec']['relaxable']
params['link_diverse'] = snc['svec']['link-diverse']
params['node_diverse'] = snc['svec']['node-diverse']
params['disjunctions_req'] = snc['svec']['request-id-number']
disjunctions_list.append(Disjunction(**params))
return disjunctions_list return disjunctions_list
@@ -205,7 +216,7 @@ def correct_route_list(network, pathreqlist):
# prepares the format of route list of nodes to be consistant # prepares the format of route list of nodes to be consistant
# remove wrong names, remove endpoints # remove wrong names, remove endpoints
# also correct source and destination # also correct source and destination
anytype = [n.uid for n in network.nodes() if not isinstance(n, Transceiver) and not isinstance(n, Fiber)] anytype = [n.uid for n in network.nodes()]
# TODO there is a problem of identification of fibers in case of parallel fibers bitween two adjacent roadms # TODO there is a problem of identification of fibers in case of parallel fibers bitween two adjacent roadms
# so fiber constraint is not supported # so fiber constraint is not supported
transponders = [n.uid for n in network.nodes() if isinstance(n, Transceiver)] transponders = [n.uid for n in network.nodes() if isinstance(n, Transceiver)]
@@ -214,9 +225,11 @@ def correct_route_list(network, pathreqlist):
# replace possibly wrong name with a formated roadm name # replace possibly wrong name with a formated roadm name
# print(n_id) # print(n_id)
if n_id not in anytype : if n_id not in anytype :
# find nodes name that include constraint among all possible names except
# transponders (not yet supported as constraints).
nodes_suggestion = [uid for uid in anytype \ nodes_suggestion = [uid for uid in anytype \
if n_id.lower() in uid.lower()] if n_id.lower() in uid.lower() and uid not in transponders]
if pathreq.loose_list[i] == 'loose': if pathreq.loose_list[i] == 'LOOSE':
if len(nodes_suggestion)>0 : if len(nodes_suggestion)>0 :
new_n = nodes_suggestion[0] new_n = nodes_suggestion[0]
print(f'invalid route node specified:\ print(f'invalid route node specified:\
@@ -257,7 +270,7 @@ def correct_disjn(disjn):
def path_result_json(pathresult): def path_result_json(pathresult):
data = { data = {
'path': [n.json for n in pathresult] 'response': [n.json for n in pathresult]
} }
return data return data

View File

@@ -157,11 +157,13 @@ def main(network, equipment, source, destination, sim_params, req=None):
if len(power_range) == 1: if len(power_range) == 1:
for elem in path: for elem in path:
print(elem) print(elem)
if power_mode: if power_mode:
print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f} dBm:') print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f} dBm:')
else:
print(f'\nTransmission results:')
print(f' Final SNR total (0.1 nm): {ansi_escapes.cyan}{mean(destination.snr_01nm):.02f} dB{ansi_escapes.reset}')
else: else:
print(f'\nTransmission results:') print(path[-1])
print(f' Final SNR total (signal bw): {ansi_escapes.cyan}{mean(destination.snr):.02f} dB{ansi_escapes.reset}')
#print(f'\n !!!!!!!!!!!!!!!!! TEST POINT !!!!!!!!!!!!!!!!!!!!!') #print(f'\n !!!!!!!!!!!!!!!!! TEST POINT !!!!!!!!!!!!!!!!!!!!!')
#print(f'carriers ase output of {path[1]} =\n {list(path[1].carriers("out", "nli"))}') #print(f'carriers ase output of {path[1]} =\n {list(path[1].carriers("out", "nli"))}')

View File

@@ -25,7 +25,7 @@ from collections import namedtuple
from gnpy.core.node import Node from gnpy.core.node import Node
from gnpy.core.units import UNITS from gnpy.core.units import UNITS
from gnpy.core.utils import lin2db, db2lin, itufs, itufl, snr_sum from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
from gnpy.core.science_utils import propagate_raman_fiber, _psi from gnpy.core.science_utils import propagate_raman_fiber, _psi
class Transceiver(Node): class Transceiver(Node):
@@ -615,7 +615,7 @@ class Edfa(Node):
self.channel_freq, self.nf, self.interpol_dgt and self.interpol_gain_ripple self.channel_freq, self.nf, self.interpol_dgt and self.interpol_gain_ripple
""" """
# TODO|jla: read amplifier actual frequencies from additional params in json # TODO|jla: read amplifier actual frequencies from additional params in json
amplifier_freq = itufl(len(self.params.dgt), self.params.f_min, self.params.f_max) # Hz amplifier_freq = arrange_frequencies(len(self.params.dgt), self.params.f_min, self.params.f_max) # Hz
self.channel_freq = frequencies self.channel_freq = frequencies
self.interpol_dgt = interp(self.channel_freq, amplifier_freq, self.params.dgt) self.interpol_dgt = interp(self.channel_freq, amplifier_freq, self.params.dgt)

View File

@@ -81,9 +81,9 @@ class Path_request:
f'baud_rate:\t{temp} Gbaud', f'baud_rate:\t{temp} Gbaud',
f'bit_rate:\t{temp2} Gb/s', f'bit_rate:\t{temp2} Gb/s',
f'spacing:\t{self.spacing * 1e-9} GHz', f'spacing:\t{self.spacing * 1e-9} GHz',
f'power: \t{round(lin2db(self.power)+30,2)} dBm', f'power: \t{round(lin2db(self.power)+30, 2)} dBm',
f'nb channels: \t{self.nb_channel}', f'nb channels: \t{self.nb_channel}',
f'path_bandwidth: \t{round(self.path_bandwidth * 1e-9,2)} Gbit/s', f'path_bandwidth: \t{round(self.path_bandwidth * 1e-9, 2)} Gbit/s',
f'nodes-list:\t{self.nodes_list}', f'nodes-list:\t{self.nodes_list}',
f'loose-list:\t{self.loose_list}' f'loose-list:\t{self.loose_list}'
'\n']) '\n'])
@@ -97,16 +97,16 @@ class Disjunction:
self.disjunctions_req = params.disjunctions_req self.disjunctions_req = params.disjunctions_req
def __str__(self): def __str__(self):
return '\n\t'.join([f'relaxable: {self.relaxable}', return '\n\t'.join([f'relaxable: {self.relaxable}',
f'link-diverse: {self.link_diverse}', f'link-diverse: {self.link_diverse}',
f'node-diverse: {self.node_diverse}', f'node-diverse: {self.node_diverse}',
f'request-id-numbers: {self.disjunctions_req}'] f'request-id-numbers: {self.disjunctions_req}']
) )
def __repr__(self): def __repr__(self):
return '\n\t'.join([ f'{type(self).__name__} {self.disjunction_id}', return '\n\t'.join([ f'{type(self).__name__} {self.disjunction_id}',
f'relaxable: {self.relaxable}', f'relaxable: {self.relaxable}',
f'link-diverse: {self.link_diverse}', f'link-diverse: {self.link_diverse}',
f'node-diverse: {self.node_diverse}', f'node-diverse: {self.node_diverse}',
f'request-id-numbers: {self.disjunctions_req}' f'request-id-numbers: {self.disjunctions_req}'
'\n']) '\n'])
@@ -115,149 +115,77 @@ class Result_element(Element):
self.path_id = path_request.request_id self.path_id = path_request.request_id
self.path_request = path_request self.path_request = path_request
self.computed_path = computed_path self.computed_path = computed_path
hop_type = []
if len(computed_path)>0 :
for e in computed_path :
if isinstance(e, Transceiver) :
hop_type.append(' - '.join([path_request.tsp,path_request.tsp_mode]))
else:
hop_type.append('not recorded')
else:
# TODO differentiate empty path in case not feasible because of tsp or not feasible because
# ther is no path connecting the nodes (whatever the tsp)
mode = 'not feasible with this transponder'
hop_type = ' - '.join([path_request.tsp,mode])
self.hop_type = hop_type
uid = property(lambda self: repr(self)) uid = property(lambda self: repr(self))
@property @property
def pathresult(self): def pathresult(self):
if not self.computed_path: if not self.computed_path:
return { return {
'path-id': self.path_id, 'response-id': self.path_id,
'path-properties':{ 'no-path': "Response without path information, due to failure performing the path computation"
'path-metric': [ }
{ else:
'metric-type': 'SNR@bandwidth', index = 0
'accumulative-value': 'None' pro_list = []
}, for element in self.computed_path:
{ temp = {
'metric-type': 'SNR@0.1nm', 'path-route-object': {
'accumulative-value': 'None' 'index': index,
}, 'num-unnum-hop': {
{ 'node-id': element.uid,
'metric-type': 'OSNR@bandwidth', 'link-tp-id': element.uid,
'accumulative-value': 'None' # TODO change index in order to insert transponder attribute
}, }
{ }
'metric-type': 'OSNR@0.1nm', }
'accumulative-value': 'None' pro_list.append(temp)
}, index += 1
{ if isinstance(element, Transceiver):
'metric-type': 'reference_power', temp = {
'accumulative-value': self.path_request.power 'path-route-object': {
}, 'index': index,
{ 'transponder' : {
'metric-type': 'path_bandwidth', 'transponder-type' : self.path_request.tsp,
'accumulative-value': self.path_request.path_bandwidth 'transponder-mode' : self.path_request.tsp_mode,
}
],
'path-srlgs': {
'usage': 'not used yet',
'values': 'not used yet'
},
'path-route-objects': [
{
'path-route-object': {
'index': 0,
'unnumbered-hop': {
'node-id': self.path_request.source,
'link-tp-id': self.path_request.source,
'hop-type': self.hop_type,
'direction': 'not used'
},
'label-hop': {
'te-label': {
'generic': 'not used yet',
'direction': 'not used yet'
}
}
}
},
{
'path-route-object': {
'index': 1,
'unnumbered-hop': {
'node-id': self.path_request.destination,
'link-tp-id': self.path_request.destination,
'hop-type': self.hop_type,
'direction': 'not used'
},
'label-hop': {
'te-label': {
'generic': 'not used yet',
'direction': 'not used yet'
}
}
} }
} }
] }
} pro_list.append(temp)
} index += 1
else:
return { response = {
'path-id': self.path_id, 'response-id': self.path_id,
'path-properties':{ 'path-properties':{
'path-metric': [ 'path-metric': [
{ {
'metric-type': 'SNR@bandwidth', 'metric-type': 'SNR-bandwidth',
'accumulative-value': round(mean(self.computed_path[-1].snr),2) 'accumulative-value': round(mean(self.computed_path[-1].snr), 2)
},
{
'metric-type': 'SNR@0.1nm',
'accumulative-value': round(mean(self.computed_path[-1].snr+lin2db(self.path_request.baud_rate/12.5e9)),2)
},
{
'metric-type': 'OSNR@bandwidth',
'accumulative-value': round(mean(self.computed_path[-1].osnr_ase),2)
},
{
'metric-type': 'OSNR@0.1nm',
'accumulative-value': round(mean(self.computed_path[-1].osnr_ase_01nm),2)
},
{
'metric-type': 'reference_power',
'accumulative-value': self.path_request.power
},
{
'metric-type': 'path_bandwidth',
'accumulative-value': self.path_request.path_bandwidth
}
],
'path-srlgs': {
'usage': 'not used yet',
'values': 'not used yet'
}, },
'path-route-objects': [ {
{ 'metric-type': 'SNR-0.1nm',
'path-route-object': { 'accumulative-value': round(mean(self.computed_path[-1]. snr + \
'index': self.computed_path.index(n), lin2db(self.path_request.baud_rate/12.5e9)), 2)
'unnumbered-hop': { },
'node-id': n.uid, {
'link-tp-id': n.uid, 'metric-type': 'OSNR-bandwidth',
'hop-type': self.hop_type[self.computed_path.index(n)], 'accumulative-value': round(mean(self.computed_path[-1].osnr_ase), 2)
'direction': 'not used' },
}, {
'label-hop': { 'metric-type': 'OSNR-0.1nm',
'te-label': { 'accumulative-value': round(mean(self.computed_path[-1].osnr_ase_01nm), 2)
'generic': 'not used yet', },
'direction': 'not used yet' {
} 'metric-type': 'reference_power',
} 'accumulative-value': self.path_request.power
} },
} for n in self.computed_path {
] 'metric-type': 'path_bandwidth',
'accumulative-value': self.path_request.path_bandwidth
}
],
'path-route-objects': pro_list
} }
} }
return response
@property @property
def json(self): def json(self):
@@ -304,7 +232,7 @@ def compute_constrained_path(network, req):
msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path from {source.uid} to node : {destination.uid} in network topology'+ '\x1b[0m' msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path from {source.uid} to node : {destination.uid} in network topology'+ '\x1b[0m'
logger.critical(msg) logger.critical(msg)
print(msg) print(msg)
total_path = [] total_path = []
else : else :
all_simp_pths = list(all_simple_paths(network,source=source,\ all_simp_pths = list(all_simple_paths(network,source=source,\
target=destination, cutoff=120)) target=destination, cutoff=120))
@@ -319,12 +247,26 @@ def compute_constrained_path(network, req):
candidate.sort(key=lambda x: sum(network.get_edge_data(x[i],x[i+1])['weight'] for i in range(len(x)-2))) candidate.sort(key=lambda x: sum(network.get_edge_data(x[i],x[i+1])['weight'] for i in range(len(x)-2)))
total_path = candidate[0] total_path = candidate[0]
else: else:
if req.loose_list[req.nodes_list.index(n)] == 'loose': # TODO: better account for individual loose and strict node
print(f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path crossing {nodes_list} in network topology'+ '\x1b[0m') # to ease: suppose that one strict makes the whole liste strict (except for the
# last node which is the transceiver)
# if all nodes i n node_list are LOOSE constraint, skip the constraints and find
# a path w/o constraints, else there is no possible path
if nodes_list[:-len("STRICT")]:
print(f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path crossing ' +\
f'{[el.uid for el in nodes_list[:-len("STRICT")]]} in network topology'+ '\x1b[0m')
else:
print(f'\x1b[1;33;40m'+f'User include_node constraints could not be applied ' +\
f'(invalid names specified)'+ '\x1b[0m')
if 'STRICT' not in req.loose_list[:-len('STRICT')]:
msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path with user_' +\
f'include node constraints' + '\x1b[0m'
logger.info(msg)
print(f'constraint ignored') print(f'constraint ignored')
total_path = dijkstra_path(network, source, destination, weight = 'weight') total_path = dijkstra_path(network, source, destination, weight = 'weight')
else: else:
msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path crossing {nodes_list}.\nNo path computed'+ '\x1b[0m' msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path with user ' +\
f'include node constraints.\nNo path computed'+ '\x1b[0m'
logger.critical(msg) logger.critical(msg)
print(msg) print(msg)
total_path = [] total_path = []
@@ -418,7 +360,7 @@ def propagate_and_optimize_mode(path, req, equipment):
# if mode is unknown : loops on the modes starting from the highest baudrate fiting in the # if mode is unknown : loops on the modes starting from the highest baudrate fiting in the
# step 1: create an ordered list of modes based on baudrate # step 1: create an ordered list of modes based on baudrate
baudrate_to_explore = list(set([m['baud_rate'] for m in equipment['Transceiver'][req.tsp].mode baudrate_to_explore = list(set([m['baud_rate'] for m in equipment['Transceiver'][req.tsp].mode
if float(m['min_spacing'])<= req.spacing])) if float(m['min_spacing'])<= req.spacing]))
# TODO be carefull on limits cases if spacing very close to req spacing eg 50.001 50.000 # TODO be carefull on limits cases if spacing very close to req spacing eg 50.001 50.000
baudrate_to_explore = sorted(baudrate_to_explore, reverse=True) baudrate_to_explore = sorted(baudrate_to_explore, reverse=True)
if baudrate_to_explore : if baudrate_to_explore :
@@ -468,65 +410,91 @@ def jsontocsv(json_data,equipment,fileout):
# and write results in an CSV file # and write results in an CSV file
mywriter = writer(fileout) mywriter = writer(fileout)
mywriter.writerow(('path-id','source','destination','path_bandwidth','Pass?',\ mywriter.writerow(('response-id','source','destination','path_bandwidth','Pass?',\
'nb of tsp pairs','total cost','transponder-type','transponder-mode',\ 'nb of tsp pairs','total cost','transponder-type','transponder-mode',\
'OSNR@0.1nm','SNR@0.1nm','SNR@bandwidth','baud rate (Gbaud)',\ 'OSNR-0.1nm','SNR-0.1nm','SNR-bandwidth','baud rate (Gbaud)',\
'input power (dBm)','path')) 'input power (dBm)','path'))
tspjsondata = equipment['Transceiver'] tspjsondata = equipment['Transceiver']
#print(tspjsondata) #print(tspjsondata)
for p in json_data['path']:
path_id = p['path-id']
source = p['path-properties']['path-route-objects'][0]\
['path-route-object']['unnumbered-hop']['node-id']
destination = p['path-properties']['path-route-objects'][-1]\
['path-route-object']['unnumbered-hop']['node-id']
# selects only roadm nodes
pth = ' | '.join([ e['path-route-object']['unnumbered-hop']['node-id']
for e in p['path-properties']['path-route-objects']
if e['path-route-object']['unnumbered-hop']['node-id'].startswith('roadm') or e['path-route-object']['unnumbered-hop']['node-id'].startswith('Edfa')])
[tsp,mode] = p['path-properties']['path-route-objects'][0]\ for pth_el in json_data['response']:
['path-route-object']['unnumbered-hop']['hop-type'].split(' - ') path_id = pth_el['response-id']
try:
if pth_el['no-path'] :
source = ''
destination = ''
tsp = ''
mode = ''
isok = False
nb_tsp = 0
pthbdbw = ''
rosnr = ''
rsnr = ''
rsnrb = ''
br = ''
pw = ''
total_cost = ''
pth = ''
except KeyError:
source = pth_el['path-properties']['path-route-objects'][0]\
['path-route-object']['num-unnum-hop']['node-id']
destination = pth_el['path-properties']['path-route-objects'][-2]\
['path-route-object']['num-unnum-hop']['node-id']
# selects only roadm nodes
temp = []
for e in pth_el['path-properties']['path-route-objects']:
try :
temp.append(e['path-route-object']['num-unnum-hop']['node-id'])
except KeyError:
pass
pth = ' | '.join(temp)
temp_tsp = pth_el['path-properties']['path-route-objects'][1]\
['path-route-object']['transponder']
tsp = temp_tsp['transponder-type']
mode = temp_tsp['transponder-mode']
# find the min acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format)
# loading equipment already tests the existence of tsp type and mode:
if mode !='not feasible with this transponder' :
[minosnr, baud_rate, bit_rate, cost] = next([m['OSNR'] , m['baud_rate'] , m['bit_rate'], m['cost']]
for m in equipment['Transceiver'][tsp].mode if m['format']==mode)
# else:
# [minosnr, baud_rate, bit_rate] = ['','','','']
output_snr = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'SNR-0.1nm')
output_snrbandwidth = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'SNR-bandwidth')
output_osnr = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'OSNR-0.1nm')
output_osnrbandwidth = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'OSNR-bandwidth')
power = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'reference_power')
path_bandwidth = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'path_bandwidth')
if isinstance(output_snr, str):
isok = False
nb_tsp = 0
pthbdbw = round(path_bandwidth*1e-9,2)
rosnr = ''
rsnr = ''
rsnrb = ''
br = ''
pw = ''
total_cost = ''
else:
isok = output_snr >= minosnr
nb_tsp = ceil(path_bandwidth / bit_rate)
pthbdbw = round(path_bandwidth*1e-9,2)
rosnr = round(output_osnr,2)
rsnr = round(output_snr,2)
rsnrb = round(output_snrbandwidth,2)
br = round(baud_rate*1e-9,2)
pw = round(lin2db(power)+30,2)
total_cost = nb_tsp * cost
# find the min acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format)
# loading equipment already tests the existence of tsp type and mode:
if mode !='not feasible with this transponder' :
[minosnr, baud_rate, bit_rate, cost] = next([m['OSNR'] , m['baud_rate'] , m['bit_rate'], m['cost']]
for m in equipment['Transceiver'][tsp].mode if m['format']==mode)
# else:
# [minosnr, baud_rate, bit_rate] = ['','','','']
output_snr = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@0.1nm')
output_snrbandwidth = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@bandwidth')
output_osnr = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@0.1nm')
output_osnrbandwidth = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@bandwidth')
power = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'reference_power')
path_bandwidth = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'path_bandwidth')
if isinstance(output_snr, str):
isok = False
nb_tsp = 0
pthbdbw = round(path_bandwidth*1e-9,2)
rosnr = ''
rsnr = ''
rsnrb = ''
br = ''
pw = ''
total_cost = ''
else:
isok = output_snr >= minosnr
nb_tsp = ceil(path_bandwidth / bit_rate)
pthbdbw = round(path_bandwidth*1e-9,2)
rosnr = round(output_osnr,2)
rsnr = round(output_snr,2)
rsnrb = round(output_snrbandwidth,2)
br = round(baud_rate*1e-9,2)
pw = round(lin2db(power)+30,2)
total_cost = nb_tsp * cost
mywriter.writerow((path_id, mywriter.writerow((path_id,
source, source,
destination, destination,
@@ -617,7 +585,7 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
all_simp_pths_reversed = [] all_simp_pths_reversed = []
for pth in all_simp_pths: for pth in all_simp_pths:
all_simp_pths_reversed.append(find_reversed_path(pth,network)) all_simp_pths_reversed.append(find_reversed_path(pth,network))
rqs[pathreq.request_id] = all_simp_pths rqs[pathreq.request_id] = all_simp_pths
temp =[] temp =[]
for p in all_simp_pths : for p in all_simp_pths :
# build a short list representing each roadm+direction with the first item # build a short list representing each roadm+direction with the first item
@@ -759,9 +727,10 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
testispartok = False testispartok = False
#break #break
else: else:
if 'loose' in allpaths[id(p)].req.loose_list: if 'LOOSE' in allpaths[id(p)].req.loose_list:
logger.info(f'Could not apply route constraint'+ logger.info(f'Could not apply route constraint'+
f'{allpaths[id(p)].req.nodes_list} on request {allpaths[id(p)].req.request_id}') f'{allpaths[id(p)].req.nodes_list} on request' +\
f' {allpaths[id(p)].req.request_id}')
else : else :
logger.info(f'removing last solution from candidate paths\n{sol}') logger.info(f'removing last solution from candidate paths\n{sol}')
testispartok = False testispartok = False
@@ -798,7 +767,7 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
for req in pathreqlist : for req in pathreqlist :
req.nodes_list.append(req.destination) req.nodes_list.append(req.destination)
# we assume that the destination is a strict constraint # we assume that the destination is a strict constraint
req.loose_list.append('strict') req.loose_list.append('STRICT')
if req in pathreqlist_simple: if req in pathreqlist_simple:
path_res_list.append(compute_constrained_path(network, req)) path_res_list.append(compute_constrained_path(network, req))
else: else:
@@ -890,19 +859,19 @@ def compare_reqs(req1,req2,disjlist) :
req1.format == req2.format and \ req1.format == req2.format and \
req1.OSNR == req2.OSNR and \ req1.OSNR == req2.OSNR and \
req1.roll_off == req2.roll_off and \ req1.roll_off == req2.roll_off and \
same_disj : same_disj:
return True return True
else: else:
return False return False
def requests_aggregation(pathreqlist,disjlist) : def requests_aggregation(pathreqlist,disjlist):
# this function aggregates requests so that if several requests # this function aggregates requests so that if several requests
# exist between same source and destination and with same transponder type # exist between same source and destination and with same transponder type
# todo maybe add conditions on mode ??, spacing ... # todo maybe add conditions on mode ??, spacing ...
# currently if undefined takes the default values # currently if undefined takes the default values
local_list = pathreqlist.copy() local_list = pathreqlist.copy()
for req in pathreqlist: for req in pathreqlist:
for r in local_list : for r in local_list:
if req.request_id != r.request_id and compare_reqs(req, r, disjlist): if req.request_id != r.request_id and compare_reqs(req, r, disjlist):
# aggregate # aggregate
r.path_bandwidth += req.path_bandwidth r.path_bandwidth += req.path_bandwidth
@@ -912,12 +881,12 @@ def requests_aggregation(pathreqlist,disjlist) :
local_list.remove(req) local_list.remove(req)
# todo change also disjunction req with new demand # todo change also disjunction req with new demand
for d in disjlist : for d in disjlist:
if req.request_id in d.disjunctions_req : if req.request_id in d.disjunctions_req:
d.disjunctions_req.remove(req.request_id) d.disjunctions_req.remove(req.request_id)
d.disjunctions_req.append(r.request_id) d.disjunctions_req.append(r.request_id)
for d in disjlist : for d in disjlist:
if temp_r_id in d.disjunctions_req : if temp_r_id in d.disjunctions_req:
disjlist.remove(d) disjlist.remove(d)
break break
return local_list, disjlist return local_list, disjlist

View File

@@ -48,8 +48,8 @@ class Request_element(Element):
# excel has automatic number formatting that adds .0 on integer values # excel has automatic number formatting that adds .0 on integer values
# the next lines recover the pure int value, assuming this .0 is unwanted # the next lines recover the pure int value, assuming this .0 is unwanted
self.request_id = correct_xlrd_int_to_str_reading(Request.request_id) self.request_id = correct_xlrd_int_to_str_reading(Request.request_id)
self.source = Request.source self.source = f'trx {Request.source}'
self.destination = Request.destination self.destination = f'trx {Request.destination}'
# TODO: the automatic naming generated by excel parser requires that source and dest name # TODO: the automatic naming generated by excel parser requires that source and dest name
# be a string starting with 'trx' : this is manually added here. # be a string starting with 'trx' : this is manually added here.
self.srctpid = f'trx {Request.source}' self.srctpid = f'trx {Request.source}'
@@ -120,9 +120,9 @@ class Request_element(Element):
# the excel parser applies the same hop-type to all nodes in the route nodes_list. # the excel parser applies the same hop-type to all nodes in the route nodes_list.
# user can change this per node in the generated json # user can change this per node in the generated json
self.loose = 'loose' self.loose = 'LOOSE'
if Request.is_loose == 'no' : if Request.is_loose == 'no' :
self.loose = 'strict' self.loose = 'STRICT'
self.path_bandwidth = None self.path_bandwidth = None
if Request.path_bandwidth is not None: if Request.path_bandwidth is not None:
self.path_bandwidth = Request.path_bandwidth * 1e9 self.path_bandwidth = Request.path_bandwidth * 1e9
@@ -132,6 +132,7 @@ class Request_element(Element):
uid = property(lambda self: repr(self)) uid = property(lambda self: repr(self))
@property @property
def pathrequest(self): def pathrequest(self):
req_dictionnary = { req_dictionnary = {
'request-id':self.request_id, 'request-id':self.request_id,
'source': self.source, 'source': self.source,
@@ -143,35 +144,28 @@ class Request_element(Element):
'technology': 'flexi-grid', 'technology': 'flexi-grid',
'trx_type' : self.trx_type, 'trx_type' : self.trx_type,
'trx_mode' : self.mode, 'trx_mode' : self.mode,
'effective-freq-slot':[{'n': 'null','m': 'null'}] , 'effective-freq-slot':[{'N': 'null', 'M': 'null'}],
'spacing' : self.spacing, 'spacing' : self.spacing,
'max-nb-of-channel' : self.nb_channel, 'max-nb-of-channel' : self.nb_channel,
'output-power' : self.power 'output-power' : self.power
# 'path_bandwidth' : self.path_bandwidth
} }
}, }
'optimizations': { }
'explicit-route-include-objects': [
{ if self.nodes_list:
'index': self.nodes_list.index(node), req_dictionnary['explicit-route-objects'] = {}
'unnumbered-hop':{ temp = {'route-object-include-exclude' : [
'node-id': f'{node}', {'explicit-route-usage': 'route-include-ero',
'link-tp-id': 'link-tp-id is not used', 'index': self.nodes_list.index(node),
'hop-type': f'{self.loose}', 'num-unnum-hop': {
'direction': 'direction is not used' 'node-id': f'{node}',
}, 'link-tp-id': 'link-tp-id is not used',
'label-hop':{ 'hop-type': f'{self.loose}',
'te-label': {
'generic': 'generic is not used',
'direction': 'direction is not used'
}
} }
} }
for node in self.nodes_list for node in self.nodes_list]
] }
req_dictionnary['explicit-route-objects'] = temp
}
}
if self.path_bandwidth is not None: if self.path_bandwidth is not None:
req_dictionnary['path-constraints']['te-bandwidth']['path_bandwidth'] = self.path_bandwidth req_dictionnary['path-constraints']['te-bandwidth']['path_bandwidth'] = self.path_bandwidth
@@ -181,12 +175,13 @@ class Request_element(Element):
if self.disjoint_from : if self.disjoint_from :
return {'synchronization-id':self.request_id, return {'synchronization-id':self.request_id,
'svec': { 'svec': {
'relaxable' : 'False', 'relaxable' : 'false',
'link-diverse': 'True', 'disjointness': 'node link',
'node-diverse': 'True',
'request-id-number': [self.request_id]+ [n for n in self.disjoint_from] 'request-id-number': [self.request_id]+ [n for n in self.disjoint_from]
} }
} }
else:
return None
# TO-DO: avoid multiple entries with same synchronisation vectors # TO-DO: avoid multiple entries with same synchronisation vectors
@property @property
def json(self): def json(self):
@@ -201,11 +196,17 @@ def convert_service_sheet(input_filename, eqpt_filename, output_filename='', fil
output_filename = f'{str(input_filename)[0:len(str(input_filename))-len(str(input_filename.suffixes[0]))]}_services.json' output_filename = f'{str(input_filename)[0:len(str(input_filename))-len(str(input_filename.suffixes[0]))]}_services.json'
# for debug # for debug
# print(json_filename) # print(json_filename)
data = { # if there is no sync vector , do not write any synchronization
'path-request': [n.json[0] for n in req], synchro = [n.json[1] for n in req if n.json[1] is not None]
'synchronization': [n.json[1] for n in req if synchro:
if n.json[1] is not None] data = {
} 'path-request': [n.json[0] for n in req],
'synchronization': synchro
}
else:
data = {
'path-request': [n.json[0] for n in req]
}
with open(output_filename, 'w', encoding='utf-8') as f: with open(output_filename, 'w', encoding='utf-8') as f:
f.write(dumps(data, indent=2, ensure_ascii=False)) f.write(dumps(data, indent=2, ensure_ascii=False))
return data return data

View File

@@ -73,35 +73,19 @@ def c():
return constants.c return constants.c
def itufs(spacing, startf=191.35, stopf=196.10): def arrange_frequencies(length, start, stop):
"""Creates an array of frequencies whose default range is """Create an array of frequencies
191.35-196.10 THz
:param spacing: Frequency spacing in THz
:param starf: Start frequency in THz
:param stopf: Stop frequency in THz
:type spacing: float
:type startf: float
:type stopf: float
:return an array of frequnecies determined by the spacing parameter
:rtype: numpy.ndarray
"""
return np.arange(startf, stopf + spacing / 2, spacing)
def itufl(length, startf=191.35, stopf=196.10):
"""Creates an array of frequencies whose default range is
191.35-196.10 THz
:param length: number of elements :param length: number of elements
:param starf: Start frequency in THz :param star: Start frequency in THz
:param stopf: Stop frequency in THz :param stop: Stop frequency in THz
:type length: integer :type length: integer
:type startf: float :type start: float
:type stopf: float :type stop: float
:return an array of frequnecies determined by the spacing parameter :return an array of frequencies determined by the spacing parameter
:rtype: numpy.ndarray :rtype: numpy.ndarray
""" """
return np.linspace(startf, stopf, length) return np.linspace(start, stop, length)
def h(): def h():
""" """

View File

@@ -1,39 +1,63 @@
{ {
"paths": [ "response": [
{ {
"path": { "response-id": null,
"path-id": null, "path-properties": {
"path-properties": { "path-metric": [
"path-metric": [ {
{ "metric-type": "SNR@bandwidth",
"metric-type": null, "accumulative-value": null
"accumulative-value": null
}
],
"path-srlgs": {
"usage": "not used yet",
"values": ["not used yet"]
}, },
"path-route-objects": [ {
{ "metric-type": "SNR@0.1nm",
"path-route-object": { "accumulative-value": null
"index": null, },
"unnumbered-hop": { {
"node-id": null, "metric-type": "OSNR@bandwidth",
"link-tp-id": null, "accumulative-value": null
"hop-type": null, },
"direction": "not used" {
}, "metric-type": "OSNR@0.1nm",
"label-hop": { "accumulative-value": null
"te-label": { },
"generic": "not used yet", {
"direction": "not used yet" "metric-type": "reference_power",
} "accumulative-value": null
} },
{
"metric-type": "path_bandwidth",
"accumulative-value": null
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": null,
"link-tp-id": null
} }
} }
] },
} {
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": null,
"transponder-mode": null
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": null,
"link-tp-id": null
}
}
}
]
} }
} }
] ]

View File

@@ -2,6 +2,7 @@ alabaster>=0.7.12,<1
matplotlib>=3.1.0,<4 matplotlib>=3.1.0,<4
networkx>=2.3,<3 networkx>=2.3,<3
numpy>=1.16.1,<2 numpy>=1.16.1,<2
pandas==0.24.2
Pygments>=2.4.2,<3 Pygments>=2.4.2,<3
pytest>=4.0.0,<5 pytest>=4.0.0,<5
scipy>=1.3.0,<2 scipy>=1.3.0,<2

View File

@@ -6,6 +6,44 @@
"destination": null, "destination": null,
"src-tp-id": null, "src-tp-id": null,
"dst-tp-id": null, "dst-tp-id": null,
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": null,
"index": null,
"num-unnum-hop": {
"node-id": null,
"link-tp-id": null,
"hop-type": null
}
},
{
"explicit-route-usage": null,
"index": null,
"label-hop": {
"N": null,
"M": null
}
},
{
"explicit-route-usage": null,
"index": null,
"transponder": {
"transponder-type": null,
"transponder-mode": null
}
},
{
"explicit-route-usage": null,
"index": null,
"regenerator": {
"regenerator-id": null,
"transponder-type": null,
"transponder-mode": null
}
}
]
},
"path-constraints": { "path-constraints": {
"te-bandwidth": { "te-bandwidth": {
"technology": "flexi-grid", "technology": "flexi-grid",
@@ -22,27 +60,6 @@
"output-power": null, "output-power": null,
"path_bandwidth": null "path_bandwidth": null
} }
},
"optimizations": {
"explicit-route-include-objects": {
"route-object-include-object": [
{
"index": null,
"unnumbered-hop": {
"node-id": null,
"link-tp-id": "link-tp-id is not used",
"hop-type": null,
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
}
}
]
}
} }
}], }],
"synchronization": [ "synchronization": [
@@ -50,10 +67,9 @@
"synchronization-id": null, "synchronization-id": null,
"svec": { "svec": {
"relaxable": "True", "relaxable": "True",
"link-diverse": "False", "disjointness": "node link",
"node-diverse": "False",
"request-id-number": [ "request-id-number": [
null ] null, null ]
}, },
} }
] ]

Binary file not shown.

View File

@@ -0,0 +1,866 @@
{
"response": [
{
"response-id": "0",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 26.75
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 30.84
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 26.76
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 30.84
},
{
"metric-type": "reference_power",
"accumulative-value": 0.001
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 100000000000.0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Lorient_KMA",
"link-tp-id": "trx Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "Voyager",
"transponder-mode": "mode 1"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "Edfa1_roadm Lorient_KMA",
"link-tp-id": "Edfa1_roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Lorient_KMA → Vannes_KBE)-F055",
"link-tp-id": "fiber (Lorient_KMA → Vannes_KBE)-F055"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055",
"link-tp-id": "Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "roadm Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "trx Vannes_KBE",
"link-tp-id": "trx Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 8,
"transponder": {
"transponder-type": "Voyager",
"transponder-mode": "mode 1"
}
}
}
]
}
},
{
"response-id": "1",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 18.03
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 22.11
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 18.57
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 22.65
},
{
"metric-type": "reference_power",
"accumulative-value": 0.0012589254117941673
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Brest_KLA",
"link-tp-id": "trx Brest_KLA"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "Voyager",
"transponder-mode": "mode 1"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Brest_KLA",
"link-tp-id": "roadm Brest_KLA"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "Edfa0_roadm Brest_KLA",
"link-tp-id": "Edfa0_roadm Brest_KLA"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Brest_KLA → Morlaix)-F060",
"link-tp-id": "fiber (Brest_KLA → Morlaix)-F060"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "east fused spans in Morlaix",
"link-tp-id": "east fused spans in Morlaix"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "fiber (Morlaix → Lannion_CAS)-F059",
"link-tp-id": "fiber (Morlaix → Lannion_CAS)-F059"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "west edfa in Lannion_CAS to Morlaix",
"link-tp-id": "west edfa in Lannion_CAS to Morlaix"
}
}
},
{
"path-route-object": {
"index": 8,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "roadm Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 9,
"num-unnum-hop": {
"node-id": "east edfa in Lannion_CAS to Corlay",
"link-tp-id": "east edfa in Lannion_CAS to Corlay"
}
}
},
{
"path-route-object": {
"index": 10,
"num-unnum-hop": {
"node-id": "fiber (Lannion_CAS → Corlay)-F061",
"link-tp-id": "fiber (Lannion_CAS → Corlay)-F061"
}
}
},
{
"path-route-object": {
"index": 11,
"num-unnum-hop": {
"node-id": "west fused spans in Corlay",
"link-tp-id": "west fused spans in Corlay"
}
}
},
{
"path-route-object": {
"index": 12,
"num-unnum-hop": {
"node-id": "fiber (Corlay → Loudeac)-F010",
"link-tp-id": "fiber (Corlay → Loudeac)-F010"
}
}
},
{
"path-route-object": {
"index": 13,
"num-unnum-hop": {
"node-id": "west fused spans in Loudeac",
"link-tp-id": "west fused spans in Loudeac"
}
}
},
{
"path-route-object": {
"index": 14,
"num-unnum-hop": {
"node-id": "fiber (Loudeac → Lorient_KMA)-F054",
"link-tp-id": "fiber (Loudeac → Lorient_KMA)-F054"
}
}
},
{
"path-route-object": {
"index": 15,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Loudeac → Lorient_KMA)-F054",
"link-tp-id": "Edfa0_fiber (Loudeac → Lorient_KMA)-F054"
}
}
},
{
"path-route-object": {
"index": 16,
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 17,
"num-unnum-hop": {
"node-id": "Edfa1_roadm Lorient_KMA",
"link-tp-id": "Edfa1_roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 18,
"num-unnum-hop": {
"node-id": "fiber (Lorient_KMA → Vannes_KBE)-F055",
"link-tp-id": "fiber (Lorient_KMA → Vannes_KBE)-F055"
}
}
},
{
"path-route-object": {
"index": 19,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055",
"link-tp-id": "Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055"
}
}
},
{
"path-route-object": {
"index": 20,
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "roadm Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 21,
"num-unnum-hop": {
"node-id": "trx Vannes_KBE",
"link-tp-id": "trx Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 22,
"transponder": {
"transponder-type": "Voyager",
"transponder-mode": "mode 1"
}
}
}
]
}
},
{
"response-id": "3",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 21.77
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 25.85
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 24.2
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 28.29
},
{
"metric-type": "reference_power",
"accumulative-value": 0.0012589254117941673
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 60000000000.0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Lannion_CAS",
"link-tp-id": "trx Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 1"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "roadm Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "east edfa in Lannion_CAS to Stbrieuc",
"link-tp-id": "east edfa in Lannion_CAS to Stbrieuc"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Lannion_CAS → Stbrieuc)-F056",
"link-tp-id": "fiber (Lannion_CAS → Stbrieuc)-F056"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "east edfa in Stbrieuc to Rennes_STA",
"link-tp-id": "east edfa in Stbrieuc to Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "fiber (Stbrieuc → Rennes_STA)-F057",
"link-tp-id": "fiber (Stbrieuc → Rennes_STA)-F057"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Stbrieuc → Rennes_STA)-F057",
"link-tp-id": "Edfa0_fiber (Stbrieuc → Rennes_STA)-F057"
}
}
},
{
"path-route-object": {
"index": 8,
"num-unnum-hop": {
"node-id": "roadm Rennes_STA",
"link-tp-id": "roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 9,
"num-unnum-hop": {
"node-id": "trx Rennes_STA",
"link-tp-id": "trx Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 10,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 1"
}
}
}
]
}
},
{
"response-id": "4",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 15.05
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 22.15
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 15.18
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 22.27
},
{
"metric-type": "reference_power",
"accumulative-value": 0.001
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 150000000000.0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Rennes_STA",
"link-tp-id": "trx Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 2"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Rennes_STA",
"link-tp-id": "roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "Edfa1_roadm Rennes_STA",
"link-tp-id": "Edfa1_roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Rennes_STA → Ploermel)-",
"link-tp-id": "fiber (Rennes_STA → Ploermel)-"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "east edfa in Ploermel to Vannes_KBE",
"link-tp-id": "east edfa in Ploermel to Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "fiber (Ploermel → Vannes_KBE)-",
"link-tp-id": "fiber (Ploermel → Vannes_KBE)-"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Ploermel → Vannes_KBE)-",
"link-tp-id": "Edfa0_fiber (Ploermel → Vannes_KBE)-"
}
}
},
{
"path-route-object": {
"index": 8,
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "roadm Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 9,
"num-unnum-hop": {
"node-id": "Edfa0_roadm Vannes_KBE",
"link-tp-id": "Edfa0_roadm Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 10,
"num-unnum-hop": {
"node-id": "fiber (Vannes_KBE → Lorient_KMA)-F055",
"link-tp-id": "fiber (Vannes_KBE → Lorient_KMA)-F055"
}
}
},
{
"path-route-object": {
"index": 11,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Vannes_KBE → Lorient_KMA)-F055",
"link-tp-id": "Edfa0_fiber (Vannes_KBE → Lorient_KMA)-F055"
}
}
},
{
"path-route-object": {
"index": 12,
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 13,
"num-unnum-hop": {
"node-id": "Edfa0_roadm Lorient_KMA",
"link-tp-id": "Edfa0_roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 14,
"num-unnum-hop": {
"node-id": "fiber (Lorient_KMA → Loudeac)-F054",
"link-tp-id": "fiber (Lorient_KMA → Loudeac)-F054"
}
}
},
{
"path-route-object": {
"index": 15,
"num-unnum-hop": {
"node-id": "east fused spans in Loudeac",
"link-tp-id": "east fused spans in Loudeac"
}
}
},
{
"path-route-object": {
"index": 16,
"num-unnum-hop": {
"node-id": "fiber (Loudeac → Corlay)-F010",
"link-tp-id": "fiber (Loudeac → Corlay)-F010"
}
}
},
{
"path-route-object": {
"index": 17,
"num-unnum-hop": {
"node-id": "east fused spans in Corlay",
"link-tp-id": "east fused spans in Corlay"
}
}
},
{
"path-route-object": {
"index": 18,
"num-unnum-hop": {
"node-id": "fiber (Corlay → Lannion_CAS)-F061",
"link-tp-id": "fiber (Corlay → Lannion_CAS)-F061"
}
}
},
{
"path-route-object": {
"index": 19,
"num-unnum-hop": {
"node-id": "west edfa in Lannion_CAS to Corlay",
"link-tp-id": "west edfa in Lannion_CAS to Corlay"
}
}
},
{
"path-route-object": {
"index": 20,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "roadm Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 21,
"num-unnum-hop": {
"node-id": "trx Lannion_CAS",
"link-tp-id": "trx Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 22,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 2"
}
}
}
]
}
},
{
"response-id": "5",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 21.68
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 28.77
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 23.7
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 30.79
},
{
"metric-type": "reference_power",
"accumulative-value": 0.0019952623149688794
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 20000000000.0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Rennes_STA",
"link-tp-id": "trx Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 2"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Rennes_STA",
"link-tp-id": "roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "Edfa0_roadm Rennes_STA",
"link-tp-id": "Edfa0_roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Rennes_STA → Stbrieuc)-F057",
"link-tp-id": "fiber (Rennes_STA → Stbrieuc)-F057"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Rennes_STA → Stbrieuc)-F057",
"link-tp-id": "Edfa0_fiber (Rennes_STA → Stbrieuc)-F057"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "fiber (Stbrieuc → Lannion_CAS)-F056",
"link-tp-id": "fiber (Stbrieuc → Lannion_CAS)-F056"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Stbrieuc → Lannion_CAS)-F056",
"link-tp-id": "Edfa0_fiber (Stbrieuc → Lannion_CAS)-F056"
}
}
},
{
"path-route-object": {
"index": 8,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "roadm Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 9,
"num-unnum-hop": {
"node-id": "trx Lannion_CAS",
"link-tp-id": "trx Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 10,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 2"
}
}
}
]
}
},
{
"response-id": "6",
"no-path": "Response without path information, due to failure performing the path computation"
}
]
}

View File

@@ -0,0 +1,7 @@
response-id,source,destination,path_bandwidth,Pass?,nb of tsp pairs,total cost,transponder-type,transponder-mode,OSNR-0.1nm,SNR-0.1nm,SNR-bandwidth,baud rate (Gbaud),input power (dBm),path
0,trx Lorient_KMA,trx Vannes_KBE,100.0,True,1,1,Voyager,mode 1,30.84,30.84,26.75,32.0,0.0,trx Lorient_KMA | roadm Lorient_KMA | Edfa1_roadm Lorient_KMA | fiber (Lorient_KMA → Vannes_KBE)-F055 | Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055 | roadm Vannes_KBE | trx Vannes_KBE
1,trx Brest_KLA,trx Vannes_KBE,0.0,True,0,0,Voyager,mode 1,22.65,22.11,18.03,32.0,1.0,trx Brest_KLA | roadm Brest_KLA | Edfa0_roadm Brest_KLA | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | Edfa0_fiber (Loudeac → Lorient_KMA)-F054 | roadm Lorient_KMA | Edfa1_roadm Lorient_KMA | fiber (Lorient_KMA → Vannes_KBE)-F055 | Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055 | roadm Vannes_KBE | trx Vannes_KBE
3,trx Lannion_CAS,trx Rennes_STA,60.0,True,1,1,vendorA_trx-type1,mode 1,28.29,25.85,21.77,32.0,1.0,trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | Edfa0_fiber (Stbrieuc → Rennes_STA)-F057 | roadm Rennes_STA | trx Rennes_STA
4,trx Rennes_STA,trx Lannion_CAS,150.0,True,1,1,vendorA_trx-type1,mode 2,22.27,22.15,15.05,64.0,0.0,trx Rennes_STA | roadm Rennes_STA | Edfa1_roadm Rennes_STA | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | Edfa0_fiber (Ploermel → Vannes_KBE)- | roadm Vannes_KBE | Edfa0_roadm Vannes_KBE | fiber (Vannes_KBE → Lorient_KMA)-F055 | Edfa0_fiber (Vannes_KBE → Lorient_KMA)-F055 | roadm Lorient_KMA | Edfa0_roadm Lorient_KMA | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS
5,trx Rennes_STA,trx Lannion_CAS,20.0,True,1,1,vendorA_trx-type1,mode 2,30.79,28.77,21.68,64.0,3.0,trx Rennes_STA | roadm Rennes_STA | Edfa0_roadm Rennes_STA | fiber (Rennes_STA → Stbrieuc)-F057 | Edfa0_fiber (Rennes_STA → Stbrieuc)-F057 | fiber (Stbrieuc → Lannion_CAS)-F056 | Edfa0_fiber (Stbrieuc → Lannion_CAS)-F056 | roadm Lannion_CAS | trx Lannion_CAS
6,,,,False,0,,,,,,,,,
1 response-id source destination path_bandwidth Pass? nb of tsp pairs total cost transponder-type transponder-mode OSNR-0.1nm SNR-0.1nm SNR-bandwidth baud rate (Gbaud) input power (dBm) path
2 0 trx Lorient_KMA trx Vannes_KBE 100.0 True 1 1 Voyager mode 1 30.84 30.84 26.75 32.0 0.0 trx Lorient_KMA | roadm Lorient_KMA | Edfa1_roadm Lorient_KMA | fiber (Lorient_KMA → Vannes_KBE)-F055 | Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055 | roadm Vannes_KBE | trx Vannes_KBE
3 1 trx Brest_KLA trx Vannes_KBE 0.0 True 0 0 Voyager mode 1 22.65 22.11 18.03 32.0 1.0 trx Brest_KLA | roadm Brest_KLA | Edfa0_roadm Brest_KLA | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | Edfa0_fiber (Loudeac → Lorient_KMA)-F054 | roadm Lorient_KMA | Edfa1_roadm Lorient_KMA | fiber (Lorient_KMA → Vannes_KBE)-F055 | Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055 | roadm Vannes_KBE | trx Vannes_KBE
4 3 trx Lannion_CAS trx Rennes_STA 60.0 True 1 1 vendorA_trx-type1 mode 1 28.29 25.85 21.77 32.0 1.0 trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | Edfa0_fiber (Stbrieuc → Rennes_STA)-F057 | roadm Rennes_STA | trx Rennes_STA
5 4 trx Rennes_STA trx Lannion_CAS 150.0 True 1 1 vendorA_trx-type1 mode 2 22.27 22.15 15.05 64.0 0.0 trx Rennes_STA | roadm Rennes_STA | Edfa1_roadm Rennes_STA | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | Edfa0_fiber (Ploermel → Vannes_KBE)- | roadm Vannes_KBE | Edfa0_roadm Vannes_KBE | fiber (Vannes_KBE → Lorient_KMA)-F055 | Edfa0_fiber (Vannes_KBE → Lorient_KMA)-F055 | roadm Lorient_KMA | Edfa0_roadm Lorient_KMA | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS
6 5 trx Rennes_STA trx Lannion_CAS 20.0 True 1 1 vendorA_trx-type1 mode 2 30.79 28.77 21.68 64.0 3.0 trx Rennes_STA | roadm Rennes_STA | Edfa0_roadm Rennes_STA | fiber (Rennes_STA → Stbrieuc)-F057 | Edfa0_fiber (Rennes_STA → Stbrieuc)-F057 | fiber (Stbrieuc → Lannion_CAS)-F056 | Edfa0_fiber (Stbrieuc → Lannion_CAS)-F056 | roadm Lannion_CAS | trx Lannion_CAS
7 6 False 0

View File

@@ -2,8 +2,8 @@
"path-request": [ "path-request": [
{ {
"request-id": "0", "request-id": "0",
"source": "Lorient_KMA", "source": "trx Lorient_KMA",
"destination": "Vannes_KBE", "destination": "trx Vannes_KBE",
"src-tp-id": "trx Lorient_KMA", "src-tp-id": "trx Lorient_KMA",
"dst-tp-id": "trx Vannes_KBE", "dst-tp-id": "trx Vannes_KBE",
"path-constraints": { "path-constraints": {
@@ -13,8 +13,8 @@
"trx_mode": "mode 1", "trx_mode": "mode 1",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 50000000000.0, "spacing": 50000000000.0,
@@ -22,15 +22,12 @@
"output-power": null, "output-power": null,
"path_bandwidth": 100000000000.0 "path_bandwidth": 100000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "1", "request-id": "1",
"source": "Brest_KLA", "source": "trx Brest_KLA",
"destination": "Vannes_KBE", "destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA", "src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE", "dst-tp-id": "trx Vannes_KBE",
"path-constraints": { "path-constraints": {
@@ -40,8 +37,8 @@
"trx_mode": "mode 1", "trx_mode": "mode 1",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 50000000000.0, "spacing": 50000000000.0,
@@ -50,66 +47,42 @@
"path_bandwidth": 0 "path_bandwidth": 0
} }
}, },
"optimizations": { "explicit-route-objects": {
"explicit-route-include-objects": [ "route-object-include-exclude": [
{ {
"explicit-route-usage": "route-include-ero",
"index": 0, "index": 0,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm Brest_KLA", "node-id": "roadm Brest_KLA",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 1, "index": 1,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm Lannion_CAS", "node-id": "roadm Lannion_CAS",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 2, "index": 2,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm Lorient_KMA", "node-id": "roadm Lorient_KMA",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 3, "index": 3,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm Vannes_KBE", "node-id": "roadm Vannes_KBE",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
} }
] ]
@@ -117,8 +90,8 @@
}, },
{ {
"request-id": "3", "request-id": "3",
"source": "Lannion_CAS", "source": "trx Lannion_CAS",
"destination": "Rennes_STA", "destination": "trx Rennes_STA",
"src-tp-id": "trx Lannion_CAS", "src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Rennes_STA", "dst-tp-id": "trx Rennes_STA",
"path-constraints": { "path-constraints": {
@@ -128,8 +101,8 @@
"trx_mode": "mode 1", "trx_mode": "mode 1",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 50000000000.0, "spacing": 50000000000.0,
@@ -137,15 +110,12 @@
"output-power": 0.0012589254117941673, "output-power": 0.0012589254117941673,
"path_bandwidth": 60000000000.0 "path_bandwidth": 60000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "4", "request-id": "4",
"source": "Rennes_STA", "source": "trx Rennes_STA",
"destination": "Lannion_CAS", "destination": "trx Lannion_CAS",
"src-tp-id": "trx Rennes_STA", "src-tp-id": "trx Rennes_STA",
"dst-tp-id": "trx Lannion_CAS", "dst-tp-id": "trx Lannion_CAS",
"path-constraints": { "path-constraints": {
@@ -155,8 +125,8 @@
"trx_mode": "mode 2", "trx_mode": "mode 2",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 75000000000.0, "spacing": 75000000000.0,
@@ -164,15 +134,12 @@
"output-power": null, "output-power": null,
"path_bandwidth": 150000000000.0 "path_bandwidth": 150000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "5", "request-id": "5",
"source": "Rennes_STA", "source": "trx Rennes_STA",
"destination": "Lannion_CAS", "destination": "trx Lannion_CAS",
"src-tp-id": "trx Rennes_STA", "src-tp-id": "trx Rennes_STA",
"dst-tp-id": "trx Lannion_CAS", "dst-tp-id": "trx Lannion_CAS",
"path-constraints": { "path-constraints": {
@@ -182,8 +149,8 @@
"trx_mode": "mode 2", "trx_mode": "mode 2",
"effective-freq-slot": [ "effective-freq-slot": [
{ {
"n": "null", "N": "null",
"m": "null" "M": "null"
} }
], ],
"spacing": 75000000000.0, "spacing": 75000000000.0,
@@ -191,9 +158,30 @@
"output-power": 0.0019952623149688794, "output-power": 0.0019952623149688794,
"path_bandwidth": 20000000000.0 "path_bandwidth": 20000000000.0
} }
}, }
"optimizations": { },
"explicit-route-include-objects": [] {
"request-id": "6",
"source": "trx Lannion_CAS",
"destination": "trx a",
"src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx a",
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "vendorA_trx-type1",
"trx_mode": "mode 2",
"effective-freq-slot": [
{
"N": "null",
"M": "null"
}
],
"spacing": 75000000000.0,
"max-nb-of-channel": null,
"output-power": null,
"path_bandwidth": 100000000000.0
}
} }
} }
], ],
@@ -201,9 +189,8 @@
{ {
"synchronization-id": "3", "synchronization-id": "3",
"svec": { "svec": {
"relaxable": "False", "relaxable": "false",
"link-diverse": "True", "disjointness": "node link",
"node-diverse": "True",
"request-id-number": [ "request-id-number": [
"3", "3",
"1" "1"
@@ -213,9 +200,8 @@
{ {
"synchronization-id": "4", "synchronization-id": "4",
"svec": { "svec": {
"relaxable": "False", "relaxable": "false",
"link-diverse": "True", "disjointness": "node link",
"node-diverse": "True",
"request-id-number": [ "request-id-number": [
"4", "4",
"5" "5"

View File

@@ -2,8 +2,8 @@
"path-request": [ "path-request": [
{ {
"request-id": "1", "request-id": "1",
"source": "a", "source": "trx a",
"destination": "g", "destination": "trx g",
"src-tp-id": "trx a", "src-tp-id": "trx a",
"dst-tp-id": "trx g", "dst-tp-id": "trx g",
"path-constraints": { "path-constraints": {
@@ -22,15 +22,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "2a", "request-id": "2a",
"source": "a", "source": "trx a",
"destination": "h", "destination": "trx h",
"src-tp-id": "trx a", "src-tp-id": "trx a",
"dst-tp-id": "trx h", "dst-tp-id": "trx h",
"path-constraints": { "path-constraints": {
@@ -49,15 +46,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "3", "request-id": "3",
"source": "f", "source": "trx f",
"destination": "b", "destination": "trx b",
"src-tp-id": "trx f", "src-tp-id": "trx f",
"dst-tp-id": "trx b", "dst-tp-id": "trx b",
"path-constraints": { "path-constraints": {
@@ -76,15 +70,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "ee", "request-id": "ee",
"source": "c", "source": "trx c",
"destination": "f", "destination": "trx f",
"src-tp-id": "trx c", "src-tp-id": "trx c",
"dst-tp-id": "trx f", "dst-tp-id": "trx f",
"path-constraints": { "path-constraints": {
@@ -104,36 +95,23 @@
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
}, },
"optimizations": { "explicit-route-objects": {
"explicit-route-include-objects": [ "route-object-include-exclude": [
{ {
"explicit-route-usage": "route-include-ero",
"index": 0, "index": 0,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm e", "node-id": "roadm e",
"link-tp-id": "link-tp-id is not used", "hop-type": "LOOSE"
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 1, "index": 1,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm g", "node-id": "roadm g",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
} }
] ]
@@ -141,8 +119,8 @@
}, },
{ {
"request-id": "ff", "request-id": "ff",
"source": "c", "source": "trx c",
"destination": "f", "destination": "trx f",
"src-tp-id": "trx c", "src-tp-id": "trx c",
"dst-tp-id": "trx f", "dst-tp-id": "trx f",
"path-constraints": { "path-constraints": {
@@ -161,15 +139,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "10", "request-id": "10",
"source": "a", "source": "trx a",
"destination": "g", "destination": "trx g",
"src-tp-id": "trx a", "src-tp-id": "trx a",
"dst-tp-id": "trx g", "dst-tp-id": "trx g",
"path-constraints": { "path-constraints": {
@@ -188,15 +163,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "11", "request-id": "11",
"source": "a", "source": "trx a",
"destination": "h", "destination": "trx h",
"src-tp-id": "trx a", "src-tp-id": "trx a",
"dst-tp-id": "trx h", "dst-tp-id": "trx h",
"path-constraints": { "path-constraints": {
@@ -216,21 +188,15 @@
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
}, },
"optimizations": { "explicit-route-objects": {
"explicit-route-include-objects": [ "route-object-include-exclude": [
{ {
"explicit-route-usage": "route-include-ero",
"index": 0, "index": 0,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "bb", "node-id": "bb",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
} }
] ]
@@ -238,8 +204,8 @@
}, },
{ {
"request-id": "12", "request-id": "12",
"source": "f", "source": "trx f",
"destination": "b", "destination": "trx b",
"src-tp-id": "trx f", "src-tp-id": "trx f",
"dst-tp-id": "trx b", "dst-tp-id": "trx b",
"path-constraints": { "path-constraints": {
@@ -259,21 +225,15 @@
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
}, },
"optimizations": { "explicit-route-objects": {
"explicit-route-include-objects": [ "route-object-include-exclude": [
{ {
"explicit-route-usage": "route-include-ero",
"index": 0, "index": 0,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "trx b", "node-id": "trx b",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
} }
] ]
@@ -281,8 +241,8 @@
}, },
{ {
"request-id": "13", "request-id": "13",
"source": "c", "source": "trx c",
"destination": "f", "destination": "trx f",
"src-tp-id": "trx c", "src-tp-id": "trx c",
"dst-tp-id": "trx f", "dst-tp-id": "trx f",
"path-constraints": { "path-constraints": {
@@ -301,15 +261,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "14", "request-id": "14",
"source": "c", "source": "trx c",
"destination": "f", "destination": "trx f",
"src-tp-id": "trx c", "src-tp-id": "trx c",
"dst-tp-id": "trx f", "dst-tp-id": "trx f",
"path-constraints": { "path-constraints": {
@@ -329,36 +286,23 @@
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
}, },
"optimizations": { "explicit-route-objects": {
"explicit-route-include-objects": [ "route-object-include-exclude": [
{ {
"explicit-route-usage": "route-include-ero",
"index": 0, "index": 0,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm e", "node-id": "roadm e",
"link-tp-id": "link-tp-id is not used", "hop-type": "LOOSE"
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 1, "index": 1,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm g", "node-id": "roadm g",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
} }
] ]
@@ -366,8 +310,8 @@
}, },
{ {
"request-id": "e:1# /", "request-id": "e:1# /",
"source": "a", "source": "trx a",
"destination": "g", "destination": "trx g",
"src-tp-id": "trx a", "src-tp-id": "trx a",
"dst-tp-id": "trx g", "dst-tp-id": "trx g",
"path-constraints": { "path-constraints": {
@@ -386,15 +330,12 @@
"output-power": null, "output-power": null,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "b-2a", "request-id": "b-2a",
"source": "a", "source": "trx a",
"destination": "h", "destination": "trx h",
"src-tp-id": "trx a", "src-tp-id": "trx a",
"dst-tp-id": "trx h", "dst-tp-id": "trx h",
"path-constraints": { "path-constraints": {
@@ -413,15 +354,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "3a;?", "request-id": "3a;?",
"source": "f", "source": "trx f",
"destination": "b", "destination": "trx b",
"src-tp-id": "trx f", "src-tp-id": "trx f",
"dst-tp-id": "trx b", "dst-tp-id": "trx b",
"path-constraints": { "path-constraints": {
@@ -440,15 +378,12 @@
"output-power": null, "output-power": null,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "ee-s", "request-id": "ee-s",
"source": "c", "source": "trx c",
"destination": "f", "destination": "trx f",
"src-tp-id": "trx c", "src-tp-id": "trx c",
"dst-tp-id": "trx f", "dst-tp-id": "trx f",
"path-constraints": { "path-constraints": {
@@ -468,36 +403,23 @@
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
}, },
"optimizations": { "explicit-route-objects": {
"explicit-route-include-objects": [ "route-object-include-exclude": [
{ {
"explicit-route-usage": "route-include-ero",
"index": 0, "index": 0,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm e", "node-id": "roadm e",
"link-tp-id": "link-tp-id is not used", "hop-type": "LOOSE"
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
}, },
{ {
"explicit-route-usage": "route-include-ero",
"index": 1, "index": 1,
"unnumbered-hop": { "num-unnum-hop": {
"node-id": "roadm g", "node-id": "roadm g",
"link-tp-id": "link-tp-id is not used", "link-tp-id": "link-tp-id is not used",
"hop-type": "loose", "hop-type": "LOOSE"
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
} }
} }
] ]
@@ -505,8 +427,8 @@
}, },
{ {
"request-id": "ff-b", "request-id": "ff-b",
"source": "c", "source": "trx c",
"destination": "f", "destination": "trx f",
"src-tp-id": "trx c", "src-tp-id": "trx c",
"dst-tp-id": "trx f", "dst-tp-id": "trx f",
"path-constraints": { "path-constraints": {
@@ -525,15 +447,12 @@
"output-power": 0.001, "output-power": 0.001,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "10-z", "request-id": "10-z",
"source": "a", "source": "trx a",
"destination": "g", "destination": "trx g",
"src-tp-id": "trx a", "src-tp-id": "trx a",
"dst-tp-id": "trx g", "dst-tp-id": "trx g",
"path-constraints": { "path-constraints": {
@@ -552,15 +471,12 @@
"output-power": null, "output-power": null,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "11 g", "request-id": "11 g",
"source": "a", "source": "trx a",
"destination": "h", "destination": "trx h",
"src-tp-id": "trx a", "src-tp-id": "trx a",
"dst-tp-id": "trx h", "dst-tp-id": "trx h",
"path-constraints": { "path-constraints": {
@@ -579,15 +495,12 @@
"output-power": null, "output-power": null,
"path_bandwidth": 300000000000.0 "path_bandwidth": 300000000000.0
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "12<", "request-id": "12<",
"source": "f", "source": "trx f",
"destination": "b", "destination": "trx b",
"src-tp-id": "trx f", "src-tp-id": "trx f",
"dst-tp-id": "trx b", "dst-tp-id": "trx b",
"path-constraints": { "path-constraints": {
@@ -606,15 +519,12 @@
"output-power": null, "output-power": null,
"path_bandwidth": null "path_bandwidth": null
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
}, },
{ {
"request-id": "12>", "request-id": "12>",
"source": "f", "source": "trx f",
"destination": "b", "destination": "trx b",
"src-tp-id": "trx f", "src-tp-id": "trx f",
"dst-tp-id": "trx b", "dst-tp-id": "trx b",
"path-constraints": { "path-constraints": {
@@ -633,9 +543,6 @@
"output-power": null, "output-power": null,
"path_bandwidth": null "path_bandwidth": null
} }
},
"optimizations": {
"explicit-route-include-objects": []
} }
} }
], ],
@@ -644,8 +551,7 @@
"synchronization-id": "1", "synchronization-id": "1",
"svec": { "svec": {
"relaxable": "False", "relaxable": "False",
"link-diverse": "True", "disjointness": "node link",
"node-diverse": "True",
"request-id-number": [ "request-id-number": [
"1", "1",
"2a" "2a"
@@ -656,8 +562,7 @@
"synchronization-id": "3", "synchronization-id": "3",
"svec": { "svec": {
"relaxable": "False", "relaxable": "False",
"link-diverse": "True", "disjointness": "node link",
"node-diverse": "True",
"request-id-number": [ "request-id-number": [
"3", "3",
"1" "1"
@@ -668,8 +573,7 @@
"synchronization-id": "ff", "synchronization-id": "ff",
"svec": { "svec": {
"relaxable": "False", "relaxable": "False",
"link-diverse": "True", "disjointness": "node link",
"node-diverse": "True",
"request-id-number": [ "request-id-number": [
"ff", "ff",
"13" "13"
@@ -680,8 +584,7 @@
"synchronization-id": "13", "synchronization-id": "13",
"svec": { "svec": {
"relaxable": "False", "relaxable": "False",
"link-diverse": "True", "disjointness": "node link",
"node-diverse": "True",
"request-id-number": [ "request-id-number": [
"13", "13",
"14" "14"

View File

@@ -3,38 +3,48 @@
# @Author: Esther Le Rouzic # @Author: Esther Le Rouzic
# @Date: 2018-06-15 # @Date: 2018-06-15
from gnpy.core.elements import Edfa """ Adding tests to check the parser non regression
import numpy as np convention of naming of test files:
- ..._expected.json for the reference output
tests:
- generation of topology json
- reading of Eqpt sheet w and W/ power mode
- consistency of autodesign
- generation of service list based on service sheet
- writing of results in csv
- writing of results in json (same keys)
"""
from json import load from json import load
from pathlib import Path
from os import unlink
from pandas import read_csv
import pytest import pytest
from gnpy.core import network_from_json
from gnpy.core.elements import Transceiver, Fiber, Edfa
from gnpy.core.utils import lin2db, db2lin
from gnpy.core.info import SpectralInformation, Channel, Power
from gnpy.core.network import save_network, build_network
from tests.compare import compare_networks, compare_services from tests.compare import compare_networks, compare_services
from gnpy.core.utils import lin2db
from gnpy.core.network import save_network, build_network
from gnpy.core.convert import convert_file from gnpy.core.convert import convert_file
from gnpy.core.service_sheet import convert_service_sheet from gnpy.core.service_sheet import convert_service_sheet
from gnpy.core.equipment import load_equipment, automatic_nch from gnpy.core.equipment import load_equipment, automatic_nch
from gnpy.core.network import load_network from gnpy.core.network import load_network
from pathlib import Path from gnpy.core.request import (jsontocsv, requests_aggregation,
import filecmp compute_path_dsjctn, Result_element)
from os import unlink from examples.path_requests_run import (requests_from_json, disjunctions_from_json,
correct_route_list, correct_disjn,
compute_path_with_disjunction)
TEST_DIR = Path(__file__).parent TEST_DIR = Path(__file__).parent
DATA_DIR = TEST_DIR / 'data' DATA_DIR = TEST_DIR / 'data'
eqpt_filename = DATA_DIR / 'eqpt_config.json' eqpt_filename = DATA_DIR / 'eqpt_config.json'
# adding tests to check the parser non regression
# convention of naming of test files:
#
# - ..._expected.json for the reference output
@pytest.mark.parametrize('xls_input,expected_json_output', { @pytest.mark.parametrize('xls_input,expected_json_output', {
DATA_DIR / 'CORONET_Global_Topology.xls': DATA_DIR / 'CORONET_Global_Topology_expected.json', DATA_DIR / 'CORONET_Global_Topology.xls': DATA_DIR / 'CORONET_Global_Topology_expected.json',
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_expected.json', DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_expected.json',
}.items()) }.items())
def test_excel_json_generation(xls_input, expected_json_output): def test_excel_json_generation(xls_input, expected_json_output):
""" tests generation of topology json
"""
convert_file(xls_input) convert_file(xls_input)
actual_json_output = xls_input.with_suffix('.json') actual_json_output = xls_input.with_suffix('.json')
@@ -55,20 +65,25 @@ def test_excel_json_generation(xls_input, expected_json_output):
# assume xls entries # assume xls entries
# test that the build network gives correct results in gain mode # test that the build network gives correct results in gain mode
#
@pytest.mark.parametrize('xls_input,expected_json_output', { @pytest.mark.parametrize('xls_input,expected_json_output',
DATA_DIR / 'CORONET_Global_Topology.xls': DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json', {DATA_DIR / 'CORONET_Global_Topology.xls':\
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_auto_design_expected.json', DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json',
}.items()) DATA_DIR / 'testTopology.xls':\
DATA_DIR / 'testTopology_auto_design_expected.json',
}.items())
def test_auto_design_generation_fromxlsgainmode(xls_input, expected_json_output): def test_auto_design_generation_fromxlsgainmode(xls_input, expected_json_output):
""" tests generation of topology json
test that the build network gives correct results in gain mode
"""
equipment = load_equipment(eqpt_filename) equipment = load_equipment(eqpt_filename)
network = load_network(xls_input,equipment) network = load_network(xls_input, equipment)
# in order to test the Eqpt sheet and load gain target, change the power-mode to False (to be in gain mode) # in order to test the Eqpt sheet and load gain target,
# change the power-mode to False (to be in gain mode)
equipment['Span']['default'].power_mode = False equipment['Span']['default'].power_mode = False
# Build the network once using the default power defined in SI in eqpt config # Build the network once using the default power defined in SI in eqpt config
p_db = equipment['SI']['default'].power_dbm p_db = equipment['SI']['default'].power_dbm
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\ p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
build_network(network, equipment, p_db, p_total_db) build_network(network, equipment, p_db, p_total_db)
@@ -92,19 +107,23 @@ def test_auto_design_generation_fromxlsgainmode(xls_input, expected_json_output)
assert not results.connections.different assert not results.connections.different
#test that autodesign creates same file as an input file already autodesigned #test that autodesign creates same file as an input file already autodesigned
@pytest.mark.parametrize('json_input,expected_json_output', { @pytest.mark.parametrize('json_input,expected_json_output',
DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json': DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json', {DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json':\
DATA_DIR / 'testTopology_auto_design_expected.json': DATA_DIR / 'testTopology_auto_design_expected.json', DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json',
}.items()) DATA_DIR / 'testTopology_auto_design_expected.json':\
DATA_DIR / 'testTopology_auto_design_expected.json',
}.items())
def test_auto_design_generation_fromjson(json_input, expected_json_output): def test_auto_design_generation_fromjson(json_input, expected_json_output):
"""test that autodesign creates same file as an input file already autodesigned
"""
equipment = load_equipment(eqpt_filename) equipment = load_equipment(eqpt_filename)
network = load_network(json_input,equipment) network = load_network(json_input, equipment)
# in order to test the Eqpt sheet and load gain target, change the power-mode to False (to be in gain mode) # in order to test the Eqpt sheet and load gain target,
# change the power-mode to False (to be in gain mode)
equipment['Span']['default'].power_mode = False equipment['Span']['default'].power_mode = False
# Build the network once using the default power defined in SI in eqpt config # Build the network once using the default power defined in SI in eqpt config
p_db = equipment['SI']['default'].power_dbm p_db = equipment['SI']['default'].power_dbm
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\ p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing)) equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
build_network(network, equipment, p_db, p_total_db) build_network(network, equipment, p_db, p_total_db)
@@ -131,8 +150,10 @@ def test_auto_design_generation_fromjson(json_input, expected_json_output):
@pytest.mark.parametrize('xls_input,expected_json_output', { @pytest.mark.parametrize('xls_input,expected_json_output', {
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_services_expected.json', DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_services_expected.json',
}.items()) }.items())
def test_excel_service_json_generation(xls_input, expected_json_output): def test_excel_service_json_generation(xls_input, expected_json_output):
""" test services creation
"""
convert_service_sheet(xls_input, eqpt_filename) convert_service_sheet(xls_input, eqpt_filename)
actual_json_output = f'{str(xls_input)[:-4]}_services.json' actual_json_output = f'{str(xls_input)[:-4]}_services.json'
@@ -150,3 +171,128 @@ def test_excel_service_json_generation(xls_input, expected_json_output):
assert not results.synchronizations.missing assert not results.synchronizations.missing
assert not results.synchronizations.extra assert not results.synchronizations.extra
assert not results.synchronizations.different assert not results.synchronizations.different
# test xls answers creation
@pytest.mark.parametrize('json_input, csv_output', {
DATA_DIR / 'testTopology_response.json': DATA_DIR / 'testTopology_response',
}.items())
def test_csv_response_generation(json_input, csv_output):
""" tests if generated csv is consistant with expected generation
same columns (order not important)
"""
with open(json_input) as jsonfile:
json_data = load(jsonfile)
equipment = load_equipment(eqpt_filename)
csv_filename = str(csv_output)+'.csv'
with open(csv_filename, 'w', encoding='utf-8') as fcsv:
jsontocsv(json_data, equipment, fcsv)
expected_csv_filename = str(csv_output)+'_expected.csv'
# expected header
# csv_header = \
# [
# 'response-id',
# 'source',
# 'destination',
# 'path_bandwidth',
# 'Pass?',
# 'nb of tsp pairs',
# 'total cost',
# 'transponder-type',
# 'transponder-mode',
# 'OSNR-0.1nm',
# 'SNR-0.1nm',
# 'SNR-bandwidth',
# 'baud rate (Gbaud)',
# 'input power (dBm)',
# 'path'
# ]
resp = read_csv(csv_filename)
unlink(csv_filename)
expected_resp = read_csv(expected_csv_filename)
resp_header = list(resp.head(0))
expected_resp_header = list(expected_resp.head(0))
# check that headers are the same
resp_header.sort()
expected_resp_header.sort()
print('headers are differents')
print(resp_header)
print(expected_resp_header)
assert resp_header == expected_resp_header
# for each header checks that the output are as expected
resp.sort_values(by=['response-id'])
expected_resp.sort_values(by=['response-id'])
for column in expected_resp:
assert list(resp[column].fillna('')) == list(expected_resp[column].fillna(''))
print('results are different')
print(list(resp[column]))
print(list(expected_resp[column]))
print(type(list(resp[column])[-1]))
def compare_response(exp_resp, act_resp):
""" False if the keys are different in the nested dicts as well
"""
print(exp_resp)
print(act_resp)
test = True
for key in act_resp.keys():
print(key)
if not key in exp_resp.keys():
print(key)
return False
if isinstance(act_resp[key], dict):
test = compare_response(exp_resp[key], act_resp[key])
if test:
for key in exp_resp.keys():
if not key in act_resp.keys():
print(key)
return False
if isinstance(exp_resp[key], dict):
test = compare_response(exp_resp[key], act_resp[key])
# at this point exp_resp and act_resp have the same keys. Check if their values are the same
for key in act_resp.keys():
if not isinstance(act_resp[key], dict):
if exp_resp[key] != act_resp[key]:
return False
return test
# test json answers creation
@pytest.mark.parametrize('xls_input, expected_response_file', {
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_response.json',
}.items())
def test_json_response_generation(xls_input, expected_response_file):
""" tests if json response is correctly generated for all combinations of requests
"""
data = convert_service_sheet(xls_input, eqpt_filename)
equipment = load_equipment(eqpt_filename)
network = load_network(xls_input, equipment)
p_db = equipment['SI']['default'].power_dbm
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
build_network(network, equipment, p_db, p_total_db)
rqs = requests_from_json(data, equipment)
rqs = correct_route_list(network, rqs)
dsjn = disjunctions_from_json(data)
dsjn = correct_disjn(dsjn)
rqs, dsjn = requests_aggregation(rqs, dsjn)
pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
propagatedpths = compute_path_with_disjunction(network, equipment, rqs, pths)
result = []
for i, pth in enumerate(propagatedpths):
result.append(Result_element(rqs[i], pth))
temp = {
'response': [n.json for n in result]
}
# load expected result and compare keys
# (not values at this stage)
with open(expected_response_file) as jsonfile:
expected = load(jsonfile)
for i, response in enumerate(temp['response']):
assert compare_response(expected['response'][i], response)