2 # Licensed under the Apache License, Version 2.0 (the "License"); you may
3 # not use this file except in compliance with the License. You may obtain
4 # a copy of the License at
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11 # License for the specific language governing permissions and limitations
14 # Copyright 2016 RIFT.io Inc
20 from rift
.mano
.yang_translator
.common
.exception
import YangClassAttributeError
21 from rift
.mano
.yang_translator
.common
.exception
import YangClassImportError
22 from rift
.mano
.yang_translator
.common
.exception
import YangModImportError
23 from rift
.mano
.yang_translator
.common
.utils
import _
24 from rift
.mano
.yang_translator
.conf
.config
import ConfigProvider \
26 from rift
.mano
.yang_translator
.rwmano
.syntax
.tosca_resource \
30 class TranslateDescriptors(object):
31 '''Translate YANG NodeTemplates to RIFT.io MANO Resources.'''
33 YANG_DESC
= (NSD
, VNFD
) = ('nsd', 'vnfd')
35 ###########################
36 # Module utility Functions
37 # for dynamic class loading
38 ###########################
40 YANG_TO_TOSCA_TYPE
= None
42 def _load_classes(log
, locations
, classes
):
43 '''Dynamically load all the classes from the given locations.'''
45 for cls_path
in locations
:
46 # Use the absolute path of the class path
47 abs_path
= os
.path
.dirname(os
.path
.abspath(__file__
))
48 abs_path
= abs_path
.replace('rift/mano/yang_translator/rwmano',
50 log
.debug(_("Loading classes from %s") % abs_path
)
52 # Grab all the yang type module files in the given path
53 mod_files
= [f
for f
in os
.listdir(abs_path
) if (
55 not f
.startswith('__init__') and
56 f
.startswith('yang_'))]
58 # For each module, pick out the target translation class
60 f_name
, ext
= f
.rsplit('.', 1)
61 mod_name
= cls_path
+ '/' + f_name
62 mod_name
= mod_name
.replace('/', '.')
64 mod
= importlib
.import_module(mod_name
)
65 target_name
= getattr(mod
, 'TARGET_CLASS_NAME')
66 clazz
= getattr(mod
, target_name
)
69 raise YangModImportError(mod_name
=mod_name
)
70 except AttributeError:
72 raise YangClassImportError(name
=target_name
,
75 # TARGET_CLASS_NAME is not defined in module.
76 # Re-raise the exception
79 def _generate_type_map(log
):
80 '''Generate YANG translation types map.
82 Load user defined classes from location path specified in conf file.
83 Base classes are located within the yang directory.
86 # Base types directory
87 BASE_PATH
= 'rift/mano/yang_translator/rwmano/yang'
89 # Custom types directory defined in conf file
90 custom_path
= translatorConfig
.get_value('DEFAULT',
91 'custom_types_location')
93 # First need to load the parent module, for example 'contrib.mano',
94 # for all of the dynamically loaded classes.
96 TranslateDescriptors
._load
_classes
(log
,
97 (BASE_PATH
, custom_path
),
100 types_map
= {clazz
.yangtype
: clazz
for clazz
in classes
}
101 log
.debug(_("Type maps loaded: {}").format(types_map
.keys()))
102 except AttributeError as e
:
103 raise YangClassAttributeError(message
=e
.message
)
107 def __init__(self
, log
, yangs
, tosca_template
):
110 self
.tosca_template
= tosca_template
111 # list of all TOSCA resources generated
112 self
.tosca_resources
= []
114 log
.debug(_('Mapping between YANG nodetemplate and TOSCA resource.'))
117 if TranslateDescriptors
.YANG_TO_TOSCA_TYPE
is None:
118 TranslateDescriptors
.YANG_TO_TOSCA_TYPE
= \
119 TranslateDescriptors
._generate
_type
_map
(self
.log
)
120 return self
._translate
_yang
()
122 def translate_metadata(self
):
123 """Translate and store the metadata in instance"""
127 'version': 'version',
130 # Initialize to default values
131 metadata
['name'] = 'yang_to_tosca'
132 metadata
['vendor'] = 'RIFT.io'
133 metadata
['version'] = '1.0'
134 if 'nsd' in self
.yangs
:
135 yang_meta
= self
.yang
['nsd'][0]
136 elif 'vnfd' in self
.yangs
:
137 yang_meta
= self
.yang
['vnfd'][0]
138 for key
in FIELDS_MAP
:
139 if key
in yang_meta
.keys():
140 metadata
[key
] = str(yang_meta
[FIELDS_MAP
[key
]])
141 self
.log
.debug(_("Metadata {0}").format(metadata
))
142 self
.metadata
= metadata
144 def _translate_yang(self
):
145 self
.log
.debug(_('Translating the descriptors.'))
146 for nsd
in self
.yangs
[self
.NSD
]:
147 self
.log
.debug(_("Translate descriptor of type nsd: {}").
149 tosca_node
= TranslateDescriptors
. \
150 YANG_TO_TOSCA_TYPE
[self
.NSD
](
152 nsd
.pop(ToscaResource
.NAME
),
155 self
.tosca_resources
.append(tosca_node
)
157 for vnfd
in self
.yangs
[self
.VNFD
]:
158 self
.log
.debug(_("Translate descriptor of type vnfd: {}").
160 tosca_node
= TranslateDescriptors
. \
161 YANG_TO_TOSCA_TYPE
[self
.VNFD
](
163 vnfd
.pop(ToscaResource
.NAME
),
166 self
.tosca_resources
.append(tosca_node
)
168 # First translate VNFDs
169 for node
in self
.tosca_resources
:
170 if node
.type == self
.VNFD
:
171 self
.log
.debug(_("Handle yang for {0} of type {1}").
172 format(node
.name
, node
.type_
))
176 for node
in self
.tosca_resources
:
177 if node
.type == self
.NSD
:
178 self
.log
.debug(_("Handle yang for {0} of type {1}").
179 format(node
.name
, node
.type_
))
180 node
.handle_yang(self
.tosca_resources
)
182 return self
.tosca_resources
184 def find_tosca_resource(self
, name
):
185 for resource
in self
.tosca_resources
:
186 if resource
.name
== name
:
189 def _find_yang_node(self
, yang_name
):
190 for node
in self
.nodetemplates
:
191 if node
.name
== yang_name
: