X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2Fosmclient.git;a=blobdiff_plain;f=osmclient%2Fcommon%2Fpackage_tool.py;h=e792ce9e9e0ebc43c77378d784428e04bdc810eb;hp=568880c0fd3defb3f36f746808098545850931a7;hb=1931b2032c07d1ed3897739d0b40485d4411db1d;hpb=3c1603818230f52cf5102fdfbdd8fd8907062e8d diff --git a/osmclient/common/package_tool.py b/osmclient/common/package_tool.py index 568880c..e792ce9 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): @@ -86,7 +89,7 @@ class PackageTool(object): self.create_files(structure["files"], output, package_type) return "Created" - def validate(self, base_directory, recursive=True): + def validate(self, base_directory, recursive=True, old_format=False): """ **Validate OSM Descriptors given a path** @@ -109,12 +112,81 @@ class PackageTool(object): desc_type = "-" try: desc_type, descriptor_data = validation_im.yaml_validation(self, descriptor_data) + if not old_format: + if ( desc_type=="vnfd" or desc_type=="nsd" ): + print("OSM descriptor '{}' written in an unsupported format. Please update to ETSI SOL006 format".format(desc_path)) + print("Package validation skipped. It can still be done with 'osm package-validate --old'") + print("Package build can still be done with 'osm package-build --skip-validation'") + raise Exception("Not SOL006 format") validation_im.pyangbind_validation(self, desc_type, descriptor_data) table.append({"type": desc_type, "path": desc_path, "valid": "OK", "error": "-"}) except Exception as e: 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** @@ -217,6 +289,7 @@ class PackageTool(object): :returns: cloud-init content """ + self._logger.debug("") return "---\n#cloud-config" def create_files(self, files, file_content, package_type): @@ -287,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)): @@ -441,14 +514,23 @@ class PackageTool(object): return directory_name, package_name def charms_search(self, descriptor_file, desc_type): - self._logger.debug("") + self._logger.debug("descriptor_file: {}, desc_type: {}".format(descriptor_file, + desc_type)) with open("{}".format(descriptor_file)) as yaml_desc: descriptor_dict = yaml.safe_load(yaml_desc) - if "catalog" in descriptor_dict: # Match OSM-IM vnfd-catalog and nsd-catalog - charms_list = self._charms_search_on_sol006_dict(descriptor_dict, desc_type) - else: - charms_list = self._charms_search_on_osm_im_dict(descriptor_dict, desc_type) + #self._logger.debug("\n"+yaml.safe_dump(descriptor_dict, indent=4, default_flow_style=False)) + if ( (desc_type=="vnf" and ("vnfd:vnfd-catalog" in descriptor_dict or "vnfd-catalog" in descriptor_dict)) or + (desc_type=="ns" and ( "nsd:nsd-catalog" in descriptor_dict or "nsd-catalog" in descriptor_dict)) ): + charms_list = self._charms_search_on_osm_im_dict(descriptor_dict, desc_type) + else: + if desc_type == "ns": + get_charm_list = self._charms_search_on_nsd_sol006_dict + elif desc_type == "vnf": + get_charm_list = self._charms_search_on_vnfd_sol006_dict + else: + raise Exception("Bad descriptor type") + charms_list = get_charm_list(descriptor_dict) return charms_list def _charms_search_on_osm_im_dict(self, osm_im_dict, desc_type): @@ -471,19 +553,28 @@ class PackageTool(object): charms_list.append((v4['charm'])) return charms_list - def _charms_search_on_sol006_dict(self, sol006_dict, desc_type): + def _charms_search_on_vnfd_sol006_dict(self, sol006_dict): self._logger.debug("") charms_list = [] for k1, v1 in sol006_dict.items(): for k2, v2 in v1.items(): - if '{}-configuration'.format(desc_type) in k2: - for vnf_config in v2: - for k3, v3 in vnf_config.items(): - if 'charm' in v3: - charms_list.append((v3['charm'])) - if 'vdu-configuration' in k2: - for vdu_config in v2: - for k3, v3 in vdu_config.items(): - if 'charm' in v3: - charms_list.append((v3['charm'])) + if k2 == "df": + for df in v2: + lcm_ops = df.get("lcm-operations-configuration", {}) + ops_config = lcm_ops.get("operate-vnf-op-config", {}) + for day_12_config in ops_config.get("day1-2", []): + self._logger.debug("Execution environment found") + for ee in day_12_config.get("execution-environment-list", []): + if "juju" in ee: + charms_list.append((ee["juju"]['charm'])) + return charms_list + + def _charms_search_on_nsd_sol006_dict(self, sol006_dict): + self._logger.debug("") + charms_list = [] + nsd_list = sol006_dict.get("nsd", {}).get("nsd", []) + for nsd in nsd_list: + charm = nsd.get("ns-configuration", {}).get("juju", {}).get("charm") + if charm: + charms_list.append(charm) return charms_list