X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=rwlaunchpad%2Fplugins%2Frwlaunchpadtasklet%2Frift%2Fpackage%2Fconvert.py;h=143b3e226accfcd96bee66ef4487d3462224d62a;hb=f314b4af9744068a7ed7a6a6314220c3aa857523;hp=7571c570e9000772942f02de265381e17b18b7f2;hpb=6f1a3fe149e4a6b9803382cb299c902f4cf58ec9;p=osm%2FSO.git diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/convert.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/convert.py index 7571c570..143b3e22 100644 --- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/convert.py +++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/package/convert.py @@ -1,6 +1,6 @@ -# -# Copyright 2016 RIFT.IO Inc +# +# Copyright 2016-2017 RIFT.IO Inc # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,21 +16,30 @@ # import json +import logging import os -import tempfile +import yaml import gi gi.require_version('RwNsdYang', '1.0') +gi.require_version('RwProjectNsdYang', '1.0') gi.require_version('RwVnfdYang', '1.0') +gi.require_version('RwProjectVnfdYang', '1.0') gi.require_version('RwYang', '1.0') from gi.repository import ( RwNsdYang, RwVnfdYang, NsdYang, VnfdYang, + RwProjectNsdYang, + RwProjectVnfdYang, + ProjectNsdYang, + ProjectVnfdYang, RwYang, ) +from rift.mano.utils.project import NS_PROJECT +from rift.rwlib.translation.json2xml import InvalidSchemaException class UnknownExtensionError(Exception): pass @@ -49,12 +58,17 @@ def decode(desc_data): class ProtoMessageSerializer(object): """(De)Serializer/deserializer fo a specific protobuf message into various formats""" - libncx_model = None + libyang_model = None - def __init__(self, yang_ns, yang_pb_cls): + def __init__(self, yang_ns, yang_pb_cls, + yang_ns_project, yang_pb_project_cls): """ Create a serializer for a specific protobuf message """ self._yang_ns = yang_ns self._yang_pb_cls = yang_pb_cls + self._yang_ns_project = yang_ns_project + self._yang_pb_project_cls = yang_pb_project_cls + + self._log = logging.getLogger('rw-maon-log') @classmethod def _deserialize_extension_method_map(cls): @@ -100,37 +114,92 @@ class ProtoMessageSerializer(object): """ The Protobuf's GI class (e.g. RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd) """ return self._yang_pb_cls + @property + def yang_ns_project(self): + """ The Protobuf's GI namespace class (e.g. RwProjectVnfdYang) """ + return self._yang_ns_project + + @property + def yang_class_project(self): + """ The Protobuf's GI class (e.g. RwProjectVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd) """ + return self._yang_pb_project_cls + @property def model(self): cls = self.__class__ - # Cache the libncx model for the serializer class - if cls.libncx_model is None: - cls.libncx_model = RwYang.model_create_libncx() - cls.libncx_model.load_schema_ypbc(self.yang_namespace.get_schema()) + # Cache the libyang model for the serializer class + if cls.libyang_model is None: + cls.libyang_model = RwYang.model_create_libyang() + cls.libyang_model.load_schema_ypbc(self.yang_namespace.get_schema()) + cls.libyang_model.load_schema_ypbc(self.yang_ns_project.get_schema()) - return cls.libncx_model + return cls.libyang_model - def _from_xml_file_hdl(self, file_hdl): + def _from_xml_file_hdl(self, file_hdl, project=None): xml = file_hdl.read() - return self.yang_class.from_xml_v2(self.model, decode(xml), strict=False) + return self.yang_class.from_xml_v2(self.model, decode(xml), strict=False) \ + if not project else self._yang_pb_project_cls.from_xml_v2(self.model, decode(xml), strict=False) + + def _from_json_file_hdl(self, file_hdl, project=None): + jstr = file_hdl.read() + self._log.debug("Convert from json file: {}".format(jstr)) + + try: + if not project: + desc_msg = self.yang_class.from_json(self.model, decode(jstr), strict=False) + else: + desc_msg = self._yang_pb_project_cls.from_json(self.model, decode(jstr), strict=False) + + self._log.debug("desc_msg: {}".format(desc_msg.as_dict())) + return self.yang_class_project.from_dict(desc_msg.as_dict()) + except Exception as e: + self._log.exception(e) + raise e + + def _from_yaml_file_hdl(self, file_hdl, project=None): + yml = file_hdl.read() + + try: + desc_msg = self.yang_class.from_yaml(self.model, decode(yml), strict=True) + except InvalidSchemaException as invalid_scheme_exception: + self._log.error("Exception raised during schema translation, %s. Launchpad will" \ + "continue to process the remaining elements ", str(invalid_scheme_exception)) + desc_msg = self.yang_class.from_yaml(self.model, decode(yml), strict=False) + except Exception as e: + self._log.exception(e) + raise e + + return self.yang_class_project.from_dict(desc_msg.as_dict()) - def _from_json_file_hdl(self, file_hdl): - json = file_hdl.read() + def to_desc_msg(self, pb_msg, project_rooted=True): + """Convert to and from project rooted pb msg descriptor to catalog + rooted pb msg + project_rooted: if pb_msg is project rooted or not + """ + if project_rooted: + if isinstance(pb_msg, self._yang_pb_project_cls): + return self._yang_pb_cls.from_dict(pb_msg.as_dict()) + elif isinstance(pb_msg, self._yang_pb_cls): + return pb_msg - return self.yang_class.from_json(self.model, decode(json), strict=False) + else: + if isinstance(pb_msg, self._yang_pb_cls): + return self._yang_pb_project_cls.from_dict(pb_msg.as_dict()) + elif isinstance(pb_msg, self._yang_pb_project_cls): + return pb_msg - def _from_yaml_file_hdl(self, file_hdl): - yaml = file_hdl.read() + raise TypeError("Invalid protobuf message type provided: {}".format(type(pb_msg))) - return self.yang_class.from_yaml(self.model, decode(yaml), strict=False) - def to_json_string(self, pb_msg): + def to_json_string(self, pb_msg, project_ns=False): """ Serialize a protobuf message into JSON Arguments: pb_msg - A GI-protobuf object of type provided into constructor + project_ns - Need the desc in project namespace, required for + posting to Restconf as part of onboarding Returns: A JSON string representing the protobuf message @@ -139,22 +208,32 @@ class ProtoMessageSerializer(object): SerializationError - Message could not be serialized TypeError - Incorrect protobuf type provided """ - if not isinstance(pb_msg, self._yang_pb_cls): - raise TypeError("Invalid protobuf message type provided") - + self._log.debug("Convert desc to json (ns:{}): {}".format(project_ns, pb_msg.as_dict())) try: - json_str = pb_msg.to_json(self.model) + # json_str = pb_msg.to_json(self.model) + + desc_msg = self.to_desc_msg(pb_msg, not project_ns) + json_str = desc_msg.to_json(self.model) + if project_ns: + # Remove rw-project:project top level element + dic = json.loads(json_str) + jstr = json.dumps(dic[NS_PROJECT][0]) + else: + jstr = json_str except Exception as e: raise SerializationError(e) - return json_str + self._log.debug("Convert desc to json: {}".format(jstr)) + return jstr - def to_yaml_string(self, pb_msg): + def to_yaml_string(self, pb_msg, project_ns=False): """ Serialize a protobuf message into YAML Arguments: pb_msg - A GI-protobuf object of type provided into constructor + project_ns - Need the desc in project namespace, required for + posting to Restconf as part of onboarding Returns: A YAML string representing the protobuf message @@ -163,16 +242,23 @@ class ProtoMessageSerializer(object): SerializationError - Message could not be serialized TypeError - Incorrect protobuf type provided """ - if not isinstance(pb_msg, self._yang_pb_cls): - raise TypeError("Invalid protobuf message type provided") - + self._log.debug("Convert desc to yaml (ns:{}): {}".format(project_ns, pb_msg.as_dict())) try: - yaml_str = pb_msg.to_yaml(self.model) + desc_msg = self.to_desc_msg(pb_msg, not project_ns) + yaml_str = desc_msg.to_yaml(self.model) + if project_ns: + # Remove rw-project:project top level element + dic = yaml.loads(yaml_str) + ystr = yaml.dump(dic[NS_PROJECT][0]) + else: + ystr = yaml_str + except Exception as e: + self._log.exception("Exception converting to yaml: {}".format(e)) raise SerializationError(e) - return yaml_str + return ystr def to_xml_string(self, pb_msg): """ Serialize a protobuf message into XML @@ -187,18 +273,17 @@ class ProtoMessageSerializer(object): SerializationError - Message could not be serialized TypeError - Incorrect protobuf type provided """ - if not isinstance(pb_msg, self._yang_pb_cls): - raise TypeError("Invalid protobuf message type provided") - try: - xml_str = pb_msg.to_xml_v2(self.model) + desc_msg = self.to_desc_msg(pb_msg) + xml_str = desc_msg.to_xml_v2(self.model) except Exception as e: + self._log.exception("Exception converting to xml: {}".format(e)) raise SerializationError(e) return xml_str - def from_file_hdl(self, file_hdl, extension): + def from_file_hdl(self, file_hdl, extension, project=None): """ Returns the deserialized protobuf message from file contents This function determines the serialization format based on file extension @@ -222,7 +307,8 @@ class ProtoMessageSerializer(object): raise UnknownExtensionError("Cannot detect message format for %s extension" % extension_lc) try: - msg = extension_map[extension_lc](self, file_hdl) + self._log.debug("Converting from json..project = {}".format(project)) + msg = extension_map[extension_lc](self, file_hdl, project) except Exception as e: raise SerializationError(e) @@ -262,22 +348,26 @@ class ProtoMessageSerializer(object): class VnfdSerializer(ProtoMessageSerializer): """ Creates a serializer for the VNFD descriptor""" def __init__(self): - super().__init__(VnfdYang, VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd) + super().__init__(VnfdYang, VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd, + ProjectVnfdYang, ProjectVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd) class NsdSerializer(ProtoMessageSerializer): """ Creates a serializer for the NSD descriptor""" def __init__(self): - super().__init__(NsdYang, NsdYang.YangData_Nsd_NsdCatalog_Nsd) + super().__init__(NsdYang, NsdYang.YangData_Nsd_NsdCatalog_Nsd, + ProjectNsdYang, ProjectNsdYang.YangData_RwProject_Project_NsdCatalog_Nsd) class RwVnfdSerializer(ProtoMessageSerializer): """ Creates a serializer for the VNFD descriptor""" def __init__(self): - super().__init__(RwVnfdYang, RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd) + super().__init__(RwVnfdYang, RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd, + RwProjectVnfdYang, RwProjectVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd) class RwNsdSerializer(ProtoMessageSerializer): """ Creates a serializer for the NSD descriptor""" def __init__(self): - super().__init__(RwNsdYang, RwNsdYang.YangData_Nsd_NsdCatalog_Nsd) + super().__init__(RwNsdYang, RwNsdYang.YangData_Nsd_NsdCatalog_Nsd, + RwProjectNsdYang, RwProjectNsdYang.YangData_RwProject_Project_NsdCatalog_Nsd)