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

-Add energy planner

-Add new flags to activate planner and NRPs
-Update copyright header
-Add new flags to dump templates for debugging
parent 0f829776
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
import logging, os, json

# Default logging level
DEFAULT_LOGGING_LEVEL = logging.INFO
DEFAULT_LOGGING_LEVEL = logging.DEBUG

# Default port for NSC deployment
NSC_PORT = 8081
@@ -31,6 +31,20 @@ with open(os.path.join(SRC_PATH, 'IPs.json')) as f:
# Create the path to the desired file relative to the current file
TEMPLATES_PATH = os.path.join(SRC_PATH, "templates")

# Dump templates
DUMP_TEMPLATES = True

# Mapper 

# Flag to determine if the NSC performs NRPs
NRP_ENABLED = False
# Planner Flags
PLANNER_ENABLED = True
# Flag to determine if external PCE is used
PCE_EXTERNAL = False

# Realizer 

# Controller Flags
# If True, config is not sent to controllers
DUMMY_MODE = True
@@ -42,5 +56,6 @@ TFS_L2VPN_SUPPORT = False
IXIA_IP = ips.get('IXIA_IP')

# WebUI

# Flag to deploy the WebUI
WEBUI_DEPLOY = True
 No newline at end of file
+53 −140
Original line number Diff line number Diff line
@@ -17,8 +17,9 @@
import json, time, os, logging, uuid, traceback, sys
from datetime import datetime
from src.helpers import tfs_connector, cisco_connector
from src.Constants import DEFAULT_LOGGING_LEVEL, TFS_IP, TFS_L2VPN_SUPPORT, IXIA_IP, SRC_PATH, TEMPLATES_PATH, DUMMY_MODE
from src.Constants import DEFAULT_LOGGING_LEVEL, TFS_IP, TFS_L2VPN_SUPPORT, IXIA_IP, SRC_PATH, TEMPLATES_PATH, DUMMY_MODE, DUMP_TEMPLATES, PLANNER_ENABLED, NRP_ENABLED
from src.realizers.ixia.NEII_V4 import NEII_controller
from src.planner.planner import Planner

# Configure logging to provide clear and informative log messages
logging.basicConfig(
@@ -263,9 +264,19 @@ class NSController:
            self.__load_template(1, os.path.join(TEMPLATES_PATH, "ietf_template_empty.json"))  
            requests = {"services":[]}

            # Store the received template for debugging
            if DUMP_TEMPLATES:
                with open(os.path.join(TEMPLATES_PATH, "nbi_template.json"), "w") as file:
                    file.write(json.dumps(intent_json,indent=2))
            
            # Process intent (translate if 3GPP)
            ietf_intents = self.__nbi_processor(intent_json)

            # Store the generated template for debugging
            if DUMP_TEMPLATES:
                with open(os.path.join(TEMPLATES_PATH, "ietf_template.json"), "w") as file:
                    file.write(json.dumps(ietf_intents,indent=2))

            if ietf_intents:
                for intent in ietf_intents:
                     # Extract and store slice request details
@@ -279,8 +290,10 @@ class NSController:
            else:
                return self.__send_response(False, code=404, message="No intents found")
            
            # Generated service
            logging.debug(json.dumps(requests, indent=2))
            # Store the generated template for debugging
            if DUMP_TEMPLATES:
                with open(os.path.join(TEMPLATES_PATH, "realizer_template.json"), "w") as archivo:
                    archivo.write(json.dumps(requests,indent=2))
            
            # Optional: Upload template to Teraflow
            if not DUMMY_MODE:
@@ -330,7 +343,6 @@ class NSController:
        # Detect the input JSON format (3GPP or IETF)
        format = self.__detect_format(intent_json)
        ietf_intents = []
        logging.debug("--------NEW REQUEST--------")

        # TODO Needs to be generalized to support different names of slicesubnets
        # Process different input formats
@@ -343,8 +355,6 @@ class NSController:
            # If already in IETF format, add directly
            logging.info(f"IETF intent received")
            ietf_intents.append(intent_json)
            with open(os.path.join(TEMPLATES_PATH, "ietf_template_example.json"), "w") as archivo:
                archivo.write(json.dumps(ietf_intents,indent=2))
        else:
            # Handle unrecognized format
            logging.error(f"JSON request format not recognized")
@@ -369,6 +379,7 @@ class NSController:
        Raises:
            Exception: If no suitable NRP is found and slice creation fails.
        """ 
        if NRP_ENABLED:
            # Retrieve NRP view
            self.__realizer(None, True, "READ")

@@ -400,6 +411,11 @@ class NSController:
                        raise Exception("Slice rejected due to lack of NRPs") 
                    # TODO Here we should put how the slice is attached to the new nrp
        
        if PLANNER_ENABLED:
            optimal_path = Planner().planner(ietf_intent)

            logging.info(f"Optimal path: {optimal_path}")

    def __realizer(self, ietf_intent, need_nrp=False, order=None, nrp=None):
        """
        Manage the slice creation workflow.
@@ -476,7 +492,6 @@ class NSController:
                "setup_time": self.setup_time
            }
            # Add slice details to the response
            logging.info(self.answer)
            for subnet in self.answer:
                slice_info = {
                    "id": subnet,
@@ -672,10 +687,6 @@ class NSController:
        ietf_i["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["service-match-criteria"]["match-criterion"][0]["target-connection-group-id"] = f"{ep_transport_objects[0].split(' ', 1)[1]}_{ep_transport_objects[1].split(' ', 1)[1]}"
        ietf_i["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["service-match-criteria"]["match-criterion"][0]["target-connection-group-id"] = f"{ep_transport_objects[0].split(' ', 1)[1]}_{ep_transport_objects[1].split(' ', 1)[1]}"

        # Log translated intent for debugging
        logging.debug(json.dumps(ietf_i,indent=2))
        with open(os.path.join(TEMPLATES_PATH, "ietf_template_example.json"), "w") as archivo:
            archivo.write(json.dumps(ietf_i,indent=2))
        return ietf_i
    
    ### Mapper functionalities
@@ -723,102 +734,6 @@ class NSController:
            score = sum(flexibility_scores) / len(flexibility_scores) if flexibility_scores else 0
        return True, score  # Si pasó todas las verificaciones, la NRP es viable
    
    def __planner(self, intent, nrp_view):
        """
        TODO
        Request slice viability from the Planner module.

        This method prepares and sends a viability request for network slice creation, 
        detaching the implementation from the main core thread.

        Args:
            intent (dict): Network slice intent
            nrp_view (list): Current Network Resource Pool view

        Returns:
            tuple: A tuple containing:
                - Viability status (str): "Good" or other status
                - Reason (str): Explanation of viability
        
        Notes:
            - Calculates source and destination service delivery points (SDP)
            - Extracts QoS requirements
            - Performs viability check through internal methods
        """
        
        #Version 1
        matriz = {}
        matriz["payloads"] = []
        #for i in intent:
        # SI ya existe, suma, si no existe, lo crea
        origen = self.__calculate_sdp(intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["sdp-ip-address"])
        destino = self.__calculate_sdp(intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["sdp-ip-address"])
        #qos_req = i["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["slo-sle-policy"]["slo-sle-template"]
        qos_req = intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][0]["bound"]
        payload = {
            "Source": origen,
            "Destination": destino,
            "QoS requirements": qos_req
        }
        matriz["payloads"].append(payload)
        m_res = []
        m_qos = []
        for p in matriz["payloads"]:
            res = p
            m_res.append(res)
            m_qos.append(p["QoS requirements"])
        m_res, m_qos = self.__viability(m_res,intent, m_qos)
        reason="Viable"
        viability = "Good"
        return viability, reason

    def __viability(self, matrix, intent, qos):
        """
        TODO
        """
        aux = {}
        aux["good"] = []
        aux["bad"] = []
        l_qos = []
        for i in range(len(intent)):
            # if matrix[i]['success'] == True:
            aux["good"].append(matrix[i])
            l_qos.append(qos[i])
            # else:
            # aux["bad"].append(intent[i])
        return aux, l_qos

    def __calculate_sdp(self, pip):
        '''
        TODO
        Imput:
        Output:
        Work: Identifies the network entpoint from the IP-sdp received. 
            Version 0 will be done directly with next hop.
            Version 1 will translate directly from the public IP of each node to their Loopback address.
        '''
        nid = 0
        with open(os.path.join(TEMPLATES_PATH, "ips.json"), 'r') as source:
            jason = source.read()
            jason = jason.replace('\t', '').replace('\n', '').replace("'", '"').strip()
            nodos = json.loads(str(jason))
            #template = json.loads(str(jason))
            # Once we have the template, we search for the one charged.
            for nodo in nodos["public-prefixes"]:
                if pip == nodo["prefix"]:
                    #nid = nodo["node-id"]
                    nid = nodo["node-name"]
            for nodo in nodos["CU"]:
                if pip == nodo["prefix"]:
                    #nid = nodo["node-id"]
                    nid = nodo["node-name"]
            for nodo in nodos["DU"]:
                if pip == nodo["prefix"]:
                    #nid = nodo["node-id"]
                    nid = nodo["node-name"]
        return nid


    ### Realizer functionalities.
    def __nrp(self, request, nrp):
        """
@@ -1126,8 +1041,6 @@ class NSController:
        
        logging.info(f"L3VPN Intent realized\n")
        self.answer[self.subnet]["VLAN"] = vlan_value
        with open(os.path.join(TEMPLATES_PATH, "L3-VPN_template_example.json"), "w") as archivo:
            archivo.write(json.dumps(tfs_request,indent=2))
        return tfs_request

    def __ixia(self, ietf_intent):
+156 −0
Original line number Diff line number Diff line
[
    {
        "name": "A",
        "typical-power": 3500,
        "maximum-traffic": 100.0,
        "max-power": 150.0,
        "efficiency": 0.9,
        "nominal-power": 130.0,
        "carbon-emissions": 130.0,
        "renewable-energy-usage": 0.7,
        "power-supply": [
            {"name": "PSU-1", "type": "AC", "capacity": 200.0, "typical-power": 100.0, "nominal-power": 110.0}
        ],
        "boards": [
            {"name": "Board-1", "type": "Linecard", "capacity": 40.0, "typical-power": 20.0, "nominal-power": 25.0}
        ],
        "components": [
            {"name": "CPU", "type": "Control", "capacity": 10.0, "typical-power": 5.0, "nominal-power": 6.0}
        ],
        "transceivers": [
            {"name": "XFP1", "type": "10G", "capacity": 10.0, "typical-power": 2.0, "nominal-power": 2.5}
        ]
    },
    {
        "name": "B",
        "typical-power": 6000,
        "maximum-traffic": 120.0,
        "max-power": 180.0,
        "efficiency": 1,
        "nominal-power": 160.0,
        "carbon-emissions": 180.0,
        "renewable-energy-usage": 0.6,
        "power-supply": [
            {"name": "PSU-1", "type": "DC", "capacity": 250.0, "typical-power": 120.0, "nominal-power": 130.0}
        ],
        "boards": [
            {"name": "Board-2", "type": "Switching", "capacity": 60.0, "typical-power": 30.0, "nominal-power": 35.0}
        ],
        "components": [
            {"name": "ASIC", "type": "Forwarding", "capacity": 15.0, "typical-power": 7.0, "nominal-power": 8.0}
        ],
        "transceivers": [
            {"name": "SFP1", "type": "1G", "capacity": 1.0, "typical-power": 1.0, "nominal-power": 1.2}
        ]
    },
    {
        "name": "C",
        "typical-power": 3200,
        "maximum-traffic": 150.0,
        "max-power": 250.0,
        "efficiency": 1.2,
        "nominal-power": 210.0,
        "carbon-emissions": 160.0,
        "renewable-energy-usage": 0.5,
        "power-supply": [
            {"name": "PSU-2", "type": "AC", "capacity": 300.0, "typical-power": 150.0, "nominal-power": 160.0}
        ],
        "boards": [
            {"name": "Board-3", "type": "Routing", "capacity": 80.0, "typical-power": 40.0, "nominal-power": 45.0}
        ],
        "components": [
            {"name": "FPGA", "type": "Processing", "capacity": 20.0, "typical-power": 10.0, "nominal-power": 12.0}
        ],
        "transceivers": [
            {"name": "QSFP1", "type": "40G", "capacity": 40.0, "typical-power": 4.0, "nominal-power": 5.0}
        ]
    },
    {
        "name": "D",
        "typical-power": 6000,
        "maximum-traffic": 200.0,
        "max-power": 300.0,
        "efficiency": 0.9,
        "nominal-power": 260.0,
        "carbon-emissions": 100.0,
        "renewable-energy-usage": 0.5,
        "power-supply": [
            {"name": "PSU-3", "type": "DC", "capacity": 350.0, "typical-power": 180.0, "nominal-power": 190.0}
        ],
        "boards": [
            {"name": "Board-4", "type": "Access", "capacity": 100.0, "typical-power": 50.0, "nominal-power": 55.0}
        ],
        "components": [
            {"name": "GPU", "type": "Accelerator", "capacity": 25.0, "typical-power": 12.0, "nominal-power": 14.0}
        ],
        "transceivers": [
            {"name": "CFP1", "type": "100G", "capacity": 100.0, "typical-power": 8.0, "nominal-power": 10.0}
        ]
    },
    {
        "name": "E",
        "typical-power": 4500,
        "maximum-traffic": 250.0,
        "max-power": 350.0,
        "efficiency": 1.4,
        "nominal-power": 310.0,
        "carbon-emissions": 180,
        "renewable-energy-usage": 0.6,
        "power-supply": [
            {"name": "PSU-4", "type": "AC", "capacity": 400.0, "typical-power": 200.0, "nominal-power": 210.0}
        ],
        "boards": [
            {"name": "Board-5", "type": "Core", "capacity": 120.0, "typical-power": 60.0, "nominal-power": 65.0}
        ],
        "components": [
            {"name": "TPU", "type": "Neural Processing", "capacity": 30.0, "typical-power": 15.0, "nominal-power": 18.0}
        ],
        "transceivers": [
            {"name": "OSFP1", "type": "400G", "capacity": 400.0, "typical-power": 12.0, "nominal-power": 15.0}
        ]
    },
    {
        "name": "F",
        "typical-power": 3000,
        "maximum-traffic": 300.0,
        "max-power": 400.0,
        "efficiency": 1.3,
        "nominal-power": 360.0,
        "carbon-emissions": 140,
        "renewable-energy-usage": 0.6,
        "power-supply": [
            {"name": "PSU-5", "type": "DC", "capacity": 450.0, "typical-power": 220.0, "nominal-power": 230.0}
        ],
        "boards": [
            {"name": "Board-6", "type": "Edge", "capacity": 150.0, "typical-power": 75.0, "nominal-power": 80.0}
        ],
        "components": [
            {"name": "ASIC2", "type": "Edge Processing", "capacity": 40.0, "typical-power": 20.0, "nominal-power": 22.0}
        ],
        "transceivers": [
            {"name": "QSFP-DD1", "type": "800G", "capacity": 800.0, "typical-power": 16.0, "nominal-power": 20.0}
        ]
    },
    {
        "name": "G",
        "typical-power": 3100,
        "maximum-traffic": 350.0,
        "max-power": 450.0,
        "efficiency": 1.1,
        "nominal-power": 410.0,
        "carbon-emissions": 105.0,
        "renewable-energy-usage": 0.6,
        "power-supply": [
            {"name": "PSU-6", "type": "AC", "capacity": 500.0, "typical-power": 250.0, "nominal-power": 260.0}
        ],
        "boards": [
            {"name": "Board-7", "type": "Virtualization", "capacity": 180.0, "typical-power": 90.0, "nominal-power": 95.0}
        ],
        "components": [
            {"name": "FPGA2", "type": "Reconfigurable Processing", "capacity": 50.0, "typical-power": 25.0, "nominal-power": 28.0}
        ],
        "transceivers": [
            {"name": "CFP2", "type": "1.6T", "capacity": 1600.0, "typical-power": 20.0, "nominal-power": 25.0}
        ]
    }
]
 No newline at end of file
+195 −0
Original line number Diff line number Diff line
{
"nodes": [
  {
    "nodeId": 1,
    "name": "A",
    "type": "SITE",
    "footprint": { "cpu": 2, "memory": 1024, "disk": 5000 },
    "vulnerability": 1
  },
  {
    "nodeId": 2,
    "name": "B",
    "type": "SITE",
    "footprint": { "cpu": 1, "memory": 512, "disk": 3000 },
    "vulnerability": 2
  },
  {
    "nodeId": 3,
    "name": "C",
    "type": "SITE",
    "footprint": { "cpu": 2, "memory": 2048, "disk": 6000 },
    "vulnerability": 3
  },
  {
    "nodeId": 4,
    "name": "D",
    "type": "SITE",
    "footprint": { "cpu": 1, "memory": 1024, "disk": 4000 },
    "vulnerability": 1
  },
  {
    "nodeId": 5,
    "name": "E",
    "type": "SITE",
    "footprint": { "cpu": 2, "memory": 1024, "disk": 5000 },
    "vulnerability": 2
  },
  {
    "nodeId": 6,
    "name": "F",
    "type": "SITE",
    "footprint": { "cpu": 1, "memory": 512, "disk": 3000 },
    "vulnerability": 2
  },
  {
    "nodeId": 7,
    "name": "G",
    "type": "SITE",
    "footprint": { "cpu": 2, "memory": 1024, "disk": 7000 },
    "vulnerability": 3
  }
],
"links":[
  {
    "linkId": "A-E",
    "sourceNodeId": "1",
    "destNodeId": "5",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 5 }]
  },
  {
    "linkId": "E-A",
    "sourceNodeId": "5",
    "destNodeId": "1",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 5 }]
  },
  {
    "linkId": "A-D",
    "sourceNodeId": "1",
    "destNodeId": "4",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 4 }]
  },
  {
    "linkId": "D-A",
    "sourceNodeId": "4",
    "destNodeId": "1",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 4 }]
  },
  {
    "linkId": "A-C",
    "sourceNodeId": "1",
    "destNodeId": "3",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 3 }]
  },
  {
    "linkId": "C-A",
    "sourceNodeId": "3",
    "destNodeId": "1",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 3 }]
  },
  {
    "linkId": "B-C",
    "sourceNodeId": "2",
    "destNodeId": "3",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 6 }]
  },
  {
    "linkId": "C-B",
    "sourceNodeId": "3",
    "destNodeId": "2",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 6 }]
  },
  {
    "linkId": "B-D",
    "sourceNodeId": "2",
    "destNodeId": "4",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 7 }]
  },
  {
    "linkId": "D-B",
    "sourceNodeId": "4",
    "destNodeId": "2",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 7 }]
  },
  {
    "linkId": "B-F",
    "sourceNodeId": "2",
    "destNodeId": "6",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 5 }]
  },
  {
    "linkId": "F-B",
    "sourceNodeId": "6",
    "destNodeId": "2",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 5 }]
  },
  {
    "linkId": "D-E",
    "sourceNodeId": "4",
    "destNodeId": "5",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 2 }]
  },
  {
    "linkId": "E-D",
    "sourceNodeId": "5",
    "destNodeId": "4",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 2 }]
  },
  {
    "linkId": "D-F",
    "sourceNodeId": "4",
    "destNodeId": "6",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 6 }]
  },
  {
    "linkId": "F-D",
    "sourceNodeId": "6",
    "destNodeId": "4",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 6 }]
  },
  {
    "linkId": "E-G",
    "sourceNodeId": "5",
    "destNodeId": "7",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 3 }]
  },
  {
    "linkId": "G-E",
    "sourceNodeId": "7",
    "destNodeId": "5",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 3 }]
  },
  {
    "linkId": "F-G",
    "sourceNodeId": "6",
    "destNodeId": "7",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 4 }]
  },
  {
    "linkId": "G-F",
    "sourceNodeId": "7",
    "destNodeId": "6",
    "bandwidth": 1000000000,
    "metrics": [{ "metric": "DELAY", "value": 4 }]
  }
]
}
 No newline at end of file
Loading