From 0b15ad14da2cf5d4a51129a212e0756265948bc8 Mon Sep 17 00:00:00 2001
From: Mohamad Rahhal <mrahhal@cttc.es>
Date: Tue, 11 Feb 2025 12:28:33 +0000
Subject: [PATCH 1/2] QOS CAMARA- NBI: - Correction After Shayan's Review

---
 manifests/nbiservice.yaml                     |  2 +-
 manifests/qos_profileservice.yaml             |  2 +-
 my_deploy.sh                                  |  2 +-
 .../nbi_plugins/camara_qod/Resources.py       | 21 +++++++-------
 .../nbi_plugins/camara_qod/Tools.py           | 28 ++++---------------
 src/nbi/tests/test_camara_qod_profile.py      |  3 +-
 src/nbi/tests/test_camara_qos_service.py      |  3 +-
 7 files changed, 21 insertions(+), 40 deletions(-)

diff --git a/manifests/nbiservice.yaml b/manifests/nbiservice.yaml
index c156ef26c..55accdc44 100644
--- a/manifests/nbiservice.yaml
+++ b/manifests/nbiservice.yaml
@@ -41,7 +41,7 @@ spec:
             - containerPort: 8762
           env:
             - name: LOG_LEVEL
-              value: "DEBUG"
+              value: "INFO"
             - name: IETF_NETWORK_RENDERER
               value: "LIBYANG"
             - name: WS_E2E_PORT
diff --git a/manifests/qos_profileservice.yaml b/manifests/qos_profileservice.yaml
index b851aec4d..01b8adf76 100644
--- a/manifests/qos_profileservice.yaml
+++ b/manifests/qos_profileservice.yaml
@@ -38,7 +38,7 @@ spec:
             - containerPort: 9192
           env:
             - name: LOG_LEVEL
-              value: "DEBUG"
+              value: "INFO"
             - name: CRDB_DATABASE
               value: "tfs_qos_profile"
           envFrom:
diff --git a/my_deploy.sh b/my_deploy.sh
index 7984f77d0..225480682 100644
--- a/my_deploy.sh
+++ b/my_deploy.sh
@@ -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=""
diff --git a/src/nbi/service/rest_server/nbi_plugins/camara_qod/Resources.py b/src/nbi/service/rest_server/nbi_plugins/camara_qod/Resources.py
index b208b561f..9e1072afe 100644
--- a/src/nbi/service/rest_server/nbi_plugins/camara_qod/Resources.py
+++ b/src/nbi/service/rest_server/nbi_plugins/camara_qod/Resources.py
@@ -54,15 +54,15 @@ class ProfileList(_Resource):
         try:
             qos_profile = create_qos_profile_from_json(request_data)
         except Exception as e:
-            LOGGER.info(e) # track if there is an error
+            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 +140,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 +162,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
-            
-            return e
-        LOGGER.info(f"error related to response: {response}")
+            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 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:
diff --git a/src/nbi/service/rest_server/nbi_plugins/camara_qod/Tools.py b/src/nbi/service/rest_server/nbi_plugins/camara_qod/Tools.py
index 1b246a79d..feec71cb6 100644
--- a/src/nbi/service/rest_server/nbi_plugins/camara_qod/Tools.py
+++ b/src/nbi/service/rest_server/nbi_plugins/camara_qod/Tools.py
@@ -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
 
diff --git a/src/nbi/tests/test_camara_qod_profile.py b/src/nbi/tests/test_camara_qod_profile.py
index 4408305a9..7acb20374 100644
--- a/src/nbi/tests/test_camara_qod_profile.py
+++ b/src/nbi/tests/test_camara_qod_profile.py
@@ -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",
diff --git a/src/nbi/tests/test_camara_qos_service.py b/src/nbi/tests/test_camara_qos_service.py
index fe4ee3f2e..e74e68231 100644
--- a/src/nbi/tests/test_camara_qos_service.py
+++ b/src/nbi/tests/test_camara_qos_service.py
@@ -18,9 +18,8 @@ import requests
 
 logging.basicConfig(level=logging.DEBUG)
 LOGGER = logging.getLogger()
-BASE_URL = 'http://10.1.7.197/camara/qod/v0'
 def test_create_SESSION():
-    BASE_URL = 'http://10.1.7.197/camara/qod/v0'
+    BASE_URL = 'http://localhost/camara/qod/v0'
     service_data={  
     "device":
         {"ipv4Address":"84.75.11.12/25" },
-- 
GitLab


From 0f3fc78c4602b3a70b4e54efbffa155bdea437d8 Mon Sep 17 00:00:00 2001
From: gifrerenom <lluis.gifre@cttc.es>
Date: Wed, 12 Feb 2025 17:09:54 +0000
Subject: [PATCH 2/2] Pre-merge code cleanup

---
 .../nbi_plugins/camara_qod/Resources.py       | 29 ++++++++-----------
 .../nbi_plugins/camara_qod/Tools.py           |  2 +-
 .../nbi_plugins/camara_qod/__init__.py        | 13 ++++-----
 3 files changed, 19 insertions(+), 25 deletions(-)

diff --git a/src/nbi/service/rest_server/nbi_plugins/camara_qod/Resources.py b/src/nbi/service/rest_server/nbi_plugins/camara_qod/Resources.py
index 253823545..cd89c02fb 100644
--- a/src/nbi/service/rest_server/nbi_plugins/camara_qod/Resources.py
+++ b/src/nbi/service/rest_server/nbi_plugins/camara_qod/Resources.py
@@ -1,4 +1,4 @@
-# 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__)
 
-LOGGER = logging.getLogger(__name__)    
-#Initiate the QoSProfileClient
 class _Resource(Resource):
     def __init__(self) -> None:
         super().__init__()
@@ -43,7 +38,7 @@ class _Resource(Resource):
         self.client = ContextClient()
         self.service_client = ServiceClient()
 
-#ProfileList Endpoint for posting 
+#ProfileList Endpoint for posting
 class ProfileList(_Resource):
     def post(self):
         if not request.is_json:
diff --git a/src/nbi/service/rest_server/nbi_plugins/camara_qod/Tools.py b/src/nbi/service/rest_server/nbi_plugins/camara_qod/Tools.py
index feec71cb6..e0d19efff 100644
--- a/src/nbi/service/rest_server/nbi_plugins/camara_qod/Tools.py
+++ b/src/nbi/service/rest_server/nbi_plugins/camara_qod/Tools.py
@@ -1,4 +1,4 @@
-# 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.
diff --git a/src/nbi/service/rest_server/nbi_plugins/camara_qod/__init__.py b/src/nbi/service/rest_server/nbi_plugins/camara_qod/__init__.py
index ab4fe2bbd..19c452955 100644
--- a/src/nbi/service/rest_server/nbi_plugins/camara_qod/__init__.py
+++ b/src/nbi/service/rest_server/nbi_plugins/camara_qod/__init__.py
@@ -1,4 +1,4 @@
-# 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,18 +13,17 @@
 # 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.profile_list',ProfileList,'/profiles'),
-    ('camara.qod.profile_detail',ProfileDetail,'/profiles/<string:qos_profile_id>'),
+    ('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>'),
 ]
 
 def register_camara_qod(rest_server : RestServer):
-- 
GitLab