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
====================================================================
|docs| |build|
|docs| |build| |doi|
**`gnpy` is an open-source, community-developed library for building route
planning and optimization tools in real-world mesh optical networks.**
@@ -601,6 +601,11 @@ implementations.
:alt: Build Status
: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
-----------------------------

View File

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

View File

@@ -55,16 +55,18 @@ def requests_from_json(json_data,equipment):
# init all params from request
params = {}
params['request_id'] = req['request-id']
params['source'] = req['src-tp-id']
params['destination'] = req['dst-tp-id']
params['source'] = req['source']
params['destination'] = req['destination']
params['trx_type'] = req['path-constraints']['te-bandwidth']['trx_type']
params['trx_mode'] = req['path-constraints']['te-bandwidth']['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']
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
# in trx_mode_params optical power is read from equipment['SI']['default'] and
# nb_channel is computed based on min max frequency and spacing
@@ -73,12 +75,15 @@ def requests_from_json(json_data,equipment):
# print(trx_params['min_spacing'])
# optical power might be set differently in the request. if it is indicated then the
# params['power'] is updated
try:
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
f_min = params['f_min']
f_max_from_si = params['f_max']
try:
if req['path-constraints']['te-bandwidth']['max-nb-of-channel'] is not None:
nch = req['path-constraints']['te-bandwidth']['max-nb-of-channel']
params['nb_channel'] = nch
@@ -86,7 +91,8 @@ def requests_from_json(json_data,equipment):
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'])
consistency_check(params, f_max_from_si)
try :
@@ -122,15 +128,20 @@ def consistency_check(params, f_max_from_si):
def disjunctions_from_json(json_data):
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'] = snc['svec']['link-diverse']
params['node_diverse'] = snc['svec']['node-diverse']
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))
return disjunctions_list
@@ -205,7 +216,7 @@ def correct_route_list(network, pathreqlist):
# prepares the format of route list of nodes to be consistant
# remove wrong names, remove endpoints
# 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
# so fiber constraint is not supported
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
# print(n_id)
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 \
if n_id.lower() in uid.lower()]
if pathreq.loose_list[i] == 'loose':
if n_id.lower() in uid.lower() and uid not in transponders]
if pathreq.loose_list[i] == 'LOOSE':
if len(nodes_suggestion)>0 :
new_n = nodes_suggestion[0]
print(f'invalid route node specified:\
@@ -257,7 +270,7 @@ def correct_disjn(disjn):
def path_result_json(pathresult):
data = {
'path': [n.json for n in pathresult]
'response': [n.json for n in pathresult]
}
return data

View File

@@ -161,7 +161,9 @@ def main(network, equipment, source, destination, sim_params, req=None):
print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f} dBm:')
else:
print(f'\nTransmission results:')
print(f' Final SNR total (signal bw): {ansi_escapes.cyan}{mean(destination.snr):.02f} dB{ansi_escapes.reset}')
print(f' Final SNR total (0.1 nm): {ansi_escapes.cyan}{mean(destination.snr_01nm):.02f} dB{ansi_escapes.reset}')
else:
print(path[-1])
#print(f'\n !!!!!!!!!!!!!!!!! TEST POINT !!!!!!!!!!!!!!!!!!!!!')
#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.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
class Transceiver(Node):
@@ -615,7 +615,7 @@ class Edfa(Node):
self.channel_freq, self.nf, self.interpol_dgt and self.interpol_gain_ripple
"""
# 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.interpol_dgt = interp(self.channel_freq, amplifier_freq, self.params.dgt)

View File

@@ -115,113 +115,62 @@ class Result_element(Element):
self.path_id = path_request.request_id
self.path_request = path_request
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))
@property
def pathresult(self):
if not self.computed_path:
return {
'path-id': self.path_id,
'path-properties':{
'path-metric': [
{
'metric-type': 'SNR@bandwidth',
'accumulative-value': 'None'
},
{
'metric-type': 'SNR@0.1nm',
'accumulative-value': 'None'
},
{
'metric-type': 'OSNR@bandwidth',
'accumulative-value': 'None'
},
{
'metric-type': 'OSNR@0.1nm',
'accumulative-value': 'None'
},
{
'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': [
{
'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'
}
}
}
}
]
}
'response-id': self.path_id,
'no-path': "Response without path information, due to failure performing the path computation"
}
else:
return {
'path-id': self.path_id,
index = 0
pro_list = []
for element in self.computed_path:
temp = {
'path-route-object': {
'index': index,
'num-unnum-hop': {
'node-id': element.uid,
'link-tp-id': element.uid,
# TODO change index in order to insert transponder attribute
}
}
}
pro_list.append(temp)
index += 1
if isinstance(element, Transceiver):
temp = {
'path-route-object': {
'index': index,
'transponder' : {
'transponder-type' : self.path_request.tsp,
'transponder-mode' : self.path_request.tsp_mode,
}
}
}
pro_list.append(temp)
index += 1
response = {
'response-id': self.path_id,
'path-properties':{
'path-metric': [
{
'metric-type': 'SNR@bandwidth',
'metric-type': 'SNR-bandwidth',
'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': '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',
'metric-type': 'OSNR-bandwidth',
'accumulative-value': round(mean(self.computed_path[-1].osnr_ase), 2)
},
{
'metric-type': 'OSNR@0.1nm',
'metric-type': 'OSNR-0.1nm',
'accumulative-value': round(mean(self.computed_path[-1].osnr_ase_01nm), 2)
},
{
@@ -233,31 +182,10 @@ class Result_element(Element):
'accumulative-value': self.path_request.path_bandwidth
}
],
'path-srlgs': {
'usage': 'not used yet',
'values': 'not used yet'
},
'path-route-objects': [
{
'path-route-object': {
'index': self.computed_path.index(n),
'unnumbered-hop': {
'node-id': n.uid,
'link-tp-id': n.uid,
'hop-type': self.hop_type[self.computed_path.index(n)],
'direction': 'not used'
},
'label-hop': {
'te-label': {
'generic': 'not used yet',
'direction': 'not used yet'
}
}
}
} for n in self.computed_path
]
'path-route-objects': pro_list
}
}
return response
@property
def json(self):
@@ -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)))
total_path = candidate[0]
else:
if req.loose_list[req.nodes_list.index(n)] == 'loose':
print(f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path crossing {nodes_list} in network topology'+ '\x1b[0m')
# TODO: better account for individual loose and strict node
# 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')
total_path = dijkstra_path(network, source, destination, weight = 'weight')
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)
print(msg)
total_path = []
@@ -468,25 +410,50 @@ def jsontocsv(json_data,equipment,fileout):
# and write results in an CSV file
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',\
'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'))
tspjsondata = equipment['Transceiver']
#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]\
['path-route-object']['unnumbered-hop']['hop-type'].split(' - ')
for pth_el in json_data['response']:
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:
@@ -496,17 +463,17 @@ def jsontocsv(json_data,equipment,fileout):
# 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')
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 p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@bandwidth')
for e in pth_el['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')
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 p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@bandwidth')
for e in pth_el['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')
for e in pth_el['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')
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
@@ -527,6 +494,7 @@ def jsontocsv(json_data,equipment,fileout):
br = round(baud_rate*1e-9,2)
pw = round(lin2db(power)+30,2)
total_cost = nb_tsp * cost
mywriter.writerow((path_id,
source,
destination,
@@ -759,9 +727,10 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
testispartok = False
#break
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'+
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 :
logger.info(f'removing last solution from candidate paths\n{sol}')
testispartok = False
@@ -798,7 +767,7 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
for req in pathreqlist :
req.nodes_list.append(req.destination)
# we assume that the destination is a strict constraint
req.loose_list.append('strict')
req.loose_list.append('STRICT')
if req in pathreqlist_simple:
path_res_list.append(compute_constrained_path(network, req))
else:

View File

@@ -48,8 +48,8 @@ class Request_element(Element):
# excel has automatic number formatting that adds .0 on integer values
# 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.source = Request.source
self.destination = Request.destination
self.source = f'trx {Request.source}'
self.destination = f'trx {Request.destination}'
# 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.
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.
# user can change this per node in the generated json
self.loose = 'loose'
self.loose = 'LOOSE'
if Request.is_loose == 'no' :
self.loose = 'strict'
self.loose = 'STRICT'
self.path_bandwidth = None
if Request.path_bandwidth is not None:
self.path_bandwidth = Request.path_bandwidth * 1e9
@@ -132,6 +132,7 @@ class Request_element(Element):
uid = property(lambda self: repr(self))
@property
def pathrequest(self):
req_dictionnary = {
'request-id':self.request_id,
'source': self.source,
@@ -143,35 +144,28 @@ class Request_element(Element):
'technology': 'flexi-grid',
'trx_type' : self.trx_type,
'trx_mode' : self.mode,
'effective-freq-slot':[{'n': 'null','m': 'null'}] ,
'effective-freq-slot':[{'N': 'null', 'M': 'null'}],
'spacing' : self.spacing,
'max-nb-of-channel' : self.nb_channel,
'output-power' : self.power
# 'path_bandwidth' : self.path_bandwidth
}
},
'optimizations': {
'explicit-route-include-objects': [
{
}
}
if self.nodes_list:
req_dictionnary['explicit-route-objects'] = {}
temp = {'route-object-include-exclude' : [
{'explicit-route-usage': 'route-include-ero',
'index': self.nodes_list.index(node),
'unnumbered-hop':{
'num-unnum-hop': {
'node-id': f'{node}',
'link-tp-id': 'link-tp-id is not used',
'hop-type': f'{self.loose}',
'direction': 'direction is not used'
},
'label-hop':{
'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:
req_dictionnary['path-constraints']['te-bandwidth']['path_bandwidth'] = self.path_bandwidth
@@ -181,12 +175,13 @@ class Request_element(Element):
if self.disjoint_from :
return {'synchronization-id':self.request_id,
'svec': {
'relaxable' : 'False',
'link-diverse': 'True',
'node-diverse': 'True',
'relaxable' : 'false',
'disjointness': 'node link',
'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
@property
def json(self):
@@ -201,10 +196,16 @@ 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'
# for debug
# print(json_filename)
# if there is no sync vector , do not write any synchronization
synchro = [n.json[1] for n in req if n.json[1] is not None]
if synchro:
data = {
'path-request': [n.json[0] for n in req],
'synchronization': [n.json[1] for n in req
if n.json[1] is not None]
'synchronization': synchro
}
else:
data = {
'path-request': [n.json[0] for n in req]
}
with open(output_filename, 'w', encoding='utf-8') as f:
f.write(dumps(data, indent=2, ensure_ascii=False))

View File

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

View File

@@ -1,40 +1,64 @@
{
"paths": [
"response": [
{
"path": {
"path-id": null,
"response-id": null,
"path-properties": {
"path-metric": [
{
"metric-type": null,
"metric-type": "SNR@bandwidth",
"accumulative-value": null
},
{
"metric-type": "SNR@0.1nm",
"accumulative-value": null
},
{
"metric-type": "OSNR@bandwidth",
"accumulative-value": null
},
{
"metric-type": "OSNR@0.1nm",
"accumulative-value": null
},
{
"metric-type": "reference_power",
"accumulative-value": null
},
{
"metric-type": "path_bandwidth",
"accumulative-value": null
}
],
"path-srlgs": {
"usage": "not used yet",
"values": ["not used yet"]
},
"path-route-objects": [
{
"path-route-object": {
"index": null,
"unnumbered-hop": {
"index": 0,
"num-unnum-hop": {
"node-id": null,
"link-tp-id": null,
"hop-type": null,
"direction": "not used"
"link-tp-id": null
}
}
},
"label-hop": {
"te-label": {
"generic": "not used yet",
"direction": "not used yet"
{
"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
networkx>=2.3,<3
numpy>=1.16.1,<2
pandas==0.24.2
Pygments>=2.4.2,<3
pytest>=4.0.0,<5
scipy>=1.3.0,<2

View File

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

View File

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

View File

@@ -3,38 +3,48 @@
# @Author: Esther Le Rouzic
# @Date: 2018-06-15
from gnpy.core.elements import Edfa
import numpy as np
""" Adding tests to check the parser non regression
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 pathlib import Path
from os import unlink
from pandas import read_csv
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 gnpy.core.utils import lin2db
from gnpy.core.network import save_network, build_network
from gnpy.core.convert import convert_file
from gnpy.core.service_sheet import convert_service_sheet
from gnpy.core.equipment import load_equipment, automatic_nch
from gnpy.core.network import load_network
from pathlib import Path
import filecmp
from os import unlink
from gnpy.core.request import (jsontocsv, requests_aggregation,
compute_path_dsjctn, Result_element)
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
DATA_DIR = TEST_DIR / 'data'
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', {
DATA_DIR / 'CORONET_Global_Topology.xls': DATA_DIR / 'CORONET_Global_Topology_expected.json',
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_expected.json',
}.items())
def test_excel_json_generation(xls_input, expected_json_output):
""" tests generation of topology json
"""
convert_file(xls_input)
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
# test that the build network gives correct results in gain mode
#
@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 / 'testTopology.xls': DATA_DIR / 'testTopology_auto_design_expected.json',
@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 / 'testTopology.xls':\
DATA_DIR / 'testTopology_auto_design_expected.json',
}.items())
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)
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
# Build the network once using the default power defined in SI in eqpt config
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)
@@ -92,19 +107,23 @@ def test_auto_design_generation_fromxlsgainmode(xls_input, expected_json_output)
assert not results.connections.different
#test that autodesign creates same file as an input file already autodesigned
@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 / 'testTopology_auto_design_expected.json': DATA_DIR / 'testTopology_auto_design_expected.json',
@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 / 'testTopology_auto_design_expected.json':\
DATA_DIR / 'testTopology_auto_design_expected.json',
}.items())
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)
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
# Build the network once using the default power defined in SI in eqpt config
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)
@@ -133,6 +152,8 @@ def test_auto_design_generation_fromjson(json_input, expected_json_output):
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_services_expected.json',
}.items())
def test_excel_service_json_generation(xls_input, expected_json_output):
""" test services creation
"""
convert_service_sheet(xls_input, eqpt_filename)
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.extra
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)