示例#1
0
def update_definitions(version):
    exttools = ExtTools()
    extension_defs_file = exttools.get_defs_file(version)

    loader = toscaparser.utils.yamlparser.load_yaml

    EntityType.TOSCA_DEF.update(loader(extension_defs_file))
示例#2
0
def update_definitions(version):
    exttools = ExtTools()
    extension_defs_file = exttools.get_defs_file(version)

    loader = toscaparser.utils.yamlparser.load_yaml

    EntityType.TOSCA_DEF.update(loader(extension_defs_file))
示例#3
0
def update_definitions(version):
    exttools = ExtTools()
    extension_defs_file = exttools.get_defs_file(version)
    loader = toscaparser.utils.yamlparser.load_yaml
    nfv_def_file = loader(extension_defs_file)
    nfv_def = {}
    for section in EntityType.TOSCA_DEF_SECTIONS:
        if section in nfv_def_file.keys():
            value = nfv_def_file[section]
            for key in value.keys():
                nfv_def[key] = value[key]
    EntityType.TOSCA_DEF.update(nfv_def)
示例#4
0
def update_definitions(version):
    exttools = ExtTools()
    extension_defs_file = exttools.get_defs_file(version)
    loader = toscaparser.utils.yamlparser.load_yaml
    nfv_def_file = loader(extension_defs_file)
    nfv_def = {}
    for section in EntityType.TOSCA_DEF_SECTIONS:
        if section in nfv_def_file.keys():
            value = nfv_def_file[section]
            for key in value.keys():
                nfv_def[key] = value[key]
    EntityType.TOSCA_DEF.update(nfv_def)
class TypeValidation(object):

    ALLOWED_TYPE_SECTIONS = (DEFINITION_VERSION, DESCRIPTION, IMPORTS,
                             DSL_DEFINITIONS, NODE_TYPES, REPOSITORIES,
                             DATA_TYPES, ARTIFACT_TYPES, GROUP_TYPES,
                             RELATIONSHIP_TYPES, CAPABILITY_TYPES,
                             INTERFACE_TYPES, POLICY_TYPES,
                             TOPOLOGY_TEMPLATE, METADATA) = \
        ('tosca_definitions_version', 'description', 'imports',
         'dsl_definitions', 'node_types', 'repositories',
         'data_types', 'artifact_types', 'group_types',
         'relationship_types', 'capability_types',
         'interface_types', 'policy_types', 'topology_template', 'metadata')


    STANDARD_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0',
                                  'tosca_simple_yaml_1_1',
                                  'tosca_simple_yaml_1_2']

    VALID_TEMPLATE_VERSIONS = copy.deepcopy(STANDARD_TEMPLATE_VERSIONS)

    exttools = ExtTools()
    VALID_TEMPLATE_VERSIONS.extend(exttools.get_versions())

    def __init__(self, custom_types, import_def):
        self.import_def = import_def
        self._validate_type_keys(custom_types)

    def _validate_type_keys(self, custom_type):
        version = custom_type[self.DEFINITION_VERSION] \
            if self.DEFINITION_VERSION in custom_type \
            else None
        if version:
            self._validate_type_version(version)
            self.version = version

        for name in custom_type:
            if name in self.ALLOWED_TYPE_SECTIONS:
                pass
            elif version and version in self.exttools.get_sections() and \
                 name in self.exttools.get_sections()[version]:
                pass
            else:
                ExceptionCollector.appendException(
                    UnknownFieldError(what='Template ' + str(self.import_def),
                                      field=name))

    def _validate_type_version(self, version):
        if version not in self.VALID_TEMPLATE_VERSIONS:
            ExceptionCollector.appendException(
                InvalidTemplateVersion(
                    what=version + ' in ' + str(self.import_def),
                    valid_versions=', '. join(sorted(self.VALID_TEMPLATE_VERSIONS))))
示例#6
0
class ToscaTemplate(object):
    exttools = ExtTools()

    VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0']

    VALID_TEMPLATE_VERSIONS.extend(exttools.get_versions())

    ADDITIONAL_SECTIONS = {'tosca_simple_yaml_1_0': SPECIAL_SECTIONS}

    ADDITIONAL_SECTIONS.update(exttools.get_sections())
    '''Load the template data.'''
    def __init__(self,
                 path=None,
                 parsed_params=None,
                 a_file=True,
                 yaml_dict_tpl=None):

        ExceptionCollector.start()
        self.a_file = a_file
        self.input_path = None
        self.path = None
        self.tpl = None
        self.nested_tosca_tpls_with_topology = {}
        self.nested_tosca_templates_with_topology = []
        if path:
            self.input_path = path
            self.path = self._get_path(path)
            if self.path:
                self.tpl = YAML_LOADER(self.path, self.a_file)
            if yaml_dict_tpl:
                msg = (_('Both path and yaml_dict_tpl arguments were '
                         'provided. Using path and ignoring yaml_dict_tpl.'))
                log.info(msg)
                print(msg)
        else:
            if yaml_dict_tpl:
                self.tpl = yaml_dict_tpl
            else:
                ExceptionCollector.appendException(
                    ValueError(
                        _('No path or yaml_dict_tpl was provided. '
                          'There is nothing to parse.')))

        if self.tpl:
            self.parsed_params = parsed_params
            self._validate_field()
            self.version = self._tpl_version()
            self.relationship_types = self._tpl_relationship_types()
            self.description = self._tpl_description()
            self.topology_template = self._topology_template()
            self.repositories = self._tpl_repositories()
            if self.topology_template.tpl:
                self.inputs = self._inputs()
                self.relationship_templates = self._relationship_templates()
                self.nodetemplates = self._nodetemplates()
                self.groups = self._groups()
                self.outputs = self._outputs()
                self.policies = self._policies()
                self._handle_nested_tosca_templates_with_topology()
                self.graph = ToscaGraph(self.nodetemplates)

        ExceptionCollector.stop()
        self.verify_template()

    def _topology_template(self):
        return TopologyTemplate(self._tpl_topology_template(),
                                self._get_all_custom_defs(),
                                self.relationship_types, self.parsed_params,
                                None)

    def _inputs(self):
        return self.topology_template.inputs

    def _nodetemplates(self):
        return self.topology_template.nodetemplates

    def _relationship_templates(self):
        return self.topology_template.relationship_templates

    def _outputs(self):
        return self.topology_template.outputs

    def _tpl_version(self):
        return self.tpl.get(DEFINITION_VERSION)

    def _tpl_description(self):
        desc = self.tpl.get(DESCRIPTION)
        if desc:
            return desc.rstrip()

    def _tpl_imports(self):
        return self.tpl.get(IMPORTS)

    def _tpl_repositories(self):
        repositories = self.tpl.get(REPOSITORIES)
        reposit = []
        if repositories:
            for name, val in repositories.items():
                reposits = Repository(name, val)
                reposit.append(reposits)
        return reposit

    def _tpl_relationship_types(self):
        return self._get_custom_types(RELATIONSHIP_TYPES)

    def _tpl_relationship_templates(self):
        topology_template = self._tpl_topology_template()
        return topology_template.get(RELATIONSHIP_TEMPLATES)

    def _tpl_topology_template(self):
        return self.tpl.get(TOPOLOGY_TEMPLATE)

    def _policies(self):
        return self.topology_template.policies

    def _groups(self):
        return self.topology_template.groups

    def _get_all_custom_defs(self, imports=None):
        types = [
            IMPORTS, NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
            DATA_TYPES, INTERFACE_TYPES, POLICY_TYPES, GROUP_TYPES
        ]
        custom_defs_final = {}
        custom_defs = self._get_custom_types(types, imports)
        if custom_defs:
            custom_defs_final.update(custom_defs)
            if custom_defs.get(IMPORTS):
                import_defs = self._get_all_custom_defs(
                    custom_defs.get(IMPORTS))
                custom_defs_final.update(import_defs)

        # As imports are not custom_types, removing from the dict
        custom_defs_final.pop(IMPORTS, None)
        return custom_defs_final

    def _get_custom_types(self, type_definitions, imports=None):
        """Handle custom types defined in imported template files

        This method loads the custom type definitions referenced in "imports"
        section of the TOSCA YAML template.
        """

        custom_defs = {}
        type_defs = []
        if not isinstance(type_definitions, list):
            type_defs.append(type_definitions)
        else:
            type_defs = type_definitions

        if not imports:
            imports = self._tpl_imports()

        if imports:
            custom_service = toscaparser.imports.\
                ImportsLoader(imports, self.path,
                              type_defs, self.tpl)

            nested_tosca_tpls = custom_service.get_nested_tosca_tpls()
            self._update_nested_tosca_tpls_with_topology(nested_tosca_tpls)

            custom_defs = custom_service.get_custom_defs()
            if not custom_defs:
                return

        # Handle custom types defined in current template file
        for type_def in type_defs:
            if type_def != IMPORTS:
                inner_custom_types = self.tpl.get(type_def) or {}
                if inner_custom_types:
                    custom_defs.update(inner_custom_types)
        return custom_defs

    def _update_nested_tosca_tpls_with_topology(self, nested_tosca_tpls):
        for tpl in nested_tosca_tpls:
            filename, tosca_tpl = list(tpl.items())[0]
            if (tosca_tpl.get(TOPOLOGY_TEMPLATE) and filename not in list(
                    self.nested_tosca_tpls_with_topology.keys())):
                self.nested_tosca_tpls_with_topology.update(tpl)

    def _handle_nested_tosca_templates_with_topology(self):
        for fname, tosca_tpl in self.nested_tosca_tpls_with_topology.items():
            for nodetemplate in self.nodetemplates:
                if self._is_sub_mapped_node(nodetemplate, tosca_tpl):
                    parsed_params = self._get_params_for_nested_template(
                        nodetemplate)
                    topology_tpl = tosca_tpl.get(TOPOLOGY_TEMPLATE)
                    topology_with_sub_mapping = TopologyTemplate(
                        topology_tpl, self._get_all_custom_defs(),
                        self.relationship_types, parsed_params, nodetemplate)
                    if topology_with_sub_mapping.substitution_mappings:
                        # Record nested topo templates in top level template
                        self.nested_tosca_templates_with_topology.\
                            append(topology_with_sub_mapping)
                        # Set substitution mapping object for mapped node
                        nodetemplate.sub_mapping_tosca_template = \
                            topology_with_sub_mapping.substitution_mappings

    def _validate_field(self):
        version = self._tpl_version()
        if not version:
            ExceptionCollector.appendException(
                MissingRequiredFieldError(what='Template',
                                          required=DEFINITION_VERSION))
        else:
            self._validate_version(version)
            self.version = version

        for name in self.tpl:
            if (name not in SECTIONS
                    and name not in self.ADDITIONAL_SECTIONS.get(version, ())):
                ExceptionCollector.appendException(
                    UnknownFieldError(what='Template', field=name))

    def _validate_version(self, version):
        if version not in self.VALID_TEMPLATE_VERSIONS:
            ExceptionCollector.appendException(
                InvalidTemplateVersion(what=version,
                                       valid_versions=', '.join(
                                           self.VALID_TEMPLATE_VERSIONS)))
        else:
            if version != 'tosca_simple_yaml_1_0':
                update_definitions(version)

    def _get_path(self, path):
        if path.lower().endswith('.yaml') or path.lower().endswith('.yml'):
            return path
        elif path.lower().endswith(('.zip', '.csar')):
            # a CSAR archive
            csar = CSAR(path, self.a_file)
            if csar.validate():
                csar.decompress()
                self.a_file = True  # the file has been decompressed locally
                return os.path.join(csar.temp_dir, csar.get_main_template())
        else:
            ExceptionCollector.appendException(
                ValueError(
                    _('"%(path)s" is not a valid file.') % {'path': path}))

    def verify_template(self):
        if ExceptionCollector.exceptionsCaught():
            if self.input_path:
                raise ValidationError(
                    message=(_('\nThe input "%(path)s" failed validation with '
                               'the following error(s): \n\n\t') % {
                                   'path': self.input_path
                               }) +
                    '\n\t'.join(ExceptionCollector.getExceptionsReport()))
            else:
                raise ValidationError(
                    message=_('\nThe pre-parsed input failed validation with '
                              'the following error(s): \n\n\t') +
                    '\n\t'.join(ExceptionCollector.getExceptionsReport()))
        else:
            if self.input_path:
                msg = (_('The input "%(path)s" successfully passed '
                         'validation.') % {
                             'path': self.input_path
                         })
            else:
                msg = _('The pre-parsed input successfully passed validation.')

            log.info(msg)

    def _is_sub_mapped_node(self, nodetemplate, tosca_tpl):
        """Return True if the nodetemple is substituted."""
        if (nodetemplate and not nodetemplate.sub_mapping_tosca_template and
                self.get_sub_mapping_node_type(tosca_tpl) == nodetemplate.type
                and len(nodetemplate.interfaces) < 1):
            return True
        else:
            return False

    def _get_params_for_nested_template(self, nodetemplate):
        """Return total params for nested_template."""
        parsed_params = deepcopy(self.parsed_params) \
            if self.parsed_params else {}
        if nodetemplate:
            for pname in nodetemplate.get_properties():
                parsed_params.update(
                    {pname: nodetemplate.get_property_value(pname)})
        return parsed_params

    def get_sub_mapping_node_type(self, tosca_tpl):
        """Return substitution mappings node type."""
        if tosca_tpl:
            return TopologyTemplate.get_sub_mapping_node_type(
                tosca_tpl.get(TOPOLOGY_TEMPLATE))

    def _has_substitution_mappings(self):
        """Return True if the template has valid substitution mappings."""
        return self.topology_template is not None and \
            self.topology_template.substitution_mappings is not None

    def has_nested_templates(self):
        """Return True if the tosca template has nested templates."""
        return self.nested_tosca_templates_with_topology is not None and \
            len(self.nested_tosca_templates_with_topology) >= 1
示例#7
0
class ToscaTemplate(object):
    exttools = ExtTools()

    msg = ''

    VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0']

    VALID_TEMPLATE_VERSIONS.extend(exttools.get_versions())

    ADDITIONAL_SECTIONS = {'tosca_simple_yaml_1_0': SPECIAL_SECTIONS}

    ADDITIONAL_SECTIONS.update(exttools.get_sections())
    '''Load the template data.'''
    def __init__(self,
                 path=None,
                 parsed_params=None,
                 a_file=True,
                 yaml_dict_tpl=None):
        ExceptionCollector.start()
        self.a_file = a_file
        self.input_path = None
        self.path = None
        self.tpl = None
        if path:
            self.input_path = path
            self.path = self._get_path(path)
            if self.path:
                self.tpl = YAML_LOADER(self.path, self.a_file)
            if yaml_dict_tpl:
                msg = (_('Both path and yaml_dict_tpl arguments were '
                         'provided. Using path and ignoring yaml_dict_tpl.'))
                log.info(msg)
                print(msg)
        else:
            if yaml_dict_tpl:
                self.tpl = yaml_dict_tpl
            else:
                ExceptionCollector.appendException(
                    ValueError(
                        _('No path or yaml_dict_tpl was provided. '
                          'There is nothing to parse.')))

        if self.tpl:
            self.parsed_params = parsed_params
            self._validate_field()
            self.version = self._tpl_version()
            self.relationship_types = self._tpl_relationship_types()
            self.description = self._tpl_description()
            self.topology_template = self._topology_template()
            if self.topology_template.tpl:
                self.inputs = self._inputs()
                self.relationship_templates = self._relationship_templates()
                self.nodetemplates = self._nodetemplates()
                self.outputs = self._outputs()
                self.graph = ToscaGraph(self.nodetemplates)

        ExceptionCollector.stop()
        self.msg = self.verify_template()

    def _topology_template(self):
        return TopologyTemplate(self._tpl_topology_template(),
                                self._get_all_custom_defs(),
                                self.relationship_types, self.parsed_params)

    def _inputs(self):
        return self.topology_template.inputs

    def _nodetemplates(self):
        return self.topology_template.nodetemplates

    def _relationship_templates(self):
        return self.topology_template.relationship_templates

    def _outputs(self):
        return self.topology_template.outputs

    def _tpl_version(self):
        return self.tpl.get(DEFINITION_VERSION)

    def _tpl_description(self):
        desc = self.tpl.get(DESCRIPTION)
        if desc:
            return desc.rstrip()

    def _tpl_imports(self):
        return self.tpl.get(IMPORTS)

    def _tpl_relationship_types(self):
        return self._get_custom_types(RELATIONSHIP_TYPES)

    def _tpl_relationship_templates(self):
        topology_template = self._tpl_topology_template()
        return topology_template.get(RELATIONSHIP_TEMPLATES)

    def _tpl_topology_template(self):
        return self.tpl.get(TOPOLOGY_TEMPLATE)

    def _get_all_custom_defs(self, imports=None):
        types = [
            IMPORTS, NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
            DATA_TYPES, POLICY_TYPES, GROUP_TYPES
        ]
        custom_defs_final = {}
        custom_defs = self._get_custom_types(types, imports)
        if custom_defs:
            custom_defs_final.update(custom_defs)
            if custom_defs.get(IMPORTS):
                import_defs = self._get_all_custom_defs(
                    custom_defs.get(IMPORTS))
                custom_defs_final.update(import_defs)

        # As imports are not custom_types, removing from the dict
        custom_defs_final.pop(IMPORTS, None)
        return custom_defs_final

    def _get_custom_types(self, type_definitions, imports=None):
        """Handle custom types defined in imported template files

        This method loads the custom type definitions referenced in "imports"
        section of the TOSCA YAML template.
        """

        custom_defs = {}
        type_defs = []
        if not isinstance(type_definitions, list):
            type_defs.append(type_definitions)
        else:
            type_defs = type_definitions

        if not imports:
            imports = self._tpl_imports()

        if imports:
            custom_defs = toscaparser.imports.\
                ImportsLoader(imports, self.path,
                              type_defs, self.tpl).get_custom_defs()
            if not custom_defs:
                return

        # Handle custom types defined in current template file
        for type_def in type_defs:
            if type_def != IMPORTS:
                inner_custom_types = self.tpl.get(type_def) or {}
                if inner_custom_types:
                    custom_defs.update(inner_custom_types)
        return custom_defs

    def _validate_field(self):
        version = self._tpl_version()
        if not version:
            ExceptionCollector.appendException(
                MissingRequiredFieldError(what='Template',
                                          required=DEFINITION_VERSION))
        else:
            self._validate_version(version)
            self.version = version

        for name in self.tpl:
            if (name not in SECTIONS
                    and name not in self.ADDITIONAL_SECTIONS.get(version, ())):
                ExceptionCollector.appendException(
                    UnknownFieldError(what='Template', field=name))

    def _validate_version(self, version):
        if version not in self.VALID_TEMPLATE_VERSIONS:
            ExceptionCollector.appendException(
                InvalidTemplateVersion(what=version,
                                       valid_versions=', '.join(
                                           self.VALID_TEMPLATE_VERSIONS)))
        else:
            if version != 'tosca_simple_yaml_1_0':
                update_definitions(version)

    def _get_path(self, path):
        if path.lower().endswith('.yaml'):
            return path
        elif path.lower().endswith(('.zip', '.csar')):
            # a CSAR archive
            csar = CSAR(path, self.a_file)
            if csar.validate():
                csar.decompress()
                self.a_file = True  # the file has been decompressed locally
                return os.path.join(csar.temp_dir, csar.get_main_template())
        else:
            ExceptionCollector.appendException(
                ValueError(
                    _('"%(path)s" is not a valid file.') % {'path': path}))

    def verify_template(self):
        if ExceptionCollector.exceptionsCaught():
            if self.input_path:

                msg = (_('\nThe input "%(path)s" failed validation with '
                         'the following error(s): \n\n\t') % {
                             'path': self.input_path
                         }) + '\n\t'.join(
                             ExceptionCollector.getExceptionsReport())
            else:

                msg = _('\nThe pre-parsed input failed validation with '
                        'the following error(s): \n\n\t') + '\n\t'.join(
                            ExceptionCollector.getExceptionsReport())
        else:
            if self.input_path:
                msg = msg = (_('success'))
            else:
                msg = msg = (_('success'))

            log.info(msg)
        return msg
示例#8
0
class ToscaTemplate(object):
    exttools = ExtTools()

    MAIN_TEMPLATE_VERSIONS = [
        'tosca_simple_yaml_1_0', 'tosca_simple_yaml_1_2',
        'tosca_simple_yaml_1_3'
    ]

    VALID_TEMPLATE_VERSIONS = MAIN_TEMPLATE_VERSIONS + exttools.get_versions()

    ADDITIONAL_SECTIONS = {
        'tosca_simple_yaml_1_0': SPECIAL_SECTIONS,
        'tosca_simple_yaml_1_2': SPECIAL_SECTIONS,
        'tosca_simple_yaml_1_3': SPECIAL_SECTIONS
    }

    ADDITIONAL_SECTIONS.update(exttools.get_sections())
    '''Load the template data.'''
    def __init__(self,
                 path=None,
                 parsed_params=None,
                 a_file=True,
                 yaml_dict_tpl=None,
                 import_resolver=None,
                 verify=True):

        ExceptionCollector.start()
        self.a_file = a_file
        self.input_path = None
        self.path = None
        self.tpl = None
        self.import_resolver = import_resolver
        self.nested_tosca_tpls = {}
        self.nested_topologies = {}
        if path:
            self.input_path = path
            # don't validate or load if yaml_dict_tpl was set
            if yaml_dict_tpl:
                self.path = path
            else:
                self.path = self._get_path(path)
                self.tpl = YAML_LOADER(self.path, self.a_file)

        if yaml_dict_tpl:
            self.tpl = yaml_dict_tpl

        if not path and not yaml_dict_tpl:
            ExceptionCollector.appendException(
                ValueError(
                    _('No path or yaml_dict_tpl was provided. '
                      'There is nothing to parse.')))

        if self.tpl:
            self.parsed_params = parsed_params
            self._validate_field()
            self.version = self._tpl_version()
            # XXX causes imports to be loaded twice
            self.description = self._tpl_description()
            self.topology_template = self._topology_template()
            self.repositories = self._tpl_repositories()
            if self.topology_template.tpl:
                self.inputs = self._inputs()
                self.relationship_templates = self._relationship_templates()
                self.outputs = self._outputs()
                self.policies = self._policies()
                self._handle_nested_tosca_templates_with_topology()

        ExceptionCollector.stop()
        if verify:
            self.verify_template()

    def _topology_template(self):
        return TopologyTemplate(self._tpl_topology_template(),
                                self._get_all_custom_defs(),
                                self.parsed_params, None)

    def _inputs(self):
        return self.topology_template.inputs

    @property
    def nodetemplates(self):
        return self.topology_template.nodetemplates

    def _relationship_templates(self):
        return self.topology_template.relationship_templates

    def _outputs(self):
        return self.topology_template.outputs

    def _tpl_version(self):
        return self.tpl.get(DEFINITION_VERSION)

    def _tpl_description(self):
        desc = self.tpl.get(DESCRIPTION)
        if desc:
            return desc.rstrip()

    def _tpl_imports(self):
        return self.tpl.get(IMPORTS)

    def _tpl_repositories(self):
        repositories = {}
        assert self.topology_template  # sets self.nested_tosca_tpls
        for filename, tosca_tpl in self.nested_tosca_tpls.items():
            repositories.update(tosca_tpl.get(REPOSITORIES) or {})
        repositories.update(self.tpl.get(REPOSITORIES) or {})
        # we need to update the template because it is passed directly to the import loader
        self.tpl[REPOSITORIES] = repositories
        if self.import_resolver:
            get_repository = self.import_resolver.get_repository
        else:
            get_repository = Repository
        return {
            name: get_repository(name, val)
            for name, val in repositories.items()
        }

    def _tpl_relationship_templates(self):
        topology_template = self._tpl_topology_template()
        return topology_template.get(RELATIONSHIP_TEMPLATES)

    def _tpl_topology_template(self):
        return self.tpl.get(TOPOLOGY_TEMPLATE)

    def _policies(self):
        return self.topology_template.policies

    def _get_all_custom_defs(self, imports=None, path=None):
        types = [
            TYPES, NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
            DATA_TYPES, ARTIFACT_TYPES, INTERFACE_TYPES, POLICY_TYPES,
            GROUP_TYPES
        ]
        custom_defs_final = {}

        custom_defs, nested_imports = self._get_custom_types(
            types, imports, path)
        if custom_defs:
            custom_defs_final.update(custom_defs)
        if nested_imports:
            for a_file, nested_import in nested_imports.items():
                import_defs = self._get_all_custom_defs(nested_import, a_file)
                custom_defs_final.update(import_defs)

        return custom_defs_final

    def _get_custom_types(self, type_definitions, imports=None, path=None):
        """Handle custom types defined in imported template files

        This method loads the custom type definitions referenced in "imports"
        section of the TOSCA YAML template.
        """

        custom_defs = {}
        nested_imports = None
        type_defs = []
        if not isinstance(type_definitions, list):
            type_defs.append(type_definitions)
        else:
            type_defs = type_definitions

        if imports is None:
            imports = self._tpl_imports()

        if imports:
            if path is None:
                path = getattr(imports, "baseDir", self.path)
            imported = toscaparser.imports.\
                ImportsLoader(imports, path, type_defs, self.tpl, self.import_resolver)

            nested_tosca_tpls = imported.get_nested_tosca_tpls()
            self._update_nested_tosca_tpls(nested_tosca_tpls)

            nested_imports = imported.get_nested_imports()
            imported_custom_defs = imported.get_custom_defs()
            if imported_custom_defs:
                custom_defs.update(imported_custom_defs)

        # Handle custom types defined in current template file
        for type_def in type_defs:
            inner_custom_types = self.tpl.get(type_def)
            if inner_custom_types:
                custom_defs.update(inner_custom_types)
        return custom_defs, nested_imports

    def _update_nested_tosca_tpls(self, nested_tosca_tpls):
        for tpl in nested_tosca_tpls:
            # add every import (even if it doesn't have a topology)
            filename, tosca_tpl = list(tpl.items())[0]
            if filename not in self.nested_tosca_tpls:
                self.nested_tosca_tpls.update(tpl)

    def _handle_nested_tosca_templates_with_topology(self):
        for filename, tosca_tpl in self.nested_tosca_tpls.items():
            topology_tpl = tosca_tpl.get(TOPOLOGY_TEMPLATE)
            if topology_tpl:
                custom_types = self._get_all_custom_defs().copy()
                custom_types.update(tosca_tpl.get(
                    'node_types', {}))  # XXX isn't this redundant?
                self.nested_topologies[filename] = TopologyTemplate(
                    topology_tpl, custom_types)

        # if a nodetemplate should be substituted, set its sub_mapping_tosca_template
        for nodetemplate in self.nodetemplates:
            if "substitute" not in nodetemplate.directives:
                continue
            for topology in self.nested_topologies.values():
                if not topology.substitution_mappings:
                    continue
                if topology.substitution_mappings.type == nodetemplate.type:
                    # the node template's properties treated as inputs
                    inputs = self._get_params_for_nested_template(nodetemplate)
                    # create a new substitution mapping object for the mapped node
                    # XXX SubstitutionMappings is just a simple wrapper around the def dict, only performs validation
                    # and sub_mapping_tosca_template is never unused!
                    nodetemplate.sub_mapping_tosca_template = SubstitutionMappings(
                        topology.substitution_mappings.sub_mapping_def,
                        topology, inputs, topology.outputs, nodetemplate,
                        topology.custom_defs)
                    break

    def _validate_field(self):
        version = self._tpl_version()
        if not version:
            ExceptionCollector.appendException(
                MissingRequiredFieldError(what='Template',
                                          required=DEFINITION_VERSION))
        else:
            self._validate_version(version)
            self.version = version

        for name in self.tpl:
            if (name not in SECTIONS
                    and name not in self.ADDITIONAL_SECTIONS.get(version, ())):
                ExceptionCollector.appendException(
                    UnknownFieldError(what='Template', field=name))

    def _validate_version(self, version):
        if version not in self.VALID_TEMPLATE_VERSIONS:
            ExceptionCollector.appendException(
                InvalidTemplateVersion(what=version,
                                       valid_versions='", "'.join(
                                           self.VALID_TEMPLATE_VERSIONS)))
        else:
            if version not in self.MAIN_TEMPLATE_VERSIONS:
                update_definitions(self.exttools, version, YAML_LOADER)

    def _get_path(self, path):
        if path.lower().endswith('.yaml') or path.lower().endswith('.yml'):
            return path
        elif path.lower().endswith(('.zip', '.csar')):
            # a CSAR archive
            csar = CSAR(path, self.a_file)
            if csar.validate():
                csar.decompress()
                self.a_file = True  # the file has been decompressed locally
                return os.path.join(csar.temp_dir, csar.get_main_template())
        else:
            ExceptionCollector.appendException(
                ValueError(
                    _('"%(path)s" is not a valid file.') % {'path': path}))

    def verify_template(self):
        if ExceptionCollector.exceptionsCaught():
            if self.input_path:
                raise ValidationError(
                    message=(_('\nThe input "%(path)s" failed validation with '
                               'the following error(s): \n\n\t') % {
                                   'path': self.input_path
                               }) +
                    '\n\t'.join(ExceptionCollector.getExceptionsReport()))
            else:
                raise ValidationError(
                    message=_('\nThe pre-parsed input failed validation with '
                              'the following error(s): \n\n\t') +
                    '\n\t'.join(ExceptionCollector.getExceptionsReport()))
        else:
            if self.input_path:
                msg = (_('The input "%(path)s" successfully passed '
                         'validation.') % {
                             'path': self.input_path
                         })
            else:
                msg = _('The pre-parsed input successfully passed validation.')

            log.info(msg)

    def _is_sub_mapped_node(self, nodetemplate, tosca_tpl):
        """Return True if the nodetemple is substituted."""
        # NOTE(ueha): Since condition "not nodetemplate.sub_mapping_tosca_\
        #             template" was deleted as a fix for bug/1883220, there is
        #             some possibility of breaking something on translator side
        #             that current tests not coverd.
        #             And this enhancement does not align with TOSCA standard
        #             but needed for ETSI NFV-SOL 001.
        if (nodetemplate and self.get_sub_mapping_node_type(tosca_tpl)
                == nodetemplate.type and len(nodetemplate.interfaces) < 1):
            return True
        else:
            return False

    def _get_params_for_nested_template(self, nodetemplate):
        """Return total params for nested_template."""
        parsed_params = {
            input.name: input
            for input in self.topology_template.inputs
        }
        if nodetemplate:
            parsed_params.update(nodetemplate.get_properties())
        return list(parsed_params.values())

    def _has_substitution_mappings(self):
        """Return True if the template has valid substitution mappings."""
        return self.topology_template is not None and \
            self.topology_template.substitution_mappings is not None