Commit e01a219d authored by jvelazquezm's avatar jvelazquezm
Browse files

Modify code to support both webui and nbi TFS uploads

parent 7bce196c
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
import logging, os, json

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

# Default port for NSC deployment
NSC_PORT = 8081
@@ -47,10 +47,11 @@ PCE_EXTERNAL = False

# Controller Flags
# If True, config is not sent to controllers
DUMMY_MODE = True
DUMMY_MODE = False
# Teraflow IP
TFS_IP = ips.get('TFS_IP')
path = "restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services"
UPLOAD_TYPE = "NBI"  # "WEBUI" or "NBI"
NBI_L2_PATH = "restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services"
# Flag to determine if additional L2VPN configuration support is required for deploying L2VPNs with path selection
TFS_L2VPN_SUPPORT = False
# IXIA NEII IP
+28 −6
Original line number Diff line number Diff line
@@ -26,18 +26,40 @@ logging.basicConfig(
#Teraflow
class tfs_connector():
    
    def simple_post(self, tfs_ip, service, path):
    def webui_post(self, tfs_ip, service):
        user="admin"
        password="admin"
        token=""
        session = requests.Session()
        session.auth = (user, password)
        url=f'http://{tfs_ip}/webui'
        response=session.get(url=url)
        for item in response.iter_lines():
            if("csrf_token" in str(item)):
                string=str(item).split('<input id="csrf_token" name="csrf_token" type="hidden" value=')[1]
                token=string.split(">")[0].strip('"')
        logging.debug("csrf token %s",token)

        files = {'descriptors': ("data.json", json.dumps(service).encode("utf-8"), "application/json")}
        token={'csrf_token':token}
        response = session.post(url,files=files,data=token,timeout=60)
        logging.debug("Http response: %s",response.text)
        return response

    def nbi_post(self, tfs_ip, service, path):
        token=""
        user="admin"
        password="admin"
        token=""
        session = requests.Session()
        session.auth = (user, password)
        url = f'http://{tfs_ip}/{path}'
        logging.info(service)
        headers = {'Content-Type': 'application/json'}
        json_data = json.dumps(service)
        json_decoded = json_data
        data = json.dumps(service)
        logging.debug("Posting to TFS NBI: %s",data)
        token={'csrf_token':token}
        response = requests.post(url,headers=headers,data=json_decoded,timeout=60)
        logging.info(response.text)
        response = session.post(url,headers=headers,data=data,timeout=60)
        logging.debug("Http response: %s",response.text)
        return response

#CISCO
+38 −37
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
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, DUMP_TEMPLATES, PLANNER_ENABLED, NRP_ENABLED, path, path_l3
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, UPLOAD_TYPE, NBI_L2_PATH
from src.realizers.ixia.NEII_V4 import NEII_controller
from src.planner.planner import Planner

@@ -42,7 +42,7 @@ class NSController:
    - Slice Realization: Convert intents to specific network configurations (L2VPN, L3VPN)
    """

    def __init__(self, controller_type = "TFS", tfs_ip=TFS_IP, ixia_ip =IXIA_IP, need_l2vpn_support=TFS_L2VPN_SUPPORT, path=path):
    def __init__(self, controller_type = "TFS", tfs_ip=TFS_IP, ixia_ip =IXIA_IP, need_l2vpn_support=TFS_L2VPN_SUPPORT, path=NBI_L2_PATH):
        """
        Initialize the Network Slice Controller.

@@ -62,7 +62,6 @@ class NSController:
        self.controller_type = controller_type
        self.tfs_ip = tfs_ip
        self.path = path
        self.path_l3 = path_l3
        self.answer = {}
        self.cool_answer = {}
        self.start_time = 0
@@ -300,7 +299,10 @@ class NSController:
            # Optional: Upload template to Teraflow
            if not DUMMY_MODE:
                if self.controller_type == "TFS":
                    response = tfs_connector().simple_post(self.tfs_ip, requests, self.path)
                    if UPLOAD_TYPE == "WEBUI":
                        response = tfs_connector().webui_post(self.tfs_ip, requests)
                    elif UPLOAD_TYPE == "NBI":
                        response = tfs_connector().nbi_post(self.tfs_ip, requests, self.path)

                    if not response.ok:
                        return self.__send_response(False, code=response.status_code, message=f"Teraflow upload failed. Response: {response.text}")
@@ -494,7 +496,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,
@@ -825,6 +826,7 @@ class NSController:
            logging.warning(f"Unsupported controller: {controller}. Defaulting to TFS L2VPN realization.")
            realizing_request = self.__tfs_l2vpn(ietf_intent)
        return realizing_request
    
    def __tfs_l2vpn(self, ietf_intent):
        """
        Translate slice intent into a TeraFlow service request.
@@ -847,27 +849,26 @@ class NSController:
        # Hardcoded router endpoints
        # TODO (should be dynamically determined)
        origin_router_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["attachment-circuits"]["attachment-circuit"][0]["sdp-peering"]["peer-sap-id"]
        origin_router_if = 'eth2'
        origin_router_if = '0/0/0-GigabitEthernet0/0/0/0'
        destination_router_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["attachment-circuits"]["attachment-circuit"][0]["sdp-peering"]["peer-sap-id"]
        destination_router_if = '0/0/0-GigabitEthernet0/0/0/0'

        # Extract QoS Profile from intent
        QoSProfile = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["id"]

        vlan_value = 0
       self.__load_template(2, os.path.join(TEMPLATES_PATH, "ietfL2VPN_template.json"))
       tfs_request = json.loads(str(self.__teraflow_template))
       full_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"]
       uuid_only = full_id.split("slice-service-")[-1]
       tfs_request["ietf-l2vpn-svc:vpn-service"][0]["vpn-id"] = uuid_only
       for site in tfs_request["ietf-l2vpn-svc:vpn-service"][0]["site"]:
           if site is tfs_request["ietf-l2vpn-svc:vpn-service"][0]["site"][0]:
               site["site-id"] = origin_router_id
               site["site-location"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["node-id"]
               site["site-network-access"]["interface"]["ip-address"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["sdp-ip-address"]
           else:
               site["site-id"] = destination_router_id
               site["site-location"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["node-id"]
               site["site-network-access"]["interface"]["ip-address"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["sdp-ip-address"]
        
        # Load L2VPN service template
        self.__load_template(2, os.path.join(TEMPLATES_PATH, "L2-VPN_template_empty.json"))
        tfs_request = json.loads(str(self.__teraflow_template))["services"][0]

        # Generate unique service UUID
        tfs_request["service_id"]["service_uuid"]["uuid"] += "-" + str(int(datetime.now().timestamp() * 1e7))

        # Configure service endpoints
        for endpoint in tfs_request["service_endpoint_ids"]:
            endpoint["device_id"]["device_uuid"]["uuid"] = origin_router_id if endpoint is tfs_request["service_endpoint_ids"][0] else destination_router_id
            endpoint["endpoint_uuid"]["uuid"] = origin_router_if if endpoint is tfs_request["service_endpoint_ids"][0] else destination_router_if

        self.answer[self.subnet]["QoS Requirements"] = []
        # Add service constraints
@@ -993,7 +994,7 @@ class NSController:
            dict: A TeraFlow service request for L3VPN configuration.
        """
        # Hardcoded router endpoints
        # TODO (should be dynamically determined)
        # TODO should be dynamically determined
        origin_router_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["attachment-circuits"]["attachment-circuit"][0]["sdp-peering"]["peer-sap-id"]
        origin_router_if = '0/0/0-GigabitEthernet0/0/0/0'
        destination_router_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["attachment-circuits"]["attachment-circuit"][0]["sdp-peering"]["peer-sap-id"]
+31 −35
Original line number Diff line number Diff line
{
    "l2vpn": {
      "vpn-services": {
        "vpn-service": [
  "ietf-l2vpn-svc:vpn-service": [
    {
            "vpn-id": 100,
            "name": "VPN_L2_Example",
            "vpn-type": "point-to-point",
      "vpn-id": "11327140-7361-41b3-aa45-e84a7fb40be9",
      "customer-name": "osm",
      "vpn-svc-type": "vpws",
      "svc-topo": "any-to-any",
      "site": [
        {
                "site-id": 1,
          "site-id": "1.1.1.1",
          "site-role": "hub",
                "site-location": "R4",
          "site-location": "CU-N2",
          "site-network-access": {
            "interface": {
                    "ip-address": "4.4.4.4",
              "ip-address": "10.60.11.3",
              "encapsulation": "ethernet"
            }
          }
        },
        {
                "site-id": 2,
          "site-id": "3.3.3.3",
          "site-role": "spoke",
                "site-location": "R5",
          "site-location": "AMF-N2",
          "site-network-access": {
            "interface": {
                    "ip-address": "5.5.5.5",
              "ip-address": "10.60.60.105",
              "encapsulation": "ethernet"
            }
          }
@@ -33,6 +32,3 @@
    }
  ]
}
    }
  }
  
 No newline at end of file