1 # Copyright 2016 RIFT.io Inc
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
16 from copy
import deepcopy
19 from rift
.mano
.yang_translator
.common
.exception
import ValidationError
20 from rift
.mano
.yang_translator
.common
.utils
import _
21 from rift
.mano
.yang_translator
.rwmano
.syntax
.tosca_resource \
23 from rift
.mano
.yang_translator
.rwmano
.yang
.yang_vld
import YangVld
24 from collections
import OrderedDict
27 TARGET_CLASS_NAME
= 'YangNsd'
30 class YangNsd(ToscaResource
):
31 '''Class for RIFT.io YANG NS descriptor translation to TOSCA type.'''
35 OTHER_FIELDS
= (SCALE_GRP
, CONF_PRIM
,
36 USER_DEF_SCRIPT
, SCALE_ACT
,
37 TRIGGER
, NS_CONF_PRIM_REF
,
38 CONST_VNFD
, VNFD_MEMBERS
,
39 MIN_INST_COUNT
, MAX_INST_COUNT
,
40 INPUT_PARAM_XPATH
, CONFIG_ACTIONS
,
42 ('scaling_group_descriptor', 'service_primitive',
43 'user_defined_script', 'scaling_config_action',
44 'trigger', 'ns_service_primitive_name_ref',
45 'constituent_vnfd', 'vnfd_member',
46 'min_instance_count', 'max_instance_count',
47 'input_parameter_xpath', 'config_actions',
48 'initial_config_primitive', )
56 super(YangNsd
, self
).__init
__(log
,
67 self
.service_primitive
= []
68 self
.placement_groups
= []
69 self
.vnf_id_to_vnf_map
= {}
70 self
.vnfd_files
= vnfd_files
71 self
.vld_to_vnf_map
= {}
72 self
.vnf_to_vld_map
= {}
73 self
._vnf
_vld
_conn
_point
_map
= {}
75 self
.forwarding_paths
= {}
76 self
.substitution_mapping_forwarder
= []
77 self
.vnfd_sfc_map
= None
78 self
.duplicate_vnfd_name_list
= []
80 def handle_yang(self
, vnfds
):
81 self
.log
.debug(_("Process NSD desc {0}: {1}").
82 format(self
.name
, self
.yang
))
84 def process_input_param(param
):
85 if self
.XPATH
in param
:
86 val
= param
.pop(self
.XPATH
)
87 # Strip namesapce, catalog and nsd part
90 self
.map_yang_name_to_tosca(
91 val
.replace('/rw-project:project/project-nsd:nsd-catalog/project-nsd:nsd/nsd:', ''))})
93 self
.log
.warn(_("{0}, Did not process the following for "
94 "input param {1}: {2}").
95 format(self
, self
.inputs
, param
))
96 self
.log
.debug(_("{0}, inputs: {1}").format(self
, self
.inputs
[-1]))
98 def process_const_vnfd(cvnfd
):
99 # Get the matching VNFD
100 vnfd_id
= cvnfd
.pop(self
.VNFD_ID_REF
)
102 if vnfd
.type == self
.VNFD
and vnfd
.id == vnfd_id
:
103 self
.vnf_id_to_vnf_map
[vnfd_id
] = vnfd
.name
104 self
.vnfds
[cvnfd
.pop(self
.MEM_VNF_INDEX
)] = vnfd
105 if self
.START_BY_DFLT
in cvnfd
:
106 vnfd
.props
[self
.START_BY_DFLT
] = \
107 cvnfd
.pop(self
.START_BY_DFLT
)
111 self
.log
.warn(_("{0}, Did not process the following for "
112 "constituent vnfd {1}: {2}").
113 format(self
, vnfd_id
, cvnfd
))
114 self
.log
.debug(_("{0}, VNFD: {1}").format(self
, self
.vnfds
))
116 def process_scale_grp(dic
):
118 self
.log
.debug(_("{0}, scale group: {1}").format(self
, dic
))
119 fields
= [self
.NAME
, self
.MIN_INST_COUNT
, self
.MAX_INST_COUNT
]
122 sg
[key
] = dic
.pop(key
)
125 for vnfd_memb
in dic
.pop(self
.VNFD_MEMBERS
):
126 vnfd_idx
= vnfd_memb
[self
.MEM_VNF_INDEX_REF
]
127 if vnfd_idx
in self
.vnfds
:
128 membs
[self
.vnfds
[vnfd_idx
].name
] = \
129 vnfd_memb
[self
.COUNT
]
130 sg
['vnfd_members'] = membs
133 if self
.SCALE_ACT
in dic
:
134 for sg_act
in dic
.pop(self
.SCALE_ACT
):
135 # Validate the primitive
136 prim
= sg_act
.pop(self
.NS_CONF_PRIM_REF
)
137 for cprim
in self
.conf_prims
:
138 if cprim
[self
.NAME
] == prim
:
139 trigs
[sg_act
.pop(self
.TRIGGER
)] = prim
142 err_msg
= (_("{0}, Did not find config-primitive {1}").
144 self
.log
.error(err_msg
)
145 raise ValidationError(message
=err_msg
)
146 sg
[self
.CONFIG_ACTIONS
] = trigs
149 self
.log
.warn(_("{0}, Did not process all fields for {1}").
151 self
.log
.debug(_("{0}, Scale group {1}").format(self
, sg
))
152 self
.scale_grps
.append(sg
)
154 def process_initial_config(dic
):
156 self
.log
.debug(_("{0}, initial config: {1}").format(self
, dic
))
157 for key
in [self
.NAME
, self
.SEQ
, self
.USER_DEF_SCRIPT
]:
159 icp
[key
] = dic
.pop(key
)
162 if self
.PARAM
in dic
:
163 for p
in dic
.pop(self
.PARAM
):
164 if (self
.NAME
in p
and
166 params
.append({self
.NAME
: p
[self
.NAME
], self
.VALUE
:p
[self
.VALUE
]})
168 # TODO (pjoseph): Need to add support to read the
169 # config file and get the value from that
170 self
.log
.warn(_("{0}, Got parameter without value: {1}").
173 icp
[self
.PARAM
] = params
176 self
.log
.warn(_("{0}, Did not process all fields for {1}").
178 self
.log
.debug(_("{0}, Initial config {1}").format(self
, icp
))
179 self
.initial_cfg
.append({self
.PROPERTIES
: icp
})
181 def process_service_primitive(dic
):
184 for key
in [self
.NAME
, self
.USER_DEF_SCRIPT
]:
186 prop
[key
] = dic
.pop(key
)
188 if self
.PARAM
in dic
:
189 for p
in dic
.pop(self
.PARAM
):
191 for name
, value
in p
.items():
192 p_entry
[name
] = value
193 params
.append(p_entry
)
196 prop
[self
.PARAM
] = params
198 conf_prim
= {self
.NAME
: prop
[self
.NAME
], self
.DESC
: 'TestDescription'}
199 if self
.USER_DEF_SCRIPT
in prop
:
200 conf_prim
[self
.USER_DEF_SCRIPT
] = prop
[self
.USER_DEF_SCRIPT
]
201 self
.conf_prims
.append(conf_prim
)
203 self
.service_primitive
.append({self
.PROPERTIES
: prop
})
206 def process_vld(vld
, dic
):
209 ip_profile_vld
= None
211 if 'ip_profile_ref' in vld
:
212 ip_profile_name
= vld
['ip_profile_ref']
213 if 'ip_profiles' in dic
:
214 for ip_prof
in dic
['ip_profiles']:
215 if ip_profile_name
== ip_prof
['name']:
216 ip_profile_vld
= ip_prof
218 vld_name
= vld
['name'].replace('-','_').replace(' ','')
219 if 'description' in vld
:
220 vld_conf
['description'] = vld
['description']
222 vld_conf
['vendor'] = vld
['vendor']
224 if 'ip_profile_params' in ip_profile_vld
:
225 ip_param
= ip_profile_vld
['ip_profile_params']
226 if 'gateway_address' in ip_param
:
227 vld_conf
['gateway_ip'] = ip_param
['gateway_address']
228 if 'subnet_address' in ip_param
:
229 vld_conf
['cidr'] = ip_param
['subnet_address']
230 if 'ip_version' in ip_param
:
231 vld_conf
['ip_version'] = ip_param
['ip_version'].replace('ipv','')
234 vld_prop
= {vld_name
:
237 self
.PROPERTIES
: vld_conf
239 self
.vlds
[vld_name
] = { 'type': self
.T_ELAN
,
240 self
.PROPERTIES
: vld_conf
243 self
.vld_to_vnf_map
[vld_name
] = []
244 if 'vnfd_connection_point_ref' in vld
:
245 for vnfd_ref
in vld
['vnfd_connection_point_ref']:
246 vnf_name
= self
.vnf_id_to_vnf_map
[vnfd_ref
['vnfd_id_ref']]
247 if vnf_name
in self
.vnf_to_vld_map
:
248 self
.vnf_to_vld_map
[vnf_name
].append(vld_name
)
249 self
._vnf
_vld
_conn
_point
_map
[vnf_name
].\
250 append((vld_name
,vnfd_ref
['vnfd_connection_point_ref']))
252 self
.vnf_to_vld_map
[vnf_name
] = []
253 self
._vnf
_vld
_conn
_point
_map
[vnf_name
] = []
254 self
.vnf_to_vld_map
[vnf_name
].append(vld_name
)
255 self
._vnf
_vld
_conn
_point
_map
[vnf_name
].\
256 append((vld_name
,vnfd_ref
['vnfd_connection_point_ref']))
258 def process_placement_group(placement_groups
):
259 for i
in range(0, len(placement_groups
)):
260 placement_group
= placement_groups
[i
]
261 pg_name
= "placement_{0}".format(i
)
264 if 'name' in placement_group
:
265 pg_config
['name'] = placement_group
['name']
266 if 'requirement' in placement_group
:
267 pg_config
['requirement'] = placement_group
['requirement']
268 if 'strategy' in placement_group
:
269 pg_config
['strategy'] = placement_group
['strategy']
270 if 'member_vnfd' in placement_group
:
271 for member_vnfd
in placement_group
['member_vnfd']:
272 targets
.append(self
.vnf_id_to_vnf_map
[member_vnfd
['vnfd_id_ref']])
273 placement
= { pg_name
: {
274 'type': self
.T_PLACEMENT
,
275 self
.PROPERTIES
: pg_config
,
276 self
.TARGETS
: str(targets
)
279 self
.placement_groups
.append(placement
)
281 def process_vnffgd(vnffgs
, dic
):
282 associated_cp_names
= []
286 conn_point_to_conection_node
= {}
287 conn_point_to_vnf_name_map
= {}
289 unigue_id_forwarder_path_map
= OrderedDict()
290 forwarder_name_to_constitent_vnf_map
= OrderedDict()
291 unique_id_classifier_map
= OrderedDict()
295 vnffg_to_unique_id_rsp_map
= OrderedDict()
296 vnffg_to_unique_id_classifier_map
= OrderedDict()
297 vnffg_to_associated_cp_names
= OrderedDict()
298 rsp_associated_cp_names
= OrderedDict()
299 vnffg_to_forwarder_map
= OrderedDict()
301 unique_id_rsp_map
= {}
302 for rs
in vnffg
['rsp']:
303 unique_id_rsp_map
[str(rs
['id'])] = rs
304 for class_identifier
in vnffg
['classifier']:
305 unique_id_classifier_map
[str(class_identifier
['rsp_id_ref'])] = class_identifier
306 associated_cp_names
.append(class_identifier
['vnfd_connection_point_ref'])
307 all_cp_names
.append(class_identifier
['vnfd_connection_point_ref'])
308 conn_point_to_vnf_name_map
[class_identifier
['vnfd_connection_point_ref']] = self
.vnf_id_to_vnf_map
[class_identifier
['vnfd_id_ref']]
309 vnfd_sfc_map
[self
.vnf_id_to_vnf_map
[class_identifier
['vnfd_id_ref']]] = class_identifier
['vnfd_connection_point_ref']
311 rsp_associated_cp_names
[str(class_identifier
['rsp_id_ref'])] = class_identifier
['vnfd_connection_point_ref']
313 vnffg_to_unique_id_rsp_map
[vnffg
['name']] = unique_id_rsp_map
314 vnffg_to_forwarder_map
[vnffg
['name']] = []
321 prop
['type'] = self
.T_VNFFG
322 prop
[self
.DESC
] = "Test"
323 prop
[self
.PROPERTIES
] = {}
324 if 'vendor' in vnffg
:
325 prop
[self
.PROPERTIES
]['vendor'] = vnffg
['vendor']
327 self
.vnffgds
[vnffg
['name']] = prop
329 for rs_id
, rs
in vnffg_to_unique_id_rsp_map
[vnffg
['name']].items():
330 associated_cp_node_names
= []
331 associated_vnf_names
= []
332 number_of_endpoints
= 0
333 if 'vnfd_connection_point_ref' in rs
:
334 number_of_endpoints
= number_of_endpoints
+ len(rs
['vnfd_connection_point_ref'])
335 for vnf
in rs
['vnfd_connection_point_ref']:
336 associated_vnf_names
.append(str(self
.vnf_id_to_vnf_map
[vnf
['vnfd_id_ref']]))
337 associated_cp_names
.append(vnf
['vnfd_connection_point_ref'])
338 all_cp_names
.append(vnf
['vnfd_connection_point_ref'])
339 conn_point_to_vnf_name_map
[vnf
['vnfd_connection_point_ref']] = self
.vnf_id_to_vnf_map
[vnf
['vnfd_id_ref']]
340 if "forwarder{}".format(fp_path_count
) not in forwarder_name_to_constitent_vnf_map
:
341 forwarder_name_to_constitent_vnf_map
["forwarder{}".format(fp_path_count
)] = associated_vnf_names
342 vnffg_to_forwarder_map
[vnffg
['name']].append("forwarder{}".format(fp_path_count
))
343 fp_path_count
= fp_path_count
+ 1
345 associated_cp_names
= list(set(associated_cp_names
))
346 for cp_name
in associated_cp_names
:
347 for idx
, vnfd
in self
.vnfds
.items():
348 for vdu
in vnfd
.vdus
:
349 if cp_name
== rsp_associated_cp_names
[rs_id
]:
350 if cp_name
in vdu
.conn_point_to_conection_node
:
351 associated_cp_node_names
.append(vdu
.conn_point_to_conection_node
[cp_name
])
352 #conn_point_to_conection_node[cp_name] = vdu.conn_point_to_conection_node[cp_name]
354 for cp_name
in all_cp_names
:
355 for idx
, vnfd
in self
.vnfds
.items():
356 for vdu
in vnfd
.vdus
:
357 if cp_name
in vdu
.conn_point_to_conection_node
:
358 conn_point_to_conection_node
[cp_name
] = vdu
.conn_point_to_conection_node
[cp_name
]
360 if len(associated_vnf_names
) > 0:
361 associated_vnf_names
= list(set(associated_vnf_names
))
362 vnf_str
= ", ".join(associated_vnf_names
)
363 prop
[self
.PROPERTIES
]['constituent_vnfs'] = "[{}]".format(vnf_str
)
364 if len(associated_cp_node_names
) > 0:
365 associated_cp_node_names
= list(set(associated_cp_node_names
))
366 connection_point_str
= ", ".join(associated_cp_node_names
)
367 prop
[self
.PROPERTIES
]['connection_point'] = "[{}]".format(", ".join(associated_cp_node_names
))
369 prop
[self
.PROPERTIES
]['number_of_endpoints'] = number_of_endpoints
370 fp_name
= "Forwarding_path{}".format(forwarder_count
)
371 unigue_id_forwarder_path_map
[fp_name
] = rs_id
372 fp_members
.append(fp_name
)
373 forwarder_count
= forwarder_count
+ 1
375 if len(fp_members
) > 0:
377 for fp
in fp_members
:
378 prop
['members'].append(fp
)
381 for fp
, idx
in unigue_id_forwarder_path_map
.items():
382 for vnffg_name
, unique_id_rsp_map
in vnffg_to_unique_id_rsp_map
.items():
383 if idx
in unique_id_rsp_map
:
385 prop
['type'] = self
.T_FP
386 prop
[self
.PROPERTIES
] = {}
387 prop
[self
.PROPERTIES
][self
.DESC
] = "Forwarder"
388 prop
[self
.PROPERTIES
]['policy'] = {}
389 prop
[self
.PROPERTIES
]['policy']['type'] = 'ACL'
390 prop
[self
.PROPERTIES
]['policy']['criteria'] = []
392 prop
[self
.PROPERTIES
]['path'] = []
394 rsp
= unique_id_rsp_map
[idx
]
395 classifier
= unique_id_classifier_map
[idx
]
397 for match
in classifier
['match_attributes']:
399 if 'source_port' in match
:
400 port
= "'{}'".format((match
['source_port']))
401 prop
[self
.PROPERTIES
]['policy']['criteria'].append({'source_port_range': port
})
402 if 'destination_port' in match
:
403 port
= "'f'{}''".format((match
['destination_port']))
404 prop
[self
.PROPERTIES
]['policy']['criteria'].append({'destination_port_range': '5006'})
405 if 'ip_proto' in match
:
406 port
= match
['ip_proto']
407 prop
[self
.PROPERTIES
]['policy']['criteria'].append({'ip_proto': port
})
408 if 'destination_ip_address' in match
:
409 port
= "'{}'".format((match
['destination_ip_address']))
410 prop
[self
.PROPERTIES
]['policy']['criteria'].append({'ip_dst_prefix': port
})
412 if 'vnfd_connection_point_ref' in classifier
:
413 if classifier
['vnfd_connection_point_ref'] in conn_point_to_vnf_name_map
:
414 if 'cp' not in prop
[self
.PROPERTIES
]:
415 prop
[self
.PROPERTIES
]['cp'] = {}
416 prop
[self
.PROPERTIES
]['cp']['forwarder'] = conn_point_to_vnf_name_map
[classifier
['vnfd_connection_point_ref']]
417 prop
[self
.PROPERTIES
]['cp']['capability'] = conn_point_to_conection_node
[classifier
['vnfd_connection_point_ref']]
419 for fp
, vnf_list
in forwarder_name_to_constitent_vnf_map
.items():
421 for cp
, vnf_name
in conn_point_to_vnf_name_map
.items():
423 self
.substitution_mapping_forwarder
.append((vnf
, fp
, conn_point_to_conection_node
[cp
]))
425 visited_forwarder
= []
427 for path
, vnfs
in forwarder_name_to_constitent_vnf_map
.items():
429 if (vnf
not in visited_forwarder
) and (path
in vnffg_to_forwarder_map
[vnffg_name
]):
431 path_prop
['forwarder'] = vnf
432 path_prop
['capability'] = path
433 prop
[self
.PROPERTIES
]['path'].append(path_prop
)
434 visited_forwarder
.append(vnf
)
436 forwarder_name_to_constitent_vnf_map
.pop(visited_path
)
438 self
.forwarding_paths
["Forwarding_path{}".format(fp_count
)] = prop
439 fp_count
= fp_count
+1
441 self
.vnfd_sfc_map
= vnfd_sfc_map
443 dic
= deepcopy(self
.yang
)
445 for key
in self
.REQUIRED_FIELDS
:
447 self
.props
[key
] = dic
.pop(key
)
449 self
.id = self
.props
[self
.ID
]
451 # Process constituent VNFDs
454 member_vnf_index_list
= []
455 if self
.CONST_VNFD
in dic
:
456 for cvnfd
in dic
.pop(self
.CONST_VNFD
):
457 if cvnfd
[self
.VNFD_ID_REF
] not in member_vnf_index_list
:
458 member_vnf_index_list
.append(cvnfd
[self
.VNFD_ID_REF
])
459 process_const_vnfd(cvnfd
)
461 self
.duplicate_vnfd_name_list
.append(self
.vnf_id_to_vnf_map
[cvnfd
[self
.VNFD_ID_REF
]])
465 for vld_dic
in dic
.pop(self
.VLD
):
466 process_vld(vld_dic
, dic
)
467 #self.vlds.append(vld)
470 if self
.VNFFGD
in dic
:
471 process_vnffgd(dic
[self
.VNFFGD
], dic
)
476 # Process initial config primitives
477 if self
.INITIAL_CFG
in dic
:
478 for icp_dic
in dic
.pop(self
.INITIAL_CFG
):
479 process_initial_config(icp_dic
)
481 # NS service prmitive
482 if self
.CONF_PRIM
in dic
:
483 for icp_dic
in dic
.pop(self
.CONF_PRIM
):
484 process_service_primitive(icp_dic
)
486 # Process scaling group
487 if self
.SCALE_GRP
in dic
:
488 for sg_dic
in dic
.pop(self
.SCALE_GRP
):
489 process_scale_grp(sg_dic
)
491 # Process the input params
492 if self
.INPUT_PARAM_XPATH
in dic
:
493 for param
in dic
.pop(self
.INPUT_PARAM_XPATH
):
494 process_input_param(param
)
496 if 'placement_groups' in dic
:
497 process_placement_group(dic
['placement_groups'])
500 self
.remove_ignored_fields(dic
)
502 self
.log
.warn(_("{0}, Did not process the following for "
504 format(self
, self
.props
, dic
))
505 self
.log
.debug(_("{0}, NSD: {1}").format(self
, self
.props
))
506 except Exception as e
:
507 err_msg
= _("Exception processing NSD {0} : {1}"). \
509 self
.log
.error(err_msg
)
510 self
.log
.exception(e
)
511 raise ValidationError(message
=err_msg
)
513 def generate_tosca_type(self
):
515 self
.log
.debug(_("{0} Generate tosa types").
519 #tosca[self.DATA_TYPES] = {}
520 #tosca[self.NODE_TYPES] = {}
522 for idx
, vnfd
in self
.vnfds
.items():
523 tosca
= vnfd
.generate_tosca_type(tosca
)
525 for vld
in self
.vlds
:
526 tosca
= vld
.generate_tosca_type(tosca
)
528 # Generate type for config primitives
529 if self
.GROUP_TYPES
not in tosca
:
530 tosca
[self
.GROUP_TYPES
] = {}
531 if self
.T_CONF_PRIM
not in tosca
[self
.GROUP_TYPES
]:
532 tosca
[self
.GROUP_TYPES
][self
.T_CONF_PRIM
] = {
533 self
.DERIVED_FROM
: 'tosca.policies.Root',
535 'primitive': self
.MAP
538 # Generate type for scaling group
539 if self
.POLICY_TYPES
not in tosca
:
540 tosca
[self
.POLICY_TYPES
] = {}
541 if self
.T_SCALE_GRP
not in tosca
[self
.POLICY_TYPES
]:
542 tosca
[self
.POLICY_TYPES
][self
.T_SCALE_GRP
] = {
543 self
.DERIVED_FROM
: 'tosca.policies.Root',
546 {self
.TYPE
: self
.STRING
},
548 {self
.TYPE
: self
.INTEGER
},
550 {self
.TYPE
: self
.INTEGER
},
552 {self
.TYPE
: self
.MAP
},
554 {self
.TYPE
: self
.MAP
}
557 if self
.T_INITIAL_CFG
not in tosca
[self
.POLICY_TYPES
]:
558 tosca
[self
.POLICY_TYPES
][self
.T_INITIAL_CFG
] = {
559 self
.DERIVED_FROM
: 'tosca.policies.Root',
562 {self
.TYPE
: self
.STRING
},
564 {self
.TYPE
: self
.INTEGER
},
565 self
.USER_DEF_SCRIPT
:
566 {self
.TYPE
: self
.STRING
},
568 {self
.TYPE
: self
.MAP
},
573 def generate_tosca_template(self
, tosca
):
574 self
.log
.debug(_("{0}, Generate tosca template").
576 # Add the standard entries
577 tosca
['tosca_definitions_version'] = \
578 'tosca_simple_profile_for_nfv_1_0'
579 tosca
[self
.DESC
] = self
.props
[self
.DESC
]
580 tosca
[self
.METADATA
] = {
582 self
.VENDOR
: self
.props
[self
.VENDOR
],
583 self
.VERSION
: self
.props
[self
.VERSION
],
585 if self
.LOGO
in self
.props
:
586 tosca
[self
.METADATA
][self
.LOGO
] = self
.props
[self
.LOGO
]
588 if len(self
.vnfd_files
) > 0:
589 tosca
[self
.IMPORT
] = []
591 for vnfd_file
in set(self
.vnfd_files
):
592 tosca
[self
.IMPORT
].append('"{0}.yaml"'.format(vnfd_file
))
594 tosca
[self
.TOPOLOGY_TMPL
] = {}
599 if self.INPUTS not in tosca[self.TOPOLOGY_TMPL]:
600 tosca[self.TOPOLOGY_TMPL][self.INPUTS] = {}
601 for inp in self.inputs:
602 entry = {inp[self.NAME]: {self.TYPE: self.STRING,
604 'Translated from YANG'}}
605 tosca[self.TOPOLOGY_TMPL][self.INPUTS] = entry
607 tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
] = {}
609 # Add the VNFDs and VLDs
610 vnf_type_vld_list
= []
611 for idx
, vnfd
in self
.vnfds
.items():
612 #vnfd.generate_vnf_template(tosca, idx)
614 'type' : vnfd
.vnf_type
,
617 self
.VENDOR
: self
.props
[self
.VENDOR
],
618 self
.VERSION
: self
.props
[self
.VERSION
]
621 if vnfd
.name
in self
.vnf_to_vld_map
:
622 vld_list
= self
.vnf_to_vld_map
[vnfd
.name
]
623 node
[self
.REQUIREMENTS
] = []
625 for vld_idx
in range(0, len(vld_list
)):
626 if vnfd
.vnf_type
not in vnf_type_vld_list
:
627 vld_link_name
= "{0}{1}".format("virtualLink", vld_idx
+ 1)
629 vld_prop
[vld_link_name
] = vld_list
[vld_idx
]
630 node
[self
.REQUIREMENTS
].append(vld_prop
)
631 if vnfd
.vnf_type
not in vnf_type_vld_list
:
632 vnf_type_vld_list
.append(vnfd
.vnf_type
)
633 if vnfd
.name
in self
._vnf
_vld
_conn
_point
_map
:
634 vnf_vld_list
= set(self
._vnf
_vld
_conn
_point
_map
[vnfd
.name
])
635 for vnf_vld
in vnf_vld_list
:
636 vnfd
.generate_vld_link(vld_link_name
, vnf_vld
[1])
638 for sub_mapping
in self
.substitution_mapping_forwarder
:
639 if sub_mapping
[0] == vnfd
.name
:
640 vnfd
.generate_forwarder_sub_mapping(sub_mapping
)
642 if self
.vnfd_sfc_map
:
643 for vnfd_name
, cp_name
in self
.vnfd_sfc_map
.items():
644 if vnfd
.name
== vnfd_name
:
645 vnfd
.generate_sfc_link(cp_name
)
649 tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
][vnfd
.name
] = node
651 v_idx
= len(self
.vnfds
) + 1 + len(self
.duplicate_vnfd_name_list
)
652 for vnfd_name
in self
.duplicate_vnfd_name_list
:
653 node
= tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
][vnfd_name
]
654 new_node
= deepcopy(node
)
655 st
= re
.sub(r
'\d+$', '', vnfd_name
.rstrip('_vnfd'))
657 new_node
[self
.PROPERTIES
][self
.ID
] = v_idx
658 node_name
= "{}{}_vnfd".format(st
, v_idx
)
659 tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
][node_name
] = new_node
662 for vld_node_name
in self
.vlds
:
663 tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
][vld_node_name
] = self
.vlds
[vld_node_name
]
665 for fp_name
, fp
in self
.forwarding_paths
.items():
666 tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
][fp_name
] = fp
668 # add the config primitives
669 if len(self
.conf_prims
):
670 if self
.GROUPS
not in tosca
[self
.TOPOLOGY_TMPL
]:
671 tosca
[self
.TOPOLOGY_TMPL
][self
.GROUPS
] = {}
674 self
.TYPE
: self
.T_CONF_PRIM
676 conf_prims
[self
.MEMBERS
] = [vnfd
.name
for vnfd
in
679 for confp
in self
.conf_prims
:
680 prims
[confp
[self
.NAME
]] = {
681 self
.USER_DEF_SCRIPT
: confp
[self
.USER_DEF_SCRIPT
]
683 conf_prims
[self
.PROPERTIES
] = {
684 self
.PRIMITIVES
: prims
686 conf_prims
[self
.DESC
] = 'Test'
687 #tosca[self.TOPOLOGY_TMPL][self.GROUPS][self.CONF_PRIM] = conf_prims
690 # Add the scale group
691 if len(self
.scale_grps
):
692 if self
.POLICIES
not in tosca
[self
.TOPOLOGY_TMPL
]:
693 tosca
[self
.TOPOLOGY_TMPL
][self
.POLICIES
] = []
695 for sg
in self
.scale_grps
:
697 self
.TYPE
: self
.T_SCALE_GRP
,
700 tosca
[self
.TOPOLOGY_TMPL
][self
.POLICIES
].append({
704 # Add initial configs
705 if len(self
.initial_cfg
):
706 if self
.POLICIES
not in tosca
[self
.TOPOLOGY_TMPL
]:
707 tosca
[self
.TOPOLOGY_TMPL
][self
.POLICIES
] = []
709 for icp
in self
.initial_cfg
:
710 if len(tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
]) > 0:
711 node_name
= list(tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
].keys())[0]
713 self
.TYPE
: self
.T_INITIAL_CFG
,
714 self
.TARGETS
: "[{0}]".format(node_name
)
717 tosca
[self
.TOPOLOGY_TMPL
][self
.POLICIES
].append({
718 self
.INITIAL_CFG
: icpt
721 if len(self
.service_primitive
) > 0:
722 if self
.POLICIES
not in tosca
[self
.TOPOLOGY_TMPL
]:
723 tosca
[self
.TOPOLOGY_TMPL
][self
.POLICIES
] = []
725 for icp
in self
.service_primitive
:
726 if len(tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
]) > 0:
727 node_name
= list(tosca
[self
.TOPOLOGY_TMPL
][self
.NODE_TMPL
].keys())[0]
729 self
.TYPE
: self
.T_NS_PRIMITIVE
,
730 self
.TARGETS
: "[{0}]".format(node_name
)
733 tosca
[self
.TOPOLOGY_TMPL
][self
.POLICIES
].append({
734 'ns_service_primitives': icpt
738 if len(self
.placement_groups
) > 0:
739 if self
.POLICIES
not in tosca
[self
.TOPOLOGY_TMPL
]:
740 tosca
[self
.TOPOLOGY_TMPL
][self
.POLICIES
] = []
742 for placment_group
in self
.placement_groups
:
743 tosca
[self
.TOPOLOGY_TMPL
][self
.POLICIES
].append(placment_group
)
745 if len(self
.vnffgds
) > 0:
746 if self
.GROUPS
not in tosca
[self
.TOPOLOGY_TMPL
]:
747 tosca
[self
.TOPOLOGY_TMPL
][self
.GROUPS
] = {}
748 for vnffgd_name
in self
.vnffgds
:
749 tosca
[self
.TOPOLOGY_TMPL
][self
.GROUPS
][vnffgd_name
] = self
.vnffgds
[vnffgd_name
]
754 def get_supporting_files(self
):
756 # Get the config files for initial config
757 for icp
in self
.initial_cfg
:
758 if 'properties' in icp
:
759 if 'user_defined_script' in icp
['properties']:
760 script
= os
.path
.basename(icp
['properties']['user_defined_script'])
764 self
.DEST
: "{}/{}".format(self
.SCRIPT_DIR
, script
),
767 for prim
in self
.service_primitive
:
768 if 'properties' in prim
:
769 if 'user_defined_script' in prim
['properties']:
770 script
= os
.path
.basename(prim
['properties']['user_defined_script'])
774 self
.DEST
: "{}/{}".format(self
.SCRIPT_DIR
, script
),
777 if 'logo' in self
.props
:
778 icon
= os
.path
.basename(self
.props
['logo'])
782 self
.DEST
: "{}/{}".format(self
.ICON_DIR
, icon
),
786 # TODO (pjoseph): Add support for config scripts,
789 self
.log
.debug(_("{0}, supporting files: {1}").format(self
, files
))