Commit af45ad8b authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Service component:

- Implement optical spectrum reservation in add_lightpath
- Add tests for the new functionality
parent a1a6f027
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -55,6 +55,21 @@ LOGGER = logging.getLogger(__name__)

METRICS_POOL = MetricsPool('Service', 'RPC')

def _load_opticalcontroller_reply(reply_txt : str) -> Dict:
    try:
        reply_json = json.loads(reply_txt)
    except json.JSONDecodeError as exc:
        raise OperationFailedException(
            'optical-controller-reply',
            extra_details='reply={:s}'.format(str(reply_txt))
        ) from exc
    if not isinstance(reply_json, dict):
        raise OperationFailedException(
            'optical-controller-reply',
            extra_details='reply={:s}'.format(str(reply_txt))
        )
    return reply_json


class ServiceServiceServicerImpl(ServiceServiceServicer):
    def __init__(self, service_handler_factory : ServiceHandlerFactory) -> None:
@@ -350,7 +365,9 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
                        spectrum_reservation=spectrum_reservation
                    )
                elif oc_type == 2:
                    reply_txt = add_lightpath(src, dst, bitrate, bidir)
                    reply_txt = add_lightpath(
                        src, dst, bitrate, bidir, spectrum_reservation=spectrum_reservation
                    )
                else:
                    reply_txt = add_flex_lightpath(
                        src, dst, bitrate, bidir, preferred, ob_band, dj_optical_band_id,
@@ -358,7 +375,7 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
                    )
            if reply_txt is None:
                return service_with_uuids.service_id
            reply_json = json.loads(reply_txt)
            reply_json = _load_opticalcontroller_reply(reply_txt)
            LOGGER.debug('[optical] reply_json[{:s}]={:s}'.format(str(type(reply_json)), str(reply_json)))
            optical_band_txt = ""
            
+17 −1
Original line number Diff line number Diff line
@@ -189,7 +189,7 @@ def add_alien_flex_lightpath(src, s_port, dst, d_port, band, ob_id, bidir=None)
    reply = r.text 
    return reply

def add_lightpath(src, dst, bitrate, bidir) -> str:
def add_lightpath(src, dst, bitrate, bidir, spectrum_reservation: Optional[Dict] = None) -> str:
    if not TESTING:
        urlx = ""
        headers = {"Content-Type": "application/json"}
@@ -197,6 +197,13 @@ def add_lightpath(src, dst, bitrate, bidir) -> str:
        if bidir is None:
            bidir = 1
        urlx = "{:s}/AddLightpath/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(bidir))
        if spectrum_reservation is not None:
            query = {
                'reservation_band': spectrum_reservation['band'],
                'reservation_start': str(spectrum_reservation['n_start']),
                'reservation_end': str(spectrum_reservation['n_end']),
            }
            urlx = '{:s}?{:s}'.format(urlx, urlencode(query))
        r = requests.put(urlx, headers=headers)
        LOGGER.debug(f"addpathlight {r}")
        reply = r.text 
@@ -541,6 +548,9 @@ def adapt_reply(
    op_mode = r["op-mode"] if "op-mode" in r else None
    frequency = r["freq"] if "freq" in r else None
    flow_id = r["flow_id"] if "flow_id" in r else None
    slots = r["slots"] if "slots" in r else None
    links = r["links"] if "links" in r else None
    path = r["path"] if "path" in r else None
    r_type = r["band_type"] if "band_type" in r else None
    if r_type == "l_slots":
        band_type = "L_BAND"
@@ -553,6 +563,12 @@ def adapt_reply(
        val = {"target-output-power": "1.0", "frequency": frequency, "operational-mode": op_mode, "band": band, "flow_id": flow_id, "ob_id": ob_id, "band_type": band_type, "bidir": bidir_f}
    else:
        val = {"target-output-power": "1.0", "frequency": frequency, "operational-mode": op_mode, "band": band, "flow_id": flow_id, "band_type": band_type, "bidir": bidir_f}
    if slots is not None:
        val["slots"] = slots
    if links is not None:
        val["links"] = links
    if path is not None:
        val["path"] = path
    custom_rule = ConfigRule_Custom(resource_key="/settings", resource_value=json.dumps(val))
    rule = ConfigRule(action=ConfigActionEnum.CONFIGACTION_SET, custom=custom_rule)
    service.service_config.config_rules.add().CopyFrom(rule)
+29 −0
Original line number Diff line number Diff line
@@ -72,3 +72,32 @@ def test_add_flex_lightpath_forwards_reservation_query(monkeypatch):
    assert "reservation_band=c_slots" in captured["url"]
    assert "reservation_start=51" in captured["url"]
    assert "reservation_end=66" in captured["url"]


def test_add_lightpath_forwards_reservation_query(monkeypatch):
    captured = {}

    class Response:
        text = "{}"

    def put(url, headers=None):
        captured["url"] = url
        captured["headers"] = headers
        return Response()

    monkeypatch.setattr(OpticalTools, "get_optical_controller_base_url", lambda: "http://optical/OpticalTFS")
    monkeypatch.setattr(OpticalTools.requests, "put", put)
    monkeypatch.setattr(OpticalTools, "TESTING", False)

    OpticalTools.add_lightpath(
        "T1",
        "T2",
        100,
        0,
        spectrum_reservation={"band": "c_slots", "n_start": 51, "n_end": 66},
    )

    assert captured["url"].startswith("http://optical/OpticalTFS/AddLightpath/T1/T2/100/0?")
    assert "reservation_band=c_slots" in captured["url"]
    assert "reservation_start=51" in captured["url"]
    assert "reservation_end=66" in captured["url"]