Merge "Merge TOSCA changes from RIFT to OSM"
[osm/SO.git] / rwlaunchpad / plugins / rwlaunchpadtasklet / rift / package / convert.py
1
2 #
3 # Copyright 2016 RIFT.IO Inc
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16 #
17
18 import json
19 import os
20 import tempfile
21
22 import gi
23 gi.require_version('RwNsdYang', '1.0')
24 gi.require_version('RwVnfdYang', '1.0')
25 gi.require_version('RwYang', '1.0')
26 from gi.repository import (
27 RwNsdYang,
28 RwVnfdYang,
29 NsdYang,
30 VnfdYang,
31 RwYang,
32 )
33
34
35 class UnknownExtensionError(Exception):
36 pass
37
38
39 class SerializationError(Exception):
40 pass
41
42
43 def decode(desc_data):
44 if isinstance(desc_data, bytes):
45 desc_data = desc_data.decode()
46
47 return desc_data
48
49
50 class ProtoMessageSerializer(object):
51 """(De)Serializer/deserializer fo a specific protobuf message into various formats"""
52 libncx_model = None
53
54 def __init__(self, yang_ns, yang_pb_cls):
55 """ Create a serializer for a specific protobuf message """
56 self._yang_ns = yang_ns
57 self._yang_pb_cls = yang_pb_cls
58
59 @classmethod
60 def _deserialize_extension_method_map(cls):
61 return {
62 ".xml": cls._from_xml_file_hdl,
63 ".yml": cls._from_yaml_file_hdl,
64 ".yaml": cls._from_yaml_file_hdl,
65 ".json": cls._from_json_file_hdl,
66 }
67
68 @classmethod
69 def _serialize_extension_method_map(cls):
70 return {
71 ".xml": cls.to_xml_string,
72 ".yml": cls.to_yaml_string,
73 ".yaml": cls.to_yaml_string,
74 ".json": cls.to_json_string,
75 }
76
77 @classmethod
78 def is_supported_file(cls, filename):
79 """Returns whether a file has a supported file extension
80
81 Arguments:
82 filename - A descriptor file
83
84 Returns:
85 True if file extension is supported, False otherwise
86
87 """
88 _, extension = os.path.splitext(filename)
89 extension_lc = extension.lower()
90
91 return extension_lc in cls._deserialize_extension_method_map()
92
93 @property
94 def yang_namespace(self):
95 """ The Protobuf's GI namespace class (e.g. RwVnfdYang) """
96 return self._yang_ns
97
98 @property
99 def yang_class(self):
100 """ The Protobuf's GI class (e.g. RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd) """
101 return self._yang_pb_cls
102
103 @property
104 def model(self):
105 cls = self.__class__
106
107 # Cache the libncx model for the serializer class
108 if cls.libncx_model is None:
109 cls.libncx_model = RwYang.model_create_libncx()
110 cls.libncx_model.load_schema_ypbc(self.yang_namespace.get_schema())
111
112 return cls.libncx_model
113
114 def _from_xml_file_hdl(self, file_hdl):
115 xml = file_hdl.read()
116
117 return self.yang_class.from_xml_v2(self.model, decode(xml), strict=False)
118
119 def _from_json_file_hdl(self, file_hdl):
120 json = file_hdl.read()
121
122 return self.yang_class.from_json(self.model, decode(json), strict=False)
123
124 def _from_yaml_file_hdl(self, file_hdl):
125 yaml = file_hdl.read()
126
127 return self.yang_class.from_yaml(self.model, decode(yaml), strict=False)
128
129 def to_json_string(self, pb_msg):
130 """ Serialize a protobuf message into JSON
131
132 Arguments:
133 pb_msg - A GI-protobuf object of type provided into constructor
134
135 Returns:
136 A JSON string representing the protobuf message
137
138 Raises:
139 SerializationError - Message could not be serialized
140 TypeError - Incorrect protobuf type provided
141 """
142 if not isinstance(pb_msg, self._yang_pb_cls):
143 raise TypeError("Invalid protobuf message type provided")
144
145 try:
146 json_str = pb_msg.to_json(self.model)
147
148 except Exception as e:
149 raise SerializationError(e)
150
151 return json_str
152
153 def to_yaml_string(self, pb_msg):
154 """ Serialize a protobuf message into YAML
155
156 Arguments:
157 pb_msg - A GI-protobuf object of type provided into constructor
158
159 Returns:
160 A YAML string representing the protobuf message
161
162 Raises:
163 SerializationError - Message could not be serialized
164 TypeError - Incorrect protobuf type provided
165 """
166 if not isinstance(pb_msg, self._yang_pb_cls):
167 raise TypeError("Invalid protobuf message type provided")
168
169 try:
170 yaml_str = pb_msg.to_yaml(self.model)
171
172 except Exception as e:
173 raise SerializationError(e)
174
175 return yaml_str
176
177 def to_xml_string(self, pb_msg):
178 """ Serialize a protobuf message into XML
179
180 Arguments:
181 pb_msg - A GI-protobuf object of type provided into constructor
182
183 Returns:
184 A XML string representing the protobuf message
185
186 Raises:
187 SerializationError - Message could not be serialized
188 TypeError - Incorrect protobuf type provided
189 """
190 if not isinstance(pb_msg, self._yang_pb_cls):
191 raise TypeError("Invalid protobuf message type provided")
192
193 try:
194 xml_str = pb_msg.to_xml_v2(self.model)
195
196 except Exception as e:
197 raise SerializationError(e)
198
199 return xml_str
200
201 def from_file_hdl(self, file_hdl, extension):
202 """ Returns the deserialized protobuf message from file contents
203
204 This function determines the serialization format based on file extension
205
206 Arguments:
207 file_hdl - The file hdl to deserialize (set at pos 0)
208 extension - Extension of the file format (second item of os.path.splitext())
209
210 Returns:
211 A GI-Proto message of type that was provided into the constructor
212
213 Raises:
214 UnknownExtensionError - File extension is not of a known serialization format
215 SerializationError - File failed to be deserialized into the protobuf message
216 """
217
218 extension_lc = extension.lower()
219 extension_map = self._deserialize_extension_method_map()
220
221 if extension_lc not in extension_map:
222 raise UnknownExtensionError("Cannot detect message format for %s extension" % extension_lc)
223
224 try:
225 msg = extension_map[extension_lc](self, file_hdl)
226 except Exception as e:
227 raise SerializationError(e)
228
229 return msg
230
231 def to_string(self, pb_msg, extension):
232 """ Returns the serialized protobuf message for a particular file extension
233
234 This function determines the serialization format based on file extension
235
236 Arguments:
237 pb_msg - A GI-protobuf object of type provided into constructor
238 extension - Extension of the file format (second item of os.path.splitext())
239
240 Returns:
241 A GI-Proto message of type that was provided into the constructor
242
243 Raises:
244 UnknownExtensionError - File extension is not of a known serialization format
245 SerializationError - File failed to be deserialized into the protobuf message
246 """
247
248 extension_lc = extension.lower()
249 extension_map = self._serialize_extension_method_map()
250
251 if extension_lc not in extension_map:
252 raise UnknownExtensionError("Cannot detect message format for %s extension" % extension_lc)
253
254 try:
255 msg = extension_map[extension_lc](self, pb_msg)
256 except Exception as e:
257 raise SerializationError(e)
258
259 return msg
260
261
262 class VnfdSerializer(ProtoMessageSerializer):
263 """ Creates a serializer for the VNFD descriptor"""
264 def __init__(self):
265 super().__init__(VnfdYang, VnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd)
266
267
268 class NsdSerializer(ProtoMessageSerializer):
269 """ Creates a serializer for the NSD descriptor"""
270 def __init__(self):
271 super().__init__(NsdYang, NsdYang.YangData_Nsd_NsdCatalog_Nsd)
272
273
274 class RwVnfdSerializer(ProtoMessageSerializer):
275 """ Creates a serializer for the VNFD descriptor"""
276 def __init__(self):
277 super().__init__(RwVnfdYang, RwVnfdYang.YangData_Vnfd_VnfdCatalog_Vnfd)
278
279
280 class RwNsdSerializer(ProtoMessageSerializer):
281 """ Creates a serializer for the NSD descriptor"""
282 def __init__(self):
283 super().__init__(RwNsdYang, RwNsdYang.YangData_Nsd_NsdCatalog_Nsd)