Пример #1
0
class SubmissionForm(forms.ModelForm):
    answers = SimpleArrayField(SimpleArrayField(forms.CharField()),
                               delimiter='|')

    class Meta:
        model = Submission
        fields = '__all__'
Пример #2
0
class RackReservationCSVForm(CustomFieldModelCSVForm):
    site = CSVModelChoiceField(queryset=Site.objects.all(),
                               to_field_name='name',
                               help_text='Parent site')
    location = CSVModelChoiceField(queryset=Location.objects.all(),
                                   to_field_name='name',
                                   required=False,
                                   help_text="Rack's location (if any)")
    rack = CSVModelChoiceField(queryset=Rack.objects.all(),
                               to_field_name='name',
                               help_text='Rack')
    units = SimpleArrayField(
        base_field=forms.IntegerField(),
        required=True,
        help_text='Comma-separated list of individual unit numbers')
    tenant = CSVModelChoiceField(queryset=Tenant.objects.all(),
                                 required=False,
                                 to_field_name='name',
                                 help_text='Assigned tenant')

    class Meta:
        model = RackReservation
        fields = ('site', 'location', 'rack', 'units', 'tenant', 'description')

    def __init__(self, data=None, *args, **kwargs):
        super().__init__(data, *args, **kwargs)

        if data:

            # Limit location queryset by assigned site
            params = {
                f"site__{self.fields['site'].to_field_name}": data.get('site')
            }
            self.fields['location'].queryset = self.fields[
                'location'].queryset.filter(**params)

            # Limit rack queryset by assigned site and group
            params = {
                f"site__{self.fields['site'].to_field_name}":
                data.get('site'),
                f"location__{self.fields['location'].to_field_name}":
                data.get('location'),
            }
            self.fields['rack'].queryset = self.fields['rack'].queryset.filter(
                **params)
Пример #3
0
class CloneForm(forms.Form):
    """Clone storage/interface form."""

    source = NodeChoiceField(
        label="Source",
        queryset=Machine.objects.all(),
        required=True,
        initial=None,
        help_text="The source machine to clone from.",
    )

    destinations = SimpleArrayField(
        NodeChoiceField(queryset=Machine.objects.all()),
        label="Destinations",
        min_length=1,
        error_messages={
            "item_invalid": "Machine %(nth)s in the array did not validate:"
        },
        help_text="The destinations to clone to.",
    )

    storage = forms.BooleanField(
        label="Storage",
        required=False,
        help_text="Clone the storage configuration.",
    )

    interfaces = forms.BooleanField(
        label="Interfaces",
        required=False,
        help_text="Clone the interfaces configuration.",
    )

    def __init__(self, user, **kwargs):
        self.user = user
        super().__init__(**kwargs)
        self.fields["source"].queryset = Machine.objects.get_nodes(
            self.user, NodePermission.view)
        self.fields[
            "destinations"].base_field.queryset = Machine.objects.get_nodes(
                self.user,
                NodePermission.admin,
                from_nodes=Machine.objects.filter(
                    status__in={NODE_STATUS.READY, NODE_STATUS.FAILED_TESTING
                                }),
            )

    def clean(self):
        """Validate that the form is valid and that the destinations can accept
        the storage and/or interfaces configuration from the source."""
        cleaned_data = super().clean()
        source = self.cleaned_data.get("source")
        if not source:
            # Django should be placing this automatically, but it does not
            # occur. So we force the setting of this error here.
            set_form_error(self, "source", "This field is required.")
        destinations = self.cleaned_data.get("destinations")
        destination_field = self.fields["destinations"]
        item_invalid = destination_field.error_messages["item_invalid"]
        storage = self.cleaned_data.get("storage", False)
        interfaces = self.cleaned_data.get("interfaces", False)
        if source and destinations:
            for index, dest in enumerate(destinations, 1):
                if source == dest:
                    error = prefix_validation_error(
                        ValidationError(
                            "Source machine cannot be a destination machine."),
                        prefix=item_invalid,
                        code="item_invalid",
                        params={"nth": index},
                    )
                    set_form_error(self, "destinations", error)
                else:
                    if storage:
                        try:
                            dest._get_storage_mapping_between_nodes(source)
                        except ValidationError as exc:
                            error = prefix_validation_error(
                                exc,
                                prefix=item_invalid,
                                code="item_invalid",
                                params={"nth": index},
                            )
                            set_form_error(self, "destinations", error)
                    if interfaces:
                        try:
                            dest._get_interface_mapping_between_nodes(source)
                        except ValidationError as exc:
                            error = prefix_validation_error(
                                exc,
                                prefix=item_invalid,
                                code="item_invalid",
                                params={"nth": index},
                            )
                            set_form_error(self, "destinations", error)
        if not storage and not interfaces:
            set_form_error(self, "__all__",
                           "Either storage or interfaces must be true.")
        return cleaned_data

    def save(self):
        """Clone the storage and/or interfaces configuration to the
        destinations."""
        source = self.cleaned_data.get("source")
        destinations = self.cleaned_data.get("destinations")
        storage = self.cleaned_data.get("storage", False)
        interfaces = self.cleaned_data.get("interfaces", False)
        for dest in destinations:
            if storage:
                dest.set_storage_configuration_from_node(source)
            if interfaces:
                dest.set_networking_configuration_from_node(source)
Пример #4
0
class CloneForm(forms.Form):
    """Clone storage/interface form."""

    source = NodeChoiceField(
        label="Source",
        queryset=Machine.objects.all(),
        required=True,
        initial=None,
        help_text="The source machine to clone from.",
    )

    destinations = SimpleArrayField(
        NodeChoiceField(queryset=Machine.objects.all()),
        label="Destinations",
        min_length=1,
        error_messages={
            "item_invalid": "Machine %(nth)s is invalid:",
            "is-source":
            "Source machine %(machine)s cannot be a destination machine.",
            "storage": "%(machine)s is invalid:",
            "networking": "%(machine)s is invalid:",
        },
        help_text="The destinations to clone to.",
    )

    storage = forms.BooleanField(
        label="Storage",
        required=False,
        help_text="Clone the storage configuration.",
    )

    interfaces = forms.BooleanField(
        label="Interfaces",
        required=False,
        help_text="Clone the interfaces configuration.",
    )

    def __init__(self, user, **kwargs):
        self.user = user
        super().__init__(**kwargs)
        self.fields["source"].queryset = Machine.objects.get_nodes(
            self.user, NodePermission.view)
        self.fields[
            "destinations"].base_field.queryset = Machine.objects.get_nodes(
                self.user,
                NodePermission.admin,
                from_nodes=Machine.objects.filter(
                    status__in={NODE_STATUS.READY, NODE_STATUS.FAILED_TESTING
                                }),
            )

    def clean(self):
        """Validate that the form is valid and that the destinations can accept
        the storage and/or interfaces configuration from the source."""
        cleaned_data = super().clean()
        source = self.cleaned_data.get("source")
        if not source:
            # Django should be placing this automatically, but it does not
            # occur. So we force the setting of this error here.
            self.add_error("source", "This field is required.")
        destinations = self.cleaned_data.get("destinations")
        destination_field = self.fields["destinations"]
        storage = self.cleaned_data.get("storage", False)
        interfaces = self.cleaned_data.get("interfaces", False)
        if source and destinations:
            for dest in destinations:
                if source == dest:
                    error = ValidationError(
                        destination_field.error_messages["is-source"],
                        code="is-source",
                        params={
                            "machine": str(dest),
                            "system_id": dest.system_id,
                        },
                    )
                    self.add_error("destinations", error)
                else:
                    if storage:
                        try:
                            dest._get_storage_mapping_between_nodes(source)
                        except ValidationError as exc:
                            error = prefix_validation_error(
                                exc,
                                prefix=destination_field.
                                error_messages["storage"],
                                code="storage",
                                params={
                                    "machine": str(dest),
                                    "system_id": dest.system_id,
                                },
                            )
                            self.add_error("destinations", error)
                    if interfaces:
                        try:
                            dest._get_interface_mapping_between_nodes(source)
                        except ValidationError as exc:
                            error = prefix_validation_error(
                                exc,
                                prefix=destination_field.
                                error_messages["networking"],
                                code="networking",
                                params={
                                    "machine": str(dest),
                                    "system_id": dest.system_id,
                                },
                            )
                            self.add_error("destinations", error)
        if not storage and not interfaces:
            self.add_error(
                "__all__",
                ValidationError(
                    "Either storage or interfaces must be true.",
                    code="required",
                ),
            )
        return cleaned_data

    def strip_failed_destinations(self):
        """Remove destinations that have errors."""
        if "destinations" not in self.cleaned_data:
            submitted_destinations = self.data.get("destinations")
            # Don't try and manipulate empty submission
            if not submitted_destinations:
                return
            errors = self.errors.as_data()
            bogus_system_ids = {
                error.params["system_id"]
                for error in errors["destinations"]
            }
            return [
                dest for dest in submitted_destinations
                if dest not in bogus_system_ids
            ]

    def save(self):
        """Clone the storage and/or interfaces configuration to the
        destinations."""
        source = self.cleaned_data.get("source")
        destinations = self.cleaned_data.get("destinations", [])
        storage = self.cleaned_data.get("storage", False)
        interfaces = self.cleaned_data.get("interfaces", False)
        for dest in destinations:
            if storage:
                dest.set_storage_configuration_from_node(source)
            if interfaces:
                dest.set_networking_configuration_from_node(source)