Skip to content
Snippets Groups Projects
network_slice_controller.py 59.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • Javier Velázquez's avatar
    Javier Velázquez committed
            cisco_destiny.execute_commands(commands)
    
        def __tfs_l2vpn_delete(self):
            """
            Delete L2VPN configurations from Cisco devices.
    
            This method removes L2VPN configurations from Cisco routers
    
            Notes:
                - Uses cisco_connector to generate and execute deletion commands
                - Clears Network Interface (NI) settings
            """
            # Delete Source Endpoint Configuration
            source_address = "10.60.125.44"
            cisco_source = cisco_connector(source_address)
            cisco_source.execute_commands(cisco_source.create_command_template_delete())
    
            # Delete Destination Endpoint Configuration
            destination_address = "10.60.125.45"
            cisco_destiny = cisco_connector(destination_address)
            cisco_destiny.execute_commands(cisco_destiny.create_command_template_delete())
        
        def __tfs_l3vpn(self, ietf_intent):
            """
            Translate L3VPN (Layer 3 Virtual Private Network) intent into a TeraFlow service request.
    
            Similar to __tfs_l2vpn, but configured for Layer 3 VPN:
            1. Defines endpoint routers
            2. Loads service template
            3. Generates unique service UUID
            4. Configures service endpoints
            5. Adds QoS constraints
            6. Prepares configuration rules for network interfaces
    
            Args:
                ietf_intent (dict): IETF-formatted network slice intent.
    
            Returns:
                dict: A TeraFlow service request for L3VPN configuration.
            """
            # 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"]
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            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"]
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            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
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            self.answer[self.subnet]["QoS Requirements"] = []
    
    
            # Populate response with QoS requirements and VLAN from intent
            slo_policy = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]
    
            # Process metrics
            for metric in slo_policy.get("metric-bound", []):
                constraint_type = f"{metric['metric-type']}[{metric['metric-unit']}]"
                constraint_value = str(metric["bound"])
                self.answer[self.subnet]["QoS Requirements"].append({
                    "constraint_type": constraint_type,
                    "constraint_value": constraint_value
                })
    
            # Availability
            if "availability" in slo_policy:
                self.answer[self.subnet]["QoS Requirements"].append({
                    "constraint_type": "availability[%]",
                    "constraint_value": str(slo_policy["availability"])
                })
    
            # MTU
            if "mtu" in slo_policy:
                self.answer[self.subnet]["QoS Requirements"].append({
                    "constraint_type": "mtu[bytes]",
                    "constraint_value": str(slo_policy["mtu"])
                })
    
            # VLAN
            vlan_value = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["service-match-criteria"]["match-criterion"][0]["value"]
            self.answer[self.subnet]["VLAN"] = vlan_value
    
            if UPLOAD_TYPE == "WEBUI":
                # Load L3VPN service template
                self.__load_template(2, os.path.join(TEMPLATES_PATH, "L3-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
    
                # Add service constraints
                for constraint in self.answer[self.subnet]["QoS Requirements"]:
                    tfs_request["service_constraints"].append({"custom": constraint})
    
                # Add configuration rules
                for i, config_rule in enumerate(tfs_request["service_config"]["config_rules"][1:], start=1):
                    router_id = origin_router_id if i == 1 else destination_router_id
                    router_if = origin_router_if if i == 1 else destination_router_if
                    resource_value = config_rule["custom"]["resource_value"]
    
                    sdp_index = i - 1
                    vlan_value = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][sdp_index]["service-match-criteria"]["match-criterion"][0]["value"]
                    resource_value["router_id"] = destination_router_id if i == 1 else origin_router_id
                    resource_value["vlan_id"] = int(vlan_value)
                    resource_value["address_ip"] = destination_router_id if i == 1 else origin_router_id
                    resource_value["policy_AZ"] = "policyA"
                    resource_value["policy_ZA"] = "policyB"
                    resource_value["ni_name"] = 'ELAN{:s}'.format(str(vlan_value))
                    config_rule["custom"]["resource_key"] = f"/device[{router_id}]/endpoint[{router_if}]/settings"
            
            elif UPLOAD_TYPE == "NBI":
                self.path = NBI_L3_PATH
                # Load IETF L3VPN service template
                self.__load_template(2, os.path.join(TEMPLATES_PATH, "ietfL3VPN_template_empty.json"))
                tfs_request = json.loads(str(self.__teraflow_template))
    
                # Generate service UUID
                full_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"]
                tfs_request["ietf-l3vpn-svc:l3vpn-svc"]["vpn-services"]["vpn-service"][0]["vpn-id"] = full_id
                # Configure service endpoints
                for i, site in enumerate(tfs_request["ietf-l3vpn-svc:l3vpn-svc"]["sites"]["site"]):
    
                    # Determine if origin or destination
                    is_origin = (i == 0)
                    sdp_index = 0 if is_origin else 1
                    location = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][sdp_index]["node-id"]
                    router_id = origin_router_id if is_origin else destination_router_id
                    router_if = origin_router_if if is_origin else destination_router_if
    
                    # Assign common values
                    site["site-id"] = f"site_{location}"
                    site["locations"]["location"][0]["location-id"] = location
                    site["devices"]["device"][0]["device-id"] = router_id
                    site["devices"]["device"][0]["location"] = location
    
                    access = site["site-network-accesses"]["site-network-access"][0]
                    access["site-network-access-id"] = router_if
                    access["device-reference"] = router_id
                    access["vpn-attachment"]["vpn-id"] = full_id
    
                    # Aplicar restricciones QoS
                    for constraint in self.answer[self.subnet]["QoS Requirements"]:
                        ctype = constraint["constraint_type"]
                        cvalue = float(constraint["constraint_value"])
                        if constraint["constraint_type"].startswith("one-way-bandwidth"):
                                unit = constraint["constraint_type"].split("[")[-1].rstrip("]")
                                multiplier = {"bps": 1, "kbps": 1_000, "Mbps": 1_000_000, "Gbps": 1_000_000_000}.get(unit, 1)
                                value = int(cvalue * multiplier)
                                access["service"]["svc-input-bandwidth"] = value
                                access["service"]["svc-output-bandwidth"] = value
                        elif ctype == "one-way-delay-maximum[milliseconds]":
                            access["service"]["qos"]["qos-profile"]["classes"]["class"][0]["latency"]["latency-boundary"] = int(cvalue)
                        elif ctype == "availability[%]":
                            access["service"]["qos"]["qos-profile"]["classes"]["class"][0]["bandwidth"]["guaranteed-bw-percent"] = int(cvalue)
                        elif ctype == "mtu[bytes]":
                            access["service"]["svc-mtu"] = int(cvalue)
    
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            logging.info(f"L3VPN Intent realized\n")
            self.answer[self.subnet]["VLAN"] = vlan_value
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            return tfs_request
    
    
    Javier Velázquez's avatar
    Javier Velázquez committed
        def __ixia(self, ietf_intent):
            """
            Prepare an Ixia service request based on the IETF intent.
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            This method configures an Ixia service request by:
            1. Defining endpoint routers
            2. Loading a service template
            3. Generating a unique service UUID
            4. Configuring service endpoints
            5. Adding QoS constraints
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            Args:
                ietf_intent (dict): IETF-formatted network slice intent.
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            Returns:
                dict: An Ixia service request for configuration.
            """
            self.answer[self.subnet]["QoS Requirements"] = []
                    # Add service constraints
            for i, constraint in enumerate(ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"]):
                bound = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["bound"]
                metric_type = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["metric-type"]
                metric_unit = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["metric-unit"]
                service_constraint ={
                    "custom": {
                        "constraint_type": f"{metric_type}[{metric_unit}]",
                        "constraint_value": f"{bound}"
                    }
                }
                self.answer[self.subnet]["QoS Requirements"].append(service_constraint["custom"])
            self.answer[self.subnet]["VLAN"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["service-match-criteria"]["match-criterion"][0]["value"]
            # Extraer la lista de métricas de forma segura
            metric_bounds = ietf_intent.get("ietf-network-slice-service:network-slice-services", {}) \
                .get("slo-sle-templates", {}) \
                .get("slo-sle-template", [{}])[0] \
                .get("slo-policy", {}) \
                .get("metric-bound", [])
    
            # Inicializar valores
            bandwidth = None
            latency = None
            tolerance = None
    
            # Asignar valores según el tipo de métrica
            for metric in metric_bounds:
                metric_type = metric.get("metric-type")
                bound = metric.get("bound")
    
                if metric_type == "one-way-bandwidth":
                    bandwidth = bound
                elif metric_type == "one-way-delay-maximum":
                    latency = bound
                elif metric_type == "one-way-delay-variation-maximum": 
                    tolerance = bound
    
            # Construcción del diccionario intent
            intent = {
                "src_node_ip": ietf_intent.get("ietf-network-slice-service:network-slice-services", {})
                    .get("slice-service", [{}])[0]
                    .get("sdps", {}).get("sdp", [{}])[0]
                    .get("attachment-circuits", {}).get("attachment-circuit", [{}])[0]
                    .get("sdp-peering", {}).get("peer-sap-id"),
    
                "dst_node_ip": ietf_intent.get("ietf-network-slice-service:network-slice-services", {})
                    .get("slice-service", [{}])[0]
                    .get("sdps", {}).get("sdp", [{}, {}])[1]
                    .get("attachment-circuits", {}).get("attachment-circuit", [{}])[0]
                    .get("sdp-peering", {}).get("peer-sap-id"),
    
                "vlan_id": ietf_intent.get("ietf-network-slice-service:network-slice-services", {})
                    .get("slice-service", [{}])[0]
                    .get("sdps", {}).get("sdp", [{}])[0]
                    .get("service-match-criteria", {}).get("match-criterion", [{}])[0]
                    .get("value"),
    
                "bandwidth": bandwidth,
                "latency": latency,
                "tolerance": tolerance,
    
                "latency_version": ietf_intent.get("ietf-network-slice-service:network-slice-services", {})
                    .get("slo-sle-templates", {}).get("slo-sle-template", [{}])[0]
                    .get("description"),
    
                "reliability": ietf_intent.get("ietf-network-slice-service:network-slice-services", {})
                    .get("slo-sle-templates", {}).get("slo-sle-template", [{}])[0]
                    .get("sle-policy", {}).get("reliability"),
            }
    
    Javier Velázquez's avatar
    Javier Velázquez committed
            logging.info(f"IXIA Intent realized\n")
            return intent