Loading edge_cloud_management_api/controllers/app_controllers.py +35 −180 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ def delete_app(appId, x_correlator=None): 500, ) def create_app_instance(): logger.info("Received request to create app instance") try: Loading @@ -96,202 +97,56 @@ def create_app_instance(): app_id = body.get("appId") app_zones = body.get("appZones") 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, appZones"}), 400 return jsonify({"error": "Missing required fields: appId, edgeCloudZoneId, or kubernetesCLusterRef"}), 400 logger.info(f"Attempting to get zone for: {app_zones[0].get('EdgeCloudZone').get('edgeCloudZoneId')}") zone = get_zone(app_zones[0].get('EdgeCloudZone').get('edgeCloudZoneId')) logger.info(f"Retrieved zone: {zone}") # ---------------------------------------------------------------------- # PARTNER DEPLOYMENT (Federation path) # ---------------------------------------------------------------------- if zone.get('isLocal') == 'false': # Step 1: retrieve app metadata from SRM appData = pi_edge_client.get_app(appId=app_id).get('appManifest') # ------------------------------------------------------------------ # Step 2: Build GSMA Artefact Payload (DIRTY PATCHED VERSION) # ------------------------------------------------------------------ artefact = {} artefact['artefactId'] = app_id artefact['appProviderId'] = appData.get('appProvider') or "dummy-provider" artefact['artefactName'] = appData.get('name') or "unnamed-app" artefact['artefactVersionInfo'] = appData.get('version') or "1.0.0" artefact['artefactDescription'] = "" # Mandatory GSMA fields (missing in your original code) artefact['artefactDescriptorType'] = "HELM" artefact['artefactVirtType'] = "CONTAINER_TYPE" repoInfo = appData.get('appRepo') or {} artefact['repoType'] = repoInfo.get('type') or "PRIVATEREPO" # Dirty patch for repo credentials artefact['artefactRepoLocation'] = { 'repoURL': repoInfo.get('imagePath') or "", 'userName': repoInfo.get('userName') or "dummy-user", 'password': repoInfo.get('credentials') or "dummy-password", 'token': "" } # Extract interfaces exposedInterfaces = [] componentSpec = appData.get('componentSpec') or [{}] networkInterfaces = componentSpec[0].get('networkInterfaces') or [] interface_counter = 1 for ni in networkInterfaces: interface_id = f"ifc_{ni.get('port', 0)}_{ni.get('protocol', 'TCP')}_{interface_counter}" interface_id = interface_id.replace("-", "_") interface_counter += 1 network_name = f"net_{ni.get('port', 0)}_{ni.get('protocol', 'TCP')}" network_name = network_name.replace("-", "_") if len(network_name) < 8: network_name = network_name + "_net" interface = { 'interfaceId': 'interface_id', 'commProtocol': ni.get('protocol') or 'TCP', 'commPort': ni.get('port') or 80, 'visibilityType': ni.get('visibilityType') or 'VISIBILITY_EXTERNAL', 'network': network_name, 'InterfaceName': network_name } exposedInterfaces.append(interface) artefact['componentSpec'] = [ { 'componentName': appData.get('name') or "component", 'numOfInstances': 0, 'images': [app_id], 'restartPolicy': 'RESTART_POLICY_ALWAYS', 'exposedInterfaces': exposedInterfaces, 'compEnvParams': [], 'persistentVolumes': [], 'computeResourceProfile': { "cpuArchType": "ISA_X86_64", "numCPU": { "whole":{"value":1} }, "memory": 256, "diskStorage":0, "gpu": [], "vpu": 0, "fpga": 0, "hugepages": [], "cpuExclusivity": False } } ] # ------------------------------------------------------------------ # Step 3: Upload artefact to Federation 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 ) if zone is None: logger.error("get_zone returned None!") return jsonify({"error": "Zone not found"}), 404 # ------------------------------------------------------------------ # Step 4: If artefact OK, start onboarding # ------------------------------------------------------------------ if create_artefact_response.status_code in [200, 409]: onboard_app = { "appId": app_id, "appProviderId": appData.get("appProvider") or "dummy-provider", "appDeploymentZones": [], "appMetaData": { "appName": appData.get('name') or "unnamed-app", "version": appData.get('version') or "1.0.0" }, "appComponentSpecs": [ { "serviceNameNB": appData.get("name"), "serviceNameEW": appData.get("name"), "componentName": appData.get("name"), "artefactId": app_id } ] } onboard_app_response = federation_client.onboard_application( federation_context_id=zone.get('fedContextId'), body=onboard_app, token=fed_token ) # ------------------------------------------------------------------ # Step 5: Deploy at partner OP # ------------------------------------------------------------------ if onboard_app_response.status_code == 200: deploy_app = { "appId": app_id, "appVersion": appData.get("version") or "1.0.0", "appProviderId": appData.get("appProvider") or "dummy-provider", "zoneInfo": {"zoneId": zone.get('edgeCloudZoneId')} } deploy_app_response = federation_client.deploy_app_partner( federation_context_id=zone.get('fedContextId'), body=deploy_app, token=fed_token ) is_local = zone.get('isLocal') logger.info(f"Zone isLocal: {is_local}") if is_local == 'false': # Step 1: retrieve app metadata appData = pi_edge_client.get_app(appId=app_id).get('appManifest') # ... rest of federation logic ... return deploy_app_response return onboard_app_response return create_artefact_response # ---------------------------------------------------------------------- # LOCAL DEPLOYMENT (via SRM) # ---------------------------------------------------------------------- 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") print(f"Headers: {pi_edge_client._get_headers()}") print(f"Payload: {body}") print("=== End of Deployment Request ===\n") try: response = pi_edge_client.deploy_service_function(data=body) logger.info(f"Type of response from SRM: {type(response)}") logger.info(f"Response from SRM: {response}") if response is None: logger.error("SRM returned None!") return jsonify({"error": "SRM returned no response"}), 500 if isinstance(response, dict) and "error" in response: logger.warning(f"Failed to deploy service function: {response}") return jsonify({ "warning": "Deployment not completed (SRM not reachable)", "warning": "Deployment not completed (SRM service unreachable)", "details": response }), 202 return response except Exception as inner_error: return jsonify({ "warning": "SRM backend unreachable", "details": str(inner_error) }), 202 logger.info(f"Deployment response from SRM: {response}") return response 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": "Unexpected error", "details": str(e)}), 500 return jsonify({"error": "An unexpected error occurred", "details": str(e)}), 500 def get_app_instance(app_id=None, x_correlator=None, app_instance_id=None, region=None): Loading Loading
edge_cloud_management_api/controllers/app_controllers.py +35 −180 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ def delete_app(appId, x_correlator=None): 500, ) def create_app_instance(): logger.info("Received request to create app instance") try: Loading @@ -96,202 +97,56 @@ def create_app_instance(): app_id = body.get("appId") app_zones = body.get("appZones") 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, appZones"}), 400 return jsonify({"error": "Missing required fields: appId, edgeCloudZoneId, or kubernetesCLusterRef"}), 400 logger.info(f"Attempting to get zone for: {app_zones[0].get('EdgeCloudZone').get('edgeCloudZoneId')}") zone = get_zone(app_zones[0].get('EdgeCloudZone').get('edgeCloudZoneId')) logger.info(f"Retrieved zone: {zone}") # ---------------------------------------------------------------------- # PARTNER DEPLOYMENT (Federation path) # ---------------------------------------------------------------------- if zone.get('isLocal') == 'false': # Step 1: retrieve app metadata from SRM appData = pi_edge_client.get_app(appId=app_id).get('appManifest') # ------------------------------------------------------------------ # Step 2: Build GSMA Artefact Payload (DIRTY PATCHED VERSION) # ------------------------------------------------------------------ artefact = {} artefact['artefactId'] = app_id artefact['appProviderId'] = appData.get('appProvider') or "dummy-provider" artefact['artefactName'] = appData.get('name') or "unnamed-app" artefact['artefactVersionInfo'] = appData.get('version') or "1.0.0" artefact['artefactDescription'] = "" # Mandatory GSMA fields (missing in your original code) artefact['artefactDescriptorType'] = "HELM" artefact['artefactVirtType'] = "CONTAINER_TYPE" repoInfo = appData.get('appRepo') or {} artefact['repoType'] = repoInfo.get('type') or "PRIVATEREPO" # Dirty patch for repo credentials artefact['artefactRepoLocation'] = { 'repoURL': repoInfo.get('imagePath') or "", 'userName': repoInfo.get('userName') or "dummy-user", 'password': repoInfo.get('credentials') or "dummy-password", 'token': "" } # Extract interfaces exposedInterfaces = [] componentSpec = appData.get('componentSpec') or [{}] networkInterfaces = componentSpec[0].get('networkInterfaces') or [] interface_counter = 1 for ni in networkInterfaces: interface_id = f"ifc_{ni.get('port', 0)}_{ni.get('protocol', 'TCP')}_{interface_counter}" interface_id = interface_id.replace("-", "_") interface_counter += 1 network_name = f"net_{ni.get('port', 0)}_{ni.get('protocol', 'TCP')}" network_name = network_name.replace("-", "_") if len(network_name) < 8: network_name = network_name + "_net" interface = { 'interfaceId': 'interface_id', 'commProtocol': ni.get('protocol') or 'TCP', 'commPort': ni.get('port') or 80, 'visibilityType': ni.get('visibilityType') or 'VISIBILITY_EXTERNAL', 'network': network_name, 'InterfaceName': network_name } exposedInterfaces.append(interface) artefact['componentSpec'] = [ { 'componentName': appData.get('name') or "component", 'numOfInstances': 0, 'images': [app_id], 'restartPolicy': 'RESTART_POLICY_ALWAYS', 'exposedInterfaces': exposedInterfaces, 'compEnvParams': [], 'persistentVolumes': [], 'computeResourceProfile': { "cpuArchType": "ISA_X86_64", "numCPU": { "whole":{"value":1} }, "memory": 256, "diskStorage":0, "gpu": [], "vpu": 0, "fpga": 0, "hugepages": [], "cpuExclusivity": False } } ] # ------------------------------------------------------------------ # Step 3: Upload artefact to Federation 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 ) if zone is None: logger.error("get_zone returned None!") return jsonify({"error": "Zone not found"}), 404 # ------------------------------------------------------------------ # Step 4: If artefact OK, start onboarding # ------------------------------------------------------------------ if create_artefact_response.status_code in [200, 409]: onboard_app = { "appId": app_id, "appProviderId": appData.get("appProvider") or "dummy-provider", "appDeploymentZones": [], "appMetaData": { "appName": appData.get('name') or "unnamed-app", "version": appData.get('version') or "1.0.0" }, "appComponentSpecs": [ { "serviceNameNB": appData.get("name"), "serviceNameEW": appData.get("name"), "componentName": appData.get("name"), "artefactId": app_id } ] } onboard_app_response = federation_client.onboard_application( federation_context_id=zone.get('fedContextId'), body=onboard_app, token=fed_token ) # ------------------------------------------------------------------ # Step 5: Deploy at partner OP # ------------------------------------------------------------------ if onboard_app_response.status_code == 200: deploy_app = { "appId": app_id, "appVersion": appData.get("version") or "1.0.0", "appProviderId": appData.get("appProvider") or "dummy-provider", "zoneInfo": {"zoneId": zone.get('edgeCloudZoneId')} } deploy_app_response = federation_client.deploy_app_partner( federation_context_id=zone.get('fedContextId'), body=deploy_app, token=fed_token ) is_local = zone.get('isLocal') logger.info(f"Zone isLocal: {is_local}") if is_local == 'false': # Step 1: retrieve app metadata appData = pi_edge_client.get_app(appId=app_id).get('appManifest') # ... rest of federation logic ... return deploy_app_response return onboard_app_response return create_artefact_response # ---------------------------------------------------------------------- # LOCAL DEPLOYMENT (via SRM) # ---------------------------------------------------------------------- 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") print(f"Headers: {pi_edge_client._get_headers()}") print(f"Payload: {body}") print("=== End of Deployment Request ===\n") try: response = pi_edge_client.deploy_service_function(data=body) logger.info(f"Type of response from SRM: {type(response)}") logger.info(f"Response from SRM: {response}") if response is None: logger.error("SRM returned None!") return jsonify({"error": "SRM returned no response"}), 500 if isinstance(response, dict) and "error" in response: logger.warning(f"Failed to deploy service function: {response}") return jsonify({ "warning": "Deployment not completed (SRM not reachable)", "warning": "Deployment not completed (SRM service unreachable)", "details": response }), 202 return response except Exception as inner_error: return jsonify({ "warning": "SRM backend unreachable", "details": str(inner_error) }), 202 logger.info(f"Deployment response from SRM: {response}") return response 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": "Unexpected error", "details": str(e)}), 500 return jsonify({"error": "An unexpected error occurred", "details": str(e)}), 500 def get_app_instance(app_id=None, x_correlator=None, app_instance_id=None, region=None): Loading