Loading src/api/main.py +140 −1 Original line number Diff line number Diff line Loading @@ -78,18 +78,157 @@ class Api: # Extract uuid if exists context = alert_data.get("tapi-notification:notification-context", []) alert_id = None service_id = None subscription_id = None if context and isinstance(context, list): notification = context[0].get("tapi-notification:notification", {}) alert_id = notification.get("uuid") subscription_id = alert_id additional_info = notification.get("additional-info", {}) service_id = additional_info.get("service-id") if not alert_id: return send_response(False, code=400, message="UUID not found in alert data") # Save alert to DB alert_db.save_alert(alert_id, alert_data) # Process intent modification based on alert slice_id = None slice_info = None logging.info(f"Looking up intent for subscription_id: {subscription_id}, service_id: {service_id}") if subscription_id: try: import src.database.db as db mapped_slice_id = db.get_slice_id_by_subscription(subscription_id) if mapped_slice_id: slice_id = mapped_slice_id logging.info(f"Found slice_id {slice_id} mapped to subscription_id {subscription_id}") except Exception as e: logging.info(f"Subscription mapping lookup failed: {e}") if not slice_id and service_id: # 1. Try to find slice_id from service_db try: import src.database.service_db as service_db service_info = service_db.get_data(service_id) slice_id = service_info.get("slice_id") logging.info(f"Found slice_id {slice_id} in service_db for service_id {service_id}") except Exception as e: logging.info(f"service_db lookup failed: {e}") slice_id = service_id if slice_id: # 2. Try to get slice data from db try: import src.database.db as db slice_info = db.get_data(slice_id) logging.info(f"Found slice_info in db by slice_id {slice_id}") except Exception as e: logging.info(f"db lookup by slice_id {slice_id} failed: {e}") # Fallback: if not found by ID, look up any existing slice in the DB if not slice_info: try: import src.database.db as db slices = db.get_all_data() logging.info(f"Slices in db: {[s.get('slice_id') for s in slices]}") for s in slices: if s.get("slice_id") == slice_id: slice_info = s break if not slice_info and slices: # Default to the first/only slice if there's any slice_info = slices[0] logging.info(f"Defaulted to first slice from db: {slice_info.get('slice_id')}") except Exception as e: logging.info(f"db get_all_data lookup failed: {e}") # Fallback: read from /home/llmserver/tfs-nsc/intent.json if DB is empty if not slice_info: import os import json fallback_path = "/home/llmserver/tfs-nsc/intent.json" if os.path.exists(fallback_path): try: with open(fallback_path, "r") as f: intent_data = json.load(f) slice_info = {"slice_id": slice_id or "slice", "intent": intent_data} logging.info("Loaded fallback intent from intent.json") except Exception as e: logging.error(f"Failed to read fallback intent.json: {e}") if slice_info: intent = slice_info.get("intent") curr_slice_id = slice_info.get("slice_id") logging.info(f"Processing intent for slice {curr_slice_id}") if intent: nss = intent.get("ietf-network-slice-service:network-slice-services", {}) slice_services = nss.get("slice-service", []) modified = False for service in slice_services: # Get all SDP IDs in this slice service sdp_list = service.get("sdps", {}).get("sdp", []) sdp_ids = [sdp.get("id") for sdp in sdp_list if sdp.get("id")] connection_groups = service.get("connection-groups", {}).get("connection-group", []) for cg in connection_groups: connectivity_constructs = cg.get("connectivity-construct", []) for cc in connectivity_constructs: p2mp_sender = cc.get("p2mp-sender-sdp") p2mp_receivers = cc.get("p2mp-receiver-sdp", []) logging.info(f"sdp_ids: {sdp_ids}, p2mp_sender: {p2mp_sender}, p2mp_receivers: {p2mp_receivers}") # Find alternative receiver endpoints other_endpoints = [ sdp_id for sdp_id in sdp_ids if sdp_id != p2mp_sender and sdp_id not in p2mp_receivers ] old_receiver = None new_receiver = None if other_endpoints and p2mp_receivers: if len(p2mp_receivers) >= 2: old_receiver = p2mp_receivers[1] new_receiver = other_endpoints[0] cc["p2mp-receiver-sdp"] = [p2mp_receivers[0], new_receiver] else: old_receiver = p2mp_receivers[0] new_receiver = other_endpoints[0] cc["p2mp-receiver-sdp"] = [new_receiver] modified = True # Log ORIGEN and DESTINO logging.info(f"ORIGEN: {p2mp_sender} DESTINO: {new_receiver}") print(f"ORIGEN: {p2mp_sender} DESTINO: {new_receiver}", flush=True) else: logging.warning("No alternative receiver endpoints found to swap.") if p2mp_receivers: old_service_id = f"{p2mp_sender}_to_{','.join(p2mp_receivers)}" else: old_service_id = None if modified: # Re-apply the modified intent via slice_service.nsc try: self.slice_service.nsc(intent, curr_slice_id, old_service_id=old_service_id) logging.info(f"Slice {curr_slice_id} updated successfully following alert.") except Exception as e: logging.error(f"Failed to update slice configuration: {e}") else: logging.warning("No slice intent found to process alert.") return send_response( True, code=201, message="Alert saved successfully", message="Alert processed and saved successfully", data=alert_data ) except Exception as e: Loading src/config/config.py +2 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ def create_config(app: Flask): app.config["PCE_EXTERNAL"] = os.getenv("PCE_EXTERNAL", "false").lower() == "true" app.config["HRAT_IP"] = os.getenv("HRAT_IP", "192.168.1.143") app.config["E2E_OPTICAL_IP"] = os.getenv("E2E_OPTICAL_IP", "127.0.0.1") app.config["SUBSCRIBE_ALERTS"] = os.getenv("SUBSCRIBE_ALERTS", "false").lower() == "true" app.config["SUBSCRIBE_ALERTS_URL"] = os.getenv("SUBSCRIBE_ALERTS_URL", "") # Realizer app.config["DUMMY_MODE"] = os.getenv("DUMMY_MODE", "true").lower() == "true" Loading src/database/db.py +25 −0 Original line number Diff line number Diff line Loading @@ -31,8 +31,33 @@ def init_db(): controller TEXT NOT NULL ) """) cursor.execute(""" CREATE TABLE IF NOT EXISTS subscription ( subscription_id TEXT PRIMARY KEY, slice_id TEXT NOT NULL ) """) conn.commit() conn.close() def save_subscription(subscription_id: str, slice_id: str): conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() try: cursor.execute("INSERT OR REPLACE INTO subscription (subscription_id, slice_id) VALUES (?, ?)", (subscription_id, slice_id)) conn.commit() finally: conn.close() def get_slice_id_by_subscription(subscription_id: str) -> str: conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("SELECT slice_id FROM subscription WHERE subscription_id = ?", (subscription_id,)) row = cursor.fetchone() conn.close() if row: return row[0] return None # Save data to the database def save_data(slice_id: str, intent_dict: dict, controller: str): Loading Loading
src/api/main.py +140 −1 Original line number Diff line number Diff line Loading @@ -78,18 +78,157 @@ class Api: # Extract uuid if exists context = alert_data.get("tapi-notification:notification-context", []) alert_id = None service_id = None subscription_id = None if context and isinstance(context, list): notification = context[0].get("tapi-notification:notification", {}) alert_id = notification.get("uuid") subscription_id = alert_id additional_info = notification.get("additional-info", {}) service_id = additional_info.get("service-id") if not alert_id: return send_response(False, code=400, message="UUID not found in alert data") # Save alert to DB alert_db.save_alert(alert_id, alert_data) # Process intent modification based on alert slice_id = None slice_info = None logging.info(f"Looking up intent for subscription_id: {subscription_id}, service_id: {service_id}") if subscription_id: try: import src.database.db as db mapped_slice_id = db.get_slice_id_by_subscription(subscription_id) if mapped_slice_id: slice_id = mapped_slice_id logging.info(f"Found slice_id {slice_id} mapped to subscription_id {subscription_id}") except Exception as e: logging.info(f"Subscription mapping lookup failed: {e}") if not slice_id and service_id: # 1. Try to find slice_id from service_db try: import src.database.service_db as service_db service_info = service_db.get_data(service_id) slice_id = service_info.get("slice_id") logging.info(f"Found slice_id {slice_id} in service_db for service_id {service_id}") except Exception as e: logging.info(f"service_db lookup failed: {e}") slice_id = service_id if slice_id: # 2. Try to get slice data from db try: import src.database.db as db slice_info = db.get_data(slice_id) logging.info(f"Found slice_info in db by slice_id {slice_id}") except Exception as e: logging.info(f"db lookup by slice_id {slice_id} failed: {e}") # Fallback: if not found by ID, look up any existing slice in the DB if not slice_info: try: import src.database.db as db slices = db.get_all_data() logging.info(f"Slices in db: {[s.get('slice_id') for s in slices]}") for s in slices: if s.get("slice_id") == slice_id: slice_info = s break if not slice_info and slices: # Default to the first/only slice if there's any slice_info = slices[0] logging.info(f"Defaulted to first slice from db: {slice_info.get('slice_id')}") except Exception as e: logging.info(f"db get_all_data lookup failed: {e}") # Fallback: read from /home/llmserver/tfs-nsc/intent.json if DB is empty if not slice_info: import os import json fallback_path = "/home/llmserver/tfs-nsc/intent.json" if os.path.exists(fallback_path): try: with open(fallback_path, "r") as f: intent_data = json.load(f) slice_info = {"slice_id": slice_id or "slice", "intent": intent_data} logging.info("Loaded fallback intent from intent.json") except Exception as e: logging.error(f"Failed to read fallback intent.json: {e}") if slice_info: intent = slice_info.get("intent") curr_slice_id = slice_info.get("slice_id") logging.info(f"Processing intent for slice {curr_slice_id}") if intent: nss = intent.get("ietf-network-slice-service:network-slice-services", {}) slice_services = nss.get("slice-service", []) modified = False for service in slice_services: # Get all SDP IDs in this slice service sdp_list = service.get("sdps", {}).get("sdp", []) sdp_ids = [sdp.get("id") for sdp in sdp_list if sdp.get("id")] connection_groups = service.get("connection-groups", {}).get("connection-group", []) for cg in connection_groups: connectivity_constructs = cg.get("connectivity-construct", []) for cc in connectivity_constructs: p2mp_sender = cc.get("p2mp-sender-sdp") p2mp_receivers = cc.get("p2mp-receiver-sdp", []) logging.info(f"sdp_ids: {sdp_ids}, p2mp_sender: {p2mp_sender}, p2mp_receivers: {p2mp_receivers}") # Find alternative receiver endpoints other_endpoints = [ sdp_id for sdp_id in sdp_ids if sdp_id != p2mp_sender and sdp_id not in p2mp_receivers ] old_receiver = None new_receiver = None if other_endpoints and p2mp_receivers: if len(p2mp_receivers) >= 2: old_receiver = p2mp_receivers[1] new_receiver = other_endpoints[0] cc["p2mp-receiver-sdp"] = [p2mp_receivers[0], new_receiver] else: old_receiver = p2mp_receivers[0] new_receiver = other_endpoints[0] cc["p2mp-receiver-sdp"] = [new_receiver] modified = True # Log ORIGEN and DESTINO logging.info(f"ORIGEN: {p2mp_sender} DESTINO: {new_receiver}") print(f"ORIGEN: {p2mp_sender} DESTINO: {new_receiver}", flush=True) else: logging.warning("No alternative receiver endpoints found to swap.") if p2mp_receivers: old_service_id = f"{p2mp_sender}_to_{','.join(p2mp_receivers)}" else: old_service_id = None if modified: # Re-apply the modified intent via slice_service.nsc try: self.slice_service.nsc(intent, curr_slice_id, old_service_id=old_service_id) logging.info(f"Slice {curr_slice_id} updated successfully following alert.") except Exception as e: logging.error(f"Failed to update slice configuration: {e}") else: logging.warning("No slice intent found to process alert.") return send_response( True, code=201, message="Alert saved successfully", message="Alert processed and saved successfully", data=alert_data ) except Exception as e: Loading
src/config/config.py +2 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ def create_config(app: Flask): app.config["PCE_EXTERNAL"] = os.getenv("PCE_EXTERNAL", "false").lower() == "true" app.config["HRAT_IP"] = os.getenv("HRAT_IP", "192.168.1.143") app.config["E2E_OPTICAL_IP"] = os.getenv("E2E_OPTICAL_IP", "127.0.0.1") app.config["SUBSCRIBE_ALERTS"] = os.getenv("SUBSCRIBE_ALERTS", "false").lower() == "true" app.config["SUBSCRIBE_ALERTS_URL"] = os.getenv("SUBSCRIBE_ALERTS_URL", "") # Realizer app.config["DUMMY_MODE"] = os.getenv("DUMMY_MODE", "true").lower() == "true" Loading
src/database/db.py +25 −0 Original line number Diff line number Diff line Loading @@ -31,8 +31,33 @@ def init_db(): controller TEXT NOT NULL ) """) cursor.execute(""" CREATE TABLE IF NOT EXISTS subscription ( subscription_id TEXT PRIMARY KEY, slice_id TEXT NOT NULL ) """) conn.commit() conn.close() def save_subscription(subscription_id: str, slice_id: str): conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() try: cursor.execute("INSERT OR REPLACE INTO subscription (subscription_id, slice_id) VALUES (?, ?)", (subscription_id, slice_id)) conn.commit() finally: conn.close() def get_slice_id_by_subscription(subscription_id: str) -> str: conn = sqlite3.connect(DB_NAME) cursor = conn.cursor() cursor.execute("SELECT slice_id FROM subscription WHERE subscription_id = ?", (subscription_id,)) row = cursor.fetchone() conn.close() if row: return row[0] return None # Save data to the database def save_data(slice_id: str, intent_dict: dict, controller: str): Loading