Loading edge_cloud_management_api/controllers/app_controllers.py +20 −21 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ from edge_cloud_management_api.controllers.app_partner_orchestration import reso from edge_cloud_management_api.services.edge_cloud_services import SRMAPIClientFactory from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory from edge_cloud_management_api.services.storage_service import get_zone from edge_cloud_management_api.services.storage_service import insert_zones from edge_cloud_management_api.services.storage_service import get_fed, get_all_feds import json import re Loading Loading @@ -155,14 +154,7 @@ def delete_app(appId, x_correlator=None): try: srm_factory = SRMAPIClientFactory() api_client = srm_factory.create_srm_api_client() response = api_client.delete_app(appId=appId) if isinstance(response, dict) and int(response.get("status_code", 500)) >= 400: logger.info("SRM app delete failed, attempting federation cleanup") else: return response feds = get_all_feds() if feds: app_provider_id = None app_response = api_client.get_app(appId) if isinstance(app_response, dict): Loading @@ -171,6 +163,7 @@ def delete_app(appId, x_correlator=None): if isinstance(manifest, dict) and not app_provider_id: app_provider_id = manifest.get("appProvider") or manifest.get("appProviderId") if feds: cleanup_response = cleanup_federated_app( federation_client=federation_client, feds=feds, Loading @@ -180,8 +173,14 @@ def delete_app(appId, x_correlator=None): resolve_federated_app_identity=_resolve_federated_app_identity, ) if cleanup_response is not None: cleanup_body, cleanup_status = cleanup_response if cleanup_status not in (200, 202, 204): return cleanup_response response = api_client.delete_app(appId=appId) if isinstance(response, dict) and int(response.get("status_code", 500)) >= 400: return response return response except NotFound404Exception: Loading edge_cloud_management_api/controllers/app_instance_helpers.py +20 −1 Original line number Diff line number Diff line from edge_cloud_management_api.services.storage_service import get_zone from edge_cloud_management_api.controllers.edge_cloud_controller import get_local_zones def _find_local_zone(zone_id, zone_provider=None): for zone in get_local_zones(): if not isinstance(zone, dict): continue if zone.get("edgeCloudZoneId") != zone_id: continue if zone_provider and zone.get("edgeCloudProvider") != zone_provider: continue return zone return None def normalize_local_app_instance(instance): Loading Loading @@ -54,7 +67,13 @@ def enrich_instance_zone_from_catalog(instance): return instance zone_provider = zone.get("edgeCloudProvider") stored_zone = get_zone(zone_id, zone_provider) if zone_provider and zone_provider != "unknown" else get_zone(zone_id) stored_zone = None if zone_provider and zone_provider != "unknown": stored_zone = get_zone(zone_id, zone_provider) else: stored_zone = _find_local_zone(zone_id) if not isinstance(stored_zone, dict): stored_zone = get_zone(zone_id) if not isinstance(stored_zone, dict): return instance Loading edge_cloud_management_api/controllers/app_partner_orchestration.py +17 −9 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import json from flask import jsonify from edge_cloud_management_api.controllers.edge_cloud_controller import get_local_zones from edge_cloud_management_api.managers.log_manager import logger from edge_cloud_management_api.services.storage_service import get_fed from edge_cloud_management_api.services.storage_service import get_zone Loading @@ -12,7 +13,7 @@ def resolve_target_zone(srm_client, edge_cloud_zone_id, edge_cloud_provider, zon zone = get_zone(edge_cloud_zone_id, edge_cloud_provider) if edge_cloud_zone_id else None if not zone and edge_cloud_zone_id: try: zones = srm_client.edge_cloud_zones() zones = get_local_zones() if isinstance(zones, list): for candidate_zone in zones: if not isinstance(candidate_zone, dict): Loading @@ -22,18 +23,14 @@ def resolve_target_zone(srm_client, edge_cloud_zone_id, edge_cloud_provider, zon if edge_cloud_provider and candidate_zone.get("edgeCloudProvider") != edge_cloud_provider: continue if candidate_zone.get("edgeCloudProvider") == edge_cloud_provider or not edge_cloud_provider: candidate_zone["isLocal"] = "true" insert_zones([candidate_zone]) zone = candidate_zone break except Exception as exc: logger.info(f"Failed to refresh zones from SRM: {exc}") if not zone and edge_cloud_zone_id and isinstance(zone_payload, dict): zone_payload = dict(zone_payload) zone_payload.setdefault("isLocal", "true") insert_zones([zone_payload]) zone = get_zone(edge_cloud_zone_id, edge_cloud_provider) or zone_payload zone = dict(zone_payload) zone.setdefault("isLocal", "true") return zone Loading @@ -42,6 +39,7 @@ def cleanup_federated_app(federation_client, feds, app_id, app_provider_id, norm if not feds: return None cleanup_performed = False for fed in feds: fed_token = fed.get("token") federation_context_id = fed.get("_id") Loading @@ -56,6 +54,7 @@ def cleanup_federated_app(federation_client, feds, app_id, app_provider_id, norm token=fed_token, ) if fed_code == 200 and isinstance(fed_instances, list): cleanup_performed = True for zone_info in fed_instances: if not isinstance(zone_info, dict): continue Loading @@ -76,15 +75,24 @@ def cleanup_federated_app(federation_client, feds, app_id, app_provider_id, norm zone_id=zone_id, token=fed_token, ) elif fed_code not in (404, 422): return jsonify(fed_instances), fed_code remove_response, remove_status = federation_client.delete_onboarded_app( remove_response = federation_client.delete_onboarded_app( federation_context_id, normalize_federated_app_id(app_id), fed_token, ) remove_status = int(remove_response.get("status_code", 500)) if isinstance(remove_response, dict) else 500 if remove_status in (200, 202, 204): cleanup_performed = True continue if remove_status == 404: continue return jsonify(remove_response), remove_status if cleanup_performed: return "", 204 return None Loading edge_cloud_management_api/controllers/edge_cloud_controller.py +16 −43 Original line number Diff line number Diff line Loading @@ -4,20 +4,10 @@ from typing import List from edge_cloud_management_api.configs.env_config import config from edge_cloud_management_api.managers.log_manager import logger from edge_cloud_management_api.services.edge_cloud_services import SRMAPIClientFactory from edge_cloud_management_api.services.storage_service import insert_zones, get_zones from edge_cloud_management_api.services.storage_service import get_zones from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory try: srm_factory = SRMAPIClientFactory() api_client = srm_factory.create_srm_api_client() zones = api_client.edge_cloud_zones() for zone in zones: zone['isLocal'] = 'true' insert_zones(zones) except Exception as e: logger.error(e.args) factory = FederationManagerClientFactory() federation_client = factory.create_federation_client() Loading Loading @@ -68,43 +58,22 @@ def get_federated_zones() -> List[EdgeCloudZone]: """get partner/federated Operator Platform available zones from Federation Manager""" return [] def get_cached_zones() -> list[dict]: """Retrieve cached zones and merge with local SRM zones.""" cached = [] def get_partner_zones() -> list[dict]: """Retrieve persisted partner zones only.""" try: cached = get_zones() zones = get_zones() except Exception as e: logger.warning("Failed to read cached zones: %s", e) merged = [] existing_zone_keys = set() for zone in cached or []: if not isinstance(zone, dict): continue zone_key = (zone.get("edgeCloudProvider"), zone.get("edgeCloudZoneId")) if zone_key in existing_zone_keys: continue merged.append(zone) existing_zone_keys.add(zone_key) for zone in get_local_zones(): zone_key = None if isinstance(zone, dict): zone_key = (zone.get("edgeCloudProvider"), zone.get("edgeCloudZoneId")) if zone_key and zone_key not in existing_zone_keys: merged.append(zone) existing_zone_keys.add(zone_key) return merged logger.warning("Failed to read partner zones: %s", e) return [] return [ zone for zone in (zones or []) if isinstance(zone, dict) and zone.get("isLocal") == "false" ] def get_all_cloud_zones() -> List[EdgeCloudZone]: """Get all available zones from local and federated Operator Platforms""" # Convert dicts to EdgeCloudZone # local_zones = [EdgeCloudZone(**z) for z in get_local_zones()] # Federated zones are already EdgeCloudZone instances # federated_zones = get_federated_zones() # return local_zones + federated_zones return get_local_zones() + get_federated_zones() return get_local_zones() + get_partner_zones() + get_federated_zones() def get_edge_cloud_zones(x_correlator: str | None = None, region=None, status=None): # noqa: E501 """Retrieve a list of the operators Edge Cloud Zones and their status Loading Loading @@ -136,7 +105,11 @@ def get_edge_cloud_zones(x_correlator: str | None = None, region=None, status=No def query_status_matches(zone: EdgeCloudZone) -> bool: return query_params.status is None or zone.edgeCloudZoneStatus == query_params.status response = [EdgeCloudZone(**zone).model_dump() for zone in get_cached_zones()] response = [ zone.model_dump() for zone in (EdgeCloudZone(**zone_dict) for zone_dict in get_all_cloud_zones()) if query_region_matches(zone) and query_status_matches(zone) ] return jsonify(response), 200 except ValidationError as e: Loading edge_cloud_management_api/controllers/federation_manager_controller.py +11 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ from flask import request, jsonify import logging import connexion from requests.exceptions import Timeout, ConnectionError from pydantic import ValidationError from edge_cloud_management_api.managers.log_manager import logger import requests from edge_cloud_management_api.configs.env_config import config Loading @@ -9,6 +10,8 @@ from edge_cloud_management_api.services.storage_service import insert_zones from edge_cloud_management_api.services.storage_service import insert_federation, get_fed, get_all_feds from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory from edge_cloud_management_api.models.federation_manager_models import FederationRequestData from edge_cloud_management_api.models.federation_manager_models import ZoneRegistrationRequestData token_headers = {'Authorization': 'Basic b3JpZ2luYXRpbmctb3AtMTpkZDd2TndGcWpOcFl3YWdobEV3TWJ3MTBnMGtsV0RIYg==', 'Content-Type': 'application/x-www-form-urlencoded' Loading Loading @@ -50,6 +53,10 @@ def create_federation(): """POST /partner - Create federation with partner OP.""" body = request.get_json() try: FederationRequestData(**body) except ValidationError as error: return jsonify({"error": "Invalid input", "details": error.errors()}), 400 token = __get_token() if not token: return jsonify({"error": "Unable to obtain access token"}), 500 Loading Loading @@ -126,6 +133,10 @@ def request_zone_synch(federationContextId): body = {} if not body.get("availZoneNotifLink"): body["availZoneNotifLink"] = config.AVAIL_ZONE_NOTIF_LINK try: ZoneRegistrationRequestData(**body) except ValidationError as error: return jsonify({"error": "Invalid input", "details": error.errors()}), 400 response, code = federation_client.request_zone_sync( federation_context_id=federationContextId, body=body, token=token ) Loading Loading
edge_cloud_management_api/controllers/app_controllers.py +20 −21 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ from edge_cloud_management_api.controllers.app_partner_orchestration import reso from edge_cloud_management_api.services.edge_cloud_services import SRMAPIClientFactory from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory from edge_cloud_management_api.services.storage_service import get_zone from edge_cloud_management_api.services.storage_service import insert_zones from edge_cloud_management_api.services.storage_service import get_fed, get_all_feds import json import re Loading Loading @@ -155,14 +154,7 @@ def delete_app(appId, x_correlator=None): try: srm_factory = SRMAPIClientFactory() api_client = srm_factory.create_srm_api_client() response = api_client.delete_app(appId=appId) if isinstance(response, dict) and int(response.get("status_code", 500)) >= 400: logger.info("SRM app delete failed, attempting federation cleanup") else: return response feds = get_all_feds() if feds: app_provider_id = None app_response = api_client.get_app(appId) if isinstance(app_response, dict): Loading @@ -171,6 +163,7 @@ def delete_app(appId, x_correlator=None): if isinstance(manifest, dict) and not app_provider_id: app_provider_id = manifest.get("appProvider") or manifest.get("appProviderId") if feds: cleanup_response = cleanup_federated_app( federation_client=federation_client, feds=feds, Loading @@ -180,8 +173,14 @@ def delete_app(appId, x_correlator=None): resolve_federated_app_identity=_resolve_federated_app_identity, ) if cleanup_response is not None: cleanup_body, cleanup_status = cleanup_response if cleanup_status not in (200, 202, 204): return cleanup_response response = api_client.delete_app(appId=appId) if isinstance(response, dict) and int(response.get("status_code", 500)) >= 400: return response return response except NotFound404Exception: Loading
edge_cloud_management_api/controllers/app_instance_helpers.py +20 −1 Original line number Diff line number Diff line from edge_cloud_management_api.services.storage_service import get_zone from edge_cloud_management_api.controllers.edge_cloud_controller import get_local_zones def _find_local_zone(zone_id, zone_provider=None): for zone in get_local_zones(): if not isinstance(zone, dict): continue if zone.get("edgeCloudZoneId") != zone_id: continue if zone_provider and zone.get("edgeCloudProvider") != zone_provider: continue return zone return None def normalize_local_app_instance(instance): Loading Loading @@ -54,7 +67,13 @@ def enrich_instance_zone_from_catalog(instance): return instance zone_provider = zone.get("edgeCloudProvider") stored_zone = get_zone(zone_id, zone_provider) if zone_provider and zone_provider != "unknown" else get_zone(zone_id) stored_zone = None if zone_provider and zone_provider != "unknown": stored_zone = get_zone(zone_id, zone_provider) else: stored_zone = _find_local_zone(zone_id) if not isinstance(stored_zone, dict): stored_zone = get_zone(zone_id) if not isinstance(stored_zone, dict): return instance Loading
edge_cloud_management_api/controllers/app_partner_orchestration.py +17 −9 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import json from flask import jsonify from edge_cloud_management_api.controllers.edge_cloud_controller import get_local_zones from edge_cloud_management_api.managers.log_manager import logger from edge_cloud_management_api.services.storage_service import get_fed from edge_cloud_management_api.services.storage_service import get_zone Loading @@ -12,7 +13,7 @@ def resolve_target_zone(srm_client, edge_cloud_zone_id, edge_cloud_provider, zon zone = get_zone(edge_cloud_zone_id, edge_cloud_provider) if edge_cloud_zone_id else None if not zone and edge_cloud_zone_id: try: zones = srm_client.edge_cloud_zones() zones = get_local_zones() if isinstance(zones, list): for candidate_zone in zones: if not isinstance(candidate_zone, dict): Loading @@ -22,18 +23,14 @@ def resolve_target_zone(srm_client, edge_cloud_zone_id, edge_cloud_provider, zon if edge_cloud_provider and candidate_zone.get("edgeCloudProvider") != edge_cloud_provider: continue if candidate_zone.get("edgeCloudProvider") == edge_cloud_provider or not edge_cloud_provider: candidate_zone["isLocal"] = "true" insert_zones([candidate_zone]) zone = candidate_zone break except Exception as exc: logger.info(f"Failed to refresh zones from SRM: {exc}") if not zone and edge_cloud_zone_id and isinstance(zone_payload, dict): zone_payload = dict(zone_payload) zone_payload.setdefault("isLocal", "true") insert_zones([zone_payload]) zone = get_zone(edge_cloud_zone_id, edge_cloud_provider) or zone_payload zone = dict(zone_payload) zone.setdefault("isLocal", "true") return zone Loading @@ -42,6 +39,7 @@ def cleanup_federated_app(federation_client, feds, app_id, app_provider_id, norm if not feds: return None cleanup_performed = False for fed in feds: fed_token = fed.get("token") federation_context_id = fed.get("_id") Loading @@ -56,6 +54,7 @@ def cleanup_federated_app(federation_client, feds, app_id, app_provider_id, norm token=fed_token, ) if fed_code == 200 and isinstance(fed_instances, list): cleanup_performed = True for zone_info in fed_instances: if not isinstance(zone_info, dict): continue Loading @@ -76,15 +75,24 @@ def cleanup_federated_app(federation_client, feds, app_id, app_provider_id, norm zone_id=zone_id, token=fed_token, ) elif fed_code not in (404, 422): return jsonify(fed_instances), fed_code remove_response, remove_status = federation_client.delete_onboarded_app( remove_response = federation_client.delete_onboarded_app( federation_context_id, normalize_federated_app_id(app_id), fed_token, ) remove_status = int(remove_response.get("status_code", 500)) if isinstance(remove_response, dict) else 500 if remove_status in (200, 202, 204): cleanup_performed = True continue if remove_status == 404: continue return jsonify(remove_response), remove_status if cleanup_performed: return "", 204 return None Loading
edge_cloud_management_api/controllers/edge_cloud_controller.py +16 −43 Original line number Diff line number Diff line Loading @@ -4,20 +4,10 @@ from typing import List from edge_cloud_management_api.configs.env_config import config from edge_cloud_management_api.managers.log_manager import logger from edge_cloud_management_api.services.edge_cloud_services import SRMAPIClientFactory from edge_cloud_management_api.services.storage_service import insert_zones, get_zones from edge_cloud_management_api.services.storage_service import get_zones from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory try: srm_factory = SRMAPIClientFactory() api_client = srm_factory.create_srm_api_client() zones = api_client.edge_cloud_zones() for zone in zones: zone['isLocal'] = 'true' insert_zones(zones) except Exception as e: logger.error(e.args) factory = FederationManagerClientFactory() federation_client = factory.create_federation_client() Loading Loading @@ -68,43 +58,22 @@ def get_federated_zones() -> List[EdgeCloudZone]: """get partner/federated Operator Platform available zones from Federation Manager""" return [] def get_cached_zones() -> list[dict]: """Retrieve cached zones and merge with local SRM zones.""" cached = [] def get_partner_zones() -> list[dict]: """Retrieve persisted partner zones only.""" try: cached = get_zones() zones = get_zones() except Exception as e: logger.warning("Failed to read cached zones: %s", e) merged = [] existing_zone_keys = set() for zone in cached or []: if not isinstance(zone, dict): continue zone_key = (zone.get("edgeCloudProvider"), zone.get("edgeCloudZoneId")) if zone_key in existing_zone_keys: continue merged.append(zone) existing_zone_keys.add(zone_key) for zone in get_local_zones(): zone_key = None if isinstance(zone, dict): zone_key = (zone.get("edgeCloudProvider"), zone.get("edgeCloudZoneId")) if zone_key and zone_key not in existing_zone_keys: merged.append(zone) existing_zone_keys.add(zone_key) return merged logger.warning("Failed to read partner zones: %s", e) return [] return [ zone for zone in (zones or []) if isinstance(zone, dict) and zone.get("isLocal") == "false" ] def get_all_cloud_zones() -> List[EdgeCloudZone]: """Get all available zones from local and federated Operator Platforms""" # Convert dicts to EdgeCloudZone # local_zones = [EdgeCloudZone(**z) for z in get_local_zones()] # Federated zones are already EdgeCloudZone instances # federated_zones = get_federated_zones() # return local_zones + federated_zones return get_local_zones() + get_federated_zones() return get_local_zones() + get_partner_zones() + get_federated_zones() def get_edge_cloud_zones(x_correlator: str | None = None, region=None, status=None): # noqa: E501 """Retrieve a list of the operators Edge Cloud Zones and their status Loading Loading @@ -136,7 +105,11 @@ def get_edge_cloud_zones(x_correlator: str | None = None, region=None, status=No def query_status_matches(zone: EdgeCloudZone) -> bool: return query_params.status is None or zone.edgeCloudZoneStatus == query_params.status response = [EdgeCloudZone(**zone).model_dump() for zone in get_cached_zones()] response = [ zone.model_dump() for zone in (EdgeCloudZone(**zone_dict) for zone_dict in get_all_cloud_zones()) if query_region_matches(zone) and query_status_matches(zone) ] return jsonify(response), 200 except ValidationError as e: Loading
edge_cloud_management_api/controllers/federation_manager_controller.py +11 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ from flask import request, jsonify import logging import connexion from requests.exceptions import Timeout, ConnectionError from pydantic import ValidationError from edge_cloud_management_api.managers.log_manager import logger import requests from edge_cloud_management_api.configs.env_config import config Loading @@ -9,6 +10,8 @@ from edge_cloud_management_api.services.storage_service import insert_zones from edge_cloud_management_api.services.storage_service import insert_federation, get_fed, get_all_feds from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory from edge_cloud_management_api.models.federation_manager_models import FederationRequestData from edge_cloud_management_api.models.federation_manager_models import ZoneRegistrationRequestData token_headers = {'Authorization': 'Basic b3JpZ2luYXRpbmctb3AtMTpkZDd2TndGcWpOcFl3YWdobEV3TWJ3MTBnMGtsV0RIYg==', 'Content-Type': 'application/x-www-form-urlencoded' Loading Loading @@ -50,6 +53,10 @@ def create_federation(): """POST /partner - Create federation with partner OP.""" body = request.get_json() try: FederationRequestData(**body) except ValidationError as error: return jsonify({"error": "Invalid input", "details": error.errors()}), 400 token = __get_token() if not token: return jsonify({"error": "Unable to obtain access token"}), 500 Loading Loading @@ -126,6 +133,10 @@ def request_zone_synch(federationContextId): body = {} if not body.get("availZoneNotifLink"): body["availZoneNotifLink"] = config.AVAIL_ZONE_NOTIF_LINK try: ZoneRegistrationRequestData(**body) except ValidationError as error: return jsonify({"error": "Invalid input", "details": error.errors()}), 400 response, code = federation_client.request_zone_sync( federation_context_id=federationContextId, body=body, token=token ) Loading