6356601cb832fedbb38a206f7f3eb24ff080a179
2 # Copyright 2016 RIFT.io Inc
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
18 from rift
.mano
.tosca_translator
.common
.utils
import _
19 from rift
.mano
.tosca_translator
.common
.utils
import convert_keys_to_python
20 from rift
.mano
.tosca_translator
.rwmano
.syntax
.mano_resource
import ManoResource
22 from toscaparser
.common
.exception
import ValidationError
26 gi
.require_version('RwVnfdYang', '1.0')
28 from gi
.repository
import RwVnfdYang
35 # Name used to dynamically load appropriate map class.
36 TARGET_CLASS_NAME
= 'ToscaNfvVnf'
39 class ToscaNfvVnf(ManoResource
):
40 '''Translate TOSCA node type tosca.nodes.nfv.vnf.'''
42 toscatype
= 'tosca.nodes.nfv.VNF'
44 REQUIRED_PROPS
= ['name', 'short-name', 'id', 'short-name', 'description',
46 OPTIONAL_PROPS
= ['version', 'vendor', 'http-endpoint', 'monitoring-param',
48 IGNORE_PROPS
= ['port']
49 TOSCA_CAPS
= ['mgmt_interface', 'http_endpoint', 'monitoring_param_0',
50 'monitoring_param_1', 'connection_point']
52 def __init__(self
, log
, nodetemplate
, metadata
=None):
53 super(ToscaNfvVnf
, self
).__init
__(log
,
61 def map_tosca_name_to_mano(self
, name
):
62 new_name
= super().map_tosca_name_to_mano(name
)
63 if new_name
.startswith('monitoring-param'):
64 new_name
= 'monitoring-param'
65 if new_name
== 'polling-interval':
66 new_name
= 'polling_interval_secs'
69 def handle_properties(self
):
70 tosca_props
= self
.get_tosca_props()
71 self
.log
.debug(_("VNF {0} with tosca properties: {1}").
72 format(self
.name
, tosca_props
))
74 def get_vnf_config(config
):
76 for key
, value
in config
.items():
77 new_key
= self
.map_tosca_name_to_mano(key
)
78 if isinstance(value
, dict):
80 for subkey
, subvalue
in value
.items():
81 sub_config
[self
.map_tosca_name_to_mano(subkey
)] = \
83 vnf_config
[new_key
] = sub_config
85 vnf_config
[new_key
] = value
87 if vnf_config
['config-type'] != 'script':
88 err_msg
= _("{}, Only script config supported "
90 format(self
, vnf_config
['config-type'])
91 self
.log
.error(err_msg
)
92 raise ValidationError(message
=err_msg
)
94 # Replace config-details with actual name (config-type)
95 if ('config-type' in vnf_config
and
96 'config-details' in vnf_config
):
97 vnf_config
[vnf_config
['config-type']] = \
98 vnf_config
.pop('config-details')
99 vnf_config
.pop('config-type')
101 # Update config-delay and confgig-priortiy to correct struct
102 vnf_config
['config-attributes'] = {}
103 if 'config-delay' in vnf_config
:
104 vnf_config
['config-attributes']['config-delay'] = \
105 vnf_config
.pop('config-delay')
107 vnf_config
['config-attributes']['config-delay'] = 0
108 if 'config-priority' in vnf_config
:
109 vnf_config
['config-attributes']['config-priority'] = \
110 vnf_config
.pop('config-priority')
114 for key
, value
in tosca_props
.items():
116 self
._const
_vnfd
['member-vnf-index'] = int(value
)
117 self
._const
_vnfd
['vnfd-id-ref'] = self
.id
118 elif key
== 'vnf_configuration':
119 self
._vnf
_config
= get_vnf_config(value
)
121 vnf_props
[key
] = value
123 if 'name' not in vnf_props
:
124 vnf_props
['name'] = self
.name
126 if 'short-name' not in vnf_props
:
127 vnf_props
['short-name'] = self
.name
129 if 'id' not in vnf_props
:
130 vnf_props
['id'] = self
.id
132 if 'vendor' not in vnf_props
:
133 vnf_props
['vendor'] = self
.vendor
135 if 'description' not in vnf_props
:
136 vnf_props
['description'] = self
.description
138 if 'start_by_default' in vnf_props
:
139 self
._const
_vnfd
['start-by-default'] = \
140 vnf_props
.pop('start_by_default')
142 self
.log
.debug(_("VNF {0} with constituent vnf: {1}").
143 format(self
.name
, self
._const
_vnfd
))
144 self
.log
.debug(_("VNF {0} with properties: {1}").
145 format(self
.name
, vnf_props
))
146 self
.properties
= vnf_props
148 def handle_capabilities(self
):
149 tosca_caps
= self
.get_tosca_caps()
150 self
.log
.debug(_("VDU {0} tosca capabilites: {1}").
151 format(self
.name
, tosca_caps
))
153 def get_props(props
):
155 for key
in props
.keys():
157 if isinstance(value
, dict):
158 if 'get_property' in value
:
159 val
= self
.get_property(value
['get_property'])
161 properties
[self
.map_tosca_name_to_mano(key
)] = value
164 for key
, value
in tosca_caps
.items():
165 if key
in ToscaNfvVnf
.TOSCA_CAPS
:
166 new_key
= self
.map_tosca_name_to_mano(key
)
167 props
= get_props(value
)
169 props
['id'] = str(props
['id'])
170 if 'protocol' in props
:
171 props
.pop('protocol')
173 # There is only one instance of mgmt interface, but others
175 if key
== 'mgmt_interface':
176 self
.properties
[new_key
] = props
177 elif key
== 'http_endpoint':
178 if new_key
not in self
.properties
:
179 self
.properties
[new_key
] = []
180 self
.properties
[new_key
].append(props
)
182 if new_key
not in self
.properties
:
183 self
.properties
[new_key
] = []
184 self
.properties
[new_key
].append(props
)
186 self
.log
.debug(_("VDU {0} properties: {1}").
187 format(self
.name
, self
.properties
))
189 def handle_requirements(self
, nodes
):
190 tosca_reqs
= self
.get_tosca_reqs()
191 self
.log
.debug("VNF {0} requirements: {1}".
192 format(self
.name
, tosca_reqs
))
195 for req
in tosca_reqs
:
197 target
= req
['vdus']['target']
198 node
= self
.get_node_with_name(target
, nodes
)
200 self
._vdus
.append(node
)
202 # Add the VDU id to mgmt-intf
203 if 'mgmt-interface' in self
.properties
:
204 self
.properties
['mgmt-interface']['vdu-id'] = \
206 if 'vdu' in self
.properties
['mgmt-interface']:
208 self
.properties
['mgmt-interface'].pop('vdu')
210 err_msg
= _("VNF {0}, VDU {1} specified not found"). \
211 format(self
.name
, target
)
212 self
.log
.error(err_msg
)
213 raise ValidationError(message
=err_msg
)
215 except Exception as e
:
216 err_msg
= _("Exception getting VDUs for VNF {0}: {1}"). \
218 self
.log
.error(err_msg
)
221 self
.log
.debug(_("VNF {0} properties: {1}").
222 format(self
.name
, self
.properties
))
224 def generate_yang_model_gi(self
, nsd
, vnfds
):
225 vnfd_cat
= RwVnfdYang
.YangData_RwProject_Project_VnfdCatalog()
226 vnfd
= vnfd_cat
.vnfd
.add()
227 props
= convert_keys_to_python(self
.properties
)
229 vnfd
.from_dict(props
)
230 except Exception as e
:
231 err_msg
= _("{0} Exception updating vnfd from dict {1}: {2}"). \
232 format(self
, props
, e
)
233 self
.log
.error(err_msg
)
235 vnfds
.append(vnfd_cat
)
237 # Update the VDU properties
238 for vdu
in self
._vdus
:
239 vdu
.generate_yang_submodel_gi(vnfd
)
241 # Update constituent vnfd in nsd
243 props
= convert_keys_to_python(self
._const
_vnfd
)
244 nsd
.constituent_vnfd
.add().from_dict(props
)
245 except Exception as e
:
246 err_msg
= _("{0} Exception constituent vnfd from dict {1}: {2}"). \
247 format(self
, props
, e
)
248 self
.log
.error(err_msg
)
251 # Update the vnf configuration info in mgmt_interface
252 props
= convert_keys_to_python(self
._vnf
_config
)
254 vnfd
.vnf_configuration
.from_dict(props
)
255 except Exception as e
:
256 err_msg
= _("{0} Exception vnfd mgmt intf from dict {1}: {2}"). \
257 format(self
, props
, e
)
258 self
.log
.error(err_msg
)
261 def generate_yang_model(self
, nsd
, vnfds
, use_gi
=False):
262 """Generate yang model for the node"""
263 self
.log
.debug(_("Generate YANG model for {0}").
266 for key
in ToscaNfvVnf
.IGNORE_PROPS
:
267 if key
in self
.properties
:
268 self
.properties
.pop(key
)
271 return self
.generate_yang_model_gi(nsd
, vnfds
)
274 vnfd
.update(self
.properties
)
275 # Update vnf configuration on mgmt interface
276 vnfd
['mgmt-interface']['vnf-configuration'] = self
._vnf
_config
278 # Update the VDU properties
280 for vdu
in self
._vdus
:
281 vnfd
['vdu'].append(vdu
.generate_yang_submodel())
285 # Update constituent vnfd in nsd
286 if 'constituent-vnfd' not in nsd
:
287 nsd
['constituent-vnfd'] = []
288 nsd
['constituent-vnfd'].append(self
._const
_vnfd
)
290 def get_member_vnf_index(self
):
291 return self
._const
_vnfd
['member-vnf-index']
293 def get_supporting_files(self
, files
, desc_id
=None):
295 for vdu
in self
._vdus
:
297 files
[self
.id].append({
302 files
[self
.id].append({
303 'type': 'cloud_init',
304 'name': vdu
.cloud_init
,