From ce79268a1399efb1d8e71afd71edb32b4583ce8f Mon Sep 17 00:00:00 2001 From: Laskaratos Dimitris Date: Fri, 24 Oct 2025 13:02:45 +0300 Subject: [PATCH 1/3] Last commit before leaving the company --- Dockerfile | 2 +- .../src/__main__.py | 8 ++- .../edge_cloud_management_controller.py | 26 +++---- .../network_functions_controller.py | 33 ++++----- sunrise6g-deployment.yaml | 67 +++++++++++++++++-- 5 files changed, 101 insertions(+), 35 deletions(-) diff --git a/Dockerfile b/Dockerfile index ebc2b57..3c60ffd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,5 +21,5 @@ EXPOSE 8080 ENTRYPOINT ["python3"] -CMD ["-m", "service-resource-manager-implementation/src"] +CMD ["-m", "src"] diff --git a/service-resource-manager-implementation/src/__main__.py b/service-resource-manager-implementation/src/__main__.py index 828513a..da8b42e 100644 --- a/service-resource-manager-implementation/src/__main__.py +++ b/service-resource-manager-implementation/src/__main__.py @@ -4,6 +4,7 @@ import connexion import logging import src.encoder as encoder from json import JSONEncoder +# from connexion.options import SwaggerUIOptions import urllib3 @@ -11,8 +12,13 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) def main(): logging.basicConfig(level=logging.INFO) app = connexion.App(__name__, specification_dir='./swagger/') + # swagger_options = SwaggerUIOptions(swagger_ui_path="/docs") app.app.json_encoder = JSONEncoder - app.add_api('swagger.yaml', strict_validation=True, arguments={'title': 'Service Resource Manager Controller API'}, pythonic_params=True) + app.add_api('swagger.yaml', + # swagger_ui_options=swagger_options, + strict_validation=True, + arguments={'title': 'Service Resource Manager Controller API'}, + pythonic_params=True) app.run(port=8080) diff --git a/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py b/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py index 0194906..44d2ffc 100644 --- a/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py +++ b/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py @@ -26,8 +26,8 @@ def deregister_service_function(service_function_id: str): # noqa: E501 :param service_function_name: Removed app metadata from the catalogue. """ try: - code = edgecloud_adapter.delete_onboarded_app(service_function_id) - return code + response = edgecloud_adapter.delete_onboarded_app(service_function_id) + return response.status_code except Exception as ce_: raise Exception("An exception occurred :", ce_) @@ -38,7 +38,7 @@ def get_service_function(service_function_id: str): # noqa: E501 try: service_function = edgecloud_adapter.get_onboarded_app(service_function_id) - return service_function + return service_function.json() except Exception as ce_: raise Exception("An exception occurred :", ce_) @@ -48,7 +48,7 @@ def get_service_functions(): # noqa: E501 """ try: service_functions = edgecloud_adapter.get_all_onboarded_apps() - return service_functions + return service_functions.json() except Exception as ce_: raise Exception("An exception occurred :", ce_) @@ -61,17 +61,17 @@ def register_service_function(body=None): # noqa: E501 insert_doc = connexion.request.get_json() try: - return edgecloud_adapter.onboard_app(insert_doc) + return edgecloud_adapter.onboard_app(insert_doc).json() except Exception as ce_: return ce_ def delete_deployed_service_function(app_id: str): # noqa: E501 - """Undeployes app + """Undeploys app """ - response = None try: response = edgecloud_adapter.undeploy_app(app_id) + return response.status_code # return response except Exception as ce_: @@ -98,10 +98,10 @@ def deploy_service_function(): # noqa: E501 try: # body = DeployApp.from_dict(connexion.request.get_json()) body = connexion.request.get_json() - response = edgecloud_adapter.deploy_app(body) + response = edgecloud_adapter.deploy_app(body.get('appId'), body.get('appZones')) # body = DeployServiceFunction.from_dict(connexion.request.get_json()) # response = piedge_encoder.deploy_service_function(body) - return response + return response.json() except Exception as ce_: logger.error(ce_) return ce_ @@ -123,7 +123,7 @@ def get_deployed_service_functions(): # noqa: E501 # if role is not None and role == "admin": try: response = edgecloud_adapter.get_all_deployed_apps() - return response + return response.json() except Exception as ce_: logger.error(ce_) return ce_ @@ -143,7 +143,7 @@ def get_deployed_service_function(app_id: str): # noqa: E501 # if role is not None and role == "admin": try: response = edgecloud_adapter.get_deployed_app(app_id=app_id) - return response + return response.json() except Exception as ce_: logger.error(ce_) return ce_ @@ -157,7 +157,7 @@ def get_nodes(): # noqa: E501 """ # try: response = edgecloud_adapter.get_edge_cloud_zones() - return response + return response.json() # except Exception as ce_: # logger.info(ce_) @@ -170,6 +170,6 @@ def node_details(node_id: str): # noqa: E501 """ try: response = edgecloud_adapter.get_edge_cloud_zones_details(zone_id=node_id) - return response + return response.json() except Exception as ce_: logger.info(ce_) \ No newline at end of file diff --git a/service-resource-manager-implementation/src/controllers/network_functions_controller.py b/service-resource-manager-implementation/src/controllers/network_functions_controller.py index 862731c..68f6da9 100644 --- a/service-resource-manager-implementation/src/controllers/network_functions_controller.py +++ b/service-resource-manager-implementation/src/controllers/network_functions_controller.py @@ -2,6 +2,7 @@ from os import environ import logging import connexion import sys +import json from sunrise6g_opensdk.common.sdk import Sdk as sdkclient logger = logging.getLogger(__name__) @@ -13,7 +14,7 @@ if environ.get('NETWORK_ADAPTER_NAME') is not None: adapter_base_url = environ.get('NETWORK_ADAPTER_BASE_URL') scs_as_id = environ.get('SCS_AS_ID') network_adapter_specs = {'client_name': network_adapter_name, 'base_url': adapter_base_url, 'scs_as_id': scs_as_id} - network_adapter_specs.update(environ) + # network_adapter_specs.update(environ) print('Creating network adapter with env: ', network_adapter_specs) adapters = sdkclient.create_adapters_from(adapter_specs={'network': network_adapter_specs}) network_adapter = adapters.get("network") @@ -27,7 +28,9 @@ def create_qod_session(): try: if network_adapter is not None: response = network_adapter.create_qod_session(connexion.request.get_json()) - return response + + print(response) + return response, 200 else: return { "applicationServer": { @@ -41,7 +44,7 @@ def create_qod_session(): } except Exception as ce_: logger.error(ce_) - return ce_ + return ce_.args else: return 'ERROR: Could not read JSON payload.', 400 @@ -49,31 +52,31 @@ def get_qod_session(session_id: str): try: if network_adapter is not None: - response = network_adapter.get_qod_session(id) - return {'status': 200, 'session': response} + response = network_adapter.get_qod_session(session_id) + return response, 200 else: return "Requested QoD session with ID: "+session_id except Exception as ce_: logger.error(ce_) - return ce_ + return ce_, 500 def delete_qod_session(session_id: str): try: if network_adapter is not None: - response = network_adapter.delete_qod_session(id) - return response + response = network_adapter.delete_qod_session(session_id) + return response, 200 else: return "Deleting QoD session with ID: "+ session_id except Exception as ce_: logger.error(ce_) - return ce_ + return ce_, 500 def create_traffic_influence_resource(body): try: if network_adapter is not None: response = network_adapter.create_traffic_influence_resource(traffic_influence_info=body) - return response + return response, 200 else: return { "trafficInfluenceID": "string", @@ -95,29 +98,29 @@ def create_traffic_influence_resource(body): } except Exception as ce_: logger.error(ce_) - return ce_ + return ce_, 500 def delete_traffic_influence_resource(traffic_influence_id: str): try: if network_adapter is not None: response = network_adapter.delete_traffic_influence_resource(resource_id=traffic_influence_id) - return response + return response, 200 else: return "Deleting Traffic Influence resource with ID: "+ traffic_influence_id except Exception as ce_: logger.error(ce_) - return ce_ + return ce_, 500 def get_traffic_influence_resource(traffic_influence_id: str): try: if network_adapter is not None: response = network_adapter.get_individual_traffic_influence_resource(resource_id=traffic_influence_id) - return {'status': 200, 'session': response} + return response, 200 else: return "Requested Traffice Influence resource with ID: "+traffic_influence_id except Exception as ce_: logger.error(ce_) - return ce_ + return ce_, 500 def get_all_traffic_influence_resources(): #TODO diff --git a/sunrise6g-deployment.yaml b/sunrise6g-deployment.yaml index 7d09731..c7639bf 100644 --- a/sunrise6g-deployment.yaml +++ b/sunrise6g-deployment.yaml @@ -25,7 +25,8 @@ spec: io.kompose.service: srmcontroller spec: containers: - - env: + - name: srmcontroller + env: - name: KUBERNETES_MASTER_IP value: k3d-sunriseop-server-0 - name: KUBERNETES_MASTER_PORT @@ -33,7 +34,7 @@ spec: - name: KUBERNETES_USERNAME value: cluster-admin - name: K8S_NAMESPACE - value: test + value: test - name: EMP_STORAGE_URI value: mongodb://mongosrm:27017 - name: KUBERNETES_MASTER_TOKEN @@ -46,12 +47,64 @@ spec: value: k3d-sunriseop-server-0 - name: PLATFORM_PROVIDER value: ISI + - name: NETWORK_ADAPTER_NAME + value: open5gs + - name: NETWORK_ADAPTER_BASE_URL + value: http://10.8.0.1:31004/ + - name: SCS_AS_ID + value: scs + image: ghcr.io/sunriseopenoperatorplatform/srm/srm:1.0.1 - name: srmcontroller + imagePullPolicy: Always ports: - containerPort: 8080 resources: {} - imagePullPolicy: Always + + - name: openvpn + image: alpine:3.20 + securityContext: + capabilities: + add: + - NET_ADMIN + allowPrivilegeEscalation: false + volumeMounts: + - name: ovpn + mountPath: /vpn + readOnly: true + - name: dev-net-tun + mountPath: /dev/net/tun + command: + - /bin/sh + - -c + args: + - | + apk add --no-cache openvpn iproute2 bind-tools \ + && echo "Starting OpenVPN..." \ + && openvpn --config /vpn/icom-client-1.ovpn \ + --auth-user-pass /vpn/auth.txt \ + --verb 3 \ + --writepid /var/run/openvpn.pid + readinessProbe: + exec: + command: + - /bin/sh + - -c + - > + ip link show dev tun0 >/dev/null 2>&1 || exit 1 + + # Optional: confirm a VPN route exists (adapt the CIDR to your partner's network) + + ip route | grep -q 'tun0' || exit 1 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: ovpn + secret: + secretName: partner-ovpn + - name: dev-net-tun + hostPath: + path: /dev/net/tun + type: CharDevice restartPolicy: Always status: {} @@ -304,9 +357,13 @@ spec: - name: JWT_ISSUER value: http://isiath.duckdns.org:8081/realms/federation - name: JWT_PUBLIC_KEY - value: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFHYObBh4Ar/s5/OG2swoUvmw25DNfX5j30itd3lFCzNnzXWobin/Jfywtj9HIXJ1euqiJMHchRgn7n0iY8X227/1+f+eml/bNs+roHtwP3GpO77ZLV/uP4RsGYbHUXKlGIf2EYglWNLs8ZNDFnpEIZzAEVzQrt1etr0HkwgwAKKkMbSdyRQTXoBgCPheyFgaLRtSHod4IijnBptolbK7LLKfkVaImQcs5R3GF81lM7cCtd1c+ERqZ2/pWAdlKHjt7zMuWWQypwVav59MgJprWv3oE9dvh5M0Ma+J4iH4DNiIzz6kYqAHpIJ1q813kjWlcUmwm4qSdgkDXwdGHxitwIDAQAB + value: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkMTcpuPxHgERaVDjsF8frpprzxVqOOJoKyUDRcjRqtgc5mQG/OuPYble89BoD+vtVvwwN+1CiWXeU1II1yWyNKCz2wuHdlwJlp6A6pv2QhRTs1aR7RhSd7MItzep3kMiSkWFVLiDrio9npFiv+F0AfdBbs9mCdeTAZ8cKA9AKK8+rGKhuUIwvIAIzGMlGzFRtWtqz0gGuqQlhcXE6v52m1lYc7QopDN1A7vyuPVv4QC8/L43Y/tHm3v/5n7JwRdrS+eUPLKn+eENybMPFaPsh9x0ObDXgt8guFQIKx+jxuYlwK5B5Vta8d7aHP/BBQu44iKHbSlzwV13oR6sWRBIqQIDAQAB - name: FEDERATION_MANAGER_HOST value: http://federation-manager.federation-manager.svc.cluster.local:8989/operatorplatform/federation/v1 + - name: PARTNER_API_ROOT + value: http://10.8.0.1:31002 + - name: TOKEN_ENDPOINT + value: http://federation-manager.federation-manager.svc.cluster.local:8080/realms/federation/protocol/openid-connect/token image: ghcr.io/sunriseopenoperatorplatform/oeg/oeg:1.0.1 name: oegcontroller ports: -- GitLab From 85d318b4d7d2f5f5d1318084166b57b6484dbaec Mon Sep 17 00:00:00 2001 From: papathanail Date: Tue, 23 Dec 2025 13:49:54 +0200 Subject: [PATCH 2/3] fixes on controllers --- .../controllers/app_instance_controller.py | 88 +++--- .../edge_cloud_management_controller.py | 269 +++++++++--------- .../network_functions_controller.py | 184 ++++++++---- 3 files changed, 326 insertions(+), 215 deletions(-) diff --git a/service-resource-manager-implementation/src/controllers/app_instance_controller.py b/service-resource-manager-implementation/src/controllers/app_instance_controller.py index 40ccb00..db1a110 100644 --- a/service-resource-manager-implementation/src/controllers/app_instance_controller.py +++ b/service-resource-manager-implementation/src/controllers/app_instance_controller.py @@ -1,43 +1,65 @@ -from os import environ import logging -import connexion logger = logging.getLogger(__name__) logging.basicConfig(level=logging.DEBUG) -def deploy_app(helm_request_body=None): - ''' - Retrieves the nodes of the edge cloud platform supported by the testbed - ''' - logger.info('Submitting request to edge cloud transformation function') - if connexion.request.is_json: - helm_request_body = connexion.request.get_json() - else: - return 'Wrong request schema', 400 +def deploy_app(helm_request_body): + """ + Deploys an application via Helm. + Adapter-level function: + - accepts Python dict + - returns Python dict + - raises exceptions on failure + """ + + logger.info("Submitting request to edge cloud transformation function") + + if not isinstance(helm_request_body, dict): + raise ValueError("Invalid request body") + + if not helm_request_body.get("uri"): + raise ValueError("Helm chart uri is missing") + + if not helm_request_body.get("deployment_name"): + raise ValueError("Helm chart deployment name is missing") + try: - if helm_request_body.get('uri') is None: - return 'Helm chart uri is missing', 400 - if helm_request_body.get('deployment_name') is None: - return 'Helm chart deployment name is missing', 400 - - helm_submit_response = submit_helm_chart(helm_request_body) - return helm_submit_response + # submit_helm_chart MUST return dict or list + result = submit_helm_chart(helm_request_body) + + if not isinstance(result, (dict, list)): + raise TypeError( + f"submit_helm_chart returned unsupported type: {type(result)}" + ) + + return result + except Exception as e: - logger.info(e) - return 'Error submitting helm chart: '+e.__cause__ - + logger.exception("Error submitting helm chart") + raise + + def get_app_instances(body): - ''' - Instantiates app on the edge cloud platform - ''' - logger.info('Deploying app instance') - if connexion.request.is_json: - helm_request_body = connexion.request.get_json() - else: - return 'Wrong request schema', 400 + """ + Instantiates app on the edge cloud platform. + Adapter-level function. + """ + + logger.info("Deploying app instance") + + if not isinstance(body, dict): + raise ValueError("Invalid request body") + try: - app_response = app_deploy(body) + result = app_deploy(body) + + if not isinstance(result, (dict, list)): + raise TypeError( + f"app_deploy returned unsupported type: {type(result)}" + ) + + return result + except Exception as e: - logger.info(e) - return 'Error instantiating app: '+e.__cause__ - \ No newline at end of file + logger.exception("Error instantiating app") + raise diff --git a/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py b/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py index 44d2ffc..9ca734a 100644 --- a/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py +++ b/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py @@ -2,174 +2,185 @@ import connexion import logging from os import environ from sunrise6g_opensdk import Sdk as sdkclient -import sys -logger=logging.getLogger(__name__) +logger = logging.getLogger(__name__) logging.basicConfig(level=logging.DEBUG) -if environ['EDGE_CLOUD_ADAPTER_NAME'] is not None: - edgecloud_adapter_name = environ['EDGE_CLOUD_ADAPTER_NAME'] - edgecloud_adapter_base_url = environ['ADAPTER_BASE_URL'] - edgecloud_adapter_specs = {'client_name': edgecloud_adapter_name, 'base_url': edgecloud_adapter_base_url} +# --------------------------------------------------------------------- +# Adapter initialization +# --------------------------------------------------------------------- + +edgecloud_adapter = None + +if environ.get("EDGE_CLOUD_ADAPTER_NAME"): + edgecloud_adapter_name = environ["EDGE_CLOUD_ADAPTER_NAME"] + edgecloud_adapter_base_url = environ.get("ADAPTER_BASE_URL") + + edgecloud_adapter_specs = { + "client_name": edgecloud_adapter_name, + "base_url": edgecloud_adapter_base_url, + } edgecloud_adapter_specs.update(environ) - print('Creating edge cloud adapter with env: ', edgecloud_adapter_specs) - adapters = sdkclient.create_adapters_from(adapter_specs={'edgecloud': edgecloud_adapter_specs}) + + logger.info("Creating edge cloud adapter with env: %s", edgecloud_adapter_specs) + + adapters = sdkclient.create_adapters_from( + adapter_specs={"edgecloud": edgecloud_adapter_specs} + ) edgecloud_adapter = adapters.get("edgecloud") -# else: -# logging.error('Edge Cloud adapter has not been specified! Aborting...') -# sys.exit() +if edgecloud_adapter is None: + raise RuntimeError("Edge cloud adapter could not be initialized") -def deregister_service_function(service_function_id: str): # noqa: E501 - """Deregister service. +# --------------------------------------------------------------------- +# Helper: normalize adapter responses +# --------------------------------------------------------------------- - :param service_function_name: Removed app metadata from the catalogue. +def _safe_http_json_response(response): + """ + Normalize adapter responses: + - list / dict → return directly (200) + - requests.Response → parse JSON safely """ - try: - response = edgecloud_adapter.delete_onboarded_app(service_function_id) - return response.status_code - except Exception as ce_: - raise Exception("An exception occurred :", ce_) + # Adapter already returned Python data + if isinstance(response, (list, dict)): + return response, 200 -def get_service_function(service_function_id: str): # noqa: E501 - """Returns a specific app from the catalogue. - """ + # Adapter returned nothing + if response is None: + return {"error": "Adapter returned no response"}, 502 + # Adapter returned HTTP response try: - service_function = edgecloud_adapter.get_onboarded_app(service_function_id) - return service_function.json() - except Exception as ce_: - raise Exception("An exception occurred :", ce_) - + return response.json(), response.status_code + except Exception as e: + logger.exception("Failed to parse adapter HTTP response") + return { + "error": "Invalid response from adapter", + "details": str(e) + }, 502 + +# --------------------------------------------------------------------- +# Catalogue (onboarded service functions) +# --------------------------------------------------------------------- + +def register_service_function(body=None): + if not connexion.request.is_json: + return {"error": "Invalid JSON payload"}, 400 -def get_service_functions(): # noqa: E501 - """Returns all apps from the catalogue. - """ try: - service_functions = edgecloud_adapter.get_all_onboarded_apps() - return service_functions.json() - except Exception as ce_: - raise Exception("An exception occurred :", ce_) + payload = connexion.request.get_json() + response = edgecloud_adapter.onboard_app(payload) + return _safe_http_json_response(response) + except Exception as e: + logger.exception("Failed to register service function") + return {"error": "Registration failed", "details": str(e)}, 500 -def register_service_function(body=None): # noqa: E501 - """Registers app to the database - """ +def get_service_function(service_function_id: str): + try: + response = edgecloud_adapter.get_onboarded_app(service_function_id) + return _safe_http_json_response(response) + except Exception as e: + logger.exception("Failed to get service function") + return {"error": "Fetch failed", "details": str(e)}, 500 + - if connexion.request.is_json: +def get_service_functions(): + try: + response = edgecloud_adapter.get_all_onboarded_apps() + return _safe_http_json_response(response) + except Exception as e: + logger.exception("Failed to list service functions") + return {"error": "Fetch failed", "details": str(e)}, 500 - insert_doc = connexion.request.get_json() - try: - return edgecloud_adapter.onboard_app(insert_doc).json() - except Exception as ce_: - return ce_ -def delete_deployed_service_function(app_id: str): # noqa: E501 - """Undeploys app - """ - response = None +def deregister_service_function(service_function_id: str): try: - response = edgecloud_adapter.undeploy_app(app_id) - return response.status_code - # return response + edgecloud_adapter.delete_onboarded_app(service_function_id) + return None, 204 + except Exception as e: + logger.exception("Failed to deregister service function") + return {"error": "Deletion failed", "details": str(e)}, 500 - except Exception as ce_: - logger.error(ce_) - return ce_ - # else: - # return "You are not authorized to access the URL requested", 401 +# --------------------------------------------------------------------- +# Deployment +# --------------------------------------------------------------------- +def deploy_service_function(): + if not connexion.request.is_json: + return {"error": "Invalid JSON payload"}, 400 -def deploy_service_function(): # noqa: E501 - """Request to deploy a Service function (from the catalogue) to an edge node. + try: + body = connexion.request.get_json() - # noqa: E501 + response = edgecloud_adapter.deploy_app( + body.get("appId"), + body.get("appZones") + ) - :param body: Deploy Service Function. - :type body: dict | bytes + return _safe_http_json_response(response) - :rtype: None - """ + except Exception as e: + logger.exception("Failed to deploy service function") + return { + "error": "Deployment failed", + "details": str(e) + }, 500 - # role = user_authentication.check_role() - # if role is not None and role == "admin": - if connexion.request.is_json: - try: - # body = DeployApp.from_dict(connexion.request.get_json()) - body = connexion.request.get_json() - response = edgecloud_adapter.deploy_app(body.get('appId'), body.get('appZones')) - # body = DeployServiceFunction.from_dict(connexion.request.get_json()) - # response = piedge_encoder.deploy_service_function(body) - return response.json() - except Exception as ce_: - logger.error(ce_) - return ce_ - else: - return 'ERROR: Could not read JSON payload.' - -def get_deployed_service_functions(): # noqa: E501 - """Request to deploy a Service function (from the catalogue) to an edge node. - - # noqa: E501 - - :param body: Deploy Service Function. - :type body: dict | bytes - - :rtype: None - """ - # role = user_authentication.check_role() - # if role is not None and role == "admin": +def delete_deployed_service_function(app_id: str): try: - response = edgecloud_adapter.get_all_deployed_apps() - return response.json() - except Exception as ce_: - logger.error(ce_) - return ce_ + edgecloud_adapter.undeploy_app(app_id) + return None, 204 + except Exception as e: + logger.exception("Failed to undeploy service function") + return {"error": "Undeploy failed", "details": str(e)}, 500 -def get_deployed_service_function(app_id: str): # noqa: E501 - """Request to deploy a Service function (from the catalogue) to an edge node. - # noqa: E501 +def get_deployed_service_function(app_id: str): + try: + response = edgecloud_adapter.get_deployed_app(app_id=app_id) + return _safe_http_json_response(response) + except Exception as e: + logger.exception("Failed to get deployed service function") + return {"error": "Fetch failed", "details": str(e)}, 500 - :param body: Deploy Service Function. - :type body: dict | bytes - :rtype: None - """ - - # role = user_authentication.check_role() - # if role is not None and role == "admin": +def get_deployed_service_functions(): try: - response = edgecloud_adapter.get_deployed_app(app_id=app_id) - return response.json() - except Exception as ce_: - logger.error(ce_) - return ce_ - -def get_nodes(): # noqa: E501 - """Returns the edge nodes status. + response = edgecloud_adapter.get_all_deployed_apps() + return _safe_http_json_response(response) + except Exception as e: + logger.exception("Failed to list deployed service functions") + return {"error": "Fetch failed", "details": str(e)}, 500 - # noqa: E501 +# --------------------------------------------------------------------- +# Edge cloud nodes / zones +# --------------------------------------------------------------------- - :rtype: NodesResponse +def get_nodes(): """ - # try: - response = edgecloud_adapter.get_edge_cloud_zones() - return response.json() - # except Exception as ce_: - # logger.info(ce_) - -def node_details(node_id: str): # noqa: E501 - """Returns the edge nodes status. + Returns the edge cloud zones. + Adapter returns LIST → return directly. + """ + try: + zones = edgecloud_adapter.get_edge_cloud_zones() + return zones, 200 + except Exception as e: + logger.exception("Failed to get edge cloud zones") + return {"error": "Fetch failed", "details": str(e)}, 500 - # noqa: E501 - :rtype: NodesResponse +def node_details(node_id: str): + """ + Returns details for a specific edge cloud zone. + Adapter returns DICT → return directly. """ try: - response = edgecloud_adapter.get_edge_cloud_zones_details(zone_id=node_id) - return response.json() - except Exception as ce_: - logger.info(ce_) \ No newline at end of file + details = edgecloud_adapter.get_edge_cloud_zones_details(zone_id=node_id) + return details, 200 + except Exception as e: + logger.exception("Failed to get node details") + return {"error": "Fetch failed", "details": str(e)}, 500 diff --git a/service-resource-manager-implementation/src/controllers/network_functions_controller.py b/service-resource-manager-implementation/src/controllers/network_functions_controller.py index 68f6da9..2d92fdc 100644 --- a/service-resource-manager-implementation/src/controllers/network_functions_controller.py +++ b/service-resource-manager-implementation/src/controllers/network_functions_controller.py @@ -18,110 +18,188 @@ if environ.get('NETWORK_ADAPTER_NAME') is not None: print('Creating network adapter with env: ', network_adapter_specs) adapters = sdkclient.create_adapters_from(adapter_specs={'network': network_adapter_specs}) network_adapter = adapters.get("network") + + # else: # logging.error('Network adapter has not been specified! Aborting...') # sys.exit() +def _serialize_response(response): + """Helper function to serialize response objects to JSON-compatible format""" + if isinstance(response, tuple): + body, status = response + serialized_body = json.loads(json.dumps(body, default=str)) + return serialized_body, status + else: + serialized_response = json.loads(json.dumps(response, default=str)) + return serialized_response + + def create_qod_session(): - if connexion.request.is_json: try: if network_adapter is not None: response = network_adapter.create_qod_session(connexion.request.get_json()) - print(response) - return response, 200 + + # Convert the response to JSON-serializable format + if isinstance(response, tuple): + body, status = response + serialized_body = json.loads(json.dumps(body, default=str)) + return serialized_body, status + else: + serialized_response = json.loads(json.dumps(response, default=str)) + return serialized_response, 200 else: return { - "applicationServer": { + "applicationServer": { "ipv4Address": "198.51.100.0/24" - }, - "qosProfile": "QOS_L", - "sink": "https://application-server.com/notifications", - "sessionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "duration": 3600, - "qosStatus": "REQUESTED" - } + }, + "qosProfile": "QOS_L", + "sink": "https://application-server.com/notifications", + "sessionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "duration": 3600, + "qosStatus": "REQUESTED" + }, 200 except Exception as ce_: logger.error(ce_) - return ce_.args + return {"error": str(ce_)}, 500 else: - return 'ERROR: Could not read JSON payload.', 400 + return {'error': 'Could not read JSON payload.'}, 400 + def get_qod_session(session_id: str): - try: if network_adapter is not None: response = network_adapter.get_qod_session(session_id) - return response, 200 + + # Serialize the response to handle non-JSON-serializable objects + if isinstance(response, tuple): + body, status = response + serialized_body = json.loads(json.dumps(body, default=str)) + return serialized_body, status + else: + serialized_response = json.loads(json.dumps(response, default=str)) + return serialized_response, 200 else: - return "Requested QoD session with ID: "+session_id + return {"message": "Requested QoD session with ID: " + session_id}, 200 except Exception as ce_: logger.error(ce_) - return ce_, 500 + return {"error": str(ce_)}, 500 + def delete_qod_session(session_id: str): - try: if network_adapter is not None: - response = network_adapter.delete_qod_session(session_id) - return response, 200 + response = network_adapter.delete_qod_session(session_id) + + # Serialize the response to handle non-JSON-serializable objects + if isinstance(response, tuple): + body, status = response + serialized_body = json.loads(json.dumps(body, default=str)) + return serialized_body, status + else: + serialized_response = json.loads(json.dumps(response, default=str)) + return serialized_response, 200 else: - return "Deleting QoD session with ID: "+ session_id + return {"message": "Deleting QoD session with ID: " + session_id}, 200 except Exception as ce_: logger.error(ce_) - return ce_, 500 + return {"error": str(ce_)}, 500 + def create_traffic_influence_resource(body): - try: + try: if network_adapter is not None: response = network_adapter.create_traffic_influence_resource(traffic_influence_info=body) - return response, 200 + + # Serialize the response to handle non-JSON-serializable objects + if isinstance(response, tuple): + body, status = response + serialized_body = json.loads(json.dumps(body, default=str)) + return serialized_body, status + else: + serialized_response = json.loads(json.dumps(response, default=str)) + return serialized_response, 200 else: return { - "trafficInfluenceID": "string", - "apiConsumerId": "string", - "appId": "6B29FC40-CA47-1067-B31D-00DD010662DA", - "appInstanceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "edgeCloudRegion": "string", - "edgeCloudZoneId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", - "state": "ordered", - "sourceTrafficFilters": { + "trafficInfluenceID": "string", + "apiConsumerId": "string", + "appId": "6B29FC40-CA47-1067-B31D-00DD010662DA", + "appInstanceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "edgeCloudRegion": "string", + "edgeCloudZoneId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "state": "ordered", + "sourceTrafficFilters": { "sourcePort": 65535 - }, - "destinationTrafficFilters": { + }, + "destinationTrafficFilters": { "destinationPort": 65535, "destinationProtocol": "TCP" - }, - "notificationUri": "string", - "notificationAuthToken": "string" - } - except Exception as ce_: + }, + "notificationUri": "string", + "notificationAuthToken": "string" + }, 200 + except Exception as ce_: logger.error(ce_) - return ce_, 500 + return {"error": str(ce_)}, 500 + def delete_traffic_influence_resource(traffic_influence_id: str): - try: + try: if network_adapter is not None: - response = network_adapter.delete_traffic_influence_resource(resource_id=traffic_influence_id) - return response, 200 + response = network_adapter.delete_traffic_influence_resource(resource_id=traffic_influence_id) + + # Serialize the response to handle non-JSON-serializable objects + if isinstance(response, tuple): + body, status = response + serialized_body = json.loads(json.dumps(body, default=str)) + return serialized_body, status + else: + serialized_response = json.loads(json.dumps(response, default=str)) + return serialized_response, 200 else: - return "Deleting Traffic Influence resource with ID: "+ traffic_influence_id - except Exception as ce_: + return {"message": "Deleting Traffic Influence resource with ID: " + traffic_influence_id}, 200 + except Exception as ce_: logger.error(ce_) - return ce_, 500 + return {"error": str(ce_)}, 500 + def get_traffic_influence_resource(traffic_influence_id: str): - try: + try: if network_adapter is not None: response = network_adapter.get_individual_traffic_influence_resource(resource_id=traffic_influence_id) - return response, 200 + + # Serialize the response to handle non-JSON-serializable objects + if isinstance(response, tuple): + body, status = response + serialized_body = json.loads(json.dumps(body, default=str)) + return serialized_body, status + else: + serialized_response = json.loads(json.dumps(response, default=str)) + return serialized_response, 200 else: - return "Requested Traffice Influence resource with ID: "+traffic_influence_id - except Exception as ce_: + return {"message": "Requested Traffic Influence resource with ID: " + traffic_influence_id}, 200 + except Exception as ce_: logger.error(ce_) - return ce_, 500 + return {"error": str(ce_)}, 500 + def get_all_traffic_influence_resources(): - #TODO - pass \ No newline at end of file + try: + if network_adapter is not None: + response = network_adapter.get_all_traffic_influence_resources() + + # Serialize the response to handle non-JSON-serializable objects + if isinstance(response, tuple): + body, status = response + serialized_body = json.loads(json.dumps(body, default=str)) + return serialized_body, status + else: + serialized_response = json.loads(json.dumps(response, default=str)) + return serialized_response, 200 + else: + return {"message": "List all Traffic Influence resources"}, 200 + except Exception as ce_: + logger.error(ce_) + return {"error": str(ce_)}, 500 \ No newline at end of file -- GitLab From bb1810b49227db88721a08cfabd41f89023390df Mon Sep 17 00:00:00 2001 From: dimi Date: Wed, 25 Feb 2026 09:19:25 +0000 Subject: [PATCH 3/3] fix: resolve merge requests, cleanup --- .idea/.gitignore | 8 - .idea/deployment.xml | 15 - .idea/edge-implementation.iml | 8 - .../inspectionProfiles/profiles_settings.xml | 6 - .idea/misc.xml | 4 - .idea/modules.xml | 8 - .idea/vcs.xml | 6 - Dockerfile | 2 +- requirements.txt | 2 +- .../edge_cloud_management_controller.py | 39 +- .../network_functions_controller.py | 103 +--- srm-deployment.yaml | 309 ------------ sunrise6g-deployment.yaml | 452 ------------------ 13 files changed, 56 insertions(+), 906 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/deployment.xml delete mode 100644 .idea/edge-implementation.iml delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 srm-deployment.yaml delete mode 100644 sunrise6g-deployment.yaml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 73f69e0..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/deployment.xml b/.idea/deployment.xml deleted file mode 100644 index 9e0c942..0000000 --- a/.idea/deployment.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/edge-implementation.iml b/.idea/edge-implementation.iml deleted file mode 100644 index 856ca00..0000000 --- a/.idea/edge-implementation.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2d..0000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 512431b..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 26a7349..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3c60ffd..0d3a85e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ RUN pip3 install --upgrade pip RUN pip3 install wheel --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host=files.pythonhosted.org -RUN pip3 install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host=files.pythonhosted.org --no-cache-dir -r requirements.txt +RUN pip3 install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host=files.pythonhosted.org --no-cache-dir -r requirements.txt --extra-index-url https://labs.etsi.org/rep/api/v4/projects/396/packages/pypi/simple --trusted-host labs.etsi.org COPY . /usr/src/app diff --git a/requirements.txt b/requirements.txt index 9ea2d85..d54e60b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,4 @@ requests==2.32.4 psycopg2-binary urllib3 pydantic-extra-types==2.10.3 -sunrise6g-opensdk==1.0.2.post3 \ No newline at end of file +sunrise6g-opensdk==1.0.21 \ No newline at end of file diff --git a/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py b/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py index 9ca734a..4bae015 100644 --- a/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py +++ b/service-resource-manager-implementation/src/controllers/edge_cloud_management_controller.py @@ -33,7 +33,7 @@ if edgecloud_adapter is None: raise RuntimeError("Edge cloud adapter could not be initialized") # --------------------------------------------------------------------- -# Helper: normalize adapter responses +# Helpers: normalize adapter responses # --------------------------------------------------------------------- def _safe_http_json_response(response): @@ -61,6 +61,21 @@ def _safe_http_json_response(response): "details": str(e) }, 502 + +def _ensure_edge_cloud_region(data): + """ + Ensure every zone/node object carries an edgeCloudRegion field. + Falls back to 'unknown' when the adapter omits the field. + """ + if isinstance(data, list): + for item in data: + if isinstance(item, dict) and not item.get("edgeCloudRegion"): + item["edgeCloudRegion"] = "unknown" + elif isinstance(data, dict): + if not data.get("edgeCloudRegion"): + data["edgeCloudRegion"] = "unknown" + return data + # --------------------------------------------------------------------- # Catalogue (onboarded service functions) # --------------------------------------------------------------------- @@ -98,8 +113,8 @@ def get_service_functions(): def deregister_service_function(service_function_id: str): try: - edgecloud_adapter.delete_onboarded_app(service_function_id) - return None, 204 + response = edgecloud_adapter.delete_onboarded_app(service_function_id) + return _safe_http_json_response(response) except Exception as e: logger.exception("Failed to deregister service function") return {"error": "Deletion failed", "details": str(e)}, 500 @@ -132,8 +147,8 @@ def deploy_service_function(): def delete_deployed_service_function(app_id: str): try: - edgecloud_adapter.undeploy_app(app_id) - return None, 204 + response = edgecloud_adapter.undeploy_app(app_id) + return _safe_http_json_response(response) except Exception as e: logger.exception("Failed to undeploy service function") return {"error": "Undeploy failed", "details": str(e)}, 500 @@ -163,11 +178,12 @@ def get_deployed_service_functions(): def get_nodes(): """ Returns the edge cloud zones. - Adapter returns LIST → return directly. + Normalizes the HTTP response and ensures edgeCloudRegion is always present. """ try: - zones = edgecloud_adapter.get_edge_cloud_zones() - return zones, 200 + response = edgecloud_adapter.get_edge_cloud_zones() + data, status = _safe_http_json_response(response) + return _ensure_edge_cloud_region(data), status except Exception as e: logger.exception("Failed to get edge cloud zones") return {"error": "Fetch failed", "details": str(e)}, 500 @@ -176,11 +192,12 @@ def get_nodes(): def node_details(node_id: str): """ Returns details for a specific edge cloud zone. - Adapter returns DICT → return directly. + Normalizes the HTTP response and ensures edgeCloudRegion is always present. """ try: - details = edgecloud_adapter.get_edge_cloud_zones_details(zone_id=node_id) - return details, 200 + response = edgecloud_adapter.get_edge_cloud_zones_details(zone_id=node_id) + data, status = _safe_http_json_response(response) + return _ensure_edge_cloud_region(data), status except Exception as e: logger.exception("Failed to get node details") return {"error": "Fetch failed", "details": str(e)}, 500 diff --git a/service-resource-manager-implementation/src/controllers/network_functions_controller.py b/service-resource-manager-implementation/src/controllers/network_functions_controller.py index 2d92fdc..bb5c597 100644 --- a/service-resource-manager-implementation/src/controllers/network_functions_controller.py +++ b/service-resource-manager-implementation/src/controllers/network_functions_controller.py @@ -1,8 +1,6 @@ from os import environ import logging import connexion -import sys -import json from sunrise6g_opensdk.common.sdk import Sdk as sdkclient logger = logging.getLogger(__name__) @@ -19,20 +17,28 @@ if environ.get('NETWORK_ADAPTER_NAME') is not None: adapters = sdkclient.create_adapters_from(adapter_specs={'network': network_adapter_specs}) network_adapter = adapters.get("network") - # else: # logging.error('Network adapter has not been specified! Aborting...') # sys.exit() -def _serialize_response(response): - """Helper function to serialize response objects to JSON-compatible format""" - if isinstance(response, tuple): - body, status = response - serialized_body = json.loads(json.dumps(body, default=str)) - return serialized_body, status - else: - serialized_response = json.loads(json.dumps(response, default=str)) - return serialized_response + +def _safe_http_json_response(response): + """ + Normalize adapter responses: + - list / dict → return directly (200) + - requests.Response → parse JSON body and status code safely + """ + if isinstance(response, (list, dict)): + return response, 200 + + if response is None: + return {"error": "Adapter returned no response"}, 502 + + try: + return response.json(), response.status_code + except Exception as e: + logger.exception("Failed to parse adapter HTTP response") + return {"error": "Invalid response from adapter", "details": str(e)}, 502 def create_qod_session(): @@ -40,16 +46,7 @@ def create_qod_session(): try: if network_adapter is not None: response = network_adapter.create_qod_session(connexion.request.get_json()) - print(response) - - # Convert the response to JSON-serializable format - if isinstance(response, tuple): - body, status = response - serialized_body = json.loads(json.dumps(body, default=str)) - return serialized_body, status - else: - serialized_response = json.loads(json.dumps(response, default=str)) - return serialized_response, 200 + return _safe_http_json_response(response) else: return { "applicationServer": { @@ -72,15 +69,7 @@ def get_qod_session(session_id: str): try: if network_adapter is not None: response = network_adapter.get_qod_session(session_id) - - # Serialize the response to handle non-JSON-serializable objects - if isinstance(response, tuple): - body, status = response - serialized_body = json.loads(json.dumps(body, default=str)) - return serialized_body, status - else: - serialized_response = json.loads(json.dumps(response, default=str)) - return serialized_response, 200 + return _safe_http_json_response(response) else: return {"message": "Requested QoD session with ID: " + session_id}, 200 except Exception as ce_: @@ -92,15 +81,7 @@ def delete_qod_session(session_id: str): try: if network_adapter is not None: response = network_adapter.delete_qod_session(session_id) - - # Serialize the response to handle non-JSON-serializable objects - if isinstance(response, tuple): - body, status = response - serialized_body = json.loads(json.dumps(body, default=str)) - return serialized_body, status - else: - serialized_response = json.loads(json.dumps(response, default=str)) - return serialized_response, 200 + return _safe_http_json_response(response) else: return {"message": "Deleting QoD session with ID: " + session_id}, 200 except Exception as ce_: @@ -112,15 +93,7 @@ def create_traffic_influence_resource(body): try: if network_adapter is not None: response = network_adapter.create_traffic_influence_resource(traffic_influence_info=body) - - # Serialize the response to handle non-JSON-serializable objects - if isinstance(response, tuple): - body, status = response - serialized_body = json.loads(json.dumps(body, default=str)) - return serialized_body, status - else: - serialized_response = json.loads(json.dumps(response, default=str)) - return serialized_response, 200 + return _safe_http_json_response(response) else: return { "trafficInfluenceID": "string", @@ -149,15 +122,7 @@ def delete_traffic_influence_resource(traffic_influence_id: str): try: if network_adapter is not None: response = network_adapter.delete_traffic_influence_resource(resource_id=traffic_influence_id) - - # Serialize the response to handle non-JSON-serializable objects - if isinstance(response, tuple): - body, status = response - serialized_body = json.loads(json.dumps(body, default=str)) - return serialized_body, status - else: - serialized_response = json.loads(json.dumps(response, default=str)) - return serialized_response, 200 + return _safe_http_json_response(response) else: return {"message": "Deleting Traffic Influence resource with ID: " + traffic_influence_id}, 200 except Exception as ce_: @@ -169,15 +134,7 @@ def get_traffic_influence_resource(traffic_influence_id: str): try: if network_adapter is not None: response = network_adapter.get_individual_traffic_influence_resource(resource_id=traffic_influence_id) - - # Serialize the response to handle non-JSON-serializable objects - if isinstance(response, tuple): - body, status = response - serialized_body = json.loads(json.dumps(body, default=str)) - return serialized_body, status - else: - serialized_response = json.loads(json.dumps(response, default=str)) - return serialized_response, 200 + return _safe_http_json_response(response) else: return {"message": "Requested Traffic Influence resource with ID: " + traffic_influence_id}, 200 except Exception as ce_: @@ -189,17 +146,9 @@ def get_all_traffic_influence_resources(): try: if network_adapter is not None: response = network_adapter.get_all_traffic_influence_resources() - - # Serialize the response to handle non-JSON-serializable objects - if isinstance(response, tuple): - body, status = response - serialized_body = json.loads(json.dumps(body, default=str)) - return serialized_body, status - else: - serialized_response = json.loads(json.dumps(response, default=str)) - return serialized_response, 200 + return _safe_http_json_response(response) else: return {"message": "List all Traffic Influence resources"}, 200 except Exception as ce_: logger.error(ce_) - return {"error": str(ce_)}, 500 \ No newline at end of file + return {"error": str(ce_)}, 500 diff --git a/srm-deployment.yaml b/srm-deployment.yaml deleted file mode 100644 index ea77f74..0000000 --- a/srm-deployment.yaml +++ /dev/null @@ -1,309 +0,0 @@ -kind: Namespace -apiVersion: v1 -metadata: - name: sunrise6g - labels: - name: sunrise6g ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: srmcontroller - name: srmcontroller -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: srmcontroller - strategy: {} - template: - metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: srmcontroller - spec: - containers: - - env: - - name: KUBERNETES_MASTER_IP - value: k3d-sunriseop-server-0 - - name: KUBERNETES_MASTER_PORT - value: "6443" - - name: K8S_NAMESPACE - value: - - name: KUBERNETES_USERNAME - value: - - name: EMP_STORAGE_URI - value: - - name: KUBERNETES_MASTER_TOKEN - value: eyJhbGciOiJSUzI1NiIsImtpZCI6IkRRS3VMNktkc1BOYk5ZeDhfSnFvVmJQdkJ6em1FODhPeHNIMHFya3JEQzgifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InNybS1zZWNyZXQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiY2x1c3Rlci1hZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImU1MjUxZjhiLWY2ODItNDU0Ni1hOTgxLWNlNTk0YTg2NmZiNCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmNsdXN0ZXItYWRtaW4ifQ.rnZyHFEE1ywceWqcio0UKQrp5GdfVGQOCXxx3RJpb_vvDj65GvNwN0VgA_anOlzj8kKJ9JQjWrA7an2k-5w0ycjeu8Ei_5Z0dvgRSpvKc4O5kCHddOB1kJl480hKWtZqgL0Vi6YbOziFGqvPd8hxHSTquxUgXEN2BStqII8MpVEK8z8iU2pJE5CNIaukGBozjlgc1Vb6HiEU4_UhlqG61uO6ReRVrzaYa4T1j4Zvvx1JN8t2HYcuv50QlHPrEAfW2F3ed0SBbb_X8AT0pGJrVas_uqZgMcN1j5BLO51RNmCY27ADHwCbj8HWuiHhyuLKQxYw8yKB-iMNQmq2fk3ezw - - name: ARTIFACT_MANAGER_ADDRESS - value: - - name: EDGE_CLOUD_ADAPTER_NAME - value: - - name: ADAPTER_BASE_URL - value: - - name: NETWORK_ADAPTER_NAME - value: - - name: NETWORK_ADAPTER_BASE_URL - value: - - name: SCS_AS_ID - value: - - name: PLATFORM_PROVIDER - value: - image: ghcr.io/sunriseopenoperatorplatform/srm/srm:1.0.1 - name: srmcontroller - ports: - - containerPort: 8080 - resources: {} - imagePullPolicy: Always - restartPolicy: Always -status: {} - ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: srm - name: srm -spec: - type: ClusterIP - ports: - - name: "8080" - port: 8080 - selector: - io.kompose.service: srmcontroller -status: - loadBalancer: {} - ---- -kind: PersistentVolume -apiVersion: v1 -metadata: - name: mongodb-pv-volume # Sets PV's name - labels: - type: local # Sets PV's type to local - app: mongosrm -spec: - storageClassName: manual - capacity: - storage: 200Mi # Sets PV Volume - accessModes: - - ReadWriteOnce - hostPath: - path: "/mnt/data/mongodb_srm" ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - creationTimestamp: null - labels: - io.kompose.service: mongo-db - name: mongo-db -spec: - storageClassName: manual - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 200Mi -status: {} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: mongosrm - name: mongosrm -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: mongosrm - strategy: - type: Recreate - template: - metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - #io.kompose.network/netEMPkub: "true" - io.kompose.service: mongosrm - spec: - containers: - - image: mongo - name: mongosrm - ports: - - containerPort: 27017 - resources: {} - volumeMounts: - - mountPath: /data/db - name: mongo-db - restartPolicy: Always - volumes: - - name: mongo-db - persistentVolumeClaim: - claimName: mongo-db -status: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: mongosrm - name: mongosrm -spec: - type: ClusterIP - ports: - - name: "27017" - port: 27017 - targetPort: 27017 - selector: - io.kompose.service: mongosrm -status: - loadBalancer: {} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oegmongo - name: oegmongo -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: oegmongo - strategy: - type: Recreate - template: - metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - #io.kompose.network/netEMPkub: "true" - io.kompose.service: oegmongo - spec: - containers: - - image: mongo - name: oegmongo - ports: - - containerPort: 27017 - resources: {} - restartPolicy: Always ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oegmongo - name: oegmongo -spec: - type: ClusterIP - ports: - - name: "27018" - port: 27018 - targetPort: 27017 - selector: - io.kompose.service: oegmongo -status: - loadBalancer: {} - ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oegcontroller - name: oegcontroller -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: oegcontroller - strategy: {} - template: - metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oegcontroller - spec: - containers: - - env: - - name: MONGO_URI - value: mongodb://oegmongo/sample_db?authSource=admin - - name: SRM_HOST - value: http://srm:8080/srm/1.0.0 - - name: FEDERATION_MANAGER_HOST - value: http://federation-manager:8989 - image: ghcr.io/sunriseopenoperatorplatform/oeg/oeg - name: oegcontroller - ports: - - containerPort: 8080 - resources: {} - imagePullPolicy: Always - restartPolicy: Always - -status: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oeg - name: oeg -spec: - type: LoadBalancer - ports: - - name: "8080" - port: 8081 - targetPort: 8080 - selector: - io.kompose.service: oegcontroller -status: - loadBalancer: {} - - diff --git a/sunrise6g-deployment.yaml b/sunrise6g-deployment.yaml deleted file mode 100644 index c7639bf..0000000 --- a/sunrise6g-deployment.yaml +++ /dev/null @@ -1,452 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: srmcontroller - name: srmcontroller -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: srmcontroller - strategy: {} - template: - metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: srmcontroller - spec: - containers: - - name: srmcontroller - env: - - name: KUBERNETES_MASTER_IP - value: k3d-sunriseop-server-0 - - name: KUBERNETES_MASTER_PORT - value: "6443" - - name: KUBERNETES_USERNAME - value: cluster-admin - - name: K8S_NAMESPACE - value: test - - name: EMP_STORAGE_URI - value: mongodb://mongosrm:27017 - - name: KUBERNETES_MASTER_TOKEN - value: eyJhbGciOiJSUzI1NiIsImtpZCI6Img4UWI1cDR5MzRlV1FzZ0dsTTdIYmdwa1RKVlQ5aWZtSjJ3M2V2Q1RqazgifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiLCJrM3MiXSwiZXhwIjoxNzg0NjQyNjMwLCJpYXQiOjE3NTMxMDY2MzAsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwianRpIjoiNWU4MDc0NDYtYmMzYy00OTI1LThhNWMtNjUxODQ2YWQ1ZGVmIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJzdW5yaXNlNmciLCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoic3VucmlzZS11c2VyIiwidWlkIjoiODFhMzAyNmQtYjcxMS00ZDJiLWEwYzktYjUwNmIwZjMwZTQyIn19LCJuYmYiOjE3NTMxMDY2MzAsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpzdW5yaXNlNmc6c3VucmlzZS11c2VyIn0.c6EbyUuXhCp6M1qkte7nGLFI8fDvWNPvMo0X3HIAq26pezXKEpTAafbHdGgk5o37zdgFW5RU6y6eduzdA65G8FXmHfGWIn_3h5EUvlg7ZGz-Pxl4rXehidlN-7ct8Kb9qChoIocdQWOEpCSuBTb1dS5Opc6DAXTchDkSDKoRLys4F7gu8_0djmwbDNh-17xrdeFMP76qUnBANCv3xCMzFUmYyJIj4P3ZAju7ru6xVjJOi9CveeFfuQZpYXIt_1H3zKe9zxHma5G3d6zmsfsrbfPSGXazuphC98O4M8xAJvvbRAx56tpdFs6y-BgMyEBffPxpRCW0FU3Ey8idSUK-WQ - - name: ARTIFACT_MANAGER_ADDRESS - value: http://artefact-manager-service:8000 - - name: EDGE_CLOUD_ADAPTER_NAME - value: kubernetes - - name: ADAPTER_BASE_URL - value: k3d-sunriseop-server-0 - - name: PLATFORM_PROVIDER - value: ISI - - name: NETWORK_ADAPTER_NAME - value: open5gs - - name: NETWORK_ADAPTER_BASE_URL - value: http://10.8.0.1:31004/ - - name: SCS_AS_ID - value: scs - - image: ghcr.io/sunriseopenoperatorplatform/srm/srm:1.0.1 - imagePullPolicy: Always - ports: - - containerPort: 8080 - resources: {} - - - name: openvpn - image: alpine:3.20 - securityContext: - capabilities: - add: - - NET_ADMIN - allowPrivilegeEscalation: false - volumeMounts: - - name: ovpn - mountPath: /vpn - readOnly: true - - name: dev-net-tun - mountPath: /dev/net/tun - command: - - /bin/sh - - -c - args: - - | - apk add --no-cache openvpn iproute2 bind-tools \ - && echo "Starting OpenVPN..." \ - && openvpn --config /vpn/icom-client-1.ovpn \ - --auth-user-pass /vpn/auth.txt \ - --verb 3 \ - --writepid /var/run/openvpn.pid - readinessProbe: - exec: - command: - - /bin/sh - - -c - - > - ip link show dev tun0 >/dev/null 2>&1 || exit 1 - - # Optional: confirm a VPN route exists (adapt the CIDR to your partner's network) - - ip route | grep -q 'tun0' || exit 1 - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: ovpn - secret: - secretName: partner-ovpn - - name: dev-net-tun - hostPath: - path: /dev/net/tun - type: CharDevice - restartPolicy: Always -status: {} - ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: srm - name: srm -spec: - type: NodePort - ports: - - name: "8080" - nodePort: 32415 - port: 8080 - targetPort: 8080 - selector: - io.kompose.service: srmcontroller -status: - loadBalancer: {} ---- -kind: PersistentVolume -apiVersion: v1 -metadata: - name: mongodb-pv-volume # Sets PV's name - labels: - type: local # Sets PV's type to local - app: mongosrm -spec: - storageClassName: manual - capacity: - storage: 200Mi # Sets PV Volume - accessModes: - - ReadWriteOnce - hostPath: - path: "/mnt/data/mongodb_srm" ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - creationTimestamp: null - labels: - io.kompose.service: mongo-db - name: mongo-db -spec: - storageClassName: manual - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 200Mi -status: {} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: mongosrm - name: mongosrm -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: mongosrm - strategy: - type: Recreate - template: - metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - #io.kompose.network/netEMPkub: "true" - io.kompose.service: mongosrm - spec: - containers: - - image: mongo - name: mongosrm - ports: - - containerPort: 27017 - resources: {} - volumeMounts: - - mountPath: /data/db - name: mongo-db - restartPolicy: Always - volumes: - - name: mongo-db - persistentVolumeClaim: - claimName: mongo-db -status: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: mongosrm - name: mongosrm -spec: - type: ClusterIP - ports: - - name: "27017" - port: 27017 - targetPort: 27017 - selector: - io.kompose.service: mongosrm -status: - loadBalancer: {} ---- -kind: PersistentVolume -apiVersion: v1 -metadata: - name: mongodb-oeg-pv-volume # Sets PV's name - labels: - type: local # Sets PV's type to local - app: oegmongo -spec: - storageClassName: manual - capacity: - storage: 50Mi # Sets PV Volume - accessModes: - - ReadWriteOnce - hostPath: - path: "/mnt/data/mongodb_oeg" ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - creationTimestamp: null - labels: - io.kompose.service: mongo-oeg - name: mongo-oeg -spec: - storageClassName: manual - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 50Mi -status: {} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oegmongo - name: oegmongo -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: oegmongo - strategy: - type: Recreate - template: - metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - #io.kompose.network/netEMPkub: "true" - io.kompose.service: oegmongo - spec: - containers: - - image: mongo - name: oegmongo - ports: - - containerPort: 27017 - resources: {} - volumeMounts: - - mountPath: /data/db - name: mongo-db - restartPolicy: Always - volumes: - - name: mongo-db - persistentVolumeClaim: - claimName: mongo-oeg -status: {} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oegmongo - name: oegmongo -spec: - type: ClusterIP - ports: - - name: "27017" - port: 27017 - targetPort: 27017 - selector: - io.kompose.service: oegmongo -status: - loadBalancer: {} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oegcontroller - name: oegcontroller -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: oegcontroller - strategy: {} - template: - metadata: - annotations: - kompose.cmd: kompose convert - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: oegcontroller - spec: - containers: - - env: - - name: MONGO_URI - value: mongodb://oegmongo:27017 - - name: SRM_HOST - value: http://srm:8080/srm/1.0.0 - - name: JWT_ISSUER - value: http://isiath.duckdns.org:8081/realms/federation - - name: JWT_PUBLIC_KEY - value: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkMTcpuPxHgERaVDjsF8frpprzxVqOOJoKyUDRcjRqtgc5mQG/OuPYble89BoD+vtVvwwN+1CiWXeU1II1yWyNKCz2wuHdlwJlp6A6pv2QhRTs1aR7RhSd7MItzep3kMiSkWFVLiDrio9npFiv+F0AfdBbs9mCdeTAZ8cKA9AKK8+rGKhuUIwvIAIzGMlGzFRtWtqz0gGuqQlhcXE6v52m1lYc7QopDN1A7vyuPVv4QC8/L43Y/tHm3v/5n7JwRdrS+eUPLKn+eENybMPFaPsh9x0ObDXgt8guFQIKx+jxuYlwK5B5Vta8d7aHP/BBQu44iKHbSlzwV13oR6sWRBIqQIDAQAB - - name: FEDERATION_MANAGER_HOST - value: http://federation-manager.federation-manager.svc.cluster.local:8989/operatorplatform/federation/v1 - - name: PARTNER_API_ROOT - value: http://10.8.0.1:31002 - - name: TOKEN_ENDPOINT - value: http://federation-manager.federation-manager.svc.cluster.local:8080/realms/federation/protocol/openid-connect/token - image: ghcr.io/sunriseopenoperatorplatform/oeg/oeg:1.0.1 - name: oegcontroller - ports: - - containerPort: 8080 - resources: {} - imagePullPolicy: Always - restartPolicy: Always - -status: {} ---- -apiVersion: v1 -kind: Service -metadata: - name: oeg - namespace: sunrise6g -spec: - type: ClusterIP - selector: - io.kompose.service: oegcontroller - ports: - - name: http - port: 80 - targetPort: 8080 ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: oegcontroller-ingress - namespace: sunrise6g - annotations: - traefik.ingress.kubernetes.io/router.entrypoints: web - # traefik.ingress.kubernetes.io/rewrite-target: /$2 -spec: - ingressClassName: traefik - rules: - - host: isiath.duckdns.org - http: - paths: - - path: /oeg - pathType: Prefix - backend: - service: - name: oeg - port: - number: 80 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: artefact-manager - namespace: sunrise6g -spec: - replicas: 1 - selector: - matchLabels: - app: artefact-manager - template: - metadata: - labels: - app: artefact-manager - spec: - containers: - - name: artefact-manager - image: ghcr.io/sunriseopenoperatorplatform/artefactmanager:0.5 - ports: - - containerPort: 8000 - env: - - name: PYTHONPATH - value: "/app" ---- -apiVersion: v1 -kind: Service -metadata: - name: artefact-manager-service - namespace: sunrise6g -spec: - type: NodePort - selector: - app: artefact-manager - ports: - - protocol: TCP - port: 8000 - targetPort: 8000 - nodePort: 30080 # Optional, must be between 30000–32767. Omit to let Kubernetes assign. - - -- GitLab