Commit ba67f754 authored by Laskaratos Dimitris's avatar Laskaratos Dimitris
Browse files

Added partner app deployment code

parent 006a3f47
Loading
Loading
Loading
Loading
Loading
+68 −11
Original line number Diff line number Diff line
@@ -2,9 +2,12 @@ from flask import jsonify, request
from pydantic import ValidationError
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 get_fed


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

class NotFound404Exception(Exception):
    pass
@@ -87,28 +90,82 @@ def delete_app(appId, x_correlator=None):

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")
       app_zones = body.get("appZones")
    #    k8s_ref = body.get("kubernetesClusterRef")
       pi_edge_client_factory = PiEdgeAPIClientFactory()
       pi_edge_client = pi_edge_client_factory.create_pi_edge_api_client()
       
       if not app_id or not app_zones :
           return jsonify({"error": "Missing required fields: appId, edgeCloudZoneId, or kubernetesCLusterRef"}), 400
       
       local_zone = get_zone(app_zones[0].get('EdgeCloudZone').get('edgeCloudZoneId'))
       if not local_zone:
           # TODO: apply federation logic
           return 'Zone belongs to federated partner OP. Switching to Federation Manager.'
       zone = get_zone(app_zones[0].get('EdgeCloudZone').get('edgeCloudZoneId'))
       if zone.get('isLocal')=='false':
           # Step 1: retrieve app metadata
           appData = pi_edge_client.get_app(appId=app_id).get('appManifest')
           #Step 2: compose GSMA artefact payload
           artefact = {}
           artefact['artefactId'] = app_id
           artefact['appProviderId'] = appData.get('appProvider')
           artefact['artefactName'] = appData.get('name')
           artefact['artefactVersionInfo'] = appData.get('version')
           artefact['artefactDescription'] = ''
           repoInfo = appData.get('appRepo')
           artefact['repoType'] = repoInfo.get('type')
           artefact['artefactRepoLocation'] = {'repoURL': repoInfo.get('imagePath'), 'userName': repoInfo.get('userName'), 'password': repoInfo.get('credentials'), 'token': ''}
           exposedInterfaces = []
           networkInterfaces = appData.get('componentSpec')[0].get('networkInterfaces')
           for ni in networkInterfaces:
               interface = {'interfaceId': '', 'commProtocol': ni.get('protocol'), 'commPort': ni.get('port'), 'visibilityType': ni.get('visibilityType'), 'network': '', 'InterfaceName': ''}
               exposedInterfaces.append(interface)
           artefact['componentSpec'] = [
               {
                   'componentName': appData.get('name'), 
                   'numOfInstances': 0, 
                   'restartPolicy': 'RESTART_POLICY_ALWAYS', 
                   'exposedInterfaces': exposedInterfaces, 
                   'compEnvParams': [],
                   'persistentVolumes': []
                }
            ]
           # Step 3: Send artefact to local fed manager
           fed_token = get_fed(zone.get('fedContextId')).get('token')
           create_artefact_response = federation_client.create_artefact(artefact=artefact, federation_context_id=zone.get('fedContextId'), token=fed_token)
           # Step 4: Onboard app
           if create_artefact_response.status_code == 200 or create_artefact_response.status_code ==409:
                # Step 5: Create GSM onboard app payload
                onboard_app = {}
                onboard_app['appId'] = app_id
                onboard_app['appProviderId'] = appData.get('appProvider')
                onboard_app['appDeploymentZones'] = []
                appMetaData = {}
                appMetaData['appName'] = appData.get('name')
                appMetaData['version'] = appData.get('version')
                onboard_app['appMetaData'] = appMetaData
                onboard_app['appComponentSpecs'] = [{'serviceNameNB': appData.get('name'),
                                                     'serviceNameEW': appData.get('name'),
                                                     'componentName': appData.get('name'),
                                                     'artefactId': app_id
                                                     }
                                                   ]
                # Step 6: Onboard app at partner
                onboard_app_response = federation_client.onboard_application(federation_context_id=zone.get('fedContextId'), body=onboard_app, token=fed_token)
                if onboard_app_response.status_code==200:
                    # Step 7: Construct GSMA deployment payload
                    deploy_app = {}
                    deploy_app['appId'] = app_id
                    deploy_app['appVersion'] = appData.get('version')
                    deploy_app['appProviderId'] = appData.get('appProvider')
                    deploy_app['zoneInfo'] = {'zoneId': zone.get('edgeCloudZoneId')}
                    # Step 8: Deploy app at partner
                    deploy_app_response = federation_client.deploy_app_partner(federation_context_id=zone.get('fedContextId'), body=deploy_app, token = fed_token)
                    return deploy_app_response

       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()
       logger.info(f"Preparing to send deployment request to SRM for appId={app_id}")
       
       print("\n === Preparing Deployment Request ===")
       print(f" Endpoint: {pi_edge_client.base_url}/deployedServiceFunction")
+5 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ 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 PiEdgeAPIClientFactory
from edge_cloud_management_api.services.storage_service import insert_zones
from edge_cloud_management_api.services.federation_services import FederationManagerClientFactory


try:
@@ -13,10 +14,14 @@ try:
    zones = api_client.edge_cloud_zones()
    for zone in zones:
        zone['_id'] = zone.get('edgeCloudZoneId')
        zone['isLocal'] = 'true'
    insert_zones(zones)
except Exception as e:
    logger.error(e.args)

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

class EdgeCloudZone(BaseModel):
    edgeCloudZoneId: str = Field(..., description="Unique identifier of the Edge Cloud Zone")
    edgeCloudZoneName: str = Field(..., description="Name of the Edge Cloud Zone")
+15 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ from requests.exceptions import Timeout, ConnectionError
from edge_cloud_management_api.managers.log_manager import logger
import requests
from edge_cloud_management_api.configs.env_config import config
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
@@ -30,6 +31,20 @@ def create_federation():
    response, code = federation_client.post_partner(body, token)
    fed = {'_id': response.get('federationContextId'), 'token': token}
    if code==200:
        provider = response.get('partnerOPFederationId')
        av_zones = response.get('offeredAvailabilityZones')
        zones_to_insert = []
        for zone in av_zones:
            inserted_item = {'_id': zone.get('zoneId'), 
                             'edgeCloudProvider': provider, 
                             'edgeCloudZoneId': zone.get('zoneId'), 
                             'edgeCloudZoneName': zone.get('geographyDetails'), 
                             'edgeCloudZoneStatus': 'unknown',
                             'isLocal': 'false',
                             'fedContextId': response.get('federationContextId')
                             }
            zones_to_insert.append(inserted_item)
        insert_zones(zones_to_insert)    
        insert_federation(fed)
    return response, code

+21 −2
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ 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
from edge_cloud_management_api.services.edge_cloud_services import PiEdgeAPIClientFactory
from edge_cloud_management_api.services.storage_service import delete_fed
from edge_cloud_management_api.services.storage_service import delete_fed, delete_partner_zones

class FederationManagerClient:
    def __init__(self, base_url=None):
@@ -71,6 +71,7 @@ class FederationManagerClient:
            response = requests.delete(url, headers=self._get_headers(token), timeout=10)
            if response.content:
                delete_fed(federation_context_id)
                delete_partner_zones()
                return response.json(), 200
            return {"status": response.status_code}
        except Timeout:
@@ -110,7 +111,7 @@ class FederationManagerClient:
    def onboard_application(self, federation_context_id: str, body: dict, token: str):
        url = f"{self.base_url}/{federation_context_id}/application/onboarding"
        try:
           response = requests.post(url, headers=self._get_headers(), json=body, timeout=10)
           response = requests.post(url, headers=self._get_headers(token), json=body, timeout=10)
           response.raise_for_status()
           return response.json()
        except Timeout:
@@ -167,6 +168,14 @@ class FederationManagerClient:

    '''---PARTNER APP DEPLOYMENT---'''

    def deploy_app_partner(self, federation_context_id: str, body: dict, token: str):
        url = f"{self.base_url}/{federation_context_id}/application/lcm"
        try:
            response = requests.post(url, headers=self._get_headers(token), json=body, timeout=10)
            return response
        except Exception as e:
            logger.error(f"DELETE onboarding app unexpected error: {e}")
            return {"error": str(e), "status_code": 500}

    '''---AVAILABILITY ZONE INFO SYNCHRONIZATION---'''

@@ -227,6 +236,16 @@ class FederationManagerClient:
            logger.error(f"Remove Zone sync unexpected error: {e}")
            return {"error": str(e), "status_code": 500}    

    '''---ARTEFACT API---'''

    def create_artefact(self, artefact: dict, federation_context_id, token: str):
        url = f"{self.base_url}/{federation_context_id}/artefact"
        try:
            response = requests.post(url, headers=self._get_headers(token), json=artefact, timeout=10)
            return response
        except Exception as e:
            logger.error(f"Create artefact unexpected error: {e}")
            return {"error": str(e), "status_code": 500}

class FederationManagerClientFactory:
    def __init__(self):
+7 −0
Original line number Diff line number Diff line
@@ -19,6 +19,13 @@ def get_zone(zone_id: str):
        zone = col.find_one({'_id': zone_id})
        return zone

def delete_partner_zones():
        collection = "zones"
        myclient = pymongo.MongoClient(storage_url)
        mydbmongo = myclient[mydb_mongo]
        col = mydbmongo[collection]
        col.delete_many({'isLocal': 'false'})

def insert_federation(fed: dict):
        collection = 'federations'
        myclient = pymongo.MongoClient(storage_url)