示例#1
0
    def validate(self, value):
        # check for valid hostname_template variables
        formatter = string.Formatter()
        template_vars = [x[1] for x in formatter.parse(value) if x[1]]

        invalid_vars = []
        for var in template_vars:
            if var not in VALID_TEMPLATE_VARS:
                invalid_vars.append(var)

        errors = []

        if invalid_vars:
            errors.append('Invalid variables: {0}'.format(', '.join(invalid_vars)))

        raw_str = ''

        for parse in formatter.parse(value):
            raw_str += parse[0]
            if parse[1] is not None:
                raw_str += 'placeholder'

        errors.extend(validate_hostname(raw_str))

        if errors:
            raise ValidationError({
                'hostname_template': errors
            })
示例#2
0
    def validate(self, value):
        # check for valid hostname_template variables
        formatter = string.Formatter()
        template_vars = [x[1] for x in formatter.parse(value) if x[1]]

        invalid_vars = []
        for var in template_vars:
            if var not in VALID_TEMPLATE_VARS:
                invalid_vars.append(var)

        errors = []

        if invalid_vars:
            errors.append('Invalid variables: {0}'.format(', '.join(invalid_vars)))

        raw_str = ''

        for parse in formatter.parse(value):
            raw_str += parse[0]
            if parse[1] is not None:
                raw_str += 'placeholder'

        errors.extend(validate_hostname(raw_str))

        if errors:
            raise ValidationError({
                'hostname_template': errors
            })
示例#3
0
    def validate(self, attrs):
        errors = {}

        # make sure the user has a public key or they won't be able to SSH
        # later
        request = self.context['request']
        if 'create_users' in attrs:
            create_users = attrs['create_users']
        else:
            create_users = self.instance.create_users
        if create_users and not request.user.settings.public_key:
            errors.setdefault('public_key', []).append(
                'You have not added a public key to your user '
                'profile and will not be able to SSH in to any '
                'machines. Please update your user profile '
                'before continuing.'
            )

        # Check to see if the launching user has permission to launch from the blueprint
        user = request.user
        blueprint = self.instance.blueprint if self.instance else attrs['blueprint']

        if not user.has_perm('blueprints.view_blueprint', blueprint):
            err_msg = 'You do not have permission to launch a stack from this blueprint.'
            errors.setdefault('blueprint', []).append(err_msg)

        # Check to make sure we don't have security group creation turned off without default
        # security groups
        accounts = set()
        for host_definition in blueprint.host_definitions.all():
            accounts.add(host_definition.cloud_image.account)

        for account in accounts:
            if (
                not account.create_security_groups and
                account.security_groups.filter(is_default=True).count() < 1
            ):
                errors.setdefault('security_groups', []).append(
                    'Account `{0}` has per-stack security groups disabled, but doesn\'t define any '
                    'default security groups.  You must define at least 1 default security group '
                    'on this account before launching stacks.'.format(account.title)
                )

        # check for hostname collisions if namespace is provided
        namespace = attrs.get('namespace')

        if namespace:
            # This all has to be here vs. in its own validator b/c it needs the blueprint
            hostname_errors = validate_hostname(namespace)
            if hostname_errors:
                errors.setdefault('namespace', []).extend(hostname_errors)

            # This is all only necessary if a namespace was provided
            #  (It may not be provided on a PATCH request)
            host_definitions = blueprint.host_definitions.all()
            hostnames = models.get_hostnames_from_hostdefs(
                host_definitions,
                namespace=namespace
            )

            # query for existing host names
            # Leave this in so that we catch errors faster if they are local,
            #    Only hit up salt cloud if there are no duplicates locally
            hosts = models.Host.objects.filter(hostname__in=hostnames)
            if hosts.count() > 0:
                err_msg = 'Duplicate hostnames: {0}'.format(', '.join([h.hostname for h in hosts]))
                errors.setdefault('namespace', []).append(err_msg)

            if errors:
                # Go ahead and raise an error here so that we don't check the provider if
                # we don't need to
                raise serializers.ValidationError(errors)

            salt_cloud = salt.cloud.CloudClient(os.path.join(
                settings.STACKDIO_CONFIG.salt_config_root,
                'cloud'
            ))
            query = salt_cloud.query()

            # Since a blueprint can have multiple accounts
            accounts = set()
            for bhd in host_definitions:
                accounts.add(bhd.cloud_image.account)

            # Check to find duplicates
            dups = []
            for account in accounts:
                provider = account.provider.name
                for instance, details in query.get(account.slug, {}).get(provider, {}).items():
                    if instance in hostnames:
                        if details['state'] not in ('shutting-down', 'terminated'):
                            dups.append(instance)

            if dups:
                err_msg = 'Duplicate hostnames: {0}'.format(', '.join(dups))
                errors.setdefault('namespace', []).append(err_msg)

        if errors:
            raise serializers.ValidationError(errors)

        return attrs
示例#4
0
    def validate(self, attrs):
        errors = {}

        # make sure the user has a public key or they won't be able to SSH
        # later
        request = self.context['request']

        blueprint = self.instance.blueprint if self.instance else attrs[
            'blueprint']
        if 'create_users' in attrs:
            create_users = attrs['create_users']
        else:
            if self.instance:
                create_users = self.instance.create_users
            else:
                attrs['create_users'] = blueprint.create_users
                create_users = attrs['create_users']

        if create_users and not request.user.settings.public_key:
            errors.setdefault('public_key', []).append(
                'You have not added a public key to your user '
                'profile and will not be able to SSH in to any '
                'machines. Please update your user profile '
                'before continuing.')

        # Check to see if the launching user has permission to launch from the blueprint
        user = request.user

        if not user.has_perm('blueprints.view_blueprint', blueprint):
            err_msg = 'You do not have permission to launch a stack from this blueprint.'
            errors.setdefault('blueprint', []).append(err_msg)

        # Check to make sure we don't have security group creation turned off without default
        # security groups
        accounts = set()
        for host_definition in blueprint.host_definitions.all():
            accounts.add(host_definition.cloud_image.account)

        for account in accounts:
            if (not account.create_security_groups
                    and account.security_groups.filter(
                        is_default=True).count() < 1):
                errors.setdefault('security_groups', []).append(
                    'Account `{0}` has per-stack security groups disabled, but doesn\'t define any '
                    'default security groups.  You must define at least 1 default security group '
                    'on this account before launching stacks.'.format(
                        account.title))

        # check for hostname collisions if namespace is provided
        namespace = attrs.get('namespace')

        if namespace:
            # This all has to be here vs. in its own validator b/c it needs the blueprint
            hostname_errors = validate_hostname(namespace)
            if hostname_errors:
                errors.setdefault('namespace', []).extend(hostname_errors)

            # This is all only necessary if a namespace was provided
            #  (It may not be provided on a PATCH request)
            host_definitions = blueprint.host_definitions.all()
            hostnames = models.get_hostnames_from_hostdefs(host_definitions,
                                                           namespace=namespace)

            # query for existing host names
            # Leave this in so that we catch errors faster if they are local,
            #    Only hit up salt cloud if there are no duplicates locally
            hosts = models.Host.objects.filter(hostname__in=hostnames)
            if hosts.count() > 0:
                err_msg = 'Duplicate hostnames: {0}'.format(', '.join(
                    [h.hostname for h in hosts]))
                errors.setdefault('namespace', []).append(err_msg)

            if errors:
                # Go ahead and raise an error here so that we don't check the provider if
                # we don't need to
                raise serializers.ValidationError(errors)

            salt_cloud = salt.cloud.CloudClient(
                os.path.join(settings.STACKDIO_CONFIG.salt_config_root,
                             'cloud'))
            query = salt_cloud.query()

            # Since a blueprint can have multiple accounts
            accounts = set()
            for bhd in host_definitions:
                accounts.add(bhd.cloud_image.account)

            # Check to find duplicates
            dups = []
            for account in accounts:
                provider = account.provider.name
                for instance, details in query.get(account.slug,
                                                   {}).get(provider,
                                                           {}).items():
                    if instance in hostnames:
                        if details['state'] not in ('shutting-down',
                                                    'terminated'):
                            dups.append(instance)

            if dups:
                err_msg = 'Duplicate hostnames: {0}'.format(', '.join(dups))
                errors.setdefault('namespace', []).append(err_msg)

        if errors:
            raise serializers.ValidationError(errors)

        return attrs