mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-30 17:47:50 +00:00 
			
		
		
		
	Merge pull request #104 from Orange-OpenSource/path_resquest_rundemo
Path resquest rundemo
This commit is contained in:
		| @@ -189,7 +189,7 @@ 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) | ||||
| - **route id** is mandatory. It must be unique. It is the identifier of the request. It can be an integer or a string (do not  use blank or dash) | ||||
|  | ||||
| - **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) | ||||
|  | ||||
|   | ||||
| @@ -53,7 +53,16 @@ class Element: | ||||
|  | ||||
| class Request_element(Element): | ||||
|     def __init__(self,Request,eqpt_filename): | ||||
|         self.request_id = int(Request.request_id) | ||||
|         # request_id is str | ||||
|         # excel has automatic number formatting that adds .0 on integer values  | ||||
|         # the next lines recover the pure int value, assuming this .0 is unwanted | ||||
|         if not isinstance(Request.request_id,str): | ||||
|             value = str(int(Request.request_id)) | ||||
|             if value.endswith('.0'): | ||||
|                 value = value[:-2] | ||||
|             self.request_id = value | ||||
|         else: | ||||
|             self.request_id = Request.request_id | ||||
|         self.source = Request.source | ||||
|         self.destination = Request.destination | ||||
|         self.srctpid = f'trx {Request.source}' | ||||
| @@ -61,21 +70,27 @@ class Request_element(Element): | ||||
|         # test that trx_type belongs to eqpt_config.json | ||||
|         # if not replace it with a default  | ||||
|         equipment = load_equipment(eqpt_filename) | ||||
|         try : | ||||
|             if equipment['Transceiver'][Request.trx_type]: | ||||
|                 self.trx_type = Request.trx_type | ||||
|             if [mode for mode in equipment['Transceiver'][Request.trx_type].mode]: | ||||
|                 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') | ||||
|         except KeyError: | ||||
|             msg = f'could not find tsp : {Request.trx_type} with mode: {Request.mode} in eqpt library \nComputation stopped.' | ||||
|             #print(msg) | ||||
|             logger.critical(msg) | ||||
|             exit() | ||||
|         # excel input are in GHz and dBm | ||||
|         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()] | ||||
|         if not isinstance(Request.disjoint_from,str): | ||||
|             value = str(int(Request.disjoint_from)) | ||||
|             if value.endswith('.0'): | ||||
|                 value = value[:-2] | ||||
|         else: | ||||
|             self.disjoint_from = [int(Request.disjoint_from)] | ||||
|             value = Request.disjoint_from | ||||
|         self.disjoint_from = [n for n in value.split()] | ||||
|         self.nodes_list = [] | ||||
|         if Request.nodes_list : | ||||
|             self.nodes_list = Request.nodes_list.split(' | ') | ||||
| @@ -83,7 +98,7 @@ class Request_element(Element): | ||||
|             self.nodes_list.remove(self.source) | ||||
|             msg = f'{self.source} removed from explicit path node-list' | ||||
|             logger.info(msg) | ||||
|             print(msg) | ||||
|             # print(msg) | ||||
|         except ValueError: | ||||
|             msg = f'{self.source} already removed from explicit path node-list' | ||||
|             logger.info(msg) | ||||
| @@ -92,7 +107,7 @@ class Request_element(Element): | ||||
|             self.nodes_list.remove(self.destination) | ||||
|             msg = f'{self.destination} removed from explicit path node-list' | ||||
|             logger.info(msg) | ||||
|             print(msg) | ||||
|             # print(msg) | ||||
|         except ValueError: | ||||
|             msg = f'{self.destination} already removed from explicit path node-list' | ||||
|             logger.info(msg) | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
|             { | ||||
|             "type_variety": "std_low_gain", | ||||
|             "type_def": "variable_gain", | ||||
|             "gain_flatmax": 17, | ||||
|             "gain_flatmax": 16, | ||||
|             "gain_min": 8, | ||||
|             "p_max": 22, | ||||
|             "nf_min": 6.5, | ||||
| @@ -36,7 +36,7 @@ | ||||
|             "gain_min": 20, | ||||
|             "p_max": 21, | ||||
|             "nf0": 5.5, | ||||
|             "allowed_for_design": true | ||||
|             "allowed_for_design": false | ||||
|             }, | ||||
|             { | ||||
|             "type_variety": "test", | ||||
| @@ -90,6 +90,20 @@ | ||||
|                         "max": 196.1e12 | ||||
|                         }, | ||||
|             "mode":[ | ||||
|                        { | ||||
|                        "format": "mode 1", | ||||
|                        "baud_rate": 32e9, | ||||
|                        "OSNR": 11, | ||||
|                        "bit_rate": 100e9, | ||||
|                        "roll_off": 0.15 | ||||
|                        }, | ||||
|                        { | ||||
|                        "format": "mode 2", | ||||
|                        "baud_rate": 66e9, | ||||
|                        "OSNR": 15, | ||||
|                        "bit_rate": 200e9, | ||||
|                        "roll_off": 0.15 | ||||
|                        }, | ||||
|                        { | ||||
|                        "format": "PS_SP64_1", | ||||
|                        "baud_rate": 32e9, | ||||
| @@ -107,6 +121,30 @@ | ||||
|                    ] | ||||
|             }, | ||||
|             { | ||||
|             "type_variety": "Voyager", | ||||
|             "frequency":{ | ||||
|                         "min": 191.35e12, | ||||
|                         "max": 196.1e12 | ||||
|                         }, | ||||
|             "mode":[ | ||||
|                        { | ||||
|                        "format": "16QAM", | ||||
|                        "baud_rate": 32e9, | ||||
|                        "OSNR": 19, | ||||
|                        "bit_rate": 200e9, | ||||
|                        "roll_off": 0.15 | ||||
|                        }, | ||||
|                        { | ||||
|                        "format": "QPSK", | ||||
|                        "baud_rate": 32e9, | ||||
|                        "OSNR": 12, | ||||
|                        "bit_rate": 100e9, | ||||
|                        "roll_off": 0.15 | ||||
|                        } | ||||
|  | ||||
|                    ] | ||||
|             }, | ||||
|                         { | ||||
|             "type_variety": "Voyager_16QAM", | ||||
|             "frequency":{ | ||||
|                         "min": 191.35e12, | ||||
| @@ -119,7 +157,15 @@ | ||||
|                        "OSNR": 19, | ||||
|                        "bit_rate": 200e9, | ||||
|                        "roll_off": 0.15 | ||||
|                        }, | ||||
|                        { | ||||
|                        "format": "QPSK", | ||||
|                        "baud_rate": 32e9, | ||||
|                        "OSNR": 12, | ||||
|                        "bit_rate": 100e9, | ||||
|                        "roll_off": 0.15 | ||||
|                        } | ||||
|  | ||||
|                    ] | ||||
|             } | ||||
|       ] | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								examples/meshTopologyToy.xls
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								examples/meshTopologyToy.xls
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -30,7 +30,7 @@ from gnpy.core.network import load_network, build_network, set_roadm_loss | ||||
| from gnpy.core.equipment import load_equipment, trx_mode_params | ||||
| from gnpy.core.elements import Transceiver, Roadm, Edfa, Fused | ||||
| from gnpy.core.utils import db2lin, lin2db | ||||
| from gnpy.core.request import Path_request, Result_element, compute_constrained_path, propagate | ||||
| from gnpy.core.request import Path_request, Result_element, compute_constrained_path, propagate, jsontocsv | ||||
| from copy import copy, deepcopy | ||||
|  | ||||
| #EQPT_LIBRARY_FILENAME = Path(__file__).parent / 'eqpt_config.json' | ||||
| @@ -97,14 +97,15 @@ def compute_path(network, equipment, pathreqlist): | ||||
|         #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.source]+pathreq.nodes_list}') #adding first node to be clearer on the output | ||||
|         print(f'with path constraint: {[pathreq.source]+pathreq.nodes_list}') #adding first node to be clearer on the output | ||||
|         total_path = compute_constrained_path(network, pathreq) | ||||
|          | ||||
|         print(f'Computed path (roadms):{[e.uid for e in total_path  if isinstance(e, Roadm)]}\n') | ||||
|         # for debug | ||||
|         # print(f'{pathreq.baud_rate}   {pathreq.power}   {pathreq.spacing}   {pathreq.nb_channel}') | ||||
|          | ||||
|         if total_path : | ||||
|             total_path = propagate(total_path,pathreq,equipment, show=False) | ||||
|  | ||||
|         else: | ||||
|             total_path = [] | ||||
|         # 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 | ||||
| @@ -136,16 +137,32 @@ if __name__ == '__main__': | ||||
|     print(pths) | ||||
|     test = compute_path(network, equipment, pths) | ||||
|      | ||||
|     if args.output is None: | ||||
|     #TODO write results | ||||
|         print("demand\t\t\t\tsnr@bandwidth\tsnr@0.1nm") | ||||
|  | ||||
|     header = ['demand','snr@bandwidth','snr@0.1nm','Receiver minOSNR'] | ||||
|     data = [] | ||||
|     data.append(header) | ||||
|     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+lin2db(pths[i].baud_rate/(12.5e9))),2)}') | ||||
|         if p: | ||||
|             line = [f'{pths[i].source} to {pths[i].destination} : ', f'{round(mean(p[-1].snr),2)}',\ | ||||
|                 f'{round(mean(p[-1].snr+lin2db(pths[i].baud_rate/(12.5e9))),2)}',\ | ||||
|                 f'{pths[i].OSNR}'] | ||||
|         else: | ||||
|             line = [f'no path from {pths[i].source} to {pths[i].destination} '] | ||||
|         data.append(line) | ||||
|  | ||||
|     col_width = max(len(word) for row in data for word in row)   # padding | ||||
|     for row in data: | ||||
|         print(''.join(word.ljust(col_width) for word in row)) | ||||
|  | ||||
|  | ||||
|  | ||||
|     if args.output : | ||||
|         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)) | ||||
|             fnamecsv = next(s for s in args.output.split('.')) + '.csv' | ||||
|             with open(fnamecsv,"w") as fcsv : | ||||
|                 jsontocsv(path_result_json(result),equipment,fcsv) | ||||
| @@ -14,80 +14,26 @@ and write results in an CSV file | ||||
|  | ||||
| """ | ||||
|  | ||||
| from sys import exit | ||||
| from csv import writer | ||||
| from argparse import ArgumentParser | ||||
| from pathlib import Path | ||||
| from json import dumps, loads | ||||
| from json import loads | ||||
| from gnpy.core.equipment  import load_equipment | ||||
| from gnpy.core.utils import lin2db | ||||
|  | ||||
| START_LINE = 5 | ||||
| from gnpy.core.request  import jsontocsv | ||||
|  | ||||
|  | ||||
| parser = ArgumentParser(description = 'A function that writes json path results in an excel sheet.') | ||||
| parser.add_argument('filename', nargs='?', type = Path) | ||||
| parser.add_argument('eqpt_filename', nargs='?', type = Path) | ||||
|  | ||||
| parser.add_argument('output_filename', nargs='?', type = Path) | ||||
| parser.add_argument('eqpt_filename', nargs='?', type = Path, default=Path(__file__).parent / 'eqpt_config.json') | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     args = parser.parse_args() | ||||
|     print(f'coucou {args.output_filename}') | ||||
|     with open(args.output_filename,"w") as file : | ||||
|         mywriter = writer(file) | ||||
|         mywriter.writerow(('path-id','source','destination','transponder-type',\ | ||||
|             'transponder-mode','baud rate (Gbaud)', 'input power (dBm)','path','OSNR@bandwidth','OSNR@0.1nm','SNR@bandwidth','SNR@0.1nm','Pass?')) | ||||
|      | ||||
|     with open(args.output_filename,"w") as file : | ||||
|         with open(args.filename) as f: | ||||
|             print(f'Reading {args.filename}') | ||||
|             json_data = loads(f.read()) | ||||
|             equipment = load_equipment(args.eqpt_filename) | ||||
|             tspjsondata = equipment['Transceiver'] | ||||
|             #print(tspjsondata) | ||||
|             for p in json_data['path']: | ||||
|                 path_id     = int(p['path-id']) | ||||
|                 source      = p['path-properties']['path-route-objects'][0]\ | ||||
|                 ['path-route-object']['unnumbered-hop']['node-id'] | ||||
|                 destination = p['path-properties']['path-route-objects'][-1]\ | ||||
|                 ['path-route-object']['unnumbered-hop']['node-id'] | ||||
|                 pth        = ' | '.join([ e['path-route-object']['unnumbered-hop']['node-id']  | ||||
|                          for e in p['path-properties']['path-route-objects']]) | ||||
|             print(f'Writing in {args.output_filename}') | ||||
|             jsontocsv(json_data,equipment,file) | ||||
|  | ||||
|                 [tsp,mode] = p['path-properties']['path-route-objects'][0]\ | ||||
|                 ['path-route-object']['unnumbered-hop']['hop-type'].split(' - ') | ||||
|                  | ||||
|                 # find the min  acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format) | ||||
|                 try: | ||||
|                     [minosnr, baud_rate] = next([m['OSNR'] , m['baud_rate']]   | ||||
|                         for m in equipment['Transceiver'][tsp].mode if  m['format']==mode) | ||||
|      | ||||
|                 # for debug | ||||
|                 # print(f'coucou {baud_rate}') | ||||
|                 except IndexError: | ||||
|                     msg = f'could not find tsp : {self.tsp} with mode: {self.tsp_mode} in eqpt library' | ||||
|                      | ||||
|                     raise ValueError(msg) | ||||
|                 output_snr = next(e['accumulative-value']  | ||||
|                     for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@0.1nm') | ||||
|                 output_snrbandwidth = next(e['accumulative-value']  | ||||
|                     for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@bandwidth') | ||||
|                 output_osnr = next(e['accumulative-value']  | ||||
|                     for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@0.1nm') | ||||
|                 output_osnrbandwidth = next(e['accumulative-value']  | ||||
|                     for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@bandwidth') | ||||
|                 power = next(e['accumulative-value']  | ||||
|                     for e in p['path-properties']['path-metric'] if e['metric-type'] == 'reference_power') | ||||
|                 mywriter.writerow((path_id, | ||||
|                     source, | ||||
|                     destination, | ||||
|                     tsp, | ||||
|                     mode, | ||||
|                     baud_rate*1e-9, | ||||
|                     round(lin2db(power)+30,2), | ||||
|                     pth, | ||||
|                     output_osnrbandwidth, | ||||
|                     output_osnr, | ||||
|                     output_snrbandwidth, | ||||
|                     output_snr, | ||||
|                     output_snr >= minosnr | ||||
|                     )) | ||||
|   | ||||
| @@ -137,7 +137,7 @@ def target_power(network, node, equipment): #get_fiber_dp | ||||
|         exit() | ||||
|     if isinstance(node, Roadm) or not power_mode: | ||||
|         dp = 0 | ||||
|     print(f'{repr(node)} delta power in:\n{dp}dB') | ||||
|     # print(f'{repr(node)} delta power in:\n{dp}dB') | ||||
|     return dp | ||||
|      | ||||
|  | ||||
| @@ -252,6 +252,7 @@ def set_egress_amplifier(network, roadm, equipment, pref_total_db): | ||||
|             prev_dp = dp | ||||
|             prev_node = node | ||||
|             node = next_node | ||||
|             # print(f'{node.uid}') | ||||
|             next_node = next(n for n in network.successors(node)) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -25,6 +25,10 @@ from gnpy.core.network import set_roadm_loss | ||||
| 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 csv import writer | ||||
|  | ||||
| logger = getLogger(__name__) | ||||
|  | ||||
|  | ||||
| RequestParams = namedtuple('RequestParams','request_id source destination trx_type'+ | ||||
| ' trx_mode nodes_list loose_list spacing power nb_channel frequency format baud_rate OSNR bit_rate roll_off') | ||||
| @@ -55,17 +59,19 @@ class Path_request: | ||||
|                             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'baud_rate:     {self.baud_rate}', | ||||
|                             f'spacing:      {self.spacing}', | ||||
|                             f'power:        {self.power}' | ||||
|                             f'source: \t{self.source}', | ||||
|                             f'destination:\t{self.destination}', | ||||
|                             f'trx type:\t{self.tsp}', | ||||
|                             f'trx mode:\t{self.tsp_mode}', | ||||
|                             f'baud_rate:\t{self.baud_rate * 1e-9} Gbaud', | ||||
|                             f'bit_rate:\t{self.bit_rate * 1e-9} Gb/s', | ||||
|                             f'spacing:\t{self.spacing * 1e-9} GHz', | ||||
|                             f'power:  \t{round(lin2db(self.power)+30,2)} dBm' | ||||
|                             '\n']) | ||||
|  | ||||
| class Result_element(Element): | ||||
|     def __init__(self,path_request,computed_path): | ||||
|         self.path_id = int(path_request.request_id) | ||||
|         self.path_id = path_request.request_id | ||||
|         self.path_request = path_request | ||||
|         self.computed_path = computed_path | ||||
|         hop_type = [] | ||||
| @@ -78,6 +84,75 @@ class Result_element(Element): | ||||
|     uid = property(lambda self: repr(self)) | ||||
|     @property | ||||
|     def pathresult(self): | ||||
|         if not self.computed_path: | ||||
|             return { | ||||
|                    'path-id': self.path_id, | ||||
|                    'path-properties':{ | ||||
|                        'path-metric': [ | ||||
|                            { | ||||
|                            'metric-type': 'SNR@bandwidth', | ||||
|                            'accumulative-value': 'None' | ||||
|                            }, | ||||
|                            { | ||||
|                            'metric-type': 'SNR@0.1nm', | ||||
|                            'accumulative-value': 'None' | ||||
|                            }, | ||||
|                            { | ||||
|                            'metric-type': 'OSNR@bandwidth', | ||||
|                            'accumulative-value': 'None' | ||||
|                            }, | ||||
|                            { | ||||
|                            'metric-type': 'OSNR@0.1nm', | ||||
|                            'accumulative-value': 'None' | ||||
|                            }, | ||||
|                            { | ||||
|                            'metric-type': 'reference_power', | ||||
|                            'accumulative-value': self.path_request.power | ||||
|                            } | ||||
|                         ], | ||||
|                         'path-srlgs': { | ||||
|                             'usage': 'not used yet', | ||||
|                             'values': 'not used yet' | ||||
|                         }, | ||||
|                         'path-route-objects': [ | ||||
|                             { | ||||
|                             'path-route-object': { | ||||
|                                 'index': 0, | ||||
|                                 'unnumbered-hop': { | ||||
|                                     'node-id': self.path_request.source, | ||||
|                                     'link-tp-id': self.path_request.source, | ||||
|                                     'hop-type': ' - '.join([self.path_request.tsp, self.path_request.tsp_mode]), | ||||
|                                     'direction': 'not used' | ||||
|                                 }, | ||||
|                                 'label-hop': { | ||||
|                                     'te-label': { | ||||
|                                         'generic': 'not used yet', | ||||
|                                         'direction': 'not used yet' | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                             }, | ||||
|                             { | ||||
|                             'path-route-object': { | ||||
|                                 'index': 1, | ||||
|                                 'unnumbered-hop': { | ||||
|                                     'node-id': self.path_request.destination, | ||||
|                                     'link-tp-id': self.path_request.destination, | ||||
|                                     'hop-type': ' - '.join([self.path_request.tsp, self.path_request.tsp_mode]), | ||||
|                                     'direction': 'not used' | ||||
|                                 }, | ||||
|                                 'label-hop': { | ||||
|                                     'te-label': { | ||||
|                                         'generic': 'not used yet', | ||||
|                                         'direction': 'not used yet' | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             ] | ||||
|                     } | ||||
|                 } | ||||
|         else: | ||||
|             return { | ||||
|                    'path-id': self.path_id, | ||||
|                    'path-properties':{ | ||||
| @@ -139,6 +214,8 @@ def compute_constrained_path(network, req): | ||||
|     edfa = [n for n in network.nodes() if isinstance(n, Edfa)] | ||||
|     source = next(el for el in trx if el.uid == req.source) | ||||
|     # start the path with its source | ||||
|     # TODO : avoid loops due to constraints , guess name base on string, | ||||
|     # avoid crashing if on req is not correct | ||||
|     total_path = [source] | ||||
|     for n in req.nodes_list: | ||||
|         # print(n) | ||||
| @@ -170,7 +247,16 @@ def compute_constrained_path(network, req): | ||||
|             else: | ||||
|                 msg = f'could not find a path from {source.uid} to node : {n} in network topology' | ||||
|                 logger.critical(msg) | ||||
|                 raise ValueError(msg) | ||||
|                 #raise ValueError(msg) | ||||
|                 print(msg) | ||||
|                 total_path = [] | ||||
|  | ||||
| # preparing disjonction feature | ||||
|     # for p in all_simple_paths(network,\ | ||||
|     #     source=next(el for el in trx if el.uid == req.source),\ | ||||
|     #     target=next(el for el in trx if el.uid == req.destination)): | ||||
|     #     print([e.uid for e in p if isinstance(e,Roadm)]) | ||||
|  | ||||
|     return total_path  | ||||
|  | ||||
| def propagate(path, req, equipment, show=False): | ||||
| @@ -184,3 +270,68 @@ def propagate(path, req, equipment, show=False): | ||||
|         if show : | ||||
|             print(el) | ||||
|     return path     | ||||
|  | ||||
|  | ||||
| def jsontocsv(json_data,equipment,fileout): | ||||
|     # read json path result file in accordance with: | ||||
|     # Yang model for requesting Path Computation | ||||
|     # draft-ietf-teas-yang-path-computation-01.txt.  | ||||
|     # and write results in an CSV file | ||||
|  | ||||
|     mywriter = writer(fileout) | ||||
|     mywriter.writerow(('path-id','source','destination','transponder-type',\ | ||||
|         'transponder-mode','baud rate (Gbaud)', 'input power (dBm)','path',\ | ||||
|         'OSNR@bandwidth','OSNR@0.1nm','SNR@bandwidth','SNR@0.1nm','Pass?')) | ||||
|     tspjsondata = equipment['Transceiver'] | ||||
|     #print(tspjsondata) | ||||
|     for p in json_data['path']: | ||||
|         path_id     = p['path-id'] | ||||
|         source      = p['path-properties']['path-route-objects'][0]\ | ||||
|         ['path-route-object']['unnumbered-hop']['node-id'] | ||||
|         destination = p['path-properties']['path-route-objects'][-1]\ | ||||
|         ['path-route-object']['unnumbered-hop']['node-id'] | ||||
|         pth        = ' | '.join([ e['path-route-object']['unnumbered-hop']['node-id']  | ||||
|                  for e in p['path-properties']['path-route-objects']]) | ||||
|  | ||||
|         [tsp,mode] = p['path-properties']['path-route-objects'][0]\ | ||||
|         ['path-route-object']['unnumbered-hop']['hop-type'].split(' - ') | ||||
|          | ||||
|         # find the min  acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format) | ||||
|         try: | ||||
|             [minosnr, baud_rate] = next([m['OSNR'] , m['baud_rate']]   | ||||
|                 for m in equipment['Transceiver'][tsp].mode if  m['format']==mode) | ||||
|  | ||||
|         # for debug | ||||
|         # print(f'coucou {baud_rate}') | ||||
|         except IndexError: | ||||
|             msg = f'could not find tsp : {self.tsp} with mode: {self.tsp_mode} in eqpt library' | ||||
|              | ||||
|             raise ValueError(msg) | ||||
|         output_snr = next(e['accumulative-value']  | ||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@0.1nm') | ||||
|         output_snrbandwidth = next(e['accumulative-value']  | ||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@bandwidth') | ||||
|         output_osnr = next(e['accumulative-value']  | ||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@0.1nm') | ||||
|         output_osnrbandwidth = next(e['accumulative-value']  | ||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@bandwidth') | ||||
|         power = next(e['accumulative-value']  | ||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'reference_power') | ||||
|         if isinstance(output_snr, str): | ||||
|             isok = '' | ||||
|         else: | ||||
|             isok = output_snr >= minosnr | ||||
|         mywriter.writerow((path_id, | ||||
|             source, | ||||
|             destination, | ||||
|             tsp, | ||||
|             mode, | ||||
|             baud_rate*1e-9, | ||||
|             round(lin2db(power)+30,2), | ||||
|             pth, | ||||
|             output_osnrbandwidth, | ||||
|             output_osnr, | ||||
|             output_snrbandwidth, | ||||
|             output_snr, | ||||
|             isok  | ||||
|             )) | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|   "path-request": [ | ||||
|     { | ||||
|       "request-id": 0, | ||||
|       "request-id": "0", | ||||
|       "source": "BREST_KLA", | ||||
|       "destination": "Vannes_KBE", | ||||
|       "src-tp-id": "trx BREST_KLA", | ||||
| @@ -27,7 +27,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 1, | ||||
|       "request-id": "1", | ||||
|       "source": "Lorient_KMA", | ||||
|       "destination": "Vannes_KBE", | ||||
|       "src-tp-id": "trx Lorient_KMA", | ||||
| @@ -55,26 +55,26 @@ | ||||
|   ], | ||||
|   "synchronisation": [ | ||||
|     { | ||||
|       "synchonization-id": 0, | ||||
|       "synchonization-id": "0", | ||||
|       "svec": { | ||||
|         "relaxable": "False", | ||||
|         "link-diverse": "True", | ||||
|         "node-diverse": "True", | ||||
|         "request-id-number": [ | ||||
|           0, | ||||
|           1 | ||||
|           "0", | ||||
|           "1" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "synchonization-id": 1, | ||||
|       "synchonization-id": "1", | ||||
|       "svec": { | ||||
|         "relaxable": "False", | ||||
|         "link-diverse": "True", | ||||
|         "node-diverse": "True", | ||||
|         "request-id-number": [ | ||||
|           1, | ||||
|           0 | ||||
|           "1", | ||||
|           "0" | ||||
|         ] | ||||
|       } | ||||
|     } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|   "path-request": [ | ||||
|     { | ||||
|       "request-id": 0, | ||||
|       "request-id": "0", | ||||
|       "source": "Lorient_KMA", | ||||
|       "destination": "Vannes_KBE", | ||||
|       "src-tp-id": "trx Lorient_KMA", | ||||
| @@ -27,7 +27,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 1, | ||||
|       "request-id": "1", | ||||
|       "source": "Brest_KLA", | ||||
|       "destination": "Vannes_KBE", | ||||
|       "src-tp-id": "trx Brest_KLA", | ||||
| @@ -84,7 +84,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 3, | ||||
|       "request-id": "3", | ||||
|       "source": "Lannion_CAS", | ||||
|       "destination": "Rennes_STA", | ||||
|       "src-tp-id": "trx Lannion_CAS", | ||||
| @@ -110,7 +110,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 4, | ||||
|       "request-id": "4", | ||||
|       "source": "Rennes_STA", | ||||
|       "destination": "Lannion_CAS", | ||||
|       "src-tp-id": "trx Rennes_STA", | ||||
| @@ -136,7 +136,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 5, | ||||
|       "request-id": "5", | ||||
|       "source": "Lorient_KMA", | ||||
|       "destination": "Lannion_CAS", | ||||
|       "src-tp-id": "trx Lorient_KMA", | ||||
| @@ -180,38 +180,38 @@ | ||||
|   ], | ||||
|   "synchronisation": [ | ||||
|     { | ||||
|       "synchonization-id": 0, | ||||
|       "synchonization-id": "0", | ||||
|       "svec": { | ||||
|         "relaxable": "False", | ||||
|         "link-diverse": "True", | ||||
|         "node-diverse": "True", | ||||
|         "request-id-number": [ | ||||
|           0, | ||||
|           0 | ||||
|           "0", | ||||
|           "0" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "synchonization-id": 3, | ||||
|       "synchonization-id": "3", | ||||
|       "svec": { | ||||
|         "relaxable": "False", | ||||
|         "link-diverse": "True", | ||||
|         "node-diverse": "True", | ||||
|         "request-id-number": [ | ||||
|           3, | ||||
|           4 | ||||
|           "3", | ||||
|           "4" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "synchonization-id": 5, | ||||
|       "synchonization-id": "5", | ||||
|       "svec": { | ||||
|         "relaxable": "False", | ||||
|         "link-diverse": "True", | ||||
|         "node-diverse": "True", | ||||
|         "request-id-number": [ | ||||
|           5, | ||||
|           0 | ||||
|           "5", | ||||
|           "0" | ||||
|         ] | ||||
|       } | ||||
|     } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|   "path-request": [ | ||||
|     { | ||||
|       "request-id": 0, | ||||
|       "request-id": "0", | ||||
|       "source": "Lorient_KMA", | ||||
|       "destination": "Vannes_KBE", | ||||
|       "src-tp-id": "trx Lorient_KMA", | ||||
| @@ -27,7 +27,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 1, | ||||
|       "request-id": "1", | ||||
|       "source": "Brest_KLA", | ||||
|       "destination": "Vannes_KBE", | ||||
|       "src-tp-id": "trx Brest_KLA", | ||||
| @@ -84,7 +84,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 3, | ||||
|       "request-id": "3", | ||||
|       "source": "Lannion_CAS", | ||||
|       "destination": "Rennes_STA", | ||||
|       "src-tp-id": "trx Lannion_CAS", | ||||
| @@ -110,7 +110,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 4, | ||||
|       "request-id": "4", | ||||
|       "source": "Rennes_STA", | ||||
|       "destination": "Lannion_CAS", | ||||
|       "src-tp-id": "trx Rennes_STA", | ||||
| @@ -136,7 +136,7 @@ | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "request-id": 5, | ||||
|       "request-id": "5", | ||||
|       "source": "Lorient_KMA", | ||||
|       "destination": "Lannion_CAS", | ||||
|       "src-tp-id": "trx Lorient_KMA", | ||||
| @@ -180,38 +180,38 @@ | ||||
|   ], | ||||
|   "synchronisation": [ | ||||
|     { | ||||
|       "synchonization-id": 0, | ||||
|       "synchonization-id": "0", | ||||
|       "svec": { | ||||
|         "relaxable": "False", | ||||
|         "link-diverse": "True", | ||||
|         "node-diverse": "True", | ||||
|         "request-id-number": [ | ||||
|           0, | ||||
|           0 | ||||
|           "0", | ||||
|           "0" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "synchonization-id": 3, | ||||
|       "synchonization-id": "3", | ||||
|       "svec": { | ||||
|         "relaxable": "False", | ||||
|         "link-diverse": "True", | ||||
|         "node-diverse": "True", | ||||
|         "request-id-number": [ | ||||
|           3, | ||||
|           4 | ||||
|           "3", | ||||
|           "4" | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "synchonization-id": 5, | ||||
|       "synchonization-id": "5", | ||||
|       "svec": { | ||||
|         "relaxable": "False", | ||||
|         "link-diverse": "True", | ||||
|         "node-diverse": "True", | ||||
|         "request-id-number": [ | ||||
|           5, | ||||
|           0 | ||||
|           "5", | ||||
|           "0" | ||||
|         ] | ||||
|       } | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 James
					James