From: tierno Date: Fri, 17 Nov 2017 14:21:36 +0000 (+0100) Subject: New tool to upgrade vnf,ns descriptors to R. THREE X-Git-Tag: v3.0.2~6 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fchanges%2F98%2F5698%2F3;p=osm%2Fdevops.git New tool to upgrade vnf,ns descriptors to R. THREE Change-Id: I7c47d8bd891ad54fed4c2a92ba400962fe40add9 Signed-off-by: tierno --- diff --git a/descriptor-packages/tools/upgrade_descriptor_version.py b/descriptor-packages/tools/upgrade_descriptor_version.py new file mode 100755 index 00000000..4259ece6 --- /dev/null +++ b/descriptor-packages/tools/upgrade_descriptor_version.py @@ -0,0 +1,214 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +## +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +## + +import json +import yaml +# import logging +import sys +import getopt + + +""" +Converts OSM VNFD, NSD descriptor from release TWO to release THREE format +""" +__author__ = "Alfonso Tierno" +__date__ = "2017-10-14" +__version__ = "0.0.1" +version_date = "Nov 2017" + + +class ArgumentParserError(Exception): + pass + + +def usage(): + print("Usage: {} [options] FILE".format(sys.argv[0])) + print(" EXPERIMENTAL: Upgrade vnfd, nsd descriptor from old versions to release THREE version") + print(" FILE: a yaml or json vnfd-catalog or nsd-catalog descriptor") + print(" OPTIONS:") + print(" -v|--version: prints current version") + print(" -h|--help: shows this help") + print(" -i|--input FILE: (same as param FILE) descriptor file to be upgraded") + print(" -o|--output FILE: where to write generated descriptor. By default stdout") + # print(" --test: Content is tested to check wrong format or unknown keys") + return + + +def remove_prefix(desc, prefix): + """ + Recursively removes prefix from keys + :param desc: dictionary or list to change + :param prefix: prefix to remove. Must + :return: None, param desc is changed + """ + prefix_len = len(prefix) + if isinstance(desc, dict): + prefixed_list=[] + for k,v in desc.items(): + if isinstance(v, (list, tuple, dict)): + remove_prefix(v, prefix) + if isinstance(k, str) and k.startswith(prefix) and k != prefix: + prefixed_list.append(k) + for k in prefixed_list: + desc[k[prefix_len:]] = desc.pop(k) + elif isinstance(desc, (list, tuple)): + for i in desc: + if isinstance(desc, (list, tuple, dict)): + remove_prefix(i, prefix) + + +if __name__=="__main__": + error_position = [] + format_output_yaml = True + input_file_name = None + output_file_name = None + test_file = None + try: + # load parameters and configuration + opts, args = getopt.getopt(sys.argv[1:], "hvi:o:", ["input=", "help", "version", "output=", "test",]) + + for o, a in opts: + if o in ("-v", "--version"): + print ("upgrade descriptor version " + __version__ + ' ' + version_date) + sys.exit() + elif o in ("-h", "--help"): + usage() + sys.exit() + elif o in ("-i", "--input"): + input_file_name = a + elif o in ("-o", "--output"): + output_file_name = a + elif o == "--test": + test_file = True + else: + assert False, "Unhandled option" + if not input_file_name: + if not args: + raise ArgumentParserError("missing DESCRIPTOR_FILE parameter. Type --help for more info") + input_file_name = args[0] + + # Open files + file_name = input_file_name + with open(file_name, 'r') as f: + descriptor_str = f.read() + if output_file_name: + file_name = output_file_name + output = open(file_name, 'w') + else: + output = sys.stdout + + if input_file_name.endswith('.yaml') or input_file_name.endswith('.yml') or not \ + (input_file_name.endswith('.json') or '\t' in descriptor_str): + data = yaml.load(descriptor_str) + else: # json + data = json.loads(descriptor_str) + format_output_yaml = False + + # Convert version + if "vnfd:vnfd-catalog" in data or "vnfd-catalog" in data: + remove_prefix(data, "vnfd:") + error_position.append("vnfd-catalog") + vnfd_descriptor = data["vnfd-catalog"] + + vnfd_list = vnfd_descriptor["vnfd"] + error_position.append("vnfd") + for vnfd in vnfd_list: + error_position[-1] = "vnfd[{}]".format(vnfd["id"]) + + # Remove vnf-configuration:config-attributes + if "vnf-configuration" in vnfd and "config-attributes" in vnfd["vnf-configuration"]: + del vnfd["vnf-configuration"]["config-attributes"] + + # Iterate with vdu:interfaces + vdu_list = vnfd["vdu"] + error_position.append("vdu") + for vdu in vdu_list: + error_position[-1] = "vdu[{}]".format(vdu["id"]) + + # Change exernal/internal interface + interface_list = [] + external_interface_list = vdu.pop("external-interface", ()) + error_position.append("external-interface") + for external_interface in external_interface_list: + error_position[-1] = "external-interface[{}]".format(external_interface["name"]) + external_interface["type"] = "EXTERNAL" + external_interface["external-connection-point-ref"] = \ + external_interface.pop("vnfd-connection-point-ref") + interface_list.append(external_interface) + error_position.pop() + + internal_interface_list = vdu.pop("internal-interface", ()) + error_position.append("internal-interface") + for internal_interface in internal_interface_list: + error_position[-1] = "internal-interface[{}]".format(internal_interface["name"]) + internal_interface["type"] = "INTERNAL" + internal_interface["internal-connection-point-ref"] = \ + internal_interface.pop("vdu-internal-connection-point-ref") + interface_list.append(internal_interface) + error_position.pop() + + if interface_list: + vdu["interface"] = interface_list + error_position.pop() + error_position = [] + elif "nsd:nsd-catalog" in data or "nsd-catalog" in data: + remove_prefix(data, "nsd:") + error_position.append("nsd-catalog") + nsd_descriptor = data["nsd-catalog"] + + nsd_list = nsd_descriptor["nsd"] + error_position.append("nsd") + for nsd in nsd_list: + error_position[-1] = "nsd[{}]".format(nsd["id"]) + + # Change initial-config-primitive into initial-service-primitive + if "initial-config-primitive" in nsd: + nsd['initial-service-primitive'] = nsd.pop("initial-config-primitive") + error_position = [] + else: + error_position = ["global"] + raise KeyError("This is not neither nsd-catalog nor vnfd-catalog descriptor") + + if format_output_yaml: + yaml.dump(data, output, indent=4, default_flow_style=False) + else: + json.dump(data, output) + + except yaml.YAMLError as exc: + error_pos = "" + if hasattr(exc, 'problem_mark'): + mark = exc.problem_mark + error_pos = "at line:%s column:%s" % (mark.line + 1, mark.column + 1) + print("Error loading file '{}'. yaml format error {}".format(input_file_name, error_pos), file=sys.stderr) + + except json.decoder.JSONDecodeError as e: + print("Invalid field at configuration file '{file}' {message}".format(file=input_file_name, message=str(e)), + file=sys.stderr) + except ArgumentParserError as e: + print(str(e), file=sys.stderr) + except IOError as e: + print("Error loading file '{}': {}".format(file_name, e), file=sys.stderr) + except Exception as e: + if error_position: + print("Descriptor error at '{}': {}".format(":".join(error_position), e), file=sys.stderr) + else: + raise + # print("Unexpected exception {}".format(e), file=sys.stderr) + exit(1)