class Meta: model = VirtualMachine fields = [ "name", "status", "cluster_group", "cluster", "role", "tenant_group", "tenant", "platform", "primary_ip4", "primary_ip6", "vcpus", "memory", "disk", "comments", "tags", "local_context_data", ] help_texts = { "local_context_data": "Local config context data overwrites all sources contexts in the final rendered " "config context", } widgets = { "primary_ip4": StaticSelect2(), "primary_ip6": StaticSelect2(), }
class WebhookFilterForm(BootstrapMixin, forms.Form): model = Webhook q = forms.CharField(required=False, label="Search") content_types = MultipleContentTypeField( feature="webhooks", choices_as_strings=True, required=False, label="Content Type(s)" ) type_create = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES)) type_update = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES)) type_delete = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES)) enabled = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES))
class IPAddressFilterForm(BootstrapMixin, TenancyFilterForm, StatusFilterFormMixin, CustomFieldFilterForm): model = IPAddress field_order = [ "q", "parent", "family", "mask_length", "vrf_id", "present_in_vrf_id", "status", "role", "assigned_to_interface", "tenant_group", "tenant", ] q = forms.CharField(required=False, label="Search") parent = forms.CharField( required=False, widget=forms.TextInput(attrs={ "placeholder": "Prefix", }), label="Parent Prefix", ) family = forms.ChoiceField( required=False, choices=add_blank_choice(IPAddressFamilyChoices), label="Address family", widget=StaticSelect2(), ) mask_length = forms.ChoiceField( required=False, choices=IPADDRESS_MASK_LENGTH_CHOICES, label="Mask length", widget=StaticSelect2(), ) vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, label="Assigned VRF", null_option="Global", ) present_in_vrf_id = DynamicModelChoiceField(queryset=VRF.objects.all(), required=False, label="Present in VRF") role = forms.MultipleChoiceField(choices=IPAddressRoleChoices, required=False, widget=StaticSelect2Multiple()) assigned_to_interface = forms.NullBooleanField( required=False, label="Assigned to an interface", widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES), ) tag = TagFilterField(model)
class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, StatusBulkEditFormMixin, CustomFieldBulkEditForm): pk = forms.ModelMultipleChoiceField(queryset=IPAddress.objects.all(), widget=forms.MultipleHiddenInput()) vrf = DynamicModelChoiceField( queryset=VRF.objects.all(), required=False, label="VRF", display_field="display_name", ) mask_length = forms.IntegerField( min_value=IPADDRESS_MASK_LENGTH_MIN, max_value=IPADDRESS_MASK_LENGTH_MAX, required=False, ) tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False) role = forms.ChoiceField( choices=add_blank_choice(IPAddressRoleChoices), required=False, widget=StaticSelect2(), ) dns_name = forms.CharField(max_length=255, required=False) description = forms.CharField(max_length=100, required=False) class Meta: nullable_fields = [ "vrf", "role", "tenant", "dns_name", "description", ]
class ObjectChangeFilterForm(BootstrapMixin, forms.Form): model = ObjectChange q = forms.CharField(required=False, label="Search") time_after = forms.DateTimeField(label="After", required=False, widget=DateTimePicker()) time_before = forms.DateTimeField(label="Before", required=False, widget=DateTimePicker()) action = forms.ChoiceField( choices=add_blank_choice(ObjectChangeActionChoices), required=False, widget=StaticSelect2(), ) user_id = DynamicModelMultipleChoiceField( queryset=get_user_model().objects.all(), required=False, label="User", widget=APISelectMultiple(api_url="/api/users/users/", ), ) changed_object_type_id = DynamicModelMultipleChoiceField( queryset=ContentType.objects.all(), required=False, label="Object Type", widget=APISelectMultiple(api_url="/api/extras/content-types/", ), )
class VirtualMachineFilterForm( BootstrapMixin, TenancyFilterForm, StatusFilterFormMixin, CustomFieldFilterForm, LocalContextFilterForm ): model = VirtualMachine field_order = [ "q", "cluster_group", "cluster_type", "cluster_id", "status", "role", "region", "site", "tenant_group", "tenant", "platform", "mac_address", ] q = forms.CharField(required=False, label="Search") cluster_group = DynamicModelMultipleChoiceField( queryset=ClusterGroup.objects.all(), to_field_name="slug", required=False, null_option="None", ) cluster_type = DynamicModelMultipleChoiceField( queryset=ClusterType.objects.all(), to_field_name="slug", required=False, null_option="None", ) cluster_id = DynamicModelMultipleChoiceField(queryset=Cluster.objects.all(), required=False, label="Cluster") region = DynamicModelMultipleChoiceField(queryset=Region.objects.all(), to_field_name="slug", required=False) site = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), to_field_name="slug", required=False, null_option="None", query_params={"region": "$region"}, ) role = DynamicModelMultipleChoiceField( queryset=DeviceRole.objects.filter(vm_role=True), to_field_name="slug", required=False, null_option="None", query_params={"vm_role": "True"}, ) platform = DynamicModelMultipleChoiceField( queryset=Platform.objects.all(), to_field_name="slug", required=False, null_option="None", ) mac_address = forms.CharField(required=False, label="MAC address") has_primary_ip = forms.NullBooleanField( required=False, label="Has a primary IP", widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES), ) tag = TagFilterField(model)
class SecretForm(BootstrapMixin, CustomFieldModelForm, RelationshipModelForm): """Create/update form for `Secret` objects.""" slug = SlugField() provider = forms.ChoiceField(choices=provider_choices, widget=StaticSelect2()) parameters = JSONField( help_text= 'Enter parameters in <a href="https://json.org/">JSON</a> format.') tags = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False) class Meta: model = Secret fields = [ "name", "slug", "description", "provider", "parameters", "tags", ]
class RIRFilterForm(BootstrapMixin, CustomFieldFilterForm): model = RIR is_private = forms.NullBooleanField( required=False, label="Private", widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES), )
class VMInterfaceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm): pk = forms.ModelMultipleChoiceField(queryset=VMInterface.objects.all(), widget=forms.MultipleHiddenInput()) virtual_machine = forms.ModelChoiceField( queryset=VirtualMachine.objects.all(), required=False, disabled=True, widget=forms.HiddenInput(), ) enabled = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect()) mtu = forms.IntegerField( required=False, min_value=INTERFACE_MTU_MIN, max_value=INTERFACE_MTU_MAX, label="MTU", ) description = forms.CharField(max_length=100, required=False) mode = forms.ChoiceField( choices=add_blank_choice(InterfaceModeChoices), required=False, widget=StaticSelect2(), ) untagged_vlan = DynamicModelChoiceField( queryset=VLAN.objects.all(), required=False, display_field="display_name", brief_mode=False, query_params={ "site_id": "null", }, ) tagged_vlans = DynamicModelMultipleChoiceField( queryset=VLAN.objects.all(), required=False, display_field="display_name", brief_mode=False, query_params={ "site_id": "null", }, ) class Meta: nullable_fields = [ "mtu", "description", ] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Limit available VLANs based on the parent VirtualMachine if "virtual_machine" in self.initial: parent_obj = VirtualMachine.objects.filter(pk=self.initial["virtual_machine"]).first() site = getattr(parent_obj.cluster, "site", None) if site is not None: # Add current site to VLANs query params self.fields["untagged_vlan"].widget.add_query_param("site_id", site.pk) self.fields["tagged_vlans"].widget.add_query_param("site_id", site.pk)
class LocalContextFilterForm(forms.Form): local_context_data = forms.NullBooleanField( required=False, label="Has local config context data", widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES), ) local_context_schema = DynamicModelMultipleChoiceField( queryset=ConfigContextSchema.objects.all(), to_field_name="slug", required=False )
class VMInterfaceFilterForm(BootstrapMixin, CustomFieldFilterForm): model = VMInterface cluster_id = DynamicModelMultipleChoiceField(queryset=Cluster.objects.all(), required=False, label="Cluster") virtual_machine_id = DynamicModelMultipleChoiceField( queryset=VirtualMachine.objects.all(), required=False, label="Virtual machine", query_params={"cluster_id": "$cluster_id"}, ) enabled = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES)) tag = TagFilterField(model)
class AggregateFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFilterForm): model = Aggregate q = forms.CharField(required=False, label="Search") family = forms.ChoiceField( required=False, choices=add_blank_choice(IPAddressFamilyChoices), label="Address family", widget=StaticSelect2(), ) rir = DynamicModelMultipleChoiceField(queryset=RIR.objects.all(), to_field_name="slug", required=False, label="RIR") tag = TagFilterField(model)
class VMInterfaceCreateForm(BootstrapMixin, InterfaceCommonForm): virtual_machine = DynamicModelChoiceField( queryset=VirtualMachine.objects.all()) name_pattern = ExpandableNameField(label="Name") enabled = forms.BooleanField(required=False, initial=True) mtu = forms.IntegerField( required=False, min_value=INTERFACE_MTU_MIN, max_value=INTERFACE_MTU_MAX, label="MTU", ) mac_address = forms.CharField(required=False, label="MAC Address") description = forms.CharField(max_length=100, required=False) mode = forms.ChoiceField( choices=add_blank_choice(InterfaceModeChoices), required=False, widget=StaticSelect2(), ) untagged_vlan = DynamicModelChoiceField( queryset=VLAN.objects.all(), required=False, display_field="display_name", brief_mode=False, query_params={ "site_id": "null", }, ) tagged_vlans = DynamicModelMultipleChoiceField( queryset=VLAN.objects.all(), required=False, display_field="display_name", brief_mode=False, query_params={ "site_id": "null", }, ) tags = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) virtual_machine = VirtualMachine.objects.get( pk=self.initial.get("virtual_machine") or self.data.get("virtual_machine")) # Add current site to VLANs query params site = virtual_machine.site if site: self.fields["untagged_vlan"].widget.add_query_param( "site_id", site.pk) self.fields["tagged_vlans"].widget.add_query_param( "site_id", site.pk)
class WebhookFilterForm(BootstrapMixin, forms.Form): model = Webhook q = forms.CharField(required=False, label="Search") content_types = forms.ModelMultipleChoiceField( queryset=ContentType.objects.filter( FeatureQuery("webhooks").get_query()).order_by( "app_label", "model"), required=False, label="Content Types", ) type_create = forms.NullBooleanField( required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES)) type_update = forms.NullBooleanField( required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES)) type_delete = forms.NullBooleanField( required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES)) enabled = forms.NullBooleanField( required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES))
class JobResultFilterForm(BootstrapMixin, forms.Form): model = JobResult q = forms.CharField(required=False, label="Search") # FIXME(glenn) Filtering by obj_type? name = forms.CharField(required=False) user = DynamicModelMultipleChoiceField( queryset=get_user_model().objects.all(), required=False, label="User", widget=APISelectMultiple(api_url="/api/users/users/", ), ) status = forms.ChoiceField( choices=add_blank_choice(JobResultStatusChoices), required=False, widget=StaticSelect2(), )
class Meta: model = IPAddress fields = [ "address", "vrf", "status", "role", "dns_name", "description", "tenant_group", "tenant", "tags", ] widgets = { "role": StaticSelect2(), }
class ServiceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm): pk = forms.ModelMultipleChoiceField(queryset=Service.objects.all(), widget=forms.MultipleHiddenInput()) protocol = forms.ChoiceField( choices=add_blank_choice(ServiceProtocolChoices), required=False, widget=StaticSelect2(), ) ports = NumericArrayField( base_field=forms.IntegerField(min_value=SERVICE_PORT_MIN, max_value=SERVICE_PORT_MAX), required=False, ) description = forms.CharField(max_length=100, required=False) class Meta: nullable_fields = [ "description", ]
class Meta: model = Service fields = [ "name", "protocol", "ports", "ipaddresses", "description", "tags", ] help_texts = { "ipaddresses": "IP address assignment is optional. If no IPs are selected, the service is assumed to be " "reachable via all IPs assigned to the device.", } widgets = { "protocol": StaticSelect2(), "ipaddresses": StaticSelect2Multiple(), }
class Meta: model = VMInterface fields = [ "virtual_machine", "name", "enabled", "mac_address", "mtu", "description", "mode", "tags", "untagged_vlan", "tagged_vlans", ] widgets = {"virtual_machine": forms.HiddenInput(), "mode": StaticSelect2()} labels = { "mode": "802.1Q Mode", } help_texts = { "mode": INTERFACE_MODE_HELP_TEXT, }
class Meta: model = IPAddress fields = [ "address", "vrf", "status", "role", "dns_name", "description", "primary_for_parent", "nat_site", "nat_rack", "nat_device", "nat_cluster", "nat_virtual_machine", "nat_vrf", "nat_inside", "tenant_group", "tenant", "tags", ] widgets = { "role": StaticSelect2(), }
def to_form_field(self, set_initial=True, enforce_required=True, for_csv_import=False): """ Return a form field suitable for setting a CustomField's value for an object. set_initial: Set initial date for the field. This should be False when generating a field for bulk editing. enforce_required: Honor the value of CustomField.required. Set to False for filtering/bulk editing. for_csv_import: Return a form field suitable for bulk import of objects in CSV format. """ initial = self.default if set_initial else None required = self.required if enforce_required else False # Integer if self.type == CustomFieldTypeChoices.TYPE_INTEGER: field = forms.IntegerField( required=required, initial=initial, min_value=self.validation_minimum, max_value=self.validation_maximum, ) # Boolean elif self.type == CustomFieldTypeChoices.TYPE_BOOLEAN: choices = ( (None, "---------"), (True, "True"), (False, "False"), ) field = forms.NullBooleanField( required=required, initial=initial, widget=StaticSelect2(choices=choices), ) # Date elif self.type == CustomFieldTypeChoices.TYPE_DATE: field = forms.DateField(required=required, initial=initial, widget=DatePicker()) # URL elif self.type == CustomFieldTypeChoices.TYPE_URL: field = LaxURLField(required=required, initial=initial) # Text elif self.type == CustomFieldTypeChoices.TYPE_TEXT: field = forms.CharField(max_length=255, required=required, initial=initial) if self.validation_regex: field.validators = [ RegexValidator( regex=self.validation_regex, message=mark_safe( f"Values must match this regex: <code>{self.validation_regex}</code>" ), ) ] # Select or Multi-select else: choices = [(cfc.value, cfc.value) for cfc in self.choices.all()] default_choice = self.choices.filter(value=self.default).first() if not required or default_choice is None: choices = add_blank_choice(choices) # Set the initial value to the first available choice (if any) if set_initial and default_choice: initial = default_choice.value if self.type == CustomFieldTypeChoices.TYPE_SELECT: field_class = CSVChoiceField if for_csv_import else forms.ChoiceField field = field_class( choices=choices, required=required, initial=initial, widget=StaticSelect2(), ) else: field_class = CSVMultipleChoiceField if for_csv_import else forms.MultipleChoiceField field = field_class(choices=choices, required=required, initial=initial, widget=StaticSelect2Multiple()) field.model = self field.label = str(self) if self.description: field.help_text = self.description return field
class LocalConfigContextFilterForm(forms.Form): local_context_data = forms.NullBooleanField( required=False, label="Has local config context data", widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES), )
class PrefixFilterForm(BootstrapMixin, TenancyFilterForm, StatusFilterFormMixin, CustomFieldFilterForm): model = Prefix field_order = [ "q", "within_include", "family", "mask_length", "vrf_id", "present_in_vrf_id", "status", "region", "site", "role", "tenant_group", "tenant", "is_pool", "expand", ] mask_length__lte = forms.IntegerField(widget=forms.HiddenInput()) q = forms.CharField(required=False, label="Search") within_include = forms.CharField( required=False, widget=forms.TextInput(attrs={ "placeholder": "Prefix", }), label="Search within", ) family = forms.ChoiceField( required=False, choices=add_blank_choice(IPAddressFamilyChoices), label="Address family", widget=StaticSelect2(), ) mask_length = forms.ChoiceField( required=False, choices=PREFIX_MASK_LENGTH_CHOICES, label="Mask length", widget=StaticSelect2(), ) vrf_id = DynamicModelMultipleChoiceField( queryset=VRF.objects.all(), required=False, label="Assigned VRF", null_option="Global", ) present_in_vrf_id = DynamicModelChoiceField(queryset=VRF.objects.all(), required=False, label="Present in VRF") region = DynamicModelMultipleChoiceField(queryset=Region.objects.all(), to_field_name="slug", required=False) site = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), to_field_name="slug", required=False, null_option="None", query_params={"region": "$region"}, ) role = DynamicModelMultipleChoiceField( queryset=Role.objects.all(), to_field_name="slug", required=False, null_option="None", ) is_pool = forms.NullBooleanField( required=False, label="Is a pool", widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES), ) tag = TagFilterField(model)