From 4ba77d0a0a3a2fc27575968928baeb1740b07991 Mon Sep 17 00:00:00 2001 From: EstherLerouzic Date: Thu, 19 Aug 2021 16:34:39 +0200 Subject: [PATCH] Change rq.N and rq.M from scalar to list Prepare for the next step, to be able to handle lists of candidate assignment Signed-off-by: EstherLerouzic Change-Id: I2bd78606ce4502f68efb60f85892df5f76d52bb5 --- gnpy/tools/json_io.py | 51 +- gnpy/topology/request.py | 20 +- gnpy/topology/spectrum_assignment.py | 12 +- tests/data/testTopology_response.json | 670 +++++++++++------- tests/data/testTopology_response_expected.csv | 10 +- tests/invocation/path_requests_run | 14 +- tests/test_logger.py | 5 +- tests/test_spectrum_assignment.py | 34 +- 8 files changed, 490 insertions(+), 326 deletions(-) diff --git a/gnpy/tools/json_io.py b/gnpy/tools/json_io.py index 8fa3015f6..c55b26646 100644 --- a/gnpy/tools/json_io.py +++ b/gnpy/tools/json_io.py @@ -23,6 +23,7 @@ from gnpy.core.utils import automatic_nch, automatic_fmax, merge_amplifier_restrictions from gnpy.core.parameters import DEFAULT_RAMAN_COEFFICIENT from gnpy.topology.request import PathRequest, Disjunction, compute_spectrum_slot_vs_bandwidth +from gnpy.topology.spectrum_assignment import mvalue_to_slots from gnpy.tools.convert import xls_to_json_data from gnpy.tools.service_sheet import read_service_sheet @@ -627,7 +628,8 @@ def requests_from_json(json_data, equipment): params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing']) except KeyError: params['nb_channel'] = automatic_nch(f_min, f_max_from_si, params['spacing']) - params['effective_freq_slot'] = req['path-constraints']['te-bandwidth'].get('effective-freq-slot', [None])[0] + params['effective_freq_slot'] = \ + req['path-constraints']['te-bandwidth'].get('effective-freq-slot', [{'N': None, 'M': None}]) try: params['path_bandwidth'] = req['path-constraints']['te-bandwidth']['path_bandwidth'] except KeyError: @@ -656,19 +658,46 @@ def _check_one_request(params, f_max_from_si): + f' Max recommanded nb of channels is {max_recommanded_nb_channels}.' raise ServiceError(msg) # Transponder mode already selected; will it fit to the requested bandwidth? - if params['trx_mode'] is not None and params['effective_freq_slot'] is not None \ - and params['effective_freq_slot']['M'] is not None: - _, requested_m = compute_spectrum_slot_vs_bandwidth(params['path_bandwidth'], - params['spacing'], - params['bit_rate']) - # params['effective_freq_slot']['M'] value should be bigger than the computed requested_m (simple estimate) + if params['trx_mode'] is not None and params['effective_freq_slot'] is not None: + required_nb_of_channels, requested_m = compute_spectrum_slot_vs_bandwidth(params['path_bandwidth'], + params['spacing'], + params['bit_rate']) + _, per_channel_m = compute_spectrum_slot_vs_bandwidth(params['bit_rate'], + params['spacing'], + params['bit_rate']) + # each M should fit one or more channels if it is not None + # spectrum slots should not overlap + # resulting nb of channels should be bigger than the nb computed with path_bandwidth + # without being splitted # TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of # superchannel closed packing. - if requested_m > params['effective_freq_slot']['M']: - msg = f'Requested M {params["effective_freq_slot"]["M"]} number of slots for request ' +\ - f'{params["request_id"]} should be greater than {requested_m} to support request ' +\ - f'{params["path_bandwidth"] * 1e-9} Gbit/s with {params["trx_type"]} {params["trx_mode"]}' + nb_of_channels = 0 + # order slots + slots = sorted(params['effective_freq_slot'], key=lambda x: float('inf') if x['N'] is None else x['N']) + for slot in slots: + nb_of_channels = nb_of_channels + slot['M'] // per_channel_m if slot['M'] is not None \ + and nb_of_channels is not None else None + if slot['M'] is not None and slot['M'] < per_channel_m: + msg = f'Requested M {slot} number of slots for request' +\ + f' {params["request_id"]} should be greater than {per_channel_m} to support request' +\ + f'with {params["trx_type"]} {params["trx_mode"]}' + _logger.critical(msg) + if nb_of_channels is not None and nb_of_channels < required_nb_of_channels: + msg = f'Requested M {slots} number of slots for request {params["request_id"]} support {nb_of_channels}' +\ + f' nb of channels while {required_nb_of_channels} are required to support request' +\ + f' {params["path_bandwidth"] * 1e-9} Gbit/s with {params["trx_type"]} {params["trx_mode"]}' raise ServiceError(msg) + if nb_of_channels is not None: + _, stop0n = mvalue_to_slots(slots[0]['N'], slots[0]['M']) + i = 1 + while i < len(slots): + slot = slots[i] + startn, stopn = mvalue_to_slots(slot['N'], slot['M']) + if startn <= stop0n: + msg = f'Requested M {slots} for request {params["request_id"]} overlap' + raise ServiceError(msg) + _, stop0n = startn, stopn + i += 1 def disjunctions_from_json(json_data): diff --git a/gnpy/topology/request.py b/gnpy/topology/request.py index 3e414a7f7..b7e4f28b7 100644 --- a/gnpy/topology/request.py +++ b/gnpy/topology/request.py @@ -68,8 +68,8 @@ def __init__(self, *args, **params): self.cost = params.cost self.path_bandwidth = params.path_bandwidth if params.effective_freq_slot is not None: - self.N = params.effective_freq_slot['N'] - self.M = params.effective_freq_slot['M'] + self.N = [s['N'] for s in params.effective_freq_slot] + self.M = [s['M'] for s in params.effective_freq_slot] self.initial_spectrum = None self.offset_db = params.equalization_offset_db @@ -172,10 +172,10 @@ def detailed_path_json(self): temp = { 'path-route-object': { 'index': index, - "label-hop": { - "N": self.path_request.N, - "M": self.path_request.M - }, + "label-hop": [{ + "N": n, + "M": m + } for n, m in zip(self.path_request.N, self.path_request.M)], } } pro_list.append(temp) @@ -459,8 +459,8 @@ def jsontoparams(my_p, tsp, mode, equipment): temp2 = [] for elem in my_p['path-properties']['path-route-objects']: if 'label-hop' in elem['path-route-object'].keys(): - temp2.append(f'{elem["path-route-object"]["label-hop"]["N"]}, ' + - f'{elem["path-route-object"]["label-hop"]["M"]}') + temp2.append(f'{[e["N"] for e in elem["path-route-object"]["label-hop"]]}, ' + + f'{[e["M"] for e in elem["path-route-object"]["label-hop"]]}') # OrderedDict.fromkeys returns the unique set of strings. # TODO: if spectrum changes along the path, we should be able to give the segments # eg for regeneration case @@ -978,8 +978,8 @@ def compare_reqs(req1, req2, disjlist): req1.OSNR == req2.OSNR and \ req1.roll_off == req2.roll_off and \ same_disj and \ - getattr(req1, 'N', None) is None and getattr(req2, 'N', None) is None and \ - getattr(req1, 'M', None) is None and getattr(req2, 'M', None) is None: + getattr(req1, 'N', [None]) == [None] and getattr(req2, 'N', [None]) == [None] and \ + getattr(req1, 'M', [None]) == [None] and getattr(req2, 'M', [None]) == [None]: return True else: return False diff --git a/gnpy/topology/spectrum_assignment.py b/gnpy/topology/spectrum_assignment.py index caaa83461..6a7b8f94b 100644 --- a/gnpy/topology/spectrum_assignment.py +++ b/gnpy/topology/spectrum_assignment.py @@ -386,20 +386,20 @@ def pth_assign_spectrum(pths, rqs, oms_list, rpths): else: nb_wl, requested_m = compute_spectrum_slot_vs_bandwidth(rq.path_bandwidth, rq.spacing, rq.bit_rate) - if getattr(rq, 'M', None) is not None: + if getattr(rq, 'M', [None])[0] is not None: # Consistency check between the requested M and path_bandwidth # M value should be bigger than the computed requested_m (simple estimate) # TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of # superchannel closed packing. - if requested_m > rq.M: + if requested_m > rq.M[0]: rq.N = None rq.M = None rq.blocking_reason = 'NOT_ENOUGH_RESERVED_SPECTRUM' # need to stop here for this request and not go though spectrum selection process with requested_m continue # use the req.M even if requested_m is smaller - requested_m = rq.M - requested_n = getattr(rq, 'N', None) + requested_m = rq.M[0] + requested_n = getattr(rq, 'N', [None])[0] (center_n, startn, stopn), path_oms = spectrum_selection(pth + rpth, oms_list, requested_m, requested_n) # if requested n and m concern already occupied spectrum the previous function returns a None candidate @@ -409,8 +409,8 @@ def pth_assign_spectrum(pths, rqs, oms_list, rpths): for oms_elem in path_oms: oms_list[oms_elem].assign_spectrum(center_n, requested_m) oms_list[oms_elem].add_service(rq.request_id, nb_wl) - rq.N = center_n - rq.M = requested_m + rq.N = [center_n] + rq.M = [requested_m] else: rq.N = None rq.M = None diff --git a/tests/data/testTopology_response.json b/tests/data/testTopology_response.json index 2e1314840..5c7d050a3 100644 --- a/tests/data/testTopology_response.json +++ b/tests/data/testTopology_response.json @@ -42,10 +42,12 @@ { "path-route-object": { "index": 1, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -69,10 +71,12 @@ { "path-route-object": { "index": 4, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -87,10 +91,12 @@ { "path-route-object": { "index": 6, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -105,10 +111,12 @@ { "path-route-object": { "index": 8, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -123,10 +131,12 @@ { "path-route-object": { "index": 10, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -141,10 +151,12 @@ { "path-route-object": { "index": 12, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -159,10 +171,12 @@ { "path-route-object": { "index": 14, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -219,10 +233,12 @@ { "path-route-object": { "index": 1, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -246,10 +262,12 @@ { "path-route-object": { "index": 4, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -264,10 +282,12 @@ { "path-route-object": { "index": 6, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -282,10 +302,12 @@ { "path-route-object": { "index": 8, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -300,10 +322,12 @@ { "path-route-object": { "index": 10, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -318,10 +342,12 @@ { "path-route-object": { "index": 12, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -336,10 +362,12 @@ { "path-route-object": { "index": 14, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -354,10 +382,12 @@ { "path-route-object": { "index": 16, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -372,10 +402,12 @@ { "path-route-object": { "index": 18, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -390,10 +422,12 @@ { "path-route-object": { "index": 20, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -408,10 +442,12 @@ { "path-route-object": { "index": 22, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -426,10 +462,12 @@ { "path-route-object": { "index": 24, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -444,10 +482,12 @@ { "path-route-object": { "index": 26, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -462,10 +502,12 @@ { "path-route-object": { "index": 28, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -480,10 +522,12 @@ { "path-route-object": { "index": 30, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -498,10 +542,12 @@ { "path-route-object": { "index": 32, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -516,10 +562,12 @@ { "path-route-object": { "index": 34, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -534,10 +582,12 @@ { "path-route-object": { "index": 36, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -552,10 +602,12 @@ { "path-route-object": { "index": 38, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -570,10 +622,12 @@ { "path-route-object": { "index": 40, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -588,10 +642,12 @@ { "path-route-object": { "index": 42, - "label-hop": { - "N": -276, - "M": 4 - } + "label-hop": [ + { + "N": -276, + "M": 4 + } + ] } }, { @@ -648,10 +704,12 @@ { "path-route-object": { "index": 1, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -675,10 +733,12 @@ { "path-route-object": { "index": 4, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -693,10 +753,12 @@ { "path-route-object": { "index": 6, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -711,10 +773,12 @@ { "path-route-object": { "index": 8, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -729,10 +793,12 @@ { "path-route-object": { "index": 10, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -747,10 +813,12 @@ { "path-route-object": { "index": 12, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -765,10 +833,12 @@ { "path-route-object": { "index": 14, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -783,10 +853,12 @@ { "path-route-object": { "index": 16, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -801,10 +873,12 @@ { "path-route-object": { "index": 18, - "label-hop": { - "N": -284, - "M": 4 - } + "label-hop": [ + { + "N": -284, + "M": 4 + } + ] } }, { @@ -861,10 +935,12 @@ { "path-route-object": { "index": 1, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -888,10 +964,12 @@ { "path-route-object": { "index": 4, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -906,10 +984,12 @@ { "path-route-object": { "index": 6, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -924,10 +1004,12 @@ { "path-route-object": { "index": 8, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -942,10 +1024,12 @@ { "path-route-object": { "index": 10, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -960,10 +1044,12 @@ { "path-route-object": { "index": 12, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -978,10 +1064,12 @@ { "path-route-object": { "index": 14, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -996,10 +1084,12 @@ { "path-route-object": { "index": 16, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1014,10 +1104,12 @@ { "path-route-object": { "index": 18, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1032,10 +1124,12 @@ { "path-route-object": { "index": 20, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1050,10 +1144,12 @@ { "path-route-object": { "index": 22, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1068,10 +1164,12 @@ { "path-route-object": { "index": 24, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1086,10 +1184,12 @@ { "path-route-object": { "index": 26, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1104,10 +1204,12 @@ { "path-route-object": { "index": 28, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1122,10 +1224,12 @@ { "path-route-object": { "index": 30, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1140,10 +1244,12 @@ { "path-route-object": { "index": 32, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1158,10 +1264,12 @@ { "path-route-object": { "index": 34, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1176,10 +1284,12 @@ { "path-route-object": { "index": 36, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1194,10 +1304,12 @@ { "path-route-object": { "index": 38, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1212,10 +1324,12 @@ { "path-route-object": { "index": 40, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1230,10 +1344,12 @@ { "path-route-object": { "index": 42, - "label-hop": { - "N": -266, - "M": 6 - } + "label-hop": [ + { + "N": -266, + "M": 6 + } + ] } }, { @@ -1290,10 +1406,12 @@ { "path-route-object": { "index": 1, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { @@ -1317,10 +1435,12 @@ { "path-route-object": { "index": 4, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { @@ -1335,10 +1455,12 @@ { "path-route-object": { "index": 6, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { @@ -1353,10 +1475,12 @@ { "path-route-object": { "index": 8, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { @@ -1371,10 +1495,12 @@ { "path-route-object": { "index": 10, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { @@ -1389,10 +1515,12 @@ { "path-route-object": { "index": 12, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { @@ -1407,10 +1535,12 @@ { "path-route-object": { "index": 14, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { @@ -1425,10 +1555,12 @@ { "path-route-object": { "index": 16, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { @@ -1443,10 +1575,12 @@ { "path-route-object": { "index": 18, - "label-hop": { - "N": -274, - "M": 6 - } + "label-hop": [ + { + "N": -274, + "M": 6 + } + ] } }, { diff --git a/tests/data/testTopology_response_expected.csv b/tests/data/testTopology_response_expected.csv index 1d74fb0cb..319d064f1 100644 --- a/tests/data/testTopology_response_expected.csv +++ b/tests/data/testTopology_response_expected.csv @@ -1,7 +1,7 @@ response-id,source,destination,path_bandwidth,Pass?,nb of tsp pairs,total cost,transponder-type,transponder-mode,OSNR-0.1nm,SNR-0.1nm,SNR-bandwidth,baud rate (Gbaud),input power (dBm),path,"spectrum (N,M)",reversed path OSNR-0.1nm,reversed path SNR-0.1nm,reversed path SNR-bandwidth -0,trx Lorient_KMA,trx Vannes_KBE,100.0,True,1,1,Voyager,mode 1,30.84,30.84,26.75,32.0,0.0,trx Lorient_KMA | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE,"-284, 4",,, -1,trx Brest_KLA,trx Vannes_KBE,10.0,True,1,1,Voyager,mode 1,22.65,22.11,18.03,32.0,1.0,trx Brest_KLA | roadm Brest_KLA | east edfa in Brest_KLA to Morlaix | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | west edfa in Lorient_KMA to Loudeac | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE,"-276, 4",,, -3,trx Lannion_CAS,trx Rennes_STA,60.0,True,1,1,vendorA_trx-type1,mode 1,28.29,25.85,21.77,32.0,1.0,trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | west edfa in Rennes_STA to Stbrieuc | roadm Rennes_STA | trx Rennes_STA,"-284, 4",,, -4,trx Rennes_STA,trx Lannion_CAS,150.0,True,1,1,vendorA_trx-type1,mode 2,22.27,22.14,15.05,64.0,0.0,trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Ploermel | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | west edfa in Vannes_KBE to Ploermel | roadm Vannes_KBE | east edfa in Vannes_KBE to Lorient_KMA | fiber (Vannes_KBE → Lorient_KMA)-F055 | west edfa in Lorient_KMA to Vannes_KBE | roadm Lorient_KMA | east edfa in Lorient_KMA to Loudeac | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS,"-266, 6",,, -5,trx Rennes_STA,trx Lannion_CAS,20.0,True,1,1,vendorA_trx-type1,mode 2,30.79,28.76,21.67,64.0,3.0,trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Stbrieuc | fiber (Rennes_STA → Stbrieuc)-F057 | west edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Lannion_CAS)-F056 | west edfa in Lannion_CAS to Stbrieuc | roadm Lannion_CAS | trx Lannion_CAS,"-274, 6",,, +0,trx Lorient_KMA,trx Vannes_KBE,100.0,True,1,1,Voyager,mode 1,30.84,30.84,26.75,32.0,0.0,trx Lorient_KMA | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE,"[-284], [4]",,, +1,trx Brest_KLA,trx Vannes_KBE,10.0,True,1,1,Voyager,mode 1,22.65,22.11,18.03,32.0,1.0,trx Brest_KLA | roadm Brest_KLA | east edfa in Brest_KLA to Morlaix | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | west edfa in Lorient_KMA to Loudeac | roadm Lorient_KMA | east edfa in Lorient_KMA to Vannes_KBE | fiber (Lorient_KMA → Vannes_KBE)-F055 | west edfa in Vannes_KBE to Lorient_KMA | roadm Vannes_KBE | trx Vannes_KBE,"[-276], [4]",,, +3,trx Lannion_CAS,trx Rennes_STA,60.0,True,1,1,vendorA_trx-type1,mode 1,28.29,25.85,21.77,32.0,1.0,trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | west edfa in Rennes_STA to Stbrieuc | roadm Rennes_STA | trx Rennes_STA,"[-284], [4]",,, +4,trx Rennes_STA,trx Lannion_CAS,150.0,True,1,1,vendorA_trx-type1,mode 2,22.27,22.14,15.05,64.0,0.0,trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Ploermel | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | west edfa in Vannes_KBE to Ploermel | roadm Vannes_KBE | east edfa in Vannes_KBE to Lorient_KMA | fiber (Vannes_KBE → Lorient_KMA)-F055 | west edfa in Lorient_KMA to Vannes_KBE | roadm Lorient_KMA | east edfa in Lorient_KMA to Loudeac | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS,"[-266], [6]",,, +5,trx Rennes_STA,trx Lannion_CAS,20.0,True,1,1,vendorA_trx-type1,mode 2,30.79,28.76,21.67,64.0,3.0,trx Rennes_STA | roadm Rennes_STA | east edfa in Rennes_STA to Stbrieuc | fiber (Rennes_STA → Stbrieuc)-F057 | west edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Lannion_CAS)-F056 | west edfa in Lannion_CAS to Stbrieuc | roadm Lannion_CAS | trx Lannion_CAS,"[-274], [6]",,, 6,,,,NO_PATH,,,,,,,,,,,,,, diff --git a/tests/invocation/path_requests_run b/tests/invocation/path_requests_run index a3a3c2249..a6d89d64c 100644 --- a/tests/invocation/path_requests_run +++ b/tests/invocation/path_requests_run @@ -108,11 +108,11 @@ Propagating on selected path Result summary req id demand GSNR@bandwidth A-Z (Z-A) GSNR@0.1nm A-Z (Z-A) Receiver minOSNR mode Gbit/s nb of tsp pairs N,M or blocking reason -0 trx Lorient_KMA to trx Vannes_KBE : 24.83 28.92 14 mode 1 100.0 1 (-284,4) -1 trx Brest_KLA to trx Vannes_KBE : 17.74 21.82 14 mode 1 200.0 2 (-272,8) -3 trx Lannion_CAS to trx Rennes_STA : 22.19 26.28 13 mode 1 60.0 1 (-284,4) -4 trx Rennes_STA to trx Lannion_CAS : 16.06 23.29 17 mode 2 150.0 1 (-258,6) -5 trx Rennes_STA to trx Lannion_CAS : 20.3 27.53 17 mode 2 20.0 1 (-274,6) -7 | 6 trx Lannion_CAS to trx Lorient_KMA : 19.52 23.61 14 mode 1 700.0 7 (-224,28) -7b trx Lannion_CAS to trx Lorient_KMA : 19.61 23.69 14 mode 1 400.0 4 (-172,24) +0 trx Lorient_KMA to trx Vannes_KBE : 24.83 28.92 14 mode 1 100.0 1 ([-284],[4]) +1 trx Brest_KLA to trx Vannes_KBE : 17.74 21.82 14 mode 1 200.0 2 ([-272],[8]) +3 trx Lannion_CAS to trx Rennes_STA : 22.19 26.28 13 mode 1 60.0 1 ([-284],[4]) +4 trx Rennes_STA to trx Lannion_CAS : 16.06 23.29 17 mode 2 150.0 1 ([-258],[6]) +5 trx Rennes_STA to trx Lannion_CAS : 20.3 27.53 17 mode 2 20.0 1 ([-274],[6]) +7 | 6 trx Lannion_CAS to trx Lorient_KMA : 19.52 23.61 14 mode 1 700.0 7 ([-224],[28]) +7b trx Lannion_CAS to trx Lorient_KMA : 19.61 23.69 14 mode 1 400.0 4 ([-172],[24]) Result summary shows mean GSNR and OSNR (average over all channels) diff --git a/tests/test_logger.py b/tests/test_logger.py index fa5bb5705..509d9c965 100644 --- a/tests/test_logger.py +++ b/tests/test_logger.py @@ -279,8 +279,9 @@ def wrong_requests(): } } }]}, - 'expected_msg': 'Requested M 4 number of slots for request Wrong_M should be greater than 6 to ' - + 'support request 100.0 Gbit/s with Voyager mode 2' + 'expected_msg': 'Requested M [{\'N\': -208, \'M\': 4}] number of slots for request Wrong_M ' + + 'support 0 nb of channels while 1 are required to support request 100.0 Gbit/s' + + ' with Voyager mode 2' }) return data diff --git a/tests/test_spectrum_assignment.py b/tests/test_spectrum_assignment.py index 60c524b49..6002c7351 100644 --- a/tests/test_spectrum_assignment.py +++ b/tests/test_spectrum_assignment.py @@ -296,12 +296,12 @@ def test_freq_slot_exist(setup, equipment, request_set): """test that assignment works even if effective_freq_slot is not populated""" network, oms_list = setup params = request_set - params['effective_freq_slot'] = None + params['effective_freq_slot'] = [{'N': None, 'M': None}] rqs = [PathRequest(**params)] paths = compute_path_dsjctn(network, equipment, rqs, []) pth_assign_spectrum(paths, rqs, oms_list, [find_reversed_path(paths[0])]) - assert rqs[0].N == -256 - assert rqs[0].M == 32 + assert rqs[0].N == [-256] + assert rqs[0].M == [32] def test_inconsistant_freq_slot(setup, equipment, request_set): @@ -309,7 +309,7 @@ def test_inconsistant_freq_slot(setup, equipment, request_set): network, oms_list = setup params = request_set # minimum required nb of slots is 32 (800Gbit/100Gbit/s channels each occupying 50GHz ie 4 slots) - params['effective_freq_slot'] = {'N': 0, 'M': 4} + params['effective_freq_slot'] = [{'N': 0, 'M': 4}] with pytest.raises(ServiceError): _check_one_request(params, 196.05e12) params['trx_mode'] = None @@ -319,25 +319,25 @@ def test_inconsistant_freq_slot(setup, equipment, request_set): assert rqs[0].blocking_reason == 'NOT_ENOUGH_RESERVED_SPECTRUM' -@pytest.mark.parametrize('n, m, final_n, final_m, blocking_reason', [ +@pytest.mark.parametrize('req_n, req_m, final_n, final_m, blocking_reason', [ # regular requests that should be correctly assigned: - (-100, 32, -100, 32, None), - (150, 50, 150, 50, None), + ([-100], [32], [-100], [32], None), + ([150], [50], [150], [50], None), # if n is None, there should be an assignment (enough spectrum cases) # and the center frequency should be set on the lower part of the spectrum based on m value if it exists # or based on 32 - (None, 32, -256, 32, None), - (None, 40, -248, 40, None), - (-100, None, -100, 32, None), - (None, None, -256, 32, None), + ([None], [32], [-256], [32], None), + ([None], [40], [-248], [40], None), + ([-100], [None], [-100], [32], None), + ([None], [None], [-256], [32], None), # -280 and 60 center indexes should result in unfeasible spectrum, either out of band or # overlapping with occupied spectrum. The requested spectrum is not available - (-280, None, None, None, 'NO_SPECTRUM'), - (-60, 40, None, None, 'NO_SPECTRUM'), + ([-280], [None], None, None, 'NO_SPECTRUM'), + ([-60], [40], None, None, 'NO_SPECTRUM'), # 20 is smaller than min 32 required nb of slots so should also be blocked - (-60, 20, None, None, 'NOT_ENOUGH_RESERVED_SPECTRUM') - ]) -def test_n_m_requests(setup, equipment, n, m, final_n, final_m, blocking_reason, request_set): + ([-60], [20], None, None, 'NOT_ENOUGH_RESERVED_SPECTRUM') +]) +def test_n_m_requests(setup, equipment, req_n, req_m, final_n, final_m, blocking_reason, request_set): """test that various N and M values for a request end up with the correct path assgnment""" network, oms_list = setup # add an occupation on one of the span of the expected path OMS list on both directions @@ -347,7 +347,7 @@ def test_n_m_requests(setup, equipment, n, m, final_n, final_m, blocking_reason, some_oms = oms_list[expected_oms[3]] some_oms.assign_spectrum(-30, 32) # means that spectrum is occupied from indexes -62 to 1 on reversed path params = request_set - params['effective_freq_slot'] = {'N': n, 'M': m} + params['effective_freq_slot'] = [{'N': n, 'M': m} for n, m in zip(req_n, req_m)] rqs = [PathRequest(**params)] paths = compute_path_dsjctn(network, equipment, rqs, [])