mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-10-29 09:12:37 +00:00
@@ -5,5 +5,7 @@ python:
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
# command to run tests
|
||||
before_script:
|
||||
- export PYTHONPATH=$PYTHONPATH:/home/travis/build/Orange-OpenSource/gnpy/examples
|
||||
script:
|
||||
- pytest
|
||||
|
||||
@@ -115,7 +115,7 @@ Eqpt sheet
|
||||
Eqt sheet is optional. It lists the amplifiers types and characteristics on each degree of the *Node A* line.
|
||||
Links sheet must contain sixteen columns::
|
||||
|
||||
<-- east cable from a to z --> <-- west from z to -->
|
||||
<-- east cable from a to z --> <-- west from z to a -->
|
||||
Node A ; Node Z ; amp type ; att_in ; amp gain ; tilt ; att_out ; amp type ; att_in ; amp gain ; tilt ; att_out
|
||||
|
||||
If the sheet is present, it MUST have as many lines as egress directions of ROADMs defined in Links Sheet.
|
||||
@@ -172,9 +172,80 @@ then Eqpt sheet should contain:
|
||||
|
||||
# to be completed #
|
||||
|
||||
|
||||
|
||||
(in progress)
|
||||
|
||||
Service sheet
|
||||
-------------
|
||||
|
||||
Service sheet is optional. It lists the services for which path and feasibility must be computed with path_requests_run.py.
|
||||
|
||||
Service sheet must contain 11 columns::
|
||||
|
||||
route id ; Source ; Destination ; TRX type ; Mode ; System: spacing ; System: input power (dBm) ; System: nb of channels ; routing: disjoint from ; routing: path ; routing: is loose?
|
||||
|
||||
- **route id** is mandatory. It must be unique. It is the identifier of the request. It must be an integer value (TODO: relax this format in future development to accept any strings)
|
||||
|
||||
- **Source** is mandatory. It is the name of the source node (as listed in Nodes sheet). Source MUST be a ROADM node. (TODO: relax this and accept trx entries)
|
||||
|
||||
- **Destination** is mandatory. It is the name of the destination node (as listed in Nodes sheet). Source MUST be a ROADM node. (TODO: relax this and accept trx entries)
|
||||
|
||||
- **TRX type and mode** are mandatory. They are the variety type and selected mode of the transceiver to be used for the propagation simulation. These modes MUST be defined in the equipment library. The format of the mode is used as the name of the mode. (TODO: maybe add another mode id on Transceiver library ?). In particular the mode selection defines the channel baudrate to be used for the propagation simulation.
|
||||
|
||||
- **System: spacing ; System: input power (dBm) ; System: nb of channels** are mandatory input defining the system parameters for the propagation simulation.
|
||||
|
||||
- spacing is the channel spacing defined in GHz
|
||||
- input power is the channel optical input power in dBm
|
||||
- nb of channels is the number of channels to be used for the simulation.
|
||||
|
||||
- **routing: disjoint from ; routing: path ; routing: is loose?** are optional.
|
||||
|
||||
- disjoint from: (work not started) identifies the requests from which this request must be disjoint. It is not used yet
|
||||
- path: is the set of ROADM nodes that must be used by the path. It must contain the list of ROADM names that the path must cross. TODO : only ROADM nodes are accepted in this release. Relax this with any type of nodes.
|
||||
- is loose? (in progress) 'no' value means that the list of nodes should be strictly followed, while any other value means that the constraint may be relaxed if the node is not reachable.
|
||||
|
||||
# to be completed #
|
||||
|
||||
convert_service_sheet.py
|
||||
------------------------
|
||||
|
||||
|
||||
`convert_service_sheet.py <examples/convert_service_sheet.py>`_ converts the service sheet to a json file following the Yang model for requesting Path Computation defined in `draft-ietf-teas-yang-path-computation-01.txt <https://www.ietf.org/id/draft-ietf-teas-yang-path-computation-01.pdf>`_. TODO: verify that this implementation is correct + give feedback to ietf on what is missing for our specific application.
|
||||
For PSE use, additional fields with trx type and mode have been added to the te-bandwidth field.
|
||||
|
||||
**Usage**: convert_service_sheet.py [-h] [-v] [-o OUTPUT] [workbook_name.xls]
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cd examples
|
||||
$ python convert_service_sheet.py meshTopologyExampleV2.xls -o service_file.json
|
||||
|
||||
-o output_file.json is an optional parameter:
|
||||
|
||||
- if not used, the program output the json data on standard output and on a json file with name 'workbook_name_services.json'.
|
||||
|
||||
A template for the json file can be found here: `service_template.json <service_template.json>`_
|
||||
|
||||
path_requests_run.py
|
||||
------------------------
|
||||
|
||||
**Usage**: path_requests_run.py [-h] [-v] [-o OUTPUT]
|
||||
[network_filename xls or json] [service_filename xls or json] [eqpt_filename json]
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ cd examples
|
||||
$ python path_requests_run.py meshTopologyExampleV2.xls service_file.json eqpt_file -o output_file.json
|
||||
|
||||
A function that computes performances for a list of services provided in the service file (accepts json or excel format.
|
||||
|
||||
If no output file is given, the computation is shown on standard output for demo.
|
||||
If a file is specified with the optional -o argument, the result of the computation is converted into a json format following the Yang model for requesting Path Computation defined in `draft-ietf-teas-yang-path-computation-01.txt <https://www.ietf.org/id/draft-ietf-teas-yang-path-computation-01.pdf>`_. TODO: verify that this implementation is correct + give feedback to ietf on what is missing for our specific application.
|
||||
|
||||
A template for the result of computation json file can be found here: `path_result_template.json <path_result_template.json>`_
|
||||
|
||||
Important note: path_requests_run.py is not a dimensionning tool, it only computes path feasibility assuming full load with system parameters input in the service file. The network topology is created only once for the set of requests. As a result the transceiver element acts as a "logical starting/stopping point" for the spectral information propagation. At that point it is not meant to represent the capacity of add drop ports
|
||||
As a result transponder type is not part of the network info. it is related to the list of services requests.
|
||||
|
||||
(in progress)
|
||||
|
||||
|
||||
|
||||
203
examples/compare_json.py
Normal file
203
examples/compare_json.py
Normal file
@@ -0,0 +1,203 @@
|
||||
from json import loads
|
||||
from pathlib import Path
|
||||
from argparse import ArgumentParser
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('expected_output', type=Path, metavar='FILE')
|
||||
parser.add_argument('actual_output', type=Path, metavar='FILE')
|
||||
parser.add_argument('-o', '--output', default=None)
|
||||
|
||||
def compare_network_file(expected_output, actual_output):
|
||||
with open(expected_output) as f:
|
||||
expected_json = f.read()
|
||||
with open(actual_output) as f:
|
||||
actual_json = f.read()
|
||||
|
||||
expected_data = loads(expected_json)
|
||||
actual_data = loads(actual_json)
|
||||
|
||||
print(f'Comparing:'
|
||||
f'\n\t{expected_output}'
|
||||
f'\n\t{actual_output}')
|
||||
expected_elements = expected_data['elements']
|
||||
actual_elements = actual_data['elements']
|
||||
expected_elements = {el['uid']: el for el in expected_elements}
|
||||
actual_elements = {el['uid']: el for el in actual_elements}
|
||||
missing = set(expected_elements) - set(actual_elements)
|
||||
extra = set(actual_elements) - set(expected_elements)
|
||||
different = [(expected_elements[x], actual_elements[x]) for
|
||||
x in set(expected_elements) & set(actual_elements)
|
||||
if expected_elements[x] != actual_elements[x]]
|
||||
identical = True
|
||||
msg = []
|
||||
if missing:
|
||||
msg.append(f'Missing Elements (by uid): {len(missing)}/{len(expected_elements)}')
|
||||
for x in sorted(missing):
|
||||
msg.append(f'\t{expected_elements[x]}')
|
||||
identical = False
|
||||
if extra:
|
||||
msg.append(f'Extra Elements (by uid): {len(extra)}/{len(expected_elements)}')
|
||||
for x in sorted(extra):
|
||||
msg.append(f'\t{actual_elements[x]}')
|
||||
identical = False
|
||||
if different:
|
||||
msg.append(f'Different Elements: {len(different)}/{len(expected_elements)}')
|
||||
for x, y in sorted(different, key=lambda xy: xy[0]['uid']):
|
||||
msg.append(f'\t- Expected: {x}\n\t Actual: {y}')
|
||||
identical = False
|
||||
if not missing and not extra and not different:
|
||||
msg.append('All elements match!')
|
||||
identical = True
|
||||
|
||||
expected_connections = expected_data['connections']
|
||||
actual_connections = actual_data['connections']
|
||||
|
||||
missing = []
|
||||
for x in sorted(expected_connections, key=lambda d: (d['from_node'], d['to_node'])):
|
||||
if x not in actual_connections:
|
||||
missing.append(x)
|
||||
extra = []
|
||||
for x in sorted(actual_connections, key=lambda d: (d['from_node'], d['to_node'])):
|
||||
if x not in expected_connections:
|
||||
extra.append(x)
|
||||
|
||||
if missing:
|
||||
msg.append(f'Missing Connections: {len(missing)}/{len(expected_connections)}')
|
||||
for x in missing:
|
||||
msg.append(f'\t{x}')
|
||||
identical = False
|
||||
if extra:
|
||||
msg.append(f'Extra Connections: {len(extra)}/{len(expected_connections)}')
|
||||
for x in extra:
|
||||
msg.append(f'\t{x}')
|
||||
identical = False
|
||||
|
||||
if not missing and not extra:
|
||||
msg.append('All connections match!')
|
||||
|
||||
return identical,msg
|
||||
|
||||
def compare_service_file(expected_output, actual_output):
|
||||
with open(expected_output) as f:
|
||||
expected_json = f.read()
|
||||
with open(actual_output) as f:
|
||||
actual_json = f.read()
|
||||
|
||||
expected_data = loads(expected_json)
|
||||
actual_data = loads(actual_json)
|
||||
|
||||
print(f'Comparing:'
|
||||
f'\n\t{expected_output}'
|
||||
f'\n\t{actual_output}')
|
||||
expected_elements = expected_data['path-request']
|
||||
actual_elements = actual_data['path-request']
|
||||
expected_elements = {el['request-id']: el for el in expected_elements}
|
||||
actual_elements = {el['request-id']: el for el in actual_elements}
|
||||
missing = set(expected_elements) - set(actual_elements)
|
||||
extra = set(actual_elements) - set(expected_elements)
|
||||
different = [(expected_elements[x], actual_elements[x]) for
|
||||
x in set(expected_elements) & set(actual_elements)
|
||||
if expected_elements[x] != actual_elements[x]]
|
||||
identical = True
|
||||
msg = []
|
||||
if missing:
|
||||
msg.append(f'Missing requests (by request-id): {len(missing)}/{len(expected_elements)}')
|
||||
for x in sorted(missing):
|
||||
msg.append(f'\t{expected_elements[x]}')
|
||||
identical = False
|
||||
if extra:
|
||||
msg.append(f'Extra requests (by request-id): {len(extra)}/{len(expected_elements)}')
|
||||
for x in sorted(extra):
|
||||
msg.append(f'\t{actual_elements[x]}')
|
||||
identical = False
|
||||
if different:
|
||||
msg.append(f'Different requests: {len(different)}/{len(expected_elements)}')
|
||||
for x, y in sorted(different, key=lambda xy: xy[0]['request-id']):
|
||||
msg.append(f'\t- Expected: {x}\n\t Actual: {y}')
|
||||
identical = False
|
||||
if not missing and not extra and not different:
|
||||
msg.append('All elements match!')
|
||||
|
||||
expected_elements = expected_data['synchronisation']
|
||||
actual_elements = actual_data['synchronisation']
|
||||
expected_elements = {el['synchonization-id']: el for el in expected_elements}
|
||||
actual_elements = {el['synchonization-id']: el for el in actual_elements}
|
||||
missing = set(expected_elements) - set(actual_elements)
|
||||
extra = set(actual_elements) - set(expected_elements)
|
||||
different = [(expected_elements[x], actual_elements[x]) for
|
||||
x in set(expected_elements) & set(actual_elements)
|
||||
if expected_elements[x] != actual_elements[x]]
|
||||
|
||||
if missing:
|
||||
msg.append(f'Missing synchronisations (by synchronisation-id): {len(missing)}/{len(expected_elements)}')
|
||||
for x in sorted(missing):
|
||||
msg.append(f'\t{expected_elements[x]}')
|
||||
identical = False
|
||||
if extra:
|
||||
msg.append(f'Extra synchronisations (by synchronisation-id): {len(extra)}/{len(expected_elements)}')
|
||||
for x in sorted(extra):
|
||||
msg.append(f'\t{actual_elements[x]}')
|
||||
identical = False
|
||||
if different:
|
||||
msg.append(f'Different synchronisations: {len(different)}/{len(expected_elements)}')
|
||||
for x, y in sorted(different, key=lambda xy: xy[0]['synchonization-id']):
|
||||
msg.append(f'\t- Expected: {x}\n\t Actual: {y}')
|
||||
identical = False
|
||||
|
||||
if not missing and not extra and not different:
|
||||
msg.append('All synchronisations match!')
|
||||
|
||||
return identical,msg
|
||||
|
||||
def compare_result_file(expected_output, actual_output):
|
||||
with open(expected_output) as f:
|
||||
expected_json = f.read()
|
||||
with open(actual_output) as f:
|
||||
actual_json = f.read()
|
||||
|
||||
expected_data = loads(expected_json)
|
||||
actual_data = loads(actual_json)
|
||||
|
||||
print(f'Comparing:'
|
||||
f'\n\t{expected_output}'
|
||||
f'\n\t{actual_output}')
|
||||
expected_elements = expected_data['path']
|
||||
actual_elements = actual_data['path']
|
||||
expected_elements = {el['path-id']: el for el in expected_elements}
|
||||
actual_elements = {el['path-id']: el for el in actual_elements}
|
||||
missing = set(expected_elements) - set(actual_elements)
|
||||
extra = set(actual_elements) - set(expected_elements)
|
||||
different = [(expected_elements[x], actual_elements[x]) for
|
||||
x in set(expected_elements) & set(actual_elements)
|
||||
if expected_elements[x] != actual_elements[x]]
|
||||
identical = True
|
||||
msg = []
|
||||
if missing:
|
||||
msg.append(f'Missing paths (by path-id): {len(missing)}/{len(expected_elements)}')
|
||||
for x in sorted(missing):
|
||||
msg.append(f'\t{expected_elements[x]}')
|
||||
identical = False
|
||||
if extra:
|
||||
msg.append(f'Extra paths (by path-id): {len(extra)}/{len(expected_elements)}')
|
||||
for x in sorted(extra):
|
||||
msg.append(f'\t{actual_elements[x]}')
|
||||
identical = False
|
||||
if different:
|
||||
msg.append(f'Different paths: {len(different)}/{len(expected_elements)}')
|
||||
for x, y in sorted(different, key=lambda xy: xy[0]['path-id']):
|
||||
msg.append(f'\t- Expected: {x}\n\t Actual: {y}')
|
||||
identical = False
|
||||
if not missing and not extra and not different:
|
||||
msg.append('All elements match!')
|
||||
|
||||
return identical,msg
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
identical,msg = compare_result_file(args.expected_output, args.actual_output)
|
||||
print(identical)
|
||||
if args.output:
|
||||
with open(args.output,"w") as f:
|
||||
f.write('\n'.join(msg))
|
||||
|
||||
220
examples/convert_service_sheet.py
Normal file
220
examples/convert_service_sheet.py
Normal file
@@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python3
|
||||
# TelecomInfraProject/gnpy/examples
|
||||
# Module name : convert_service_sheet.py
|
||||
# Version :
|
||||
# License : BSD 3-Clause Licence
|
||||
# Copyright (c) 2018, Telecom Infra Project
|
||||
|
||||
"""
|
||||
@author: esther.lerouzic
|
||||
@author: jeanluc-auge
|
||||
xls parser, that can be called to create a json request file in accordance with:
|
||||
Yang model for requesting Path Computation
|
||||
draft-ietf-teas-yang-path-computation-01.txt.
|
||||
|
||||
|
||||
"""
|
||||
from sys import exit
|
||||
try:
|
||||
from xlrd import open_workbook, XL_CELL_EMPTY
|
||||
except ModuleNotFoundError:
|
||||
exit('Required: `pip install xlrd`')
|
||||
from argparse import ArgumentParser
|
||||
from collections import namedtuple
|
||||
from logging import getLogger, basicConfig, CRITICAL, DEBUG, INFO
|
||||
from json import dumps
|
||||
from pathlib import Path
|
||||
from gnpy.core.equipment import load_equipment
|
||||
from gnpy.core.utils import db2lin, lin2db
|
||||
|
||||
SERVICES_COLUMN = 11
|
||||
#EQPT_LIBRARY_FILENAME = Path(__file__).parent / 'eqpt_config.json'
|
||||
|
||||
all_rows = lambda sheet, start=0: (sheet.row(x) for x in range(start, sheet.nrows))
|
||||
logger = getLogger(__name__)
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('workbook', nargs='?', type = Path , default='meshTopologyExampleV2.xls')
|
||||
parser.add_argument('-v', '--verbose', action='count')
|
||||
parser.add_argument('-o', '--output', default=None)
|
||||
|
||||
# Type for input data
|
||||
class Request(namedtuple('Request', 'request_id source destination trx_type mode \
|
||||
spacing power nb_channel disjoint_from nodes_list is_loose')):
|
||||
def __new__(cls, request_id, source, destination, trx_type, mode , spacing , power , nb_channel , disjoint_from ='' , nodes_list = None, is_loose = ''):
|
||||
return super().__new__(cls, request_id, source, destination, trx_type, mode, spacing, power, nb_channel, disjoint_from, nodes_list, is_loose)
|
||||
|
||||
# Type for output data: // from dutc
|
||||
class Element:
|
||||
def __eq__(self, other):
|
||||
return type(self) == type(other) and self.uid == other.uid
|
||||
def __hash__(self):
|
||||
return hash((type(self), self.uid))
|
||||
|
||||
class Request_element(Element):
|
||||
def __init__(self,Request,eqpt_filename):
|
||||
self.request_id = int(Request.request_id)
|
||||
self.source = Request.source
|
||||
self.destination = Request.destination
|
||||
self.srctpid = f'trx {Request.source}'
|
||||
self.dsttpid = f'trx {Request.destination}'
|
||||
# test that trx_type belongs to eqpt_config.json
|
||||
# if not replace it with a default
|
||||
equipment = load_equipment(eqpt_filename)
|
||||
if equipment['Transceiver'][Request.trx_type]:
|
||||
self.trx_type = Request.trx_type
|
||||
self.mode = Request.mode
|
||||
else:
|
||||
#TODO : this case must raise an error instead of using Voyager
|
||||
self.trx_type = 'Voyager_16QAM'
|
||||
print(f'Transceiver type {Request.trx_type} is not defined in {eqpt_filename}')
|
||||
print('replaced by Voyager_16QAM')
|
||||
self.spacing = Request.spacing * 1e9
|
||||
self.power = db2lin(Request.power) * 1e-3
|
||||
self.nb_channel = int(Request.nb_channel)
|
||||
if isinstance(Request.disjoint_from,str):
|
||||
self.disjoint_from = [int(n) for n in Request.disjoint_from.split()]
|
||||
else:
|
||||
self.disjoint_from = [int(Request.disjoint_from)]
|
||||
self.nodes_list = []
|
||||
if Request.nodes_list :
|
||||
self.nodes_list = Request.nodes_list.split(' | ')
|
||||
try :
|
||||
self.nodes_list.remove(self.source)
|
||||
msg = f'{self.source} removed from explicit path node-list'
|
||||
logger.info(msg)
|
||||
print(msg)
|
||||
except ValueError:
|
||||
msg = f'{self.source} already removed from explicit path node-list'
|
||||
logger.info(msg)
|
||||
# print(msg)
|
||||
try :
|
||||
self.nodes_list.remove(self.destination)
|
||||
msg = f'{self.destination} removed from explicit path node-list'
|
||||
logger.info(msg)
|
||||
print(msg)
|
||||
except ValueError:
|
||||
msg = f'{self.destination} already removed from explicit path node-list'
|
||||
logger.info(msg)
|
||||
# print(msg)
|
||||
|
||||
self.loose = 'loose'
|
||||
if Request.is_loose == 'no' :
|
||||
self.loose = 'strict'
|
||||
|
||||
uid = property(lambda self: repr(self))
|
||||
@property
|
||||
def pathrequest(self):
|
||||
return {
|
||||
'request-id':self.request_id,
|
||||
'source': self.source,
|
||||
'destination': self.destination,
|
||||
'src-tp-id': self.srctpid,
|
||||
'dst-tp-id': self.dsttpid,
|
||||
'path-constraints':{
|
||||
'te-bandwidth': {
|
||||
'technology': 'flexi-grid',
|
||||
'trx_type' : self.trx_type,
|
||||
'trx_mode' : self.mode,
|
||||
'effective-freq-slot':[{'n': 'null','m': 'null'}] ,
|
||||
'spacing' : self.spacing,
|
||||
'max-nb-of-channel' : self.nb_channel,
|
||||
'output-power' : self.power
|
||||
}
|
||||
},
|
||||
'optimizations': {
|
||||
'explicit-route-include-objects': [
|
||||
{
|
||||
'index': self.nodes_list.index(node),
|
||||
'unnumbered-hop':{
|
||||
'node-id': f'{node}',
|
||||
'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'
|
||||
}
|
||||
}
|
||||
}
|
||||
for node in self.nodes_list
|
||||
]
|
||||
|
||||
}
|
||||
}
|
||||
@property
|
||||
def pathsync(self):
|
||||
if self.disjoint_from :
|
||||
return {'synchonization-id':self.request_id,
|
||||
'svec': {
|
||||
'relaxable' : 'False',
|
||||
'link-diverse': 'True',
|
||||
'node-diverse': 'True',
|
||||
'request-id-number': [self.request_id]+ [n for n in self.disjoint_from]
|
||||
}
|
||||
}
|
||||
# TO-DO: avoid multiple entries with same synchronisation vectors
|
||||
@property
|
||||
def json(self):
|
||||
return self.pathrequest , self.pathsync
|
||||
|
||||
def convert_service_sheet(input_filename, eqpt_filename, output_filename='', filter_region=[]):
|
||||
service = parse_excel(input_filename)
|
||||
req = [Request_element(n,eqpt_filename) for n in service]
|
||||
# dumps the output into a json file with name
|
||||
# split_filename = [input_filename[0:len(input_filename)-len(suffix_filename)] , suffix_filename[1:]]
|
||||
if output_filename=='':
|
||||
output_filename = f'{str(input_filename)[0:len(str(input_filename))-len(str(input_filename.suffixes[0]))]}_services.json'
|
||||
# for debug
|
||||
# print(json_filename)
|
||||
data = {
|
||||
'path-request': [n.json[0] for n in req],
|
||||
'synchronisation': [n.json[1] for n in req
|
||||
if n.json[1] is not None]
|
||||
}
|
||||
with open(output_filename, 'w') as f:
|
||||
f.write(dumps(data, indent=2))
|
||||
return data
|
||||
|
||||
# to be used from dutc
|
||||
def parse_row(row, fieldnames):
|
||||
return {f: r.value for f, r in zip(fieldnames, row[0:SERVICES_COLUMN])
|
||||
if r.ctype != XL_CELL_EMPTY}
|
||||
#
|
||||
|
||||
def parse_excel(input_filename):
|
||||
with open_workbook(input_filename) as wb:
|
||||
service_sheet = wb.sheet_by_name('Service')
|
||||
services = list(parse_service_sheet(service_sheet))
|
||||
return services
|
||||
|
||||
def parse_service_sheet(service_sheet):
|
||||
logger.info(f'Validating headers on {service_sheet.name!r}')
|
||||
header = [x.value.strip() for x in service_sheet.row(4)[0:SERVICES_COLUMN]]
|
||||
expected = ['route id', 'Source', 'Destination', 'TRX type', \
|
||||
'Mode', 'System: spacing', 'System: input power (dBm)', 'System: nb of channels',\
|
||||
'routing: disjoint from', 'routing: path', 'routing: is loose?']
|
||||
if header != expected:
|
||||
msg = f'Malformed header on Service sheet: {header} != {expected}'
|
||||
logger.critical(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
service_fieldnames = 'request_id source destination trx_type mode spacing power nb_channel disjoint_from nodes_list is_loose'.split()
|
||||
# Important Note: it reads all colum on each row so that
|
||||
# it is not possible to write annotation in the excel sheet
|
||||
# outside the SERVICES_COLUMN ... TO BE IMPROVED
|
||||
# request_id should be unique for disjunction constraints (not used yet)
|
||||
for row in all_rows(service_sheet, start=5):
|
||||
yield Request(**parse_row(row[0:SERVICES_COLUMN], service_fieldnames))
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
basicConfig(level={2: DEBUG, 1: INFO, 0: CRITICAL}.get(args.verbose, CRITICAL))
|
||||
logger.info(f'Converting Service sheet {args.workbook!r} into gnpy JSON format')
|
||||
if args.output is None:
|
||||
data = convert_service_sheet(args.workbook,'eqpt_config.json')
|
||||
print(dumps(data, indent=2))
|
||||
else:
|
||||
data = convert_service_sheet(args.workbook,'eqpt_config.json',args.output)
|
||||
@@ -93,10 +93,10 @@ def create_eqt_template(links,nodes, links_by_src , links_by_dest, input_filenam
|
||||
temp = []
|
||||
i = 0
|
||||
for lk in links:
|
||||
temp = [lk.src , lk.dest]
|
||||
tab.append(temp)
|
||||
# print(temp)
|
||||
my_file.write(f'{temp[0]}\t{temp[1]}\n')
|
||||
if [e for n,e in nodes if n==lk.src][0] != 'FUSED' :
|
||||
temp = [lk.src , lk.dest]
|
||||
tab.append(temp)
|
||||
my_file.write(f'{temp[0]}\t{temp[1]}\n')
|
||||
for n in nodes :
|
||||
if n.eqt.lower() == 'roadm' :
|
||||
for src in links_by_dest[n.nodename] :
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
"p_max": 21,
|
||||
"nf_min": 7,
|
||||
"nf_max": 11
|
||||
},
|
||||
{
|
||||
"type_variety": "test",
|
||||
"gain_flatmax": 25,
|
||||
"gain_min": 15,
|
||||
"p_max": 21,
|
||||
"nf_min": 5.8,
|
||||
"nf_max": 10
|
||||
}
|
||||
],
|
||||
"Fiber":[{
|
||||
@@ -41,11 +49,50 @@
|
||||
"loss": 20
|
||||
}],
|
||||
"SI":[{
|
||||
"f_min": 193.1e12,
|
||||
"Nch": 96,
|
||||
"f_min": 191.3e12,
|
||||
"Nch": 80,
|
||||
"baud_rate": 32e9,
|
||||
"spacing": 50e9,
|
||||
"spacing": 75e9,
|
||||
"roll_off": 0.15,
|
||||
"power": 1e-3
|
||||
}]
|
||||
"power": 1.2589e-3
|
||||
}],
|
||||
"Transceiver":[
|
||||
{
|
||||
"type_variety": "vendorA_trx-type1",
|
||||
"frequency":{
|
||||
"min": 191.35e12,
|
||||
"max": 196.1e12
|
||||
},
|
||||
"mode":[
|
||||
{
|
||||
"format": "PS_SP64_1",
|
||||
"baudrate": 32e9,
|
||||
"OSNR": 9,
|
||||
"bit_rate": 100e9
|
||||
},
|
||||
{
|
||||
"format": "PS_SP64_2",
|
||||
"baudrate": 66e9,
|
||||
"OSNR": 10,
|
||||
"bit_rate": 200e9
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type_variety": "Voyager_16QAM",
|
||||
"frequency":{
|
||||
"min": 191.35e12,
|
||||
"max": 196.1e12
|
||||
},
|
||||
"mode":[
|
||||
{
|
||||
"format": "16QAM",
|
||||
"baudrate": 32e9,
|
||||
"OSNR": 15,
|
||||
"bit_rate": 200e9
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
"location": {
|
||||
"city": "Lannion_CAS",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
@@ -18,8 +18,8 @@
|
||||
"location": {
|
||||
"city": "Lorient_KMA",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
@@ -30,8 +30,8 @@
|
||||
"location": {
|
||||
"city": "Vannes_KBE",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 4.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
@@ -42,8 +42,8 @@
|
||||
"location": {
|
||||
"city": "Rennes_STA",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
@@ -54,8 +54,8 @@
|
||||
"location": {
|
||||
"city": "Brest_KLA",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 4.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
@@ -66,8 +66,8 @@
|
||||
"location": {
|
||||
"city": "Lannion_CAS",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
@@ -78,8 +78,8 @@
|
||||
"location": {
|
||||
"city": "Lorient_KMA",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
@@ -90,8 +90,8 @@
|
||||
"location": {
|
||||
"city": "Vannes_KBE",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 4.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
@@ -102,8 +102,8 @@
|
||||
"location": {
|
||||
"city": "Rennes_STA",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
@@ -114,8 +114,8 @@
|
||||
"location": {
|
||||
"city": "Brest_KLA",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 4.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
@@ -126,8 +126,8 @@
|
||||
"location": {
|
||||
"city": "Corlay",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
@@ -138,8 +138,8 @@
|
||||
"location": {
|
||||
"city": "Loudeac",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
@@ -150,8 +150,8 @@
|
||||
"location": {
|
||||
"city": "Morlaix",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 3.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
@@ -162,8 +162,8 @@
|
||||
"location": {
|
||||
"city": "Corlay",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
@@ -174,8 +174,8 @@
|
||||
"location": {
|
||||
"city": "Loudeac",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
@@ -186,18 +186,18 @@
|
||||
"location": {
|
||||
"city": "Morlaix",
|
||||
"region": "RLD",
|
||||
"latitude": 0,
|
||||
"longitude": 0
|
||||
"latitude": 3.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Corlay)-",
|
||||
"uid": "fiber (Lannion_CAS \u2192 Corlay)-F061",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
@@ -209,11 +209,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Corlay \u2192 Loudeac)-",
|
||||
"uid": "fiber (Corlay \u2192 Loudeac)-F010",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
@@ -225,11 +225,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Loudeac \u2192 Lorient_KMA)-",
|
||||
"uid": "fiber (Loudeac \u2192 Lorient_KMA)-F054",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
@@ -241,11 +241,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F01",
|
||||
"uid": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
@@ -257,10 +257,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Stbrieuc)-",
|
||||
"uid": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"latitude": 1.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
@@ -273,10 +273,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Stbrieuc \u2192 Rennes_STA)-",
|
||||
"uid": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"latitude": 0.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
@@ -289,10 +289,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Morlaix)-",
|
||||
"uid": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"latitude": 2.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
@@ -305,10 +305,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Morlaix \u2192 Brest_KLA)-",
|
||||
"uid": "fiber (Morlaix \u2192 Brest_KLA)-F060",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"latitude": 3.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
@@ -321,11 +321,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Corlay \u2192 Lannion_CAS)-",
|
||||
"uid": "fiber (Corlay \u2192 Lannion_CAS)-F061",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
@@ -337,11 +337,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Loudeac \u2192 Corlay)-",
|
||||
"uid": "fiber (Loudeac \u2192 Corlay)-F010",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
@@ -353,11 +353,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lorient_KMA \u2192 Loudeac)-",
|
||||
"uid": "fiber (Lorient_KMA \u2192 Loudeac)-F054",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
@@ -369,11 +369,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F01",
|
||||
"uid": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
@@ -385,10 +385,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Stbrieuc \u2192 Lannion_CAS)-",
|
||||
"uid": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"latitude": 1.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
@@ -401,10 +401,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Rennes_STA \u2192 Stbrieuc)-",
|
||||
"uid": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"latitude": 0.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
@@ -417,10 +417,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Morlaix \u2192 Lannion_CAS)-",
|
||||
"uid": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"latitude": 2.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
@@ -433,10 +433,10 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Brest_KLA \u2192 Morlaix)-",
|
||||
"uid": "fiber (Brest_KLA \u2192 Morlaix)-F060",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.0,
|
||||
"latitude": 3.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
@@ -452,122 +452,122 @@
|
||||
"connections": [
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Corlay)-"
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Corlay)-F061"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Corlay \u2192 Lannion_CAS)-",
|
||||
"from_node": "fiber (Corlay \u2192 Lannion_CAS)-F061",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-"
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-",
|
||||
"from_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Morlaix)-"
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Morlaix)-F059"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Morlaix \u2192 Lannion_CAS)-",
|
||||
"from_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Corlay)-",
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Corlay)-F061",
|
||||
"to_node": "ingress fused spans in Corlay"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Corlay",
|
||||
"to_node": "fiber (Corlay \u2192 Loudeac)-"
|
||||
"to_node": "fiber (Corlay \u2192 Loudeac)-F010"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Loudeac \u2192 Corlay)-",
|
||||
"from_node": "fiber (Loudeac \u2192 Corlay)-F010",
|
||||
"to_node": "egress fused spans in Corlay"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Corlay",
|
||||
"to_node": "fiber (Corlay \u2192 Lannion_CAS)-"
|
||||
"to_node": "fiber (Corlay \u2192 Lannion_CAS)-F061"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Corlay \u2192 Loudeac)-",
|
||||
"from_node": "fiber (Corlay \u2192 Loudeac)-F010",
|
||||
"to_node": "ingress fused spans in Loudeac"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Loudeac",
|
||||
"to_node": "fiber (Loudeac \u2192 Lorient_KMA)-"
|
||||
"to_node": "fiber (Loudeac \u2192 Lorient_KMA)-F054"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lorient_KMA \u2192 Loudeac)-",
|
||||
"from_node": "fiber (Lorient_KMA \u2192 Loudeac)-F054",
|
||||
"to_node": "egress fused spans in Loudeac"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Loudeac",
|
||||
"to_node": "fiber (Loudeac \u2192 Corlay)-"
|
||||
"to_node": "fiber (Loudeac \u2192 Corlay)-F010"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lorient_KMA",
|
||||
"to_node": "fiber (Lorient_KMA \u2192 Loudeac)-"
|
||||
"to_node": "fiber (Lorient_KMA \u2192 Loudeac)-F054"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Loudeac \u2192 Lorient_KMA)-",
|
||||
"from_node": "fiber (Loudeac \u2192 Lorient_KMA)-F054",
|
||||
"to_node": "roadm Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lorient_KMA",
|
||||
"to_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F01"
|
||||
"to_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F01",
|
||||
"from_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
|
||||
"to_node": "roadm Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Vannes_KBE",
|
||||
"to_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F01"
|
||||
"to_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F01",
|
||||
"from_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
|
||||
"to_node": "roadm Vannes_KBE"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-",
|
||||
"to_node": "fiber (Stbrieuc \u2192 Rennes_STA)-"
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
|
||||
"to_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Rennes_STA \u2192 Stbrieuc)-",
|
||||
"to_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-"
|
||||
"from_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
|
||||
"to_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Rennes_STA",
|
||||
"to_node": "fiber (Rennes_STA \u2192 Stbrieuc)-"
|
||||
"to_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Stbrieuc \u2192 Rennes_STA)-",
|
||||
"from_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
|
||||
"to_node": "roadm Rennes_STA"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Morlaix)-",
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
|
||||
"to_node": "ingress fused spans in Morlaix"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Morlaix",
|
||||
"to_node": "fiber (Morlaix \u2192 Brest_KLA)-"
|
||||
"to_node": "fiber (Morlaix \u2192 Brest_KLA)-F060"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Brest_KLA \u2192 Morlaix)-",
|
||||
"from_node": "fiber (Brest_KLA \u2192 Morlaix)-F060",
|
||||
"to_node": "egress fused spans in Morlaix"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Morlaix",
|
||||
"to_node": "fiber (Morlaix \u2192 Lannion_CAS)-"
|
||||
"to_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Brest_KLA",
|
||||
"to_node": "fiber (Brest_KLA \u2192 Morlaix)-"
|
||||
"to_node": "fiber (Brest_KLA \u2192 Morlaix)-F060"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Morlaix \u2192 Brest_KLA)-",
|
||||
"from_node": "fiber (Morlaix \u2192 Brest_KLA)-F060",
|
||||
"to_node": "roadm Brest_KLA"
|
||||
},
|
||||
{
|
||||
|
||||
Binary file not shown.
286
examples/path_requests_run.py
Normal file
286
examples/path_requests_run.py
Normal file
@@ -0,0 +1,286 @@
|
||||
#!/usr/bin/env python3
|
||||
# TelecomInfraProject/gnpy/examples
|
||||
# Module name : path_requests_run.py
|
||||
# Version :
|
||||
# License : BSD 3-Clause Licence
|
||||
# Copyright (c) 2018, Telecom Infra Project
|
||||
|
||||
"""
|
||||
@author: esther.lerouzic
|
||||
@author: jeanluc-auge
|
||||
read json request file in accordance with:
|
||||
Yang model for requesting Path Computation
|
||||
draft-ietf-teas-yang-path-computation-01.txt.
|
||||
and returns path results in terms of path and feasibility
|
||||
|
||||
"""
|
||||
|
||||
from sys import exit
|
||||
from argparse import ArgumentParser
|
||||
from pathlib import Path
|
||||
from collections import namedtuple
|
||||
from logging import getLogger, basicConfig, CRITICAL, DEBUG, INFO
|
||||
from json import dumps, loads
|
||||
from networkx import (draw_networkx_nodes, draw_networkx_edges,
|
||||
draw_networkx_labels, dijkstra_path, NetworkXNoPath)
|
||||
from numpy import mean
|
||||
from examples.convert_service_sheet import convert_service_sheet, Request_element, Element
|
||||
from gnpy.core.utils import load_json
|
||||
from gnpy.core.network import load_network, build_network
|
||||
from gnpy.core.equipment import load_equipment
|
||||
from gnpy.core.elements import Transceiver, Roadm, Edfa, Fused
|
||||
from gnpy.core.utils import db2lin, lin2db
|
||||
from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power
|
||||
from copy import copy, deepcopy
|
||||
from numpy import log10
|
||||
|
||||
#EQPT_LIBRARY_FILENAME = Path(__file__).parent / 'eqpt_config.json'
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
parser = ArgumentParser(description = 'A function that computes performances for a list of services provided in a json file or an excel sheet.')
|
||||
parser.add_argument('network_filename', nargs='?', type = Path, default= Path(__file__).parent / 'meshTopologyExampleV2.xls')
|
||||
parser.add_argument('service_filename', nargs='?', type = Path, default= Path(__file__).parent / 'meshTopologyExampleV2.xls')
|
||||
parser.add_argument('eqpt_filename', nargs='?', type = Path, default=Path(__file__).parent / 'eqpt_config.json')
|
||||
parser.add_argument('-v', '--verbose', action='count')
|
||||
parser.add_argument('-o', '--output', default=None)
|
||||
|
||||
|
||||
class Path_request():
|
||||
def __init__(self,jsondata,tspjsondata):
|
||||
self.request_id = jsondata['request-id']
|
||||
self.source = jsondata['src-tp-id']
|
||||
self.destination = jsondata['dst-tp-id']
|
||||
# retrieving baudrate out of transponder type and mode (format)
|
||||
self.tsp = jsondata['path-constraints']['te-bandwidth']['trx_type']
|
||||
self.tsp_mode = jsondata['path-constraints']['te-bandwidth']['trx_mode']
|
||||
# for debug
|
||||
# print(tsp)
|
||||
try:
|
||||
baudrate = next(m['baudrate']
|
||||
for t in tspjsondata if t['type_variety'] == self.tsp
|
||||
for m in t['mode'] if m['format'] == self.tsp_mode)
|
||||
except StopIteration:
|
||||
msg = f'could not find tsp : {self.tsp} with mode: {self.tsp_mode} in eqpt library'
|
||||
logger.critical(msg)
|
||||
raise ValueError(msg)
|
||||
self.baudrate = baudrate
|
||||
|
||||
nodes_list = jsondata['optimizations']['explicit-route-include-objects']
|
||||
self.nodes_list = [n['unnumbered-hop']['node-id'] for n in nodes_list]
|
||||
# create a list for individual loose capability for each node ...
|
||||
# even if convert_service_sheet fills it with the same value
|
||||
self.loose_list = [n['unnumbered-hop']['hop-type'] for n in nodes_list]
|
||||
|
||||
self.spacing = jsondata['path-constraints']['te-bandwidth']['spacing']
|
||||
self.power = jsondata['path-constraints']['te-bandwidth']['output-power']
|
||||
self.nb_channel = jsondata['path-constraints']['te-bandwidth']['max-nb-of-channel']
|
||||
|
||||
def __str__(self):
|
||||
return '\n\t'.join([ f'{type(self).__name__} {self.request_id}',
|
||||
f'source: {self.source}',
|
||||
f'destination: {self.destination}'])
|
||||
def __repr__(self):
|
||||
return '\n\t'.join([ f'{type(self).__name__} {self.request_id}',
|
||||
f'source: {self.source}',
|
||||
f'destination: {self.destination}',
|
||||
f'trx type: {self.tsp}',
|
||||
f'baudrate: {self.baudrate}',
|
||||
f'spacing: {self.spacing}',
|
||||
f'power: {self.power}'
|
||||
'\n'])
|
||||
|
||||
|
||||
class Result_element(Element):
|
||||
def __init__(self,path_request,computed_path):
|
||||
self.path_id = int(path_request.request_id)
|
||||
self.path_request = path_request
|
||||
self.computed_path = computed_path
|
||||
hop_type = []
|
||||
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')
|
||||
self.hop_type = hop_type
|
||||
uid = property(lambda self: repr(self))
|
||||
@property
|
||||
def pathresult(self):
|
||||
return {
|
||||
'path-id': self.path_id,
|
||||
'path-properties':{
|
||||
'path-metric': [
|
||||
{
|
||||
'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+10*log10(self.path_request.baudrate/12.5)),2)
|
||||
}
|
||||
],
|
||||
'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
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@property
|
||||
def json(self):
|
||||
return self.pathresult
|
||||
|
||||
def load_SI(filename):
|
||||
with open(filename) as f:
|
||||
json_data = loads(f.read())
|
||||
return json_data['SI'][0]
|
||||
|
||||
def load_Transceiver(filename):
|
||||
with open(filename) as f:
|
||||
json_data = loads(f.read())
|
||||
return json_data['Transceiver']
|
||||
|
||||
def requests_from_json(json_data,eqpt_filename):
|
||||
requests_list = []
|
||||
tspjsondata = load_Transceiver(eqpt_filename)
|
||||
for req in json_data['path-request']:
|
||||
#print(f'{req}')
|
||||
requests_list.append(Path_request(req,tspjsondata))
|
||||
|
||||
return requests_list
|
||||
|
||||
|
||||
def load_requests(filename,eqpt_filename):
|
||||
if filename.suffix.lower() == '.xls':
|
||||
logger.info('Automatically converting requests from XLS to JSON')
|
||||
json_data = convert_service_sheet(filename,eqpt_filename)
|
||||
else:
|
||||
with open(filename) as f:
|
||||
json_data = loads(f.read())
|
||||
return json_data
|
||||
|
||||
def compute_path(network, pathreqlist):
|
||||
# temporary : repeats calls from transmission_main_example
|
||||
# to be merged when ready
|
||||
|
||||
path_res_list = []
|
||||
trx = [n for n in network.nodes() if isinstance(n, Transceiver)]
|
||||
roadm = [n for n in network.nodes() if isinstance(n, Roadm)]
|
||||
edfa = [n for n in network.nodes() if isinstance(n, Edfa)]
|
||||
# TODO include also fused in the element check : too difficult because of direction
|
||||
# fused = [n for n in network.nodes() if isinstance(n, Fused)]
|
||||
sidata = load_SI(args.eqpt_filename)
|
||||
for pathreq in pathreqlist:
|
||||
pathreq.nodes_list.append(pathreq.destination)
|
||||
#we assume that the destination is a strict constraint
|
||||
pathreq.loose_list.append('strict')
|
||||
print(f'Computing path from {pathreq.source} to {pathreq.destination}')
|
||||
print(f'with explicit path: {pathreq.nodes_list}')
|
||||
|
||||
source = next(el for el in trx if el.uid == pathreq.source)
|
||||
# start the path with its source
|
||||
total_path = [source]
|
||||
for n in pathreq.nodes_list:
|
||||
# print(n)
|
||||
try :
|
||||
node = next(el for el in trx if el.uid == n)
|
||||
except StopIteration:
|
||||
try:
|
||||
node = next(el for el in roadm if el.uid == f'roadm {n}')
|
||||
except StopIteration:
|
||||
try:
|
||||
node = next(el for el in edfa
|
||||
if el.uid.startswith(f'egress edfa in {n}'))
|
||||
except StopIteration:
|
||||
msg = f'could not find node : {n} in network topology: \
|
||||
not a trx, roadm, edfa or fused element'
|
||||
logger.critical(msg)
|
||||
raise ValueError(msg)
|
||||
# extend path list without repeating source -> skip first element in the list
|
||||
try:
|
||||
total_path.extend(dijkstra_path(network, source, node)[1:])
|
||||
source = node
|
||||
except NetworkXNoPath:
|
||||
# for debug
|
||||
# print(pathreq.loose_list)
|
||||
# print(pathreq.nodes_list.index(n))
|
||||
if pathreq.loose_list[pathreq.nodes_list.index(n)] == 'loose':
|
||||
print(f'could not find a path from {source.uid} to loose node : {n} in network topology')
|
||||
print(f'node {n} is skipped')
|
||||
else:
|
||||
msg = f'could not find a path from {source.uid} to node : {n} in network topology'
|
||||
logger.critical(msg)
|
||||
raise ValueError(msg)
|
||||
# for debug
|
||||
# print(f'{pathreq.baudrate} {pathreq.power} {pathreq.spacing} {pathreq.nb_channel}')
|
||||
si = create_input_spectral_information(
|
||||
sidata['f_min'], sidata['roll_off'],
|
||||
pathreq.baudrate, pathreq.power, pathreq.spacing, pathreq.nb_channel)
|
||||
for el in total_path:
|
||||
si = el(si)
|
||||
# print(el)
|
||||
# we record the last tranceiver object in order to have th whole
|
||||
# information about spectrum. Important Note: since transceivers
|
||||
# attached to roadms are actually logical elements to simulate
|
||||
# performance, several demands having the same destination may use
|
||||
# the same transponder for the performance simaulation. This is why
|
||||
# we use deepcopy: to ensure each propagation is recorded and not
|
||||
# overwritten
|
||||
|
||||
# path_res_list.append(deepcopy(destination))
|
||||
path_res_list.append(deepcopy(total_path))
|
||||
return path_res_list
|
||||
|
||||
def path_result_json(pathresult):
|
||||
data = {
|
||||
'path': [n.json for n in pathresult]
|
||||
}
|
||||
return data
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parser.parse_args()
|
||||
basicConfig(level={2: DEBUG, 1: INFO, 0: CRITICAL}.get(args.verbose, CRITICAL))
|
||||
logger.info(f'Computing path requests {args.service_filename} into JSON format')
|
||||
# for debug
|
||||
# print( args.eqpt_filename)
|
||||
data = load_requests(args.service_filename,args.eqpt_filename)
|
||||
equipment = load_equipment(args.eqpt_filename)
|
||||
network = load_network(args.network_filename,equipment)
|
||||
build_network(network, equipment=equipment)
|
||||
pths = requests_from_json(data, args.eqpt_filename)
|
||||
print(pths)
|
||||
test = compute_path(network,pths)
|
||||
|
||||
if args.output is None:
|
||||
#TODO write results
|
||||
print("demand\t\t\t\tsnr@bandwidth\tsnr@0.1nm")
|
||||
|
||||
for i, p in enumerate(test):
|
||||
print(f'{pths[i].source} to {pths[i].destination} : {round(mean(p[-1].snr),2)} ,\
|
||||
{round(mean(p[-1].snr+10*log10(pths[i].baudrate/(12.5e9))),2)}')
|
||||
else:
|
||||
result = []
|
||||
for p in test:
|
||||
result.append(Result_element(pths[test.index(p)],p))
|
||||
with open(args.output, 'w') as f:
|
||||
f.write(dumps(path_result_json(result), indent=2))
|
||||
@@ -5,8 +5,8 @@ reads from network json (default = examples/edfa/edfa_example_network.json)
|
||||
propagates a 96 channels comb
|
||||
'''
|
||||
|
||||
from gnpy.core.equipment import equipment_from_json
|
||||
from gnpy.core.utils import db2lin, lin2db, load_json
|
||||
from gnpy.core.equipment import load_equipment
|
||||
from gnpy.core.utils import db2lin, lin2db
|
||||
from argparse import ArgumentParser
|
||||
from sys import exit
|
||||
from pathlib import Path
|
||||
@@ -18,8 +18,7 @@ from matplotlib.pyplot import show, axis, figure, title
|
||||
from networkx import (draw_networkx_nodes, draw_networkx_edges,
|
||||
draw_networkx_labels, dijkstra_path)
|
||||
|
||||
from convert import convert_file
|
||||
from gnpy.core import network_from_json, build_network
|
||||
from gnpy.core import load_network, build_network
|
||||
from gnpy.core.elements import Transceiver, Fiber, Edfa, Roadm
|
||||
from gnpy.core.info import SpectralInformation, Channel, Power
|
||||
|
||||
@@ -49,22 +48,6 @@ def plot_results(network, path, source, sink):
|
||||
show()
|
||||
|
||||
|
||||
def load_network(filename, equipment):
|
||||
json_filename = ''
|
||||
if args.filename.suffix.lower() == '.xls':
|
||||
logger.info('Automatically generating topology JSON file')
|
||||
json_filename = convert_file(args.filename)
|
||||
elif args.filename.suffix.lower() == '.json':
|
||||
json_filename = args.filename
|
||||
else:
|
||||
raise ValueError(f'unsuported topology filename extension {args.filename.suffix.lower()}')
|
||||
json_data = load_json(json_filename)
|
||||
return network_from_json(json_data, equipment)
|
||||
|
||||
def load_equipment(filename):
|
||||
json_data = load_json(filename)
|
||||
return equipment_from_json(json_data, filename)
|
||||
|
||||
def main(network, equipment, source, sink):
|
||||
build_network(network, equipment=equipment)
|
||||
path = dijkstra_path(network, source, sink)
|
||||
@@ -108,6 +91,7 @@ if __name__ == '__main__':
|
||||
# logger.info(equipment)
|
||||
|
||||
network = load_network(args.filename, equipment)
|
||||
print(network)
|
||||
|
||||
transceivers = {n.uid: n for n in network.nodes() if isinstance(n, Transceiver)}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ def convert_file(input_filename, filter_region=[]):
|
||||
'params': {'length': round(x.west_distance, 3),
|
||||
'length_units': x.distance_units,
|
||||
'loss_coef': x.west_lineic}
|
||||
}
|
||||
} # missing ILA construction
|
||||
for x in links] +
|
||||
[{'uid': f'egress edfa in {e.from_city} to {e.to_city}',
|
||||
'metadata': {'location': {'city': nodes_by_city[e.from_city].city,
|
||||
@@ -11,13 +11,14 @@ from operator import itemgetter
|
||||
from math import isclose
|
||||
from pathlib import Path
|
||||
from json import loads
|
||||
from gnpy.core.utils import lin2db, db2lin
|
||||
from gnpy.core.utils import lin2db, db2lin, load_json
|
||||
from collections import namedtuple
|
||||
|
||||
Model = namedtuple('Model', 'nf1 nf2 delta_p')
|
||||
Fiber = namedtuple('Fiber', 'type_variety dispersion gamma')
|
||||
Spans = namedtuple('Spans', 'max_length length_units max_loss padding EOL con_loss')
|
||||
Roadms = namedtuple('Roadms', 'loss')
|
||||
Transceiver = namedtuple('Transceiver', 'type_variety frequency mode')
|
||||
SI = namedtuple('SI', 'f_min Nch baud_rate spacing roll_off power')
|
||||
EdfaBase = namedtuple(
|
||||
'EdfaBase',
|
||||
@@ -107,6 +108,11 @@ def edfa_nf(gain, variety_type, equipment):
|
||||
nf_avg = polyval(edfa.nf_fit_coeff, dg)
|
||||
return nf_avg + pad # input VOA = 1 for 1 NF degradation
|
||||
|
||||
|
||||
def load_equipment(filename):
|
||||
json_data = load_json(filename)
|
||||
return equipment_from_json(json_data, filename)
|
||||
|
||||
def equipment_from_json(json_data, filename):
|
||||
"""build global dictionnary eqpt_library that stores all eqpt characteristics:
|
||||
edfa type type_variety, fiber type_variety
|
||||
|
||||
@@ -49,6 +49,13 @@ class SpectralInformation(namedtuple('SpectralInformation', 'carriers'), Conveni
|
||||
return super().__new__(cls, carriers)
|
||||
|
||||
|
||||
def create_input_spectral_information(f_min, roll_off, baudrate, power, spacing, nb_channel):
|
||||
si = SpectralInformation() # !! SI units W, Hz
|
||||
si = si.update(carriers=tuple(
|
||||
Channel(f, (f_min+spacing*f),
|
||||
baudrate, roll_off, Power(power, 0, 0)) for f in range(1,nb_channel+1)))
|
||||
return si
|
||||
|
||||
if __name__ == '__main__':
|
||||
si = SpectralInformation(
|
||||
Channel(1, 193.95e12, 32e9, 0.15, # 193.95 THz, 32 Gbaud
|
||||
|
||||
@@ -7,7 +7,7 @@ gnpy.core.network
|
||||
This module contains functions for constructing networks of network elements.
|
||||
'''
|
||||
|
||||
|
||||
from gnpy.core.convert import convert_file
|
||||
from networkx import DiGraph
|
||||
from logging import getLogger
|
||||
from operator import itemgetter
|
||||
@@ -15,9 +15,21 @@ from gnpy.core import elements
|
||||
from gnpy.core.elements import Fiber, Edfa, Transceiver, Roadm, Fused
|
||||
from gnpy.core.equipment import edfa_nf
|
||||
from gnpy.core.units import UNITS
|
||||
from gnpy.core.utils import load_json
|
||||
|
||||
logger = getLogger(__name__)
|
||||
|
||||
def load_network(filename, equipment):
|
||||
json_filename = ''
|
||||
if filename.suffix.lower() == '.xls':
|
||||
logger.info('Automatically generating topology JSON file')
|
||||
json_filename = convert_file(filename)
|
||||
elif filename.suffix.lower() == '.json':
|
||||
json_filename = filename
|
||||
else:
|
||||
raise ValueError(f'unsuported topology filename extension {filename.suffix.lower()}')
|
||||
json_data = load_json(json_filename)
|
||||
return network_from_json(json_data, equipment)
|
||||
|
||||
def network_from_json(json_data, equipment):
|
||||
# NOTE|dutc: we could use the following, but it would tie our data format
|
||||
|
||||
40
path_result_template.json
Normal file
40
path_result_template.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"path": {
|
||||
"path-id": null,
|
||||
"path-properties": {
|
||||
"path-metric": [
|
||||
{
|
||||
"metric-type": null,
|
||||
"accumulative-value": null
|
||||
}
|
||||
],
|
||||
"path-srlgs": {
|
||||
"usage": "not used yet",
|
||||
"values": ["not used yet"]
|
||||
},
|
||||
"path-route-objects": [
|
||||
{
|
||||
"path-route-object": {
|
||||
"index": null,
|
||||
"unnumbered-hop": {
|
||||
"node-id": null,
|
||||
"link-tp-id": null,
|
||||
"hop-type": null,
|
||||
"direction": "not used"
|
||||
},
|
||||
"label-hop": {
|
||||
"te-label": {
|
||||
"generic": "not used yet",
|
||||
"direction": "not used yet"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
59
service-template.json
Normal file
59
service-template.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"path-request": [
|
||||
{
|
||||
"request-id": null,
|
||||
"source": null,
|
||||
"destination": null,
|
||||
"src-tp-id": null,
|
||||
"dst-tp-id": null,
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": null,
|
||||
"trx_mode": null,
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": null,
|
||||
"max-nb-of-channel": null,
|
||||
"output-power": 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-id": null,
|
||||
"svec": {
|
||||
"relaxable": "True",
|
||||
"link-diverse": "False",
|
||||
"node-diverse": "False",
|
||||
"request-id-number": [
|
||||
null ]
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
3
setup.py
3
setup.py
@@ -33,6 +33,7 @@ setup(
|
||||
'Topic :: Scientific/Engineering :: Physics',
|
||||
],
|
||||
keywords='optics network fiber communication route planning optimization',
|
||||
packages=find_packages(exclude=['examples', 'docs', 'tests']), # Required
|
||||
#packages=find_packages(exclude=['examples', 'docs', 'tests']), # Required
|
||||
packages=find_packages(exclude=['docs', 'tests']), # Required
|
||||
install_requires=list(open('requirements.txt'))
|
||||
)
|
||||
|
||||
@@ -7,19 +7,18 @@ from gnpy.core.elements import Edfa
|
||||
import numpy as np
|
||||
from json import load, dumps
|
||||
import pytest
|
||||
from gnpy.core import network_from_json
|
||||
from gnpy.core.elements import Transceiver, Fiber, Edfa
|
||||
from gnpy.core.utils import lin2db, db2lin , load_json
|
||||
from gnpy.core.info import SpectralInformation, Channel, Power
|
||||
from gnpy.core.equipment import read_eqpt_library
|
||||
from gnpy.core.network import build_network
|
||||
from examples.convert import convert_file
|
||||
from gnpy.core.utils import lin2db, db2lin
|
||||
from gnpy.core.info import create_input_spectral_information, SpectralInformation, Channel, Power
|
||||
from gnpy.core.equipment import load_equipment
|
||||
from gnpy.core.network import build_network, load_network
|
||||
from pathlib import Path
|
||||
import filecmp
|
||||
|
||||
#network_file_name = 'tests/test_network.json'
|
||||
network_file_name = 'tests/test_network.json'
|
||||
eqpt_library_name = 'examples/eqpt_config.json'
|
||||
network_file_name = Path(__file__).parent.parent / 'tests/test_network.json'
|
||||
#network_file_name = Path(__file__).parent.parent / 'examples/edfa_example_network.json'
|
||||
eqpt_library_name = Path(__file__).parent.parent / 'examples/eqpt_config.json'
|
||||
|
||||
@pytest.fixture(params=[(96, 0.05e12), (60, 0.075e12), (45, 0.1e12), (2, 0.1e12)],
|
||||
ids=['50GHz spacing', '75GHz spacing', '100GHz spacing', '2 channels'])
|
||||
@@ -38,23 +37,24 @@ def setup_edfa():
|
||||
"""init edfa class by reading test_network.json file
|
||||
remove all gain and nf ripple"""
|
||||
# eqpt_library = pytest_eqpt_library()
|
||||
read_eqpt_library(eqpt_library_name)
|
||||
with open(network_file_name) as network_file:
|
||||
network_json = load(network_file)
|
||||
network = network_from_json(network_json)
|
||||
equipment = load_equipment(eqpt_library_name)
|
||||
network = load_network(network_file_name,equipment)
|
||||
build_network(network, equipment=equipment)
|
||||
edfa = [n for n in network.nodes() if isinstance(n, Edfa)][0]
|
||||
|
||||
#edfa.params.dgt = np.zeros(96)
|
||||
edfa.params.gain_ripple = np.zeros(96)
|
||||
edfa.params.nf_ripple = np.zeros(96)
|
||||
# edfa.params.gain_ripple = np.zeros(96)
|
||||
# edfa.params.nf_ripple = np.zeros(96)
|
||||
edfa.gain_ripple = np.zeros(96)
|
||||
edfa.interpol_nf_ripple = np.zeros(96)
|
||||
yield edfa
|
||||
|
||||
@pytest.fixture()
|
||||
def setup_trx():
|
||||
"""init transceiver class to access snr and osnr calculations"""
|
||||
with open(network_file_name) as network_file:
|
||||
network_json = load(network_file)
|
||||
network = network_from_json(network_json)
|
||||
equipment = load_equipment(eqpt_library_name)
|
||||
network = load_network(network_file_name,equipment)
|
||||
build_network(network, equipment=equipment)
|
||||
trx = [n for n in network.nodes() if isinstance(n, Transceiver)][0]
|
||||
return trx
|
||||
|
||||
@@ -62,10 +62,7 @@ def setup_trx():
|
||||
def si(nch_and_spacing, bw):
|
||||
"""parametrize a channel comb with nch, spacing and signal bw"""
|
||||
nch, spacing = nch_and_spacing
|
||||
si = SpectralInformation()
|
||||
si = si.update(carriers=tuple(Channel(f, 191.3e12+spacing*f,
|
||||
bw, 0.15, Power(1e-6, 0, 0)) for f in range(1,nch+1)))
|
||||
return si
|
||||
return create_input_spectral_information(191.3e12, 0.15, bw, 1e-6, spacing, nch)
|
||||
|
||||
@pytest.mark.parametrize("enabled", [True, False])
|
||||
@pytest.mark.parametrize("gain, nf_expected", [(10, 15), (15, 10), (25, 5.8)])
|
||||
@@ -80,7 +77,7 @@ def test_nf_calc(gain, nf_expected, enabled, setup_edfa, si):
|
||||
pin = np.array([c.power.signal+c.power.nli+c.power.ase for c in si.carriers])
|
||||
baud_rates = np.array([c.baud_rate for c in si.carriers])
|
||||
edfa.operational.gain_target = gain
|
||||
edfa.params.nf_model_enabled = enabled
|
||||
# edfa.params.nf_model_enabled = enabled
|
||||
edfa.interpol_params(frequencies, pin, baud_rates)
|
||||
|
||||
nf = edfa.nf
|
||||
@@ -99,11 +96,11 @@ def test_compare_nf_models(gain, setup_edfa, si):
|
||||
pin = np.array([c.power.signal+c.power.nli+c.power.ase for c in si.carriers])
|
||||
baud_rates = np.array([c.baud_rate for c in si.carriers])
|
||||
edfa.operational.gain_target = gain
|
||||
edfa.params.nf_model_enabled = True
|
||||
# edfa.params.nf_model_enabled = True
|
||||
edfa.interpol_params(frequencies, pin, baud_rates)
|
||||
nf_model = edfa.nf[0]
|
||||
|
||||
edfa.params.nf_model_enabled = False
|
||||
# edfa.params.nf_model_enabled = False
|
||||
edfa.interpol_params(frequencies, pin, baud_rates)
|
||||
nf_poly = edfa.nf[0]
|
||||
dif = abs(nf_model - nf_poly)
|
||||
@@ -130,7 +127,7 @@ def test_ase_noise(gain, si, setup_edfa, setup_trx, bw):
|
||||
pin = np.array([c.power.signal+c.power.nli+c.power.ase for c in si.carriers])
|
||||
baud_rates = np.array([c.baud_rate for c in si.carriers])
|
||||
edfa.operational.gain_target = gain
|
||||
edfa.params.nf_model_enabled = False
|
||||
# edfa.params.nf_model_enabled = False
|
||||
edfa.interpol_params(frequencies, pin, baud_rates)
|
||||
nf = edfa.nf
|
||||
pin = lin2db(pin[0]*1e3)
|
||||
@@ -150,39 +147,3 @@ def test_ase_noise(gain, si, setup_edfa, setup_trx, bw):
|
||||
assert dif < 0.01
|
||||
|
||||
|
||||
# adding tests to check the parser non regression
|
||||
# convention of naming of test files:
|
||||
# - excelTest... .xls for the xls undertest
|
||||
# - test... .json for the reference output
|
||||
excel_filename = ['tests/excelTestFile.xls',
|
||||
'examples/CORONET_Global_Topology.xls']
|
||||
test_filenames = {'tests/excelTestFile.xls':'tests/testFile.json',
|
||||
'examples/CORONET_Global_Topology.xls':'tests/CORONET_Global_Topology.json'}
|
||||
@pytest.mark.parametrize("inputfile",excel_filename)
|
||||
def test_excel_json_generation(inputfile) :
|
||||
convert_file(Path(inputfile))
|
||||
json_filename = f'{inputfile[:-3]}json'
|
||||
test_filename = test_filenames[inputfile]
|
||||
print(json_filename)
|
||||
print(test_filename)
|
||||
|
||||
assert filecmp.cmp(json_filename,test_filename) is True
|
||||
|
||||
# assume json entries
|
||||
# test that the build network gives correct results
|
||||
# json_filename = ['tests/testFile.json',
|
||||
# 'examples/CORONET_Global_Topology.json']
|
||||
# @pytest.mark.parametrize("inputfile",json_filename)
|
||||
# def test_network_generation(inputfile) :
|
||||
# json_data = load_json(inputfile)
|
||||
# read_eqpt_library(Path(eqpt_library_name))
|
||||
|
||||
# network = network_from_json(json_data)
|
||||
# build_network(network)
|
||||
# for n in network.nodes():
|
||||
# print(f'elements: {n},\n')
|
||||
# print(',connections: [\n')
|
||||
# for u, v in network.edges():
|
||||
# print(f'[from_node: {u.uid}, to_node: {v.uid} ]')
|
||||
|
||||
# assert False
|
||||
Binary file not shown.
82
tests/excelTestFile_services_expected.json
Normal file
82
tests/excelTestFile_services_expected.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"path-request": [
|
||||
{
|
||||
"request-id": 0,
|
||||
"source": "BREST_KLA",
|
||||
"destination": "Vannes_KBE",
|
||||
"src-tp-id": "trx BREST_KLA",
|
||||
"dst-tp-id": "trx Vannes_KBE",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager_16QAM",
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.001
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 1,
|
||||
"source": "Lorient_KMA",
|
||||
"destination": "Vannes_KBE",
|
||||
"src-tp-id": "trx Lorient_KMA",
|
||||
"dst-tp-id": "trx Vannes_KBE",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager_16QAM",
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.001
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"synchronisation": [
|
||||
{
|
||||
"synchonization-id": 0,
|
||||
"svec": {
|
||||
"relaxable": "False",
|
||||
"link-diverse": "True",
|
||||
"node-diverse": "True",
|
||||
"request-id-number": [
|
||||
0,
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"synchonization-id": 1,
|
||||
"svec": {
|
||||
"relaxable": "False",
|
||||
"link-diverse": "True",
|
||||
"node-diverse": "True",
|
||||
"request-id-number": [
|
||||
1,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
tests/meshTopologyExampleV2.xls
Normal file
BIN
tests/meshTopologyExampleV2.xls
Normal file
Binary file not shown.
BIN
tests/meshTopologyExampleV2Eqpt.xls
Normal file
BIN
tests/meshTopologyExampleV2Eqpt.xls
Normal file
Binary file not shown.
768
tests/meshTopologyExampleV2Eqpt_expected.json
Normal file
768
tests/meshTopologyExampleV2Eqpt_expected.json
Normal file
@@ -0,0 +1,768 @@
|
||||
{
|
||||
"elements": [
|
||||
{
|
||||
"uid": "trx Lannion_CAS",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lannion_CAS",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx Lorient_KMA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lorient_KMA",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx Vannes_KBE",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Vannes_KBE",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 4.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx Rennes_STA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Rennes_STA",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx Brest_KLA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Brest_KLA",
|
||||
"region": "RLD",
|
||||
"latitude": 4.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx toto",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "toto",
|
||||
"region": "",
|
||||
"latitude": 6.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx tata",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "tata",
|
||||
"region": "",
|
||||
"latitude": 7.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Lannion_CAS",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lannion_CAS",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Lorient_KMA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lorient_KMA",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Vannes_KBE",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Vannes_KBE",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 4.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Rennes_STA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Rennes_STA",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Brest_KLA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Brest_KLA",
|
||||
"region": "RLD",
|
||||
"latitude": 4.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm toto",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "toto",
|
||||
"region": "",
|
||||
"latitude": 6.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm tata",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "tata",
|
||||
"region": "",
|
||||
"latitude": 7.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "ingress fused spans in Corlay",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Corlay",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "ingress fused spans in Loudeac",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Loudeac",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "ingress fused spans in Morlaix",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Morlaix",
|
||||
"region": "RLD",
|
||||
"latitude": 3.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "egress fused spans in Corlay",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Corlay",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "egress fused spans in Loudeac",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Loudeac",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "egress fused spans in Morlaix",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Morlaix",
|
||||
"region": "RLD",
|
||||
"latitude": 3.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Corlay)-F061",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 20.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Corlay \u2192 Loudeac)-F010",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 50.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Loudeac \u2192 Lorient_KMA)-F054",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 10.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 1.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 65.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 40.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Morlaix \u2192 Brest_KLA)-F060",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 3.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 35.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (toto \u2192 tata)-",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 6.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Corlay \u2192 Lannion_CAS)-F061",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 20.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Loudeac \u2192 Corlay)-F010",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 50.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lorient_KMA \u2192 Loudeac)-F054",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 10.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 1.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 65.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 40.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Brest_KLA \u2192 Morlaix)-F060",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 3.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 35.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (tata \u2192 toto)-",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 6.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "egress edfa in Lannion_CAS to Corlay",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lannion_CAS",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 0,
|
||||
"tilt_target": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "egress edfa in Lorient_KMA to Loudeac",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lorient_KMA",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.0
|
||||
}
|
||||
},
|
||||
"type": "Edfa",
|
||||
"type_variety": "test",
|
||||
"operational": {
|
||||
"gain_target": 0,
|
||||
"tilt_target": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "egress edfa in Lannion_CAS to Corlay"
|
||||
},
|
||||
{
|
||||
"from_node": "egress edfa in Lannion_CAS to Corlay",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Corlay)-F061"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Corlay \u2192 Lannion_CAS)-F061",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Morlaix)-F059"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Corlay)-F061",
|
||||
"to_node": "ingress fused spans in Corlay"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Corlay",
|
||||
"to_node": "fiber (Corlay \u2192 Loudeac)-F010"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Loudeac \u2192 Corlay)-F010",
|
||||
"to_node": "egress fused spans in Corlay"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Corlay",
|
||||
"to_node": "fiber (Corlay \u2192 Lannion_CAS)-F061"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Corlay \u2192 Loudeac)-F010",
|
||||
"to_node": "ingress fused spans in Loudeac"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Loudeac",
|
||||
"to_node": "fiber (Loudeac \u2192 Lorient_KMA)-F054"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lorient_KMA \u2192 Loudeac)-F054",
|
||||
"to_node": "egress fused spans in Loudeac"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Loudeac",
|
||||
"to_node": "fiber (Loudeac \u2192 Corlay)-F010"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lorient_KMA",
|
||||
"to_node": "egress edfa in Lorient_KMA to Loudeac"
|
||||
},
|
||||
{
|
||||
"from_node": "egress edfa in Lorient_KMA to Loudeac",
|
||||
"to_node": "fiber (Lorient_KMA \u2192 Loudeac)-F054"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Loudeac \u2192 Lorient_KMA)-F054",
|
||||
"to_node": "roadm Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lorient_KMA",
|
||||
"to_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
|
||||
"to_node": "roadm Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Vannes_KBE",
|
||||
"to_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
|
||||
"to_node": "roadm Vannes_KBE"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
|
||||
"to_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
|
||||
"to_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Rennes_STA",
|
||||
"to_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
|
||||
"to_node": "roadm Rennes_STA"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
|
||||
"to_node": "ingress fused spans in Morlaix"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Morlaix",
|
||||
"to_node": "fiber (Morlaix \u2192 Brest_KLA)-F060"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Brest_KLA \u2192 Morlaix)-F060",
|
||||
"to_node": "egress fused spans in Morlaix"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Morlaix",
|
||||
"to_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Brest_KLA",
|
||||
"to_node": "fiber (Brest_KLA \u2192 Morlaix)-F060"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Morlaix \u2192 Brest_KLA)-F060",
|
||||
"to_node": "roadm Brest_KLA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm toto",
|
||||
"to_node": "fiber (toto \u2192 tata)-"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (tata \u2192 toto)-",
|
||||
"to_node": "roadm toto"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm tata",
|
||||
"to_node": "fiber (tata \u2192 toto)-"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (toto \u2192 tata)-",
|
||||
"to_node": "roadm tata"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Lannion_CAS",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "trx Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Lorient_KMA",
|
||||
"to_node": "roadm Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lorient_KMA",
|
||||
"to_node": "trx Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Vannes_KBE",
|
||||
"to_node": "roadm Vannes_KBE"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Vannes_KBE",
|
||||
"to_node": "trx Vannes_KBE"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Rennes_STA",
|
||||
"to_node": "roadm Rennes_STA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Rennes_STA",
|
||||
"to_node": "trx Rennes_STA"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Brest_KLA",
|
||||
"to_node": "roadm Brest_KLA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Brest_KLA",
|
||||
"to_node": "trx Brest_KLA"
|
||||
},
|
||||
{
|
||||
"from_node": "trx toto",
|
||||
"to_node": "roadm toto"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm toto",
|
||||
"to_node": "trx toto"
|
||||
},
|
||||
{
|
||||
"from_node": "trx tata",
|
||||
"to_node": "roadm tata"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm tata",
|
||||
"to_node": "trx tata"
|
||||
}
|
||||
]
|
||||
}
|
||||
219
tests/meshTopologyExampleV2Eqpt_services_expected.json
Normal file
219
tests/meshTopologyExampleV2Eqpt_services_expected.json
Normal file
@@ -0,0 +1,219 @@
|
||||
{
|
||||
"path-request": [
|
||||
{
|
||||
"request-id": 0,
|
||||
"source": "Lorient_KMA",
|
||||
"destination": "Vannes_KBE",
|
||||
"src-tp-id": "trx Lorient_KMA",
|
||||
"dst-tp-id": "trx Vannes_KBE",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager_16QAM",
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.0012589254117941673
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 1,
|
||||
"source": "Brest_KLA",
|
||||
"destination": "Vannes_KBE",
|
||||
"src-tp-id": "trx Brest_KLA",
|
||||
"dst-tp-id": "trx Vannes_KBE",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager_16QAM",
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.0012589254117941673
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": [
|
||||
{
|
||||
"index": 0,
|
||||
"unnumbered-hop": {
|
||||
"node-id": "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"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"unnumbered-hop": {
|
||||
"node-id": "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"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 3,
|
||||
"source": "Lannion_CAS",
|
||||
"destination": "Rennes_STA",
|
||||
"src-tp-id": "trx Lannion_CAS",
|
||||
"dst-tp-id": "trx Rennes_STA",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "vendorA_trx-type1",
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.0012589254117941673
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 4,
|
||||
"source": "Rennes_STA",
|
||||
"destination": "Lannion_CAS",
|
||||
"src-tp-id": "trx Rennes_STA",
|
||||
"dst-tp-id": "trx Lannion_CAS",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "vendorA_trx-type1",
|
||||
"trx_mode": "PS_SP64_2",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
"max-nb-of-channel": 64,
|
||||
"output-power": 0.0019952623149688794
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 5,
|
||||
"source": "Lorient_KMA",
|
||||
"destination": "Lannion_CAS",
|
||||
"src-tp-id": "trx Lorient_KMA",
|
||||
"dst-tp-id": "trx Lannion_CAS",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager_16QAM",
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.0012589254117941673
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": [
|
||||
{
|
||||
"index": 0,
|
||||
"unnumbered-hop": {
|
||||
"node-id": "toto",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"synchronisation": [
|
||||
{
|
||||
"synchonization-id": 0,
|
||||
"svec": {
|
||||
"relaxable": "False",
|
||||
"link-diverse": "True",
|
||||
"node-diverse": "True",
|
||||
"request-id-number": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"synchonization-id": 3,
|
||||
"svec": {
|
||||
"relaxable": "False",
|
||||
"link-diverse": "True",
|
||||
"node-diverse": "True",
|
||||
"request-id-number": [
|
||||
3,
|
||||
4
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"synchonization-id": 5,
|
||||
"svec": {
|
||||
"relaxable": "False",
|
||||
"link-diverse": "True",
|
||||
"node-diverse": "True",
|
||||
"request-id-number": [
|
||||
5,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
726
tests/meshTopologyExampleV2_expected.json
Normal file
726
tests/meshTopologyExampleV2_expected.json
Normal file
@@ -0,0 +1,726 @@
|
||||
{
|
||||
"elements": [
|
||||
{
|
||||
"uid": "trx Lannion_CAS",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lannion_CAS",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx Lorient_KMA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lorient_KMA",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx Vannes_KBE",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Vannes_KBE",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 4.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx Rennes_STA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Rennes_STA",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx Brest_KLA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Brest_KLA",
|
||||
"region": "RLD",
|
||||
"latitude": 4.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx toto",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "toto",
|
||||
"region": "",
|
||||
"latitude": 6.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "trx tata",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "tata",
|
||||
"region": "",
|
||||
"latitude": 7.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Transceiver"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Lannion_CAS",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lannion_CAS",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Lorient_KMA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Lorient_KMA",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Vannes_KBE",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Vannes_KBE",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 4.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Rennes_STA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Rennes_STA",
|
||||
"region": "RLD",
|
||||
"latitude": 0.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm Brest_KLA",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Brest_KLA",
|
||||
"region": "RLD",
|
||||
"latitude": 4.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm toto",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "toto",
|
||||
"region": "",
|
||||
"latitude": 6.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "roadm tata",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "tata",
|
||||
"region": "",
|
||||
"latitude": 7.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Roadm"
|
||||
},
|
||||
{
|
||||
"uid": "ingress fused spans in Corlay",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Corlay",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "ingress fused spans in Loudeac",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Loudeac",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "ingress fused spans in Morlaix",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Morlaix",
|
||||
"region": "RLD",
|
||||
"latitude": 3.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "egress fused spans in Corlay",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Corlay",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "egress fused spans in Loudeac",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Loudeac",
|
||||
"region": "RLD",
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "egress fused spans in Morlaix",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"city": "Morlaix",
|
||||
"region": "RLD",
|
||||
"latitude": 3.0,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fused"
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Corlay)-F061",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 20.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Corlay \u2192 Loudeac)-F010",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 50.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Loudeac \u2192 Lorient_KMA)-F054",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 10.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 1.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 65.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 40.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Morlaix \u2192 Brest_KLA)-F060",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 3.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 35.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (toto \u2192 tata)-",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 6.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Corlay \u2192 Lannion_CAS)-F061",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 0.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 20.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Loudeac \u2192 Corlay)-F010",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 1.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 50.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Lorient_KMA \u2192 Loudeac)-F054",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 2.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.0,
|
||||
"longitude": 3.5
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 10.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 1.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 60.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 0.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 65.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 2.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 40.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (Brest_KLA \u2192 Morlaix)-F060",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 3.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 35.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"uid": "fiber (tata \u2192 toto)-",
|
||||
"metadata": {
|
||||
"location": {
|
||||
"latitude": 6.5,
|
||||
"longitude": 0.0
|
||||
}
|
||||
},
|
||||
"type": "Fiber",
|
||||
"type_variety": "SSMF",
|
||||
"params": {
|
||||
"length": 80.0,
|
||||
"length_units": "km",
|
||||
"loss_coef": 0.2
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Corlay)-F061"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Corlay \u2192 Lannion_CAS)-F061",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "fiber (Lannion_CAS \u2192 Morlaix)-F059"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Corlay)-F061",
|
||||
"to_node": "ingress fused spans in Corlay"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Corlay",
|
||||
"to_node": "fiber (Corlay \u2192 Loudeac)-F010"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Loudeac \u2192 Corlay)-F010",
|
||||
"to_node": "egress fused spans in Corlay"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Corlay",
|
||||
"to_node": "fiber (Corlay \u2192 Lannion_CAS)-F061"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Corlay \u2192 Loudeac)-F010",
|
||||
"to_node": "ingress fused spans in Loudeac"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Loudeac",
|
||||
"to_node": "fiber (Loudeac \u2192 Lorient_KMA)-F054"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lorient_KMA \u2192 Loudeac)-F054",
|
||||
"to_node": "egress fused spans in Loudeac"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Loudeac",
|
||||
"to_node": "fiber (Loudeac \u2192 Corlay)-F010"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lorient_KMA",
|
||||
"to_node": "fiber (Lorient_KMA \u2192 Loudeac)-F054"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Loudeac \u2192 Lorient_KMA)-F054",
|
||||
"to_node": "roadm Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lorient_KMA",
|
||||
"to_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055",
|
||||
"to_node": "roadm Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Vannes_KBE",
|
||||
"to_node": "fiber (Vannes_KBE \u2192 Lorient_KMA)-F055"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lorient_KMA \u2192 Vannes_KBE)-F055",
|
||||
"to_node": "roadm Vannes_KBE"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Stbrieuc)-F056",
|
||||
"to_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057",
|
||||
"to_node": "fiber (Stbrieuc \u2192 Lannion_CAS)-F056"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Rennes_STA",
|
||||
"to_node": "fiber (Rennes_STA \u2192 Stbrieuc)-F057"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Stbrieuc \u2192 Rennes_STA)-F057",
|
||||
"to_node": "roadm Rennes_STA"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Lannion_CAS \u2192 Morlaix)-F059",
|
||||
"to_node": "ingress fused spans in Morlaix"
|
||||
},
|
||||
{
|
||||
"from_node": "ingress fused spans in Morlaix",
|
||||
"to_node": "fiber (Morlaix \u2192 Brest_KLA)-F060"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Brest_KLA \u2192 Morlaix)-F060",
|
||||
"to_node": "egress fused spans in Morlaix"
|
||||
},
|
||||
{
|
||||
"from_node": "egress fused spans in Morlaix",
|
||||
"to_node": "fiber (Morlaix \u2192 Lannion_CAS)-F059"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Brest_KLA",
|
||||
"to_node": "fiber (Brest_KLA \u2192 Morlaix)-F060"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (Morlaix \u2192 Brest_KLA)-F060",
|
||||
"to_node": "roadm Brest_KLA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm toto",
|
||||
"to_node": "fiber (toto \u2192 tata)-"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (tata \u2192 toto)-",
|
||||
"to_node": "roadm toto"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm tata",
|
||||
"to_node": "fiber (tata \u2192 toto)-"
|
||||
},
|
||||
{
|
||||
"from_node": "fiber (toto \u2192 tata)-",
|
||||
"to_node": "roadm tata"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Lannion_CAS",
|
||||
"to_node": "roadm Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lannion_CAS",
|
||||
"to_node": "trx Lannion_CAS"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Lorient_KMA",
|
||||
"to_node": "roadm Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Lorient_KMA",
|
||||
"to_node": "trx Lorient_KMA"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Vannes_KBE",
|
||||
"to_node": "roadm Vannes_KBE"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Vannes_KBE",
|
||||
"to_node": "trx Vannes_KBE"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Rennes_STA",
|
||||
"to_node": "roadm Rennes_STA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Rennes_STA",
|
||||
"to_node": "trx Rennes_STA"
|
||||
},
|
||||
{
|
||||
"from_node": "trx Brest_KLA",
|
||||
"to_node": "roadm Brest_KLA"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm Brest_KLA",
|
||||
"to_node": "trx Brest_KLA"
|
||||
},
|
||||
{
|
||||
"from_node": "trx toto",
|
||||
"to_node": "roadm toto"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm toto",
|
||||
"to_node": "trx toto"
|
||||
},
|
||||
{
|
||||
"from_node": "trx tata",
|
||||
"to_node": "roadm tata"
|
||||
},
|
||||
{
|
||||
"from_node": "roadm tata",
|
||||
"to_node": "trx tata"
|
||||
}
|
||||
]
|
||||
}
|
||||
219
tests/meshTopologyExampleV2_services_expected.json
Normal file
219
tests/meshTopologyExampleV2_services_expected.json
Normal file
@@ -0,0 +1,219 @@
|
||||
{
|
||||
"path-request": [
|
||||
{
|
||||
"request-id": 0,
|
||||
"source": "Lorient_KMA",
|
||||
"destination": "Vannes_KBE",
|
||||
"src-tp-id": "trx Lorient_KMA",
|
||||
"dst-tp-id": "trx Vannes_KBE",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager_16QAM",
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.0012589254117941673
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 1,
|
||||
"source": "Brest_KLA",
|
||||
"destination": "Vannes_KBE",
|
||||
"src-tp-id": "trx Brest_KLA",
|
||||
"dst-tp-id": "trx Vannes_KBE",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager_16QAM",
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.0012589254117941673
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": [
|
||||
{
|
||||
"index": 0,
|
||||
"unnumbered-hop": {
|
||||
"node-id": "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"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"unnumbered-hop": {
|
||||
"node-id": "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"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 3,
|
||||
"source": "Lannion_CAS",
|
||||
"destination": "Rennes_STA",
|
||||
"src-tp-id": "trx Lannion_CAS",
|
||||
"dst-tp-id": "trx Rennes_STA",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "vendorA_trx-type1",
|
||||
"trx_mode": "PS_SP64_1",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.0012589254117941673
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 4,
|
||||
"source": "Rennes_STA",
|
||||
"destination": "Lannion_CAS",
|
||||
"src-tp-id": "trx Rennes_STA",
|
||||
"dst-tp-id": "trx Lannion_CAS",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "vendorA_trx-type1",
|
||||
"trx_mode": "PS_SP64_2",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 75000000000.0,
|
||||
"max-nb-of-channel": 64,
|
||||
"output-power": 0.0019952623149688794
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"request-id": 5,
|
||||
"source": "Lorient_KMA",
|
||||
"destination": "Lannion_CAS",
|
||||
"src-tp-id": "trx Lorient_KMA",
|
||||
"dst-tp-id": "trx Lannion_CAS",
|
||||
"path-constraints": {
|
||||
"te-bandwidth": {
|
||||
"technology": "flexi-grid",
|
||||
"trx_type": "Voyager_16QAM",
|
||||
"trx_mode": "16QAM",
|
||||
"effective-freq-slot": [
|
||||
{
|
||||
"n": "null",
|
||||
"m": "null"
|
||||
}
|
||||
],
|
||||
"spacing": 50000000000.0,
|
||||
"max-nb-of-channel": 80,
|
||||
"output-power": 0.0012589254117941673
|
||||
}
|
||||
},
|
||||
"optimizations": {
|
||||
"explicit-route-include-objects": [
|
||||
{
|
||||
"index": 0,
|
||||
"unnumbered-hop": {
|
||||
"node-id": "toto",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"synchronisation": [
|
||||
{
|
||||
"synchonization-id": 0,
|
||||
"svec": {
|
||||
"relaxable": "False",
|
||||
"link-diverse": "True",
|
||||
"node-diverse": "True",
|
||||
"request-id-number": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"synchonization-id": 3,
|
||||
"svec": {
|
||||
"relaxable": "False",
|
||||
"link-diverse": "True",
|
||||
"node-diverse": "True",
|
||||
"request-id-number": [
|
||||
3,
|
||||
4
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"synchonization-id": 5,
|
||||
"svec": {
|
||||
"relaxable": "False",
|
||||
"link-diverse": "True",
|
||||
"node-diverse": "True",
|
||||
"request-id-number": [
|
||||
5,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
67
tests/parsers_test.py
Normal file
67
tests/parsers_test.py
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Author: Esther Le Rouzic
|
||||
# @Date: 2018-06-15
|
||||
|
||||
from gnpy.core.elements import Edfa
|
||||
import numpy as np
|
||||
from json import load, dumps
|
||||
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 examples.compare_json import compare_network_file, compare_service_file, compare_result_file
|
||||
from gnpy.core.convert import convert_file
|
||||
from examples.convert_service_sheet import convert_service_sheet
|
||||
from pathlib import Path
|
||||
import filecmp
|
||||
|
||||
|
||||
network_file_name = 'tests/test_network.json'
|
||||
eqpt_library_name = 'examples/eqpt_config.json'
|
||||
|
||||
# adding tests to check the parser non regression
|
||||
# convention of naming of test files:
|
||||
#
|
||||
# - ..._expected.json for the reference output
|
||||
|
||||
excel_filename = ['tests/excelTestFile.xls',
|
||||
'examples/CORONET_Global_Topology.xls',
|
||||
'tests/meshTopologyExampleV2.xls',
|
||||
'tests/meshTopologyExampleV2Eqpt.xls']
|
||||
network_test_filenames = {
|
||||
'tests/excelTestFile.xls' : 'tests/excelTestFile_expected.json',
|
||||
'examples/CORONET_Global_Topology.xls': 'tests/CORONET_Global_Topology_expected.json',
|
||||
'tests/meshTopologyExampleV2.xls' : 'tests/meshTopologyExampleV2_expected.json',
|
||||
'tests/meshTopologyExampleV2Eqpt.xls' : 'tests/meshTopologyExampleV2Eqpt_expected.json'}
|
||||
@pytest.mark.parametrize("inputfile",excel_filename)
|
||||
def test_excel_json_generation(inputfile) :
|
||||
convert_file(Path(inputfile))
|
||||
# actual
|
||||
json_filename = f'{inputfile[:-3]}json'
|
||||
# expected
|
||||
expected_filename = network_test_filenames[inputfile]
|
||||
|
||||
assert compare_network_file(expected_filename,json_filename)[0] is True
|
||||
|
||||
# assume json entries
|
||||
# test that the build network gives correct results
|
||||
# TODO !!
|
||||
|
||||
excel_filename = ['tests/excelTestFile.xls',
|
||||
'tests/meshTopologyExampleV2.xls',
|
||||
'tests/meshTopologyExampleV2Eqpt.xls']
|
||||
service_test_filenames = {
|
||||
'tests/excelTestFile.xls' : 'tests/excelTestFile_services_expected.json',
|
||||
'tests/meshTopologyExampleV2.xls' : 'tests/meshTopologyExampleV2_services_expected.json',
|
||||
'tests/meshTopologyExampleV2Eqpt.xls' : 'tests/meshTopologyExampleV2Eqpt_services_expected.json'}
|
||||
@pytest.mark.parametrize("inputfile",excel_filename)
|
||||
def test_excel_service_json_generation(inputfile) :
|
||||
convert_service_sheet(Path(inputfile),eqpt_library_name)
|
||||
# actual
|
||||
json_filename = f'{inputfile[:-4]}_services.json'
|
||||
# expected
|
||||
test_filename = service_test_filenames[inputfile]
|
||||
|
||||
assert compare_service_file(test_filename,json_filename)[0] is True
|
||||
Reference in New Issue
Block a user