X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FN2VC.git;a=blobdiff_plain;f=n2vc%2Fn2vc_juju_conn.py;h=4efbd1ca8aecafae83d0c5c708a1dafde2cbb194;hp=c01c436924fa23538910858400c049090684faaa;hb=0ebadd80cf20e478677b1af7b57a3faaefcc239a;hpb=7114f65ca3ba581281fa03639f21db61a111b53e diff --git a/n2vc/n2vc_juju_conn.py b/n2vc/n2vc_juju_conn.py index c01c436..4efbd1c 100644 --- a/n2vc/n2vc_juju_conn.py +++ b/n2vc/n2vc_juju_conn.py @@ -24,6 +24,7 @@ import asyncio import logging from n2vc.config import EnvironConfig +from n2vc.definitions import RelationEndpoint from n2vc.exceptions import ( N2VCBadArgumentsException, N2VCException, @@ -38,6 +39,7 @@ from n2vc.n2vc_conn import N2VCConnector from n2vc.n2vc_conn import obj_to_dict, obj_to_yaml from n2vc.libjuju import Libjuju from n2vc.store import MotorStore +from n2vc.utils import get_ee_id_components, generate_random_alfanum_string from n2vc.vca.connection import get_connection from retrying_async import retry @@ -716,69 +718,48 @@ class N2VCJujuConnector(N2VCConnector): async def add_relation( self, - ee_id_1: str, - ee_id_2: str, - endpoint_1: str, - endpoint_2: str, - vca_id: str = None, + provider: RelationEndpoint, + requirer: RelationEndpoint, ): """ Add relation between two charmed endpoints - :param: ee_id_1: The id of the first execution environment - :param: ee_id_2: The id of the second execution environment - :param: endpoint_1: The endpoint in the first execution environment - :param: endpoint_2: The endpoint in the second execution environment - :param: vca_id: VCA ID + :param: provider: Provider relation endpoint + :param: requirer: Requirer relation endpoint """ - self.log.debug( - "adding new relation between {} and {}, endpoints: {}, {}".format( - ee_id_1, ee_id_2, endpoint_1, endpoint_2 - ) + self.log.debug(f"adding new relation between {provider} and {requirer}") + cross_model_relation = ( + provider.model_name != requirer.model_name + or requirer.vca_id != requirer.vca_id ) - libjuju = await self._get_libjuju(vca_id) - - # check arguments - if not ee_id_1: - message = "EE 1 is mandatory" - self.log.error(message) - raise N2VCBadArgumentsException(message=message, bad_args=["ee_id_1"]) - if not ee_id_2: - message = "EE 2 is mandatory" - self.log.error(message) - raise N2VCBadArgumentsException(message=message, bad_args=["ee_id_2"]) - if not endpoint_1: - message = "endpoint 1 is mandatory" - self.log.error(message) - raise N2VCBadArgumentsException(message=message, bad_args=["endpoint_1"]) - if not endpoint_2: - message = "endpoint 2 is mandatory" - self.log.error(message) - raise N2VCBadArgumentsException(message=message, bad_args=["endpoint_2"]) - - # get the model, the applications and the machines from the ee_id's - model_1, app_1, _machine_1 = self._get_ee_id_components(ee_id_1) - model_2, app_2, _machine_2 = self._get_ee_id_components(ee_id_2) - - # model must be the same - if model_1 != model_2: - message = "EE models are not the same: {} vs {}".format(ee_id_1, ee_id_2) - self.log.error(message) - raise N2VCBadArgumentsException( - message=message, bad_args=["ee_id_1", "ee_id_2"] - ) - - # add juju relations between two applications try: - await libjuju.add_relation( - model_name=model_1, - endpoint_1="{}:{}".format(app_1, endpoint_1), - endpoint_2="{}:{}".format(app_2, endpoint_2), - ) + if cross_model_relation: + # Cross-model relation + provider_libjuju = await self._get_libjuju(provider.vca_id) + requirer_libjuju = await self._get_libjuju(requirer.vca_id) + offer = await provider_libjuju.offer(provider) + if offer: + saas_name = await requirer_libjuju.consume( + requirer.model_name, offer, provider_libjuju + ) + await requirer_libjuju.add_relation( + requirer.model_name, + requirer.endpoint, + saas_name, + ) + else: + # Standard relation + vca_id = provider.vca_id + model = provider.model_name + libjuju = await self._get_libjuju(vca_id) + # add juju relations between two applications + await libjuju.add_relation( + model_name=model, + endpoint_1=provider.endpoint, + endpoint_2=requirer.endpoint, + ) except Exception as e: - message = "Error adding relation between {} and {}: {}".format( - ee_id_1, ee_id_2, e - ) + message = f"Error adding relation between {provider} and {requirer}: {e}" self.log.error(message) raise N2VCException(message=message) @@ -1047,7 +1028,7 @@ class N2VCJujuConnector(N2VCConnector): machine_id=machine_id, progress_timeout=progress_timeout, total_timeout=total_timeout, - **params_dict + **params_dict, ) if status == "completed": return output @@ -1153,21 +1134,13 @@ class N2VCJujuConnector(N2VCConnector): :return: model_name, application_name, machine_id """ - if ee_id is None: - return None, None, None - - # split components of id - parts = ee_id.split(".") - model_name = parts[0] - application_name = parts[1] - machine_id = parts[2] - return model_name, application_name, machine_id + return get_ee_id_components(ee_id) def _get_application_name(self, namespace: str) -> str: """ Build application name from namespace :param namespace: - :return: app-vnf--vdu--cnt- + :return: app-vnf--vdu--cnt-- """ # TODO: Enforce the Juju 50-character application limit @@ -1194,7 +1167,12 @@ class N2VCJujuConnector(N2VCConnector): else: vdu_count = "-cnt-" + vdu_count - application_name = "app-{}{}{}".format(vnf_id, vdu_id, vdu_count) + # Generate a random suffix with 5 characters (the default size used by K8s) + random_suffix = generate_random_alfanum_string(size=5) + + application_name = "app-{}{}{}-{}".format( + vnf_id, vdu_id, vdu_count, random_suffix + ) return N2VCJujuConnector._format_app_name(application_name)