1 package org.openecomp.sdc.toscaparser.api;
3 import java.util.ArrayList;
4 import java.util.LinkedHashMap;
8 import org.openecomp.sdc.toscaparser.api.elements.*;
9 import org.openecomp.sdc.toscaparser.api.utils.CopyUtils;
10 import org.openecomp.sdc.toscaparser.api.utils.ThreadLocalsHolder;
12 public class NodeTemplate extends EntityTemplate {
14 private LinkedHashMap<String,Object> templates;
15 private LinkedHashMap<String,Object> customDef;
16 private ArrayList<RelationshipTemplate> availableRelTpls;
17 private LinkedHashMap<String,Object> availableRelTypes;
18 private LinkedHashMap<NodeTemplate,RelationshipType> related;
19 private ArrayList<RelationshipTemplate> relationshipTpl;
20 private LinkedHashMap<RelationshipType,NodeTemplate> _relationships;
21 private SubstitutionMappings subMappingToscaTemplate;
22 private Metadata metadata;
24 private static final String METADATA = "metadata";
26 @SuppressWarnings("unchecked")
27 public NodeTemplate(String name,
28 LinkedHashMap<String,Object> ntnodeTemplates,
29 LinkedHashMap<String,Object> ntcustomDef,
30 ArrayList<RelationshipTemplate> ntavailableRelTpls,
31 LinkedHashMap<String,Object> ntavailableRelTypes) {
33 super(name, (LinkedHashMap<String,Object>)ntnodeTemplates.get(name), "node_type", ntcustomDef);
35 templates = ntnodeTemplates;
36 _validateFields((LinkedHashMap<String,Object>)templates.get(name));
37 customDef = ntcustomDef;
38 related = new LinkedHashMap<NodeTemplate,RelationshipType>();
39 relationshipTpl = new ArrayList<RelationshipTemplate>();
40 availableRelTpls = ntavailableRelTpls;
41 availableRelTypes = ntavailableRelTypes;
42 _relationships = new LinkedHashMap<RelationshipType,NodeTemplate>();
43 subMappingToscaTemplate = null;
44 metadata = _metaData();
47 @SuppressWarnings("unchecked")
48 public LinkedHashMap<RelationshipType,NodeTemplate> getRelationships() {
49 if(_relationships.isEmpty()) {
50 List<RequirementAssignment> requires = getRequirements().getAll();
51 if(requires != null && requires instanceof List) {
52 for(RequirementAssignment r: requires) {
53 LinkedHashMap<RelationshipType,NodeTemplate> explicit = _getExplicitRelationship(r);
54 if(explicit != null) {
55 // _relationships.putAll(explicit)...
56 for(Map.Entry<RelationshipType,NodeTemplate> ee: explicit.entrySet()) {
57 _relationships.put(ee.getKey(), ee.getValue());
63 return _relationships;
66 @SuppressWarnings("unchecked")
67 private LinkedHashMap<RelationshipType,NodeTemplate> _getExplicitRelationship(RequirementAssignment req) {
68 // Handle explicit relationship
73 // relationship: tosca.relationships.HostedOn
75 LinkedHashMap<RelationshipType,NodeTemplate> explicitRelation = new LinkedHashMap<RelationshipType,NodeTemplate>();
76 String node = req.getNodeTemplateName();
78 if(node != null && !node.isEmpty()) {
79 //msg = _('Lookup by TOSCA types is not supported. '
80 // 'Requirement for "%s" can not be full-filled.') % self.name
81 boolean bFound = false;
82 for(String k: EntityType.TOSCA_DEF.keySet()) {
88 if(bFound || customDef.get(node) != null) {
89 ThreadLocalsHolder.getCollector().appendException(String.format(
90 "NotImplementedError: Lookup by TOSCA types is not supported. Requirement for \"%s\" can not be full-filled",
94 if(templates.get(node) == null) {
95 ThreadLocalsHolder.getCollector().appendException(String.format(
96 "KeyError: Node template \"%s\" was not found",node));
99 NodeTemplate relatedTpl = new NodeTemplate(node,templates,customDef,null,null);
100 Object relationship = req.getRelationship();
101 String relationshipString = null;
102 // // here relationship can be a string or a LHM with 'type':<relationship>
104 // check if its type has relationship defined
105 if(relationship == null) {
106 ArrayList<Object> parentReqs = ((NodeType)typeDefinition).getAllRequirements();
107 if(parentReqs == null) {
108 ThreadLocalsHolder.getCollector().appendException("ValidationError: parent_req is null");
111 // for(String key: req.keySet()) {
112 // boolean bFoundRel = false;
113 for(Object rdo: parentReqs) {
114 LinkedHashMap<String,Object> reqDict = (LinkedHashMap<String,Object>)rdo;
115 LinkedHashMap<String,Object> relDict = (LinkedHashMap<String,Object>)reqDict.get(req.getName());
116 if(relDict != null) {
117 relationship = relDict.get("relationship");
118 //BUG-python??? need to break twice?
130 if(relationship != null) {
131 // here relationship can be a string or a LHM with 'type':<relationship>
132 if(relationship instanceof String) {
133 relationshipString = (String)relationship;
135 else if(relationship instanceof LinkedHashMap) {
136 relationshipString = (String)((LinkedHashMap<String,Object>)relationship).get("type");
139 boolean foundRelationshipTpl = false;
140 // apply available relationship templates if found
141 if(availableRelTpls != null) {
142 for(RelationshipTemplate tpl: availableRelTpls) {
143 if(tpl.getName().equals(relationshipString)) {
144 RelationshipType rtype = new RelationshipType(tpl.getType(),null,customDef);
145 explicitRelation.put(rtype, relatedTpl);
146 tpl.setTarget(relatedTpl);
148 relationshipTpl.add(tpl);
149 foundRelationshipTpl = true;
153 // create relationship template object.
154 String relPrfx = EntityType.RELATIONSHIP_PREFIX;
155 if(!foundRelationshipTpl) {
156 if(relationship instanceof LinkedHashMap) {
157 relationshipString = (String)((LinkedHashMap<String,Object>)relationship).get("type");
158 if(relationshipString != null) {
159 if(availableRelTypes != null && !availableRelTypes.isEmpty() &&
160 availableRelTypes.get(relationshipString) != null) {
163 else if(!(relationshipString).startsWith(relPrfx)) {
164 relationshipString = relPrfx + relationshipString;
168 ThreadLocalsHolder.getCollector().appendException(String.format(
169 "MissingRequiredFieldError: \"relationship\" used in template \"%s\" is missing required field \"type\"",
170 relatedTpl.getName()));
173 for(RelationshipType rtype: ((NodeType)typeDefinition).getRelationship().keySet()) {
174 if(rtype.getType().equals(relationshipString)) {
175 explicitRelation.put(rtype,relatedTpl);
176 relatedTpl._addRelationshipTemplate(req,rtype.getType(),this);
178 else if(availableRelTypes != null && !availableRelTypes.isEmpty()) {
179 LinkedHashMap<String,Object> relTypeDef = (LinkedHashMap<String,Object>)availableRelTypes.get(relationshipString);
180 if(relTypeDef != null) {
181 String superType = (String)relTypeDef.get("derived_from");
182 if(superType != null) {
183 if(!superType.startsWith(relPrfx)) {
184 superType = relPrfx + superType;
186 if(rtype.getType().equals(superType)) {
187 explicitRelation.put(rtype,relatedTpl);
188 relatedTpl._addRelationshipTemplate(req,rtype.getType(),this);
197 return explicitRelation;
200 @SuppressWarnings("unchecked")
201 private void _addRelationshipTemplate(RequirementAssignment requirement, String rtype, NodeTemplate source) {
202 LinkedHashMap<String,Object> req = new LinkedHashMap<>();
203 req.put("relationship", CopyUtils.copyLhmOrAl(requirement.getRelationship()));
204 req.put("type",rtype);
205 RelationshipTemplate tpl = new RelationshipTemplate(req, rtype, customDef, this, source);
206 relationshipTpl.add(tpl);
209 public ArrayList<RelationshipTemplate> getRelationshipTemplate() {
210 return relationshipTpl;
213 void _addNext(NodeTemplate nodetpl,RelationshipType relationship) {
214 related.put(nodetpl,relationship);
217 public ArrayList<NodeTemplate> getRelatedNodes() {
218 if(related.isEmpty()) {
219 for(Map.Entry<RelationshipType,NodeType> me: ((NodeType)typeDefinition).getRelationship().entrySet()) {
220 RelationshipType relation = me.getKey();
221 NodeType node = me.getValue();
222 for(String tpl: templates.keySet()) {
223 if(tpl.equals(node.getType())) {
225 // self.related[NodeTemplate(tpl)] = relation
226 // but NodeTemplate doesn't have a constructor with just name...
228 related.put(new NodeTemplate(tpl,null,null,null,null),relation);
233 return new ArrayList<NodeTemplate>(related.keySet());
236 public void validate(/*tosca_tpl=none is not used...*/) {
237 _validateCapabilities();
238 _validateRequirements();
239 _validateProperties(entityTpl,(NodeType)typeDefinition);
240 _validateInterfaces();
241 for(Property prop: getPropertiesObjects()) {
246 private Metadata _metaData() {
247 if(entityTpl.get(METADATA) != null) {
248 return new Metadata((Map<String,Object>)entityTpl.get(METADATA));
255 @SuppressWarnings("unchecked")
256 private void _validateRequirements() {
257 ArrayList<Object> typeRequires = ((NodeType)typeDefinition).getAllRequirements();
258 ArrayList<String> allowedReqs = new ArrayList<>();
259 allowedReqs.add("template");
260 if(typeRequires != null) {
261 for(Object to: typeRequires) {
262 LinkedHashMap<String,Object> treq = (LinkedHashMap<String,Object>)to;
263 for(Map.Entry<String,Object> me: treq.entrySet()) {
264 String key = me.getKey();
265 Object value = me.getValue();
266 allowedReqs.add(key);
267 if(value instanceof LinkedHashMap) {
268 allowedReqs.addAll(((LinkedHashMap<String,Object>)value).keySet());
275 ArrayList<Object> requires = (ArrayList<Object>)((NodeType)typeDefinition).getValue(REQUIREMENTS, entityTpl, false);
276 if(requires != null) {
277 if(!(requires instanceof ArrayList)) {
278 ThreadLocalsHolder.getCollector().appendException(String.format(
279 "TypeMismatchError: \"requirements\" of template \"%s\" are not of type \"list\"",name));
282 for(Object ro: requires) {
283 LinkedHashMap<String,Object> req = (LinkedHashMap<String,Object>)ro;
284 for(Map.Entry<String,Object> me: req.entrySet()) {
285 String rl = me.getKey();
286 Object vo = me.getValue();
287 if(vo instanceof LinkedHashMap) {
288 LinkedHashMap<String,Object> value = (LinkedHashMap<String,Object>)vo;
289 _validateRequirementsKeys(value);
290 _validateRequirementsProperties(value);
294 _commonValidateField(req,allowedReqs,"requirements");
300 @SuppressWarnings("unchecked")
301 private void _validateRequirementsProperties(LinkedHashMap<String,Object> reqs) {
302 // TO-DO(anyone): Only occurrences property of the requirements is
303 // validated here. Validation of other requirement properties are being
304 // validated in different files. Better to keep all the requirements
305 // properties validation here.
306 for(Map.Entry<String,Object> me: reqs.entrySet()) {
307 if(me.getKey().equals("occurrences")) {
308 ArrayList<Object> val = (ArrayList<Object>)me.getValue();
309 _validateOccurrences(val);
315 private void _validateOccurrences(ArrayList<Object> occurrences) {
316 DataEntity.validateDatatype("list",occurrences,null,null,null);
317 for(Object val: occurrences) {
318 DataEntity.validateDatatype("Integer",val,null,null,null);
320 if(occurrences.size() != 2 ||
321 !(0 <= (int)occurrences.get(0) && (int)occurrences.get(0) <= (int)occurrences.get(1)) ||
322 (int)occurrences.get(1) == 0) {
323 ThreadLocalsHolder.getCollector().appendException(String.format(
324 "InvalidPropertyValueError: property has invalid value %s",occurrences.toString()));
328 private void _validateRequirementsKeys(LinkedHashMap<String,Object> reqs) {
329 for(String key: reqs.keySet()) {
330 boolean bFound = false;
331 for(int i=0; i< REQUIREMENTS_SECTION.length; i++) {
332 if(key.equals(REQUIREMENTS_SECTION[i])) {
338 ThreadLocalsHolder.getCollector().appendException(String.format(
339 "UnknownFieldError: \"requirements\" of template \"%s\" contains unknown field \"%s\"",name,key));
344 @SuppressWarnings("unchecked")
345 private void _validateInterfaces() {
346 LinkedHashMap<String,Object> ifaces = (LinkedHashMap<String,Object>)
347 ((NodeType)typeDefinition).getValue(INTERFACES, entityTpl, false);
349 for(Map.Entry<String,Object> me: ifaces.entrySet()) {
350 String iname = me.getKey();
351 LinkedHashMap<String,Object> value = (LinkedHashMap<String,Object>)me.getValue();
352 if(iname.equals(InterfacesDef.LIFECYCLE) || iname.equals(InterfacesDef.LIFECYCLE_SHORTNAME)) {
353 // maybe we should convert [] to arraylist???
354 ArrayList<String> inlo = new ArrayList<>();
355 for(int i=0; i<InterfacesDef.interfacesNodeLifecycleOperations.length; i++) {
356 inlo.add(InterfacesDef.interfacesNodeLifecycleOperations[i]);
358 _commonValidateField(value,inlo,"interfaces");
360 else if(iname.equals(InterfacesDef.CONFIGURE) || iname.equals(InterfacesDef.CONFIGURE_SHORTNAME)) {
361 // maybe we should convert [] to arraylist???
362 ArrayList<String> irco = new ArrayList<>();
363 for(int i=0; i<InterfacesDef.interfacesRelationshipConfigureOperations.length; i++) {
364 irco.add(InterfacesDef.interfacesRelationshipConfigureOperations[i]);
366 _commonValidateField(value,irco,"interfaces");
368 else if(((NodeType)typeDefinition).getInterfaces().keySet().contains(iname)) {
369 _commonValidateField(value,_collectCustomIfaceOperations(iname),"interfaces");
372 ThreadLocalsHolder.getCollector().appendException(String.format(
373 "UnknownFieldError: \"interfaces\" of template \"%s\" contains unknown field %s",name,iname));
379 @SuppressWarnings("unchecked")
380 private ArrayList<String> _collectCustomIfaceOperations(String iname) {
381 ArrayList<String> allowedOperations = new ArrayList<>();
382 LinkedHashMap<String,Object> nodetypeIfaceDef = (LinkedHashMap<String,Object>)((NodeType)
383 typeDefinition).getInterfaces().get(iname);
384 allowedOperations.addAll(nodetypeIfaceDef.keySet());
385 String ifaceType = (String)nodetypeIfaceDef.get("type");
386 if(ifaceType != null) {
387 LinkedHashMap<String,Object> ifaceTypeDef = null;
388 if(((NodeType)typeDefinition).customDef != null) {
389 ifaceTypeDef = (LinkedHashMap<String,Object>)((NodeType)typeDefinition).customDef.get(ifaceType);
391 if(ifaceTypeDef == null) {
392 ifaceTypeDef = (LinkedHashMap<String,Object>)EntityType.TOSCA_DEF.get(ifaceType);
394 allowedOperations.addAll(ifaceTypeDef.keySet());
396 // maybe we should convert [] to arraylist???
397 ArrayList<String> idrw = new ArrayList<>();
398 for(int i=0; i<InterfacesDef.INTERFACE_DEF_RESERVED_WORDS.length; i++) {
399 idrw.add(InterfacesDef.INTERFACE_DEF_RESERVED_WORDS[i]);
401 allowedOperations.removeAll(idrw);
402 return allowedOperations;
405 private void _validateFields(LinkedHashMap<String,Object> nodetemplate) {
406 for(String ntname: nodetemplate.keySet()) {
407 boolean bFound = false;
408 for(int i=0; i< SECTIONS.length; i++) {
409 if(ntname.equals(SECTIONS[i])) {
415 for(int i=0; i< SPECIAL_SECTIONS.length; i++) {
416 if(ntname.equals(SPECIAL_SECTIONS[i])) {
424 ThreadLocalsHolder.getCollector().appendException(String.format(
425 "UnknownFieldError: Node template \"%s\" has unknown field \"%s\"",name,ntname));
432 // multilevel nesting
433 public SubstitutionMappings getSubMappingToscaTemplate() {
434 return subMappingToscaTemplate;
437 public void setSubMappingToscaTemplate(SubstitutionMappings sm) {
438 subMappingToscaTemplate = sm;
441 public Metadata getMetaData() {
445 public void setMetaData(Metadata metadata) {
446 this.metadata = metadata;
450 public String toString() {
458 from toscaparser.common.exception import ExceptionCollector
459 from toscaparser.common.exception import InvalidPropertyValueError
460 from toscaparser.common.exception import MissingRequiredFieldError
461 from toscaparser.common.exception import TypeMismatchError
462 from toscaparser.common.exception import UnknownFieldError
463 from toscaparser.common.exception import ValidationError
464 from toscaparser.dataentity import DataEntity
465 from toscaparser.elements.interfaces import CONFIGURE
466 from toscaparser.elements.interfaces import CONFIGURE_SHORTNAME
467 from toscaparser.elements.interfaces import INTERFACE_DEF_RESERVED_WORDS
468 from toscaparser.elements.interfaces import InterfacesDef
469 from toscaparser.elements.interfaces import LIFECYCLE
470 from toscaparser.elements.interfaces import LIFECYCLE_SHORTNAME
471 from toscaparser.elements.relationshiptype import RelationshipType
472 from toscaparser.entity_template import EntityTemplate
473 from toscaparser.relationship_template import RelationshipTemplate
474 from toscaparser.utils.gettextutils import _
476 log = logging.getLogger('tosca')
479 class NodeTemplate(EntityTemplate):
480 '''Node template from a Tosca profile.'''
481 def __init__(self, name, node_templates, custom_def=None,
482 available_rel_tpls=None, available_rel_types=None):
483 super(NodeTemplate, self).__init__(name, node_templates[name],
486 self.templates = node_templates
487 self._validate_fields(node_templates[name])
488 self.custom_def = custom_def
490 self.relationship_tpl = []
491 self.available_rel_tpls = available_rel_tpls
492 self.available_rel_types = available_rel_types
493 self._relationships = {}
494 self.sub_mapping_tosca_template = None
497 def relationships(self):
498 if not self._relationships:
499 requires = self.requirements
500 if requires and isinstance(requires, list):
502 for r1, value in r.items():
503 explicit = self._get_explicit_relationship(r, value)
505 for key, value in explicit.items():
506 self._relationships[key] = value
507 return self._relationships
509 def _get_explicit_relationship(self, req, value):
510 """Handle explicit relationship
515 relationship: tosca.relationships.HostedOn
517 explicit_relation = {}
518 node = value.get('node') if isinstance(value, dict) else value
521 # TO-DO(spzala) implement look up once Glance meta data is available
522 # to find a matching TOSCA node using the TOSCA types
523 msg = _('Lookup by TOSCA types is not supported. '
524 'Requirement for "%s" can not be full-filled.') % self.name
525 if (node in list(self.type_definition.TOSCA_DEF.keys())
526 or node in self.custom_def):
527 ExceptionCollector.appendException(NotImplementedError(msg))
530 if node not in self.templates:
531 ExceptionCollector.appendException(
532 KeyError(_('Node template "%s" was not found.') % node))
535 related_tpl = NodeTemplate(node, self.templates, self.custom_def)
536 relationship = value.get('relationship') \
537 if isinstance(value, dict) else None
538 # check if it's type has relationship defined
540 parent_reqs = self.type_definition.get_all_requirements()
541 if parent_reqs is None:
542 ExceptionCollector.appendException(
543 ValidationError(message='parent_req is ' +
546 for key in req.keys():
547 for req_dict in parent_reqs:
548 if key in req_dict.keys():
549 relationship = (req_dict.get(key).
553 found_relationship_tpl = False
554 # apply available relationship templates if found
555 if self.available_rel_tpls:
556 for tpl in self.available_rel_tpls:
557 if tpl.name == relationship:
558 rtype = RelationshipType(tpl.type, None,
560 explicit_relation[rtype] = related_tpl
561 tpl.target = related_tpl
563 self.relationship_tpl.append(tpl)
564 found_relationship_tpl = True
565 # create relationship template object.
566 rel_prfx = self.type_definition.RELATIONSHIP_PREFIX
567 if not found_relationship_tpl:
568 if isinstance(relationship, dict):
569 relationship = relationship.get('type')
571 if self.available_rel_types and \
572 relationship in self.available_rel_types.keys():
574 elif not relationship.startswith(rel_prfx):
575 relationship = rel_prfx + relationship
577 ExceptionCollector.appendException(
578 MissingRequiredFieldError(
579 what=_('"relationship" used in template '
580 '"%s"') % related_tpl.name,
582 for rtype in self.type_definition.relationship.keys():
583 if rtype.type == relationship:
584 explicit_relation[rtype] = related_tpl
585 related_tpl._add_relationship_template(req,
588 elif self.available_rel_types:
589 if relationship in self.available_rel_types.keys():
590 rel_type_def = self.available_rel_types.\
592 if 'derived_from' in rel_type_def:
594 rel_type_def.get('derived_from')
595 if not super_type.startswith(rel_prfx):
596 super_type = rel_prfx + super_type
597 if rtype.type == super_type:
598 explicit_relation[rtype] = related_tpl
600 _add_relationship_template(
601 req, rtype.type, self)
602 return explicit_relation
604 def _add_relationship_template(self, requirement, rtype, source):
605 req = requirement.copy()
607 tpl = RelationshipTemplate(req, rtype, self.custom_def, self, source)
608 self.relationship_tpl.append(tpl)
610 def get_relationship_template(self):
611 return self.relationship_tpl
613 def _add_next(self, nodetpl, relationship):
614 self.related[nodetpl] = relationship
617 def related_nodes(self):
619 for relation, node in self.type_definition.relationship.items():
620 for tpl in self.templates:
622 self.related[NodeTemplate(tpl)] = relation
623 return self.related.keys()
625 def validate(self, tosca_tpl=None):
626 self._validate_capabilities()
627 self._validate_requirements()
628 self._validate_properties(self.entity_tpl, self.type_definition)
629 self._validate_interfaces()
630 for prop in self.get_properties_objects():
633 def _validate_requirements(self):
634 type_requires = self.type_definition.get_all_requirements()
635 allowed_reqs = ["template"]
637 for treq in type_requires:
638 for key, value in treq.items():
639 allowed_reqs.append(key)
640 if isinstance(value, dict):
642 allowed_reqs.append(key)
644 requires = self.type_definition.get_value(self.REQUIREMENTS,
647 if not isinstance(requires, list):
648 ExceptionCollector.appendException(
650 what='"requirements" of template "%s"' % self.name,
654 for r1, value in req.items():
655 if isinstance(value, dict):
656 self._validate_requirements_keys(value)
657 self._validate_requirements_properties(value)
658 allowed_reqs.append(r1)
659 self._common_validate_field(req, allowed_reqs,
662 def _validate_requirements_properties(self, requirements):
663 # TO-DO(anyone): Only occurrences property of the requirements is
664 # validated here. Validation of other requirement properties are being
665 # validated in different files. Better to keep all the requirements
666 # properties validation here.
667 for key, value in requirements.items():
668 if key == 'occurrences':
669 self._validate_occurrences(value)
672 def _validate_occurrences(self, occurrences):
673 DataEntity.validate_datatype('list', occurrences)
674 for value in occurrences:
675 DataEntity.validate_datatype('integer', value)
676 if len(occurrences) != 2 or not (0 <= occurrences[0] <= occurrences[1]) \
677 or occurrences[1] == 0:
678 ExceptionCollector.appendException(
679 InvalidPropertyValueError(what=(occurrences)))
681 def _validate_requirements_keys(self, requirement):
682 for key in requirement.keys():
683 if key not in self.REQUIREMENTS_SECTION:
684 ExceptionCollector.appendException(
686 what='"requirements" of template "%s"' % self.name,
689 def _validate_interfaces(self):
690 ifaces = self.type_definition.get_value(self.INTERFACES,
693 for name, value in ifaces.items():
694 if name in (LIFECYCLE, LIFECYCLE_SHORTNAME):
695 self._common_validate_field(
696 value, InterfacesDef.
697 interfaces_node_lifecycle_operations,
699 elif name in (CONFIGURE, CONFIGURE_SHORTNAME):
700 self._common_validate_field(
701 value, InterfacesDef.
702 interfaces_relationship_configure_operations,
704 elif name in self.type_definition.interfaces.keys():
705 self._common_validate_field(
707 self._collect_custom_iface_operations(name),
710 ExceptionCollector.appendException(
712 what='"interfaces" of template "%s"' %
713 self.name, field=name))
715 def _collect_custom_iface_operations(self, name):
716 allowed_operations = []
717 nodetype_iface_def = self.type_definition.interfaces[name]
718 allowed_operations.extend(nodetype_iface_def.keys())
719 if 'type' in nodetype_iface_def:
720 iface_type = nodetype_iface_def['type']
721 if iface_type in self.type_definition.custom_def:
722 iface_type_def = self.type_definition.custom_def[iface_type]
724 iface_type_def = self.type_definition.TOSCA_DEF[iface_type]
725 allowed_operations.extend(iface_type_def.keys())
726 allowed_operations = [op for op in allowed_operations if
727 op not in INTERFACE_DEF_RESERVED_WORDS]
728 return allowed_operations
730 def _validate_fields(self, nodetemplate):
731 for name in nodetemplate.keys():
732 if name not in self.SECTIONS and name not in self.SPECIAL_SECTIONS:
733 ExceptionCollector.appendException(
734 UnknownFieldError(what='Node template "%s"' % self.name,