Commit d4edce5c authored by Sergio Gimenez's avatar Sergio Gimenez
Browse files

Improve federation zone sync and zone refresh

parent a0d5c0b0
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ class Configuration(BaseSettings):
    FEDERATION_MANAGER_HOST=os.getenv("FEDERATION_MANAGER_HOST")
    TOKEN_ENDPOINT = os.getenv('TOKEN_ENDPOINT')
    PARTNER_API_ROOT = os.getenv('PARTNER_API_ROOT')
    AVAIL_ZONE_NOTIF_LINK = os.getenv('AVAIL_ZONE_NOTIF_LINK')


config = Configuration()
+32 −6
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ from edge_cloud_management_api.managers.log_manager import logger
from edge_cloud_management_api.services.edge_cloud_services import PiEdgeAPIClientFactory
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
import json
import re
@@ -186,12 +187,37 @@ def create_app_instance():
        first_zone = app_zones[0] if isinstance(app_zones, list) and app_zones else {}
        if not isinstance(first_zone, dict):
            first_zone = {}
        edge_cloud_zone_id = (
            first_zone
            .get("EdgeCloudZone", {})
            .get("edgeCloudZoneId")
        zone_payload = (
            first_zone.get("EdgeCloudZone", {})
            if isinstance(first_zone.get("EdgeCloudZone", {}), dict)
            else first_zone
        )
        zone = get_zone(edge_cloud_zone_id)
        edge_cloud_zone_id = None
        if isinstance(zone_payload, dict):
            edge_cloud_zone_id = zone_payload.get("edgeCloudZoneId") or zone_payload.get("zoneId")

        zone = get_zone(edge_cloud_zone_id) if edge_cloud_zone_id else None
        if not zone and edge_cloud_zone_id:
            try:
                zones = pi_edge_client.edge_cloud_zones()
                if isinstance(zones, list):
                    for z in zones:
                        if isinstance(z, dict) and z.get("edgeCloudZoneId") == edge_cloud_zone_id:
                            z["_id"] = edge_cloud_zone_id
                            z["isLocal"] = "true"
                            insert_zones([z])
                            zone = z
                            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["_id"] = edge_cloud_zone_id
            zone_payload.setdefault("isLocal", "true")
            insert_zones([zone_payload])
            zone = zone_payload

        if not zone:
            return jsonify({
                "error": "Edge Cloud Zone not found",
+26 −14
Original line number Diff line number Diff line
@@ -47,17 +47,24 @@ def create_federation():
        insert_zones(zones_to_insert)    
        insert_federation(fed)

        zone_ids = [zone.get('zoneId') for zone in av_zones]
        callback_url = body.get('availZoneNotifLink')  # Optional from request
        avail_zone_notif_link = config.AVAIL_ZONE_NOTIF_LINK or body.get("availZoneNotifLink")
        accepted_availability_zones = []
        for zone in av_zones or []:
            if isinstance(zone, dict) and zone.get("zoneId"):
                accepted_availability_zones.append({"zoneId": zone.get("zoneId")})
        if accepted_availability_zones:
            zone_response, zone_code = federation_client.subscribe_to_zones(
            response.get('federationContextId'),
            zone_ids,
                response.get("federationContextId"),
                accepted_availability_zones,
                token,
            callback_url
                avail_zone_notif_link,
            )
            if zone_code != 200:
            logger.warning(f"Zone subscription returned non-200: {zone_code} - {zone_response}")

                logger.warning(
                    "Zone subscription returned non-200: %s - %s",
                    zone_code,
                    zone_response,
                )
    return response, code

def get_federation(federationContextId):
@@ -119,8 +126,14 @@ def delete_onboarded_app(federationContextId, appId):
def request_zone_synch(federationContextId):
    token = __get_token()
    body = request.get_json()
    response = federation_client.request_zone_sync(federation_context_id=federationContextId, body=body, token=token)
    return jsonify(response)
    if not body:
        body = {}
    if not body.get("availZoneNotifLink"):
        body["availZoneNotifLink"] = config.AVAIL_ZONE_NOTIF_LINK
    response, code = federation_client.request_zone_sync(
        federation_context_id=federationContextId, body=body, token=token
    )
    return jsonify(response), code

def get_zone_resource_info(federationContextId, zoneId):
    token = __get_token()
@@ -137,4 +150,3 @@ def __get_token():
    token = bearer.split()[1]
    # __token = requests.post(TOKEN_ENDPOINT, headers=token_headers, data=data).json().get('access_token')
    return token
+19 −8
Original line number Diff line number Diff line
@@ -30,9 +30,12 @@ class FederationManagerClient:
        
        try:
            response = requests.post(url, json=data, headers=headers, timeout=20)
            try:
                body = response.json()
            except ValueError:
                body = response.text
            response.raise_for_status()
            print(response.json())
            return response.json(), 200
            return body, response.status_code
        except Timeout:
            logger.error("POST /partner timed out")
            return {"error": "Request timed out"}, 408
@@ -41,7 +44,11 @@ class FederationManagerClient:
            return {"error": "Connection error"}, 504
        except requests.exceptions.HTTPError as http_err:
            logger.error(f"POST /partner HTTP error: {http_err}")
            return {'Error': http_err.response.json().get('detail')}, response.status_code
            try:
                body = http_err.response.json()
            except ValueError:
                body = http_err.response.text
            return {"error": body}, http_err.response.status_code
        except Exception as e:
            logger.error(f"POST /partner unexpected error: {e}")
            return {"error": str(e)}, 500
@@ -239,19 +246,23 @@ class FederationManagerClient:
        url = f"{self.base_url}/{federation_context_id}/zones"
        try:
            response = requests.post(url, headers=self._get_headers(token), json=body, timeout=10)
            return response.json()
            try:
                response_body = response.json()
            except ValueError:
                response_body = response.text
            return response_body, response.status_code
        except Timeout:
            logger.error("Zone synchronization timed out")
            return {"error": "Request timed out", "status_code": 408}
            return {"error": "Request timed out"}, 408
        except ConnectionError:
            logger.error("Zone synchronization connection error")
            return {"error": "Connection error", "status_code": 503}
            return {"error": "Connection error"}, 503
        except requests.exceptions.HTTPError as http_err:
            logger.error(f"Zone synchronization HTTP error: {http_err}")
            return {"error": str(http_err), "status_code": response.status_code}
            return {"error": str(http_err)}, response.status_code
        except Exception as e:
            logger.error(f"Zone synchronization unexpected error: {e}")
            return {"error": str(e), "status_code": 500}
            return {"error": str(e)}, 500

    def subscribe_to_zones(self, federation_context_id: str, accepted_zone_ids: list, token: str,
                           callback_url: str = None):
+29 −2
Original line number Diff line number Diff line
@@ -1124,6 +1124,33 @@ paths:
      #       application/problem+json:
      #         schema:
      #           $ref: '#/components/schemas/ProblemDetails'
  /{federationContextId}/zones:
    post:
      tags:
      - FederationManagement
      summary: Subscribe to availability zones for a federation context.
      operationId: edge_cloud_management_api.controllers.federation_manager_controller.request_zone_synch
      parameters:
      - name: federationContextId
        in: path
        required: true
        style: simple
        explode: false
        schema:
          $ref: '#/components/schemas/FederationContextId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        "200":
          description: Zone subscription accepted
        "400":
          description: Bad request
        "404":
          description: Federation not found
  /fed-context-id:
   get:
     tags: