Commit 8a83fbb4 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Merge branch 'rahhal-feat/163-implement-camara-based-nbi-connector-patch-789a'...

Merge branch 'rahhal-feat/163-implement-camara-based-nbi-connector-patch-789a' into 'feat/163-implement-camara-based-nbi-connector'

Polish "Implement CAMARA-based NBI connector"

See merge request !325
parents 4964ac9e 0f3fc78c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -134,7 +134,7 @@ export CRDB_PASSWORD="tfs123"
export CRDB_DEPLOY_MODE="single"

# Disable flag for dropping database, if it exists.
export CRDB_DROP_DATABASE_IF_EXISTS="YES"
export CRDB_DROP_DATABASE_IF_EXISTS=""

# Disable flag for re-deploying CockroachDB from scratch.
export CRDB_REDEPLOY=""
+21 −27
Original line number Diff line number Diff line
# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
# Copyright 2022-2024 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.
@@ -11,31 +11,26 @@
# 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.
from flask.json import jsonify
from flask_restful import Resource, request
from enum import Enum
import grpc._channel
from qos_profile.client.QoSProfileClient import QoSProfileClient
from werkzeug.exceptions import UnsupportedMediaType
from common.proto.context_pb2 import  QoSProfileId, Uuid,Empty
from common.proto.qos_profile_pb2 import  QoDConstraintsRequest


import copy, grpc, grpc._channel, logging
from typing import Dict
from uuid import uuid4
import grpc, logging
import copy, deepmerge, json, logging
from typing import Dict
from flask.json import jsonify
from flask_restful import Resource, request
from werkzeug.exceptions import UnsupportedMediaType
from common.proto.context_pb2 import  QoSProfileId, Uuid,Empty
from common.Constants import DEFAULT_CONTEXT_NAME
from context.client.ContextClient import ContextClient
from qos_profile.client.QoSProfileClient import QoSProfileClient
from service.client.ServiceClient import ServiceClient
from .Tools import (
    format_grpc_to_json, grpc_context_id, grpc_service_id, QOD_2_service, service_2_qod,grpc_message_to_qos_table_data,create_qos_profile_from_json
    format_grpc_to_json, grpc_context_id, grpc_service_id,
    QOD_2_service, service_2_qod, grpc_message_to_qos_table_data,
    create_qos_profile_from_json
)


LOGGER = logging.getLogger(__name__)
#Initiate the QoSProfileClient

class _Resource(Resource):
    def __init__(self) -> None:
        super().__init__()
@@ -56,13 +51,13 @@ class ProfileList(_Resource):
        except Exception as e:
            LOGGER.error(e) # track if there is an error
            raise e  
        # Send to gRPC server using CreateQosProfile done by Shayan
        # Send to gRPC server using CreateQosProfile 
        try:
            qos_profile_created = self.qos_profile_client.CreateQoSProfile(qos_profile) 
        except Exception as e:
            LOGGER.info(e)
            LOGGER.error(e)
            raise e
        #gRPC message back to JSON using the helper function created by shayan 
        #gRPC message back to JSON using the helper function 
        qos_profile_data = grpc_message_to_qos_table_data(qos_profile_created)
        LOGGER.info(f'qos_profile_data{qos_profile_data}')       
        return jsonify(qos_profile_data)
@@ -140,8 +135,7 @@ class ProfileDetail(_Resource):
            return {"error": "Internal Server Error"}, 500
        
###SESSION##########################################################
LOGGER = logging.getLogger(__name__)
class qodinfo(_Resource):
class QodInfo(_Resource):
    def post(self):
        if not request.is_json:
            return (jsonify({'error': 'Unsupported Media Type', 'message': 'JSON payload is required'}), 415)
@@ -163,18 +157,18 @@ class qodinfo(_Resource):
            response = format_grpc_to_json(self.service_client.CreateService(stripped_service))
            response = format_grpc_to_json(self.service_client.UpdateService(service))
        except Exception as e: # pylint: disable=broad-except
            LOGGER.error(f"Unexpected error: {str(e)}", exc_info=True)
            return jsonify({'error': 'Internal Server Error', 'message': 'An unexpected error occurred'}), 500
        LOGGER.error(f"error related to response: {response}")
            return e

        return response
    
    def get(self):
        service_list = self.client.ListServices(grpc_context_id(DEFAULT_CONTEXT_NAME)) #return context id as json
        qod_info = [service_2_qod(service) for service in service_list.services] #iterating over service list 
        LOGGER.info(f"error related to qod_info: {qod_info}")
        return qod_info
        return jsonify(qod_info), 200
           
class qodinfoId(_Resource):
class QodInfoID(_Resource):

    def get(self, sessionId: str):
        try:
+7 −23
Original line number Diff line number Diff line
# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
# Copyright 2022-2024 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.
@@ -91,7 +91,7 @@ def ip_withoutsubnet(ip_withsubnet,neededip):
    return IPAddress(neededip) in network


def QOD_2_service(client,qod_info: dict,qos_profile_id,duration) -> Service:
def QOD_2_service(client,qod_info: dict,qos_profile_id: int,duration: int) -> Service:
    qos_profile_client = QoSProfileClient()
    service = Service()
    service_config_rules = service.service_config.config_rules
@@ -110,8 +110,8 @@ def QOD_2_service(client,qod_info: dict,qos_profile_id,duration) -> Service:
        a_ip = qod_info['device'].get('ipv4Address')
        z_ip = qod_info['applicationServer'].get('ipv4Address')

        LOGGER.info('a_ip = {:s}'.format(str(a_ip)))
        LOGGER.info('z_ip = {:s}'.format(str(z_ip)))
        LOGGER.debug('a_ip = {:s}'.format(str(a_ip)))
        LOGGER.debug('z_ip = {:s}'.format(str(z_ip)))

        if a_ip and z_ip:
            devices = client.ListDevices(Empty()).devices
@@ -133,9 +133,9 @@ def QOD_2_service(client,qod_info: dict,qos_profile_id,duration) -> Service:
                    if not match_subif:
                        continue
                    address_ip =json.loads(cr.custom.resource_value).get('address_ip')
                    LOGGER.info('cr..address_ip = {:s}'.format(str(address_ip)))
                    LOGGER.debug('cr..address_ip = {:s}'.format(str(address_ip)))
                    short_port_name = match_subif.groups()[0]
                    LOGGER.info('short_port_name = {:s}'.format(str(short_port_name)))
                    LOGGER.debug('short_port_name = {:s}'.format(str(short_port_name)))

                    ip_interface_name_dict[address_ip] = short_port_name
                    
@@ -145,7 +145,7 @@ def QOD_2_service(client,qod_info: dict,qos_profile_id,duration) -> Service:
                    ep_id.endpoint_uuid.uuid = device_endpoint_uuids.get(short_port_name , '')
                    ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid
                    service.service_endpoint_ids.append(ep_id)
                    LOGGER.info(f"the ip address{ep_id}")
                    LOGGER.debug(f"the ip address{ep_id}")
    
            #LOGGER.info('ip_interface_name_dict = {:s}'.format(str(ip_interface_name_dict)))
    
@@ -158,17 +158,6 @@ def QOD_2_service(client,qod_info: dict,qos_profile_id,duration) -> Service:
    qod_info["context"]='admin'
    service.service_id.service_uuid.uuid = qod_info['sessionID']
    service.service_id.context_id.context_uuid.uuid = qod_info["context"]

    #try:
    #    id = QoSProfileId(qos_profile_id=Uuid(uuid=qos_profile_id))
    #    id= QoSProfileId()
    #    id.qos_profile_id.uuid="qos_profile_id"
    #    qos_profile = qos_profile_client.GetQoSProfile(id)
    #except grpc._channel._InactiveRpcError as exc:
    #    if exc.code() == grpc.StatusCode.NOT_FOUND:
    #        return {"error": f"QoSProfile {qos_profile_id} not found"}, 404 
    #if qos_profile.qos_profile_id:
    #    qos_profile_id = qod_info.get('qos_profile_id')
    service.name = qod_info.get('qos_profile_id', qos_profile_id)    
    current_time = time.time() 
    duration_days = duration  # days as i saw it in the proto files
@@ -186,11 +175,6 @@ def QOD_2_service(client,qod_info: dict,qos_profile_id,duration) -> Service:
            cs.qos_profile.qos_profile_name.CopyFrom(qos_profile_client.name) #i copied this from the qosprofile
            LOGGER.info(f'the cs : {cs}')
        service.service_constraints.append(cs)
        #qos_profile = QoSProfile()
        #qos_profile.qos_profile_id.qos_profile_id.uuid = qod_info['qosProfile']
    #if 'qosProfile' in qos_profile_list:
    #    qos_profile = QoSProfile()
    #    qos_profile.qos_profile_id.qos_profile_id.uuid = qod_info['qosProfile']

    return service

+6 −7
Original line number Diff line number Diff line
# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
# Copyright 2022-2024 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.
@@ -13,16 +13,15 @@
# limitations under the License.

from nbi.service.rest_server.RestServer import RestServer
from .Resources import ProfileList, ProfileDetail, qodinfo, qodinfoId
from .Resources import ProfileList, ProfileDetail, QodInfo, QodInfoID

URL_PREFIX = '/camara/qod/v0'

# Use 'path' type since some identifiers might contain char '/' and Flask is unable to recognize them in 'string' type.
RESOURCES = [
    # (endpoint_name, resource_class, resource_url)
    # TODO: Add appropriate endpoints
    ('camara.qod_session_info',         qodinfo,     '/sessions'),
    ('camara.qod_info_session_id',      qodinfoId,   '/sessions/<sessionId>'),
    ('camara.qod_session_info',    QodInfo,       '/sessions'),
    ('camara.qod_info_session_id', QodInfoID,     '/sessions/<sessionId>'),
    ('camara.qod.profile_list',    ProfileList,   '/profiles'),
    ('camara.qod.profile_detail',  ProfileDetail, '/profiles/<string:qos_profile_id>'),
]
+1 −2
Original line number Diff line number Diff line
@@ -19,10 +19,9 @@ import requests

logging.basicConfig(level=logging.DEBUG)
LOGGER = logging.getLogger()
BASE_URL = 'http://10.1.7.197/camara/qod/v0'

def test_create_profile():
    BASE_URL = 'http://10.1.7.197/camara/qod/v0'
    BASE_URL = 'http://localhost/camara/qod/v0'
    qos_profile_data={  
                      "name": "QCI_2_voice",
                      "description": "QoS profile for video streaming",
Loading