Merge from OSM SO master
[osm/SO.git] / rwlaunchpad / plugins / rwlaunchpadtasklet / rift / package / convert.py
index 7571c57..e10d7ca 100644 (file)
@@ -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.
 #
 
 import json
+import logging
 import os
-import tempfile
 
 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
+
 
 class UnknownExtensionError(Exception):
     pass
@@ -51,10 +59,15 @@ class ProtoMessageSerializer(object):
     """(De)Serializer/deserializer fo a specific protobuf message into various formats"""
     libncx_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,6 +113,16 @@ 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__
@@ -108,6 +131,7 @@ class ProtoMessageSerializer(object):
         if cls.libncx_model is None:
             cls.libncx_model = RwYang.model_create_libncx()
             cls.libncx_model.load_schema_ypbc(self.yang_namespace.get_schema())
+            cls.libncx_model.load_schema_ypbc(self.yang_ns_project.get_schema())
 
         return cls.libncx_model
 
@@ -117,20 +141,54 @@ class ProtoMessageSerializer(object):
         return self.yang_class.from_xml_v2(self.model, decode(xml), strict=False)
 
     def _from_json_file_hdl(self, file_hdl):
-        json = file_hdl.read()
+        jstr = file_hdl.read()
+        self._log.debug("Convert from json file: {}".format(jstr))
 
-        return self.yang_class.from_json(self.model, decode(json), strict=False)
+        try:
+            desc_msg = self.yang_class.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):
-        yaml = file_hdl.read()
+        yml = file_hdl.read()
+
+        try:
+            desc_msg = self.yang_class.from_yaml(self.model, decode(yml), strict=False)
+            return self.yang_class_project.from_dict(desc_msg.as_dict())
+        except Exception as e:
+            self._log.exception(e)
+            raise e
+
+    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
+
+        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
 
-        return self.yang_class.from_yaml(self.model, decode(yaml), strict=False)
+        raise TypeError("Invalid protobuf message type provided: {}".format(type(pb_msg)))
 
-    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,16 +197,24 @@ 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):
         """ Serialize a protobuf message into YAML
@@ -163,13 +229,12 @@ 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:
-            yaml_str = pb_msg.to_yaml(self.model)
+            desc_msg = self.to_desc_msg(pb_msg)
+            yaml_str = desc_msg.to_yaml(self.model)
 
         except Exception as e:
+            self._log.exception("Exception converting to yaml: {}".format(e))
             raise SerializationError(e)
 
         return yaml_str
@@ -187,13 +252,12 @@ 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
@@ -262,22 +326,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)