def generate_pillar_file(self, update_formulas=False):
        # Import here to not cause circular imports
        from stackdio.api.formulas.models import FormulaVersion
        from stackdio.api.formulas.tasks import update_formula

        users = []
        # pull the create_ssh_users property from the stackd.io config file.
        # If it's False, we won't create ssh users on the box.
        if self.create_users:
            user_permissions_map = get_users_with_perms(
                self, attach_perms=True, with_superusers=True, with_group_users=True
            )

            for user, perms in user_permissions_map.items():
                if 'ssh_stack' in perms:
                    if user.settings.public_key:
                        logger.debug('Granting {0} ssh permission to stack: {1}'.format(
                            user.username,
                            self.title,
                        ))
                        users.append({
                            'username': user.username,
                            'public_key': user.settings.public_key,
                            'id': user.id,
                        })
                    else:
                        logger.debug(
                            'User {0} has ssh permission for stack {1}, but has no public key.  '
                            'Skipping.'.format(
                                user.username,
                                self.title,
                            )
                        )

        pillar_props = {
            '__stackdio__': {
                'users': users
            }
        }

        # If any of the formulas we're using have default pillar
        # data defined in its corresponding SPECFILE, we need to pull
        # that into our stack pillar file.

        # First get the unique set of formulas
        formulas = set()
        for host in self.hosts.all():
            formulas.update([c.formula for c in host.formula_components.all()])

        # Update the formulas if requested
        if update_formulas:
            for formula in formulas:
                # Update the formula, and fail silently if there was an error.
                if formula.private_git_repo:
                    logger.debug('Skipping private formula: {0}'.format(formula.uri))
                    continue

                try:
                    version = self.formula_versions.get(formula=formula).version
                except FormulaVersion.DoesNotExist:
                    version = formula.default_version

                update_formula.si(formula.id, None, version, raise_exception=False)()

        # for each unique formula, pull the properties from the SPECFILE
        for formula in formulas:
            recursive_update(pillar_props, formula.properties)

        # Add in properties that were supplied via the blueprint and during
        # stack creation
        recursive_update(pillar_props, self.properties)

        pillar_file_yaml = yaml.safe_dump(pillar_props, default_flow_style=False)

        if not self.pillar_file:
            self.pillar_file.save('stack.pillar', ContentFile(pillar_file_yaml))
        else:
            with open(self.pillar_file.path, 'w') as f:
                f.write(pillar_file_yaml)
dataset/ETHPy150Open stackdio/stackdio/stackdio/api/stacks/models.py/Stack.generate_pillar_file/original