3 # Copyright 2016 RIFT.IO Inc
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
25 gi
.require_version('RwNsdYang', '1.0')
26 gi
.require_version('RwVnfdYang', '1.0')
27 gi
.require_version('RwYang', '1.0')
28 from gi
.repository
import (
36 from rift
.mano
.utils
.project
import NS_PROJECT
39 class UnknownExtensionError(Exception):
43 class SerializationError(Exception):
47 def decode(desc_data
):
48 if isinstance(desc_data
, bytes
):
49 desc_data
= desc_data
.decode()
54 class ProtoMessageSerializer(object):
55 """(De)Serializer/deserializer fo a specific protobuf message into various formats"""
58 def __init__(self
, yang_ns
, yang_pb_cls
):
59 """ Create a serializer for a specific protobuf message """
60 self
._yang
_ns
= yang_ns
61 self
._yang
_pb
_cls
= yang_pb_cls
64 def _deserialize_extension_method_map(cls
):
66 ".xml": cls
._from
_xml
_file
_hdl
,
67 ".yml": cls
._from
_yaml
_file
_hdl
,
68 ".yaml": cls
._from
_yaml
_file
_hdl
,
69 ".json": cls
._from
_json
_file
_hdl
,
73 def _serialize_extension_method_map(cls
):
75 ".xml": cls
.to_xml_string
,
76 ".yml": cls
.to_yaml_string
,
77 ".yaml": cls
.to_yaml_string
,
78 ".json": cls
.to_json_string
,
82 def is_supported_file(cls
, filename
):
83 """Returns whether a file has a supported file extension
86 filename - A descriptor file
89 True if file extension is supported, False otherwise
92 _
, extension
= os
.path
.splitext(filename
)
93 extension_lc
= extension
.lower()
95 return extension_lc
in cls
._deserialize
_extension
_method
_map
()
98 def yang_namespace(self
):
99 """ The Protobuf's GI namespace class (e.g. RwVnfdYang) """
103 def yang_class(self
):
104 """ The Protobuf's GI class (e.g. RwVnfdYang.YangData_RwProject_Project_VnfdCatalog_Vnfd) """
105 return self
._yang
_pb
_cls
111 # Cache the libncx model for the serializer class
112 if cls
.libncx_model
is None:
113 cls
.libncx_model
= RwYang
.model_create_libncx()
114 cls
.libncx_model
.load_schema_ypbc(self
.yang_namespace
.get_schema())
116 return cls
.libncx_model
118 def _from_xml_file_hdl(self
, file_hdl
):
119 xml
= file_hdl
.read()
121 return self
.yang_class
.from_xml_v2(self
.model
, decode(xml
), strict
=False)
123 def _from_json_file_hdl(self
, file_hdl
):
124 json
= file_hdl
.read()
126 return self
.yang_class
.from_json(self
.model
, decode(json
), strict
=False)
128 def _from_yaml_file_hdl(self
, file_hdl
):
129 yml
= file_hdl
.read()
131 # Need to prefix project on to the descriptor and then
133 # TODO: See if there is a better way to do this
134 desc
= {NS_PROJECT
: []}
135 desc
[NS_PROJECT
].append(yaml
.load(decode(yml
)))
136 # log = logging.getLogger('rw-mano-log')
137 # log.error("Desc from yaml: {}".format(desc))
138 return self
.yang_class
.from_yaml(self
.model
, yaml
.dump(desc
), strict
=False)
140 def to_json_string(self
, pb_msg
):
141 """ Serialize a protobuf message into JSON
144 pb_msg - A GI-protobuf object of type provided into constructor
147 A JSON string representing the protobuf message
150 SerializationError - Message could not be serialized
151 TypeError - Incorrect protobuf type provided
153 if not isinstance(pb_msg
, self
._yang
_pb
_cls
):
154 raise TypeError("Invalid protobuf message type provided")
157 json_str
= pb_msg
.to_json(self
.model
)
159 # Remove rw-project:project top level element
160 dic
= json
.loads(json_str
)
161 jstr
= json
.dumps(dic
[NS_PROJECT
][0])
162 except Exception as e
:
163 raise SerializationError(e
)
165 log
= logging
.getLogger('rw-mano-log')
166 log
.error("Desc to json: {}".format(jstr
))
169 def to_yaml_string(self
, pb_msg
):
170 """ Serialize a protobuf message into YAML
173 pb_msg - A GI-protobuf object of type provided into constructor
176 A YAML string representing the protobuf message
179 SerializationError - Message could not be serialized
180 TypeError - Incorrect protobuf type provided
182 if not isinstance(pb_msg
, self
._yang
_pb
_cls
):
183 raise TypeError("Invalid protobuf message type provided")
186 yaml_str
= pb_msg
.to_yaml(self
.model
)
188 except Exception as e
:
189 raise SerializationError(e
)
193 def to_xml_string(self
, pb_msg
):
194 """ Serialize a protobuf message into XML
197 pb_msg - A GI-protobuf object of type provided into constructor
200 A XML string representing the protobuf message
203 SerializationError - Message could not be serialized
204 TypeError - Incorrect protobuf type provided
206 if not isinstance(pb_msg
, self
._yang
_pb
_cls
):
207 raise TypeError("Invalid protobuf message type provided")
210 xml_str
= pb_msg
.to_xml_v2(self
.model
)
212 except Exception as e
:
213 raise SerializationError(e
)
217 def from_file_hdl(self
, file_hdl
, extension
):
218 """ Returns the deserialized protobuf message from file contents
220 This function determines the serialization format based on file extension
223 file_hdl - The file hdl to deserialize (set at pos 0)
224 extension - Extension of the file format (second item of os.path.splitext())
227 A GI-Proto message of type that was provided into the constructor
230 UnknownExtensionError - File extension is not of a known serialization format
231 SerializationError - File failed to be deserialized into the protobuf message
234 extension_lc
= extension
.lower()
235 extension_map
= self
._deserialize
_extension
_method
_map
()
237 if extension_lc
not in extension_map
:
238 raise UnknownExtensionError("Cannot detect message format for %s extension" % extension_lc
)
241 msg
= extension_map
[extension_lc
](self
, file_hdl
)
242 except Exception as e
:
243 raise SerializationError(e
)
247 def to_string(self
, pb_msg
, extension
):
248 """ Returns the serialized protobuf message for a particular file extension
250 This function determines the serialization format based on file extension
253 pb_msg - A GI-protobuf object of type provided into constructor
254 extension - Extension of the file format (second item of os.path.splitext())
257 A GI-Proto message of type that was provided into the constructor
260 UnknownExtensionError - File extension is not of a known serialization format
261 SerializationError - File failed to be deserialized into the protobuf message
264 extension_lc
= extension
.lower()
265 extension_map
= self
._serialize
_extension
_method
_map
()
267 if extension_lc
not in extension_map
:
268 raise UnknownExtensionError("Cannot detect message format for %s extension" % extension_lc
)
271 msg
= extension_map
[extension_lc
](self
, pb_msg
)
272 except Exception as e
:
273 raise SerializationError(e
)
278 class VnfdSerializer(ProtoMessageSerializer
):
279 """ Creates a serializer for the VNFD descriptor"""
281 super().__init
__(VnfdYang
, VnfdYang
.YangData_RwProject_Project_VnfdCatalog_Vnfd
)
284 class NsdSerializer(ProtoMessageSerializer
):
285 """ Creates a serializer for the NSD descriptor"""
287 super().__init
__(NsdYang
, NsdYang
.YangData_RwProject_Project_NsdCatalog_Nsd
)
290 class RwVnfdSerializer(ProtoMessageSerializer
):
291 """ Creates a serializer for the VNFD descriptor"""
293 super().__init
__(RwVnfdYang
, RwVnfdYang
.YangData_RwProject_Project_VnfdCatalog_Vnfd
)
296 class RwNsdSerializer(ProtoMessageSerializer
):
297 """ Creates a serializer for the NSD descriptor"""
299 super().__init
__(RwNsdYang
, RwNsdYang
.YangData_RwProject_Project_NsdCatalog_Nsd
)