Commit a5d6de44 authored by Javier Velázquez's avatar Javier Velázquez Committed by Samuel Santos
Browse files

Service_db creation with all functions to access de database

Modify slice creation and deletion to also change the service database
parent c375c711
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@ from swagger.restconf_namespace import restconf_ns
from src.config.constants import NSC_PORT
from src.webui.gui import gui_bp
from src.config.config import create_config
from src.database.db import init_db
from src.database.db import init_db as init_slice
from src.database.service_db import init_db as init_service

# Paths that do not require authentication (Swagger UI and its static assets)
# /nsc       → Swagger UI
@@ -55,7 +56,8 @@ def _check_basic_auth(app):

def create_app():
    """Create Flask application with configured API and namespaces."""
    init_db()
    init_slice()
    init_service()
    app = Flask(__name__)
    app = create_config(app)
    app.logger.setLevel(logging.INFO)
+16 −3
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ 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.database.service_db import delete_by_slice_id, get_data_by_slice_id
from src.realizer.tfs.helpers.tfs_connector import tfs_connector
from src.utils.safe_get import safe_get
from src.database.sysrepo_store import get_data_store, create_data_store, delete_data_store, update_data_store, normalize_libyang_data
@@ -659,7 +660,11 @@ class Api:
                        slice_type = "L2"
                        logging.warning(f"Slice type not found in slice intent. Defaulting to L2")
                    logging.debug(f"Send slice to delete in TFS with slice_type {slice_type}")
                    tfs_connector().nbi_delete(current_app.config["RESTCONF_IP"], slice_type, slice.get("id"))
                    services = get_data_by_slice_id(slice.get("id"))
                    for service in services:
                        id = service.get("service_id")
                        tfs_connector().nbi_delete(current_app.config["RESTCONF_IP"], slice_type, id)
                    delete_by_slice_id(slice.get("id"))
                if current_app.config["TFS_L2VPN_SUPPORT"]:
                    self.slice_service.tfs_l2vpn_delete()
            
@@ -712,7 +717,11 @@ class Api:
                        slice_type = "L2"
                        logging.warning(f"Slice type not found in slice intent. Defaulting to L2")
                    logging.debug(f"Send slice to delete in TFS with slice_type {slice_type}")
                    tfs_connector().nbi_delete(current_app.config["RESTCONF_IP"], slice_type, existing_slice.get("id"))
                    services = get_data_by_slice_id(existing_slice.get("id"))
                    for service in services:
                        id = service.get("service_id")
                        tfs_connector().nbi_delete(current_app.config["RESTCONF_IP"], slice_type, id)
                    delete_by_slice_id(slice.get("id"))
                if current_app.config["TFS_L2VPN_SUPPORT"]:
                    self.slice_service.tfs_l2vpn_delete()                

@@ -732,7 +741,11 @@ class Api:
                            slice_type = "L2"
                            logging.warning(f"Slice type not found in slice intent. Defaulting to L2")
                        logging.debug(f"Send slice to delete in TFS with slice_type {slice_type}")
                        tfs_connector().nbi_delete(current_app.config["RESTCONF_IP"], slice_type, slice.get("id"))
                        services = get_data_by_slice_id(slice.get("id"))
                        for service in services:
                            id = service.get("service_id")
                            tfs_connector().nbi_delete(current_app.config["RESTCONF_IP"], slice_type, id)
                        delete_by_slice_id(slice.get("id"))
                    if current_app.config["TFS_L2VPN_SUPPORT"]:
                        self.slice_service.tfs_l2vpn_delete()
                delete_data_store(xpath)
+1 −1
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ TFS_E2E_IP=127.0.0.1
# -------------------------
# Restconf Controller
# -------------------------
RESTCONF_IP=192.168.27.165
RESTCONF_IP=127.0.0.1
# Options: TFS or IXIA
SDN_CONTROLLER_TYPE=TFS
# Options: FRR, CISCO
+233 −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.

# This file is an original contribution from Telefonica Innovación Digital S.L.

import sqlite3, logging

# Database file
DB_NAME = "service.db"

# Initialize database and create table
def init_db():
    """
    Initialize the SQLite database and create the service table if not exists.
    """
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS service (
            service_id TEXT PRIMARY KEY,
            slice_id TEXT NOT NULL
        )
    """)
    conn.commit()
    conn.close()

# Save data to the database
def save_data(service_id: str, slice_id: str):
    """
    Save a new service entry to the database.

    Args:
        service_id (str): Unique identifier for the service
        slice_id (dict): Unique identifier for the slice
    
    Raises:
        ValueError: If a service with the given service_id already exists
    """
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    try:
        cursor.execute("INSERT INTO service (service_id, slice_id) VALUES (?, ?)", (service_id, slice_id))
        conn.commit()
    # Handle duplicate service ID
    except sqlite3.IntegrityError:
        raise ValueError(f"Service with id '{service_id}' already exists.")
    finally:
        conn.close()

# Update data in the database
def update_data(service_id: str, new_slice_id: str):
    """
    Update an existing service entry in the database.

    Args:
        service_id (str): Unique identifier for the service
        slice_id (str): Unique identifier for the slice
    
    Raises:
        ValueError: If no service is found with the given service_id
    """
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    cursor.execute("UPDATE service SET slice_id = ? WHERE service_id = ?", (new_slice_id, service_id))
    if cursor.rowcount == 0:
        raise ValueError(f"No slice found with id '{service_id}' to update.")
    else:
        logging.debug(f"Slice '{service_id}' updated.")
    conn.commit()
    conn.close()

# Delete data from the database
def delete_data(service_id: str):
    """
    Delete a service entry from the database.

    Args:
        service_id (str): Unique identifier for the service to delete
    
    Raises:
        ValueError: If no service is found with the given service_id
    """
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    cursor.execute("DELETE FROM service WHERE service_id = ?", (service_id,))
    if cursor.rowcount == 0:
        raise ValueError(f"No service found with id '{service_id}' to delete.")
    else:
        logging.debug(f"Service '{service_id}' deleted.")
    conn.commit()
    conn.close()

# Get data from the database
def get_data(service_id: str) -> dict[str, str]:
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    
    cursor.execute("SELECT * FROM service WHERE service_id = ?", (service_id,))
    row = cursor.fetchone()
    
    if not row:
        conn.close()
        raise ValueError(f"No service found with id '{service_id}'.")
    
    column_names = [desc[0] for desc in cursor.description]
    conn.close()
    
    return dict(zip(column_names, row))


# Get all services
def get_all_data() -> list[dict[str, str]]:
    """
    Retrieve all service entries from the database.

    Returns:
        list: List of service data dictionaries including service_id and slice_id
    """
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM service")
    
    rows = cursor.fetchall()
    column_names = [description[0] for description in cursor.description]
    
    conn.close()

    return [dict(zip(column_names, row)) for row in rows]


def delete_all_data():
    """
    Delete all service entries from the database.
    """
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    cursor.execute("DELETE FROM service")
    conn.commit()
    conn.close()
    logging.debug("All service data deleted.")


def get_data_by_slice_id(slice_id: str) -> list[dict[str, str]]:
    """
    Retrieve all service entries associated with a given slice_id.

    Args:
        slice_id (str): Identifier of the slice
    
    Returns:
        list: List of service data dictionaries including service_id and slice_id
    
    Raises:
        ValueError: If no services are found with the given slice_id
    """
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    
    cursor.execute("SELECT * FROM service WHERE slice_id = ?", (slice_id,))
    rows = cursor.fetchall()
    
    if not rows:
        conn.close()
        raise ValueError(f"No services found with slice_id '{slice_id}'.")
    
    column_names = [desc[0] for desc in cursor.description]
    conn.close()
    
    return [dict(zip(column_names, row)) for row in rows]

def delete_by_slice_id(slice_id: str):
    """
    Delete all service entries associated with a given slice_id.

    Args:
        slice_id (str): Identifier of the slice whose services will be deleted
    
    Raises:
        ValueError: If no services are found with the given slice_id
    """
    conn = sqlite3.connect(DB_NAME)
    cursor = conn.cursor()
    
    cursor.execute("DELETE FROM service WHERE slice_id = ?", (slice_id,))
    
    if cursor.rowcount == 0:
        conn.close()
        raise ValueError(f"No services found with slice_id '{slice_id}' to delete.")
    
    logging.debug(f"All services with slice_id '{slice_id}' deleted.")
    
    conn.commit()
    conn.close()


# Example usage
if __name__ == "__main__":
    init_db()

    # Save a service
    save_data("service-001", "slice-001")
    save_data("service-002", "slice-001")
    save_data("service-003", "slice-002")

    # Get the service
    result = get_data("service-001")
    if result:
        print(f"Retrieved service for service-001: {result}")

    # Update the service
    update_data("service-001", "slice-002")

    # Delete the service
    delete_data("service-001")

    delete_by_slice_id("slice-001")


    result = get_all_data()
    if result:
        print(f"Retrieved data: {result}")
    delete_all_data()
+4 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ from .process_connnectivity import process_connectivity
from src.realizer.main import realizer
from flask import current_app
from src.database.sysrepo_store import get_data_store, create_data_store, delete_data_store, update_data_store, normalize_libyang_data
from src.database.service_db import save_data, update_data

def mapper(ietf_intent, controller_type="TFS"):
    """
@@ -158,6 +159,9 @@ def mapper(ietf_intent, controller_type="TFS"):
                            "way": way
                        }
                        services.append(service)
                        if not current_app.config["DUMMY_MODE"]:
                            # Save mapping from service_id to slice_id
                            save_data(service_id=safe_get(service, ["id"]), slice_id=service_id)
                        logging.debug(f"Service added: {service}")
                        
                        # Break only for point-to-point