From: garciadeblas Date: Mon, 25 Jan 2021 16:39:19 +0000 (+0000) Subject: New translation commands for SOL006: recursive package-translate, descriptor-translate X-Git-Tag: v9.0.0-dev~10 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=85fe6ebf08098c66cfb3b140fc994835f70d9efc;p=osm%2Fosmclient.git New translation commands for SOL006: recursive package-translate, descriptor-translate Change-Id: I4dd6e5b6eed7f8869ef7462b1ba9a9ff36944b5c Signed-off-by: garciadeblas --- diff --git a/osmclient/common/package_tool.py b/osmclient/common/package_tool.py index c858150..af1e426 100644 --- a/osmclient/common/package_tool.py +++ b/osmclient/common/package_tool.py @@ -26,6 +26,8 @@ import time from jinja2 import Environment, PackageLoader from osm_im.validation import Validation as validation_im +from osm_im.validation import ValidationException +from osm_im import im_translation from osmclient.common.exceptions import ClientException import yaml @@ -34,6 +36,7 @@ class PackageTool(object): def __init__(self, client=None): self._client = client self._logger = logging.getLogger('osmclient') + self._validator = validation_im() def create(self, package_type, base_directory, package_name, override, image, vdus, vcpu, memory, storage, interfaces, vendor, detailed, netslice_subnets, netslice_vlds): @@ -121,6 +124,69 @@ class PackageTool(object): table.append({"type": desc_type, "path": desc_path, "valid": "ERROR", "error": str(e)}) return table + def translate(self, base_directory, recursive=True, dryrun=False): + """ + **Translate OSM Packages given a path** + + :params: + - base_directory is the root path for all packages + + :return: List of dict of translated packages. keys: current type, new type, path, valid, translated, error + """ + self._logger.debug("") + table = [] + if recursive: + descriptors_paths = [f for f in glob.glob(base_directory + "/**/*.yaml", recursive=recursive)] + else: + descriptors_paths = [f for f in glob.glob(base_directory + "/*.yaml", recursive=recursive)] + print("Base directory: {}".format(base_directory)) + print("{} Descriptors found to validate".format(len(descriptors_paths))) + for desc_path in descriptors_paths: + with open(desc_path) as descriptor_file: + descriptor_data = descriptor_file.read() + desc_type = "-" + try: + desc_type, descriptor_data = validation_im.yaml_validation(self, descriptor_data) + self._logger.debug("desc_type: {}".format(desc_type)) + self._logger.debug("descriptor_data:\n{}".format(descriptor_data)) + self._validator.pyangbind_validation(desc_type, descriptor_data) + if not ( desc_type=="vnfd" or desc_type=="nsd" ): + table.append({"current type": desc_type, "new type": desc_type, "path": desc_path, "valid": "OK", "translated": "N/A", "error": "-"}) + else: + new_desc_type = desc_type + try: + sol006_model = yaml.safe_dump(im_translation.translate_im_model_to_sol006(descriptor_data), indent=4, default_flow_style=False) + new_desc_type, new_descriptor_data = self._validator.yaml_validation(sol006_model) + self._validator.pyangbind_validation(new_desc_type, new_descriptor_data) + if not dryrun: + with open(desc_path, 'w') as descriptor_file: + descriptor_file.write(sol006_model) + table.append({"current type": desc_type, "new type": new_desc_type, "path": desc_path, "valid": "OK", "translated": "OK", "error": "-"}) + except ValidationException as ve2: + table.append({"current type": desc_type, "new type": new_desc_type, "path": desc_path, "valid": "OK", "translated": "ERROR", "error": "Error in the post-validation: {}".format(str(ve2))}) + except Exception as e2: + table.append({"current type": desc_type, "new type": new_desc_type, "path": desc_path, "valid": "OK", "translated": "ERROR", "error": "Error in the translation: {}".format(str(e2))}) + except ValidationException as ve: + table.append({"current type": desc_type, "new type": "N/A", "path": desc_path, "valid": "ERROR", "translated": "N/A", "error": "Error in the pre-validation: {}".format(str(ve))}) + except Exception as e: + table.append({"current type": desc_type, "new type": "N/A", "path": desc_path, "valid": "ERROR", "translated": "N/A", "error": str(e)}) + return table + + def descriptor_translate(self, descriptor_file): + """ + **Translate input descriptor file from Rel EIGHT OSM to SOL006** + + :params: + - base_directory is the root path for all packages + + :return: YAML descriptor in the new format + """ + self._logger.debug("") + with open(descriptor_file, 'r') as df: + im_model = yaml.safe_load(df.read()) + sol006_model = im_translation.translate_im_model_to_sol006(im_model) + return yaml.safe_dump(sol006_model, indent=4, default_flow_style=False) + def build(self, package_folder, skip_validation=False, skip_charm_build=False): """ **Creates a .tar.gz file given a package_folder** @@ -294,7 +360,7 @@ class PackageTool(object): listCharms = self.charms_search(file, 'ns') print("List of charms in the descriptor: {}".format(listCharms)) if not descriptor_file: - raise ClientException('descriptor name is not correct in: {}'.format(package_folder)) + raise ClientException('Descriptor filename is not correct in: {}. It should end with "nfd.yaml" or "nsd.yaml"'.format(package_folder)) if listCharms and not skip_charm_build: for charmName in listCharms: if os.path.isdir('{}/charms/layers/{}'.format(package_folder, charmName)): diff --git a/osmclient/scripts/osm.py b/osmclient/scripts/osm.py index 3af70c6..d9136f3 100755 --- a/osmclient/scripts/osm.py +++ b/osmclient/scripts/osm.py @@ -4224,7 +4224,7 @@ def role_show(ctx, name): @cli_osm.command(name='package-create', - short_help='Create a package descriptor') + short_help='Create empty NS package structure') @click.argument('package-type') @click.argument('package-name') @click.option('--base-directory', @@ -4290,6 +4290,7 @@ def package_create(ctx, """ # try: + logger.debug("") check_client_version(ctx.obj, ctx.command.name) print("Creating the {} structure: {}/{}".format(package_type.upper(), base_directory, package_name)) resp = ctx.obj.package_tool.create(package_type, @@ -4312,7 +4313,7 @@ def package_create(ctx, # exit(1) @cli_osm.command(name='package-validate', - short_help='Validate a package descriptor') + short_help='Validate descriptors given a base directory') @click.argument('base-directory', default=".", required=False) @@ -4333,9 +4334,10 @@ def package_validate(ctx, Validate descriptors given a base directory. \b - BASE_DIRECTORY: Stub folder for NS, VNF or NST package. + BASE_DIRECTORY: Base folder for NS, VNF or NST package. """ # try: + logger.debug("") check_client_version(ctx.obj, ctx.command.name) results = ctx.obj.package_tool.validate(base_directory, recursive, old) table = PrettyTable() @@ -4352,6 +4354,47 @@ def package_validate(ctx, # print("ERROR: {}".format(inst)) # exit(1) +@cli_osm.command(name='package-translate', + short_help='Translate descriptors given a base directory') +@click.argument('base-directory', + default=".", + required=False) +@click.option('--recursive/--no-recursive', + default=True, + help='The activated recursive option will translate the yaml files' + ' within the indicated directory and in its subdirectories') +@click.option('--dryrun', + is_flag=True, + default=False, + help='Do not translate yet, only make a dry-run to test translation') +@click.pass_context +def package_translate(ctx, + base_directory, + recursive, + dryrun): + """ + Translate descriptors given a base directory. + + \b + BASE_DIRECTORY: Stub folder for NS, VNF or NST package. + """ + logger.debug("") + check_client_version(ctx.obj, ctx.command.name) + results = ctx.obj.package_tool.translate(base_directory, recursive, dryrun) + table = PrettyTable() + table.field_names = ["CURRENT TYPE", "NEW TYPE", "PATH", "VALID", "TRANSLATED", "ERROR"] + # Print the dictionary generated by the validation function + for result in results: + table.add_row([result["current type"], result["new type"], result["path"], result["valid"], result["translated"], result["error"]]) + table.sortby = "TRANSLATED" + table.align["PATH"] = "l" + table.align["TYPE"] = "l" + table.align["ERROR"] = "l" + print(table) + # except ClientException as inst: + # print("ERROR: {}".format(inst)) + # exit(1) + @cli_osm.command(name='package-build', short_help='Build the tar.gz of the package') @click.argument('package-folder') @@ -4373,6 +4416,7 @@ def package_build(ctx, PACKAGE_FOLDER: Folder of the NS, VNF or NST to be packaged """ # try: + logger.debug("") check_client_version(ctx.obj, ctx.command.name) results = ctx.obj.package_tool.build(package_folder, skip_validation=skip_validation, @@ -4382,6 +4426,24 @@ def package_build(ctx, # print("ERROR: {}".format(inst)) # exit(1) +@cli_osm.command(name='descriptor-translate', + short_help='Translate input descriptor file from Rel EIGHT OSM descriptors to SOL006 and prints in standard output') +@click.argument('descriptor-file', + required=True) +@click.pass_context +def descriptor_translate(ctx, + descriptor_file): + """ + Translate input descriptor. + + \b + DESCRIPTOR_FILE: Descriptor file for NS, VNF or Network Slice. + """ + logger.debug("") + check_client_version(ctx.obj, ctx.command.name) + result = ctx.obj.package_tool.descriptor_translate(descriptor_file) + print(result) + def cli(): try: