'Check the validity of a template.
Checks, so far as we can, that a template is valid, and returns
information about the parameters suitable for producing a user
interface through which to specify the parameter values.
:param cnxt: RPC context.
:param template: Template of stack you want to create.
:param params: Stack Input Params
:param files: Files referenced from the template
:param environment_files: optional ordered list of environment file
names included in the files dict
:type  environment_files: list or None
:param show_nested: if True, any nested templates will be checked
:param ignorable_errors: List of error_code to be ignored as part of
validation'

@context.request_context
def validate_template(self, cnxt, template, params=None, files=None, environment_files=None, show_nested=False, ignorable_errors=None):

    LOG.info('validate_template')
    if (template is None):
        msg = _('No    Template    provided.')
        return webob.exc.HTTPBadRequest(explanation=msg)
    if ignorable_errors:
        invalid_codes = (set(ignorable_errors) - set(exception.ERROR_CODE_MAP.keys()))
        if invalid_codes:
            msg = (_('Invalid    codes    in    ignore_errors    :    %s') % list(invalid_codes))
            return webob.exc.HTTPBadRequest(explanation=msg)
    tmpl = templatem.Template(template, files=files)
    env_util.merge_environments(environment_files, files, params, tmpl.all_param_schemata(files))
    tmpl.env = environment.Environment(params)
    try:
        self._validate_template(cnxt, tmpl)
    except Exception as ex:
        return {'Error': six.text_type(ex)}
    stack_name = 'dummy'
    stack = parser.Stack(cnxt, stack_name, tmpl, strict_validate=False)
    try:
        stack.validate(ignorable_errors=ignorable_errors, validate_res_tmpl_only=True)
    except exception.StackValidationFailed as ex:
        return {'Error': six.text_type(ex)}
    def filter_parameter(p):
        return (p.name not in stack.parameters.PSEUDO_PARAMETERS)
    params = stack.parameters.map(api.format_validate_parameter, filter_func=filter_parameter)
    result = {'Description': tmpl.get('Description', ''), 'Parameters': params}
    param_groups = parameter_groups.ParameterGroups(tmpl)
    if param_groups.parameter_groups:
        result['ParameterGroups'] = param_groups.parameter_groups
    if show_nested:
        stack.preview_resources()
        def nested_params(stk):
            n_result = {}
            for r in stk:
                if stk[r].has_nested():
                    n_params = stk[r].nested().parameters.map(api.format_validate_parameter, filter_func=filter_parameter)
                    n_result[r] = {'Type': stk[r].type(), 'Description': stk[r].nested().t.get('Description', ''), 'Parameters': n_params}
                    nested_pg = parameter_groups.ParameterGroups(stk[r].nested().t)
                    if nested_pg.parameter_groups:
                        n_result[r].update({'ParameterGroups': nested_pg.parameter_groups})
                    n_result[r].update(nested_params(stk[r].nested()))
            return ({'NestedParameters': n_result} if n_result else {})
        result.update(nested_params(stack))
    return result
