Loading src/realizer/e2e/e2e_connect.py +36 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ # This file is an original contribution from Telefonica Innovación Digital S.L. from ..tfs.helpers.tfs_connector import tfs_connector import logging, requests import os def e2e_connect(requests, controller_ip): """ Loading @@ -24,5 +26,37 @@ def e2e_connect(requests, controller_ip): requests (list): List of requests to be sent to the TFS e2e controller. controller_ip (str): IP address of the TFS e2e controller. """ response = tfs_connector().webui_post(controller_ip, requests) def _extract_slice_id(payload): if isinstance(payload, dict): services = payload.get("services") else: services = payload if not services or not isinstance(services, list): return None first_service = services[0] if isinstance(first_service, list) and first_service: first_service = first_service[0] if not isinstance(first_service, dict): return None slice_id = first_service.get("service_id", {}).get("service_uuid", {}).get("uuid") if slice_id: return slice_id rule_set = first_service.get("rule_set", {}) l3vpn = rule_set.get("l3vpn", {}) slice_id = l3vpn.get("tunnel-uuid") or l3vpn.get("uuid") if slice_id: return slice_id return rule_set.get("uuid") slice_id = _extract_slice_id(requests) or "TEST-SLICE" logging.info("Connecting end-to-end services in TFS controller at %s with slice ID %s", controller_ip, slice_id) response = tfs_connector().ipowdm_post(os.getenv("E2E_OPTICAL_IP"), slice_id, requests) return response src/realizer/e2e/service_types/l3ipowdm_slice.py +31 −55 Original line number Diff line number Diff line Loading @@ -87,65 +87,41 @@ def l3ipowdm_slice(rules): logging.debug(f"Sending Media Channel Service to Orchestrator: {tfs_request}") tfs_requests.append(tfs_request) elif rule["type"] == "ACTIVATE_TRANSCEIVER": params = { "router_id": rule["content"]["node-uuid"], "router_tp": rule["content"]["termination-point-uuid"], "frequency": rule["content"]["frequency-ghz"], "power": rule["content"]["tx-power-dbm"] } transceiver_params.append(params) elif rule["type"] == "CONFIG_VPNL3": src_router_id = rule["content"]["src-node-uuid"] if src_router_id == transceiver_params[0]["router_id"]: src_power = transceiver_params[0]["power"] src_frequency = transceiver_params[0]["frequency"] dst_power = transceiver_params[1]["power"] dst_frequency = transceiver_params[1]["frequency"] else: src_power = transceiver_params[1]["power"] src_frequency = transceiver_params[1]["frequency"] dst_power = transceiver_params[0]["power"] dst_frequency = transceiver_params[0]["frequency"] src_router_id = rule["content"]["src-node-uuid"] src_ip_address = rule["content"]["src-ip-address"] src_ip_mask = rule["content"]["src-ip-mask"] src_vlan_id = rule["content"]["src-vlan-id"] dst_router_id = rule["content"]["dest-node-uuid"] dst_ip_address = rule["content"]["dest-ip-address"] dst_ip_mask = rule["content"]["dest-ip-mask"] dst_vlan_id = rule["content"]["dest-vlan-id"] elif rule["type"] == "XR_AGENT_ACTIVATE_TRANSCEIVER": transceiver_params = rule["content"]["components"] elif rule["type"] == "CONFIG_VPNL3": service_uuid = rule["content"]["tunnel-uuid"] tfs_request = load_template(os.path.join(TEMPLATES_PATH, "IPoWDM_orchestrator.json")) tfs_request["services"][0]["service_id"]["service_uuid"]["uuid"] = service_uuid config_rules = tfs_request["services"][0]["service_config"]["config_rules"][0] src = config_rules["ipowdm"]["rule_set"]["src"] src.append({ 'uuid': src_router_id, 'ip_address': src_ip_address, 'ip_mask': src_ip_mask, 'vlan_id': src_vlan_id, 'power': src_power, 'frequency': src_frequency }) src = [{ 'uuid': rule["content"]["src-node-uuid"], 'ip_address': rule["content"]["src-ip-address"], 'ip_mask': rule["content"]["src-ip-mask"], 'vlan_id': rule["content"]["src-vlan-id"] }] dst = config_rules["ipowdm"]["rule_set"]["dst"] dst = [] i = 1 while f"dest{i}-node-uuid" in rule["content"]: dst.append({ 'uuid': dst_router_id, 'ip_address': dst_ip_address, 'ip_mask': dst_ip_mask, 'vlan_id': dst_vlan_id, 'power': dst_power, 'frequency': dst_frequency 'uuid': rule["content"][f"dest{i}-node-uuid"], 'ip_address': rule["content"][f"dest{i}-ip-address"], 'ip_mask': rule["content"][f"dest{i}-ip-mask"], 'vlan_id': rule["content"][f"dest{i}-vlan-id"] }) i += 1 config_rules["ipowdm"]["rule_set"]["bw"] = bandwidth config_rules["ipowdm"]["rule_set"]["uuid"] = service_uuid tfs_request = load_template(os.path.join(TEMPLATES_PATH, "IPoWDM_orchestrator.json")) config_rules = tfs_request config_rules["endpoint_id"]["device_id"]["device_uuid"]["uuid"] = rule["controller_uuid"] config_rules["rule_set"]["uuid"] = rule["controller_uuid"] config_rules["rule_set"]["src"] = src config_rules["rule_set"]["dst"] = dst config_rules["rule_set"]["transceiver"] = { "components": transceiver_params } config_rules["rule_set"]["l3vpn"] = rule["content"] logging.debug(f"Sending IPoWDM Service to Orchestrator: {tfs_request}") tfs_requests.append(tfs_request) Loading src/realizer/restconf/service_types/builders/create_site_from_sdp.py +3 −2 Original line number Diff line number Diff line Loading @@ -39,13 +39,14 @@ def create_site_from_sdp(sdp, ietf_intent, connectivity_type, layer_type): router_id = safe_get(sdp, ["sdp", "attachment-circuits", "attachment-circuit", 0, "ac-node-id"]) router_if = safe_get(sdp, ["sdp", "attachment-circuits", "attachment-circuit", 0, "ac-tp-id"]) logging.debug(f"Configured site for SDP {safe_get(sdp, ['sdp', 'id'])} with location: {location}, router_id: {router_id}, router_if: {router_if}") sdp_id = safe_get(sdp, ["sdp", "id"]) or safe_get(sdp, ["sdp", "node-id"]) logging.debug(f"Configured site for SDP {sdp_id} with location: {location}, router_id: {router_id}, router_if: {router_if}") network_access = create_network_access(sdp, ietf_intent, connectivity_type, router_id, router_if, layer_type) # Create site structure site = { "site-id": safe_get(sdp, ["sdp", "id"]), "site-id": sdp_id, "locations": { "location": [{"location-id": location}] }, Loading src/realizer/send_controller.py +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ def send_controller(controller_type, requests): response = ixia_connect(requests, current_app.config["IXIA_IP"]) logging.info("Requests sent to Ixia") elif controller_type == "E2E": response = e2e_connect(requests, current_app.config["TFS_E2E"]) response = e2e_connect(requests, current_app.config["TFS_E2E_IP"]) logging.info("Requests sent to Teraflow E2E") elif controller_type == "RESTCONF": response = restconf_connect(requests, current_app.config["RESTCONF_IP"]) Loading src/realizer/tfs/helpers/tfs_connector.py +29 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,35 @@ class tfs_connector(): logging.debug("Http response: %s",response.text) return response def ipowdm_post(self, tfs_ip: str, slice_id: str, payload: object, timeout: int = 60): """ Post IPoWDM service payload to the controller NBI endpoint: http://{tfs_ip}/restconf/ipowdm/v1/service/{slice_id} Args: tfs_ip: controller host (ip[:port]) slice_id: identifier for the slice (path parameter) payload: JSON-serializable payload to send timeout: request timeout in seconds Returns: requests.Response """ session = requests.Session() url = f'http://{tfs_ip}/restconf/ipowdm/v1/service/{slice_id}' headers = {'Content-Type': 'application/json'} data = json.dumps(payload) # logging.debug("Posting IPoWDM to %s: %s", url, data) # response = session.post(url, headers=headers, data=data, timeout=timeout) # response.raise_for_status() # logging.debug("Http response: %s", response.text) # STATIC RESPONSE FOR TESTING PURPOSES response = requests.Response() response.status_code = 200 response._content = b'{"status": "success", "message": "IPoWDM service created successfully"}' logging.debug("Mocked Http response: %s", response.text) return response def nbi_delete(self, tfs_ip: str, service_type: str , service_id: str) -> requests.Response: """ Delete service from TFS NBI. Loading Loading
src/realizer/e2e/e2e_connect.py +36 −2 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ # This file is an original contribution from Telefonica Innovación Digital S.L. from ..tfs.helpers.tfs_connector import tfs_connector import logging, requests import os def e2e_connect(requests, controller_ip): """ Loading @@ -24,5 +26,37 @@ def e2e_connect(requests, controller_ip): requests (list): List of requests to be sent to the TFS e2e controller. controller_ip (str): IP address of the TFS e2e controller. """ response = tfs_connector().webui_post(controller_ip, requests) def _extract_slice_id(payload): if isinstance(payload, dict): services = payload.get("services") else: services = payload if not services or not isinstance(services, list): return None first_service = services[0] if isinstance(first_service, list) and first_service: first_service = first_service[0] if not isinstance(first_service, dict): return None slice_id = first_service.get("service_id", {}).get("service_uuid", {}).get("uuid") if slice_id: return slice_id rule_set = first_service.get("rule_set", {}) l3vpn = rule_set.get("l3vpn", {}) slice_id = l3vpn.get("tunnel-uuid") or l3vpn.get("uuid") if slice_id: return slice_id return rule_set.get("uuid") slice_id = _extract_slice_id(requests) or "TEST-SLICE" logging.info("Connecting end-to-end services in TFS controller at %s with slice ID %s", controller_ip, slice_id) response = tfs_connector().ipowdm_post(os.getenv("E2E_OPTICAL_IP"), slice_id, requests) return response
src/realizer/e2e/service_types/l3ipowdm_slice.py +31 −55 Original line number Diff line number Diff line Loading @@ -87,65 +87,41 @@ def l3ipowdm_slice(rules): logging.debug(f"Sending Media Channel Service to Orchestrator: {tfs_request}") tfs_requests.append(tfs_request) elif rule["type"] == "ACTIVATE_TRANSCEIVER": params = { "router_id": rule["content"]["node-uuid"], "router_tp": rule["content"]["termination-point-uuid"], "frequency": rule["content"]["frequency-ghz"], "power": rule["content"]["tx-power-dbm"] } transceiver_params.append(params) elif rule["type"] == "CONFIG_VPNL3": src_router_id = rule["content"]["src-node-uuid"] if src_router_id == transceiver_params[0]["router_id"]: src_power = transceiver_params[0]["power"] src_frequency = transceiver_params[0]["frequency"] dst_power = transceiver_params[1]["power"] dst_frequency = transceiver_params[1]["frequency"] else: src_power = transceiver_params[1]["power"] src_frequency = transceiver_params[1]["frequency"] dst_power = transceiver_params[0]["power"] dst_frequency = transceiver_params[0]["frequency"] src_router_id = rule["content"]["src-node-uuid"] src_ip_address = rule["content"]["src-ip-address"] src_ip_mask = rule["content"]["src-ip-mask"] src_vlan_id = rule["content"]["src-vlan-id"] dst_router_id = rule["content"]["dest-node-uuid"] dst_ip_address = rule["content"]["dest-ip-address"] dst_ip_mask = rule["content"]["dest-ip-mask"] dst_vlan_id = rule["content"]["dest-vlan-id"] elif rule["type"] == "XR_AGENT_ACTIVATE_TRANSCEIVER": transceiver_params = rule["content"]["components"] elif rule["type"] == "CONFIG_VPNL3": service_uuid = rule["content"]["tunnel-uuid"] tfs_request = load_template(os.path.join(TEMPLATES_PATH, "IPoWDM_orchestrator.json")) tfs_request["services"][0]["service_id"]["service_uuid"]["uuid"] = service_uuid config_rules = tfs_request["services"][0]["service_config"]["config_rules"][0] src = config_rules["ipowdm"]["rule_set"]["src"] src.append({ 'uuid': src_router_id, 'ip_address': src_ip_address, 'ip_mask': src_ip_mask, 'vlan_id': src_vlan_id, 'power': src_power, 'frequency': src_frequency }) src = [{ 'uuid': rule["content"]["src-node-uuid"], 'ip_address': rule["content"]["src-ip-address"], 'ip_mask': rule["content"]["src-ip-mask"], 'vlan_id': rule["content"]["src-vlan-id"] }] dst = config_rules["ipowdm"]["rule_set"]["dst"] dst = [] i = 1 while f"dest{i}-node-uuid" in rule["content"]: dst.append({ 'uuid': dst_router_id, 'ip_address': dst_ip_address, 'ip_mask': dst_ip_mask, 'vlan_id': dst_vlan_id, 'power': dst_power, 'frequency': dst_frequency 'uuid': rule["content"][f"dest{i}-node-uuid"], 'ip_address': rule["content"][f"dest{i}-ip-address"], 'ip_mask': rule["content"][f"dest{i}-ip-mask"], 'vlan_id': rule["content"][f"dest{i}-vlan-id"] }) i += 1 config_rules["ipowdm"]["rule_set"]["bw"] = bandwidth config_rules["ipowdm"]["rule_set"]["uuid"] = service_uuid tfs_request = load_template(os.path.join(TEMPLATES_PATH, "IPoWDM_orchestrator.json")) config_rules = tfs_request config_rules["endpoint_id"]["device_id"]["device_uuid"]["uuid"] = rule["controller_uuid"] config_rules["rule_set"]["uuid"] = rule["controller_uuid"] config_rules["rule_set"]["src"] = src config_rules["rule_set"]["dst"] = dst config_rules["rule_set"]["transceiver"] = { "components": transceiver_params } config_rules["rule_set"]["l3vpn"] = rule["content"] logging.debug(f"Sending IPoWDM Service to Orchestrator: {tfs_request}") tfs_requests.append(tfs_request) Loading
src/realizer/restconf/service_types/builders/create_site_from_sdp.py +3 −2 Original line number Diff line number Diff line Loading @@ -39,13 +39,14 @@ def create_site_from_sdp(sdp, ietf_intent, connectivity_type, layer_type): router_id = safe_get(sdp, ["sdp", "attachment-circuits", "attachment-circuit", 0, "ac-node-id"]) router_if = safe_get(sdp, ["sdp", "attachment-circuits", "attachment-circuit", 0, "ac-tp-id"]) logging.debug(f"Configured site for SDP {safe_get(sdp, ['sdp', 'id'])} with location: {location}, router_id: {router_id}, router_if: {router_if}") sdp_id = safe_get(sdp, ["sdp", "id"]) or safe_get(sdp, ["sdp", "node-id"]) logging.debug(f"Configured site for SDP {sdp_id} with location: {location}, router_id: {router_id}, router_if: {router_if}") network_access = create_network_access(sdp, ietf_intent, connectivity_type, router_id, router_if, layer_type) # Create site structure site = { "site-id": safe_get(sdp, ["sdp", "id"]), "site-id": sdp_id, "locations": { "location": [{"location-id": location}] }, Loading
src/realizer/send_controller.py +1 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ def send_controller(controller_type, requests): response = ixia_connect(requests, current_app.config["IXIA_IP"]) logging.info("Requests sent to Ixia") elif controller_type == "E2E": response = e2e_connect(requests, current_app.config["TFS_E2E"]) response = e2e_connect(requests, current_app.config["TFS_E2E_IP"]) logging.info("Requests sent to Teraflow E2E") elif controller_type == "RESTCONF": response = restconf_connect(requests, current_app.config["RESTCONF_IP"]) Loading
src/realizer/tfs/helpers/tfs_connector.py +29 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,35 @@ class tfs_connector(): logging.debug("Http response: %s",response.text) return response def ipowdm_post(self, tfs_ip: str, slice_id: str, payload: object, timeout: int = 60): """ Post IPoWDM service payload to the controller NBI endpoint: http://{tfs_ip}/restconf/ipowdm/v1/service/{slice_id} Args: tfs_ip: controller host (ip[:port]) slice_id: identifier for the slice (path parameter) payload: JSON-serializable payload to send timeout: request timeout in seconds Returns: requests.Response """ session = requests.Session() url = f'http://{tfs_ip}/restconf/ipowdm/v1/service/{slice_id}' headers = {'Content-Type': 'application/json'} data = json.dumps(payload) # logging.debug("Posting IPoWDM to %s: %s", url, data) # response = session.post(url, headers=headers, data=data, timeout=timeout) # response.raise_for_status() # logging.debug("Http response: %s", response.text) # STATIC RESPONSE FOR TESTING PURPOSES response = requests.Response() response.status_code = 200 response._content = b'{"status": "success", "message": "IPoWDM service created successfully"}' logging.debug("Mocked Http response: %s", response.text) return response def nbi_delete(self, tfs_ip: str, service_type: str , service_id: str) -> requests.Response: """ Delete service from TFS NBI. Loading