Loading src/opticalcontroller/OpticalController.py +11 −2 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ # limitations under the License. import logging, time from flask import Flask from flask import Flask, request from flask import render_template from common.DeviceTypes import DeviceTypeEnum from flask_restplus import Resource, Api Loading Loading @@ -88,7 +88,16 @@ class AddFlexLightpath(Resource): # rsa.g.printGraph() if rsa is not None: flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band, obx_idx, pref) reservation = request.args.get("reservation") if reservation is None and request.args.get("reservation_band") is not None: reservation = { "band": request.args.get("reservation_band"), "n_start": request.args.get("reservation_start"), "n_end": request.args.get("reservation_end"), } flow_id, optical_band_id = rsa.rsa_fs_computation( src, dst, bitrate, bidir, band, obx_idx, pref, reservation=reservation ) if flow_id is not None: if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 Loading src/opticalcontroller/RSA.py +26 −15 Original line number Diff line number Diff line Loading @@ -614,10 +614,13 @@ class RSA(): return fiber_list #function invoked for lightpaths and OB def select_slots_and_ports(self, links, n_slots, c, l, s, bidir, preferred=None): def select_slots_and_ports(self, links, n_slots, c, l, s, bidir, preferred=None, reservation=None): if debug: print (links, n_slots, c, l, s, bidir, self.c_slot_number, self.l_slot_number, self.s_slot_number) band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, preferred) band, slots = slot_selection( c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, preferred, reservation=reservation ) if debug: print (band, slots) if band is None: Loading Loading @@ -686,10 +689,13 @@ class RSA(): return t_flows, band, slots, {}, {} #function ivoked for fs lightpaths only def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id): def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id, reservation=None): if debug: print(self.links_dict) band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number) band, slots = slot_selection( c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, reservation=reservation ) if band is None: print("ERROR: No slots available in the three bands") return None, None, None, None, None Loading Loading @@ -953,7 +959,7 @@ class RSA(): #self.db_flows[flow_id]["parent_opt_band"] = 0 #self.db_flows[flow_id]["new_optical_band"] = 0 def create_optical_band(self, links, path, bidir, num_slots, old_band_x=None, preferred=None): def create_optical_band(self, links, path, bidir, num_slots, old_band_x=None, preferred=None, reservation=None): print("INFO: Creating optical-band of {} slots".format(num_slots)) if self.opt_band_id == 0: self.opt_band_id += 1 Loading Loading @@ -1008,7 +1014,9 @@ class RSA(): print(l_slots) print(s_slots) if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir, preferred) flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports( links, num_slots, c_slots, l_slots, s_slots, bidir, preferred, reservation=reservation ) if debug: print(flow_list, band_range, slots, fiber_f, fiber_b) f0, band = frequency_converter(band_range, slots) Loading Loading @@ -1203,7 +1211,7 @@ class RSA(): self.null_values(self.flow_id) return self.flow_id def rsa_fs_computation(self, src, dst, rate, bidir, band, bandx_id, preferred=None): def rsa_fs_computation(self, src, dst, rate, bidir, band, bandx_id, preferred=None, reservation=None): if band is not None: num_slots_ob = map_band_to_slot(band) print(band, num_slots_ob) Loading @@ -1227,7 +1235,9 @@ class RSA(): if len(path) < 1: self.null_values_ob(self.opt_band_id) return self.opt_band_id, [] optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob, old_band_x, preferred) optical_band_id, temp_links = self.create_optical_band( links, path, bidir, num_slots_ob, old_band_x, preferred, reservation=reservation ) return None, optical_band_id print("INFO: TP to TP connection") if self.flow_id == 0: Loading Loading @@ -1285,7 +1295,7 @@ class RSA(): flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, ob_id) ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading Loading @@ -1345,7 +1355,7 @@ class RSA(): temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, ob_id) ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading Loading @@ -1399,7 +1409,7 @@ class RSA(): flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, ob_id) ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading Loading @@ -1465,7 +1475,7 @@ class RSA(): temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, ob_id) ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading Loading @@ -1510,7 +1520,7 @@ class RSA(): print("INFO: optical-band width specified") #if no OB I create a new one links, path = self.compute_path(src, dst) optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob, reservation=reservation) op, num_slots = map_rate_to_slot(rate) if debug: print(temp_links) Loading @@ -1520,8 +1530,9 @@ class RSA(): print(l_slots) print(s_slots) if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links, num_slots, c_slots, l_slots, s_slots, bidir, optical_band_id) flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs( temp_links, num_slots, c_slots, l_slots, s_slots, bidir, optical_band_id, reservation=reservation ) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading src/opticalcontroller/tests/test_spectrum_reservation.py 0 → 100644 +90 −0 Original line number Diff line number Diff line # Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import pytest from opticalcontroller.tools import parse_slot_reservation, slot_selection def test_parse_compact_optical_spectrum_reservation(): reservation = parse_slot_reservation("C_BAND:51-66") assert reservation == {"band": "c_slots", "n_start": 51, "n_end": 66} def test_parse_dict_optical_spectrum_reservation(): reservation = parse_slot_reservation({"band": "l_slots", "n_start": "4", "n_end": "11"}) assert reservation == {"band": "l_slots", "n_start": 4, "n_end": 11} def test_slot_selection_without_reservation_keeps_first_fit(): band, slots = slot_selection( c=list(range(0, 10)), l=list(range(20, 30)), s=list(range(40, 50)), n_slots=4, Nc=10, Nl=10, Ns=10, ) assert band == "c_slots" assert slots == [0, 1, 2, 3] def test_slot_selection_with_reservation_consumes_requested_band_and_range(): band, slots = slot_selection( c=list(range(0, 100)), l=list(range(0, 100)), s=list(range(0, 100)), n_slots=4, Nc=100, Nl=100, Ns=100, reservation={"band": "l_slots", "n_start": 20, "n_end": 30}, ) assert band == "l_slots" assert slots == [20, 21, 22, 23] def test_slot_selection_with_unavailable_reservation_returns_none(): band, slots = slot_selection( c=[0, 1, 2, 3], l=[10, 11, 13, 14], s=[20, 21, 22, 23], n_slots=3, Nc=4, Nl=4, Ns=4, reservation={"band": "l_slots", "n_start": 10, "n_end": 12}, ) assert band is None assert slots is None def test_slot_selection_rejects_too_narrow_reservation(): with pytest.raises(ValueError): slot_selection( c=list(range(0, 100)), l=[], s=[], n_slots=4, Nc=100, Nl=0, Ns=0, reservation={"band": "c_slots", "n_start": 20, "n_end": 22}, ) src/opticalcontroller/tools.py +75 −4 Original line number Diff line number Diff line Loading @@ -12,7 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. import numpy as np import json, logging, numpy as np from typing import Dict, List, Optional, Tuple from opticalcontroller.variables import * import json , logging from context.client.ContextClient import ContextClient Loading Loading @@ -251,9 +252,68 @@ def get_links_to_node(topology, node): return result def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None): # First Fit def _normalize_reservation_band(band: str) -> str: normalized_band = str(band).strip().lower().replace("-", "_") if normalized_band in {"c", "c_band", "c_slots"}: return "c_slots" if normalized_band in {"l", "l_band", "l_slots"}: return "l_slots" if normalized_band in {"s", "s_band", "s_slots"}: return "s_slots" raise ValueError("Unsupported optical spectrum band: {:s}".format(str(band))) def parse_slot_reservation(reservation) -> Optional[Dict[str, int]]: if reservation is None: return None if isinstance(reservation, dict): if len(reservation) == 0: return None band = reservation.get("band") n_start = reservation.get("n_start", reservation.get("start")) n_end = reservation.get("n_end", reservation.get("end")) else: reservation_text = str(reservation).strip() if len(reservation_text) == 0: return None if reservation_text.startswith("{"): return parse_slot_reservation(json.loads(reservation_text)) if ":" not in reservation_text or "-" not in reservation_text: raise ValueError( "Optical spectrum reservation must be '<band>:<start>-<end>' or JSON" ) band, slot_range = reservation_text.split(":", maxsplit=1) n_start, n_end = slot_range.split("-", maxsplit=1) band = _normalize_reservation_band(band) n_start = int(n_start) n_end = int(n_end) if n_start < 0 or n_end < n_start: raise ValueError( "Invalid optical spectrum reservation range: {:d}-{:d}".format(n_start, n_end) ) return {"band": band, "n_start": n_start, "n_end": n_end} def _select_reserved_slots(available_slots: List[int], n_slots: int, reservation: Dict[str, int]) -> Optional[List[int]]: requested_slots = list(range(reservation["n_start"], reservation["n_end"] + 1)) if len(requested_slots) < n_slots: raise ValueError( "Optical spectrum reservation provides {:d} slots, but {:d} are required".format( len(requested_slots), n_slots ) ) selected_slots = requested_slots[0:n_slots] if not list_in_list(selected_slots, sorted(available_slots)): return None return selected_slots def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None, reservation=None): # First Fit reservation = parse_slot_reservation(reservation) if isinstance(n_slots, int): slot_c = n_slots slot_l = n_slots Loading @@ -262,6 +322,18 @@ def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None): slot_c = Nc slot_l = Nl slot_s = Ns if reservation is not None: band = reservation["band"] if band == "c_slots": selected_slots = _select_reserved_slots(c, slot_c, reservation) elif band == "l_slots": selected_slots = _select_reserved_slots(l, slot_l, reservation) else: selected_slots = _select_reserved_slots(s, slot_s, reservation) if selected_slots is None: return None, None return band, selected_slots if preferred == None or preferred == "ANY": if len(c) >= slot_c: return "c_slots", c[0: slot_c] Loading Loading @@ -371,4 +443,3 @@ def set_link_update (fib:dict,link:dict,test="updating"): except Exception as err: print (f"setOpticalLink {err}") Loading
src/opticalcontroller/OpticalController.py +11 −2 Original line number Diff line number Diff line Loading @@ -13,7 +13,7 @@ # limitations under the License. import logging, time from flask import Flask from flask import Flask, request from flask import render_template from common.DeviceTypes import DeviceTypeEnum from flask_restplus import Resource, Api Loading Loading @@ -88,7 +88,16 @@ class AddFlexLightpath(Resource): # rsa.g.printGraph() if rsa is not None: flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band, obx_idx, pref) reservation = request.args.get("reservation") if reservation is None and request.args.get("reservation_band") is not None: reservation = { "band": request.args.get("reservation_band"), "n_start": request.args.get("reservation_start"), "n_end": request.args.get("reservation_end"), } flow_id, optical_band_id = rsa.rsa_fs_computation( src, dst, bitrate, bidir, band, obx_idx, pref, reservation=reservation ) if flow_id is not None: if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 Loading
src/opticalcontroller/RSA.py +26 −15 Original line number Diff line number Diff line Loading @@ -614,10 +614,13 @@ class RSA(): return fiber_list #function invoked for lightpaths and OB def select_slots_and_ports(self, links, n_slots, c, l, s, bidir, preferred=None): def select_slots_and_ports(self, links, n_slots, c, l, s, bidir, preferred=None, reservation=None): if debug: print (links, n_slots, c, l, s, bidir, self.c_slot_number, self.l_slot_number, self.s_slot_number) band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, preferred) band, slots = slot_selection( c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, preferred, reservation=reservation ) if debug: print (band, slots) if band is None: Loading Loading @@ -686,10 +689,13 @@ class RSA(): return t_flows, band, slots, {}, {} #function ivoked for fs lightpaths only def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id): def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id, reservation=None): if debug: print(self.links_dict) band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number) band, slots = slot_selection( c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, reservation=reservation ) if band is None: print("ERROR: No slots available in the three bands") return None, None, None, None, None Loading Loading @@ -953,7 +959,7 @@ class RSA(): #self.db_flows[flow_id]["parent_opt_band"] = 0 #self.db_flows[flow_id]["new_optical_band"] = 0 def create_optical_band(self, links, path, bidir, num_slots, old_band_x=None, preferred=None): def create_optical_band(self, links, path, bidir, num_slots, old_band_x=None, preferred=None, reservation=None): print("INFO: Creating optical-band of {} slots".format(num_slots)) if self.opt_band_id == 0: self.opt_band_id += 1 Loading Loading @@ -1008,7 +1014,9 @@ class RSA(): print(l_slots) print(s_slots) if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir, preferred) flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports( links, num_slots, c_slots, l_slots, s_slots, bidir, preferred, reservation=reservation ) if debug: print(flow_list, band_range, slots, fiber_f, fiber_b) f0, band = frequency_converter(band_range, slots) Loading Loading @@ -1203,7 +1211,7 @@ class RSA(): self.null_values(self.flow_id) return self.flow_id def rsa_fs_computation(self, src, dst, rate, bidir, band, bandx_id, preferred=None): def rsa_fs_computation(self, src, dst, rate, bidir, band, bandx_id, preferred=None, reservation=None): if band is not None: num_slots_ob = map_band_to_slot(band) print(band, num_slots_ob) Loading @@ -1227,7 +1235,9 @@ class RSA(): if len(path) < 1: self.null_values_ob(self.opt_band_id) return self.opt_band_id, [] optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob, old_band_x, preferred) optical_band_id, temp_links = self.create_optical_band( links, path, bidir, num_slots_ob, old_band_x, preferred, reservation=reservation ) return None, optical_band_id print("INFO: TP to TP connection") if self.flow_id == 0: Loading Loading @@ -1285,7 +1295,7 @@ class RSA(): flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, ob_id) ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading Loading @@ -1345,7 +1355,7 @@ class RSA(): temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, ob_id) ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading Loading @@ -1399,7 +1409,7 @@ class RSA(): flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, ob_id) ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading Loading @@ -1465,7 +1475,7 @@ class RSA(): temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, ob_id) ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading Loading @@ -1510,7 +1520,7 @@ class RSA(): print("INFO: optical-band width specified") #if no OB I create a new one links, path = self.compute_path(src, dst) optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob, reservation=reservation) op, num_slots = map_rate_to_slot(rate) if debug: print(temp_links) Loading @@ -1520,8 +1530,9 @@ class RSA(): print(l_slots) print(s_slots) if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links, num_slots, c_slots, l_slots, s_slots, bidir, optical_band_id) flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs( temp_links, num_slots, c_slots, l_slots, s_slots, bidir, optical_band_id, reservation=reservation ) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) Loading
src/opticalcontroller/tests/test_spectrum_reservation.py 0 → 100644 +90 −0 Original line number Diff line number Diff line # Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import pytest from opticalcontroller.tools import parse_slot_reservation, slot_selection def test_parse_compact_optical_spectrum_reservation(): reservation = parse_slot_reservation("C_BAND:51-66") assert reservation == {"band": "c_slots", "n_start": 51, "n_end": 66} def test_parse_dict_optical_spectrum_reservation(): reservation = parse_slot_reservation({"band": "l_slots", "n_start": "4", "n_end": "11"}) assert reservation == {"band": "l_slots", "n_start": 4, "n_end": 11} def test_slot_selection_without_reservation_keeps_first_fit(): band, slots = slot_selection( c=list(range(0, 10)), l=list(range(20, 30)), s=list(range(40, 50)), n_slots=4, Nc=10, Nl=10, Ns=10, ) assert band == "c_slots" assert slots == [0, 1, 2, 3] def test_slot_selection_with_reservation_consumes_requested_band_and_range(): band, slots = slot_selection( c=list(range(0, 100)), l=list(range(0, 100)), s=list(range(0, 100)), n_slots=4, Nc=100, Nl=100, Ns=100, reservation={"band": "l_slots", "n_start": 20, "n_end": 30}, ) assert band == "l_slots" assert slots == [20, 21, 22, 23] def test_slot_selection_with_unavailable_reservation_returns_none(): band, slots = slot_selection( c=[0, 1, 2, 3], l=[10, 11, 13, 14], s=[20, 21, 22, 23], n_slots=3, Nc=4, Nl=4, Ns=4, reservation={"band": "l_slots", "n_start": 10, "n_end": 12}, ) assert band is None assert slots is None def test_slot_selection_rejects_too_narrow_reservation(): with pytest.raises(ValueError): slot_selection( c=list(range(0, 100)), l=[], s=[], n_slots=4, Nc=100, Nl=0, Ns=0, reservation={"band": "c_slots", "n_start": 20, "n_end": 22}, )
src/opticalcontroller/tools.py +75 −4 Original line number Diff line number Diff line Loading @@ -12,7 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. import numpy as np import json, logging, numpy as np from typing import Dict, List, Optional, Tuple from opticalcontroller.variables import * import json , logging from context.client.ContextClient import ContextClient Loading Loading @@ -251,9 +252,68 @@ def get_links_to_node(topology, node): return result def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None): # First Fit def _normalize_reservation_band(band: str) -> str: normalized_band = str(band).strip().lower().replace("-", "_") if normalized_band in {"c", "c_band", "c_slots"}: return "c_slots" if normalized_band in {"l", "l_band", "l_slots"}: return "l_slots" if normalized_band in {"s", "s_band", "s_slots"}: return "s_slots" raise ValueError("Unsupported optical spectrum band: {:s}".format(str(band))) def parse_slot_reservation(reservation) -> Optional[Dict[str, int]]: if reservation is None: return None if isinstance(reservation, dict): if len(reservation) == 0: return None band = reservation.get("band") n_start = reservation.get("n_start", reservation.get("start")) n_end = reservation.get("n_end", reservation.get("end")) else: reservation_text = str(reservation).strip() if len(reservation_text) == 0: return None if reservation_text.startswith("{"): return parse_slot_reservation(json.loads(reservation_text)) if ":" not in reservation_text or "-" not in reservation_text: raise ValueError( "Optical spectrum reservation must be '<band>:<start>-<end>' or JSON" ) band, slot_range = reservation_text.split(":", maxsplit=1) n_start, n_end = slot_range.split("-", maxsplit=1) band = _normalize_reservation_band(band) n_start = int(n_start) n_end = int(n_end) if n_start < 0 or n_end < n_start: raise ValueError( "Invalid optical spectrum reservation range: {:d}-{:d}".format(n_start, n_end) ) return {"band": band, "n_start": n_start, "n_end": n_end} def _select_reserved_slots(available_slots: List[int], n_slots: int, reservation: Dict[str, int]) -> Optional[List[int]]: requested_slots = list(range(reservation["n_start"], reservation["n_end"] + 1)) if len(requested_slots) < n_slots: raise ValueError( "Optical spectrum reservation provides {:d} slots, but {:d} are required".format( len(requested_slots), n_slots ) ) selected_slots = requested_slots[0:n_slots] if not list_in_list(selected_slots, sorted(available_slots)): return None return selected_slots def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None, reservation=None): # First Fit reservation = parse_slot_reservation(reservation) if isinstance(n_slots, int): slot_c = n_slots slot_l = n_slots Loading @@ -262,6 +322,18 @@ def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None): slot_c = Nc slot_l = Nl slot_s = Ns if reservation is not None: band = reservation["band"] if band == "c_slots": selected_slots = _select_reserved_slots(c, slot_c, reservation) elif band == "l_slots": selected_slots = _select_reserved_slots(l, slot_l, reservation) else: selected_slots = _select_reserved_slots(s, slot_s, reservation) if selected_slots is None: return None, None return band, selected_slots if preferred == None or preferred == "ANY": if len(c) >= slot_c: return "c_slots", c[0: slot_c] Loading Loading @@ -371,4 +443,3 @@ def set_link_update (fib:dict,link:dict,test="updating"): except Exception as err: print (f"setOpticalLink {err}")