--- /dev/null
+# Copyright 2016 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.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import os
+import shutil
+import subprocess
+import tarfile
+
+from rift.mano.yang_translator.common.exception import ValidationError
+from rift.mano.yang_translator.common.utils import _
+from rift.mano.yang_translator.rwmano.syntax.tosca_resource \
+ import ToscaResource
+from rift.mano.yang_translator.rwmano.syntax.tosca_template \
+ import ToscaTemplate
+from rift.mano.yang_translator.rwmano.translate_descriptors \
+ import TranslateDescriptors
+
+import rift.package.image
+from rift.package.package import TarPackageArchive
+import rift.package.cloud_init
+import rift.package.script
+import rift.package.store
+
+
+class YangTranslator(object):
+ '''Invokes translation methods.'''
+
+ def __init__(self, log, yangs=None, files=None, packages=[]):
+ super(YangTranslator, self).__init__()
+ self.log = log
+ self.yangs = {}
+ if yangs is not None:
+ self.yangs = yangs
+ self.files = files
+ self.archive = None
+ self.tosca_template = ToscaTemplate(log)
+ self.node_translator = None
+ self.pkgs = packages
+ log.info(_('Initialized parameters for translation.'))
+
+ def translate(self):
+ if self.files:
+ self.get_yangs()
+
+ self.node_translator = TranslateDescriptors(self.log,
+ self.yangs,
+ self.tosca_template)
+
+ self.tosca_template.resources = self.node_translator.translate()
+
+ return self.tosca_template.output_to_tosca()
+
+ def get_yangs(self):
+ '''Get the descriptors and convert to yang instances'''
+ for filename in self.files:
+ self.log.debug(_("Load file {0}").format(filename))
+ # Only one descriptor per file
+ if tarfile.is_tarfile(filename):
+ tar = open(filename, "r+b")
+ archive = TarPackageArchive(self.log, tar)
+ pkg = archive.create_package()
+ self.pkgs.append(pkg)
+ desc_type = pkg.descriptor_type
+ if desc_type == TranslateDescriptors.NSD:
+ if TranslateDescriptors.NSD not in self.yangs:
+ self.yangs[TranslateDescriptors.NSD] = []
+ self.yangs[TranslateDescriptors.NSD]. \
+ append(pkg.descriptor_msg.as_dict())
+ elif desc_type == TranslateDescriptors.VNFD:
+ if TranslateDescriptors.VNFD not in self.yangs:
+ self.yangs[TranslateDescriptors.VNFD] = []
+ self.yangs[TranslateDescriptors.VNFD]. \
+ append(pkg.descriptor_msg.as_dict())
+ else:
+ raise ValidationError("Unknown descriptor type: {}".
+ format(desc_type))
+
+ def _create_csar_files(self, output_dir, name, tmpl,
+ archive=False):
+ if ToscaTemplate.TOSCA not in tmpl:
+ self.log.error(_("Did not find TOSCA template for {0}").
+ format(name))
+ return
+
+ # Create sub for each NS template
+ subdir = os.path.join(output_dir, name)
+ if os.path.exists(subdir):
+ shutil.rmtree(subdir)
+ os.makedirs(subdir)
+
+ # Create the definitions dir
+ def_dir = os.path.join(subdir, 'Definitions')
+ os.makedirs(def_dir)
+ entry_file = os.path.join(def_dir, name+'.yaml')
+ self.log.debug(_("Writing file {0}").
+ format(entry_file))
+ with open(entry_file, 'w+') as f:
+ f.write(tmpl[ToscaTemplate.TOSCA])
+
+ # Create the Tosca meta
+ meta_dir = os.path.join(subdir, 'TOSCA-Metadata')
+ os.makedirs(meta_dir)
+ meta = '''TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: RIFT.io
+Entry-Definitions: Definitions/'''
+ meta_data = "{}{}".format(meta, name+'.yaml')
+ meta_file = os.path.join(meta_dir, 'TOSCA.meta')
+ self.log.debug(_("Writing file {0}:\n{1}").
+ format(meta_file, meta_data))
+ with open(meta_file, 'w+') as f:
+ f.write(meta_data)
+
+ # Copy other supporting files
+ if ToscaTemplate.FILES in tmpl:
+ for f in tmpl[ToscaTemplate.FILES]:
+ self.log.debug(_("Copy supporting file {0}").format(f))
+
+ # Search in source packages
+ if len(self.pkgs):
+ for pkg in self.pkgs:
+ # TODO(pjoseph): Need to add support for other file types
+ fname = f[ToscaResource.NAME]
+ dest_path = os.path.join(subdir, f[ToscaResource.DEST])
+ ftype = f[ToscaResource.TYPE]
+
+ if ftype == 'image':
+ image_file_map = rift.package.image.get_package_image_files(pkg)
+
+ if fname in image_file_map:
+ self.log.debug(_("Extracting image {0} to {1}").
+ format(fname, dest_path))
+ pkg.extract_file(image_file_map[fname],
+ dest_path)
+ break
+
+ elif ftype == 'script':
+ script_file_map = \
+ rift.package.script.PackageScriptExtractor.package_script_files(pkg)
+ if fname in script_file_map:
+ self.log.debug(_("Extracting script {0} to {1}").
+ format(fname, dest_path))
+ pkg.extract_file(script_file_map[fname],
+ dest_path)
+ break
+
+ elif ftype == 'cloud_init':
+ script_file_map = \
+ rift.package.cloud_init.PackageCloudInitExtractor.package_script_files(pkg)
+ if fname in script_file_map:
+ self.log.debug(_("Extracting script {0} to {1}").
+ format(fname, dest_path))
+ pkg.extract_file(script_file_map[fname],
+ dest_path)
+ break
+
+ else:
+ self.log.warn(_("Unknown file type {0}: {1}").
+ format(ftype, f))
+
+ #TODO(pjoseph): Search in other locations
+
+ # Create the ZIP archive
+ if archive:
+ prev_dir=os.getcwd()
+ os.chdir(subdir)
+
+ try:
+ zip_file = name + '.zip'
+ zip_path = os.path.join(output_dir, zip_file)
+ self.log.debug(_("Creating zip file {0}").format(zip_path))
+ zip_cmd = "zip -r {}.partial ."
+ subprocess.check_call(zip_cmd.format(zip_path),
+ shell=True,
+ stdout=subprocess.DEVNULL)
+ mv_cmd = "mv {0}.partial {0}"
+ subprocess.check_call(mv_cmd.format(zip_path),
+ shell=True,
+ stdout=subprocess.DEVNULL)
+ shutil.rmtree(subdir)
+ return zip_path
+
+ except subprocess.CalledProcessError as e:
+ self.log.error(_("Creating CSAR archive failed: {0}").
+ format(e))
+
+ except Exception as e:
+ self.log.exception(e)
+
+ finally:
+ os.chdir(prev_dir)
+
+ def write_output(self, output,
+ output_dir=None,
+ archive=False,):
+ if output:
+ zip_files = []
+ for key in output.keys():
+ if output_dir:
+ zf = self._create_csar_files(output_dir,
+ key,
+ output[key],
+ archive=archive,)
+ zip_files.append(zf)
+ else:
+ print(_("TOSCA Template {0}:\n{1}").
+ format(key, output[key]))
+ return zip_files