diff --git a/app.py b/app.py index 61503b3b4600483708559bac25bee7cb4588a2a6..1e34ec5486daeb0eb38f32e84494ba5f4fcb4db0 100644 --- a/app.py +++ b/app.py @@ -14,14 +14,11 @@ # This file is an original contribution from Telefonica Innovación Digital S.L. -import os from flask import Flask from flask_restx import Api from flask_cors import CORS -from swagger.tfs_namespace import tfs_ns -from swagger.ixia_namespace import ixia_ns -from src.Constants import NSC_PORT, WEBUI_DEPLOY -from src.webui.gui import gui_bp +from swagger.slice_namespace import slice_ns +from src.Constants import NSC_PORT app = Flask(__name__) CORS(app) @@ -36,14 +33,7 @@ api = Api( ) # Register namespaces -api.add_namespace(tfs_ns, path="/tfs") -api.add_namespace(ixia_ns, path="/ixia") -#gui_bp = Blueprint('gui', __name__, template_folder='templates') - -if WEBUI_DEPLOY: - app.secret_key = 'clave-secreta-dev' - app.register_blueprint(gui_bp) - +api.add_namespace(slice_ns, path="/slice") if __name__ == "__main__": app.run(host="0.0.0.0", port=NSC_PORT, debug=True) diff --git a/src/Constants.py b/src/Constants.py index 3b02ffd287c6eced608c00b993a71605fe53d0d4..337be8856e4a91907a76466498fb6cb57634bca9 100644 --- a/src/Constants.py +++ b/src/Constants.py @@ -12,10 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This file includes original contributions from Telefonica Innovación Digital S.L. - -import logging, os, json +# This file is an original contribution from Telefonica Innovación Digital S.L. +import logging, os # Default logging level DEFAULT_LOGGING_LEVEL = logging.INFO @@ -25,44 +24,14 @@ NSC_PORT = 8081 # Paths # Obtain the absolute path of the current file SRC_PATH = os.path.dirname(os.path.abspath(__file__)) -with open(os.path.join(SRC_PATH, 'IPs.json')) as f: - ips = json.load(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 = False - -# 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 = False - -#####TERAFLOW##### +# TFS Flags +# Flag to determine if configurations should be uploaded to Teraflow +TFS_UPLOAD = False # Teraflow IP -TFS_IP = ips.get('TFS_IP') -UPLOAD_TYPE = "WEBUI" # "WEBUI" or "NBI" -NBI_L2_PATH = "restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services" -NBI_L3_PATH = "restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services" +TFS_IP = "192.168.165.10" # Flag to determine if additional L2VPN configuration support is required for deploying L2VPNs with path selection -TFS_L2VPN_SUPPORT = False - -#####IXIA##### -# IXIA NEII IP -IXIA_IP = ips.get('IXIA_IP') - -# WebUI - -# Flag to deploy the WebUI -WEBUI_DEPLOY = True \ No newline at end of file +TFS_L2VPN_SUPPORT = False \ No newline at end of file diff --git a/src/IPs.json b/src/IPs.json deleted file mode 100644 index e56bdb0ea8dbb92225dae67bdda6176929eb211a..0000000000000000000000000000000000000000 --- a/src/IPs.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "TFS_IP": "192.168.27.165", - "IXIA_IP": "192.168.27.59" -} \ No newline at end of file diff --git a/src/helpers.py b/src/helpers.py index 0e150791ac742c02c03aaa755c04a980481b4336..47adc1619360e8f8438842b73efe31a07b3c1252 100644 --- a/src/helpers.py +++ b/src/helpers.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This file includes original contributions from Telefonica Innovación Digital S.L. - import logging, requests, json from netmiko import ConnectHandler from src.Constants import DEFAULT_LOGGING_LEVEL @@ -26,7 +24,7 @@ logging.basicConfig( #Teraflow class tfs_connector(): - def webui_post(self, tfs_ip, service): + def simple_post(self, tfs_ip, service): user="admin" password="admin" token="" @@ -46,22 +44,6 @@ class tfs_connector(): 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}' - headers = {'Content-Type': 'application/json'} - data = json.dumps(service) - logging.debug("Posting to TFS NBI: %s",data) - token={'csrf_token':token} - response = session.post(url,headers=headers,data=data,timeout=60) - logging.debug("Http response: %s",response.text) - return response - #CISCO class cisco_connector(): def __init__(self, address, configs=None): diff --git a/src/network_slice_controller.py b/src/network_slice_controller.py index 6ac70885c872dda4d18e919a602abd4f1a15c870..7d141146d3a4cf1862008ef031ebfdfc10957f38 100644 --- a/src/network_slice_controller.py +++ b/src/network_slice_controller.py @@ -12,14 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This file includes original contributions from Telefonica Innovación Digital S.L. - -import json, time, os, logging, uuid, traceback, sys +import json, time, os, logging, uuid 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, UPLOAD_TYPE, NBI_L2_PATH, NBI_L3_PATH -from src.realizers.ixia.NEII_V4 import NEII_controller -from src.planner.planner import Planner +from src.Constants import DEFAULT_LOGGING_LEVEL, TFS_UPLOAD, TFS_IP, TFS_L2VPN_SUPPORT, SRC_PATH, TEMPLATES_PATH # Configure logging to provide clear and informative log messages logging.basicConfig( @@ -42,26 +38,26 @@ 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): + def __init__(self, upload_to_tfs = TFS_UPLOAD, tfs_ip=TFS_IP, need_l2vpn_support=TFS_L2VPN_SUPPORT): """ Initialize the Network Slice Controller. Args: - controller_type (str): Flag to determine if configurations - should be uploaded to Teraflow or IXIA system. + upload_to_tfs (bool, optional): Flag to determine if configurations + should be uploaded to Teraflow system. Defaults to False. need_l2vpn_support (bool, optional): Flag to determine if additional L2VPN configuration support is required. Defaults to False. Attributes: - controller_type (str): Flag for Teraflow or Ixia upload + upload_to_tfs (bool): Flag for Teraflow upload answer (dict): Stores slice creation responses + tfs_requests (dict): Stores requests to be sent to Teraflow start_time (float): Tracks slice setup start time end_time (float): Tracks slice setup end time need_l2vpn_support (bool): Flag for additional L2VPN configuration support """ - self.controller_type = controller_type + self.upload_to_tfs = upload_to_tfs self.tfs_ip = tfs_ip - self.path = "" self.answer = {} self.cool_answer = {} self.start_time = 0 @@ -134,7 +130,7 @@ class NSController: raise ValueError("Transport network slices not found") # Return all slices if no specific ID is given - return [slice for slice in content if slice.get("controller") == self.controller_type] + return content except ValueError as e: # Handle case where no slices are found @@ -183,7 +179,7 @@ class NSController: Exception: For unexpected errors during deletion process Notes: - - If controller_type is TFS, attempts to delete from Teraflow + - If upload_to_tfs is True, attempts to delete from Teraflow - If need_l2vpn_support is True, performs additional L2VPN cleanup """ try: @@ -195,7 +191,7 @@ class NSController: # 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.controller_type: + if slice["slice_id"] == slice_id: del content[i] id = i break @@ -211,21 +207,19 @@ class NSController: # Delete all slices else: # Optional: Delete in Teraflow if configured - if self.controller_type == "TFS": + if self.upload_to_tfs == True: # TODO: should send a delete request to Teraflow if self.need_l2vpn_support: self.__tfs_l2vpn_delete() - data_removed = [slice for slice in content if slice.get("controller") == self.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.controller_type] + with open(os.path.join(SRC_PATH, "slice_ddbb.json"), 'r') as file: + if len(json.load(file)) == 0: + raise ValueError("Transport network slices not found") + # Clear slice database with open(os.path.join(SRC_PATH, "slice_ddbb.json"), 'w') as file: - json.dump(filtered_data, file, indent=4) + json.dump([], file, indent=4) logging.info("All slices removed successfully") return self.__send_response(False, code=200, status="success", message="All transport network slices deleted successfully.") @@ -263,21 +257,11 @@ class NSController: # Reset requests and load IETF template 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)) + tfs_requests = {"services":[]} # 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 @@ -287,39 +271,25 @@ class NSController: self.__mapper(intent) # Realizer tfs_request = self.__realizer(intent) - requests["services"].append(tfs_request) + tfs_requests["services"].append(tfs_request) else: return self.__send_response(False, code=404, message="No intents found") - - # 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)) + + # Generated service + logging.debug(json.dumps(tfs_requests, indent=2)) # Optional: Upload template to Teraflow - if not DUMMY_MODE: - if self.controller_type == "TFS": - if UPLOAD_TYPE == "WEBUI": - response = tfs_connector().webui_post(self.tfs_ip, requests) - elif UPLOAD_TYPE == "NBI": - for intent in requests["services"]: - # Send each separate NBI request - response = tfs_connector().nbi_post(self.tfs_ip, intent, self.path) - - if not response.ok: - return self.__send_response(False, code=response.status_code, message=f"Teraflow upload failed. Response: {response.text}") - - # For deploying an L2VPN with path selection (not supported by Teraflow) - if self.need_l2vpn_support: - self.__tfs_l2vpn_support(requests["services"]) + if self.upload_to_tfs == True: + response = tfs_connector().simple_post(self.tfs_ip, tfs_requests) + + if not response.ok: + return self.__send_response(False, code=response.status_code, message=f"Teraflow upload failed. Response: {response.text}") + + # For deploying an L2VPN with path selection (not supported by Teraflow) + if self.need_l2vpn_support: + self.__tfs_l2vpn_support(tfs_requests["services"]) - logging.info("Request sent to Teraflow") - elif self.controller_type == "IXIA": - neii_controller = NEII_controller() - for intent in requests["services"]: - # Send each separate IXIA request - neii_controller.nscNEII(intent) - logging.info("Requests sent to Ixia") + logging.info("Request sent to Teraflow") # End performance tracking self.end_time = time.perf_counter() @@ -349,6 +319,7 @@ class NSController: # Detect the input JSON format (3GPP or IETF) format = self.__detect_format(intent_json) ietf_intents = [] + logging.info("--------NEW REQUEST--------") # TODO Needs to be generalized to support different names of slicesubnets # Process different input formats @@ -385,42 +356,35 @@ 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") - - # Extract Service Level Objectives (SLOs) from the intent - slos = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"] - - if slos: - # Find candidate NRPs that can meet the SLO requirements - candidates = [ - (nrp, self.__slo_viability(slos, nrp)[1]) - for nrp in self.__nrp_view - if self.__slo_viability(slos, nrp)[0] and nrp["available"] - ] - logging.debug(f"Candidates: {candidates}") - - # Select the best NRP based on candidates - best_nrp = max(candidates, key=lambda x: x[1])[0] if candidates else None - logging.debug(f"Best NRP: {best_nrp}") - - if best_nrp: - best_nrp["slices"].append(ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"]) - # Update NRP view - self.__realizer(ietf_intent, True, "UPDATE") - # TODO Here we should put how the slice is attached to an already created nrp - else: - # Request the controller to create a new NRP that meets the SLOs - answer = self.__realizer(ietf_intent, True, "CREATE", best_nrp) - if not answer: - 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}") + # Retrieve NRP view + self.__realizer(None, True, "READ") + + # Extract Service Level Objectives (SLOs) from the intent + slos = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"] + + # Find candidate NRPs that can meet the SLO requirements + candidates = [ + (nrp, self.__slo_viability(slos, nrp)[1]) + for nrp in self.__nrp_view + if self.__slo_viability(slos, nrp)[0] and nrp["available"] + ] + logging.debug(f"Candidates: {candidates}") + + # Select the best NRP based on candidates + best_nrp = max(candidates, key=lambda x: x[1])[0] if candidates else None + logging.debug(f"Best NRP: {best_nrp}") + + if best_nrp: + best_nrp["slices"].append(ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"]) + # Update NRP view + self.__realizer(ietf_intent, True, "UPDATE") + # TODO Here we should put how the slice is attached to an already created nrp + else: + # Request the controller to create a new NRP that meets the SLOs + answer = self.__realizer(ietf_intent, True, "CREATE", best_nrp) + if not answer: + raise Exception("Slice rejected due to lack of NRPs") + # TODO Here we should put how the slice is attached to the new nrp def __realizer(self, ietf_intent, need_nrp=False, order=None, nrp=None): """ @@ -441,9 +405,7 @@ class NSController: self.__nrp(order, nrp) else: # Select slice service method - way = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["service-tags"]["tag-type"]["value"] - way = "L3VPN" - return self.__select_way(controller=self.controller_type, way=way, ietf_intent=ietf_intent) + return self.__select_way("L2VPN", ietf_intent) ### Generic functionalities def __load_template(self, which, dir_t): @@ -505,7 +467,8 @@ class NSController: "source": self.answer[subnet]["Source"], "destination": self.answer[subnet]["Destination"], "vlan": self.answer[subnet]["VLAN"], - "requirements": self.answer[subnet]["QoS Requirements"], + "bandwidth(Mbps)": self.answer[subnet]["QoS Requirements"][0], + "latency(ms)": self.answer[subnet]["QoS Requirements"][1] } answer["slices"].append(slice_info) self.cool_answer = answer @@ -574,8 +537,7 @@ class NSController: content.append( { "slice_id": intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"], - "intent": intent, - "controller": self.controller_type, + "intent": intent }) # # Write updated content back to file @@ -635,38 +597,8 @@ class NSController: # Populate template with SLOs (currently supporting QoS profile, latency and bandwidth) ietf_i["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["id"] = gpp_intent[ep_transport_objects[0]]["qosProfile"] - - profile = gpp_intent.get(subnet, {}).get("SliceProfileList", [{}])[0].get("RANSliceSubnetProfile", {}) - - - metrics = { - ("uLThptPerSliceSubnet", "MaxThpt"): ("one-way-bandwidth", "kbps"), - ("uLLatency",): ("one-way-delay-maximum", "milliseconds"), - ("EnergyConsumption",): ("energy_consumption", "Joules"), - ("EnergyEfficiency",): ("energy_efficiency", "W/bps"), - ("CarbonEmissions",): ("carbon_emission", "gCO2eq"), - ("RenewableEnergyUsage",): ("renewable_energy_usage", "rate") - } - - # Aux - def get_nested(d, keys): - for k in keys: - if isinstance(d, dict) and k in d: - d = d[k] - else: - return None - return d - - for key_path, (metric_type, metric_unit) in metrics.items(): - value = get_nested(profile, key_path) - if value is not None: - ietf_i["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]\ - ["slo-sle-template"][0]["slo-policy"]["metric-bound"].append({ - "metric-type": metric_type, - "metric-unit": metric_unit, - "bound": value - }) - + ietf_i["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][0]["bound"] = gpp_intent[subnet]["SliceProfileList"][0]["RANSliceSubnetProfile"]["uLThptPerSliceSubnet"]["MaxThpt"] + ietf_i["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][1]["bound"] = gpp_intent[subnet]["SliceProfileList"][0]["RANSliceSubnetProfile"]["uLLatency"] # Generate unique slice service ID and description ietf_i["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"] = f"slice-service-{uuid.uuid4()}" @@ -694,6 +626,10 @@ 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 @@ -741,6 +677,102 @@ 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): """ @@ -794,15 +826,11 @@ class NSController: logging.debug("Updating NRP") answer = "" - def __select_way(self, controller=None, way=None, ietf_intent=None): + def __select_way(self,way, ietf_intent): """ Determine the method of slice realization. Args: - controller (str): The controller to use for slice realization. - Supported values: - - "IXIA": IXIA NEII for network testing - - "TFS": TeraFlow Service for network slice management way (str): The type of technology to use. Supported values: - "L2VPN": Layer 2 Virtual Private Network @@ -814,22 +842,12 @@ class NSController: dict: A realization request for the specified network slice type. """ - realizing_request = None - if controller == "TFS": - if way == "L2VPN": - realizing_request = self.__tfs_l2vpn(ietf_intent) - elif way == "L3VPN": - realizing_request = self.__tfs_l3vpn(ietf_intent) - else: - logging.warning(f"Unsupported way: {way}. Defaulting to L2VPN realization.") - realizing_request = self.__tfs_l2vpn(ietf_intent) - elif controller == "IXIA": - realizing_request = self.__ixia(ietf_intent) - else: - logging.warning(f"Unsupported controller: {controller}. Defaulting to TFS L2VPN realization.") + if way == "L2VPN": realizing_request = self.__tfs_l2vpn(ietf_intent) + elif way == "L3VPN": + realizing_request = self.__tfs_l3vpn(ietf_intent) return realizing_request - + def __tfs_l2vpn(self, ietf_intent): """ Translate slice intent into a TeraFlow service request. @@ -854,100 +872,49 @@ class NSController: 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"] - destination_router_if = '0/0/0-GigabitEthernet0/0/0/0' + destination_router_if = '0/0/3-GigabitEthernet0/0/0/3' # 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 + + # 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] - self.answer[self.subnet]["QoS Requirements"] = [] + # Generate unique service UUID + tfs_request["service_id"]["service_uuid"]["uuid"] += "-" + str(int(datetime.now().timestamp() * 1e7)) - # 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 + # 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 - if UPLOAD_TYPE == "WEBUI": - # 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 - - # 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"] - if vlan_value: - resource_value["vlan_id"] = int(vlan_value) - resource_value["circuit_id"] = vlan_value - resource_value["remote_router"] = destination_router_id if i == 1 else origin_router_id - 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_L2_PATH - # Load IETF L2VPN service template - self.__load_template(2, os.path.join(TEMPLATES_PATH, "ietfL2VPN_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"] - uuid_only = full_id.split("slice-service-")[-1] - tfs_request["ietf-l2vpn-svc:vpn-service"][0]["vpn-id"] = uuid_only - - # Configure service endpoints - sites = tfs_request["ietf-l2vpn-svc:vpn-service"][0]["site"] - sdps = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"] - - for i, site in enumerate(sites): - is_origin = (i == 0) - router_id = origin_router_id if is_origin else destination_router_id - sdp = sdps[0] if is_origin else sdps[1] - site["site-id"] = router_id - site["site-location"] = sdp["node-id"] - site["site-network-access"]["interface"]["ip-address"] = sdp["sdp-ip-address"] - - logging.info(f"L2VPN Intent realized\n") + self.answer[self.subnet]["QoS Requirements"] = [] + # Add service constraints + for i, constraint in enumerate(tfs_request["service_constraints"]): + bound = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["bound"] + self.answer[self.subnet]["QoS Requirements"].append(bound) + constraint["custom"]["constraint_value"] = str(bound) + + # 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["vlan_id"] = int(vlan_value) + resource_value["circuit_id"] = vlan_value + resource_value["remote_router"] = destination_router_id if i == 1 else origin_router_id + resource_value["ni_name"] = 'ELAN{:s}'.format(str(vlan_value)) + config_rule["custom"]["resource_key"] = f"/device[{router_id}]/endpoint[{router_if}]/settings" + + # Log and store VLAN information + logging.info(f"Intent with VLAN {vlan_value} realized\n") + self.answer[self.subnet]["VLAN"] = vlan_value return tfs_request def __tfs_l2vpn_support(self, requests): @@ -1039,221 +1006,50 @@ 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"] - 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 + destination_router_if = '0/0/3-GigabitEthernet0/0/0/3' + + # 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] - self.answer[self.subnet]["QoS Requirements"] = [] + # Generate unique service UUID + tfs_request["service_id"]["service_uuid"]["uuid"] += "-" + str(int(datetime.now().timestamp() * 1e7)) - # 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) + # 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 i, constraint in enumerate(tfs_request["service_constraints"]): + bound = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["bound"] + constraint["custom"]["constraint_value"] = str(bound) + + # 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" - logging.info(f"L3VPN Intent realized\n") - self.answer[self.subnet]["VLAN"] = vlan_value return tfs_request - def __ixia(self, ietf_intent): - """ - Prepare an Ixia service request based on the IETF intent. - 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 - Args: - ietf_intent (dict): IETF-formatted network slice intent. - 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"), - } - logging.info(f"IXIA Intent realized\n") - return intent + diff --git a/src/planner/energy_ddbb.json b/src/planner/energy_ddbb.json deleted file mode 100644 index 7826de6031621fb4103690cc02ac8b655c8996ad..0000000000000000000000000000000000000000 --- a/src/planner/energy_ddbb.json +++ /dev/null @@ -1,156 +0,0 @@ -[ - { - "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 diff --git a/src/planner/ext_topo_ddbb.json b/src/planner/ext_topo_ddbb.json deleted file mode 100644 index 72dc93dc10ca271adf670d9b85466920a4736929..0000000000000000000000000000000000000000 --- a/src/planner/ext_topo_ddbb.json +++ /dev/null @@ -1,195 +0,0 @@ -{ -"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 diff --git a/src/planner/planner.py b/src/planner/planner.py deleted file mode 100644 index b5fb1ba1ee624fcc090d4c85dfc252f2463ac042..0000000000000000000000000000000000000000 --- a/src/planner/planner.py +++ /dev/null @@ -1,286 +0,0 @@ -# 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. - -# This file is an original contribution from Telefonica Innovación Digital S.L. - -import logging, random, os, json, heapq -from src.Constants import SRC_PATH, PCE_EXTERNAL, DEFAULT_LOGGING_LEVEL - -# Configure logging to provide clear and informative log messages -logging.basicConfig( - level=DEFAULT_LOGGING_LEVEL, - format='%(levelname)s - %(message)s') - -class Planner: - """ - Planner class to compute the optimal path for a network slice based on energy consumption and topology. - """ - - def planner(self, intent): - """ - Plan the optimal path for a network slice based on energy consumption and topology. - """ - energy_metrics = self.__retrieve_energy() - topology = self.__retrieve_topology() - source = intent.get("ietf-network-slice-service:network-slice-services", {}).get("slice-service", [])[0].get("sdps", {}).get("sdp", [])[0].get("id") or "A" - destination = intent.get("ietf-network-slice-service:network-slice-services", {}).get("slice-service", [])[0].get("sdps", {}).get("sdp", [])[1].get("id") or "B" - optimal_path = [] - # If using an external PCE - if PCE_EXTERNAL: - logging.info("Using external PCE for path planning") - def build_slice_input(node_source, node_destination): - return { - "clientName": "demo-client", - "requestId": random.randint(1000, 9999), - "sites": [node_source["nodeId"], node_destination["nodeId"]], - "graph": { - "nodes": [ - { - "nodeId": node_source["nodeId"], - "name": node_source["name"], - "footprint": node_source["footprint"], - "sticky": [node_source["nodeId"]] - }, - { - "nodeId": node_destination["nodeId"], - "name": node_destination["name"], - "footprint": node_destination["footprint"], - "sticky": [node_destination["nodeId"]] - } - ], - "links": [ - { - "fromNodeId": node_source["nodeId"], - "toNodeId": node_destination["nodeId"], - "bandwidth": 1000000000, - "metrics": [ - { - "metric": "DELAY", - "value": 10, - "bound": True, - "required": True - } - ] - } - ], - "constraints": { - "maxVulnerability": 3, - "maxDeployedServices": 10, - "metricLimits": [] - } - } - } - source = next((node for node in topology["nodes"] if node["name"] == source), None) - destination = next((node for node in topology["nodes"] if node["name"] == destination), None) - slice_input = build_slice_input(source, destination) - - # POST /sss/v1/slice/compute - def simulate_slice_output(input_data): - return { - "input": input_data, - "slice": { - "nodes": [ - {"site": 1, "service": 1}, - {"site": 2, "service": 2} - ], - "links": [ - { - "fromNodeId": 1, - "toNodeId": 2, - "lspId": 500, - "path": { - "ingressNodeId": 1, - "egressNodeId": 2, - "hops": [ - {"nodeId": 3, "linkId": "A-C", "portId": 1}, - {"nodeId": 2, "linkId": "C-B", "portId": 2} - ] - } - } - ], - "metric": {"value": 9} - }, - "error": None - } - slice_output = simulate_slice_output(slice_input) - # Mostrar resultado - optimal_path.append(source["name"]) - for link in slice_output["slice"]["links"]: - for hop in link["path"]["hops"]: - optimal_path.append(next((node for node in topology["nodes"] if node["nodeId"] == hop['nodeId']), None)["name"]) - - else: - logging.info("Using internal PCE for path planning") - ietf_dlos = intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"] - logging.info(ietf_dlos), - # Solo asigna los DLOS que existan, el resto a None - dlos = { - "EC": next((item.get("bound") for item in ietf_dlos if item.get("metric-type") == "energy_consumption"), None), - "CE": next((item.get("bound") for item in ietf_dlos if item.get("metric-type") == "carbon_emission"), None), - "EE": next((item.get("bound") for item in ietf_dlos if item.get("metric-type") == "energy_efficiency"), None), - "URE": next((item.get("bound") for item in ietf_dlos if item.get("metric-type") == "renewable_energy_usage"), None) - } - logging.debug(f"Planning optimal path from {source} to {destination} with DLOS: {dlos}") - optimal_path = self.__calculate_optimal_path(topology, energy_metrics, source, destination, dlos) - - if not optimal_path: - logging.error("No valid path found") - raise Exception("No valid energy path found") - - return optimal_path - - def __retrieve_energy(self): - # TODO : Implement the logic to retrieve energy consumption data from controller - # Taking it from static file - with open(os.path.join(SRC_PATH, "planner/energy_ddbb.json"), "r") as archivo: - energy_metrics = json.load(archivo) - return energy_metrics - - def __retrieve_topology(self): - if PCE_EXTERNAL: - # TODO : Implement the logic to retrieve topology data from external PCE - # GET /sss/v1/topology/node and /sss/v1/topology/link - with open(os.path.join(SRC_PATH, "planner/ext_topo_ddbb.json"), "r") as archivo: - topology = json.load(archivo) - else: - # TODO : Implement the logic to retrieve topology data from controller - # Taking it from static file - with open(os.path.join(SRC_PATH, "planner/topo_ddbb.json"), "r") as archivo: - topology = json.load(archivo) - return topology - - - - def __calculate_optimal_path(self, topology, energy_metrics, source, destination, dlos): - logging.debug("Starting optimal path calculation...") - - # Create a dictionary with the weights of each node - node_data_map = {} - for node_data in energy_metrics: - node_id = node_data["name"] - ec = node_data["typical-power"] - ce = node_data["carbon-emissions"] - ee = node_data["efficiency"] - ure = node_data["renewable-energy-usage"] - - total_power_supply = sum(ps["typical-power"] for ps in node_data["power-supply"]) - total_power_boards = sum(b["typical-power"] for b in node_data["boards"]) - total_power_components = sum(c["typical-power"] for c in node_data["components"]) - total_power_transceivers = sum(t["typical-power"] for t in node_data["transceivers"]) - - logging.debug(f"Node {node_id}: EC={ec}, CE={ce}, EE={ee}, URE={ure}") - logging.debug(f"Node {node_id}: PS={total_power_supply}, BO={total_power_boards}, CO={total_power_components}, TR={total_power_transceivers}") - - weight = self.__compute_node_weight(ec, ce, ee, ure, - total_power_supply, - total_power_boards, - total_power_components, - total_power_transceivers) - logging.debug(f"Weight for node {node_id}: {weight}") - - node_data_map[node_id] = { - "weight": weight, - "ec": ec, - "ce": ce, - "ee": ee, - "ure": ure - } - - # Create a graph representation of the topology - graph = {} - for node in topology["ietf-network:networks"]["network"][0]["node"]: - graph[node["node-id"]] = [] - for link in topology["ietf-network:networks"]["network"][0]["link"]: - src = link["source"]["source-node"] - dst = link["destination"]["dest-node"] - graph[src].append((dst, node_data_map[dst]["weight"])) - logging.debug(f"Added link: {src} -> {dst} with weight {node_data_map[dst]['weight']}") - - # Dijkstra's algorithm with restrictions - queue = [(0, source, [], 0, 0, 0, 1)] # (accumulated cost, current node, path, sum_ec, sum_ce, sum_ee, min_ure) - visited = set() - - logging.debug(f"Starting search from {source} to {destination} with restrictions: {dlos}") - - - while queue: - cost, node, path, sum_ec, sum_ce, sum_ee, min_ure = heapq.heappop(queue) - logging.debug(f"Exploring node {node} with cost {cost} and path {path + [node]}") - - if node in visited: - logging.debug(f"Node {node} already visited, skipped.") - continue - visited.add(node) - path = path + [node] - - node_metrics = node_data_map[node] - sum_ec += node_metrics["ec"] - sum_ce += node_metrics["ce"] - sum_ee += node_metrics["ee"] - min_ure = min(min_ure, node_metrics["ure"]) if path[:-1] else node_metrics["ure"] - - logging.debug(f"Accumulated -> EC: {sum_ec}, CE: {sum_ce}, EE: {sum_ee}, URE min: {min_ure}") - - if dlos["EC"] is not None and sum_ec > dlos["EC"]: - logging.debug(f"Discarded path {path} for exceeding EC ({sum_ec} > {dlos['EC']})") - continue - if dlos["CE"] is not None and sum_ce > dlos["CE"]: - logging.debug(f"Discarded path {path} for exceeding CE ({sum_ce} > {dlos['CE']})") - continue - if dlos["EE"] is not None and sum_ee > dlos["EE"]: - logging.debug(f"Discarded path {path} for exceeding EE ({sum_ee} > {dlos['EE']})") - continue - if dlos["URE"] is not None and min_ure < dlos["URE"]: - logging.debug(f"Discarded path {path} for not reaching minimum URE ({min_ure} < {dlos['URE']})") - continue - - if node == destination: - logging.debug(f"Destination {destination} reached with a valid path: {path}") - return path - - for neighbor, weight in graph.get(node, []): - if neighbor not in visited: - logging.debug(f"Qeue -> neighbour: {neighbor}, weight: {weight}") - heapq.heappush(queue, ( - cost + weight, - neighbor, - path, - sum_ec, - sum_ce, - sum_ee, - min_ure - )) - logging.debug("No valid path found that meets the restrictions.") - return [] - - - def __compute_node_weight(self, ec, ce, ee, ure, total_power_supply, total_power_boards, total_power_components, total_power_transceivers, alpha=1, beta=1, gamma=1, delta=1): - """ - Calcula el peso de un nodo con la fórmula: - w(v) = α·EC + β·CE + γ/EE + δ·(1 - URE) - """ - traffic = 100 - # Measure one hour of traffic - time = 1 - - power_idle = ec + total_power_supply + total_power_boards + total_power_components + total_power_transceivers - power_traffic = traffic * ee - - power_total = (power_idle + power_traffic) - - green_index = power_total * time / 1000 * (1 - ure) * ce - - return green_index - - diff --git a/src/planner/topo_ddbb.json b/src/planner/topo_ddbb.json deleted file mode 100644 index 76fb08c68d4c7337e09f79ce827004fba810a5b9..0000000000000000000000000000000000000000 --- a/src/planner/topo_ddbb.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "ietf-network:networks":{ - "network":[ - { - "network-id":"example_network", - "network-types":{ - - }, - "node":[ - {"node-id":"A"}, - {"node-id":"B"}, - {"node-id":"C"}, - {"node-id":"D"}, - {"node-id":"E"}, - {"node-id":"F"}, - {"node-id":"G"} - ], - "link":[ - {"link-id":"A-E","source":{"source-node":"A"},"destination":{"dest-node":"E"}}, - {"link-id":"E-A","source":{"source-node":"E"},"destination":{"dest-node":"A"}}, - {"link-id":"A-D","source":{"source-node":"A"},"destination":{"dest-node":"D"}}, - {"link-id":"D-A","source":{"source-node":"D"},"destination":{"dest-node":"A"}}, - {"link-id":"A-C","source":{"source-node":"A"},"destination":{"dest-node":"C"}}, - {"link-id":"C-A","source":{"source-node":"C"},"destination":{"dest-node":"A"}}, - {"link-id":"B-C","source":{"source-node":"B"},"destination":{"dest-node":"C"}}, - {"link-id":"C-B","source":{"source-node":"C"},"destination":{"dest-node":"B"}}, - {"link-id":"B-D","source":{"source-node":"B"},"destination":{"dest-node":"D"}}, - {"link-id":"D-B","source":{"source-node":"D"},"destination":{"dest-node":"B"}}, - {"link-id":"B-F","source":{"source-node":"B"},"destination":{"dest-node":"F"}}, - {"link-id":"F-B","source":{"source-node":"F"},"destination":{"dest-node":"B"}}, - {"link-id":"D-E","source":{"source-node":"D"},"destination":{"dest-node":"E"}}, - {"link-id":"E-D","source":{"source-node":"E"},"destination":{"dest-node":"D"}}, - {"link-id":"D-F","source":{"source-node":"D"},"destination":{"dest-node":"F"}}, - {"link-id":"F-D","source":{"source-node":"F"},"destination":{"dest-node":"D"}}, - {"link-id":"E-G","source":{"source-node":"E"},"destination":{"dest-node":"G"}}, - {"link-id":"G-E","source":{"source-node":"G"},"destination":{"dest-node":"E"}}, - {"link-id":"F-G","source":{"source-node":"F"},"destination":{"dest-node":"G"}}, - {"link-id":"G-F","source":{"source-node":"G"},"destination":{"dest-node":"F"}} - ] - } - ] - } - } \ No newline at end of file diff --git a/src/realizers/ixia/NEII_V4.py b/src/realizers/ixia/NEII_V4.py deleted file mode 100644 index f9379d2cc0ddb0aceecb38ad918e0a995b0cebfe..0000000000000000000000000000000000000000 --- a/src/realizers/ixia/NEII_V4.py +++ /dev/null @@ -1,375 +0,0 @@ -# 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. - -# This file is an original contribution from Telefonica Innovación Digital S.L. - -from .automatizacion_ne2v4 import automatizacion -import ipaddress, logging -from src.Constants import IXIA_IP - -class NEII_controller: - def __init__(self, ixia_ip=IXIA_IP): - self.ixia_ip = ixia_ip - - def menu_principal(self, ip=IXIA_IP): - ''' - Inputs: - Outputs: - Work: The main menu of the application. - Notes: If the file is executed from the terminal, ensure that the import - of "automatizacion_ne2v4" does not include a dot at the beggining. - ''' - ip=input("¿Cuál es la IP del network emulator?: ") - accion=input("¿Qué deseas hacer?: \n(1) Ver información de IP\n(2) Consultar información del Hardware\n(3) Configurar un perfil nuevo\n(4) Consultar perfiles existentes\nSelecciona una opción: ") - if accion=="1": - self.ver_info(ip) - if accion=="2": - self.hardware(ip) - if accion=="3": - self.nuevo_perfil(ip) - if accion=="4": - self.existentes(ip) - return - - ## FUNCIONES MENÚ PRINCIPAL ## - - def ver_info(self,ip): - ''' - Inputs: -ip: the ip where the Axia API is located. - Outputs: - Work: It gives the information of the API. - - ''' - informacion_ip=automatizacion.obtener_informacion_ip(ip) - if informacion_ip: - print(informacion_ip) - - def hardware(self,ip): - ''' - Inputs: -ip: the ip where the Axia API is located. - Outputs: - Work: It gives the information of the hardware. - - ''' - informacion_hardware=automatizacion.obtener_informacion_hardware(ip) - if informacion_hardware: - print(informacion_hardware) - - def nuevo_perfil(self,ip): - ''' - Inputs: -ip: the ip where the Axia API is located. - Outputs: - Work: Creates and configures the profiles requested in the Axia API on the specified port. - Notes: It is NOT required to fill all the information requested. - - ''' - puerto=input("¿Qué puerto quieres configurar?: ") - num_perfiles=int(input("¿Cuantos perfiles quieres añadir?: ")) - configuraciones_totales=[] - for i in range(num_perfiles): - nombre=f"perfil{i+1}" - accion=input("¿Qué deseas configurar?\n1)IPv4\t2)IPv6\n3)VLAN\t4)Delay\n5)Packet Drop\t6)Policer (Rx Bandwidth)\n7)Shaper (Rx Bandwidth)\nPor favor, separa las opciones con comas: ") - opciones=accion.split(',') - configuraciones={} - for opcion in opciones: - opcion=opcion.strip() - if opcion=="1": - source_ip=input("Introduce la IP de origen (IPv4): ") - destination_ip=input("Introduce la IP destino (IPv4): ") - prt=input("¿Qué protocolo quieres usar, IP o TCP? ") - configuraciones['ipv4']=self.ipv4(source_ip,destination_ip,prt) - elif opcion=="2": - source=input("Introduce la IP de origen (IPv6): ") - destination=input("Introduce la IP destino (IPv6): ") - configuraciones['ipv6']=self.ipv6(source, destination) - elif opcion=="3": - vlan_id=int(input("Introduce identificador de VLAN: ")) - configuraciones['vlan']=self.vlan(vlan_id) - elif opcion=="4": - delay_perfil=input("Introduce el delay que quieres introducir en el perfil test_api: ") - configuraciones['ethernetDelay']=self.delay(delay_perfil) - elif opcion=="5": - configuraciones['packetDrop']=self.packetDrop() - elif opcion=="6": - bandwidth=int(input('Introduzca el ancho de banda (Kbps): ')) - configuraciones['policer']=self.policer(bandwidth) - elif opcion=="7": - configuraciones['shaper']=self.shaper() - else: - print(f"Opción '{opcion}' no es válida.") - configuracion_perfil=self.configuracion_total(configuraciones, nombre) - configuraciones_totales.append(configuracion_perfil) - perfil_final = {'profiles': configuraciones_totales} - configuracion_puerto=automatizacion.envio_peticion(ip, puerto, perfil_final) - if configuracion_puerto: - print(configuracion_puerto) - - def existentes(self,ip): - ''' - Inputs: -ip: the ip where the Axia API is located. - Outputs: - Work: Shows the information of a given port- - - ''' - puerto=input("¿Qué puerto quieres consultar?: ") - informacion_puerto=automatizacion.obtener_informacion_puerto(ip, puerto) - if informacion_puerto: - print(informacion_puerto) - - def existentes_auto(self,ip,puerto): - ''' - Inputs: -ip: the ip where the Axia API is located. - - puerto: the port we want to get the information. - Outputs: - Work: Creates and configures the profiles requested in the Axia API on the specified port. - - ''' - informacion_puerto=automatizacion.obtener_informacion_puerto(ip, puerto) - if informacion_puerto: - print(f'info puerto\n{informacion_puerto}') - return informacion_puerto - - ## FUNCION PARA LA GUI DEL NSC ## - - import ipaddress - - def nscNEII(self, json_data): - configuraciones = {} - ip = self.ixia_ip - puerto = "5" - dataProfile = self.existentes_auto(ip, puerto) - - print(f'\n\n{json_data}\n') - - ip_version = json_data.get("ip_version", None) - src_node_ip = json_data.get("src_node_ip", None) - dst_node_ip = json_data.get("dst_node_ip", None) - src_node_ipv6 = json_data.get("src_node_ipv6", None) - dst_node_ipv6 = json_data.get("dst_node_ipv6", None) - vlan_id = json_data.get("vlan_id", None) - bandwidth = json_data.get("bandwidth", None) - latency = json_data.get("latency", None) - latency_version = json_data.get("latency_version", None) - reliability = json_data.get("reliability", None) - tolerance = json_data.get("tolerance", None) - packet_reorder = json_data.get("packet_reorder", None) - num_pack = json_data.get("num_pack", None) - pack_reorder = json_data.get("pack_reorder", None) - num_reorder = json_data.get("num_reorder", None) - max_reorder = json_data.get("max_reorder", None) - drop_version = json_data.get("drop_version", None) - desv_reorder = json_data.get("desv_reorder", None) - packets_drop = json_data.get("packets_drop", None) - drops = json_data.get("drops", None) - desv_drop = json_data.get("desv_drop", None) - - # --- Variables de configuración --- - - # Configuración de IPv4 / IPv6 - if src_node_ip and dst_node_ip: - if isinstance(ipaddress.ip_address(src_node_ip), ipaddress.IPv4Address) and isinstance(ipaddress.ip_address(dst_node_ip), ipaddress.IPv4Address): - configuraciones['ipv4'] = self.ipv4(src_node_ip, dst_node_ip, 5) - if src_node_ipv6 and dst_node_ipv6: - if isinstance(ipaddress.ip_address(src_node_ipv6), ipaddress.IPv6Address) and isinstance(ipaddress.ip_address(dst_node_ipv6), ipaddress.IPv6Address): - configuraciones['ipv6'] = self.ipv6(src_node_ipv6, dst_node_ipv6) - - # VLAN - if vlan_id: - configuraciones['vlan'] = self.vlan(int(vlan_id)) - - # Policer - if bandwidth: - configuraciones['policer'] = self.policer(bandwidth) - - # Latencia - if latency: - if float(latency) > 0: - configuraciones['ethernetDelay'] = self.delay_gui(float(latency), latency_version, float(tolerance)) - - # Packet Reorder - if packet_reorder: - configuraciones['reorder'] = self.packetReorder(num_reorder, pack_reorder, num_pack, max_reorder, packet_reorder, desv_reorder) - - # Packet Reorder when reliability - if reliability: - configuraciones['reorder'] = self.packetReorder(int(reliability)) - - #Dropper - if drop_version: - configuraciones['packetDrop'] = self.packetDrop(drops, packets_drop, drop_version, desv_drop) - - # Agregar perfil - num_profiles = len(dataProfile.get("profiles", [])) - configuracion_perfil = self.configuracion_total(configuraciones, f"profile{num_profiles + 1}") - dataProfile['profiles'].append(configuracion_perfil) - logging.info(f"Configuración del perfil: {configuracion_perfil}") - - # Enviar la configuración - automatizacion.envio_peticion(ip, puerto, dataProfile) - return automatizacion.obtener_informacion_puerto(ip, puerto) - - - ## FUNCIONES DE CONFIGURACIÓN DE PUERTO ## - - def delay(self,delay_perfil): - ''' - Inputs: -delay_perfil: the delay we want to configurate. - Outputs: the information of the delay for the controller. - Work: Creates the configuration JSON for delay of the controller. - - ''' - delay_perfil = input("Enter the delay you want to set in the test_api profile: ") - print(f"delay en main: {delay_perfil}") - delay_type = input("Select one option of stadistics:\n1)None\t2)Gaussian\n3)Internet\n(Type the number)") - configuracion_delay = automatizacion.añadir_configuracion_puerto_delay(delay_perfil,delay_type) - print(f"Config delay:\n{configuracion_delay}") - return configuracion_delay - - def delay_gui(self,delay_perfil, latency_version, max_latency): - ''' - Inputs: -delay_perfil: the delay we want to configurate. - Outputs: the information of the delay for the controller. - Work: Creates the configuration JSON for delay of the controller. - - ''' - print(f'\nPero: {max_latency}\n') - configuracion_delay = automatizacion.añadir_configuracion_puerto_delay(delay_perfil,latency_version,max_latency) - return configuracion_delay - - def ipv4(self,source_ip,destination_ip,prt): - ''' - Inputs: -source_ip: the source IPv4 we want to configurate. - -destination_ip: the destination IPv4 we want to configurate. - -prt: the protocol we want to configurate - Outputs: the information of the IPv4 for the controller. - Work: Creates the configuration JSON for IPv4 of the controller. - Notes: by default, the protocol is TCP (6). - - ''' - source_hx=None - destination_hx=None - protocolo=None - if source_ip: - source_hx=hex(int(ipaddress.IPv4Address(source_ip)))[2:] - if destination_ip: - destination_hx=hex(int(ipaddress.IPv4Address(destination_ip)))[2:] - if prt: - protocolo="4" if prt=="IP" else "6" - configuracion_puerto=automatizacion.añadir_configuracion_puerto_ipv4(source_hx, destination_hx, protocolo) - return configuracion_puerto - - def ipv6(self,source, destination): - ''' - Inputs: -source: the source IPv6 we want to configurate. - -destination: the destination IPv6 we want to configurate. - Outputs: the information of the IPv6 for the controller. - Work: Creates the configuration JSON for IPv6 of the controller. - - ''' - if source: - source=ipaddress.IPv6Address(source).exploded.replace(":", "") - elif not source: source=None - if destination: - destination=ipaddress.IPv6Address(destination).exploded.replace(":", "") - elif not destination: destination=None - configuracion_puerto=automatizacion.añadir_configuracion_puerto_ipv6(source, destination) - return configuracion_puerto - - def vlan(self,vlan_id): - ''' - Inputs: -vlan_id: the VLAN we want to configurate. - Outputs: the information of the VLAN for the controller. - Work: Creates the configuration JSON for VLAN of the controller. - - ''' - configuracion_vlan=automatizacion.añadir_configuracion_VLAN(vlan_id) - return configuracion_vlan - - def packetDrop(self, drop, total,version,dev): - ''' - Inputs: - Outputs: the information of the packet drop configuration for the controller. - Work: Creates the configuration JSON for packet drop of the controller. - - ''' - configuracionPD=automatizacion.añadir_configuración_packetDrop(drop,total,version,dev) - return configuracionPD - - def policer(self,bandwidth): - ''' - Inputs: -bandwidth: the TX bandwdth we want to configurate. - Outputs: the information of the TX bandwidth for the controller. - Work: Creates the configuration JSON for the TX bandwidth of the controller. - - ''' - configuracion_policer=automatizacion.añadir_configuracion_policer(bandwidth) - return configuracion_policer - - def shaper(self): - ''' - Inputs: - Outputs: the information of the RX bandwidth for the controller. - Work: Creates the configuration JSON for the RX bandwidth of the controller. - - ''' - bandwidth=int(input('Introduzca el ancho de banda (Kbps): ')) - configuracion_policer=automatizacion.añadir_configuracion_shaper(bandwidth) - return configuracion_policer - - def packetReorder(self,reorder,packages=None, npackagesreorder=None, maxreord=None, version=None, stev=None): - print(f"\n\n\nNEII ANTES DEL PASO\nPACKAGES:{packages}\nREORDER:{reorder}\nMAXREORD:{maxreord}\nNPACKAGESORDER:{npackagesreorder}\n\n\n") - configuracion_reorder=automatizacion.añadir_configuracion_reorder(packages,reorder,npackagesreorder, maxreord, version, stev) - return configuracion_reorder - - def configuracion_total(self,configuraciones, nombre_perfil): - ''' - Inputs: -configuraciones: the informtion of all the configurations for the controller. - -nombre_perfil: the name of the profile where the information is going to be allocated. - Outputs: the information of a configurated profile. - Work: Creates the configuration JSON for a profile for the controller. - - ''' - perfil = { - 'tag': nombre_perfil, - 'dramAllocation': {}, - 'rules': [], - 'ethernetDelay': {'enabled': False}, - 'packetDrop': {'enabled': False}, - 'enabled':True - } - if 'ipv4' in configuraciones: - ipv4_config = configuraciones['ipv4'] - perfil['dramAllocation'] = ipv4_config['profiles'][0]['dramAllocation'] - perfil['rules'].extend(ipv4_config['profiles'][0]['rules']) - if 'ipv6' in configuraciones: - ipv6_config = configuraciones['ipv6'] - perfil['rules'].extend(ipv6_config['profiles'][0]['rules']) - if 'vlan' in configuraciones: - vlan_config = configuraciones['vlan'] - perfil['rules'].extend(vlan_config['profiles'][0]['rules']) - if 'ethernetDelay' in configuraciones: - perfil['ethernetDelay'] = configuraciones['ethernetDelay']['ethernetDelay'] - if 'packetDrop' in configuraciones: - perfil['packetDrop'] = configuraciones['packetDrop']['packetDrop'] - if 'policer' in configuraciones: - perfil['policer']=configuraciones['policer']['policer'] - if 'shaper' in configuraciones: - perfil['shaper']=configuraciones['shaper']['shaper'] - if 'reorder' in configuraciones: - perfil['reorder']=configuraciones['reorder']['reorder'] - return perfil - -if __name__=="__main__": - controller=NEII_controller() - controller.menu_principal() \ No newline at end of file diff --git a/src/realizers/ixia/automatizacion_ne2v4.py b/src/realizers/ixia/automatizacion_ne2v4.py deleted file mode 100644 index fd8fc4f5c7b5f093fc60963687d8564001eb224d..0000000000000000000000000000000000000000 --- a/src/realizers/ixia/automatizacion_ne2v4.py +++ /dev/null @@ -1,467 +0,0 @@ -# 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. - -# This file is an original contribution from Telefonica Innovación Digital S.L. - -import requests -class automatizacion: - def obtener_informacion_ip(ip): - ''' - Gets the information IP of the NE2 - Args: - ip: IP. - Returns: - A dictionary with the IP infotmationx. - ''' - url= "http://"+ip+"/api/actions/ipInfo" - body= {"ip": ip} - response = requests.get(url, json=body, auth=('admin', 'admin')) - if response.status_code==200: - return response.json() - else: - print(f"error al obtener la informacion de la IP; {response.status_code}") - return None - - def obtener_informacion_hardware(ip): - """ - Obtiene información de una dirección IP. - - Args: - ip: La dirección IP del NE2. - - Returns: - Un diccionario con la información de IP. - """ - url = "http://"+ip+"/api/actions/hwInfo" - body = {"ip": ip} - response = requests.get(url, json=body, auth=('admin', 'admin')) - if response.status_code == 200: - return response.json() - else: - print(f"Error al obtener la información de la IP: {response.status_code}") - return None - - def obtener_informacion_puerto(ip,puerto): - """ - Obtiene información de una dirección IP. - - Args: - ip: La dirección IP del NE2. - - Returns: - Un diccionario con la información de IP. - """ - url = "http://"+ip+"/api/hw/Port/"+puerto - body = {"ip": ip} - response = requests.get(url, json=body, auth=('admin', 'admin')) - if response.status_code == 200: - return response.json() - else: - print(f"Error al obtener la información de la IP: {response.status_code}") - return None - - def añadir_configuracion_puerto_delay(delay, latency_type, max_latency): - """ - Añade una configuración de puerto según su delay a un NE2. - - Args: - delay (int): Cantidad de delay en la simulación. - - Returns: - La respuesta de la API (texto). - """ - configuracion=None - print(f'\n\nTipo de latencia: {latency_type}\n latencia: {delay}\n') - if latency_type=='1' or latency_type==None: - configuracion={'ethernetDelay': {'delay': delay, 'delayMax': 15.0, 'isUncorrelated': False, 'maxNegDelta': 0.1, 'pdvMode': 'NONE', 'delayMin': 5.0, 'units': 'MS', 'maxPosDelta': 0.1, 'enabled': True, 'spread': 1.0}} - if latency_type=='2' or latency_type=='gauss': - delay_f=float(delay) - ancho=float(max_latency) - max_delay=delay_f+ancho - min_delay=delay_f-ancho - configuracion={'ethernetDelay': {'delay': delay, 'delayMax': max_delay, 'isUncorrelated': False,'maxNegDelta': ancho/3, 'pdvMode': 'GAUSSIAN', 'delayMin':min_delay, 'units': 'MS', 'maxPosDelta':ancho/3, 'enabled': True, 'spread': 1.58}} - if latency_type =='3' or latency_type=='internet': - ancho=float(max_latency) - max_delay = float(delay)+0.9*float(ancho) - min_delay = float(delay)-0.1*float(ancho) - configuracion={'ethernetDelay': {'delay': delay, 'delayMax': max_delay, 'isUncorrelated': False, 'maxNegDelta': 0.4, 'pdvMode': 'INTERNET', 'delayMin': min_delay, 'units': 'MS', 'maxPosDelta': 0.5, 'enabled': True, 'spread': 100.0}} - print(f"\n\nConf Delay: {configuracion}\n") - return configuracion - - def añadir_configuracion_puerto_ipv4(source_hx,destination_hx,protocolo): - """ - Añade una configuración de puerto según las IPv4s de origen y destino de la comunicación. - - Args: - source_hx (int): Dirección IPv4 de origen en hexadecimal. - destination_hx (int): Dirección IPv4 de destino en hexadecimal. - protocolo (string): Numero asociado al protocolo elegido. - - Returns: - La respuesta de la API (texto). - """ - reglas = [{"field": "Common::IPv4::Version", "value": "4", "mask": "f"}] - if source_hx: - reglas.append({"field": "Common::IPv4::Source Address", "value": source_hx, "mask": "ffffffff"}) - if destination_hx: - reglas.append({"field": "Common::IPv4::Destination Address", "value": destination_hx, "mask": "ffffffff"}) - if protocolo: - reglas.append({"field": "Common::IPv4::Protocol", "value": protocolo, "mask": "ff"}) - configuracion = {"profiles": [{"dramAllocation": {"mode": "AUTO","fixedSize": 1700352},"rules": reglas,"tag": "test_api"}],"defaultProfile": {"dramAllocation": {"mode": "AUTO","fixedSize": 1700352},"tag": "defaultProfile"}} - return configuracion - - def añadir_configuracion_puerto_ipv6(source,destination): - """ - Añade una configuración de puerto según las IPv6s de origen y destino de la comunicación. - - Args: - source (int): Dirección IPv6 de origen en hexadecimal. - destination (int): Dirección IPv6 de destino en hexadecimal. - - Returns: - La respuesta de la API (texto). - """ - reglas=[{'field': 'Common::IPv6::Version', 'bitRange': 'L3@0[7]+3', 'value': '6', 'mask': 'f'}] - if source: - reglas.append({'field': 'Common::IPv6::Source Address', 'bitRange': 'L3@8[7]+127', 'value': source, 'mask': 'ffffffffffffffffffffffffffffffff'}) - if destination: - reglas.append({'field': 'Common::IPv6::Destination Address', 'bitRange': 'L3@24[7]+127', 'value': destination, 'mask': 'ffffffffffffffffffffffffffffffff'}) - configuracion = {"profiles": [{"dramAllocation": {"mode": "AUTO","fixedSize": 1700352},"rules": reglas,"tag": "test_api"}],"defaultProfile": {"dramAllocation": {"mode": "AUTO","fixedSize": 1700352},"tag": "defaultProfile"}} - return configuracion - - def añadir_configuracion_VLAN(vlan): - """ - Añade una configuración de puerto según su VLAN. - - Args: - vlan (int): Número de identificación de la VLAN. - - Returns: - La respuesta de la API (texto). - """ - vlan=hex(vlan)[2:] - configuracion={'profiles': [{'dramAllocation': {'mode': 'AUTO', 'fixedSize': 1700352}, 'rules': [{'field': 'Common::Second Tag::VLAN ID', 'bitRange': 'L2@18[3]+11', 'value': vlan, 'mask': 'fff'}]}]} - return configuracion - - def añadir_configuración_packetDrop(drops,total): - """ - Añade una configuración de puerto según su configuracion de packet Drop un NE2. - - Args: - drops (int): cantidad de paquetes dropeados - total (int): cantidad total de paquetes - - Returns: - La respuesta de la API (texto). - """ - configuracion={'packetDrop': {'rdmSel': {'dist': 'PERIODIC', 'burstlen': drops, 'interval': total, 'stddev': 10.0}, 'enabled': True}} - return configuracion - - def añadir_configuracion_policer(bitrate): - """ - Añade una configuración de puerto según su TX bandwidth a un NE2. - - Args: - bitrate (int): bandwith en Tx - - Returns: - La respuesta de la API (texto). - """ - configuracion={'policer':{'excessBitRate': bitrate, 'excessBurstTolerance': 64000, 'commitedBurstTolerance': 64000, 'commitedBitRate': bitrate, 'enabled': True, 'enableRateCoupling': False}} - return configuracion - - def añadir_configuracion_shaper(bitrate): - """ - Añade una configuración de puerto según su RX bandwidth a un NE2. - - Args: - bitrate (int): bandwith en Rx - - Returns: - La respuesta de la API (texto). - """ - configuracion={'shaper': {'burstTolerance': 64000, 'bitRate': bitrate, 'enabled': True}} - return configuracion - - def añadir_configuracion_reorder(reorder): - """ - Adds reorder configuration. - - Args: - reorder (int): reorder - - Returns: - response of the API (texto). - """ - reorder=100-reorder - print(f"\nReorder:{reorder}\n") - configuracion={"reorder": {"rdmSel": {"dist": "PERIODIC", "burstlen": reorder, "interval": 100, "stddev": 10.0 }, "reorderByMin": 1, "reorderByMax": 5, "enabled": True}} #Los demas valores los he dejado como defecto por no poder configurarlos - return configuracion - - def envio_peticion(ip,puerto, configuracion): - """ - Envía una configuración de puerto a un NE2. - - Args: - ip (int): IP del NE2 - puerto: número del puerto a configurar - configuración: la información que se quiere configurar en el puerto - - Returns: - La respuesta de la API (texto). - """ - -import requests -class automatizacion: - def obtener_informacion_ip(ip): - ''' - obtiene informacion ip del NE2 - Args: - ip: la direccion IP del NE2. - - Returns: - un diccionario con la informacion de IP. - ''' - url= "http://"+ip+"/api/actions/ipInfo" - body= {"ip": ip} - response = requests.get(url, json=body, auth=('admin', 'admin')) - if response.status_code==200: - return response.json() - else: - print(f"error al obtener la informacion de la IP; {response.status_code}") - return None - - def obtener_informacion_hardware(ip): - """ - Obtiene información de una dirección IP. - - Args: - ip: La dirección IP del NE2. - - Returns: - Un diccionario con la información de IP. - """ - url = "http://"+ip+"/api/actions/hwInfo" - body = {"ip": ip} - response = requests.get(url, json=body, auth=('admin', 'admin')) - if response.status_code == 200: - return response.json() - else: - print(f"Error al obtener la información de la IP: {response.status_code}") - return None - - def obtener_informacion_puerto(ip,puerto): - """ - Obtiene información de una dirección IP. - - Args: - ip: La dirección IP del NE2. - - Returns: - Un diccionario con la información de IP. - """ - url = "http://"+ip+"/api/hw/Port/"+puerto - body = {"ip": ip} - response = requests.get(url, json=body, auth=('admin', 'admin')) - if response.status_code == 200: - return response.json() - else: - print(f"Error al obtener la información de la IP: {response.status_code}") - return None - - def añadir_configuracion_puerto_delay(delay, latency_type, max_latency): - """ - Añade una configuración de puerto según su delay a un NE2. - - Args: - delay (int): Cantidad de delay en la simulación. - - Returns: - La respuesta de la API (texto). - """ - configuracion=None - print(f'\n\nTipo de latencia: {latency_type}\n latencia: {delay}\n') - if latency_type=='1' or latency_type==None: - configuracion={'ethernetDelay': {'delay': delay, 'delayMax': 15.0, 'isUncorrelated': False, 'maxNegDelta': 0.1, 'pdvMode': 'NONE', 'delayMin': 5.0, 'units': 'MS', 'maxPosDelta': 0.1, 'enabled': True, 'spread': 1.0}} - if latency_type=='2' or latency_type=='gauss': - delay_f=float(delay) - ancho=float(max_latency) - max_delay=delay_f+ancho - min_delay=delay_f-ancho - configuracion={'ethernetDelay': {'delay': delay, 'delayMax': max_delay, 'isUncorrelated': False,'maxNegDelta': ancho/3, 'pdvMode': 'GAUSSIAN', 'delayMin':min_delay, 'units': 'MS', 'maxPosDelta':ancho/3, 'enabled': True, 'spread': 1.58}} - if latency_type =='3' or latency_type=='internet': - ancho=float(max_latency) - max_delay = float(delay)+0.9*float(ancho) - min_delay = float(delay)-0.1*float(ancho) - configuracion={'ethernetDelay': {'delay': delay, 'delayMax': max_delay, 'isUncorrelated': False, 'maxNegDelta': 0.4, 'pdvMode': 'INTERNET', 'delayMin': min_delay, 'units': 'MS', 'maxPosDelta': 0.5, 'enabled': True, 'spread': 100.0}} - print(f"\n\nConf Delay: {configuracion}\n") - return configuracion - - def añadir_configuracion_puerto_ipv4(source_hx,destination_hx,protocolo): - """ - Añade una configuración de puerto según las IPv4s de origen y destino de la comunicación. - - Args: - source_hx (int): Dirección IPv4 de origen en hexadecimal. - destination_hx (int): Dirección IPv4 de destino en hexadecimal. - protocolo (string): Numero asociado al protocolo elegido. - - Returns: - La respuesta de la API (texto). - """ - reglas = [{"field": "Common::IPv4::Version", "value": "4", "mask": "f"}] - if source_hx: - reglas.append({"field": "Common::IPv4::Source Address", "value": source_hx, "mask": "ffffffff"}) - if destination_hx: - reglas.append({"field": "Common::IPv4::Destination Address", "value": destination_hx, "mask": "ffffffff"}) - if protocolo: - reglas.append({"field": "Common::IPv4::Protocol", "value": protocolo, "mask": "ff"}) - configuracion = {"profiles": [{"dramAllocation": {"mode": "AUTO","fixedSize": 1700352},"rules": reglas,"tag": "test_api"}],"defaultProfile": {"dramAllocation": {"mode": "AUTO","fixedSize": 1700352},"tag": "defaultProfile"}} - return configuracion - - def añadir_configuracion_puerto_ipv6(source,destination): - """ - Añade una configuración de puerto según las IPv6s de origen y destino de la comunicación. - - Args: - source (int): Dirección IPv6 de origen en hexadecimal. - destination (int): Dirección IPv6 de destino en hexadecimal. - - Returns: - La respuesta de la API (texto). - """ - reglas=[{'field': 'Common::IPv6::Version', 'bitRange': 'L3@0[7]+3', 'value': '6', 'mask': 'f'}] - if source: - reglas.append({'field': 'Common::IPv6::Source Address', 'bitRange': 'L3@8[7]+127', 'value': source, 'mask': 'ffffffffffffffffffffffffffffffff'}) - if destination: - reglas.append({'field': 'Common::IPv6::Destination Address', 'bitRange': 'L3@24[7]+127', 'value': destination, 'mask': 'ffffffffffffffffffffffffffffffff'}) - configuracion = {"profiles": [{"dramAllocation": {"mode": "AUTO","fixedSize": 1700352},"rules": reglas,"tag": "test_api"}],"defaultProfile": {"dramAllocation": {"mode": "AUTO","fixedSize": 1700352},"tag": "defaultProfile"}} - return configuracion - - def añadir_configuracion_VLAN(vlan): - """ - Añade una configuración de puerto según su VLAN. - - Args: - vlan (int): Número de identificación de la VLAN. - - Returns: - La respuesta de la API (texto). - """ - vlan=hex(vlan)[2:] - configuracion={'profiles': [{'dramAllocation': {'mode': 'AUTO', 'fixedSize': 1700352}, 'rules': [{'field': 'Common::Second Tag::VLAN ID', 'bitRange': 'L2@18[3]+11', 'value': vlan, 'mask': 'fff'}]}]} - return configuracion - - def añadir_configuración_packetDrop(drops,total,version,desv): - """ - Añade una configuración de puerto según su configuracion de packet Drop un NE2. - - Args: - drops (int): cantidad de paquetes dropeados - total (int): cantidad total de paquetes - version (string): version of the probability - - Returns: - La respuesta de la API (texto). - """ - if version != "GAUSSIAN" and version !="POISSON": - configuracion={'packetDrop': {'rdmSel': {'dist': version, 'burstlen': drops, 'interval': total, 'stddev': 10.0}, 'enabled': True}} - else: - configuracion={'packetDrop': {'rdmSel': {'dist': version, 'burstlen': drops, 'interval': total, 'stddev': desv}, 'enabled': True}} - return configuracion - - def añadir_configuracion_policer(bitrate): - """ - Añade una configuración de puerto según su TX bandwidth a un NE2. - - Args: - bitrate (int): bandwith en Tx - - Returns: - La respuesta de la API (texto). - """ - configuracion={'policer':{'excessBitRate': bitrate, 'excessBurstTolerance': 64000, 'commitedBurstTolerance': 64000, 'commitedBitRate': bitrate, 'enabled': True, 'enableRateCoupling': False}} - return configuracion - - def añadir_configuracion_shaper(bitrate): - """ - Añade una configuración de puerto según su RX bandwidth a un NE2. - - Args: - bitrate (int): bandwith en Rx - - Returns: - La respuesta de la API (texto). - """ - configuracion={'shaper': {'burstTolerance': 64000, 'bitRate': bitrate, 'enabled': True}} - return configuracion - - def añadir_configuracion_reorder(packages,reorder,npackagesreorder, maxreord, version, stev): - """ - Adds reorder configuration. - - Args: - packages: number of packages total - reorder: number of packages to reorder - npackagesreorder: number of packages of reorder - maxreord: total number of packages of reorder - version: version of reorder - stev: desviation - - Returns: - response of the API (text). - """ - if packages is not None and npackagesreorder is not None and maxreord is not None: - reorderByMin = min(npackagesreorder, maxreord) - reorderByMax = max(npackagesreorder, maxreord) - if version != 'GAUSSIAN': - configuracion={"reorder": {"rdmSel": {"dist": version, "burstlen": reorder, "interval": packages, "stddev": 10.0 }, "reorderByMin": reorderByMin, "reorderByMax": reorderByMax, "enabled": True}} - else: - configuracion={"reorder": {"rdmSel": {"dist": "GAUSSIAN", "burstlen": reorder, "interval": packages, "stddev": stev }, "reorderByMin": reorderByMin, "reorderByMax": reorderByMax, "enabled": True}} - if int(reorder) <= 0: - configuracion["filterWarning"] = "El valor de reorder es inválido, está fuera del rango permitido." - else: - reorder=10000-reorder - configuracion={"reorder": {"rdmSel": {"dist": "PERIODIC", "burstlen": int(reorder/100), "interval": 100, "stddev": 10.0 }, "reorderByMin": 1, "reorderByMax": 5, "enabled": True}} - return configuracion - - def envio_peticion(ip,puerto, configuracion): - """ - Envía una configuración de puerto a un NE2. - - Args: - ip (int): IP del NE2 - puerto: número del puerto a configurar - configuración: la información que se quiere configurar en el puerto - - Returns: - La respuesta de la API (texto). - """ - print(f'\nCONFIGURACION\n{configuracion}') - url = f"http://{ip}/api/hw/Port/{puerto}" - response = requests.put(url, json=configuracion, auth=('admin', 'admin')) - - if response.status_code == 200: - print(f'\n{configuracion}') - return response.text - else: - try: - error_info = response.json() - except ValueError: - error_info = response.text - - print(f"\n\nError al añadir configuración de puerto: {response.status_code}") - print(f"Mensaje de error: {error_info}") - print(f"Configuración enviada: {configuracion}\n\n") - return None \ No newline at end of file diff --git a/src/templates/3gpp_template_example.json b/src/templates/3gpp_template_example.json new file mode 100644 index 0000000000000000000000000000000000000000..28471a8b2026b00c6d60222e8a9943290c6bc45a --- /dev/null +++ b/src/templates/3gpp_template_example.json @@ -0,0 +1,187 @@ +{ + "NetworkSlice1": { + "operationalState": "", + "administrativeState": "", + "serviceProfileList": [], + "networkSliceSubnetRef": "TopSliceSubnet1" + }, + "TopSliceSubnet1": { + "operationalState": "", + "administrativeState": "", + "nsInfo": {}, + "managedFunctionRef": [], + "networkSliceSubnetType": "TOP_SLICESUBNET", + "SliceProfileList": [ + { + "sliceProfileId": "TopId", + "pLMNInfoList": null, + "TopSliceSubnetProfile": { + "dLThptPerSliceSubnet": { + "GuaThpt": 200, + "MaxThpt": 400 + }, + "uLThptPerSliceSubnet": { + "GuaThpt": 200, + "MaxThpt": 400 + }, + "dLLatency": 20, + "uLLatency": 20 + } + } + ], + "networkSliceSubnetRef": [ + "CNSliceSubnet1", + "RANSliceSubnet1" + ] + }, + "CNSliceSubnet1": { + "operationalState": "", + "administrativeState": "", + "nsInfo": {}, + "managedFunctionRef": [], + "networkSliceSubnetType": "CN_SLICESUBNET", + "SliceProfileList": [ + { + "sliceProfileId": "CNId", + "pLMNInfoList": null, + "CNSliceSubnetProfile": { + "dLThptPerSliceSubnet": { + "GuaThpt": 100, + "MaxThpt": 200 + }, + "uLThptPerSliceSubnet": { + "GuaThpt": 100, + "MaxThpt": 200 + }, + "dLLatency": 8, + "uLLatency": 8 + } + } + ] + }, + "RANSliceSubnet1": { + "operationalState": "", + "administrativeState": "", + "nsInfo": {}, + "managedFunctionRef": [], + "networkSliceSubnetType": "RAN_SLICESUBNET", + "SliceProfileList": [ + { + "sliceProfileId": "RANId", + "pLMNInfoList": null, + "RANSliceSubnetProfile": { + "dLThptPerSliceSubnet": { + "GuaThpt": 100, + "MaxThpt": 200 + }, + "uLThptPerSliceSubnet": { + "GuaThpt": 100, + "MaxThpt": 200 + }, + "dLLatency": 12, + "uLLatency": 12 + } + } + ], + "networkSliceSubnetRef": [ + "MidhaulSliceSubnet1", + "BackhaulSliceSubnet1" + ] + }, + "MidhaulSliceSubnet1": { + "operationalState": "", + "administrativeState": "", + "nsInfo": {}, + "managedFunctionRef": [], + "networkSliceSubnetType": "RAN_SLICESUBNET", + "SliceProfileList": [ + { + "sliceProfileId": "MidhaulId", + "pLMNInfoList": null, + "RANSliceSubnetProfile": { + "dLThptPerSliceSubnet": { + "GuaThpt": 60, + "MaxThpt": 120 + }, + "uLThptPerSliceSubnet": { + "GuaThpt": 60, + "MaxThpt": 120 + }, + "dLLatency": 4, + "uLLatency": 4 + } + } + ], + "EpTransport": [ + "EpTransport CU-UP1", + "EpTransport DU3" + ] + }, + "BackhaulSliceSubnet1": { + "operationalState": "", + "administrativeState": "", + "nsInfo": {}, + "managedFunctionRef": [], + "networkSliceSubnetType": "RAN_SLICESUBNET", + "SliceProfileList": [ + { + "sliceProfileId": "BackhaulId", + "pLMNInfoList": null, + "RANSliceSubnetProfile": { + "dLThptPerSliceSubnet": { + "GuaThpt": 40, + "MaxThpt": 80 + }, + "uLThptPerSliceSubnet": { + "GuaThpt": 40, + "MaxThpt": 80 + }, + "dLLatency": 8, + "uLLatency": 8 + } + } + ], + "EpTransport": [ + "EpTransport CU-UP2", + "EpTransport UPF" + ] + }, + "EpTransport CU-UP1": { + "IpAddress": "100.1.1.1", + "logicalInterfaceInfo": { + "logicalInterfaceType": "VLAN", + "logicalInterfaceId": "300" + }, + "NextHopInfo": "100.1.1.254", + "qosProfile": "5QI100", + "EpApplicationRef": [ + "EP_F1U CU-UP1" + ] + }, + "EP_F1U CU-UP1": { + "localAddress": "100.1.1.2", + "remoteAddress": "1.1.3.2", + "epTransportRef": [ + "EpTransport CU-UP1" + ] + }, + "EpTransport DU3": { + "IpAddress": "1.1.3.1", + "logicalInterfaceInfo": { + "logicalInterfaceType": "VLAN", + "logicalInterfaceId": "300" + }, + "NextHopInfo": "1.1.3.254", + "qosProfile": "5QI100", + "EpApplicationRef": [ + "EP_F1U DU3" + ] + }, + "EP_F1U DU3": { + "localAddress": "1.1.3.2", + "remoteAddress": "100.1.1.2", + "epTransportRef": [ + "EpTransport DU3" + ] + } +} \ No newline at end of file diff --git a/src/templates/3gpp_template_filled.json b/src/templates/3gpp_template_filled.json new file mode 100644 index 0000000000000000000000000000000000000000..dcab03aa3d095fd133fbddbac12c3621ddb481ee --- /dev/null +++ b/src/templates/3gpp_template_filled.json @@ -0,0 +1,182 @@ +{ + "NetworkSlice1":{ + "operationalState":"", + "administrativeState":"", + "serviceProfileList":[ // Requisitos generales de una NetworkSlice. Lo suponemos vacío. The attributes in ServiceProfile represent mapped requirements from an Network Slice Customer (e.g. an enterprise) to an Network Slice Provider + //{ + // "serviceProfileId":"", + // "pLMNInfoList": null, //It defines which PLMN and S-NSSAI combinations that are assigned for the service to satisfy service requirements represented by the ServiceProfile + // "sST":"2" // 1 (eMBB), 2(URLLC), 3(MIoT), 4(V2X) o 5(HMTC) + //} + ], + "networkSliceSubnetRef":"TopSliceSubnet1" //Es un DN (string) + }, + "TopSliceSubnet1":{ + "operationalState":"", + "administrativeState":"", + "nsInfo":{}, // Se usa si la slice está en un entorno virtualizado + "managedFunctionRef":[], // ??? Es un DNList (array de strings) + "networkSliceSubnetType":"TOP_SLICESUBNET", + "SliceProfileList":[ // Requisitos de una NetworkSliceSubnet, la cual representa un conjunto de funciones de red agrupadas. + { + "sliceProfileId":"TopId", + "pLMNInfoList":null, + "TopSliceSubnetProfile":{ //Condition: It shall be present when the slice profile is for top/root network slice subnet + "dLThptPerSliceSubnet":{ //kbps + "GuaThpt":1000, + "MaxThpt":2000 + }, + "uLThptPerSliceSubnet":{ + "GuaThpt":1000, + "MaxThpt":2000 + }, + "dLLatency":5, //ms + "uLLatency":5 + } + } + ], + "networkSliceSubnetRef":["CNSliceSubnet1","RANSliceSubnet1"] + }, + "CNSliceSubnet1":{ + "operationalState":"", + "administrativeState":"", + "nsInfo":{}, // Se usa si la slice está en un entorno virtualizado + "managedFunctionRef":[], // ??? Es un DNList (array de strings) + "networkSliceSubnetType":"CN_SLICESUBNET", + "SliceProfileList":[ // Requisitos de una NetworkSliceSubnet, la cual representa un conjunto de funciones de red agrupadas. Los requisitos de transporte se representan aquí + { + "sliceProfileId":"CNId", + "pLMNInfoList":null, + "CNSliceSubnetProfile":{ + "dLThptPerSliceSubnet":{ + "GuaThpt":500, + "MaxThpt":1000 + }, + "uLThptPerSliceSubnet":{ + "GuaThpt":500, + "MaxThpt":1000 + }, + "dLLatency":2, + "uLLatency":2 + } + } + ] + }, + "RANSliceSubnet1":{ + "operationalState":"", + "administrativeState":"", + "nsInfo":{}, // Se usa si la slice está en un entorno virtualizado + "managedFunctionRef":[], // ??? Es un DNList (array de strings) + "networkSliceSubnetType":"RAN_SLICESUBNET", + "SliceProfileList":[ // Requisitos de una NetworkSliceSubnet, la cual representa un conjunto de funciones de red agrupadas. Los requisitos de transporte se representan aquí + { + "sliceProfileId":"RANId", + "pLMNInfoList":null, + "RANSliceSubnetProfile":{ + "dLThptPerSliceSubnet":{ + "GuaThpt":500, + "MaxThpt":1000 + }, + "uLThptPerSliceSubnet":{ + "GuaThpt":500, + "MaxThpt":1000 + }, + "dLLatency":3, + "uLLatency":3 + } + } + ], + "networkSliceSubnetRef":["MidhaulSliceSubnet1", "BackhaulSliceSubnet1"] + }, + "MidhaulSliceSubnet1":{ + "operationalState":"", + "administrativeState":"", + "nsInfo":{}, // Se usa si la slice está en un entorno virtualizado + "managedFunctionRef":[], // ??? Es un DNList (array de strings), + "networkSliceSubnetType":"RAN_SLICESUBNET", + "SliceProfileList":[ // Requisitos de una NetworkSliceSubnet, la cual representa un conjunto de funciones de red agrupadas. Los requisitos de transporte se representan aquí + { + "sliceProfileId":"MidhaulId", + "pLMNInfoList":null, + "RANSliceSubnetProfile":{ + "dLThptPerSliceSubnet":{ + "GuaThpt":300, + "MaxThpt":600 + }, + "uLThptPerSliceSubnet":{ + "GuaThpt":300, + "MaxThpt":600 + }, + "dLLatency":1, + "uLLatency":1 + } + } + ], + "EpTransport":["EpTransport DU1","EpTransport CU-UP1"] // Es un DNList (array de strings) + }, + "BackhaulSliceSubnet1":{ + "operationalState":"", + "administrativeState":"", + "nsInfo":{}, // Se usa si la slice está en un entorno virtualizado + "managedFunctionRef":[], // ??? Es un DNList (array de strings), + "networkSliceSubnetType":"RAN_SLICESUBNET", + "SliceProfileList":[ // Requisitos de una NetworkSliceSubnet, la cual representa un conjunto de funciones de red agrupadas. Los requisitos de transporte se representan aquí + { + "sliceProfileId":"BackhaulId", + "pLMNInfoList":null, + "RANSliceSubnetProfile":{ + "dLThptPerSliceSubnet":{ + "GuaThpt":200, + "MaxThpt":400 + }, + "uLThptPerSliceSubnet":{ + "GuaThpt":200, + "MaxThpt":400 + }, + "dLLatency":2, + "uLLatency":2 + } + } + ], + "EpTransport":["EpTransport CU-UP2","EpTransport UPF"] // Es un DNList (array de strings) + }, + "EpTransport DU1": + { + "IpAddress":"100.1.1.1", + "logicalInterfaceInfo":{ + "logicalInterfaceType":"VLAN", //VLAN, MPLS o Segment + "logicalInterfaceId":"100" + }, + "NextHopInfo": "100.1.1.254", + "qosProfile":"5QI100", //Revisar el mapeo de los requisitos de la slice con esto + "EpApplicationRef":["EP_F1U DU1"] //Es un DNList (array de string) + }, + "EpTransport CU-UP1": + { + "IpAddress":"1.1.1.1", + "logicalInterfaceInfo":{ + "logicalInterfaceType":"VLAN", //VLAN, MPLS o Segment + "logicalInterfaceId":"100" + }, + "NextHopInfo": "1.1.1.254", + "QosProfile":"5QI100", + "EpApplicationRef":["EP_F1U CU-UP1"] //Es un DNList (array de string) + }, + "EP_F1U DU1":[ // El 3GPP parece que aun no ha definido las interfaces entre los distinos functional splits, por lo que estos objetos no están claros. Suponemos EP_F1U para todo, que es el que se usa para la interfaz F1-U entre gNB-DU y gNB-CU + { + "localAddress":"100.1.1.2", + "remoteAddress":"1.1.1.2", + "epTransportRef":["EpTransport DU1"] //Es un DNList (array de string) + } + ], + "EP_F1U CU-UP1":[ //Otras opciones son EP_N3 (interfaz N3 entre RAN y UPF) y EP_NgU (interfaz NG-U entre gNB y UPF) + { + "localAddress":"1.1.1.2", + "remoteAddress":"100.1.1.2", + "epTransportRef":["EpTransport CU-UP1"] //Es un DNList (array de string) + } + ] +} + + + diff --git a/src/templates/L2-VPN_template_empty.json b/src/templates/L2-VPN_template_empty.json index 9c2137c7c72479792e0c3608e6781e521f33550d..85caed08d492bff56396c2e2e87b5098dee84209 100644 --- a/src/templates/L2-VPN_template_empty.json +++ b/src/templates/L2-VPN_template_empty.json @@ -12,6 +12,8 @@ {"device_id": {"device_uuid": {"uuid": ""}}, "endpoint_uuid": {"uuid": "eth-1/0/21"}} ], "service_constraints": [ + {"custom": {"constraint_type": "bandwidth[kbps]", "constraint_value": "0"}}, + {"custom": {"constraint_type": "latency[ms]", "constraint_value": "0"}} ], "service_config": {"config_rules": [ {"action": 1, "custom": {"resource_key": "/settings", "resource_value": { diff --git a/src/templates/L2-VPN_template_example.json b/src/templates/L2-VPN_template_example.json new file mode 100644 index 0000000000000000000000000000000000000000..b29e3c69911c332fa5bac045f0f2b994008d629f --- /dev/null +++ b/src/templates/L2-VPN_template_example.json @@ -0,0 +1,271 @@ +{ + "services": [ + { + "service_id": { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + }, + "service_uuid": { + "uuid": "l2-acl-svc-17429923732568250" + } + }, + "service_type": 2, + "service_status": { + "service_status": 1 + }, + "service_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "4.4.4.4" + } + }, + "endpoint_uuid": { + "uuid": "0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "5.5.5.5" + } + }, + "endpoint_uuid": { + "uuid": "0/0/3-GigabitEthernet0/0/0/3" + } + } + ], + "service_constraints": [ + { + "custom": { + "constraint_type": "bandwidth[kbps]", + "constraint_value": "20" + } + }, + { + "custom": { + "constraint_type": "latency[ms]", + "constraint_value": "20" + } + } + ], + "service_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "/settings", + "resource_value": {} + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[4.4.4.4]/endpoint[0/0/0-GigabitEthernet0/0/0/0]/settings", + "resource_value": { + "sub_interface_index": 0, + "vlan_id": 100, + "circuit_id": "100", + "remote_router": "5.5.5.5", + "ni_name": "ELAN100" + } + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[5.5.5.5]/endpoint[0/0/3-GigabitEthernet0/0/0/3]/settings", + "resource_value": { + "sub_interface_index": 0, + "vlan_id": 100, + "circuit_id": "100", + "remote_router": "4.4.4.4", + "ni_name": "ELAN100" + } + } + } + ] + } + }, + { + "service_id": { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + }, + "service_uuid": { + "uuid": "l2-acl-svc-17429923733224160" + } + }, + "service_type": 2, + "service_status": { + "service_status": 1 + }, + "service_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "4.4.4.4" + } + }, + "endpoint_uuid": { + "uuid": "0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "5.5.5.5" + } + }, + "endpoint_uuid": { + "uuid": "0/0/3-GigabitEthernet0/0/0/3" + } + } + ], + "service_constraints": [ + { + "custom": { + "constraint_type": "bandwidth[kbps]", + "constraint_value": "200" + } + }, + { + "custom": { + "constraint_type": "latency[ms]", + "constraint_value": "5" + } + } + ], + "service_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "/settings", + "resource_value": {} + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[4.4.4.4]/endpoint[0/0/0-GigabitEthernet0/0/0/0]/settings", + "resource_value": { + "sub_interface_index": 0, + "vlan_id": 101, + "circuit_id": "101", + "remote_router": "5.5.5.5", + "ni_name": "ELAN101" + } + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[5.5.5.5]/endpoint[0/0/3-GigabitEthernet0/0/0/3]/settings", + "resource_value": { + "sub_interface_index": 0, + "vlan_id": 101, + "circuit_id": "101", + "remote_router": "4.4.4.4", + "ni_name": "ELAN101" + } + } + } + ] + } + }, + { + "service_id": { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + }, + "service_uuid": { + "uuid": "l2-acl-svc-17429923733753200" + } + }, + "service_type": 2, + "service_status": { + "service_status": 1 + }, + "service_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "4.4.4.4" + } + }, + "endpoint_uuid": { + "uuid": "0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "5.5.5.5" + } + }, + "endpoint_uuid": { + "uuid": "0/0/3-GigabitEthernet0/0/0/3" + } + } + ], + "service_constraints": [ + { + "custom": { + "constraint_type": "bandwidth[kbps]", + "constraint_value": "200" + } + }, + { + "custom": { + "constraint_type": "latency[ms]", + "constraint_value": "10" + } + } + ], + "service_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "/settings", + "resource_value": {} + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[4.4.4.4]/endpoint[0/0/0-GigabitEthernet0/0/0/0]/settings", + "resource_value": { + "sub_interface_index": 0, + "vlan_id": 102, + "circuit_id": "102", + "remote_router": "5.5.5.5", + "ni_name": "ELAN102" + } + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[5.5.5.5]/endpoint[0/0/3-GigabitEthernet0/0/0/3]/settings", + "resource_value": { + "sub_interface_index": 0, + "vlan_id": 102, + "circuit_id": "102", + "remote_router": "4.4.4.4", + "ni_name": "ELAN102" + } + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/templates/L2-VPN_template_filled.json b/src/templates/L2-VPN_template_filled.json new file mode 100644 index 0000000000000000000000000000000000000000..594fc27321d4628b7f1fb3cf803063eceb228b7f --- /dev/null +++ b/src/templates/L2-VPN_template_filled.json @@ -0,0 +1,36 @@ +{ + "services": [ + { + "service_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, //Siempre usaremos admin + "service_uuid": {"uuid": "l2-acl-svc"} //identificador unico + }, + "service_type": 2, // Numero que identifica que es una vpn de nivel 2, se mantiene + "service_status": {"service_status": 1}, + "service_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R149"}}, "endpoint_uuid": {"uuid": "eth-1/0/21"}}, // Se tiene que cambiar por el endpoint de origen + {"device_id": {"device_uuid": {"uuid": "R155"}}, "endpoint_uuid": {"uuid": "eth-1/0/21"}} // Se tiene que cambiar por el endpoint de destino + ], + "service_constraints": [ //Requerimientos que han de darse, de momento no funciona por lo que mantener igual + {"custom": {"constraint_type": "bandwidth[kbps]", "constraint_value": "10.0"}}, + {"custom": {"constraint_type": "latency[ms]", "constraint_value": "15.2"}} + ], + "service_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "/settings", "resource_value": { //Regla default, se mantiene + }}}, + {"action": 1, "custom": {"resource_key": "/device[R149]/endpoint[eth-1/0/21]/settings", "resource_value": { //Camino de ida, hay que cambiar la vlan, circuit_id y sub_interface_index por el valor de vlan que queramos usar + "sub_interface_index": 0, + "vlan_id": 999, + "circuit_id": "999", + "remote_router":"5.5.5.1" // Este valor es la ip del router en el otro extremo + }}}, + {"action": 1, "custom": {"resource_key": "/device[R155]/endpoint[eth-1/0/21]/settings", "resource_value": { //Camino de vuelta, hay que cambiar la vlan, circuit_id y sub_interface_index por el valor de vlan que queramos usar + "sub_interface_index": 0, + "vlan_id": 999, + "circuit_id": "999", + "remote_router":"5.5.5.5" // Este valor es la ip del router en el otro extremo + }}} + ]} + } + ] +} \ No newline at end of file diff --git a/src/templates/L3-VPN_template_empty.json b/src/templates/L3-VPN_template_empty.json index 41d1f1bf6562bbf1530df77883978199cb6d9f91..e894cfa4208734dc75c822ced467b7aa8e7d67a9 100644 --- a/src/templates/L3-VPN_template_empty.json +++ b/src/templates/L3-VPN_template_empty.json @@ -12,6 +12,8 @@ {"device_id": {"device_uuid": {"uuid": ""}}, "endpoint_uuid": {"uuid": ""}} ], "service_constraints": [ + {"custom": {"constraint_type": "bandwidth[kbps]", "constraint_value": "0"}}, + {"custom": {"constraint_type": "latency[ms]", "constraint_value": "0"}} ], "service_config": {"config_rules": [ {"action": 1, "custom": {"resource_key": "/settings", "resource_value": { diff --git a/src/templates/L3-VPN_template_example.json b/src/templates/L3-VPN_template_example.json new file mode 100644 index 0000000000000000000000000000000000000000..d0a70b7d738121afb27c9ad0cad178fb797d6193 --- /dev/null +++ b/src/templates/L3-VPN_template_example.json @@ -0,0 +1,102 @@ +{ + "services": [ + { + "service_id": { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + }, + "service_uuid": { + "uuid": "l3-acl-svc-17258860855224490" + } + }, + "service_type": 1, + "service_status": { + "service_status": 1 + }, + "service_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "4.4.4.4" + } + }, + "endpoint_uuid": { + "uuid": "0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "5.5.5.5" + } + }, + "endpoint_uuid": { + "uuid": "0/0/1-GigabitEthernet0/0/0/1" + } + } + ], + "service_constraints": [ + { + "custom": { + "constraint_type": "bandwidth[kbps]", + "constraint_value": "120" + } + }, + { + "custom": { + "constraint_type": "latency[ms]", + "constraint_value": "2" + } + } + ], + "service_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "/settings", + "resource_value": { + "bgp_as": 65000, + "route_distinguisher": "65000:533" + } + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[4.4.4.4]/endpoint[0/0/1-GigabitEthernet0/0/0/1]/settings", + "resource_value": { + "router_id": "5.5.5.5", + "sub_interface_index": 0, + "vlan_id": 300, + "address_ip": "5.5.5.5", + "address_prefix": 16, + "policy_AZ": "policyA", + "policy_ZA": "policyB", + "ni_name": "ELAN300" + } + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[5.5.5.5]/endpoint[0/0/1-GigabitEthernet0/0/0/1]/settings", + "resource_value": { + "router_id": "4.4.4.4", + "sub_interface_index": 0, + "vlan_id": 300, + "address_ip": "4.4.4.4", + "address_prefix": 16, + "policy_AZ": "policyA", + "policy_ZA": "policyB", + "ni_name": "ELAN300" + } + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/src/templates/L3-VPN_template_filled.json b/src/templates/L3-VPN_template_filled.json new file mode 100644 index 0000000000000000000000000000000000000000..12bea2aa922a55b17d5906cc03032ac9c5bdba42 --- /dev/null +++ b/src/templates/L3-VPN_template_filled.json @@ -0,0 +1,44 @@ +{ + "servs": [ + { + "service_id": { + "context_id": {"context_uuid": {"uuid": "admin"}}, //Siempre usaremos admin + "service_uuid": {"uuid": "l3-svc"} //identificador unico + }, + "service_type": 1, // Numero que identifica que es una vpn de nivel 3, se mantiene + "service_status": {"service_status": 1}, + "service_endpoint_ids": [ + {"device_id": {"device_uuid": {"uuid": "R149"}}, "endpoint_uuid": {"uuid": "eth-1/0/20"}}, // Se tiene que cambiar por el endpoint de origen + {"device_id": {"device_uuid": {"uuid": "R155"}}, "endpoint_uuid": {"uuid": "eth-1/0/20"}} // Se tiene que cambiar por el endpoint de destino + ], + "service_constraints": [ // Requerimientos que han de darse, de momento no funciona por lo que mantener igual + {"custom": {"constraint_type": "bandwidth[gbps]", "constraint_value": "10.0"}}, + {"custom": {"constraint_type": "latency[ms]", "constraint_value": "15.2"}} + ], + "service_config": {"config_rules": [ + {"action": 1, "custom": {"resource_key": "/settings", "resource_value": { //Regla default, se mantiene + "bgp_as" : 65000, + "route_distinguisher": "65000:533" + }}}, + {"action": 1, "custom": {"resource_key": "/device[R149]/endpoint[eth-1/0/20]/settings", "resource_value": { + "router_id" : "5.5.5.5", + "sub_interface_index": 0, + "vlan_id" : 533, + "address_ip" : "172.16.12.12", + "address_prefix" : 16, + "policy_AZ" : "srv_ACL", + "policy_ZA" : "srv_ACLr" + }}}, + {"action": 1, "custom": {"resource_key": "/device[R155]/endpoint[eth-1/0/20]/settings", "resource_value": { + "router_id" : "5.5.5.1", + "sub_interface_index": 0, + "vlan_id" : 533, + "address_ip" : "172.16.13.13", + "address_prefix" : 16, + "policy_AZ" : "srv_ACLr", + "policy_ZA" : "srv_ACL" + }}} + ]} + } + ] +} \ No newline at end of file diff --git a/src/templates/descriptor-topology copy.json b/src/templates/descriptor-topology copy.json new file mode 100644 index 0000000000000000000000000000000000000000..304373aceb7a48ac4898c361833d46e21590d04b --- /dev/null +++ b/src/templates/descriptor-topology copy.json @@ -0,0 +1,570 @@ +{ + "dummy_mode": true, + "contexts":[ + { + "context_id":{ + "context_uuid":{ + "uuid":"admin" + } + }, + "topology_ids":[ + + ], + "service_ids":[ + + ] + } + ], + "topologies":[ + { + "topology_id":{ + "context_id":{ + "context_uuid":{ + "uuid":"admin" + } + }, + "topology_uuid":{ + "uuid":"admin" + } + }, + "device_ids":[ + { + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + { + "device_uuid":{ + "uuid":"2.2.2.2" + } + } + ], + "link_ids":[ + { + "link_uuid":{ + "uuid":"4.4.4.4/0/0/1-GigabitEthernet0/0/0/1==2.2.2.2/GigabitEthernet2" + } + }, + { + "link_uuid":{ + "uuid":"2.2.2.2/GigabitEthernet2==4.4.4.4/0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "link_uuid":{ + "uuid":"2.2.2.2/GigabitEthernet1==1.1.1.1/GigabitEthernet1" + } + }, + { + "link_uuid":{ + "uuid":"1.1.1.1/GigabitEthernet1==2.2.2.2/GigabitEthernet1" + } + }, + { + "link_uuid":{ + "uuid":"2.2.2.2/GigabitEthernet4==5.5.5.5/0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "link_uuid":{ + "uuid":"5.5.5.5/0/0/0-GigabitEthernet0/0/0/0==2.2.2.2/GigabitEthernet4" + } + }, + { + "link_uuid":{ + "uuid":"2.2.2.2/GigabitEthernet3==3.3.3.3/0/0/3-GigabitEthernet0/0/0/3" + } + }, + { + "link_uuid":{ + "uuid":"3.3.3.3/0/0/3-GigabitEthernet0/0/0/3==2.2.2.2/GigabitEthernet3" + } + }, + { + "link_uuid":{ + "uuid":"1.1.1.1/GigabitEthernet2==5.5.5.5/0/0/2-GigabitEthernet0/0/0/2" + } + }, + { + "link_uuid":{ + "uuid":"5.5.5.5/0/0/2-GigabitEthernet0/0/0/2==1.1.1.1/GigabitEthernet2" + } + } + ] + } + ], + "devices":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.60.125.41" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + }, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet1]", "resource_value": { + "uuid": "GigabitEthernet1", "name": "GigabitEthernet1", "type": "-" + }}}, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet2]", "resource_value": { + "uuid": "GigabitEthernet2", "name": "GigabitEthernet2", "type": "-" + }}}, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet3]", "resource_value": { + "uuid": "GigabitEthernet3", "name": "GigabitEthernet3", "type": "-" + }}}, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet4]", "resource_value": { + "uuid": "GigabitEthernet4", "name": "GigabitEthernet4", "type": "-" + }}}, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet5]", "resource_value": { + "uuid": "GigabitEthernet5", "name": "GigabitEthernet5", "type": "-" + }}} + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + {"name": "GigabitEthernet1", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "1.1.1.1"}}, "endpoint_uuid": {"uuid": "GigabitEthernet1"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"name": "GigabitEthernet2", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "1.1.1.1"}}, "endpoint_uuid": {"uuid": "GigabitEthernet2"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"name": "GigabitEthernet3", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "1.1.1.1"}}, "endpoint_uuid": {"uuid": "GigabitEthernet3"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"name": "GigabitEthernet4", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "1.1.1.1"}}, "endpoint_uuid": {"uuid": "GigabitEthernet4"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"name": "GigabitEthernet5", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "1.1.1.1"}}, "endpoint_uuid": {"uuid": "GigabitEthernet5"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }} + ] + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.60.125.42" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + }, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet1]", "resource_value": { + "uuid": "GigabitEthernet1", "name": "GigabitEthernet1", "type": "-" + }}}, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet2]", "resource_value": { + "uuid": "GigabitEthernet2", "name": "GigabitEthernet2", "type": "-" + }}}, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet3]", "resource_value": { + "uuid": "GigabitEthernet3", "name": "GigabitEthernet3", "type": "-" + }}}, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet4]", "resource_value": { + "uuid": "GigabitEthernet4", "name": "GigabitEthernet4", "type": "-" + }}}, + {"action": 1, "custom": {"resource_key": "/endpoints/endpoint[GigabitEthernet5]", "resource_value": { + "uuid": "GigabitEthernet5", "name": "GigabitEthernet5", "type": "-" + }}} + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + {"name": "GigabitEthernet1", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "2.2.2.2"}}, "endpoint_uuid": {"uuid": "GigabitEthernet1"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"name": "GigabitEthernet2", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "2.2.2.2"}}, "endpoint_uuid": {"uuid": "GigabitEthernet2"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"name": "GigabitEthernet3", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "2.2.2.2"}}, "endpoint_uuid": {"uuid": "GigabitEthernet3"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"name": "GigabitEthernet4", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "2.2.2.2"}}, "endpoint_uuid": {"uuid": "GigabitEthernet4"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }}, + {"name": "GigabitEthernet5", "endpoint_type": "-", "endpoint_id": { + "device_id": {"device_uuid": {"uuid": "2.2.2.2"}}, "endpoint_uuid": {"uuid": "GigabitEthernet5"}, + "topology_id": {"context_id": {"context_uuid": {"uuid": "admin"}}, "topology_uuid": {"uuid": "admin"}} + }} + ] + } + ], + "links":[ + { + "link_id":{ + "link_uuid":{ + "uuid":"4.4.4.4/0/0/1-GigabitEthernet0/0/0/1==2.2.2.2/GigabitEthernet2" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"4.4.4.4" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet2" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"2.2.2.2/GigabitEthernet2==4.4.4.4/0/0/1-GigabitEthernet0/0/0/1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet2" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"4.4.4.4" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"2.2.2.2/GigabitEthernet1==1.1.1.1/GigabitEthernet1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet1" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"1.1.1.1/GigabitEthernet1==2.2.2.2/GigabitEthernet1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet1" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"2.2.2.2/GigabitEthernet4==5.5.5.5/0/0/0-GigabitEthernet0/0/0/0" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet4" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/0-GigabitEthernet0/0/0/0" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"5.5.5.5/0/0/0-GigabitEthernet0/0/0/0==2.2.2.2/GigabitEthernet4" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet4" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"2.2.2.2/GigabitEthernet3==3.3.3.3/0/0/3-GigabitEthernet0/0/0/3" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet3" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/3-GigabitEthernet0/0/0/3" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"3.3.3.3/0/0/3-GigabitEthernet0/0/0/3==2.2.2.2/GigabitEthernet3" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/3-GigabitEthernet0/0/0/3" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet3" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"1.1.1.1/GigabitEthernet2==5.5.5.5/0/0/2-GigabitEthernet0/0/0/2" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet2" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/2-GigabitEthernet0/0/0/2" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"5.5.5.5/0/0/2-GigabitEthernet0/0/0/2==1.1.1.1/GigabitEthernet2" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/2-GigabitEthernet0/0/0/2" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "endpoint_uuid":{ + "uuid":"GigabitEthernet2" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/templates/descriptor-topology-tid.json b/src/templates/descriptor-topology-tid.json new file mode 100644 index 0000000000000000000000000000000000000000..588d9e90e08589b8d78d7a51c6c5ef8c3f607c0b --- /dev/null +++ b/src/templates/descriptor-topology-tid.json @@ -0,0 +1,752 @@ +{ + "contexts":[ + { + "context_id":{ + "context_uuid":{ + "uuid":"admin" + } + }, + "topology_ids":[ + + ], + "service_ids":[ + + ] + } + ], + "topologies":[ + { + "topology_id":{ + "context_id":{ + "context_uuid":{ + "uuid":"admin" + } + }, + "topology_uuid":{ + "uuid":"admin" + } + }, + "device_ids":[ + { + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + { + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + { + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + { + "device_uuid":{ + "uuid":"4.4.4.4" + } + }, + { + "device_uuid":{ + "uuid":"5.5.5.5" + } + } + ], + "link_ids":[ + { + "link_uuid":{ + "uuid":"5.5.5.5/0/0/1-GigabitEthernet0/0/0/1==3.3.3.3/0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "link_uuid":{ + "uuid":"3.3.3.3/0/0/1-GigabitEthernet0/0/0/1==5.5.5.5/0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "link_uuid":{ + "uuid":"5.5.5.5/0/0/2-GigabitEthernet0/0/0/2==1.1.1.1/0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "link_uuid":{ + "uuid":"1.1.1.1/0/0/1-GigabitEthernet0/0/0/1==5.5.5.5/0/0/2-GigabitEthernet0/0/0/2" + } + }, + { + "link_uuid":{ + "uuid":"5.5.5.5/0/0/0-GigabitEthernet0/0/0/0==2.2.2.2/0/0/2-GigabitEthernet0/0/0/2" + } + }, + { + "link_uuid":{ + "uuid":"2.2.2.2/0/0/2-GigabitEthernet0/0/0/2==5.5.5.5/0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "link_uuid":{ + "uuid":"3.3.3.3/0/0/3-GigabitEthernet0/0/0/3==2.2.2.2/0/0/3-GigabitEthernet0/0/0/3" + } + }, + { + "link_uuid":{ + "uuid":"2.2.2.2/0/0/3-GigabitEthernet0/0/0/3==3.3.3.3/0/0/3-GigabitEthernet0/0/0/3" + } + }, + { + "link_uuid":{ + "uuid":"1.1.1.1/0/0/0-GigabitEthernet0/0/0/0==2.2.2.2/0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "link_uuid":{ + "uuid":"2.2.2.2/0/0/0-GigabitEthernet0/0/0/0==1.1.1.1/0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "link_uuid":{ + "uuid":"4.4.4.4/0/0/1-GigabitEthernet0/0/0/1==2.2.2.2/0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "link_uuid":{ + "uuid":"2.2.2.2/0/0/1-GigabitEthernet0/0/0/1==4.4.4.4/0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + } + ], + "devices":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.95.90.41" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + } + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + + ] + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.95.90.42" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + } + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + + ] + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.95.90.43" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + } + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + + ] + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"4.4.4.4" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.95.90.44" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + } + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + + ] + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.95.90.45" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + } + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + + ] + } + ], + "links":[ + { + "link_id":{ + "link_uuid":{ + "uuid":"5.5.5.5/0/0/1-GigabitEthernet0/0/0/1==3.3.3.3/0/0/1-GigabitEthernet0/0/0/1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"3.3.3.3/0/0/1-GigabitEthernet0/0/0/1==5.5.5.5/0/0/1-GigabitEthernet0/0/0/1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"5.5.5.5/0/0/2-GigabitEthernet0/0/0/2==1.1.1.1/0/0/1-GigabitEthernet0/0/0/1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/2-GigabitEthernet0/0/0/2" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"1.1.1.1/0/0/1-GigabitEthernet0/0/0/1==5.5.5.5/0/0/2-GigabitEthernet0/0/0/2" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/2-GigabitEthernet0/0/0/2" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"5.5.5.5/0/0/0-GigabitEthernet0/0/0/0==2.2.2.2/0/0/2-GigabitEthernet0/0/0/2" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/2-GigabitEthernet0/0/0/2" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"2.2.2.2/0/0/2-GigabitEthernet0/0/0/2==5.5.5.5/0/0/0-GigabitEthernet0/0/0/0" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/2-GigabitEthernet0/0/0/2" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/0-GigabitEthernet0/0/0/0" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"3.3.3.3/0/0/3-GigabitEthernet0/0/0/3==2.2.2.2/0/0/3-GigabitEthernet0/0/0/3" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/3-GigabitEthernet0/0/0/3" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/3-GigabitEthernet0/0/0/3" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"2.2.2.2/0/0/3-GigabitEthernet0/0/0/3==3.3.3.3/0/0/3-GigabitEthernet0/0/0/3" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/3-GigabitEthernet0/0/0/3" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/3-GigabitEthernet0/0/0/3" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"1.1.1.1/0/0/0-GigabitEthernet0/0/0/0==2.2.2.2/0/0/0-GigabitEthernet0/0/0/0" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/0-GigabitEthernet0/0/0/0" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"2.2.2.2/0/0/0-GigabitEthernet0/0/0/0==1.1.1.1/0/0/0-GigabitEthernet0/0/0/0" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/0-GigabitEthernet0/0/0/0" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"1.1.1.1" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/0-GigabitEthernet0/0/0/0" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"4.4.4.4/0/0/1-GigabitEthernet0/0/0/1==2.2.2.2/0/0/1-GigabitEthernet0/0/0/1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"4.4.4.4" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"2.2.2.2/0/0/1-GigabitEthernet0/0/0/1==4.4.4.4/0/0/1-GigabitEthernet0/0/0/1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"2.2.2.2" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"4.4.4.4" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/templates/descriptor-topology.json b/src/templates/descriptor-topology.json new file mode 100644 index 0000000000000000000000000000000000000000..e22737b52783b5db72e5809d83f4cbbc3a936c09 --- /dev/null +++ b/src/templates/descriptor-topology.json @@ -0,0 +1,290 @@ +{ + "contexts":[ + { + "context_id":{ + "context_uuid":{ + "uuid":"admin" + } + }, + "topology_ids":[ + + ], + "service_ids":[ + + ] + } + ], + "topologies":[ + { + "topology_id":{ + "context_id":{ + "context_uuid":{ + "uuid":"admin" + } + }, + "topology_uuid":{ + "uuid":"admin" + } + }, + "device_ids":[ + { + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + { + "device_uuid":{ + "uuid":"4.4.4.4" + } + }, + { + "device_uuid":{ + "uuid":"5.5.5.5" + } + } + ], + "link_ids":[ + { + "link_uuid":{ + "uuid":"5.5.5.5/0/0/1-GigabitEthernet0/0/0/1==3.3.3.3/0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "link_uuid":{ + "uuid":"3.3.3.3/0/0/1-GigabitEthernet0/0/0/1==5.5.5.5/0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + } + ], + "devices":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.60.125.43" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + } + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + + ] + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"4.4.4.4" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.60.125.44" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + } + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + + ] + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "device_type":"packet-router", + "device_config":{ + "config_rules":[ + { + "action":1, + "custom":{ + "resource_key":"_connect/address", + "resource_value":"10.60.125.45" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/port", + "resource_value":"830" + } + }, + { + "action":1, + "custom":{ + "resource_key":"_connect/settings", + "resource_value":{ + "username":"cisco", + "password":"cisco12345", + "vendor":"CISCO", + "force_running":false, + "hostkey_verify":false, + "message_renderer":"pyangbind", + "look_for_keys":false, + "allow_agent":false, + "commit_per_rule":true, + "device_params":{ + "name":"default" + }, + "manager_params":{ + "timeout":120 + } + } + } + } + ] + }, + "device_operational_status":2, + "device_drivers":[ + 1 + ], + "device_endpoints":[ + + ] + } + ], + "links":[ + { + "link_id":{ + "link_uuid":{ + "uuid":"5.5.5.5/0/0/1-GigabitEthernet0/0/0/1==3.3.3.3/0/0/1-GigabitEthernet0/0/0/1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + }, + { + "link_id":{ + "link_uuid":{ + "uuid":"3.3.3.3/0/0/1-GigabitEthernet0/0/0/1==5.5.5.5/0/0/1-GigabitEthernet0/0/0/1" + } + }, + "link_endpoint_ids":[ + { + "device_id":{ + "device_uuid":{ + "uuid":"3.3.3.3" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + }, + { + "device_id":{ + "device_uuid":{ + "uuid":"5.5.5.5" + } + }, + "endpoint_uuid":{ + "uuid":"0/0/1-GigabitEthernet0/0/0/1" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/src/templates/descriptor.json b/src/templates/descriptor.json new file mode 100644 index 0000000000000000000000000000000000000000..4923ab4427b5723d970c006043242373fb4eafdd --- /dev/null +++ b/src/templates/descriptor.json @@ -0,0 +1,27 @@ +{ + "contexts": [ + { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + }, + "topology_ids": [], + "service_ids": [] + } + ], + "topologies": [ + { + "topology_id": { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + }, + "topology_uuid": { + "uuid": "admin" + } + } + } + ] + } \ No newline at end of file diff --git a/src/templates/ietfL2VPN_template.json b/src/templates/ietfL2VPN_template.json new file mode 100644 index 0000000000000000000000000000000000000000..79037c2f7e423ce44b34bd90f35ca8fe74071f18 --- /dev/null +++ b/src/templates/ietfL2VPN_template.json @@ -0,0 +1,38 @@ +{ + "l2vpn": { + "vpn-services": { + "vpn-service": [ + { + "vpn-id": 100, + "name": "VPN_L2_Example", + "vpn-type": "point-to-point", + "site": [ + { + "site-id": 1, + "site-role": "hub", + "site-location": "R4", + "site-network-access": { + "interface": { + "ip-address": "4.4.4.4", + "encapsulation": "ethernet" + } + } + }, + { + "site-id": 2, + "site-role": "spoke", + "site-location": "R5", + "site-network-access": { + "interface": { + "ip-address": "5.5.5.5", + "encapsulation": "ethernet" + } + } + } + ] + } + ] + } + } + } + \ No newline at end of file diff --git a/src/templates/ietfL2VPN_template_empty.json b/src/templates/ietfL2VPN_template_empty.json deleted file mode 100644 index d7d6be05fc6a78f2ac3e8acaebae9410fd97905a..0000000000000000000000000000000000000000 --- a/src/templates/ietfL2VPN_template_empty.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "ietf-l2vpn-svc:vpn-service": [ - { - "vpn-id": "", - "customer-name": "osm", - "vpn-svc-type": "vpws", - "svc-topo": "any-to-any", - "site": [ - { - "site-id": "", - "site-location": "", - "site-network-access": { - "interface": { - "ip-address": "", - "encapsulation": "ethernet" - } - } - }, - { - "site-id": "", - "site-location": "", - "site-network-access": { - "interface": { - "ip-address": "", - "encapsulation": "ethernet" - } - } - } - ] - } - ] -} diff --git a/src/templates/ietfL3VPN_template.json b/src/templates/ietfL3VPN_template.json new file mode 100644 index 0000000000000000000000000000000000000000..07ffbe91b29addee98b3ac390076a581916038d5 --- /dev/null +++ b/src/templates/ietfL3VPN_template.json @@ -0,0 +1,184 @@ +{ + "ietf-l3vpn-svc:l3vpn-svc": { + "sites": { + "site": [ + { + "devices": { + "device": [ + { + "device-id": "4.4.4.4", + "location": "router4" + } + ] + }, + "locations": { + "location": [ + { + "location-id": "router4" + } + ] + }, + "management": { + "type": "ietf-l3vpn-svc:provider-managed" + }, + "routing-protocols": { + "routing-protocol": [ + { + "static": { + "cascaded-lan-prefixes": { + "ipv4-lan-prefixes": [ + { + "lan": "4.4.4.4/24", + "lan-tag": "100", + "next-hop": "2.2.2.2" + } + ] + } + }, + "type": "ietf-l3vpn-svc:static" + } + ] + }, + "site-id": "site_router4", + "site-network-accesses": { + "site-network-access": [ + { + "device-reference": "4.4.4.4", + "ip-connection": { + "ipv4": { + "address-allocation-type": "ietf-l3vpn-svc:static-address", + "addresses": { + "customer-address": "2.2.2.2", + "prefix-length": "24", + "provider-address": "4.4.4.4" + } + } + }, + "service": { + "qos": { + "qos-profile": { + "classes": { + "class": [ + { + "bandwidth": { + "guaranteed-bw-percent": 100 + }, + "class-id": "qos-realtime", + "direction": "ietf-l3vpn-svc:both", + "latency": { + "latency-boundary": 20 + } + } + ] + } + } + }, + "svc-input-bandwidth": 5000000000, + "svc-mtu": 1500, + "svc-output-bandwidth": 1000000000 + }, + "site-network-access-type": "ietf-l3vpn-svc:multipoint", + "vpn-attachment": { + "site-role": "ietf-l3vpn-svc:hub-role", + "vpn-id": "vpn-example" + } + } + ] + } + }, + { + "devices": { + "device": [ + { + "device-id": "5.5.5.5", + "location": "router5" + } + ] + }, + "locations": { + "location": [ + { + "location-id": "router5" + } + ] + }, + "management": { + "type": "ietf-l3vpn-svc:provider-managed" + }, + "routing-protocols": { + "routing-protocol": [ + { + "static": { + "cascaded-lan-prefixes": { + "ipv4-lan-prefixes": [ + { + "lan": "5.5.5.5/24", + "lan-tag": "200", + "next-hop": "2.2.2.2" + } + ] + } + }, + "type": "ietf-l3vpn-svc:static" + } + ] + }, + "site-id": "site_router5", + "site-network-accesses": { + "site-network-access": [ + { + "device-reference": "5.5.5.5", + "ip-connection": { + "ipv4": { + "address-allocation-type": "ietf-l3vpn-svc:static-address", + "addresses": { + "customer-address": "2.2.2.2", + "prefix-length": "24", + "provider-address": "5.5.5.5" + } + } + }, + "service": { + "qos": { + "qos-profile": { + "classes": { + "class": [ + { + "bandwidth": { + "guaranteed-bw-percent": 100 + }, + "class-id": "qos-realtime", + "direction": "ietf-l3vpn-svc:both", + "latency": { + "latency-boundary": 10 + } + } + ] + } + } + }, + "svc-input-bandwidth": 1000000000, + "svc-mtu": 1500, + "svc-output-bandwidth": 5000000000 + }, + "site-network-access-type": "ietf-l3vpn-svc:multipoint", + "vpn-attachment": { + "site-role": "ietf-l3vpn-svc:spoke-role", + "vpn-id": "vpn-example" + } + } + ] + } + } + ] + }, + "vpn-services": { + "vpn-service": [ + { + "vpn-id": "vpn-example" + } + ] + } + } + } + \ No newline at end of file diff --git a/src/templates/ietfL3VPN_template_empty.json b/src/templates/ietfL3VPN_template_empty.json deleted file mode 100644 index 628abcbe200fb58dbdb6638081c4a3087116e7fc..0000000000000000000000000000000000000000 --- a/src/templates/ietfL3VPN_template_empty.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "ietf-l3vpn-svc:l3vpn-svc": { - "vpn-services": {"vpn-service": [{"vpn-id": ""}]}, - "sites": { - "site": [ - { - "site-id": "", - "management": {"type": "ietf-l3vpn-svc:provider-managed"}, - "locations": {"location": [{"location-id": ""}]}, - "devices": {"device": [{"device-id": "", "location": ""}]}, - "site-network-accesses": { - "site-network-access": [ - { - "site-network-access-id": "", - "site-network-access-type": "ietf-l3vpn-svc:multipoint", - "device-reference": "", - "vpn-attachment": {"vpn-id": "", "site-role": "ietf-l3vpn-svc:spoke-role"}, - "ip-connection": { - "ipv4": { - "address-allocation-type": "ietf-l3vpn-svc:static-address", - "addresses": { - "provider-address": "192.168.1.1", - "customer-address": "192.168.1.10", - "prefix-length": 24 - } - } - }, - "service": { - "svc-mtu": 1500, - "svc-input-bandwidth": 1, - "svc-output-bandwidth": 1, - "qos": {"qos-profile": {"classes": {"class": [{ - "class-id": "qos-realtime", - "direction": "ietf-l3vpn-svc:both", - "latency": {"latency-boundary": 100}, - "bandwidth": {"guaranteed-bw-percent": 100} - }]}}} - } - } - ] - } - }, - { - "site-id": "", - "management": {"type": "ietf-l3vpn-svc:provider-managed"}, - "locations": {"location": [{"location-id": ""}]}, - "devices": {"device": [{"device-id": "", "location": ""}]}, - "site-network-accesses": { - "site-network-access": [ - { - "site-network-access-id": "", - "site-network-access-type": "ietf-l3vpn-svc:multipoint", - "device-reference": "", - "vpn-attachment": {"vpn-id": "", "site-role": "ietf-l3vpn-svc:hub-role"}, - "ip-connection": { - "ipv4": { - "address-allocation-type": "ietf-l3vpn-svc:static-address", - "addresses": { - "provider-address": "192.168.2.1", - "customer-address": "192.168.2.10", - "prefix-length": 24 - } - } - }, - "service": { - "svc-mtu": 1500, - "svc-input-bandwidth": 1, - "svc-output-bandwidth": 1, - "qos": {"qos-profile": {"classes": {"class": [{ - "class-id": "qos-realtime", - "direction": "ietf-l3vpn-svc:both", - "latency": {"latency-boundary": 100}, - "bandwidth": {"guaranteed-bw-percent": 100} - }]}}} - } - } - ] - } - } - ] - } - } -} diff --git a/src/templates/ietf_template_empty.json b/src/templates/ietf_template_empty.json index cdaf66cdad3fbd7f01c09a7987cf8729600952b0..b4fb81f6d61100bfa0dcdb17fa0165eb03bd9ed8 100644 --- a/src/templates/ietf_template_empty.json +++ b/src/templates/ietf_template_empty.json @@ -7,6 +7,16 @@ "description":"", "slo-policy":{ "metric-bound":[ + { + "metric-type":"one-way-bandwidth", + "metric-unit":"kbps", + "bound":"" + }, + { + "metric-type":"one-way-delay-maximum", + "metric-unit":"milliseconds", + "bound":"" + } ] }, "sle-policy":{ @@ -43,7 +53,7 @@ "sdps":{ "sdp":[ { - "id": "", + "id":"01", "geo-location":"", "node-id":"", "sdp-ip-address":"", @@ -90,7 +100,7 @@ "sdp-monitoring":"" }, { - "id":"", + "id":"02", "geo-location":"", "node-id":"", "sdp-ip-address":"", diff --git a/src/templates/ietf_template_example.json b/src/templates/ietf_template_example.json new file mode 100644 index 0000000000000000000000000000000000000000..82782208df2489ba0aba0a27c121f90a71c34d4d --- /dev/null +++ b/src/templates/ietf_template_example.json @@ -0,0 +1,158 @@ +{ + "ietf-network-slice-service:network-slice-services": { + "slo-sle-templates": { + "slo-sle-template": [ + { + "id": "A", + "description": "", + "slo-policy": { + "metric-bound": [ + { + "metric-type": "one-way-bandwidth", + "metric-unit": "kbps", + "bound": 2 + }, + { + "metric-type": "one-way-delay-maximum", + "metric-unit": "milliseconds", + "bound": 20 + } + ] + }, + "sle-policy": { + "security": "", + "isolation": "", + "path-constraints": { + "service-functions": "", + "diversity": { + "diversity": { + "diversity-type": "" + } + } + } + } + } + ] + }, + "slice-service": [ + { + "id": "slice-service-366e05b7-34e6-4597-9e28-e580abaeda71", + "description": "Transport network slice mapped with 3GPP slice NetworkSlice1", + "service-tags": { + "tag-type": { + "tag-type": "", + "value": "" + } + }, + "slo-sle-policy": { + "slo-sle-template": "A" + }, + "status": {}, + "sdps": { + "sdp": [ + { + "id": "01", + "geo-location": "", + "node-id": "CU-N2", + "sdp-ip-address": "10.60.60.105", + "tp-ref": "", + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": "VLAN", + "value": "100", + "target-connection-group-id": "CU-N2_AMF-N2" + } + ] + }, + "incoming-qos-policy": "", + "outgoing-qos-policy": "", + "sdp-peering": { + "peer-sap-id": "", + "protocols": "" + }, + "ac-svc-ref": [], + "attachment-circuits": { + "attachment-circuit": [ + { + "id": "100", + "ac-ipv4-address": "10.60.60.105", + "ac-ipv4-prefix-length": 0, + "sdp-peering": { + "peer-sap-id": "5.5.5.5" + }, + "status": {} + } + ] + }, + "status": {}, + "sdp-monitoring": "" + }, + { + "id": "02", + "geo-location": "", + "node-id": "AMF-N2", + "sdp-ip-address": "10.60.11.3", + "tp-ref": "", + "service-match-criteria": { + "match-criterion": [ + { + "index": 1, + "match-type": "VLAN", + "value": "100", + "target-connection-group-id": "CU-N2_AMF-N2" + } + ] + }, + "incoming-qos-policy": "", + "outgoing-qos-policy": "", + "sdp-peering": { + "peer-sap-id": "", + "protocols": "" + }, + "ac-svc-ref": [], + "attachment-circuits": { + "attachment-circuit": [ + { + "id": "200", + "ac-ipv4-address": "10.60.11.3", + "ac-ipv4-prefix-length": 0, + "sdp-peering": { + "peer-sap-id": "4.4.4.4" + }, + "status": {} + } + ] + }, + "status": {}, + "sdp-monitoring": "" + } + ] + }, + "connection-groups": { + "connection-group": [ + { + "id": "CU-N2_AMF-N2", + "connectivity-type": "ietf-vpn-common:any-to-any", + "connectivity-construct": [ + { + "id": 1, + "a2a-sdp": [ + { + "sdp-id": "01" + }, + { + "sdp-id": "02" + } + ] + } + ], + "status": {} + } + ] + } + } + ] + } +} \ No newline at end of file diff --git a/src/templates/ietf_template_filled.json b/src/templates/ietf_template_filled.json new file mode 100644 index 0000000000000000000000000000000000000000..e7a525e096c027323a4feb63ff8407f9385a2ee0 --- /dev/null +++ b/src/templates/ietf_template_filled.json @@ -0,0 +1,152 @@ +{ + "ietf-network-slice-service:network-slice-services":{ + "slo-sle-templates":{ + "slo-sle-template":[ + { + "id":"MidhaulId", + "slo-policy":{ + "metric-bound":[ + { + "metric-type":"one-way-bandwidth", + "metric-unit":"kbps", + "bound":300 + }, + { + "metric-type":"one-way-delay-maximum", + "metric-unit":"milliseconds", + "bound":1 + } + ] + }, + "sle-policy":{ + "security":[ + + ], + "isolation":[ + + ], + "steering-constraints":{ + "path-constraints":"", + "service-function":"" + } + } + } + ] + }, + "slice-service":[ + { + "id":"5GSliceMapping", + "description":"example 5G Slice mapping", + "slo-sle-template":"MidhaulId", + "status":{ + + }, + "sdps":{ + "sdp":[ + { + "id":"01", + "node-id":"DU1", + "sdp-ip-address":"1.1.1.2", + "service-match-criteria":{ + "match-criterion":[ + { + "index":1, + "match-type":"vlan-match", + "value":[ + "100" + ], + "target-connection-group-id":"DU-CU" + } + ] + }, + "sdp-peering":{ + "peer-sap-id":"", + "protocols":"" + }, + "ac-svc-name":[ + + ], + "attachment-circuits":{ + "attachment-circuit":[ + { + "id":"100", + "ac-ipv4-address":"1.1.1.1", + "ac-ipv4-prefix-length":0, + "sdp-peering":{ + "peer-sap-id":"1.1.1.254" + }, + "status":{ + + } + } + ] + }, + "status":{ + + } + }, + { + "id":"02", + "node-id":"CU-UP1", + "sdp-ip-address":"100.1.1.2", + "service-match-criteria":{ + "match-criterion":[ + { + "index":1, + "match-type":"vlan-match", + "value":[ + "100" + ], + "target-connection-group-id":"DU-CU" + } + ] + }, + "attachment-circuits":{ + "attachment-circuit":[ + { + "id":"200", + "ac-ipv4-address":"100.1.1.1", + "ac-ipv4-prefix-length":0, + "sdp-peering":{ + "peer-sap-id":"100.1.1.254" + }, + "status":{ + + } + } + ] + }, + "status":{ + + } + } + ] + }, + "connection-groups":{ + "connection-group":[ + { + "id":"DU-CU", + "connectivity-type":"ietf-vpn-common:any-to-any", + "connectivity-construct":[ + { + "id":1, + "a2a-sdp":[ + { + "sdp-id":"01" + }, + { + "sdp-id":"02" + } + ] + } + ], + "status":{ + + } + } + ] + } + } + ] + } +} \ No newline at end of file diff --git a/src/templates/ips.json b/src/templates/ips.json new file mode 100644 index 0000000000000000000000000000000000000000..c041c4c41f46e678598ae13d0743923e2998a114 --- /dev/null +++ b/src/templates/ips.json @@ -0,0 +1,18 @@ +{ + "CU":[ + {"prefix":"100.1.1.2", "node-name":"CU-UP1" }, + {"prefix":"100.1.2.2", "node-name":"CU-UP2" } + ], + "DU":[ + {"prefix":"1.1.1.2", "node-name":"DU1" }, + {"prefix":"1.1.2.2", "node-name":"DU2" }, + {"prefix":"1.1.3.2", "node-name":"DU3" } + ], + "public-prefixes":[ + {"prefix":"10.95.90.125", "node-name":"HL5-2-2" }, + {"prefix":"10.95.90.126", "node-name":"HL5-1-2" }, + {"prefix":"10.95.86.167", "node-name":"HL5-3-2" }, + {"prefix":"10.95.86.107", "node-name":"HL4-1-2" }, + {"prefix":"10.95.90.85", "node-name":"HL4-2-2" } + ] +} diff --git a/src/templates/test_service.json b/src/templates/test_service.json new file mode 100644 index 0000000000000000000000000000000000000000..bd956b7281afce8f3626bfa08be5dc9471e63e8b --- /dev/null +++ b/src/templates/test_service.json @@ -0,0 +1,93 @@ +{ + "services": [ + { + "service_id": { + "context_id": { + "context_uuid": { + "uuid": "admin" + } + }, + "service_uuid": { + "uuid": "l2-acl-svc-17387469754519430" + } + }, + "service_type": 2, + "service_status": { + "service_status": 1 + }, + "service_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.31" + } + }, + "endpoint_uuid": { + "uuid": "eth-1/0/22" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "172.16.185.32" + } + }, + "endpoint_uuid": { + "uuid": "eth-1/0/6" + } + } + ], + "service_constraints": [ + { + "custom": { + "constraint_type": "bandwidth[kbps]", + "constraint_value": "20" + } + }, + { + "custom": { + "constraint_type": "latency[ms]", + "constraint_value": "20" + } + } + ], + "service_config": { + "config_rules": [ + { + "action": 1, + "custom": { + "resource_key": "/settings", + "resource_value": {} + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[172.16.185.31]/endpoint[eth-1/0/22]/settings", + "resource_value": { + "sub_interface_index": 0, + "vlan_id": 100, + "circuit_id": "100", + "remote_router": "172.16.185.32", + "ni_name": "ELAN100" + } + } + }, + { + "action": 1, + "custom": { + "resource_key": "/device[172.16.185.32]/endpoint[eth-1/0/6]/settings", + "resource_value": { + "sub_interface_index": 0, + "vlan_id": 100, + "circuit_id": "100", + "remote_router": "172.16.185.31", + "ni_name": "ELAN100" + } + } + } + ] + } + } + ] + } \ No newline at end of file diff --git a/src/webui/gui.py b/src/webui/gui.py deleted file mode 100644 index 1afb831c6410b8a58d51c1b077a86c4a665db33d..0000000000000000000000000000000000000000 --- a/src/webui/gui.py +++ /dev/null @@ -1,475 +0,0 @@ -# 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. - -# This file is an original contribution from Telefonica Innovación Digital S.L. - -import json, logging, uuid -import requests -import os -import pandas as pd -from flask import Flask, render_template, request, jsonify, redirect, url_for, session, Blueprint -from collections import OrderedDict -from src.Constants import SRC_PATH, NSC_PORT, TEMPLATES_PATH, DUMMY_MODE -from src.realizers.ixia.NEII_V4 import NEII_controller - -# app =Flask(__name__) -gui_bp = Blueprint('gui', __name__, template_folder=os.path.join(SRC_PATH, 'webui', 'templates'), static_folder=os.path.join(SRC_PATH, 'webui', 'static'), static_url_path='/webui/static') - -#Variables for dev accessing -USERNAME = 'admin' -PASSWORD = 'admin' -enter=False - -def __safe_int(value): - try: - if isinstance(value, str): - value = value.strip().replace(',', '.') - number = float(value) - return int(number) if number.is_integer() else number - except (ValueError, TypeError, AttributeError): - return None - -def __build_request_ietf(src_node_ip=None, dst_node_ip=None, vlan_id=None, bandwidth=None, latency=None, tolerance=0, latency_version=None, reliability=None): - ''' - Work: Build the IETF template for the intent - ''' - # Open and read the template file - with open(os.path.join(TEMPLATES_PATH, 'ietf_template_empty.json'), 'r') as source: - # Clean up the JSON template - template = source.read().replace('\t', '').replace('\n', '').replace("'", '"').strip() - request = json.loads(template) - - request["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["id"] = f"qos-profile-{uuid.uuid4()}" - - # Generate unique slice service ID and description - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"] = f"slice-service-{uuid.uuid4()}" - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["slo-sle-policy"]["slo-sle-template"] = request["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["id"] - - # Configure Source SDP - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["node-id"] = "source-node" #Pendiente de rellenar - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["sdp-ip-address"] = src_node_ip - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["service-match-criteria"]["match-criterion"][0]["match-type"] = "VLAN" - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["service-match-criteria"]["match-criterion"][0]["value"] = vlan_id - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["attachment-circuits"]["attachment-circuit"][0]["ac-ipv4-address"] = "" # Pendiente de rellenar - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["attachment-circuits"]["attachment-circuit"][0]["sdp-peering"]["peer-sap-id"] = src_node_ip - - # Configure Destination SDP - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["node-id"] = "destination-node" - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["sdp-ip-address"] = dst_node_ip - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["service-match-criteria"]["match-criterion"][0]["match-type"] = "VLAN" - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["service-match-criteria"]["match-criterion"][0]["value"] = vlan_id - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["attachment-circuits"]["attachment-circuit"][0]["ac-ipv4-address"] = ""# Pendiente de rellenar - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["attachment-circuits"]["attachment-circuit"][0]["sdp-peering"]["peer-sap-id"] = dst_node_ip - - # Configure Connection Group and match-criteria - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["connection-groups"]["connection-group"][0]["id"] = "source-node_destination-node" #Pendiente de rellenar - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["service-match-criteria"]["match-criterion"][0]["target-connection-group-id"] = "" #Pendiente de rellenar - request["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["service-match-criteria"]["match-criterion"][0]["target-connection-group-id"] = "" #Pendiente de rellenar - - # Populate template with SLOs (currently supporting QoS profile, latency and bandwidth) - if bandwidth: - request["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"].append({ - "metric-type": "one-way-bandwidth", - "metric-unit": "Mbps", - "bound": __safe_int(bandwidth) - }) - if latency: - request["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"].append({ - "metric-type": "one-way-delay-maximum", - "metric-unit": "milliseconds", - "bound": __safe_int(latency) - }) - # Configure gaussian latency or internet if specified - if latency_version: - request["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["description"] = latency_version - if tolerance: - request["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"].append( { - "metric-type": "one-way-delay-variation-maximum", - "metric-unit": "milliseconds", - "bound": __safe_int(tolerance) - }) - if reliability: - request["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["sle-policy"]["reliability"] = __safe_int(reliability) - - return request - -def __build_request(ip_version=None, src_node_ip=None, dst_node_ip=None, src_node_ipv6=None, dst_node_ipv6=None, - vlan_id=None, bandwidth=None, latency=None, tolerance=0, latency_version=None, - reliability=None, packet_reorder=None, num_pack=None, pack_reorder=None, num_reorder=None, - max_reorder=None, desv_reorder=None, drop_version=None, packets_drop=None, - drops=None, desv_drop=None): - ''' - Work: Build the template for the IXIA NEII - ''' - json_data = { - "ip_version": ip_version, - "src_node_ip": src_node_ip, - "dst_node_ip": dst_node_ip, - "src_node_ipv6": src_node_ipv6, - "dst_node_ipv6": dst_node_ipv6, - "vlan_id": vlan_id, - "bandwidth": bandwidth, - "latency": latency, - "tolerance": tolerance, - "latency_version": latency_version, - "reliability": reliability, - "packet_reorder": packet_reorder, - "num_pack": num_pack, - "pack_reorder": pack_reorder, - "num_reorder": num_reorder, - "max_reorder": max_reorder, - "desv_reorder": desv_reorder, - "drop_version": drop_version, - "packets_drop": packets_drop, - "drops": drops, - "desv_drop": desv_drop - } - return json_data - -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"] - for dest_ip, dest_info in source_info["destination"].items(): - row ={ - "Source IP": source_ip, - "Destiny IP": dest_ip, - "VLAN": vlan, - "attributes": dest_info["attributes"] - } - rows.append(row) - dataframe =pd.DataFrame(rows) - except FileNotFoundError: - dataframe =pd.DataFrame() - except ValueError as e: - dataframe =pd.DataFrame() - return dataframe - -@gui_bp.route('/webui') -def home(): - session['enter'] = False - # Leer las IPs actuales del archivo de configuración - try: - with open(os.path.join(SRC_PATH, 'IPs.json')) as f: - ips = json.load(f) - tfs_ip = ips.get('TFS_IP', 'No configurada') - ixia_ip = ips.get('IXIA_IP', 'No configurada') - except Exception: - tfs_ip = 'No configurada' - ixia_ip = 'No configurada' - return render_template('welcome.html', tfs_ip=tfs_ip, ixia_ip=ixia_ip) - -@gui_bp.route('/webui/generate/tfs', methods=['POST','GET']) -def generate_tfs(): - session['enter']=False - if request.method =='POST': - src_node_ip =request.form['src_node_ip'] - dst_node_ip =request.form['dst_node_ip'] - vlan_id =request.form['vlan_id'] - if vlan_id == '': - vlan_id = None - latency =request.form['latency_intent'] - bandwidth =request.form['bandwidth_intent'] - - slice_request = __build_request_ietf(src_node_ip=src_node_ip, dst_node_ip=dst_node_ip, vlan_id=vlan_id, latency=latency, bandwidth=bandwidth) - - # Si 'request' es un diccionario, conviértelo a JSON - json_data = json.dumps(slice_request) - files = { - 'file': ('ietf_template_example.json', json_data, 'application/json') - } - - response = requests.post( - f'http://localhost:{NSC_PORT}/tfs/slice', - headers={ - 'accept': 'application/json' - }, - files=files - ) - response.raise_for_status() - - if response.ok: - return redirect(url_for('gui.generate_tfs', src_node_ip=src_node_ip, dst_node_ip=dst_node_ip, vlan_id=vlan_id, latency=latency, bandwidth=bandwidth)) - else: - return render_template('index.html', error="Error al generar el intent") - - src_node_ip =request.args.get('src_node_ip', '') - dst_node_ip =request.args.get('dst_node_ip', '') - vlan_id =request.args.get('vlan_id', '') - latency =request.args.get('latency', '') - bandwidth =request.args.get('bandwidth', '') - reliability=request.args.get('reliability', '') - - return render_template('index.html', src_node_ip=src_node_ip, dst_node_ip=dst_node_ip, vlan_id=vlan_id, latency=latency, bandwidth=bandwidth, reliability=reliability) - -@gui_bp.route('/webui/generate/ixia', methods=['GET','POST']) -def generate_ixia(): - session['enter']=False - if request.method =='POST': - src_node_ip =request.form['src_node_ip'] - dst_node_ip =request.form['dst_node_ip'] - vlan_id =request.form['vlan_id'] - latency =request.form['latency_intent'] - bandwidth =request.form['bandwidth_intent'] - latency_version="internet" - tolerance= request.form['tolerance_intent'] - reliability=request.form['reliability'] - - if int(reliability)==100: reliability=None - slice_request = __build_request_ietf(src_node_ip=src_node_ip, dst_node_ip=dst_node_ip, vlan_id=vlan_id, bandwidth=bandwidth, latency=latency, latency_version=latency_version, tolerance=tolerance, reliability=reliability) - # Si 'request' es un diccionario, conviértelo a JSON - json_data = json.dumps(slice_request) - files = { - 'file': ('ietf_template_example.json', json_data, 'application/json') - } - - try: - response = requests.post( - f'http://localhost:{NSC_PORT}/ixia/slice', - headers={'accept': 'application/json'}, - files=files - ) - response.raise_for_status() - if response.ok: - return redirect(url_for('gui.generate_ixia', src_node_ip=src_node_ip, dst_node_ip=dst_node_ip, vlan_id=vlan_id, latency=latency, tolerance=tolerance,bandwidth=bandwidth,reliability=reliability)) - except requests.RequestException as e: - print("HTTP error:", e) - return render_template('ixia.html', error="Intent Generation Error") - - src_node_ip =request.args.get('src_node_ip', '') - dst_node_ip =request.args.get('dst_node_ip', '') - vlan_id =request.args.get('vlan_id', '') - latency =request.args.get('latency', '') - tolerance=request.args.get('tolerance', '') - bandwidth =request.args.get('bandwidth', '') - reliability=request.args.get('reliability','') - - return render_template('ixia.html', src_node_ip=src_node_ip, dst_node_ip=dst_node_ip, vlan_id=vlan_id, latency=latency, tolerance=tolerance, bandwidth=bandwidth, reliability=reliability) - - -@gui_bp.route('/webui/dev', methods=['GET', 'POST']) -def develop(): - print('Session content:', dict(session)) - if 'enter' not in session or session['enter'] is False: - return redirect(url_for('gui.login')) - - if request.method == 'POST': - ip_version = request.form.get('ip_version', '') - src_node_ipv4 = request.form.get('src_node_ipv4', '') - dst_node_ipv4 = request.form.get('dst_node_ipv4', '') - src_node_ipv6 = request.form.get('src_node_ipv6', '') - dst_node_ipv6 = request.form.get('dst_node_ipv6', '') - vlan_id = request.form.get('vlan_id', '') - bandwidth = request.form.get('bandwidth_intent', '') - latency = request.form.get('latency_intent', '') - latency_version = request.form.get('delay_statistic', '') - tolerance = request.form.get('max_delay', '') - packet_reorder = request.form.get('packet_options', '') - num_pack = request.form.get('numPack', '') - pack_reorder = request.form.get('packReod', '') - num_reorder = request.form.get('numReod', '') - max_reorder = request.form.get('num_maxReod', '') - desv_reorder = request.form.get('desv_reord', '') - drop_version = request.form.get('object_options', '') - packets_drop = request.form.get('packets', '') - drops = request.form.get('drop', '') - desv_drop = request.form.get('desv_drop', '') - - json_data = __build_request(ip_version=ip_version, src_node_ip=src_node_ipv4, dst_node_ip=dst_node_ipv4, src_node_ipv6=src_node_ipv6, dst_node_ipv6=dst_node_ipv6, vlan_id=vlan_id, latency=latency, bandwidth=bandwidth, latency_version=latency_version, tolerance=tolerance, packet_reorder=packet_reorder, num_pack=num_pack, pack_reorder=pack_reorder, num_reorder=num_reorder, max_reorder=max_reorder, desv_reorder=desv_reorder, drop_version=drop_version, packets_drop=packets_drop, drops=drops, desv_drop=desv_drop) - logging.debug("Generated JSON data: %s", json_data) - if not DUMMY_MODE: - NEII_controller().nscNEII(json_data) - - session['enter'] = True - return render_template('dev.html', - json_data=json_data, - src_node_ip=src_node_ipv4 or src_node_ipv6, - dst_node_ip=dst_node_ipv4 or dst_node_ipv6, - vlan_id=vlan_id, - latency=latency, - bandwidth=bandwidth, - latency_version=latency_version, - tolerance=tolerance, - packet_reorder=packet_reorder, - num_pack=num_pack, - pack_reorder=pack_reorder, - num_reorder=num_reorder, - max_reorder=max_reorder, - desv_reorder=desv_reorder, - packets_drop=packets_drop, - drops=drops, - desv_drop=desv_drop - ) - - return render_template('dev.html', - src_node_ip=request.args.get('src_node_ip', ''), - dst_node_ip=request.args.get('dst_node_ip', ''), - vlan_id=request.args.get('vlan_id', ''), - latency=request.args.get('latency', ''), - bandwidth=request.args.get('bandwidth', ''), - latency_version=request.args.get('latency_version', ''), - tolerance=request.args.get('max_latency', ''), - packet_reorder=request.args.get('packet_reorder', ''), - num_pack=request.args.get('num_pack', ''), - pack_reorder=request.args.get('pack_reorder', ''), - num_reorder=request.args.get('num_reorder', ''), - max_reorder=request.args.get('max_reorder', ''), - desv_reorder=request.args.get('desv', ''), - packets_drop=request.args.get('packets_drop', ''), - drops=request.args.get('drop', ''), - desv_drop=request.args.get('desv_drop', ''), - json_data=None - ) - -@gui_bp.route('/webui/search', methods=['GET', 'POST']) -def search(): - - session['enter'] = False - - try: - response = requests.get(f"http://localhost:{NSC_PORT}/tfs/slice", headers={"accept": "application/json"}) - response.raise_for_status() - tfs_slices = response.json() - - response = requests.get(f"http://localhost:{NSC_PORT}/ixia/slice", headers={"accept": "application/json"}) - response.raise_for_status() - ixia_slices = response.json() - - # Combinar los slices de TFS e IXIA - slices = tfs_slices + ixia_slices - - except requests.RequestException as e: - logging.error("Error fetching slices: %s", e) - return render_template('search.html', error="No se pudieron obtener los slices.", dataframe_html="") - - # Extraer datos relevantes y construir un DataFrame - rows = [] - for item in slices: - try: - slice_service = item["intent"]["ietf-network-slice-service:network-slice-services"]["slice-service"][0] - sdp = slice_service["sdps"]["sdp"] - metric_bound = item["intent"]["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"] - - source_ip = sdp[0]["sdp-ip-address"] - dest_ip = sdp[1]["sdp-ip-address"] - vlan = sdp[0]["service-match-criteria"]["match-criterion"][0]["value"] - controller = item["controller"] - - # Construir atributos dinámicamente - attributes = [] - for metric in metric_bound: - if metric.get("metric-type", "") == "one-way-bandwidth": - metric_type = "bandwidth" - elif metric.get("metric-type", "") == "one-way-delay-maximum": - metric_type = "latency" - elif metric.get("metric-type", "") == "one-way-delay-variation-maximum": - metric_type = "tolerance" - bound = metric.get("bound") - unit = metric.get("metric-unit", "") - if bound is not None: - attributes.append(f"{metric_type}: {bound} {unit}") - - rows.append({ - "Source IP": source_ip, - "Destiny IP": dest_ip, - "Controller": controller, - "VLAN": vlan, - "attributes": attributes - }) - except Exception as e: - print(f"Error procesando slice: {e}") - - - import pandas as pd - dataframe = pd.DataFrame(rows) - - def format_attributes(attributes): - formatted_attrs = [] - for attr in attributes: - formatted_attrs.append(attr) - if formatted_attrs: - return formatted_attrs - else: - return None - - dataframe['attributes'] = dataframe['attributes'].apply([format_attributes]) - - if request.method == 'POST': - search_option = request.form.get('search_option') - search_value = request.form.get('search_value') - if search_option == 'Source IP': - results = dataframe[dataframe['Source IP'] == search_value] - elif search_option == 'Destiny IP': - results = dataframe[dataframe['Destiny IP'] == search_value] - elif search_option == 'Controller': - results = dataframe[dataframe['Controller'] == search_value] - elif search_option == 'VLAN': - results = dataframe[dataframe['VLAN'] == search_value] - else: - results = dataframe - result_html = results.to_html(classes='table table-striped') - return jsonify({'result': result_html}) - - dataframe_html = dataframe.to_html(classes='table table-striped') - return render_template('search.html', dataframe_html=dataframe_html) - -@gui_bp.route('/webui/login', methods=['GET', 'POST']) -def login(): - global enter - if request.method == 'POST': - username = request.form['username'] - password = request.form['password'] - if username == USERNAME and password == PASSWORD: - session['enter']=True - return redirect(url_for('gui.develop')) - else: - return render_template('login.html', error="Credenciales incorrectas") - - return render_template('login.html') - -@gui_bp.route('/webui/reset', methods=['POST']) -def reset(): - dataframe=__datos_json() - dataframe_html =dataframe.to_html(classes='table table-striped') - return jsonify({'result': dataframe_html}) - -@gui_bp.route('/webui/update_ips', methods=['POST']) -def update_ips(): - data = request.get_json() - tfs_ip = data.get('tfs_ip') - ixia_ip = data.get('ixia_ip') - - # Cargar datos existentes si el archivo existe - config_path = os.path.join(SRC_PATH, 'IPs.json') - if os.path.exists(config_path): - with open(config_path) as f: - ips = json.load(f) - else: - ips = {"TFS_IP": "", "IXIA_IP": ""} - - # Actualizar solo los campos recibidos - if tfs_ip: - ips['TFS_IP'] = tfs_ip - if ixia_ip: - ips['IXIA_IP'] = ixia_ip - - # Guardar de nuevo el archivo con los valores actualizados - with open(config_path, 'w') as f: - json.dump(ips, f, indent=4) - - return '', 200 \ No newline at end of file diff --git a/src/webui/static/img/MiniLogo.png b/src/webui/static/img/MiniLogo.png deleted file mode 100644 index 97ebca3d17c0fe8e41cbe1159ed479b26c549359..0000000000000000000000000000000000000000 Binary files a/src/webui/static/img/MiniLogo.png and /dev/null differ diff --git a/src/webui/static/img/TelefonicaLogo.png b/src/webui/static/img/TelefonicaLogo.png deleted file mode 100644 index 36a8be0e95a62016a680722ced4b392a9dd24f1d..0000000000000000000000000000000000000000 Binary files a/src/webui/static/img/TelefonicaLogo.png and /dev/null differ diff --git a/src/webui/static/img/banner.png b/src/webui/static/img/banner.png deleted file mode 100644 index 9fee130dcd0aca7550c5101855bf2de91fc469a8..0000000000000000000000000000000000000000 Binary files a/src/webui/static/img/banner.png and /dev/null differ diff --git a/src/webui/templates/dev.html b/src/webui/templates/dev.html deleted file mode 100644 index 7a18ecc9c9577eea29ec69a80cdc2142b07b7704..0000000000000000000000000000000000000000 --- a/src/webui/templates/dev.html +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - Intent Generation - - - - - -
- - - - -
-
-

Intent Generation:

- -
-
-
- -
-
- - -
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
- - -
-
- - -
-
- - -
-
- - -
- -
- - -
- - -
-
- - -
-
- -
- - -
- - -
- - -
-
- - -
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
-
- - -
-
-
-
-
-
-
- - - - - - - - - - - - - - - - - - diff --git a/src/webui/templates/index.html b/src/webui/templates/index.html deleted file mode 100644 index bef6b7ac3f4b3df673bce0751d5259e236b06262..0000000000000000000000000000000000000000 --- a/src/webui/templates/index.html +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Slice Creation - - - - -
- - - - - -
-

Slice Creation

-
-
-
-
- - -
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
-
- - -
- - {% if error %} -
{{ error }}
- {% endif %} - - {% if src_node_ip and dst_node_ip %} -
-

Intent Generated:

-
-

Source IP: {{ src_node_ip }}

-

Destiny IP: {{ dst_node_ip }}

-

VLAN ID: {{ vlan_id }}

-

Latency [ms]: {{ latency }}

-

Bandwidth [Mbps]: {{ bandwidth }}

-
-
- {% endif %} -
-
- - - - - - - diff --git a/src/webui/templates/ixia.html b/src/webui/templates/ixia.html deleted file mode 100644 index f9821e81bfe3c9c5098155fdacfeeae449b77d85..0000000000000000000000000000000000000000 --- a/src/webui/templates/ixia.html +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - IXIA: Slice Creation - - - - -
- - - -
-

IXIA: Slice Creation

-
-
- -
-
- - -
-
- - -
-
- - -
-
-
- - - (Activar) -
- -
- El valor debe estar entre 51 y 100. -
-
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- - -
- - {% if error %} -
{{ error }}
- {% endif %} - - {% if src_node_ip and dst_node_ip %} -
-

Intent Generated:

-
-

Source IP: {{ src_node_ip }}

-

Destiny IP: {{ dst_node_ip }}

-

VLAN ID: {{ vlan_id }}

-

Latency [ms]: {{ latency }}

-

Tolerance [ms]: {{ tolerance }}

-

Bandwidth [Mbps]: {{ bandwidth }}

-

Reliability: {{ reliability or 100 }}

-
-
- {% endif %} -
- -
- - - - - - - - - diff --git a/src/webui/templates/login.html b/src/webui/templates/login.html deleted file mode 100644 index 5dd54b61e4303b3502cafdc0c4b020ed536fab8d..0000000000000000000000000000000000000000 --- a/src/webui/templates/login.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Login - - - - -
- - - - -
- -
-
- - - - diff --git a/src/webui/templates/search.html b/src/webui/templates/search.html deleted file mode 100644 index 6ace2c126f20e95d73bf9fe480bb80a357676b2b..0000000000000000000000000000000000000000 --- a/src/webui/templates/search.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Search Slice Data - - - - -
- - - -

Search Slice Data

-

Fill in the fields below to search for data in the table:

-
-
- - -
-
- - -
- - -
-
-
- {{ dataframe_html|safe }} -
-
-
- - - - - - diff --git a/src/webui/templates/welcome.html b/src/webui/templates/welcome.html deleted file mode 100644 index 3fa27b2355a99e3f5c2250e5ecf156670874882c..0000000000000000000000000000000000000000 --- a/src/webui/templates/welcome.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - NSC WebUI - - - - - -
- - -
-

Welcome to the NSC WebUI

-

Please, choose the controller you would like to use:

-
- - {{ tfs_ip }} - WebUI -
-
- - {{ ixia_ip }} - WebUI -
-
-
- - - - \ No newline at end of file diff --git a/swagger/ixia_namespace.py b/swagger/ixia_namespace.py deleted file mode 100644 index 6a14ffe995ad0fb2228c2d8deaf6dd91060ea510..0000000000000000000000000000000000000000 --- a/swagger/ixia_namespace.py +++ /dev/null @@ -1,112 +0,0 @@ -from flask import request -from flask_restx import Namespace, Resource, fields, reqparse -from src.network_slice_controller import NSController -import json -from swagger.models.create_models import create_gpp_nrm_28541_model, create_ietf_network_slice_nbi_yang_model - -ixia_ns = Namespace( - "ixia", - description="Operations related to transport network slices with IXIA NEII" -) - -# 3GPP NRM TS28.541 Data models -gpp_network_slice_request_model = create_gpp_nrm_28541_model(ixia_ns) - -# IETF draft-ietf-teas-ietf-network-slice-nbi-yang Data models - -slice_ddbb_model, slice_response_model = create_ietf_network_slice_nbi_yang_model(ixia_ns) - -upload_parser = reqparse.RequestParser() -upload_parser.add_argument('file', location='files', type='FileStorage', help="Archivo a subir") -upload_parser.add_argument('json_data', location='form', help="Datos JSON en formato string") - -# Namespace Controllers -@ixia_ns.route("/slice") -class IxiaSliceList(Resource): - @ixia_ns.doc(summary="Return all transport network slices", description="Returns all transport network slices from the slice controller.") - @ixia_ns.response(200, "Slices returned", slice_ddbb_model) - @ixia_ns.response(404, "Transport network slices not found") - @ixia_ns.response(500, "Internal server error") - def get(self): - """Retrieve all slices""" - controller = NSController(controller_type="IXIA") - return controller.get_flows() - - @ixia_ns.doc(summary="Submit a transport network slice request", description="This endpoint allows clients to submit transport network slice requests using a JSON payload.") - @ixia_ns.response(200, "Slice request successfully processed", slice_response_model) - @ixia_ns.response(400, "Invalid request format") - @ixia_ns.response(500, "Internal server error") - @ixia_ns.expect(upload_parser) - def post(self): - """Submit a new slice request with a file""" - - json_data = None - - # Try to get the JSON data from the uploaded file - uploaded_file = request.files.get('file') - if uploaded_file: - if not uploaded_file.filename.endswith('.json'): - return {"error": "Only JSON files allowed"}, 400 - - try: - json_data = json.load(uploaded_file) # Convert file to JSON - except json.JSONDecodeError: - return {"error": "JSON file not valid"}, 400 - - # If no file was uploaded, try to get the JSON data from the form - if json_data is None: - raw_json = request.form.get('json_data') - if raw_json: - try: - json_data = json.loads(raw_json) # Convert string to JSON - except json.JSONDecodeError: - return {"error": "JSON file not valid"}, 400 - - # If no JSON data was found, return an error - if json_data is None: - return {"error": "No data sent"}, 400 - - # Process the JSON data with the NSController - controller = NSController(controller_type="IXIA") - return controller.add_flow(json_data) - - @ixia_ns.doc(summary="Delete all transport network slices", description="Deletes all transport network slices from the slice controller.") - @ixia_ns.response(200, "All transport network slices deleted successfully.") - @ixia_ns.response(500, "Internal server error") - def delete(self): - """Delete all slices""" - controller = NSController(controller_type="IXIA") - return controller.delete_flows() - - -@ixia_ns.route("/slice/") -@ixia_ns.doc(params={"slice_id": "The ID of the slice to retrieve or modify"}) -class IxiaSlice(Resource): - @ixia_ns.doc(summary="Return a specific transport network slice", description="Returns specific information related to a slice by providing its id") - @ixia_ns.response(200, "Slice returned", slice_ddbb_model) - @ixia_ns.response(404, "Transport network slice not found.") - @ixia_ns.response(500, "Internal server error") - def get(self, slice_id): - """Retrieve a specific slice""" - controller = NSController(controller_type="IXIA") - return controller.get_flows(slice_id) - - @ixia_ns.doc(summary="Delete a specific transport network slice", description="Deletes a specific transport network slice from the slice controller based on the provided `slice_id`.") - @ixia_ns.response(200, "Transport network slice deleted successfully.") - @ixia_ns.response(404, "Transport network slice not found.") - @ixia_ns.response(500, "Internal server error") - def delete(self, slice_id): - """Delete a slice""" - controller = NSController(controller_type="IXIA") - return controller.delete_flows(slice_id) - - @ixia_ns.expect(slice_ddbb_model, validate=True) - @ixia_ns.doc(summary="Modify a specific transport network slice", description="Returns a specific slice that has been modified") - @ixia_ns.response(200, "Slice modified", slice_ddbb_model) - @ixia_ns.response(404, "Transport network slice not found.") - @ixia_ns.response(500, "Internal server error") - def put(self, slice_id): - """Modify a slice""" - json_data = request.get_json() - controller = NSController(controller_type="IXIA") - return controller.modify_flow(slice_id, json_data) \ No newline at end of file diff --git a/swagger/tfs_namespace.py b/swagger/slice_namespace.py similarity index 52% rename from swagger/tfs_namespace.py rename to swagger/slice_namespace.py index c9c3e07f591d13390df92712a746843a8d2326bd..0f629f97e1a8ecbf4550f3e5a24e5ecca46c15ae 100644 --- a/swagger/tfs_namespace.py +++ b/swagger/slice_namespace.py @@ -20,39 +20,39 @@ from src.network_slice_controller import NSController import json from swagger.models.create_models import create_gpp_nrm_28541_model, create_ietf_network_slice_nbi_yang_model -tfs_ns = Namespace( - "tfs", - description="Operations related to transport network slices with TeraflowSDN (TFS) controller" +slice_ns = Namespace( + "slice", + description="Operations related to transport network slices" ) # 3GPP NRM TS28.541 Data models -gpp_network_slice_request_model = create_gpp_nrm_28541_model(tfs_ns) +gpp_network_slice_request_model = create_gpp_nrm_28541_model(slice_ns) # IETF draft-ietf-teas-ietf-network-slice-nbi-yang Data models -slice_ddbb_model, slice_response_model = create_ietf_network_slice_nbi_yang_model(tfs_ns) +slice_ddbb_model, slice_response_model = create_ietf_network_slice_nbi_yang_model(slice_ns) upload_parser = reqparse.RequestParser() upload_parser.add_argument('file', location='files', type='FileStorage', help="Archivo a subir") upload_parser.add_argument('json_data', location='form', help="Datos JSON en formato string") # Namespace Controllers -@tfs_ns.route("/slice") -class TfsSliceList(Resource): - @tfs_ns.doc(summary="Return all transport network slices", description="Returns all transport network slices from the slice controller.") - @tfs_ns.response(200, "Slices returned", slice_ddbb_model) - @tfs_ns.response(404, "Transport network slices not found") - @tfs_ns.response(500, "Internal server error") +@slice_ns.route("/") +class SliceList(Resource): + @slice_ns.doc(summary="Return all transport network slices", description="Returns all transport network slices from the slice controller.") + @slice_ns.response(200, "Slices returned", slice_ddbb_model) + @slice_ns.response(404, "Transport network slices not found") + @slice_ns.response(500, "Internal server error") def get(self): """Retrieve all slices""" - controller = NSController(controller_type="TFS") + controller = NSController() return controller.get_flows() - @tfs_ns.doc(summary="Submit a transport network slice request", description="This endpoint allows clients to submit transport network slice requests using a JSON payload.") - @tfs_ns.response(200, "Slice request successfully processed", slice_response_model) - @tfs_ns.response(400, "Invalid request format") - @tfs_ns.response(500, "Internal server error") - @tfs_ns.expect(upload_parser) + @slice_ns.doc(summary="Submit a transport network slice request", description="This endpoint allows clients to submit transport network slice requests using a JSON payload.") + @slice_ns.response(200, "Slice request successfully processed", slice_response_model) + @slice_ns.response(400, "Invalid request format") + @slice_ns.response(500, "Internal server error") + @slice_ns.expect(upload_parser) def post(self): """Submit a new slice request with a file""" @@ -83,48 +83,46 @@ class TfsSliceList(Resource): return {"error": "No data sent"}, 400 # Process the JSON data with the NSController - controller = NSController(controller_type="TFS") + controller = NSController() return controller.add_flow(json_data) - @tfs_ns.doc(summary="Delete all transport network slices", description="Deletes all transport network slices from the slice controller.") - @tfs_ns.response(200, "All transport network slices deleted successfully.") - @tfs_ns.response(500, "Internal server error") + @slice_ns.doc(summary="Delete all transport network slices", description="Deletes all transport network slices from the slice controller.") + @slice_ns.response(200, "All transport network slices deleted successfully.") + @slice_ns.response(500, "Internal server error") def delete(self): """Delete all slices""" - controller = NSController(controller_type="TFS") + controller = NSController() return controller.delete_flows() -@tfs_ns.route("/slice/") -@tfs_ns.doc(params={"slice_id": "The ID of the slice to retrieve or modify"}) -class TfsSlice(Resource): - @tfs_ns.doc(summary="Return a specific transport network slice", description="Returns specific information related to a slice by providing its id") - @tfs_ns.response(200, "Slice returned", slice_ddbb_model) - @tfs_ns.response(404, "Transport network slice not found.") - @tfs_ns.response(500, "Internal server error") +@slice_ns.route("/") +@slice_ns.doc(params={"slice_id": "The ID of the slice to retrieve or modify"}) +class Slice(Resource): + @slice_ns.doc(summary="Return a specific transport network slice", description="Returns specific information related to a slice by providing its id") + @slice_ns.response(200, "Slice returned", slice_ddbb_model) + @slice_ns.response(404, "Transport network slice not found.") + @slice_ns.response(500, "Internal server error") def get(self, slice_id): """Retrieve a specific slice""" - controller = NSController(controller_type="TFS") + controller = NSController() return controller.get_flows(slice_id) - @tfs_ns.doc(summary="Delete a specific transport network slice", description="Deletes a specific transport network slice from the slice controller based on the provided `slice_id`.") - @tfs_ns.response(200, "Transport network slice deleted successfully.") - @tfs_ns.response(404, "Transport network slice not found.") - @tfs_ns.response(500, "Internal server error") + @slice_ns.doc(summary="Delete a specific transport network slice", description="Deletes a specific transport network slice from the slice controller based on the provided `slice_id`.") + @slice_ns.response(200, "Transport network slice deleted successfully.") + @slice_ns.response(404, "Transport network slice not found.") + @slice_ns.response(500, "Internal server error") def delete(self, slice_id): """Delete a slice""" - controller = NSController(controller_type="TFS") + controller = NSController() return controller.delete_flows(slice_id) - @tfs_ns.expect(slice_ddbb_model, validate=True) - @tfs_ns.doc(summary="Modify a specific transport network slice", description="Returns a specific slice that has been modified") - @tfs_ns.response(200, "Slice modified", slice_ddbb_model) - @tfs_ns.response(404, "Transport network slice not found.") - @tfs_ns.response(500, "Internal server error") + @slice_ns.expect(slice_ddbb_model, validate=True) + @slice_ns.doc(summary="Modify a specific transport network slice", description="Returns a specific slice that has been modified") + @slice_ns.response(200, "Slice modified", slice_ddbb_model) + @slice_ns.response(404, "Transport network slice not found.") + @slice_ns.response(500, "Internal server error") def put(self, slice_id): """Modify a slice""" json_data = request.get_json() - controller = NSController(controller_type="TFS") + controller = NSController() return controller.modify_flow(slice_id, json_data) - -