X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FN2VC.git;a=blobdiff_plain;f=n2vc%2Fn2vc_conn.py;h=68e8c14834da5ed8c5761ff1141a3c148abe6dae;hp=12704a3f35c622888fd5606126f137ac1343321a;hb=HEAD;hpb=6331b04745fcd6d44b1b0320ca6e3e63cdebd0e8 diff --git a/n2vc/n2vc_conn.py b/n2vc/n2vc_conn.py index 12704a3..01d7df8 100644 --- a/n2vc/n2vc_conn.py +++ b/n2vc/n2vc_conn.py @@ -24,6 +24,7 @@ import abc import asyncio from http import HTTPStatus +from shlex import quote import os import shlex import subprocess @@ -54,10 +55,6 @@ class N2VCConnector(abc.ABC, Loggable): db: object, fs: object, log: object, - loop: object, - url: str, - username: str, - vca_config: dict, on_update_db=None, **kwargs, ): @@ -67,15 +64,6 @@ class N2VCConnector(abc.ABC, Loggable): :param object fs: FileSystem object managing the package artifacts (repo common FsBase) :param object log: the logging object to log to - :param object loop: the loop to use for asyncio (default current thread loop) - :param str url: a string that how to connect to the VCA (if needed, IP and port - can be obtained from there) - :param str username: the username to authenticate with VCA - :param dict vca_config: Additional parameters for the specific VCA. For example, - for juju it will contain: - secret: The password to authenticate with - public_key: The contents of the juju public SSH key - ca_cert str: The CA certificate used to authenticate :param on_update_db: callback called when n2vc connector updates database. Received arguments: table: e.g. "nsrs" @@ -93,26 +81,9 @@ class N2VCConnector(abc.ABC, Loggable): if fs is None: raise N2VCBadArgumentsException("Argument fs is mandatory", ["fs"]) - self.log.info( - "url={}, username={}, vca_config={}".format( - url, - username, - { - k: v - for k, v in vca_config.items() - if k - not in ("host", "port", "user", "secret", "public_key", "ca_cert") - }, - ) - ) - # store arguments into self self.db = db self.fs = fs - self.loop = loop or asyncio.get_event_loop() - self.url = url - self.username = username - self.vca_config = vca_config self.on_update_db = on_update_db # generate private/public key-pair @@ -145,19 +116,27 @@ class N2VCConnector(abc.ABC, Loggable): self.log.warning("No HOME environment variable, using /tmp") homedir = "/tmp" sshdir = "{}/.ssh".format(homedir) + sshdir = os.path.realpath(os.path.normpath(os.path.abspath(sshdir))) if not os.path.exists(sshdir): os.mkdir(sshdir) self.private_key_path = "{}/id_n2vc_rsa".format(sshdir) + self.private_key_path = os.path.realpath( + os.path.normpath(os.path.abspath(self.private_key_path)) + ) self.public_key_path = "{}.pub".format(self.private_key_path) + self.public_key_path = os.path.realpath( + os.path.normpath(os.path.abspath(self.public_key_path)) + ) # If we don't have a key generated, then we have to generate it using ssh-keygen if not os.path.exists(self.private_key_path): - cmd = "ssh-keygen -t {} -b {} -N '' -f {}".format( - "rsa", "4096", self.private_key_path + command = "ssh-keygen -t {} -b {} -N '' -f {}".format( + "rsa", "4096", quote(self.private_key_path) ) # run command with arguments - subprocess.check_output(shlex.split(cmd)) + args = shlex.split(command) + subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # Read the public key. Only one public key (one line) in the file with open(self.public_key_path, "r") as file: @@ -173,7 +152,7 @@ class N2VCConnector(abc.ABC, Loggable): reuse_ee_id: str = None, progress_timeout: float = None, total_timeout: float = None, - ) -> (str, dict): + ) -> tuple[str, dict]: """Create an Execution Environment. Returns when it is created or raises an exception on failing @@ -321,14 +300,12 @@ class N2VCConnector(abc.ABC, Loggable): # TODO @abc.abstractmethod async def remove_relation(self): - """ - """ + """ """ # TODO @abc.abstractmethod async def deregister_execution_environments(self): - """ - """ + """ """ @abc.abstractmethod async def delete_namespace( @@ -360,6 +337,28 @@ class N2VCConnector(abc.ABC, Loggable): :param float total_timeout: """ + @abc.abstractmethod + async def upgrade_charm( + self, + ee_id: str = None, + path: str = None, + charm_id: str = None, + charm_type: str = None, + timeout: float = None, + ) -> str: + """This method upgrade charms in VNFs + + Args: + ee_id: Execution environment id + path: Local path to the charm + charm_id: charm-id + charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm + timeout: (Float) Timeout for the ns update operation + + Returns: + The output of the update operation if status equals to "completed" + """ + @abc.abstractmethod async def exec_primitive( self, @@ -400,7 +399,9 @@ class N2VCConnector(abc.ABC, Loggable): #################################################################################### """ - def _get_namespace_components(self, namespace: str) -> (str, str, str, str, str): + def _get_namespace_components( + self, namespace: str + ) -> tuple[str, str, str, str, str]: """ Split namespace components @@ -443,7 +444,18 @@ class N2VCConnector(abc.ABC, Loggable): detailed_status: str, vca_status: str, entity_type: str, + vca_id: str = None, ): + """ + Write application status to database + + :param: db_dict: DB dictionary + :param: status: Status of the application + :param: detailed_status: Detailed status + :param: vca_status: VCA status + :param: entity_type: Entity type ("application", "machine, and "action") + :param: vca_id: Id of the VCA. If None, the default VCA will be used. + """ if not db_dict: self.log.debug("No db_dict => No database write") return @@ -452,7 +464,6 @@ class N2VCConnector(abc.ABC, Loggable): # .format(str(status.value), detailed_status, vca_status, entity_type)) try: - the_table = db_dict["collection"] the_filter = db_dict["filter"] the_path = db_dict["path"] @@ -477,10 +488,12 @@ class N2VCConnector(abc.ABC, Loggable): if self.on_update_db: if asyncio.iscoroutinefunction(self.on_update_db): await self.on_update_db( - the_table, the_filter, the_path, update_dict + the_table, the_filter, the_path, update_dict, vca_id=vca_id ) else: - self.on_update_db(the_table, the_filter, the_path, update_dict) + self.on_update_db( + the_table, the_filter, the_path, update_dict, vca_id=vca_id + ) except DbException as e: if e.http_code == HTTPStatus.NOT_FOUND: @@ -518,4 +531,4 @@ def obj_to_dict(obj: object) -> dict: # convert obj to yaml yaml_text = obj_to_yaml(obj) # parse to dict - return yaml.load(yaml_text, Loader=yaml.Loader) + return yaml.load(yaml_text, Loader=yaml.SafeLoader)