Loading src/api/main.py +7 −26 Viewed Changes for src/api/main.py: 7 added lines, 26 removed lines. Original line number Diff line number Diff line Loading @@ -14,10 +14,10 @@ # This file is an original contribution from Telefonica Innovación Digital S.L. from src.config.constants import DATABASE_PATH from src.utils.send_response import send_response import os, json, logging import logging from flask import current_app from src.database.db import get_data, delete_data, get_all_data, delete_all_data class Api: def __init__(self, slice_service): Loading Loading @@ -81,8 +81,7 @@ class Api: """ try: # Read slice database from JSON file with open(os.path.join(DATABASE_PATH, "slice_ddbb.json"), 'r') as file: content = json.load(file) content = get_all_data() # If specific slice ID is provided, find and return matching slice if slice_id: for slice in content: Loading Loading @@ -160,24 +159,14 @@ class Api: - If need_l2vpn_support is True, performs additional L2VPN cleanup """ try: # Read current slice database with open(os.path.join(DATABASE_PATH, "slice_ddbb.json"), 'r') as file: content = json.load(file) id = None # Delete specific slice if slice_id is provided if slice_id: for i, slice in enumerate(content): if slice["slice_id"] == slice_id and slice.get("controller") == self.slice_service.controller_type: del content[i] id = i break slice = get_data(slice_id) # Raise error if slice not found if id is None: if not slice or slice.get("controller") != self.slice_service.controller_type: raise ValueError("Transport network slice not found") # Update slice database with open(os.path.join(DATABASE_PATH, "slice_ddbb.json"), 'w') as file: json.dump(content, file, indent=4) delete_data(slice_id) logging.info(f"Slice {slice_id} removed successfully") return {}, 204 Loading @@ -189,16 +178,8 @@ class Api: if current_app.config["TFS_L2VPN_SUPPORT"]: self.slice_service.tfs_l2vpn_delete() data_removed = [slice for slice in content if slice.get("controller") == self.slice_service.controller_type] # Verify slices exist before deletion if len(data_removed) == 0: raise ValueError("Transport network slices not found") filtered_data = [slice for slice in content if slice.get("controller") != self.slice_service.controller_type] # Clear slice database with open(os.path.join(DATABASE_PATH, "slice_ddbb.json"), 'w') as file: json.dump(filtered_data, file, indent=4) delete_all_data() logging.info("All slices removed successfully") return {}, 204 Loading src/database/db.py 0 → 100644 +138 −0 Viewed Changes for src/database/db.py: 138 added lines, 0 removed lines. Original line number Diff line number Diff line # Copyright 2022-2025 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. import sqlite3, json, logging # Database file DB_NAME = "slice.db" # Initialize database and create table def init_db(): conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS slice ( slice_id TEXT PRIMARY KEY, intent TEXT NOT NULL, controller TEXT NOT NULL ) """) conn.commit() conn.close() # Save data to the database def save_data(slice_id: str, intent_dict: dict, controller: str): intent_str = json.dumps(intent_dict) conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() try: cursor.execute("INSERT INTO slice (slice_id, intent, controller) VALUES (?, ?, ?)", (slice_id, intent_str, controller)) conn.commit() except sqlite3.IntegrityError: raise ValueError(f"Slice with id '{slice_id}' already exists.") finally: conn.close() # Update data in the database def update_data(slice_id: str, new_intent_dict: dict, controller: str): intent_str = json.dumps(new_intent_dict) conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("UPDATE slice SET intent = ?, controller = ? WHERE slice_id = ?", (intent_str, controller, slice_id)) if cursor.rowcount == 0: raise ValueError(f"No slice found with id '{slice_id}' to update.") else: logging.debug(f"Slice '{slice_id}' updated.") conn.commit() conn.close() # Delete data from the database def delete_data(slice_id: str): conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("DELETE FROM slice WHERE slice_id = ?", (slice_id,)) if cursor.rowcount == 0: raise ValueError(f"No slice found with id '{slice_id}' to delete.") else: logging.debug(f"Slice '{slice_id}' deleted.") conn.commit() conn.close() # Get data from the database def get_data(slice_id: str) -> dict[str, dict, str]: conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("SELECT * FROM slice WHERE slice_id = ?", (slice_id,)) row = cursor.fetchone() conn.close() if row: column_names = [description[0] for description in cursor.description] result = dict(zip(column_names, row)) if isinstance(result.get("intent"), str): try: result["intent"] = json.loads(result["intent"]) except json.JSONDecodeError: raise Exception("Warning: 'intent' is not a valid JSON string.") return result else: raise ValueError(f"No slice found with id '{slice_id}'.") # Get all slices def get_all_data() -> dict[str, dict, str]: conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("SELECT * FROM slice") rows = cursor.fetchall() conn.close() return [ { "slice_id": row[0], "intent": json.loads(row[1]), "controller": row[2] } for row in rows ] def delete_all_data(): conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("DELETE FROM slice") conn.commit() conn.close() logging.debug("All slice data deleted.") # Example usage if __name__ == "__main__": init_db() # Save a slice test_intent = {"bandwidth": "1Gbps", "latency": "10ms", "provider": "opensec"} save_data("slice-001", test_intent, "TFS") # Get the slice result = get_data("slice-001") if result: print(f"Retrieved intent for slice-001: {result}") # Update the slice updated_intent = {"bandwidth": "2Gbps", "latency": "5ms", "provider": "opensec"} update_data("slice-001", updated_intent, "TFS") # Delete the slice delete_data("slice-001") get_all_data() delete_all_data() src/database/slice_ddbb.jsondeleted 100644 → 0 +0 −1 Viewed Changes for src/database/slice_ddbb.json: 0 added lines, 1 removed line. Original line number Diff line number Diff line [] No newline at end of file src/database/store_data.py +4 −26 Viewed Changes for src/database/store_data.py: 4 added lines, 26 removed lines. Original line number Diff line number Diff line Loading @@ -14,8 +14,7 @@ # This file is an original contribution from Telefonica Innovación Digital S.L. import json, os from src.config.constants import DATABASE_PATH from src.database.db import save_data, update_data def store_data(intent, slice_id, controller_type=None): """ Loading @@ -30,31 +29,10 @@ def store_data(intent, slice_id, controller_type=None): intent (dict): Network slice intent to be stored slice_id (str, optional): Existing slice ID to update. Defaults to None. """ file_path = os.path.join(DATABASE_PATH, "slice_ddbb.json") # Create initial JSON file if it doesn't exist if not os.path.exists(file_path): with open(file_path, 'w') as file: json.dump([], file, indent=4) # Read existing content with open(file_path, 'r') as file: content = json.load(file) # Update or add new slice intent if slice_id: # Update existing slice intent for slice in content: if slice["slice_id"] == slice_id: slice["intent"] = intent update_data(slice_id, intent, controller_type) else: # Add new slice intent content.append( { "slice_id": intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"], "intent": intent, "controller": controller_type, }) # # Write updated content back to file with open(file_path, 'w') as file: json.dump(content, file, indent=4) No newline at end of file slice_id = intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"] save_data(slice_id, intent, controller_type) No newline at end of file src/webui/gui.py +2 −3 Viewed Changes for src/webui/gui.py: 2 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -141,7 +141,6 @@ def __datos_json(): try: with open(os.path.join(SRC_PATH, 'slice_ddbb.json'), 'r') as fichero: datos =json.load(fichero) print(datos) rows =[] for source_ip, source_info in datos["source"].items(): vlan = source_info["vlan"] Loading @@ -165,8 +164,8 @@ def home(): session['enter'] = False # Leer las IPs actuales del archivo de configuración try: tfs_ip = {"TFS_IP": current_app.config["TFS_IP"]} ixia_ip = {"IXIA_IP": current_app.config["IXIA_IP"]} tfs_ip = current_app.config["TFS_IP"] ixia_ip = current_app.config["IXIA_IP"] except Exception: tfs_ip = 'No configurada' ixia_ip = 'No configurada' Loading Loading
src/api/main.py +7 −26 Viewed Changes for src/api/main.py: 7 added lines, 26 removed lines. Original line number Diff line number Diff line Loading @@ -14,10 +14,10 @@ # This file is an original contribution from Telefonica Innovación Digital S.L. from src.config.constants import DATABASE_PATH from src.utils.send_response import send_response import os, json, logging import logging from flask import current_app from src.database.db import get_data, delete_data, get_all_data, delete_all_data class Api: def __init__(self, slice_service): Loading Loading @@ -81,8 +81,7 @@ class Api: """ try: # Read slice database from JSON file with open(os.path.join(DATABASE_PATH, "slice_ddbb.json"), 'r') as file: content = json.load(file) content = get_all_data() # If specific slice ID is provided, find and return matching slice if slice_id: for slice in content: Loading Loading @@ -160,24 +159,14 @@ class Api: - If need_l2vpn_support is True, performs additional L2VPN cleanup """ try: # Read current slice database with open(os.path.join(DATABASE_PATH, "slice_ddbb.json"), 'r') as file: content = json.load(file) id = None # Delete specific slice if slice_id is provided if slice_id: for i, slice in enumerate(content): if slice["slice_id"] == slice_id and slice.get("controller") == self.slice_service.controller_type: del content[i] id = i break slice = get_data(slice_id) # Raise error if slice not found if id is None: if not slice or slice.get("controller") != self.slice_service.controller_type: raise ValueError("Transport network slice not found") # Update slice database with open(os.path.join(DATABASE_PATH, "slice_ddbb.json"), 'w') as file: json.dump(content, file, indent=4) delete_data(slice_id) logging.info(f"Slice {slice_id} removed successfully") return {}, 204 Loading @@ -189,16 +178,8 @@ class Api: if current_app.config["TFS_L2VPN_SUPPORT"]: self.slice_service.tfs_l2vpn_delete() data_removed = [slice for slice in content if slice.get("controller") == self.slice_service.controller_type] # Verify slices exist before deletion if len(data_removed) == 0: raise ValueError("Transport network slices not found") filtered_data = [slice for slice in content if slice.get("controller") != self.slice_service.controller_type] # Clear slice database with open(os.path.join(DATABASE_PATH, "slice_ddbb.json"), 'w') as file: json.dump(filtered_data, file, indent=4) delete_all_data() logging.info("All slices removed successfully") return {}, 204 Loading
src/database/db.py 0 → 100644 +138 −0 Viewed Changes for src/database/db.py: 138 added lines, 0 removed lines. Original line number Diff line number Diff line # Copyright 2022-2025 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. import sqlite3, json, logging # Database file DB_NAME = "slice.db" # Initialize database and create table def init_db(): conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS slice ( slice_id TEXT PRIMARY KEY, intent TEXT NOT NULL, controller TEXT NOT NULL ) """) conn.commit() conn.close() # Save data to the database def save_data(slice_id: str, intent_dict: dict, controller: str): intent_str = json.dumps(intent_dict) conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() try: cursor.execute("INSERT INTO slice (slice_id, intent, controller) VALUES (?, ?, ?)", (slice_id, intent_str, controller)) conn.commit() except sqlite3.IntegrityError: raise ValueError(f"Slice with id '{slice_id}' already exists.") finally: conn.close() # Update data in the database def update_data(slice_id: str, new_intent_dict: dict, controller: str): intent_str = json.dumps(new_intent_dict) conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("UPDATE slice SET intent = ?, controller = ? WHERE slice_id = ?", (intent_str, controller, slice_id)) if cursor.rowcount == 0: raise ValueError(f"No slice found with id '{slice_id}' to update.") else: logging.debug(f"Slice '{slice_id}' updated.") conn.commit() conn.close() # Delete data from the database def delete_data(slice_id: str): conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("DELETE FROM slice WHERE slice_id = ?", (slice_id,)) if cursor.rowcount == 0: raise ValueError(f"No slice found with id '{slice_id}' to delete.") else: logging.debug(f"Slice '{slice_id}' deleted.") conn.commit() conn.close() # Get data from the database def get_data(slice_id: str) -> dict[str, dict, str]: conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("SELECT * FROM slice WHERE slice_id = ?", (slice_id,)) row = cursor.fetchone() conn.close() if row: column_names = [description[0] for description in cursor.description] result = dict(zip(column_names, row)) if isinstance(result.get("intent"), str): try: result["intent"] = json.loads(result["intent"]) except json.JSONDecodeError: raise Exception("Warning: 'intent' is not a valid JSON string.") return result else: raise ValueError(f"No slice found with id '{slice_id}'.") # Get all slices def get_all_data() -> dict[str, dict, str]: conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("SELECT * FROM slice") rows = cursor.fetchall() conn.close() return [ { "slice_id": row[0], "intent": json.loads(row[1]), "controller": row[2] } for row in rows ] def delete_all_data(): conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("DELETE FROM slice") conn.commit() conn.close() logging.debug("All slice data deleted.") # Example usage if __name__ == "__main__": init_db() # Save a slice test_intent = {"bandwidth": "1Gbps", "latency": "10ms", "provider": "opensec"} save_data("slice-001", test_intent, "TFS") # Get the slice result = get_data("slice-001") if result: print(f"Retrieved intent for slice-001: {result}") # Update the slice updated_intent = {"bandwidth": "2Gbps", "latency": "5ms", "provider": "opensec"} update_data("slice-001", updated_intent, "TFS") # Delete the slice delete_data("slice-001") get_all_data() delete_all_data()
src/database/slice_ddbb.jsondeleted 100644 → 0 +0 −1 Viewed Changes for src/database/slice_ddbb.json: 0 added lines, 1 removed line. Original line number Diff line number Diff line [] No newline at end of file
src/database/store_data.py +4 −26 Viewed Changes for src/database/store_data.py: 4 added lines, 26 removed lines. Original line number Diff line number Diff line Loading @@ -14,8 +14,7 @@ # This file is an original contribution from Telefonica Innovación Digital S.L. import json, os from src.config.constants import DATABASE_PATH from src.database.db import save_data, update_data def store_data(intent, slice_id, controller_type=None): """ Loading @@ -30,31 +29,10 @@ def store_data(intent, slice_id, controller_type=None): intent (dict): Network slice intent to be stored slice_id (str, optional): Existing slice ID to update. Defaults to None. """ file_path = os.path.join(DATABASE_PATH, "slice_ddbb.json") # Create initial JSON file if it doesn't exist if not os.path.exists(file_path): with open(file_path, 'w') as file: json.dump([], file, indent=4) # Read existing content with open(file_path, 'r') as file: content = json.load(file) # Update or add new slice intent if slice_id: # Update existing slice intent for slice in content: if slice["slice_id"] == slice_id: slice["intent"] = intent update_data(slice_id, intent, controller_type) else: # Add new slice intent content.append( { "slice_id": intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"], "intent": intent, "controller": controller_type, }) # # Write updated content back to file with open(file_path, 'w') as file: json.dump(content, file, indent=4) No newline at end of file slice_id = intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"] save_data(slice_id, intent, controller_type) No newline at end of file
src/webui/gui.py +2 −3 Viewed Changes for src/webui/gui.py: 2 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -141,7 +141,6 @@ def __datos_json(): try: with open(os.path.join(SRC_PATH, 'slice_ddbb.json'), 'r') as fichero: datos =json.load(fichero) print(datos) rows =[] for source_ip, source_info in datos["source"].items(): vlan = source_info["vlan"] Loading @@ -165,8 +164,8 @@ def home(): session['enter'] = False # Leer las IPs actuales del archivo de configuración try: tfs_ip = {"TFS_IP": current_app.config["TFS_IP"]} ixia_ip = {"IXIA_IP": current_app.config["IXIA_IP"]} tfs_ip = current_app.config["TFS_IP"] ixia_ip = current_app.config["IXIA_IP"] except Exception: tfs_ip = 'No configurada' ixia_ip = 'No configurada' Loading