X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=common%2Fpython%2Frift%2Fmano%2Fyang_translator%2Frwmano%2Ftranslate_descriptors.py;fp=common%2Fpython%2Frift%2Fmano%2Fyang_translator%2Frwmano%2Ftranslate_descriptors.py;h=f0a68665a969a297da8b70e543dfe7ad6587d8af;hb=6f07e6f33f751ab4ffe624f6037f887b243bece2;hp=0000000000000000000000000000000000000000;hpb=72a563886272088feb7cb52e4aafbe6d2c580ff9;p=osm%2FSO.git diff --git a/common/python/rift/mano/yang_translator/rwmano/translate_descriptors.py b/common/python/rift/mano/yang_translator/rwmano/translate_descriptors.py new file mode 100644 index 00000000..f0a68665 --- /dev/null +++ b/common/python/rift/mano/yang_translator/rwmano/translate_descriptors.py @@ -0,0 +1,192 @@ +# +# 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. + +# Copyright 2016 RIFT.io Inc + + +import importlib +import os + +from rift.mano.yang_translator.common.exception import YangClassAttributeError +from rift.mano.yang_translator.common.exception import YangClassImportError +from rift.mano.yang_translator.common.exception import YangModImportError +from rift.mano.yang_translator.common.utils import _ +from rift.mano.yang_translator.conf.config import ConfigProvider \ + as translatorConfig +from rift.mano.yang_translator.rwmano.syntax.tosca_resource \ + import ToscaResource + + +class TranslateDescriptors(object): + '''Translate YANG NodeTemplates to RIFT.io MANO Resources.''' + + YANG_DESC = (NSD, VNFD) = ('nsd', 'vnfd') + + ########################### + # Module utility Functions + # for dynamic class loading + ########################### + + YANG_TO_TOSCA_TYPE = None + + def _load_classes(log, locations, classes): + '''Dynamically load all the classes from the given locations.''' + + for cls_path in locations: + # Use the absolute path of the class path + abs_path = os.path.dirname(os.path.abspath(__file__)) + abs_path = abs_path.replace('rift/mano/yang_translator/rwmano', + cls_path) + log.debug(_("Loading classes from %s") % abs_path) + + # Grab all the yang type module files in the given path + mod_files = [f for f in os.listdir(abs_path) if ( + f.endswith('.py') and + not f.startswith('__init__') and + f.startswith('yang_'))] + + # For each module, pick out the target translation class + for f in mod_files: + f_name, ext = f.rsplit('.', 1) + mod_name = cls_path + '/' + f_name + mod_name = mod_name.replace('/', '.') + try: + mod = importlib.import_module(mod_name) + target_name = getattr(mod, 'TARGET_CLASS_NAME') + clazz = getattr(mod, target_name) + classes.append(clazz) + except ImportError: + raise YangModImportError(mod_name=mod_name) + except AttributeError: + if target_name: + raise YangClassImportError(name=target_name, + mod_name=mod_name) + else: + # TARGET_CLASS_NAME is not defined in module. + # Re-raise the exception + raise + + def _generate_type_map(log): + '''Generate YANG translation types map. + + Load user defined classes from location path specified in conf file. + Base classes are located within the yang directory. + ''' + + # Base types directory + BASE_PATH = 'rift/mano/yang_translator/rwmano/yang' + + # Custom types directory defined in conf file + custom_path = translatorConfig.get_value('DEFAULT', + 'custom_types_location') + + # First need to load the parent module, for example 'contrib.mano', + # for all of the dynamically loaded classes. + classes = [] + TranslateDescriptors._load_classes(log, + (BASE_PATH, custom_path), + classes) + try: + types_map = {clazz.yangtype: clazz for clazz in classes} + log.debug(_("Type maps loaded: {}").format(types_map.keys())) + except AttributeError as e: + raise YangClassAttributeError(message=e.message) + + return types_map + + def __init__(self, log, yangs, tosca_template): + self.log = log + self.yangs = yangs + self.tosca_template = tosca_template + # list of all TOSCA resources generated + self.tosca_resources = [] + self.metadata = {} + log.debug(_('Mapping between YANG nodetemplate and TOSCA resource.')) + + def translate(self): + if TranslateDescriptors.YANG_TO_TOSCA_TYPE is None: + TranslateDescriptors.YANG_TO_TOSCA_TYPE = \ + TranslateDescriptors._generate_type_map(self.log) + return self._translate_yang() + + def translate_metadata(self): + """Translate and store the metadata in instance""" + FIELDS_MAP = { + 'ID': 'name', + 'vendor': 'vendor', + 'version': 'version', + } + metadata = {} + # Initialize to default values + metadata['name'] = 'yang_to_tosca' + metadata['vendor'] = 'RIFT.io' + metadata['version'] = '1.0' + if 'nsd' in self.yangs: + yang_meta = self.yang['nsd'][0] + elif 'vnfd' in self.yangs: + yang_meta = self.yang['vnfd'][0] + for key in FIELDS_MAP: + if key in yang_meta.keys(): + metadata[key] = str(yang_meta[FIELDS_MAP[key]]) + self.log.debug(_("Metadata {0}").format(metadata)) + self.metadata = metadata + + def _translate_yang(self): + self.log.debug(_('Translating the descriptors.')) + for nsd in self.yangs[self.NSD]: + self.log.debug(_("Translate descriptor of type nsd: {}"). + format(nsd)) + tosca_node = TranslateDescriptors. \ + YANG_TO_TOSCA_TYPE[self.NSD]( + self.log, + nsd.pop(ToscaResource.NAME), + self.NSD, + nsd) + self.tosca_resources.append(tosca_node) + + for vnfd in self.yangs[self.VNFD]: + self.log.debug(_("Translate descriptor of type vnfd: {}"). + format(vnfd)) + tosca_node = TranslateDescriptors. \ + YANG_TO_TOSCA_TYPE[self.VNFD]( + self.log, + vnfd.pop(ToscaResource.NAME), + self.VNFD, + vnfd) + self.tosca_resources.append(tosca_node) + + # First translate VNFDs + for node in self.tosca_resources: + if node.type == self.VNFD: + self.log.debug(_("Handle yang for {0} of type {1}"). + format(node.name, node.type_)) + node.handle_yang() + + # Now translate NSDs + for node in self.tosca_resources: + if node.type == self.NSD: + self.log.debug(_("Handle yang for {0} of type {1}"). + format(node.name, node.type_)) + node.handle_yang(self.tosca_resources) + + return self.tosca_resources + + def find_tosca_resource(self, name): + for resource in self.tosca_resources: + if resource.name == name: + return resource + + def _find_yang_node(self, yang_name): + for node in self.nodetemplates: + if node.name == yang_name: + return node