Skip to content
Snippets Groups Projects
Commit dd6b162d authored by Pablo Armingol's avatar Pablo Armingol
Browse files

L3SM testing

parent 8fcdf991
No related branches found
No related tags found
2 merge requests!341Draft: Resolve "optical bandwidth expansion",!239Draft: Resolve "(TID) Creation of IP link with supporting coherent pluggable to pluggable connection"
{
"l3vpn-svc": {
"vpn-services": {
"vpn-service": [
{
"vpn-id": "vpn2"
}
]
},
"sites": {
"site": [
{
"site-id": "site_OLT",
"locations": {
"location": [
{
"location-id": "OLT"
}
]
},
"devices": {
"device": [
{
"device-id": "128.32.33.5",
"location": "OLT"
}
]
},
"management": {
"type": "ietf-l3vpn-svc:provider-managed"
},
"routing-protocols": {
"routing-protocol": [
{
"type": "ietf-l3vpn-svc:static",
"static": {
"cascaded-lan-prefixes": {
"ipv4-lan-prefixes": [
{
"lan": "128.32.10.0/24",
"next-hop": "128.32.33.2",
"lan-tag": "vlan31"
},
{
"lan": "128.32.20.0/24",
"next-hop": "128.32.33.2",
"lan-tag": "vlan31"
}
]
}
}
}
]
},
"site-network-accesses": {
"site-network-access": [
{
"site-network-access-id": "500",
"site-network-access-type": "ietf-l3vpn-svc:multipoint",
"device-reference": "128.32.33.5",
"ip-connection": {
"ipv4": {
"address-allocation-type": "ietf-l3vpn-svc:static-address",
"addresses": {
"provider-address": "128.32.33.254",
"customer-address": "128.32.33.2",
"prefix-length": 24
}
}
},
"service": {
"svc-input-bandwidth": 1000000000,
"svc-output-bandwidth": 1000000000,
"svc-mtu": 1500,
"qos": {
"qos-profile": {
"classes": {
"class": [
{
"class-id": "qos-realtime",
"direction": "ietf-l3vpn-svc:both",
"latency": {
"latency-boundary": 10
},
"bandwidth": {
"guaranteed-bw-percent": 100.0
}
}
]
}
}
}
},
"routing-protocols": {
"routing-protocol": [
{
"type": "ietf-l3vpn-svc:static",
"static": {
"cascaded-lan-prefixes": {
"ipv4-lan-prefixes": [
{
"lan": "172.1.201.0/24",
"next-hop": "128.32.33.254",
"lan-tag": "vlan31"
}
]
}
}
}
]
},
"vpn-attachment": {
"vpn-id": "vpn2",
"site-role": "ietf-l3vpn-svc:spoke-role"
}
}
]
}
},
{
"site-id": "site_POP",
"locations": {
"location": [
{
"location-id": "POP"
}
]
},
"devices": {
"device": [
{
"device-id": "172.10.33.5",
"location": "POP"
}
]
},
"management": {
"type": "ietf-l3vpn-svc:provider-managed"
},
"routing-protocols": {
"routing-protocol": [
{
"type": "ietf-l3vpn-svc:static",
"static": {
"cascaded-lan-prefixes": {
"ipv4-lan-prefixes": [
{
"lan": "172.1.201.0/24",
"next-hop": "172.10.33.2",
"lan-tag": "vlan201"
}
]
}
}
}
]
},
"site-network-accesses": {
"site-network-access": [
{
"site-network-access-id": "500",
"site-network-access-type": "ietf-l3vpn-svc:multipoint",
"device-reference": "172.10.33.5",
"ip-connection": {
"ipv4": {
"address-allocation-type": "ietf-l3vpn-svc:static-address",
"addresses": {
"provider-address": "172.10.33.254",
"customer-address": "172.10.33.2",
"prefix-length": 24
}
}
},
"service": {
"svc-input-bandwidth": 1000000000,
"svc-output-bandwidth": 1000000000,
"svc-mtu": 1500,
"qos": {
"qos-profile": {
"classes": {
"class": [
{
"class-id": "qos-realtime",
"direction": "ietf-l3vpn-svc:both",
"latency": {
"latency-boundary": 10
},
"bandwidth": {
"guaranteed-bw-percent": 100.0
}
}
]
}
}
}
},
"routing-protocols": {
"routing-protocol": [
{
"type": "ietf-l3vpn-svc:static",
"static": {
"cascaded-lan-prefixes": {
"ipv4-lan-prefixes": [
{
"lan": "128.32.10.0/24",
"next-hop": "172.10.33.254",
"lan-tag": "vlan201"
},
{
"lan": "128.32.20.0/24",
"next-hop": "172.10.33.254",
"lan-tag": "vlan201"
}
]
}
}
}
]
},
"vpn-attachment": {
"vpn-id": "vpn2",
"site-role": "ietf-l3vpn-svc:hub-role"
}
}
]
}
}
]
}
}
}
\ No newline at end of file
......@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging, netaddr
import logging, netaddr, json
from typing import Dict, List, Optional, Tuple
from common.Constants import DEFAULT_CONTEXT_NAME
from common.proto.context_pb2 import Service, ServiceStatusEnum, ServiceTypeEnum
......@@ -26,6 +26,9 @@ from common.tools.grpc.EndPointIds import update_endpoint_ids
from context.client.ContextClient import ContextClient
from service.client.ServiceClient import ServiceClient
from .ReadServiceFunctionDefinition import ReadServiceFunctionDefinition
from .WriteNetworkFunctionDefinition import WriteNetworkFunctionDefinition
LOGGER = logging.getLogger(__name__)
def create_service(
......@@ -209,3 +212,55 @@ def process_site(site : Dict, errors : List[Dict]) -> None:
network_accesses : List[Dict] = site['site-network-accesses']['site-network-access']
for network_access in network_accesses:
process_site_network_access(site_id, network_access, site_static_routing, errors)
def convert_l3sm_to_l3nm():
jsonRequest = open("/home/ubuntu/tfs-ctrl/src/nbi/tests/ietf_l3vpn_req_svc1.json", "r") #devuelve un file-object. "r" es por reading
output_file_path = "/home/ubuntu/tfs-ctrl/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/EstructuraIntermedia.json"
jsonRequestData : str = jsonRequest.read() #jsonRequestData es de tipo str. Para leer el contenido, usamos read()
jParse : Dict = json.loads(jsonRequestData) #jParse es de tipo Dict. esto va a parsear jsonRequetData.
#cuando obtengamos el valor de una clave, y ese valor sea un array [], el tipo será 'list'
#in order to convert a jsonObject to an string, you can use .dumps
ietf_l3vpn : Dict = jParse['ietf-l3vpn-svc:l3vpn-svc']
vpn_services : Dict = ietf_l3vpn['vpn-services']
#print(vpn_services)
# vpn_service = vpn_services['vpn-service'] #ahora, al ser vpn-service un array, creo que la variable vpn_service es de tipo 'list'
# print(type(vpn_service)) #list
# print("VPN_SERVICE: " + str(vpn_service))
# print(vpn_service[0])
# print(vpn_service[0]['vpn-id'])
bd : Dict[any, any] = {} #Base datos de variables del JSON
#vpn_id = MiClase.readVpnServices(vpn_services) #vpn_id es variable de tipo List[str] con todas las vpn posibles
#try:
bd = ReadServiceFunctionDefinition.writeVpnServices( ReadServiceFunctionDefinition.readVpnServices(vpn_services) , bd)
#print(json.dumps(bd, indent=2))
sites : List = ietf_l3vpn['sites']['site'] #En sites se almacena el valor de la clave 'sites'.
#print(json.dumps(sites, indent=2))
#### PEQUEÑA CHAPUZA PARA CUANDO SOLO HAY UNA VPN ####
lista_VPNs : list = bd["VPN_IDs"]
bd["VPNs_Dict"][lista_VPNs[0]].update(ReadServiceFunctionDefinition.readSiteArray(sites, bd)) #vpn1.update Updatea el valor de vpn1
#### # ####
# except Exception as e: #En principio llegaran valueError o NoJSONFieldException
# print(e)
#print(json.dumps(bd, indent=2))
#YANG SUITE ENTRADA, SERVICE ->creo que IETF-NBI-TEF-DECEMBER-23; ietf-l3vpn-svc; edit-config; none selected
#YANG SUITE SALIDA, RED (RFC9182) -> IETF-NBI-TEF-DECEMBER-23; ietf-l3vpn-ntw; edit-config; none selected
#Codigo para crear archivo .json de salida
with open(output_file_path, 'w') as json_file:
json.dump(bd, json_file, indent=3)
jsonL3VPN_net : Dict = WriteNetworkFunctionDefinition.write()
# print(json.dumps(jsonL3VPN_net, indent = 3))
......@@ -11,9 +11,8 @@
# 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.
import json, logging
import logging
from typing import Dict, List
from flask import request
from flask.json import jsonify
......@@ -24,11 +23,6 @@ from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH
from .Handlers import process_site, process_vpn_service
from .YangValidator import YangValidator
# from FunctionDefinition import FunctionDefinition
# from FunctionDefinitionNetwork import FunctionDefinitionNetwork
# import FunctionDefinition
# import FunctionDefinitionNetwork
LOGGER = logging.getLogger(__name__)
class L3VPN_Services(Resource):
......@@ -38,16 +32,9 @@ class L3VPN_Services(Resource):
@HTTP_AUTH.login_required
def post(self):
jsonAValidar = open("/home/ubuntu/Documents/json1.json", "r")
jsonAValidarData : str = jsonAValidar.read()
jsonAValidarDict : Dict = json.loads(jsonAValidarData)
output_file_path = "/home/ubuntu/Documents/EstructuraIntermedia.json"
if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
request_data : Dict = request.json
# LOGGER.debug('Request: {:s}'.format(str(request_data)))
LOGGER.debug('Request: {:s}'.format(str(jsonAValidarDict)))
LOGGER.debug('Request: {:s}'.format(str(request_data)))
errors = list()
if 'ietf-l3vpn-svc:l3vpn-services' in request_data:
......@@ -79,53 +66,15 @@ class L3VPN_Services(Resource):
def _process_l3vpn(self, request_data : Dict) -> List[Dict]:
yang_validator = YangValidator('ietf-l3vpn-svc')
request_data = yang_validator.parse_to_dict(jsonAValidarDict)
request_data = yang_validator.parse_to_dict(request_data)
yang_validator.destroy()
#se supone que a partir de aqui ya ha validado
jParse = jsonAValidarDict
ietf_l3vpn : Dict = jParse['ietf-l3vpn-svc:l3vpn-svc']
vpn_services : Dict = ietf_l3vpn['vpn-services']
bd : Dict[any, any] = {} #Base datos de variables del JSON
bd = FunctionDefinition.writeVpnServices( FunctionDefinition.readVpnServices(vpn_services) , bd)
sites : List = ietf_l3vpn['sites']['site'] #En sites se almacena el valor de la clave 'sites'.
#### FUNCIONA SOLO CON 1 VPN ####
lista_VPNs = bd["VPN_IDs"]
bd["VPNs_Dict"][lista_VPNs[0]].update(FunctionDefinition.readSiteArray(sites, bd))
#### --------------------- ####
with open(output_file_path, 'w') as json_file:
json.dump(bd, json_file, indent=3)
jsonL3VPN_net : Dict = FunctionDefinitionNetwork.write()
# print(json.dumps(jsonL3VPN_net, indent = 3))
######
errors = []
errors = list()
# for vpn_service in request_data['l3vpn-svc']['vpn-services']['vpn-service']:
# process_vpn_service(vpn_service, errors)
for vpn_service in request_data['l3vpn-svc']['vpn-services']['vpn-service']:
process_vpn_service(vpn_service, errors)
# for site in request_data['l3vpn-svc']['sites']['site']:
# process_site(site, errors)
for site in request_data['l3vpn-svc']['sites']['site']:
process_site(site, errors)
# response = jsonify(errors)
# response.status_code = HTTP_CREATED if len(errors) == 0 else HTTP_SERVERERROR
# return response
return errors
from typing import Dict, List
import json
import json, os
class FunctionDefinitionNetwork:
class WriteNetworkFunctionDefinition:
jsonEstructuraIntermedia = open("/home/ubuntu/Documents/EstructuraIntermedia.json", "r")
input_file_path : str ="/home/ubuntu/Documents/EstructuraIntermedia.json"
output_file_path = "/home/ubuntu/Documents/L3VPN_ntw.json"
jsonEstructuraIntermedia = open(input_file_path, "r")
jsonEstructuraIntermediaData : str = jsonEstructuraIntermedia.read()
jsonEstIntDict : Dict = json.loads(jsonEstructuraIntermediaData)
@staticmethod
def numberVpnIDs() -> int :
vpnIDs : List = FunctionDefinitionNetwork.jsonEstIntDict["VPN_IDs"]
vpnIDs : List = WriteNetworkFunctionDefinition.jsonEstIntDict["VPN_IDs"]
return len(vpnIDs)
#Este metodo devuelve el numero de sites, y es necesario porque el numero de sites es el numero de nodes
@staticmethod
def numberSitesIDS() -> int :
sitesIDs : List = FunctionDefinitionNetwork.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"]
sitesIDs : List = WriteNetworkFunctionDefinition.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"]
return len(sitesIDs)
@staticmethod
......@@ -24,7 +26,7 @@ class FunctionDefinitionNetwork:
jsonNet : Dict = {}
jsonNet.update({"vpn-service":{}}) #no tenemos en cuenta que puede haber más de 1 VPN. Codigo valido para 1 VPN solo
vpn_id : str = FunctionDefinitionNetwork.jsonEstIntDict["VPN_IDs"][0].split("vpn")[1] #obtengo el numero de vpn_id
vpn_id : str = WriteNetworkFunctionDefinition.jsonEstIntDict["VPN_IDs"][0].split("vpn")[1] #obtengo el numero de vpn_id
jsonNet["vpn-service"]["vpn-id"] = vpn_id #de momento solo 1 vpn
# jsonNet["vpn-service"]["customer-name"] = "_"
# jsonNet["vpn-service"]["parent-service-id"] = "_"
......@@ -33,24 +35,24 @@ class FunctionDefinitionNetwork:
jsonNet["vpn-service"]["vpn-nodes"] = {}
arrayVpnNode : List = []
print(FunctionDefinitionNetwork.numberSitesIDS())
for numeroDeNode in range(FunctionDefinitionNetwork.numberSitesIDS()):
print(WriteNetworkFunctionDefinition.numberSitesIDS())
for numeroDeNode in range(WriteNetworkFunctionDefinition.numberSitesIDS()):
sites : List = FunctionDefinitionNetwork.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"]
sites : List = WriteNetworkFunctionDefinition.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"]
site: str = FunctionDefinitionNetwork.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"][numeroDeNode]
service_access: str = FunctionDefinitionNetwork.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sites_Dict"][sites[numeroDeNode]]["site-network-accesses"]["site-network-accesses-IDs"][0]
site: str = WriteNetworkFunctionDefinition.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"][numeroDeNode]
service_access: str = WriteNetworkFunctionDefinition.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sites_Dict"][sites[numeroDeNode]]["site-network-accesses"]["site-network-accesses-IDs"][0]
#con los siguientes ifs hago que las politicas cambien de lugar, uno si y uno no constantemente
if numeroDeNode % 2 is 0:
arrayVpnNode.append(FunctionDefinitionNetwork.writeNode(FunctionDefinitionNetwork.jsonEstIntDict,site,service_access,numeroDeNode, 0))
arrayVpnNode.append(WriteNetworkFunctionDefinition.writeNode(WriteNetworkFunctionDefinition.jsonEstIntDict,site,service_access,numeroDeNode, 0))
if numeroDeNode % 2 is not 0:
arrayVpnNode.append(FunctionDefinitionNetwork.writeNode(FunctionDefinitionNetwork.jsonEstIntDict,site,service_access,numeroDeNode, 1))
arrayVpnNode.append(WriteNetworkFunctionDefinition.writeNode(WriteNetworkFunctionDefinition.jsonEstIntDict,site,service_access,numeroDeNode, 1))
jsonNet["vpn-service"]["vpn-nodes"]["vpn-node"] = arrayVpnNode
#Codigo para crear el archivo y escribir el json en el
with open(FunctionDefinitionNetwork.output_file_path, 'w') as json_file:
with open(WriteNetworkFunctionDefinition.output_file_path, 'w') as json_file:
json.dump(jsonNet, json_file, indent = 3)
return jsonNet
......@@ -133,7 +135,7 @@ class FunctionDefinitionNetwork:
}
}
vpnNetworkAccessElement.update({"status":status})
vpnNetworkAccessElement.update({"connection":FunctionDefinitionNetwork.writeConnection()})
vpnNetworkAccessElement.update({"connection":WriteNetworkFunctionDefinition.writeConnection()})
vpn_id : str = jsonEstDict["VPN_IDs"][0]#valido cuando solo hay una VPN.
#de momento no IPv6, campo vacio, solo IPv4
......
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
import logging
from typing import Dict, List
from flask import request
from flask.json import jsonify
from flask_restful import Resource
from werkzeug.exceptions import UnsupportedMediaType
from nbi.service.rest_server.nbi_plugins.tools.HttpStatusCodes import HTTP_CREATED, HTTP_SERVERERROR
from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH
from .Handlers import process_site, process_vpn_service
from .YangValidator import YangValidator
LOGGER = logging.getLogger(__name__)
class L3VPN_Services(Resource):
@HTTP_AUTH.login_required
def get(self):
return {}
@HTTP_AUTH.login_required
def post(self):
if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
request_data : Dict = request.json
LOGGER.debug('Request: {:s}'.format(str(request_data)))
errors = list()
if 'ietf-l3vpn-svc:l3vpn-services' in request_data:
# processing multiple L3VPN service requests formatted as:
#{
# "ietf-l3vpn-svc:l3vpn-services": {
# "l3vpn-svc": [
# {
# "service-id": "vpn1",
# "vpn-services": {
# "vpn-service": [
for l3vpn_svc in request_data['ietf-l3vpn-svc:l3vpn-services']['l3vpn-svc']:
l3vpn_svc.pop('service-id', None)
l3vpn_svc_request_data = {'ietf-l3vpn-svc:l3vpn-svc': l3vpn_svc}
errors.extend(self._process_l3vpn(l3vpn_svc_request_data))
elif 'ietf-l3vpn-svc:l3vpn-svc' in request_data:
# processing single (standard) L3VPN service request formatted as:
#{
# "ietf-l3vpn-svc:l3vpn-svc": {
# "vpn-services": {
# "vpn-service": [
errors.extend(self._process_l3vpn(request_data))
else:
errors.append('unexpected request: {:s}'.format(str(request_data)))
response = jsonify(errors)
response.status_code = HTTP_CREATED if len(errors) == 0 else HTTP_SERVERERROR
return response
def _process_l3vpn(self, request_data : Dict) -> List[Dict]:
yang_validator = YangValidator('ietf-l3vpn-svc')
request_data = yang_validator.parse_to_dict(request_data)
yang_validator.destroy()
errors = list()
for vpn_service in request_data['l3vpn-svc']['vpn-services']['vpn-service']:
process_vpn_service(vpn_service, errors)
for site in request_data['l3vpn-svc']['sites']['site']:
process_site(site, errors)
return errors
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment