Commit faf76cc2 authored by Pablo Armingol's avatar Pablo Armingol
Browse files

refactor: Update service templates with new parameters and restructure...

refactor: Update service templates with new parameters and restructure deletion logic in the network slice controller.
parent 8bd4d91b
Loading
Loading
Loading
Loading
+241 −74
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ class NSController:
        self.__teraflow_template = ""
        self.__nrp_view = ""
        self.subnet=""
        self.delete = 0

    # API Methods
    def add_flow(self, intent):
@@ -255,7 +256,8 @@ class NSController:
                logging.info("DELETE REQUEST RECEIVED: %s", intent_json)

                rules = send_network_slice_request(intent_json, action)
                logging.info("Rules loaded: %s", rules)
                logging.info("Rules loaded from HRAT")
                logging.info("Rules: %s", rules)
                tfs_request = self.__realizer(rules=rules)
            else:
                # Start performance tracking
@@ -276,7 +278,8 @@ class NSController:
                        self.__mapper(intent, action)
                        # Realizer
                        rules = send_network_slice_request(intent, action)
                        logging.info("Rules loaded: %s", rules)
                        logging.info("Rules loaded from HRAT")
                        logging.info("Rules: %s", rules)
                        service_uuid = rules.get("network-slice-uuid")

                        self.__store_data(intent, slice_id, service_uuid = service_uuid)
@@ -978,7 +981,22 @@ class NSController:
        """

        transceiver_params = []
        logging.info(f"Delete level: {self.delete}")
        if self.delete == 1:
            self.delete = 0
            logging.info("Deleting Optical Slice")
            response = None
            for rule in rules["actions"]:
                    if rule["type"] == "REMOVE_OPTICAL_SLICE":

                        logging.info("Sending DELETE Optical Slice request to Optical Controller")
                        url = f'http://11.1.1.101:4900/restconf/data/tapi-common:context=819df891-180d-4e00-986d-06e982326975'
                        response = requests.delete(url, timeout=10)
                        logging.info("Response from Optical Controller: %s", response)
        elif self.delete == 0:
            logging.info("Deleting L3oWDM service")
            self.delete = 1
            response = None
            for rule in rules["actions"]:
                if rule["type"] == "DEACTIVATE_TRANSCEIVER":
                    params = {
@@ -988,18 +1006,14 @@ class NSController:
                    transceiver_params.append(params)

            for rule in rules["actions"]:
            if rule["type"] == "REMOVE_OPTICAL_SLICE":
                logging.info("Sending DELETE Optical Slice request to Optical Controller")
                url = f'http://11.1.1.101:4900/restconf/data/tapi-common:context={rule["content"]["tenant-uuid"]}'
                response = requests.delete(url, timeout=10)
                logging.info("Response from Optical Controller: %s", response)
                if rule["type"] == "DEPROVISION_OPTICAL_RESOURCE":

            elif rule["type"] == "DEPROVISION_OPTICAL_RESOURCE":
                url = f'http://10.95.86.58/restconf/E2E/v1/service/tapi_lsp={rule["tenant-uuid"]}:{rule["content"]["connectivity-service-uuid"]:}'
                    url = f'http://10.95.86.58/restconf/E2E/v1/service/tapi_lsp=819df891-180d-4e00-986d-06e982326975:44eb3931-c0af-497a-84c8-a3e7396c6d3f'
                    logging.info("Sending DELETE Media Channel request to Orchestrator")
                requests.delete(url, timeout=10)

                    response = requests.delete(url, timeout=10)
                    logging.info("Response from Optical Controller: %s", response)
                elif rule["type"] == "REMOVE_VPNL3":

                    logging.info("Sending DELETE IPoWDM service request to Orchestrator")
                    data = {
                        'src_router_id' : transceiver_params[0]["router_id"],
@@ -1008,7 +1022,8 @@ class NSController:
                        'dst_router_tp' : transceiver_params[1]["router_tp"],
                    }
                    url = f'http://10.95.86.58/restconf/E2E/v1/service/ipowdm={rule["content"]["tunnel-uuid"]}:{data}'
                requests.delete(url, json=data, timeout=10)
                    response = requests.delete(url, json=data, timeout=10)
                    logging.info("Response from IPoWDM Controller: %s", response)

    def __optic_slice(self, ietf_intent, rules=None):
        """
@@ -1068,10 +1083,12 @@ class NSController:

    def optical_slice_template(self, template, datos):
        """
        Complete the optical slice template with the data provided.
        Populate the optical slice template with data from the rules.

        Args:
            template (dict): optical slice template.
            data (dict): Data to complete the template.
            template (dict): The template to populate
            datos (dict): The data containing network slice information

        Returns:
            dict: Template completed.
        """
@@ -1084,22 +1101,23 @@ class NSController:
                    if 'media-channel-node-edge-point-spec' in onp:
                        onp['tapi-photonic-media:media-channel-node-edge-point-spec'] = onp.pop('media-channel-node-edge-point-spec')

        for i, sip in enumerate(template['tapi-common:context']['service-interface-point']):
        for i, sip in enumerate(template['data']['tapi-common:context']['service-interface-point']):
            if i < len(datos['actions'][0]['content']['service-interface-point']):
                sip['uuid'] = datos['actions'][0]['content']['service-interface-point'][i]['uuid']

        nodes_template = template['tapi-common:context']['tapi-topology:topology-context']['topology'][0]['node']
        nodes_template = template['data']['tapi-common:context']['tapi-topology:topology-context']['topology'][0]['node']
        nodes_data = datos['actions'][0]['content']['node']
        for new_node in nodes_data:
            nodes_template.append(new_node)

        links_template = template['tapi-common:context']['tapi-topology:topology-context']['topology'][0]['link']
        links_template = template['data']['tapi-common:context']['tapi-topology:topology-context']['topology'][0]['link']
        links_datos = datos['actions'][0]['content']['link']
        for link_t in links_datos:
            links_template.append(link_t)

        template['tapi-common:context']['uuid'] = datos['actions'][0]['content']['tenant-uuid']
        template['tapi-common:context']['name'][0]['value'] = datos['network-slice-uuid']
        template['data']['tapi-common:context']['uuid'] = datos['actions'][0]['content']['tenant-uuid']
        template['data']['tapi-common:context']['name'][0]['value'] = datos['network-slice-uuid']
        template['url'] = datos['actions'][0]['content'].get('url', '')

        return template

@@ -1125,44 +1143,65 @@ class NSController:
        bandwidth = 0
        latency = 0
        vlan_value = 0

        for rule in rules["actions"]:
            if rule["type"] == "CREATE_OPTICAL_SLICE":
                self.__load_template(2, os.path.join(TEMPLATES_PATH, "Optical_slice.json"))
                tfs_request = json.loads(str(self.__teraflow_template))
                self.optical_slice_template(tfs_request, rules)
                logging.info("Sending Optical Slice to Optical Controller")
                logging.info(f"DATOS A ENVIAR: {tfs_request}")

                # self.optical_post(tfs_request)
                logging.info("Service to send: %s",tfs_request)
                self.optical_slice_post(rules['network-slice-uuid'], tfs_request)
                   
            elif rule["type"] == "PROVISION_MEDIA_CHANNEL_OLS_PATH":

                origin_router_id = rule["content"]["src-sip-uuid"]
                destination_router_id = rule["content"]["dest-sip-uuid"]
                direction = rule["content"]["direction"]
                bandwidth = rule["content"]["bandwidth-ghz"]
                service_uuid = rule["content"]["ols-path-uuid"]
                tenant_uuid = rule["tenant-uuid"]
                layer_protocol_name = rule["content"]["layer-protocol-name"]
                layer_protocol_qualifier = rule["content"]["layer-protocol-qualifier"]
                lower_frequency_mhz = rule["content"]["lower-frequency-mhz"]
                upper_frequency_mhz = rule["content"]["upper-frequency-mhz"]
                link_uuid_path = rule["content"]["link-uuid-path"]
                granularity = rule["content"]["adjustment-granularity"]
                grid = rule["content"]["grid-type"]
                content = rule["content"]

                origin_router_id = content.get("src-sip-uuid")
                if origin_router_id is None: raise ValueError("'src-sip-uuid' missing")

                destination_router_id = content.get("dest-sip-uuid")
                if destination_router_id is None: raise ValueError("'dest-sip-uuid' missing")

                direction = content.get("direction")
                if direction is None: raise ValueError("'direction' missing")

                bandwidth = content.get("bandwidth-ghz")
                if bandwidth is None: raise ValueError("'bandwidth-ghz' missing")

                service_uuid = content.get("ols-path-uuid")
                if service_uuid is None: raise ValueError("'ols-path-uuid' missing")

                tenant_uuid = rule.get("tenant-uuid")

                layer_protocol_name = content.get("layer-protocol-name")
                if layer_protocol_name is None: raise ValueError("'layer-protocol-name' missing")

                layer_protocol_qualifier = content.get("layer-protocol-qualifier")
                if layer_protocol_qualifier is None: raise ValueError("'layer-protocol-qualifier' missing")

                lower_frequency_mhz = content.get("lower-frequency-mhz")
                upper_frequency_mhz = content.get("upper-frequency-mhz")
                link_uuid_path = content.get("link-uuid-path")
                granularity = content.get("adjustment-granularity")
                grid = content.get("grid-type")
                capacity_unit = content.get("capacity-unit")
                capacity_value = content.get("capacity-value")
                route_objective_function = content.get("route-objective-function")

                if tenant_uuid: url = f"http://11.1.1.101:4900/{tenant_uuid}/restconf/data/tapi-common:context/tapi-connectivity:connectivity-context"
                else:           url = "http://11.1.1.101:4900/restconf/data/tapi-common:context/tapi-connectivity:connectivity-context"


                self.__load_template(2, os.path.join(TEMPLATES_PATH, "TAPI_service.json"))
                tfs_request = json.loads(str(self.__teraflow_template))
                tfs_request["services"][0]["service_id"]["service_uuid"]["uuid"] = service_uuid
                config_rules = tfs_request["services"][0]["service_config"]["config_rules"][0]

                config_rules["tapi_lsp"]["rule_set"]["src"]  = origin_router_id
                config_rules["tapi_lsp"]["rule_set"]["dst"]  = destination_router_id
                config_rules["tapi_lsp"]["rule_set"]["input_sip"]  = origin_router_id
                config_rules["tapi_lsp"]["rule_set"]["output_sip"]  = destination_router_id
                config_rules["tapi_lsp"]["rule_set"]["uuid"] = service_uuid
                config_rules["tapi_lsp"]["rule_set"]["bw"]   = str(bandwidth)
                config_rules["tapi_lsp"]["rule_set"]["tenant_uuid"] = tenant_uuid
                config_rules["tapi_lsp"]["rule_set"]["direction"] = direction
                config_rules["tapi_lsp"]["rule_set"]["layer_protocol_name"] = layer_protocol_name
                config_rules["tapi_lsp"]["rule_set"]["layer_protocol_qualifier"] = layer_protocol_qualifier
                config_rules["tapi_lsp"]["rule_set"]["lower_frequency_mhz"] = str(lower_frequency_mhz)
@@ -1170,12 +1209,14 @@ class NSController:
                config_rules["tapi_lsp"]["rule_set"]["link_uuid_path"] = link_uuid_path
                config_rules["tapi_lsp"]["rule_set"]["granularity"]    = granularity
                config_rules["tapi_lsp"]["rule_set"]["grid_type"]      = grid
                config_rules["tapi_lsp"]["rule_set"]["direction"]   = direction
                config_rules["tapi_lsp"]["rule_set"]["capacity_unit"] = capacity_unit
                config_rules["tapi_lsp"]["rule_set"]["capacity_value"] = capacity_value
                config_rules["tapi_lsp"]["rule_set"]["route_objective_function"] = route_objective_function
                config_rules["tapi_lsp"]["rule_set"]["url"] = url


                logging.info("Sending Media Channel Service to Orchestrator")
                logging.info(f"DATOS A ENVIAR: {tfs_request}")

                self.tfs_post(self.tfs_ip, tfs_request)
                logging.info(f"Sending Media Channel Service to Orchestrator: {tfs_request}")
                self.media_channel_post(service_uuid, config_rules["tapi_lsp"]["rule_set"])

            elif rule["type"] == "ACTIVATE_TRANSCEIVER":
                params = {
@@ -1238,10 +1279,17 @@ class NSController:
                config_rules["ipowdm"]["rule_set"]["bw"]        = bandwidth
                config_rules["ipowdm"]["rule_set"]["uuid"]      = service_uuid

                logging.info("Sending IPoWDM Service to Orchestrator")
                self.tfs_post(self.tfs_ip, tfs_request)
            else:
                logging.info("Unsupported rule type for optical slice: %s", rule["type"])
                # Prepare IPoWDM payload for NBI
                ipowdm_payload = {
                    "src": config_rules["ipowdm"]["rule_set"]["src"],
                    "dst": config_rules["ipowdm"]["rule_set"]["dst"],
                    "bw": config_rules["ipowdm"]["rule_set"]["bw"],
                    "uuid": service_uuid,
                    "device_id": "TFS-PACKET"
                }

                logging.info(f"Sending IPoWDM Service to Orchestrator: {tfs_request}")
                self.ipowdm_post(service_uuid, ipowdm_payload)

        self.answer[self.subnet]["VLAN"] = vlan_value
        self.answer[self.subnet]["QoS Requirements"] = []
@@ -1267,8 +1315,69 @@ class NSController:
        }

        data = json.dumps(request)
        logging.info("Optical Controller request data: %s",data)

        # requests.post(url, data=data, headers=headers, timeout=10)

    def optical_slice_post(self, slice_uuid, request):
        """
        Send a POST request to the NBI Optical Slice endpoint.

        Args:
            slice_uuid (str): UUID of the optical slice.
            request (dict): The TAPI context payload to be sent.

        Returns:
            dict: The response from the NBI.
        """
        url = f"http://{self.tfs_ip}/restconf/optical-slice/v1/service/{slice_uuid}"
        
        headers = {
            "Content-Type": "application/json"
        }
        
        logging.info(f"Sending Optical Slice POST to {url}")
        logging.info(f"Payload: {json.dumps(request, indent=2)}")
        
        try:
            response = requests.post(url, json=request, headers=headers, timeout=30)
            logging.info(f"Optical Slice response status: {response.status_code}")
            logging.info(f"Optical Slice response: {response.text}")
            return response
        except Exception as e:
            logging.error(f"Failed to send Optical Slice request: {str(e)}")
            raise


    def ipowdm_post(self, service_uuid, ipowdm_data):
        """
        Send a POST request to the NBI IPoWDM endpoint.

        Args:
            service_uuid (str): UUID of the IPoWDM service.
            ipowdm_data (dict): The IPoWDM service data including src, dst, bw, etc.

        Returns:
            dict: The response from the NBI.
        """
        url = f"http://{self.tfs_ip}/restconf/ipowdm/v1/service/{service_uuid}"
        
        headers = {
            "Content-Type": "application/json"
        }
        
        logging.info(f"Sending IPoWDM POST to {url}")
        logging.info(f"Payload: {json.dumps(ipowdm_data, indent=2)}")
        
        try:
            response = requests.post(url, json=ipowdm_data, headers=headers, timeout=30)
            logging.info(f"IPoWDM response status: {response.status_code}")
            logging.info(f"IPoWDM response: {response.text}")
            return response
        except Exception as e:
            logging.error(f"Failed to send IPoWDM request: {str(e)}")
            raise

        requests.post(url, data=data, headers=headers, timeout=10)

    def tfs_post(self, ip, request):
        """
@@ -1302,6 +1411,64 @@ class NSController:

        return response

    def media_channel_post(self, service_uuid, rule_set):
        """
        Send a POST request to the NBI Media Channel endpoint.

        Args:
            service_uuid (str): UUID of the media channel service.
            rule_set (dict): Configuration data for the media channel.

        Returns:
            dict: The response from the NBI.
        """
        url = f"http://{self.tfs_ip}/restconf/media-channel/v1/service/{service_uuid}"
        
        # Prepare payload according to NBI media channel format
        payload = {
            "input_sip": rule_set["input_sip"],
            "output_sip": rule_set["output_sip"],
            "uuid": rule_set["uuid"],
            "bw": str(rule_set["bw"]),
            "tenant_uuid": rule_set["tenant_uuid"],
            "direction": rule_set["direction"],
            "layer_protocol_name": rule_set["layer_protocol_name"],
            "layer_protocol_qualifier": rule_set["layer_protocol_qualifier"],
            "lower_frequency_mhz": str(rule_set["lower_frequency_mhz"]),
            "upper_frequency_mhz": str(rule_set["upper_frequency_mhz"]),
            "link_uuid_path": rule_set.get("link_uuid_path", []),
            "granularity": rule_set["granularity"],
            "grid_type": rule_set["grid_type"],
            "device_id": "TFS-TAPI"
        }
        
        # Add optional parameters only if they have non-None values
        if rule_set.get("capacity_unit") is not None:
            payload["capacity_unit"] = rule_set["capacity_unit"]
        if rule_set.get("capacity_value") is not None:
            payload["capacity_value"] = str(rule_set["capacity_value"])
        if rule_set.get("route_objective_function") is not None:
            payload["route_objective_function"] = str(rule_set["route_objective_function"])
        if rule_set.get("url"):
            payload["url"] = rule_set["url"]
        
        headers = {
            "Content-Type": "application/json"
        }
        
        logging.info(f"Sending Media Channel POST to {url}")
        logging.info(f"Payload: {json.dumps(payload, indent=2)}")
        
        try:
            response = requests.post(url, json=payload, headers=headers, timeout=30)
            logging.info(f"Media Channel response status: {response.status_code}")
            logging.info(f"Media Channel response: {response.text}")
            return response
        except Exception as e:
            logging.error(f"Failed to send Media Channel request: {str(e)}")
            raise


    def __tfs_l2vpn(self, ietf_intent):
        """
        Translate slice intent into a TeraFlow service request.
+7560 −0

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
        {
            "service_id": {
                "context_id": {"context_uuid": {"uuid": "admin"}},
                "service_uuid": {"uuid": "TAPI LSP"}
                "service_uuid": {"uuid": "IPoWDM"}
            },
            "service_type": 12,
            "service_status": {"service_status": 1},
+25 −24
Original line number Diff line number Diff line
{
   "url": "",
   "data": {
      "tapi-common:context": {
         "name": [
            {
@@ -16,13 +18,12 @@
         "tapi-topology:topology-context": {
            "topology": [
               {
               "link" : [
               ],
               "node" : [
               ]
                  "link": [],
                  "node": []
               }
            ]
         },
         "uuid": ""
      }
   }
}
 No newline at end of file
+68 −30
Original line number Diff line number Diff line
@@ -2,42 +2,80 @@
    "services": [
        {
            "service_id": {
                "context_id": {"context_uuid": {"uuid": "admin"}},
                "service_uuid": {"uuid": "TAPI LSP"}
                "context_id": {
                    "context_uuid": {
                        "uuid": "admin"
                    }
                },
                "service_uuid": {
                    "uuid": "TAPI LSP"
                }
            },
            "service_type": 11,
            "service_status": {"service_status": 1},
            "service_status": {
                "service_status": 1
            },
            "service_endpoint_ids": [
                {"device_id": {"device_uuid": {"uuid": "TFS-OPTICAL"}},"endpoint_uuid": {"uuid": "mgmt"}},
                {"device_id": {"device_uuid": {"uuid": "TFS-PACKET"}},"endpoint_uuid": {"uuid": "mgmt"}}

                {
                    "device_id": {
                        "device_uuid": {
                            "uuid": "TFS-OPTICAL"
                        }
                    },
                    "endpoint_uuid": {
                        "uuid": "mgmt"
                    }
                },
                {
                    "device_id": {
                        "device_uuid": {
                            "uuid": "TFS-PACKET"
                        }
                    },
                    "endpoint_uuid": {
                        "uuid": "mgmt"
                    }
                }
            ],
            "service_constraints": [],

            "service_config": {"config_rules": [
                {"action": 1, "tapi_lsp": {
            "service_config": {
                "config_rules": [
                    {
                        "action": 1,
                        "tapi_lsp": {
                            "endpoint_id": {
                        "device_id": {"device_uuid": {"uuid": "TFS-OPTICAL"}},
                        "endpoint_uuid": {"uuid": "mgmt"}
                                "device_id": {
                                    "device_uuid": {
                                        "uuid": "TFS-OPTICAL"
                                    }
                                },
                                "endpoint_uuid": {
                                    "uuid": "mgmt"
                                }
                            },
                            "rule_set": {
                        "src": "",
                        "dst": "",
                                "input_sip": "",
                                "output_sip": "",
                                "uuid": "",
                                "bw": "",
                                "tenant_uuid": "",
                        "direction": "",
                                "layer_protocol_name": "",
                                "layer_protocol_qualifier": "",
                                "lower_frequency_mhz": "",
                                "upper_frequency_mhz": "",
                        "link_uuid_path": [
                        ],
                                "link_uuid_path": [],
                                "granularity": "",
                        "grid_type": ""
                                "grid_type": "",
                                "direction": "",
                                "capacity_unit": "",
                                "capacity_value": "",
                                "route_objective_function": "",
                                "url": ""
                            }
                        }
                    }
                ]
            }
                }}
            ]}
        }
    ]
}
 No newline at end of file