4 # Copyright 2016 RIFT.IO Inc
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
31 gi
.require_version('RwYang', '1.0')
32 gi
.require_version('RwProjectVnfdYang', '1.0')
33 gi
.require_version('RwProjectNsdYang', '1.0')
34 gi
.require_version('NsdYang', '1.0')
35 gi
.require_version('VnfdYang', '1.0')
37 from gi
.repository
import (
39 RwProjectVnfdYang
as RwVnfdYang
,
40 RwProjectNsdYang
as RwNsdYang
,
45 import rift
.package
.store
46 import rift
.package
.cloud_init
48 logger
= logging
.getLogger("rift2openmano.py")
51 class VNFNotFoundError(Exception):
55 class RiftNSD(object):
56 model
= RwYang
.Model
.create_libyang()
57 model
.load_module('nsd')
59 def __init__(self
, descriptor
):
60 self
._nsd
= descriptor
75 return [c
.vnfd_id_ref
for c
in self
._nsd
.constituent_vnfd
]
78 def constituent_vnfds(self
):
79 return self
._nsd
.constituent_vnfd
82 def scaling_group_descriptor(self
):
83 return self
._nsd
.scaling_group_descriptor
91 return self
._nsd
.connection_point
94 def description(self
):
95 return self
._nsd
.description
98 def from_xml_file_hdl(cls
, hdl
):
100 descriptor
= NsdYang
.YangData_Nsd_NsdCatalog_Nsd()
101 descriptor
.from_xml_v2(RiftNSD
.model
, hdl
.read())
102 return cls(descriptor
)
105 def from_yaml_file_hdl(cls
, hdl
):
107 descriptor
= NsdYang
.YangData_Nsd_NsdCatalog_Nsd()
108 descriptor
.from_yaml(RiftNSD
.model
, hdl
.read())
109 return cls(descriptor
)
112 descriptor
= NsdYang
.YangData_Nsd_NsdCatalog_Nsd
.from_dict(self
._nsd
.as_dict(), ignore_missing_keys
=True).to_json_without_namespace(RiftNSD
.model
)
116 class RiftVNFD(object):
117 model
= RwYang
.Model
.create_libyang()
118 model
.load_module('vnfd')
120 def __init__(self
, descriptor
):
121 self
._vnfd
= descriptor
124 return str(self
._vnfd
)
132 return self
._vnfd
.name
135 def description(self
):
136 return self
._vnfd
.description
140 return self
._vnfd
.connection_point
144 return self
._vnfd
.vdu
147 def internal_vlds(self
):
148 return self
._vnfd
.internal_vld
151 def from_xml_file_hdl(cls
, hdl
):
153 descriptor
= VnfdYang
.YangData_Vnfd_VnfdCatalog_Vnfd()
154 descriptor
.from_xml_v2(RiftVNFD
.model
, hdl
.read())
155 return cls(descriptor
)
158 def from_yaml_file_hdl(cls
, hdl
):
160 descriptor
= VnfdYang
.YangData_Vnfd_VnfdCatalog_Vnfd()
161 descriptor
.from_yaml(RiftVNFD
.model
, hdl
.read())
162 return cls(descriptor
)
165 descriptor
= VnfdYang
.YangData_Vnfd_VnfdCatalog_Vnfd
.from_dict(self
._vnfd
.as_dict(), ignore_missing_keys
=True).to_json_without_namespace(RiftVNFD
.model
)
169 def is_writable_directory(dir_path
):
170 """ Returns True if dir_path is writable, False otherwise
173 dir_path - A directory path
175 if not os
.path
.exists(dir_path
):
176 raise ValueError("Directory does not exist: %s", dir_path
)
179 testfile
= tempfile
.TemporaryFile(dir=dir_path
)
187 def create_vnfd_from_files(vnfd_file_hdls
):
188 """ Create a list of RiftVNFD instances from xml/yaml file handles
191 vnfd_file_hdls - Rift VNFD XML/YAML file handles
194 A list of RiftVNFD instances
197 for vnfd_file_hdl
in vnfd_file_hdls
:
198 if vnfd_file_hdl
.name
.endswith("yaml") or vnfd_file_hdl
.name
.endswith("yaml"):
199 vnfd
= RiftVNFD
.from_yaml_file_hdl(vnfd_file_hdl
)
201 vnfd
= RiftVNFD
.from_xml_file_hdl(vnfd_file_hdl
)
202 vnfd_dict
[vnfd
.id] = vnfd
207 def create_nsd_from_file(nsd_file_hdl
):
208 """ Create a list of RiftNSD instances from yaml/xml file handles
211 nsd_file_hdls - Rift NSD XML/yaml file handles
214 A list of RiftNSD instances
216 if nsd_file_hdl
.name
.endswith("yaml") or nsd_file_hdl
.name
.endswith("yaml"):
217 nsd
= RiftNSD
.from_yaml_file_hdl(nsd_file_hdl
)
219 nsd
= RiftNSD
.from_xml_file_hdl(nsd_file_hdl
)
224 return collections
.defaultdict(dict)
226 def convert_vnfd_name(vnfd_name
, member_idx
):
227 return vnfd_name
+ "__" + str(member_idx
)
230 def rift2openmano_nsd(rift_nsd
, rift_vnfds
, openmano_vnfd_ids
, http_api
, rift_vnfd_id
=None):
232 if rift_vnfd_id
is None:
233 for vnfd_id
in rift_nsd
.vnfd_ids
:
234 if vnfd_id
not in rift_vnfds
:
235 raise VNFNotFoundError("VNF id %s not provided" % vnfd_id
)
237 openmano_nsd_im_body
= json
.loads(rift_nsd
.from_dict())
238 openmano_nsd_api_format
= {
240 "nsd": [openmano_nsd_im_body
['nsd-catalog']['nsd'][0]]
244 openmano_nsd
= http_api
.post_nsd_v3(openmano_nsd_api_format
)
248 except Exception as e
:
252 def rift2openmano_vnfd_nsd(rift_nsd
, rift_vnfds
, openmano_vnfd_ids
, http_api
, rift_vnfd_id
=None):
254 if rift_vnfd_id
not in rift_vnfds
:
255 raise VNFNotFoundError("VNF id %s not provided" % rift_vnfd_id
)
257 # This is the scaling NSD Descriptor. Can use the NSD IM Model.
258 openmano_nsd_im_body
= json
.loads(rift_nsd
.from_dict())
260 openmano_nsd_api_format
= {
262 "nsd": [openmano_nsd_im_body
['nsd-catalog']['nsd'][0]]
266 openmano_nsd
= http_api
.post_nsd_v3(openmano_nsd_api_format
)
270 except Exception as e
:
275 def cloud_init(rift_vnfd_id
, vdu
, project_name
='default'):
276 """ Populate cloud_init with script from
277 either the inline contents or from the file provided
279 vnfd_package_store
= rift
.package
.store
.VnfdPackageFilesystemStore(logger
, project
=project_name
)
281 cloud_init_msg
= None
282 if 'cloud_init' in vdu
:
283 logger
.debug("cloud_init script provided inline %s", vdu
['cloud_init'])
284 cloud_init_msg
= vdu
['cloud_init']
285 elif 'cloud_init_file' in vdu
:
286 # Get cloud-init script contents from the file provided in the cloud_init_file param
287 logger
.debug("cloud_init script provided in file %s", vdu
['cloud_init_file'])
288 filename
= vdu
['cloud_init_file']
289 vnfd_package_store
.refresh()
290 stored_package
= vnfd_package_store
.get_package(rift_vnfd_id
)
291 cloud_init_extractor
= rift
.package
.cloud_init
.PackageCloudInitExtractor(logger
)
293 cloud_init_msg
= cloud_init_extractor
.read_script(stored_package
, filename
)
294 except rift
.package
.cloud_init
.CloudInitExtractionError
as e
:
297 logger
.debug("VDU translation: cloud-init script not provided")
300 logger
.debug("Current cloud init msg is {}".format(cloud_init_msg
))
301 return cloud_init_msg
303 def config_file_init(rift_vnfd_id
, vdu
, cfg_file
, project_name
='default'):
304 """ Populate config file init with file provided
306 vnfd_package_store
= rift
.package
.store
.VnfdPackageFilesystemStore(logger
, project
=project_name
)
308 # Get script contents from the file provided in the cloud_init directory
309 logger
.debug("config file script provided in file {}".format(cfg_file
))
311 vnfd_package_store
.refresh()
312 stored_package
= vnfd_package_store
.get_package(rift_vnfd_id
)
313 cloud_init_extractor
= rift
.package
.cloud_init
.PackageCloudInitExtractor(logger
)
315 cfg_file_msg
= cloud_init_extractor
.read_script(stored_package
, filename
)
316 except rift
.package
.cloud_init
.CloudInitExtractionError
as e
:
319 logger
.debug("Current config file msg is {}".format(cfg_file_msg
))
322 def rift2openmano_vnfd(rift_vnfd
, rift_nsd
, http_api
):
324 openmano_vnfd_im_body
= json
.loads(rift_vnfd
.from_dict())
326 # All type_yang leafs renamed to type
329 vnfd_dict
= openmano_vnfd_im_body
['vnfd-catalog']['vnfd'][0]
331 if 'vdu' in vnfd_dict
:
332 for vdu
in vnfd_dict
['vdu']:
333 if 'cloud_init_file' in vdu
:
334 # Replacing the leaf with the actual contents of the file.
335 # The RO does not have the ability to read files yet.
336 vdu
['cloud_init_file'] = cloud_init(openmano_vnfd_im_body
.id, vdu
)
337 elif 'cloud_init' in vdu
:
338 vdu
['cloud_init'] = cloud_init(openmano_vnfd_im_body
.id, vdu
)
340 if 'supplemental_boot_data' in vdu
:
341 if 'config_file' in vdu
['supplemental_boot_data']:
342 for config_file
in vdu
['supplemental_boot_data']['config_file']:
343 # Replacing the leaf with the actual contents of the file.
344 # The RO does not have the ability to read files yet.
345 config_file
['source'] = config_file_init(openmano_vnfd_im_body
.id, vdu
, config_file
['source'])
347 openmano_vnfd_api_format
= {
348 "vnfd:vnfd-catalog": {
353 openmano_vnfd
= http_api
.post_vnfd_v3(openmano_vnfd_api_format
)
357 except Exception as e
:
363 def parse_args(argv
=sys
.argv
[1:]):
364 """ Parse the command line arguments
367 arv - The list of arguments to parse
370 Argparse Namespace instance
372 parser
= argparse
.ArgumentParser()
376 help="Directory to output converted descriptors. Default is stdout",
380 '-n', '--nsd-file-hdl',
382 type=argparse
.FileType('r'),
383 help="Rift NSD Descriptor File",
387 '-v', '--vnfd-file-hdls',
390 type=argparse
.FileType('r'),
391 help="Rift VNFD Descriptor File",
394 args
= parser
.parse_args(argv
)
396 if not os
.path
.exists(args
.outdir
):
397 os
.makedirs(args
.outdir
)
399 if not is_writable_directory(args
.outdir
):
400 logging
.error("Directory %s is not writable", args
.outdir
)
406 def write_yaml_to_file(name
, outdir
, desc_dict
):
407 file_name
= "%s.yaml" % name
408 yaml_str
= yaml
.dump(desc_dict
)
410 sys
.stdout
.write(yaml_str
)
413 file_path
= os
.path
.join(outdir
, file_name
)
414 dir_path
= os
.path
.dirname(file_path
)
415 if not os
.path
.exists(dir_path
):
416 os
.makedirs(dir_path
)
418 with
open(file_path
, "w") as hdl
:
421 logger
.info("Wrote descriptor to %s", file_path
)
424 def main(argv
=sys
.argv
[1:]):
425 args
= parse_args(argv
)
427 openmano_vnfr_ids
= dict()
429 if args
.vnfd_file_hdls
is not None:
430 vnf_dict
= create_vnfd_from_files(args
.vnfd_file_hdls
)
432 for vnfd
in vnf_dict
:
433 openmano_vnfr_ids
[vnfd
] = vnfd
435 if args
.nsd_file_hdl
is not None:
436 nsd
= create_nsd_from_file(args
.nsd_file_hdl
)
438 openmano_nsd
= rift2openmano_nsd(nsd
, vnf_dict
, openmano_vnfr_ids
)
439 vnfd_nsd
= rift2openmano_vnfd_nsd(nsd
, vnf_dict
, openmano_vnfr_ids
)
440 write_yaml_to_file(openmano_nsd
["name"], args
.outdir
, openmano_nsd
)
441 write_yaml_to_file(vnfd_nsd
["name"], args
.outdir
, vnfd_nsd
)
443 for vnf
in vnf_dict
.values():
444 openmano_vnf
= rift2openmano_vnfd(vnf
, nsd
)
445 write_yaml_to_file(openmano_vnf
["vnf"]["name"], args
.outdir
, openmano_vnf
)
448 if __name__
== "__main__":
449 logging
.basicConfig(level
=logging
.WARNING
)