Commit 0ec675de authored by Javier Velázquez's avatar Javier Velázquez
Browse files

Merge branch 'feat/5-challenge-5-slice-deletion' into 'develop'

Change API and tfs handlers to for slice deletion and modification in TFS

See merge request !13
parents f7da0b68 378cdc12
Loading
Loading
Loading
Loading
+24 −6
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ from src.utils.send_response import send_response
import logging
from flask import current_app
from src.database.db import get_data, delete_data, get_all_data, delete_all_data
from src.realizer.tfs.helpers.tfs_connector import tfs_connector
from src.utils.safe_get import safe_get

class Api:
    def __init__(self, slice_service):
@@ -44,7 +46,7 @@ class Api:
            result = self.slice_service.nsc(intent)
            if not result:
                return send_response(False, code=404, message="No intents found")

            logging.info(f"Slice created successfully")
            return send_response(
                True,
                code=201,
@@ -120,7 +122,7 @@ class Api:
            result = self.slice_service.nsc(intent, slice_id)
            if not result:
                return send_response(False, code=404, message="Slice not found")

            logging.info(f"Slice {slice_id} modified successfully")
            return send_response(
                True,
                code=200,
@@ -165,6 +167,14 @@ class Api:
                # Raise error if slice not found
                if not slice or slice.get("controller") != self.slice_service.controller_type:
                    raise ValueError("Transport network slice not found")
                # Delete in Teraflow
                if not current_app.config["DUMMY_MODE"]:
                    if self.slice_service.controller_type == "TFS":
                        slice_type = safe_get(slice, ['intent', 'ietf-network-slice-service:network-slice-services', 'slice-service', 0, 'service-tags', 'tag-type', 0, 'tag-type-value', 0])
                        if not slice_type:
                            slice_type = "L2"
                            logging.warning(f"Slice type not found in slice intent. Defaulting to L2")
                        tfs_connector().nbi_delete(current_app.config["TFS_IP"],slice_type, slice_id)
                # Update slice database
                delete_data(slice_id)
                logging.info(f"Slice {slice_id} removed successfully")
@@ -173,8 +183,16 @@ class Api:
            # Delete all slices
            else:
                # Optional: Delete in Teraflow if configured
                if not current_app.config["DUMMY_MODE"]:
                    if self.slice_service.controller_type == "TFS":
                    # TODO: should send a delete request to Teraflow
                        content = get_all_data()
                        for slice in content:
                            if slice.get("controller") == self.slice_service.controller_type:
                                slice_type = safe_get(slice, ['intent', 'ietf-network-slice-service:network-slice-services', 'slice-service', 0, 'service-tags', 'tag-type', 0, 'tag-type-value', 0])
                                if not slice_type:
                                    slice_type = "L2"
                                    logging.warning(f"Slice type not found in slice intent. Defaulting to L2")
                                tfs_connector().nbi_delete(current_app.config["TFS_IP"],slice_type, slice.get("slice_id"))
                        if current_app.config["TFS_L2VPN_SUPPORT"]:
                            self.slice_service.tfs_l2vpn_delete()

+18 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
# This file includes original contributions from Telefonica Innovación Digital S.L.

import logging, requests, json
from src.config.constants import NBI_L2_PATH, NBI_L3_PATH

class tfs_connector():   
    def webui_post(self, tfs_ip, service):
@@ -50,5 +51,22 @@ class tfs_connector():
        logging.debug("Posting to TFS NBI: %s",data)
        token={'csrf_token':token}
        response = session.post(url,headers=headers,data=data,timeout=60)
        response.raise_for_status()
        logging.debug("Http response: %s",response.text)
        return response
    
    def nbi_delete(self, tfs_ip: str, service_type: str , service_id: str) -> requests.Response:
        user="admin"
        password="admin"
        url = f'http://{user}:{password}@{tfs_ip}'
        if service_type == 'L2':
            url = url + f'/{NBI_L2_PATH}/vpn-service={service_id}'
        elif service_type == 'L3':
            url = url + f'/{NBI_L3_PATH}/vpn-service={service_id}'
        else:
            raise ValueError("Invalid service type. Use 'L2' or 'L3'.")
        response = requests.delete(url, timeout=60)
        response.raise_for_status()
        logging.debug('Service deleted successfully')
        logging.debug("Http response: %s",response.text)
        return response
 No newline at end of file
+3 −4
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
# This file includes original contributions from Telefonica Innovación Digital S.L.

import logging, os
from datetime import datetime
from src.config.constants import TEMPLATES_PATH, NBI_L2_PATH
from src.utils.load_template import load_template
from ..helpers.cisco_connector import cisco_connector
@@ -53,8 +52,8 @@ def tfs_l2vpn(ietf_intent, response):
        # Load L2VPN service template
        tfs_request = load_template(os.path.join(TEMPLATES_PATH, "L2-VPN_template_empty.json"))["services"][0]

        # Generate unique service UUID
        tfs_request["service_id"]["service_uuid"]["uuid"] += "-" + str(int(datetime.now().timestamp() * 1e7))
        # Configure service UUID
        tfs_request["service_id"]["service_uuid"]["uuid"] = ietf_intent['ietf-network-slice-service:network-slice-services']['slice-service'][0]["id"]

        # Configure service endpoints
        for endpoint in tfs_request["service_endpoint_ids"]:
@@ -62,7 +61,7 @@ def tfs_l2vpn(ietf_intent, response):
            endpoint["endpoint_uuid"]["uuid"] = origin_router_if if endpoint is tfs_request["service_endpoint_ids"][0] else destination_router_if

        # Add service constraints
        for constraint in slice.get("QoS Requirements", []):
        for constraint in slice.get("requirements", []):
            tfs_request["service_constraints"].append({"custom": constraint})

        # Add configuration rules
+4 −5
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
# This file includes original contributions from Telefonica Innovación Digital S.L.

import logging, os
from datetime import datetime
from src.config.constants import TEMPLATES_PATH, NBI_L3_PATH
from src.utils.load_template import load_template
from flask import current_app
@@ -50,8 +49,8 @@ def tfs_l3vpn(ietf_intent, response):
    if current_app.config["UPLOAD_TYPE"] == "WEBUI":
        # Load L3VPN service template
        tfs_request = load_template(os.path.join(TEMPLATES_PATH, "L3-VPN_template_empty.json"))["services"][0]
        # Generate unique service UUID
        tfs_request["service_id"]["service_uuid"]["uuid"] += "-" + str(int(datetime.now().timestamp() * 1e7))
        # Configure service UUID
        tfs_request["service_id"]["service_uuid"]["uuid"] = ietf_intent['ietf-network-slice-service:network-slice-services']['slice-service'][0]["id"]

        # Configure service endpoints
        for endpoint in tfs_request["service_endpoint_ids"]:
@@ -59,7 +58,7 @@ def tfs_l3vpn(ietf_intent, response):
            endpoint["endpoint_uuid"]["uuid"] = origin_router_if if endpoint is tfs_request["service_endpoint_ids"][0] else destination_router_if

        # Add service constraints
        for constraint in slice.get("QoS Requirements", []):
        for constraint in slice.get("requirements", []):
            tfs_request["service_constraints"].append({"custom": constraint})

        # Add configuration rules
@@ -112,7 +111,7 @@ def tfs_l3vpn(ietf_intent, response):
            access["vpn-attachment"]["vpn-id"] = full_id

            # Aplicar restricciones QoS
            for constraint in slice.get("QoS Requirements", []):
            for constraint in slice.get("requirements", []):
                ctype = constraint["constraint_type"]
                cvalue = float(constraint["constraint_value"])
                if constraint["constraint_type"].startswith("one-way-bandwidth"):