Commit 91fa9112 authored by George Papathanail's avatar George Papathanail
Browse files

new post /appinstance specification, federationmanager apis

parent 07c60a60
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,7 @@ class Configuration(BaseSettings):
    PI_EDGE_USERNAME: str = os.getenv("PI_EDGE_USERNAME")
    PI_EDGE_USERNAME: str = os.getenv("PI_EDGE_USERNAME")
    PI_EDGE_PASSWORD: str = os.getenv("PI_EDGE_PASSWORD")
    PI_EDGE_PASSWORD: str = os.getenv("PI_EDGE_PASSWORD")
    HTTP_PROXY: str = os.getenv("HTTP_PROXY")
    HTTP_PROXY: str = os.getenv("HTTP_PROXY")
    FEDERATION_MANAGER_HOST=os.getenv("FEDERATION_MANAGER_HOST")




config = Configuration()
config = Configuration()
+96 −43
Original line number Original line Diff line number Diff line
@@ -124,26 +124,26 @@ def delete_app(appId, x_correlator=None): # noqa: E501
        )
        )




def create_app_instance():
#def create_app_instance():
    logger.info("Received request to create app instance")
 #   logger.info("Received request to create app instance")


    try:
  #  try:
        # Step 1: Get request body
        # Step 1: Get request body
        body = request.get_json()
   #     body = request.get_json()
        logger.debug(f"Request body: {body}")
    #    logger.debug(f"Request body: {body}")


        # Step 2: Validate body format
        # Step 2: Validate body format
        app_id = body.get('appId')
     #   app_id = body.get('appId')
        app_zones = body.get('appZones')
     #   app_zones = body.get('appZones')


        if not app_id or not app_zones:
      #  if not app_id or not app_zones:
            return jsonify({"error": "Missing required fields: appId or appZones"}), 400
       #     return jsonify({"error": "Missing required fields: appId or appZones"}), 400


        # Step 3: Connect to Mongo and check if app exists
        # Step 3: Connect to Mongo and check if app exists
        # with MongoManager() as mongo_manager:
        # with MongoManager() as mongo_manager:
        #     app_data = mongo_manager.find_document("apps", {"_id": app_id})
        #     app_data = mongo_manager.find_document("apps", {"_id": app_id})
        pi_edge_client_factory = PiEdgeAPIClientFactory()
       # pi_edge_client_factory = PiEdgeAPIClientFactory()
        pi_edge_client = pi_edge_client_factory.create_pi_edge_api_client()
       # pi_edge_client = pi_edge_client_factory.create_pi_edge_api_client()
        # app_data = pi_edge_client.get_app(app_id)
        # app_data = pi_edge_client.get_app(app_id)


        # if len(app_data)<1:
        # if len(app_data)<1:
@@ -155,42 +155,95 @@ def create_app_instance():
        # Step 4: Deploy app instance using Pi-Edge client
        # Step 4: Deploy app instance using Pi-Edge client
    
    


        logger.info(f"Preparing to send deployment request to SRM for appId={app_id}")
        #logger.info(f"Preparing to send deployment request to SRM for appId={app_id}")


        deployment_payload = {
       # deployment_payload = {
            "appId": app_id,
        #    "appId": app_id,
            "appZones": app_zones
        #    "appZones": app_zones
        }
        #}


        #Print everything before sending
        #Print everything before sending
       # print("\n=== Preparing Deployment Request ===")
       # print(f"Endpoint: {pi_edge_client.base_url}/deployedServiceFunction")
       # print(f"Headers: {pi_edge_client._get_headers()}")
       # print(f"Payload: {deployment_payload}")
       # print("=== End of Deployment Request ===\n")

        #Try sending to Pi-Edge, catch connection errors separately
       # try:
        #    response = pi_edge_client.deploy_service_function(data=deployment_payload)

         #   if isinstance(response, dict) and "error" in response:
          #      logger.warning(f"Failed to deploy service function: {response}")
           #     return jsonify({
            #        "warning": "Deployment not completed (SRM service unreachable)",
             #       "details": response
             #   }), 202  # Still accept the request but warn

           # logger.info(f"Deployment response from SRM: {response}")

       # except Exception as inner_error:
        #    logger.error(f"Exception while trying to deploy to SRM: {inner_error}")
         #   return jsonify({
          #      "warning": "SRM backend unavailable. Deployment request was built correctly.",
           #     "details": str(inner_error)
           # }), 202  # Still accept it (because your backend worked)

       # return jsonify({"message": f"Application {app_id} instantiation accepted"}), 202

   # except ValidationError as e:
    #    logger.error(f"Validation error: {str(e)}")
     #   return jsonify({"error": "Validation error", "details": str(e)}), 400
    #except Exception as e:
     #   logger.error(f"Unexpected error in create_app_instance: {str(e)}")
     #   return jsonify({"error": "An unexpected error occurred", "details": str(e)}), 500

def create_app_instance():
    logger.info("Received request to create app instance")
    
    try: 
        
       body = request.get_json()
       logger.debug(f"Request body: {body}")
       
       app_id = body.get("appId")
       edge_zone_id = body.get("edgeCloudZoneId")
       k8s_ref = body.get("kubernetesClusterRef")
       
       if not app_id or not edge_zone_id or not k8s_ref:
           return jsonify({"error": "Missing required fields: appId, edgeCloudZoneId, or kubernetesCLusterRef"}), 400
       
       logger.info(f"Preparing to send deployment request to SRM for appId={app_id}")
       
       pi_edge_client_factory = PiEdgeAPICLientFactory()
       pi_edge_client = pi_edge_client_factory.create_pi_edge_api_client()
       
       print("\n === Preparing Deployment Request ===")
       print("\n === Preparing Deployment Request ===")
       print(f" Endpoint: {pi_edge_client.base_url}/deployedServiceFunction")
       print(f" Endpoint: {pi_edge_client.base_url}/deployedServiceFunction")
       print(f" Headers: {pi_edge_client._get_headers()}")
       print(f" Headers: {pi_edge_client._get_headers()}")
        print(f"Payload: {deployment_payload}")
       print(f"Payload: {body}")
       print("=== End of Deployment Request ===\n")
       print("=== End of Deployment Request ===\n")
       
       
        #Try sending to Pi-Edge, catch connection errors separately
       try:
       try:
            response = pi_edge_client.deploy_service_function(data=deployment_payload)
          response = pi_edge_client_deploy_service_function(data=body)
          
          
          if isinstance(response, dict) and "error" in response:
          if isinstance(response, dict) and "error" in response:
              logger.warning(f"Failed to deploy service function: {response}")
              logger.warning(f"Failed to deploy service function: {response}")
              return jsonify({
              return jsonify({
                  "warning": "Deployment not completed (SRM service unreachable)",
                  "warning": "Deployment not completed (SRM service unreachable)",
                  "details": response
                  "details": response
                }), 202  # Still accept the request but warn
                  
                  
            logger.info(f"Deployment response from SRM: {response}")
              }), 202
              
              
          logger.info(f"Deployment response from SRM: {response}")
       except Exception as inner_error:
       except Exception as inner_error:
           logger.error(f"Exception while trying to deploy to SRM: {inner_error}")
           logger.error(f"Exception while trying to deploy to SRM: {inner_error}")
           return jsonify({
           return jsonify({
               "warning": "SRM backend unavailable. Deployment request was built correctly.",
               "warning": "SRM backend unavailable. Deployment request was built correctly.",
               "details": str(inner_error)
               "details": str(inner_error)
            }), 202  # Still accept it (because your backend worked)
           }),202
           
           
       return jsonify({"message": f"Application {app_id} instantiation accepted"}), 202
       return jsonify({"message": f"Application {app_id} instantiation accepted"}), 202

    except ValidationError as e:
    except ValidationError as e:
        logger.error(f"Validation error: {str(e)}")
        logger.error(f"Validation error: {str(e)}")
        return jsonify({"error": "Validation error", "details": str(e)}), 400
        return jsonify({"error": "Validation error", "details": str(e)}), 400
+53 −0
Original line number Original line Diff line number Diff line
from flask import request, jsonify
from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory

factory = FederationManagerClientFactory()
federation_client = factory.create_federation_client()

def create_federation():
    """
    POST /partner
    Forwards the federation creation request to Federation Manager.
    """
    try:
        body = request.get_json()
        result = federation_client.post_partner(body)
        return jsonify(result), 200 if "error" not in result else 502
    except Exception as e:
        return jsonify({"error": str(e)}), 400


def get_federation(federationContextId):
    """
    GET /{federationContextId}/partner
    Forwards the GET federation info request.
    """
    try:
        result = federation_client.get_partner(federationContextId)
        return jsonify(result), 200 if "error" not in result else 502
    except Exception as e:
        return jsonify({"error": str(e)}), 400


def delete_federation(federationContextId):
    """
    DELETE /{federationContextId}/partner
    Forwards the DELETE federation request.
    """
    try:
        result = federation_client.delete_partner(federationContextId)
        return jsonify(result), 200 if "error" not in result else 502
    except Exception as e:
        return jsonify({"error": str(e)}), 400


def get_federation_context_ids():
    """
    GET /fed-context-id
    Forwards the request to fetch federation context IDs.
    """
    try:
        result = federation_client.get_federation_context_ids()
        return jsonify(result), 200 if "error" not in result else 502
    except Exception as e:
        return jsonify({"error": str(e)}), 400
+52 −0
Original line number Original line Diff line number Diff line
from pydantic import BaseModel, Field
from typing import List, Optional


class MobileNetworkIds(BaseModel):
    mncs: List[str]
    mcc: str


class FixedNetworkIds(BaseModel):
    __root__: List[str]


class CallbackCredentials(BaseModel):
    tokenUrl: str
    clientId: str
    clientSecret: str


class ServiceEndpoint(BaseModel):
    ipv4Addresses: Optional[List[str]] = None
    ipv6Addresses: Optional[List[str]] = None
    port: Optional[int] = None
    fqdn: Optional[str] = None


class ZoneDetails(BaseModel):
    geographyDetails: str
    zoneId: str
    geolocation: str


class FederationRequestData(BaseModel):
    origOPFederationId: str
    origOPCountryCode: Optional[str]
    origOPMobileNetworkCodes: Optional[MobileNetworkIds]
    origOPFixedNetworkCodes: Optional[List[str]]
    initialDate: str
    partnerStatusLink: str
    partnerCallbackCredentials: Optional[CallbackCredentials]


class FederationResponseData(BaseModel):
    federationContextId: str
    partnerOPFederationId: str
    partnerOPCountryCode: Optional[str]
    partnerOPMobileNetworkCodes: Optional[MobileNetworkIds]
    partnerOPFixedNetworkCodes: Optional[List[str]]
    offeredAvailabilityZones: Optional[List[ZoneDetails]]
    platformCaps: List[str]
    edgeDiscoveryServiceEndPoint: Optional[ServiceEndpoint]
    lcmServiceEndPoint: Optional[ServiceEndpoint]
+108 −0
Original line number Original line Diff line number Diff line
import requests
from requests.exceptions import Timeout, ConnectionError
from edge_cloud_management_api.configs.env_config import config
from edge_cloud_management_api.managers.log_manager import logger

class FederationManagerClient:
    def __init__(self, base_url=None):
        self.base_url = base_url or config.FEDERATION_MANAGER_HOST

    def _get_headers(self):
        return {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }

    def post_partner(self, data: dict):
        url = f"{self.base_url}/partner"
        try:
            response = requests.post(url, json=data, headers=self._get_headers(), timeout=10)
            response.raise_for_status()
            return response.json()
        except Timeout:
            logger.error("POST /partner timed out")
            return {"error": "Request timed out"}
        except ConnectionError:
            logger.error("POST /partner connection error")
            return {"error": "Connection error"}
        except requests.exceptions.HTTPError as http_err:
            logger.error(f"POST /partner HTTP error: {http_err}")
            return {"error": str(http_err), "status_code": response.status_code}
        except Exception as e:
            logger.error(f"POST /partner unexpected error: {e}")
            return {"error": str(e)}

    def get_partner(self, federation_context_id: str):
        url = f"{self.base_url}/{federation_context_id}/partner"
        try:
            response = requests.get(url, headers=self._get_headers(), timeout=10)
            response.raise_for_status()
            return response.json()
        except Timeout:
            logger.error("GET /{id}/partner timed out")
            return {"error": "Request timed out"}
        except ConnectionError:
            logger.error("GET /{id}/partner connection error")
            return {"error": "Connection error"}
        except requests.exceptions.HTTPError as http_err:
            logger.error(f"GET /{id}/partner HTTP error: {http_err}")
            return {"error": str(http_err), "status_code": response.status_code}
        except Exception as e:
            logger.error(f"GET /{id}/partner unexpected error: {e}")
            return {"error": str(e)}

    def delete_partner(self, federation_context_id: str):
        url = f"{self.base_url}/{federation_context_id}/partner"
        try:
            response = requests.delete(url, headers=self._get_headers(), timeout=10)
            if response.content:
                return response.json()
            return {"status": response.status_code}
        except Timeout:
            logger.error("DELETE /{id}/partner timed out")
            return {"error": "Request timed out"}
        except ConnectionError:
            logger.error("DELETE /{id}/partner connection error")
            return {"error": "Connection error"}
        except requests.exceptions.HTTPError as http_err:
            logger.error(f"DELETE /{id}/partner HTTP error: {http_err}")
            return {"error": str(http_err), "status_code": response.status_code}
        except Exception as e:
            logger.error(f"DELETE /{id}/partner unexpected error: {e}")
            return {"error": str(e)}

    def get_federation_context_ids(self):
        url = f"{self.base_url}/fed-context-id"
        try:
            response = requests.get(url, headers=self._get_headers(), timeout=10)
            response.raise_for_status()
            return response.json()
        except Timeout:
            logger.error("GET /fed-context-id timed out")
            return {"error": "Request timed out"}
        except ConnectionError:
            logger.error("GET /fed-context-id connection error")
            return {"error": "Connection error"}
        except requests.exceptions.HTTPError as http_err:
            logger.error(f"GET /fed-context-id HTTP error: {http_err}")
            return {"error": str(http_err), "status_code": response.status_code}
        except Exception as e:
            logger.error(f"GET /fed-context-id unexpected error: {e}")
            return {"error": str(e)}


class FederationManagerClientFactory:
    def __init__(self):
        self.default_base_url = config.FEDERATION_MANAGER_HOST

    def create_federation_client(self, base_url=None):
        base_url = base_url or self.default_base_url
        return FederationManagerClient(base_url=base_url)


if __name__ == "__main__":
    factory = FederationManagerClientFactory()
    client = factory.create_federation_client()

    result = client.get_federation_context_ids()
    logger.info("Federation Context IDs: %s", result)
Loading