netbox-plugin-dns 0.21.4__py3-none-any.whl → 1.4.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- netbox_dns/__init__.py +106 -41
- netbox_dns/api/field_serializers.py +25 -0
- netbox_dns/api/nested_serializers.py +95 -52
- netbox_dns/api/serializers.py +14 -296
- netbox_dns/api/serializers_/__init__.py +0 -0
- netbox_dns/api/serializers_/dnssec_key_template.py +69 -0
- netbox_dns/api/serializers_/dnssec_policy.py +165 -0
- netbox_dns/api/serializers_/nameserver.py +56 -0
- netbox_dns/api/serializers_/prefix.py +18 -0
- netbox_dns/api/serializers_/record.py +105 -0
- netbox_dns/api/serializers_/record_template.py +71 -0
- netbox_dns/api/serializers_/registrar.py +45 -0
- netbox_dns/api/serializers_/registration_contact.py +50 -0
- netbox_dns/api/serializers_/view.py +81 -0
- netbox_dns/api/serializers_/zone.py +247 -0
- netbox_dns/api/serializers_/zone_template.py +157 -0
- netbox_dns/api/urls.py +13 -2
- netbox_dns/api/views.py +96 -58
- netbox_dns/choices/__init__.py +4 -0
- netbox_dns/choices/dnssec_key_template.py +67 -0
- netbox_dns/choices/dnssec_policy.py +40 -0
- netbox_dns/choices/record.py +104 -0
- netbox_dns/choices/utilities.py +4 -0
- netbox_dns/choices/zone.py +119 -0
- netbox_dns/fields/__init__.py +4 -0
- netbox_dns/fields/address.py +22 -16
- netbox_dns/fields/choice_array.py +33 -0
- netbox_dns/fields/ipam.py +15 -0
- netbox_dns/fields/network.py +42 -18
- netbox_dns/fields/rfc2317.py +97 -0
- netbox_dns/fields/timeperiod.py +33 -0
- netbox_dns/filters.py +7 -0
- netbox_dns/filtersets/__init__.py +12 -0
- netbox_dns/filtersets/dnssec_key_template.py +57 -0
- netbox_dns/filtersets/dnssec_policy.py +101 -0
- netbox_dns/filtersets/nameserver.py +46 -0
- netbox_dns/filtersets/record.py +135 -0
- netbox_dns/filtersets/record_template.py +59 -0
- netbox_dns/{filters → filtersets}/registrar.py +8 -1
- netbox_dns/{filters/contact.py → filtersets/registration_contact.py} +9 -3
- netbox_dns/filtersets/view.py +45 -0
- netbox_dns/filtersets/zone.py +254 -0
- netbox_dns/filtersets/zone_template.py +165 -0
- netbox_dns/forms/__init__.py +5 -1
- netbox_dns/forms/dnssec_key_template.py +250 -0
- netbox_dns/forms/dnssec_policy.py +654 -0
- netbox_dns/forms/nameserver.py +121 -27
- netbox_dns/forms/record.py +215 -104
- netbox_dns/forms/record_template.py +285 -0
- netbox_dns/forms/registrar.py +108 -31
- netbox_dns/forms/registration_contact.py +282 -0
- netbox_dns/forms/view.py +331 -20
- netbox_dns/forms/zone.py +769 -373
- netbox_dns/forms/zone_template.py +463 -0
- netbox_dns/graphql/__init__.py +25 -22
- netbox_dns/graphql/enums.py +41 -0
- netbox_dns/graphql/filter_lookups.py +13 -0
- netbox_dns/graphql/filters/__init__.py +12 -0
- netbox_dns/graphql/filters/dnssec_key_template.py +63 -0
- netbox_dns/graphql/filters/dnssec_policy.py +124 -0
- netbox_dns/graphql/filters/nameserver.py +32 -0
- netbox_dns/graphql/filters/record.py +89 -0
- netbox_dns/graphql/filters/record_template.py +55 -0
- netbox_dns/graphql/filters/registrar.py +30 -0
- netbox_dns/graphql/filters/registration_contact.py +27 -0
- netbox_dns/graphql/filters/view.py +28 -0
- netbox_dns/graphql/filters/zone.py +147 -0
- netbox_dns/graphql/filters/zone_template.py +97 -0
- netbox_dns/graphql/schema.py +89 -7
- netbox_dns/graphql/types.py +355 -0
- netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
- netbox_dns/locale/en/LC_MESSAGES/django.mo +0 -0
- netbox_dns/locale/fr/LC_MESSAGES/django.mo +0 -0
- netbox_dns/management/commands/cleanup_database.py +175 -156
- netbox_dns/management/commands/cleanup_rrset_ttl.py +64 -0
- netbox_dns/management/commands/rebuild_dnssync.py +23 -0
- netbox_dns/management/commands/setup_dnssync.py +140 -0
- netbox_dns/migrations/0001_squashed_netbox_dns_0_15.py +0 -27
- netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +557 -0
- netbox_dns/migrations/{0013_add_nameserver_zone_record_description.py → 0002_contact_description_registrar_description.py} +4 -9
- netbox_dns/migrations/0003_default_view.py +15 -0
- netbox_dns/migrations/0004_create_and_assign_default_view.py +26 -0
- netbox_dns/migrations/0005_alter_zone_view_not_null.py +18 -0
- netbox_dns/migrations/0006_templating.py +172 -0
- netbox_dns/migrations/0007_alter_ordering_options.py +25 -0
- netbox_dns/migrations/0008_view_prefixes.py +18 -0
- netbox_dns/migrations/0009_rename_contact_registrationcontact.py +36 -0
- netbox_dns/migrations/0010_view_ip_address_filter.py +18 -0
- netbox_dns/migrations/0011_rename_related_fields.py +63 -0
- netbox_dns/migrations/0012_natural_ordering.py +88 -0
- netbox_dns/migrations/0013_zonetemplate_soa_mname_zonetemplate_soa_rname.py +30 -0
- netbox_dns/migrations/0014_alter_unique_constraints_lowercase.py +42 -0
- netbox_dns/migrations/0015_dnssec.py +168 -0
- netbox_dns/migrations/{0015_add_record_status.py → 0016_dnssec_policy_status.py} +5 -4
- netbox_dns/migrations/0017_dnssec_policy_zone_zone_template.py +41 -0
- netbox_dns/migrations/0018_zone_domain_status_zone_expiration_date.py +23 -0
- netbox_dns/migrations/0019_dnssecpolicy_parental_agents.py +25 -0
- netbox_dns/migrations/0020_netbox_3_4.py +1 -1
- netbox_dns/migrations/0020_remove_dnssecpolicy_parental_agents_and_more.py +29 -0
- netbox_dns/migrations/0021_alter_record_ptr_record.py +25 -0
- netbox_dns/migrations/0021_record_ip_address.py +1 -1
- netbox_dns/migrations/0022_alter_record_ipam_ip_address.py +26 -0
- netbox_dns/migrations/0023_disable_ptr_false.py +27 -0
- netbox_dns/migrations/0024_zonetemplate_parental_agents.py +25 -0
- netbox_dns/migrations/0025_remove_zone_inline_signing_and_more.py +22 -0
- netbox_dns/migrations/0026_alter_dnssecpolicy_nsec3_opt_out.py +18 -0
- netbox_dns/migrations/0026_domain_registration.py +1 -1
- netbox_dns/migrations/0027_zone_comments.py +18 -0
- netbox_dns/migrations/0028_alter_zone_default_ttl_alter_zone_soa_minimum_and_more.py +54 -0
- netbox_dns/migrations/0028_rfc2317_fields.py +44 -0
- netbox_dns/migrations/0029_alter_registrationcontact_street.py +18 -0
- netbox_dns/migrations/0029_record_fqdn.py +30 -0
- netbox_dns/mixins/__init__.py +1 -0
- netbox_dns/mixins/object_modification.py +57 -0
- netbox_dns/models/__init__.py +5 -1
- netbox_dns/models/dnssec_key_template.py +114 -0
- netbox_dns/models/dnssec_policy.py +203 -0
- netbox_dns/models/nameserver.py +61 -30
- netbox_dns/models/record.py +781 -234
- netbox_dns/models/record_template.py +198 -0
- netbox_dns/models/registrar.py +34 -15
- netbox_dns/models/{contact.py → registration_contact.py} +72 -43
- netbox_dns/models/view.py +129 -9
- netbox_dns/models/zone.py +806 -242
- netbox_dns/models/zone_template.py +209 -0
- netbox_dns/navigation.py +176 -76
- netbox_dns/signals/__init__.py +0 -0
- netbox_dns/signals/dnssec.py +32 -0
- netbox_dns/signals/ipam_dnssync.py +216 -0
- netbox_dns/tables/__init__.py +5 -1
- netbox_dns/tables/dnssec_key_template.py +49 -0
- netbox_dns/tables/dnssec_policy.py +140 -0
- netbox_dns/tables/ipam_dnssync.py +12 -0
- netbox_dns/tables/nameserver.py +14 -17
- netbox_dns/tables/record.py +117 -59
- netbox_dns/tables/record_template.py +91 -0
- netbox_dns/tables/registrar.py +20 -10
- netbox_dns/tables/{contact.py → registration_contact.py} +22 -11
- netbox_dns/tables/view.py +47 -3
- netbox_dns/tables/zone.py +62 -31
- netbox_dns/tables/zone_template.py +78 -0
- netbox_dns/template_content.py +124 -38
- netbox_dns/templates/netbox_dns/dnsseckeytemplate.html +70 -0
- netbox_dns/templates/netbox_dns/dnssecpolicy.html +163 -0
- netbox_dns/templates/netbox_dns/nameserver.html +31 -28
- netbox_dns/templates/netbox_dns/record/managed.html +2 -1
- netbox_dns/templates/netbox_dns/record/related.html +17 -6
- netbox_dns/templates/netbox_dns/record.html +140 -93
- netbox_dns/templates/netbox_dns/recordtemplate.html +96 -0
- netbox_dns/templates/netbox_dns/registrar.html +41 -34
- netbox_dns/templates/netbox_dns/registrationcontact.html +76 -0
- netbox_dns/templates/netbox_dns/view/button.html +10 -0
- netbox_dns/templates/netbox_dns/view/prefix.html +44 -0
- netbox_dns/templates/netbox_dns/view/related.html +33 -0
- netbox_dns/templates/netbox_dns/view.html +62 -18
- netbox_dns/templates/netbox_dns/zone/base.html +6 -3
- netbox_dns/templates/netbox_dns/zone/child.html +6 -5
- netbox_dns/templates/netbox_dns/zone/child_zone.html +18 -0
- netbox_dns/templates/netbox_dns/zone/delegation_record.html +18 -0
- netbox_dns/templates/netbox_dns/zone/managed_record.html +1 -1
- netbox_dns/templates/netbox_dns/zone/record.html +6 -5
- netbox_dns/templates/netbox_dns/zone/registration.html +43 -24
- netbox_dns/templates/netbox_dns/zone/rfc2317_child_zone.html +18 -0
- netbox_dns/templates/netbox_dns/zone.html +178 -119
- netbox_dns/templates/netbox_dns/zonetemplate/child.html +46 -0
- netbox_dns/templates/netbox_dns/zonetemplate.html +124 -0
- netbox_dns/templatetags/netbox_dns.py +10 -0
- netbox_dns/urls.py +50 -210
- netbox_dns/utilities/__init__.py +3 -0
- netbox_dns/{utilities.py → utilities/conversions.py} +55 -7
- netbox_dns/utilities/dns.py +11 -0
- netbox_dns/utilities/ipam_dnssync.py +370 -0
- netbox_dns/validators/__init__.py +4 -0
- netbox_dns/validators/dns_name.py +116 -0
- netbox_dns/validators/dns_value.py +147 -0
- netbox_dns/validators/dnssec.py +148 -0
- netbox_dns/validators/rfc2317.py +28 -0
- netbox_dns/views/__init__.py +5 -1
- netbox_dns/views/dnssec_key_template.py +78 -0
- netbox_dns/views/dnssec_policy.py +146 -0
- netbox_dns/views/nameserver.py +34 -15
- netbox_dns/views/record.py +156 -15
- netbox_dns/views/record_template.py +93 -0
- netbox_dns/views/registrar.py +32 -13
- netbox_dns/views/registration_contact.py +101 -0
- netbox_dns/views/view.py +58 -14
- netbox_dns/views/zone.py +130 -33
- netbox_dns/views/zone_template.py +82 -0
- netbox_plugin_dns-1.4.7.dist-info/METADATA +132 -0
- netbox_plugin_dns-1.4.7.dist-info/RECORD +201 -0
- {netbox_plugin_dns-0.21.4.dist-info → netbox_plugin_dns-1.4.7.dist-info}/WHEEL +2 -1
- {netbox_plugin_dns-0.21.4.dist-info → netbox_plugin_dns-1.4.7.dist-info/licenses}/LICENSE +2 -1
- netbox_plugin_dns-1.4.7.dist-info/top_level.txt +1 -0
- netbox_dns/filters/__init__.py +0 -6
- netbox_dns/filters/nameserver.py +0 -18
- netbox_dns/filters/record.py +0 -53
- netbox_dns/filters/view.py +0 -18
- netbox_dns/filters/zone.py +0 -112
- netbox_dns/forms/contact.py +0 -211
- netbox_dns/graphql/contact.py +0 -19
- netbox_dns/graphql/nameserver.py +0 -19
- netbox_dns/graphql/record.py +0 -19
- netbox_dns/graphql/registrar.py +0 -19
- netbox_dns/graphql/view.py +0 -19
- netbox_dns/graphql/zone.py +0 -19
- netbox_dns/management/commands/setup_coupling.py +0 -75
- netbox_dns/management/commands/update_soa.py +0 -22
- netbox_dns/middleware.py +0 -226
- netbox_dns/migrations/0001_initial.py +0 -115
- netbox_dns/migrations/0002_zone_default_ttl.py +0 -18
- netbox_dns/migrations/0003_soa_managed_records.py +0 -112
- netbox_dns/migrations/0004_create_ptr_for_a_aaaa_records.py +0 -80
- netbox_dns/migrations/0005_update_ns_records.py +0 -41
- netbox_dns/migrations/0006_zone_soa_serial_auto.py +0 -29
- netbox_dns/migrations/0007_alter_zone_soa_serial_auto.py +0 -17
- netbox_dns/migrations/0008_zone_status_names.py +0 -21
- netbox_dns/migrations/0009_netbox32.py +0 -71
- netbox_dns/migrations/0010_update_soa_records.py +0 -58
- netbox_dns/migrations/0011_add_view_model.py +0 -70
- netbox_dns/migrations/0012_adjust_zone_and_record.py +0 -17
- netbox_dns/migrations/0014_add_view_description.py +0 -16
- netbox_dns/migrations/0016_cleanup_ptr_records.py +0 -38
- netbox_dns/migrations/0017_alter_record_ttl.py +0 -17
- netbox_dns/migrations/0018_zone_arpa_network.py +0 -51
- netbox_dns/migrations/0019_update_ns_ttl.py +0 -19
- netbox_dns/templates/netbox_dns/contact.html +0 -71
- netbox_dns/templates/netbox_dns/related_dns_objects.html +0 -21
- netbox_dns/templatetags/view_helpers.py +0 -15
- netbox_dns/validators.py +0 -57
- netbox_dns/views/contact.py +0 -83
- netbox_plugin_dns-0.21.4.dist-info/METADATA +0 -101
- netbox_plugin_dns-0.21.4.dist-info/RECORD +0 -110
netbox_dns/forms/zone.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
from django import forms
|
|
2
|
+
from django.db import models, transaction
|
|
2
3
|
from django.conf import settings
|
|
3
|
-
from django.core.exceptions import ValidationError
|
|
4
4
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
|
5
|
-
from django.
|
|
5
|
+
from django.core.exceptions import ValidationError
|
|
6
|
+
from django.contrib.postgres.forms import SimpleArrayField
|
|
7
|
+
from django.utils.translation import gettext_lazy as _
|
|
6
8
|
|
|
7
9
|
from netbox.forms import (
|
|
8
10
|
NetBoxModelBulkEditForm,
|
|
@@ -10,141 +12,277 @@ from netbox.forms import (
|
|
|
10
12
|
NetBoxModelImportForm,
|
|
11
13
|
NetBoxModelForm,
|
|
12
14
|
)
|
|
15
|
+
from netbox.context import events_queue
|
|
13
16
|
from utilities.forms.fields import (
|
|
14
17
|
DynamicModelMultipleChoiceField,
|
|
15
18
|
TagFilterField,
|
|
16
19
|
CSVChoiceField,
|
|
17
20
|
CSVModelChoiceField,
|
|
21
|
+
CSVModelMultipleChoiceField,
|
|
18
22
|
DynamicModelChoiceField,
|
|
23
|
+
CommentField,
|
|
19
24
|
)
|
|
20
|
-
from utilities.forms.widgets import BulkEditNullBooleanSelect,
|
|
21
|
-
from utilities.forms import
|
|
22
|
-
from
|
|
25
|
+
from utilities.forms.widgets import BulkEditNullBooleanSelect, DatePicker, HTMXSelect
|
|
26
|
+
from utilities.forms.rendering import FieldSet
|
|
27
|
+
from utilities.forms import (
|
|
28
|
+
BOOLEAN_WITH_BLANK_CHOICES,
|
|
29
|
+
add_blank_choice,
|
|
30
|
+
get_field_value,
|
|
31
|
+
)
|
|
32
|
+
from tenancy.models import Tenant, TenantGroup
|
|
23
33
|
from tenancy.forms import TenancyForm, TenancyFilterForm
|
|
24
34
|
|
|
25
35
|
from netbox_dns.models import (
|
|
26
36
|
View,
|
|
27
37
|
Zone,
|
|
28
|
-
ZoneStatusChoices,
|
|
29
38
|
NameServer,
|
|
30
39
|
Registrar,
|
|
31
|
-
|
|
40
|
+
RegistrationContact,
|
|
41
|
+
ZoneTemplate,
|
|
42
|
+
DNSSECPolicy,
|
|
32
43
|
)
|
|
33
|
-
from netbox_dns.
|
|
44
|
+
from netbox_dns.choices import ZoneStatusChoices, ZoneEPPStatusChoices
|
|
45
|
+
from netbox_dns.utilities import name_to_unicode, network_to_reverse
|
|
46
|
+
from netbox_dns.fields import RFC2317NetworkFormField, TimePeriodField
|
|
47
|
+
from netbox_dns.validators import validate_ipv4, validate_prefix, validate_rfc2317
|
|
34
48
|
|
|
35
49
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
label="SOA Responsible",
|
|
56
|
-
help_text="Mailbox of the zone's administrator",
|
|
57
|
-
)
|
|
58
|
-
soa_serial_auto = forms.BooleanField(
|
|
59
|
-
required=False,
|
|
60
|
-
label="Generate SOA Serial",
|
|
61
|
-
help_text="Automatically generate the SOA Serial",
|
|
62
|
-
)
|
|
63
|
-
soa_serial = forms.IntegerField(
|
|
64
|
-
required=False,
|
|
65
|
-
label="SOA Serial",
|
|
66
|
-
help_text="Serial number of the current zone data version",
|
|
67
|
-
validators=[MinValueValidator(1)],
|
|
68
|
-
)
|
|
69
|
-
soa_refresh = forms.IntegerField(
|
|
70
|
-
required=True,
|
|
71
|
-
label="SOA Refresh",
|
|
72
|
-
help_text="Refresh interval for secondary name servers",
|
|
73
|
-
validators=[MinValueValidator(1)],
|
|
74
|
-
)
|
|
75
|
-
soa_retry = forms.IntegerField(
|
|
76
|
-
required=True,
|
|
77
|
-
label="SOA Retry",
|
|
78
|
-
help_text="Retry interval for secondary name servers",
|
|
79
|
-
validators=[MinValueValidator(1)],
|
|
80
|
-
)
|
|
81
|
-
soa_expire = forms.IntegerField(
|
|
82
|
-
required=True,
|
|
83
|
-
label="SOA Expire",
|
|
84
|
-
help_text="Expire time after which the zone is considered unavailable",
|
|
85
|
-
validators=[MinValueValidator(1)],
|
|
86
|
-
)
|
|
87
|
-
soa_minimum = forms.IntegerField(
|
|
88
|
-
required=True,
|
|
89
|
-
label="SOA Minimum TTL",
|
|
90
|
-
help_text="Minimum TTL for negative results, e.g. NXRRSET",
|
|
91
|
-
validators=[MinValueValidator(1)],
|
|
92
|
-
)
|
|
93
|
-
fieldsets = (
|
|
94
|
-
(
|
|
95
|
-
"Zone",
|
|
96
|
-
(
|
|
97
|
-
"view",
|
|
98
|
-
"name",
|
|
99
|
-
"status",
|
|
100
|
-
"nameservers",
|
|
101
|
-
"default_ttl",
|
|
102
|
-
"description",
|
|
103
|
-
),
|
|
104
|
-
),
|
|
105
|
-
(
|
|
106
|
-
"SOA",
|
|
107
|
-
(
|
|
108
|
-
"soa_ttl",
|
|
50
|
+
__all__ = (
|
|
51
|
+
"ZoneForm",
|
|
52
|
+
"ZoneFilterForm",
|
|
53
|
+
"ZoneImportForm",
|
|
54
|
+
"ZoneBulkEditForm",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class RollbackTransaction(Exception):
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class ZoneTemplateUpdateMixin:
|
|
63
|
+
def _check_soa_mname(self):
|
|
64
|
+
if (
|
|
65
|
+
self.cleaned_data.get("soa_mname") is None
|
|
66
|
+
and "soa_mname" in self.fields.keys()
|
|
67
|
+
):
|
|
68
|
+
self.add_error(
|
|
109
69
|
"soa_mname",
|
|
110
|
-
"
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
70
|
+
_("soa_mname not set and no template or default value defined"),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def clean(self, *args, **kwargs):
|
|
74
|
+
super().clean(*args, **kwargs)
|
|
75
|
+
|
|
76
|
+
if (template := self.cleaned_data.get("template")) is None:
|
|
77
|
+
self._check_soa_mname()
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
if not self.cleaned_data.get("nameservers") and template.nameservers.all():
|
|
81
|
+
self.cleaned_data["nameservers"] = template.nameservers.all()
|
|
82
|
+
|
|
83
|
+
if not self.cleaned_data.get("tags") and template.tags.all():
|
|
84
|
+
self.cleaned_data["tags"] = template.tags.all()
|
|
85
|
+
|
|
86
|
+
for field in template.template_fields:
|
|
87
|
+
if self.cleaned_data.get(field) in (None, "", []) and getattr(
|
|
88
|
+
template, field
|
|
89
|
+
) not in (None, "", []):
|
|
90
|
+
self.cleaned_data[field] = getattr(template, field)
|
|
91
|
+
|
|
92
|
+
self._check_soa_mname()
|
|
93
|
+
|
|
94
|
+
if self.errors:
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
saved_events_queue = events_queue.get()
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
with transaction.atomic():
|
|
101
|
+
if self.instance.id is not None:
|
|
102
|
+
zone = super().save(*args, **kwargs)
|
|
103
|
+
else:
|
|
104
|
+
zone_data = self.cleaned_data.copy()
|
|
105
|
+
|
|
106
|
+
custom_fields = {}
|
|
107
|
+
for key, value in zone_data.copy().items():
|
|
108
|
+
if key.startswith("cf_"):
|
|
109
|
+
if isinstance(value, models.Model):
|
|
110
|
+
custom_fields[key[3:]] = value.pk
|
|
111
|
+
elif isinstance(value, models.QuerySet):
|
|
112
|
+
custom_fields[key[3:]] = list(
|
|
113
|
+
value.values_list("pk", flat=True)
|
|
114
|
+
)
|
|
115
|
+
else:
|
|
116
|
+
custom_fields[key[3:]] = value
|
|
117
|
+
zone_data.pop(key)
|
|
118
|
+
if custom_fields:
|
|
119
|
+
zone_data["custom_field_data"] = custom_fields
|
|
120
|
+
|
|
121
|
+
zone_data.pop("template", None)
|
|
122
|
+
zone_data.pop("tenant_group", None)
|
|
123
|
+
zone_data.pop("_init_time", None)
|
|
124
|
+
|
|
125
|
+
nameservers = zone_data.pop("nameservers")
|
|
126
|
+
tags = zone_data.pop("tags")
|
|
127
|
+
|
|
128
|
+
zone = Zone.objects.create(**zone_data)
|
|
129
|
+
|
|
130
|
+
zone.nameservers.set(nameservers)
|
|
131
|
+
zone.tags.set(tags)
|
|
132
|
+
|
|
133
|
+
template.create_records(zone)
|
|
134
|
+
raise RollbackTransaction
|
|
135
|
+
|
|
136
|
+
except ValidationError as exc:
|
|
137
|
+
if hasattr(exc, "error_dict"):
|
|
138
|
+
for field_name in self.fields.keys():
|
|
139
|
+
exc.error_dict.pop(field_name, None)
|
|
140
|
+
errors = exc.error_dict.values()
|
|
141
|
+
else:
|
|
142
|
+
errors = exc.messages
|
|
143
|
+
|
|
144
|
+
for error in errors:
|
|
145
|
+
self.add_error("template", error)
|
|
146
|
+
|
|
147
|
+
except RollbackTransaction:
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
events_queue.set(saved_events_queue)
|
|
151
|
+
|
|
152
|
+
return self.cleaned_data
|
|
153
|
+
|
|
154
|
+
def save(self, *args, **kwargs):
|
|
155
|
+
zone = super().save(*args, **kwargs)
|
|
156
|
+
|
|
157
|
+
if (template := self.cleaned_data.get("template")) is not None:
|
|
158
|
+
template.create_records(zone)
|
|
159
|
+
|
|
160
|
+
return zone
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class ZoneForm(ZoneTemplateUpdateMixin, TenancyForm, NetBoxModelForm):
|
|
164
|
+
class Meta:
|
|
165
|
+
model = Zone
|
|
166
|
+
|
|
167
|
+
fields = (
|
|
168
|
+
"name",
|
|
169
|
+
"view",
|
|
170
|
+
"status",
|
|
171
|
+
"template",
|
|
172
|
+
"nameservers",
|
|
173
|
+
"default_ttl",
|
|
174
|
+
"description",
|
|
175
|
+
"soa_ttl",
|
|
176
|
+
"soa_mname",
|
|
177
|
+
"soa_rname",
|
|
178
|
+
"soa_serial_auto",
|
|
179
|
+
"soa_serial",
|
|
180
|
+
"soa_refresh",
|
|
181
|
+
"soa_retry",
|
|
182
|
+
"soa_expire",
|
|
183
|
+
"soa_minimum",
|
|
184
|
+
"rfc2317_prefix",
|
|
185
|
+
"rfc2317_parent_managed",
|
|
186
|
+
"dnssec_policy",
|
|
187
|
+
"parental_agents",
|
|
188
|
+
"registrar",
|
|
189
|
+
"registry_domain_id",
|
|
190
|
+
"expiration_date",
|
|
191
|
+
"domain_status",
|
|
192
|
+
"registrant",
|
|
193
|
+
"admin_c",
|
|
194
|
+
"tech_c",
|
|
195
|
+
"billing_c",
|
|
196
|
+
"tenant_group",
|
|
197
|
+
"tenant",
|
|
198
|
+
"comments",
|
|
199
|
+
"tags",
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
labels = {
|
|
203
|
+
"soa_serial_auto": _("Generate SOA Serial"),
|
|
204
|
+
"rfc2317_parent_managed": _("RFC2317 Parent Managed"),
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
help_texts = {
|
|
208
|
+
"soa_serial_auto": _("Automatically generate the SOA serial number"),
|
|
209
|
+
"rfc2317_parent_managed": _(
|
|
210
|
+
"IPv4 reverse zone for delegating the RFC2317 PTR records is managed in NetBox DNS"
|
|
117
211
|
),
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
widgets = {
|
|
215
|
+
"dnssec_policy": HTMXSelect(),
|
|
216
|
+
"registrar": HTMXSelect(),
|
|
217
|
+
"expiration_date": DatePicker,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
fieldsets = (
|
|
221
|
+
FieldSet(
|
|
222
|
+
"view",
|
|
223
|
+
"name",
|
|
224
|
+
"template",
|
|
225
|
+
"status",
|
|
226
|
+
"nameservers",
|
|
227
|
+
"default_ttl",
|
|
228
|
+
"description",
|
|
229
|
+
name=_("Zone"),
|
|
118
230
|
),
|
|
119
|
-
(
|
|
120
|
-
"
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
231
|
+
FieldSet(
|
|
232
|
+
"soa_ttl",
|
|
233
|
+
"soa_mname",
|
|
234
|
+
"soa_rname",
|
|
235
|
+
"soa_refresh",
|
|
236
|
+
"soa_retry",
|
|
237
|
+
"soa_expire",
|
|
238
|
+
"soa_minimum",
|
|
239
|
+
"soa_serial_auto",
|
|
240
|
+
"soa_serial",
|
|
241
|
+
name=_("SOA"),
|
|
242
|
+
),
|
|
243
|
+
FieldSet(
|
|
244
|
+
"dnssec_policy",
|
|
245
|
+
"parental_agents",
|
|
246
|
+
name=_("DNSSEC"),
|
|
247
|
+
),
|
|
248
|
+
FieldSet(
|
|
249
|
+
"rfc2317_prefix",
|
|
250
|
+
"rfc2317_parent_managed",
|
|
251
|
+
name=_("RFC2317"),
|
|
252
|
+
),
|
|
253
|
+
FieldSet(
|
|
254
|
+
"registrar",
|
|
255
|
+
"registry_domain_id",
|
|
256
|
+
"expiration_date",
|
|
257
|
+
"domain_status",
|
|
258
|
+
"registrant",
|
|
259
|
+
"admin_c",
|
|
260
|
+
"tech_c",
|
|
261
|
+
"billing_c",
|
|
262
|
+
name=_("Domain Registration"),
|
|
263
|
+
),
|
|
264
|
+
FieldSet(
|
|
265
|
+
"tenant_group",
|
|
266
|
+
"tenant",
|
|
267
|
+
name=_("Tenancy"),
|
|
268
|
+
),
|
|
269
|
+
FieldSet(
|
|
270
|
+
"tags",
|
|
271
|
+
name=_("Tags"),
|
|
129
272
|
),
|
|
130
|
-
("Tags", ("tags",)),
|
|
131
|
-
("Tenancy", ("tenant_group", "tenant")),
|
|
132
273
|
)
|
|
133
274
|
|
|
134
275
|
def __init__(self, *args, **kwargs):
|
|
135
|
-
"""Override the __init__ method in order to provide the initial value for the default fields"""
|
|
136
276
|
super().__init__(*args, **kwargs)
|
|
137
277
|
|
|
138
278
|
initial_name = self.initial.get("name")
|
|
139
279
|
if initial_name:
|
|
140
280
|
self.initial["name"] = name_to_unicode(initial_name)
|
|
141
281
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def _initialize(initial, setting):
|
|
145
|
-
if initial.get(setting, None) in (None, ""):
|
|
146
|
-
initial[setting] = defaults.get(f"zone_{setting}", None)
|
|
282
|
+
if self.initial.get("view") is None:
|
|
283
|
+
self.initial["view"] = View.get_default_view()
|
|
147
284
|
|
|
285
|
+
defaults = settings.PLUGINS_CONFIG.get("netbox_dns")
|
|
148
286
|
for setting in (
|
|
149
287
|
"default_ttl",
|
|
150
288
|
"soa_ttl",
|
|
@@ -155,16 +293,14 @@ class ZoneForm(TenancyForm, NetBoxModelForm):
|
|
|
155
293
|
"soa_expire",
|
|
156
294
|
"soa_minimum",
|
|
157
295
|
):
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if self.initial.get("soa_ttl", None) is None:
|
|
161
|
-
self.initial["soa_ttl"] = self.initial.get("default_ttl", None)
|
|
296
|
+
if self.initial.get(setting) in (None, ""):
|
|
297
|
+
self.initial[setting] = defaults.get(f"zone_{setting}")
|
|
162
298
|
|
|
163
|
-
if self.initial.get("
|
|
164
|
-
self.initial["
|
|
299
|
+
if self.initial.get("soa_ttl") is None:
|
|
300
|
+
self.initial["soa_ttl"] = self.initial.get("default_ttl")
|
|
165
301
|
|
|
166
|
-
if self.initial.get("soa_mname"
|
|
167
|
-
default_soa_mname = defaults.get("zone_soa_mname"
|
|
302
|
+
if self.initial.get("soa_mname") is None:
|
|
303
|
+
default_soa_mname = defaults.get("zone_soa_mname")
|
|
168
304
|
if default_soa_mname is not None:
|
|
169
305
|
try:
|
|
170
306
|
self.initial["soa_mname"] = NameServer.objects.get(
|
|
@@ -180,6 +316,106 @@ class ZoneForm(TenancyForm, NetBoxModelForm):
|
|
|
180
316
|
name__in=default_nameservers
|
|
181
317
|
)
|
|
182
318
|
|
|
319
|
+
if not get_field_value(self, "dnssec_policy"):
|
|
320
|
+
del self.fields["parental_agents"]
|
|
321
|
+
|
|
322
|
+
if not get_field_value(self, "registrar"):
|
|
323
|
+
del self.fields["registry_domain_id"]
|
|
324
|
+
del self.fields["expiration_date"]
|
|
325
|
+
del self.fields["domain_status"]
|
|
326
|
+
|
|
327
|
+
view = DynamicModelChoiceField(
|
|
328
|
+
queryset=View.objects.all(),
|
|
329
|
+
required=True,
|
|
330
|
+
label=_("View"),
|
|
331
|
+
)
|
|
332
|
+
name = forms.CharField(
|
|
333
|
+
required=True,
|
|
334
|
+
label=_("Name"),
|
|
335
|
+
)
|
|
336
|
+
template = DynamicModelChoiceField(
|
|
337
|
+
queryset=ZoneTemplate.objects.all(),
|
|
338
|
+
required=False,
|
|
339
|
+
label=_("Template"),
|
|
340
|
+
)
|
|
341
|
+
status = forms.ChoiceField(
|
|
342
|
+
choices=ZoneStatusChoices,
|
|
343
|
+
required=False,
|
|
344
|
+
label=_("Status"),
|
|
345
|
+
)
|
|
346
|
+
nameservers = DynamicModelMultipleChoiceField(
|
|
347
|
+
queryset=NameServer.objects.all(),
|
|
348
|
+
required=False,
|
|
349
|
+
label=_("Nameservers"),
|
|
350
|
+
)
|
|
351
|
+
default_ttl = TimePeriodField(
|
|
352
|
+
required=False,
|
|
353
|
+
help_text=_("Default TTL for new records in this zone"),
|
|
354
|
+
validators=[MinValueValidator(1)],
|
|
355
|
+
label=_("Default TTL"),
|
|
356
|
+
)
|
|
357
|
+
soa_ttl = TimePeriodField(
|
|
358
|
+
required=True,
|
|
359
|
+
help_text=_("TTL for the SOA record of the zone"),
|
|
360
|
+
validators=[MinValueValidator(1)],
|
|
361
|
+
label=_("SOA TTL"),
|
|
362
|
+
)
|
|
363
|
+
soa_mname = DynamicModelChoiceField(
|
|
364
|
+
queryset=NameServer.objects.all(),
|
|
365
|
+
help_text=_("Primary nameserver this zone"),
|
|
366
|
+
required=False,
|
|
367
|
+
label=_("SOA MName"),
|
|
368
|
+
)
|
|
369
|
+
soa_rname = forms.CharField(
|
|
370
|
+
required=False,
|
|
371
|
+
help_text=_("Mailbox of the zone's administrator"),
|
|
372
|
+
label=_("SOA RName"),
|
|
373
|
+
)
|
|
374
|
+
soa_refresh = TimePeriodField(
|
|
375
|
+
required=True,
|
|
376
|
+
help_text=_("Refresh interval for secondary nameservers"),
|
|
377
|
+
validators=[MinValueValidator(1)],
|
|
378
|
+
label=_("SOA Refresh"),
|
|
379
|
+
)
|
|
380
|
+
soa_retry = TimePeriodField(
|
|
381
|
+
required=True,
|
|
382
|
+
help_text=_("Retry interval for secondary nameservers"),
|
|
383
|
+
validators=[MinValueValidator(1)],
|
|
384
|
+
label=_("SOA Retry"),
|
|
385
|
+
)
|
|
386
|
+
soa_expire = TimePeriodField(
|
|
387
|
+
required=True,
|
|
388
|
+
validators=[MinValueValidator(1)],
|
|
389
|
+
help_text=_("Expire time after which the zone is considered unavailable"),
|
|
390
|
+
label=_("SOA Expire"),
|
|
391
|
+
)
|
|
392
|
+
soa_minimum = TimePeriodField(
|
|
393
|
+
required=True,
|
|
394
|
+
help_text=_("Minimum TTL for negative results, e.g. NXRRSET, NXDOMAIN"),
|
|
395
|
+
validators=[MinValueValidator(1)],
|
|
396
|
+
label=_("SOA Minimum TTL"),
|
|
397
|
+
)
|
|
398
|
+
soa_serial = forms.IntegerField(
|
|
399
|
+
required=False,
|
|
400
|
+
validators=[MinValueValidator(1)],
|
|
401
|
+
label=_("SOA Serial"),
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
parental_agents = SimpleArrayField(
|
|
405
|
+
required=False,
|
|
406
|
+
base_field=forms.GenericIPAddressField(),
|
|
407
|
+
label=_("Parental Agents"),
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
rfc2317_prefix = RFC2317NetworkFormField(
|
|
411
|
+
required=False,
|
|
412
|
+
validators=[validate_ipv4, validate_prefix, validate_rfc2317],
|
|
413
|
+
help_text=_("RFC2317 IPv4 prefix with a length of at least 25 bits"),
|
|
414
|
+
label=_("RFC2317 Prefix"),
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
comments = CommentField()
|
|
418
|
+
|
|
183
419
|
def clean_default_ttl(self):
|
|
184
420
|
return (
|
|
185
421
|
self.cleaned_data["default_ttl"]
|
|
@@ -187,17 +423,206 @@ class ZoneForm(TenancyForm, NetBoxModelForm):
|
|
|
187
423
|
else self.initial["default_ttl"]
|
|
188
424
|
)
|
|
189
425
|
|
|
426
|
+
def clean_name(self):
|
|
427
|
+
name = self.cleaned_data["name"]
|
|
428
|
+
if reverse_name := network_to_reverse(name):
|
|
429
|
+
return reverse_name
|
|
430
|
+
else:
|
|
431
|
+
return name
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|
435
|
+
model = Zone
|
|
436
|
+
|
|
437
|
+
fieldsets = (
|
|
438
|
+
FieldSet(
|
|
439
|
+
"q",
|
|
440
|
+
"filter_id",
|
|
441
|
+
"tag",
|
|
442
|
+
),
|
|
443
|
+
FieldSet(
|
|
444
|
+
"view_id",
|
|
445
|
+
"status",
|
|
446
|
+
"name",
|
|
447
|
+
"nameserver_id",
|
|
448
|
+
"active",
|
|
449
|
+
"description",
|
|
450
|
+
name=_("Attributes"),
|
|
451
|
+
),
|
|
452
|
+
FieldSet(
|
|
453
|
+
"soa_mname_id",
|
|
454
|
+
"soa_rname",
|
|
455
|
+
"soa_serial_auto",
|
|
456
|
+
name=_("SOA"),
|
|
457
|
+
),
|
|
458
|
+
FieldSet(
|
|
459
|
+
"dnssec_policy_id",
|
|
460
|
+
"inline_signing",
|
|
461
|
+
"parental_agents",
|
|
462
|
+
name=_("DNSSEC"),
|
|
463
|
+
),
|
|
464
|
+
FieldSet(
|
|
465
|
+
"rfc2317_prefix",
|
|
466
|
+
"rfc2317_parent_managed",
|
|
467
|
+
"rfc2317_parent_zone_id",
|
|
468
|
+
name=_("RFC2317"),
|
|
469
|
+
),
|
|
470
|
+
FieldSet(
|
|
471
|
+
"registrar_id",
|
|
472
|
+
"registry_domain_id",
|
|
473
|
+
"expiration_date_before",
|
|
474
|
+
"expiration_date_after",
|
|
475
|
+
"domain_status",
|
|
476
|
+
"registrant_id",
|
|
477
|
+
"admin_c_id",
|
|
478
|
+
"tech_c_id",
|
|
479
|
+
"billing_c_id",
|
|
480
|
+
name=_("Registration"),
|
|
481
|
+
),
|
|
482
|
+
FieldSet(
|
|
483
|
+
"tenant_group_id",
|
|
484
|
+
"tenant_id",
|
|
485
|
+
name=_("Tenancy"),
|
|
486
|
+
),
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
view_id = DynamicModelMultipleChoiceField(
|
|
490
|
+
queryset=View.objects.all(),
|
|
491
|
+
required=False,
|
|
492
|
+
label=_("View"),
|
|
493
|
+
)
|
|
494
|
+
status = forms.MultipleChoiceField(
|
|
495
|
+
choices=ZoneStatusChoices,
|
|
496
|
+
required=False,
|
|
497
|
+
label=_("Status"),
|
|
498
|
+
)
|
|
499
|
+
name = forms.CharField(
|
|
500
|
+
required=False,
|
|
501
|
+
label=_("Name"),
|
|
502
|
+
)
|
|
503
|
+
nameserver_id = DynamicModelMultipleChoiceField(
|
|
504
|
+
queryset=NameServer.objects.all(),
|
|
505
|
+
required=False,
|
|
506
|
+
null_option=_("None"),
|
|
507
|
+
label=_("Nameservers"),
|
|
508
|
+
)
|
|
509
|
+
active = forms.NullBooleanField(
|
|
510
|
+
required=False,
|
|
511
|
+
widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
512
|
+
label=_("Active"),
|
|
513
|
+
)
|
|
514
|
+
description = forms.CharField(
|
|
515
|
+
required=False,
|
|
516
|
+
label=_("Description"),
|
|
517
|
+
)
|
|
518
|
+
soa_mname_id = DynamicModelMultipleChoiceField(
|
|
519
|
+
queryset=NameServer.objects.all(),
|
|
520
|
+
required=False,
|
|
521
|
+
label=_("MName"),
|
|
522
|
+
)
|
|
523
|
+
soa_rname = forms.CharField(
|
|
524
|
+
required=False,
|
|
525
|
+
label=_("RName"),
|
|
526
|
+
)
|
|
527
|
+
soa_serial_auto = forms.NullBooleanField(
|
|
528
|
+
required=False,
|
|
529
|
+
widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
530
|
+
label=_("Generate SOA Serial"),
|
|
531
|
+
)
|
|
532
|
+
rfc2317_prefix = RFC2317NetworkFormField(
|
|
533
|
+
required=False,
|
|
534
|
+
label=_("Prefix"),
|
|
535
|
+
)
|
|
536
|
+
rfc2317_parent_managed = forms.NullBooleanField(
|
|
537
|
+
required=False,
|
|
538
|
+
widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
539
|
+
label=_("Parent Managed"),
|
|
540
|
+
)
|
|
541
|
+
rfc2317_parent_zone_id = DynamicModelMultipleChoiceField(
|
|
542
|
+
queryset=Zone.objects.all(),
|
|
543
|
+
required=False,
|
|
544
|
+
null_option=_("None"),
|
|
545
|
+
label=_("Parent Zone"),
|
|
546
|
+
)
|
|
547
|
+
dnssec_policy_id = DynamicModelMultipleChoiceField(
|
|
548
|
+
queryset=DNSSECPolicy.objects.all(),
|
|
549
|
+
required=False,
|
|
550
|
+
null_option=_("None"),
|
|
551
|
+
label=_("DNSSEC Policy"),
|
|
552
|
+
)
|
|
553
|
+
inline_signing = forms.NullBooleanField(
|
|
554
|
+
required=False,
|
|
555
|
+
widget=forms.Select(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
556
|
+
label=_("DNSSEC Policy uses inline signing"),
|
|
557
|
+
)
|
|
558
|
+
parental_agents = forms.GenericIPAddressField(
|
|
559
|
+
required=False,
|
|
560
|
+
label=_("Parental Agents"),
|
|
561
|
+
)
|
|
562
|
+
registrar_id = DynamicModelMultipleChoiceField(
|
|
563
|
+
queryset=Registrar.objects.all(),
|
|
564
|
+
required=False,
|
|
565
|
+
null_option=_("None"),
|
|
566
|
+
label=_("Registrar"),
|
|
567
|
+
)
|
|
568
|
+
registry_domain_id = forms.CharField(
|
|
569
|
+
required=False,
|
|
570
|
+
label=_("Registry Domain ID"),
|
|
571
|
+
)
|
|
572
|
+
expiration_date_after = forms.DateField(
|
|
573
|
+
required=False,
|
|
574
|
+
label=_("Expiration Date after"),
|
|
575
|
+
widget=DatePicker,
|
|
576
|
+
)
|
|
577
|
+
expiration_date_before = forms.DateField(
|
|
578
|
+
required=False,
|
|
579
|
+
label=_("Expiration Date before"),
|
|
580
|
+
widget=DatePicker,
|
|
581
|
+
)
|
|
582
|
+
domain_status = forms.MultipleChoiceField(
|
|
583
|
+
choices=ZoneEPPStatusChoices,
|
|
584
|
+
required=False,
|
|
585
|
+
label=_("Domain Status"),
|
|
586
|
+
)
|
|
587
|
+
registrant_id = DynamicModelMultipleChoiceField(
|
|
588
|
+
queryset=RegistrationContact.objects.all(),
|
|
589
|
+
required=False,
|
|
590
|
+
null_option=_("None"),
|
|
591
|
+
label=_("Registrant"),
|
|
592
|
+
)
|
|
593
|
+
admin_c_id = DynamicModelMultipleChoiceField(
|
|
594
|
+
queryset=RegistrationContact.objects.all(),
|
|
595
|
+
required=False,
|
|
596
|
+
null_option=_("None"),
|
|
597
|
+
label=_("Administrative Contact"),
|
|
598
|
+
)
|
|
599
|
+
tech_c_id = DynamicModelMultipleChoiceField(
|
|
600
|
+
queryset=RegistrationContact.objects.all(),
|
|
601
|
+
required=False,
|
|
602
|
+
null_option=_("None"),
|
|
603
|
+
label=_("Technical Contact"),
|
|
604
|
+
)
|
|
605
|
+
billing_c_id = DynamicModelMultipleChoiceField(
|
|
606
|
+
queryset=RegistrationContact.objects.all(),
|
|
607
|
+
required=False,
|
|
608
|
+
null_option=_("None"),
|
|
609
|
+
label=_("Billing Contact"),
|
|
610
|
+
)
|
|
611
|
+
tag = TagFilterField(Zone)
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
class ZoneImportForm(ZoneTemplateUpdateMixin, NetBoxModelImportForm):
|
|
190
615
|
class Meta:
|
|
191
616
|
model = Zone
|
|
192
617
|
|
|
193
618
|
fields = (
|
|
194
|
-
"name",
|
|
195
619
|
"view",
|
|
620
|
+
"name",
|
|
196
621
|
"status",
|
|
622
|
+
"template",
|
|
197
623
|
"nameservers",
|
|
198
624
|
"default_ttl",
|
|
199
625
|
"description",
|
|
200
|
-
"tags",
|
|
201
626
|
"soa_ttl",
|
|
202
627
|
"soa_mname",
|
|
203
628
|
"soa_rname",
|
|
@@ -207,442 +632,413 @@ class ZoneForm(TenancyForm, NetBoxModelForm):
|
|
|
207
632
|
"soa_retry",
|
|
208
633
|
"soa_expire",
|
|
209
634
|
"soa_minimum",
|
|
635
|
+
"dnssec_policy",
|
|
636
|
+
"parental_agents",
|
|
637
|
+
"rfc2317_prefix",
|
|
638
|
+
"rfc2317_parent_managed",
|
|
210
639
|
"registrar",
|
|
211
640
|
"registry_domain_id",
|
|
641
|
+
"expiration_date",
|
|
642
|
+
"domain_status",
|
|
212
643
|
"registrant",
|
|
213
644
|
"admin_c",
|
|
214
645
|
"tech_c",
|
|
215
646
|
"billing_c",
|
|
216
647
|
"tenant",
|
|
648
|
+
"comments",
|
|
649
|
+
"tags",
|
|
217
650
|
)
|
|
218
|
-
help_texts = {
|
|
219
|
-
"view": "View the zone belongs to",
|
|
220
|
-
"soa_mname": "Primary name server for the zone",
|
|
221
|
-
}
|
|
222
651
|
|
|
223
|
-
|
|
224
|
-
class ZoneFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|
225
|
-
model = Zone
|
|
226
|
-
fieldsets = (
|
|
227
|
-
(None, ("q", "filter_id", "tag")),
|
|
228
|
-
("Attributes", ("view_id", "status", "name", "nameservers")),
|
|
229
|
-
("Tenant", ("tenant_group_id", "tenant_id")),
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
view_id = DynamicModelMultipleChoiceField(
|
|
233
|
-
queryset=View.objects.all(),
|
|
234
|
-
required=False,
|
|
235
|
-
label="View",
|
|
236
|
-
)
|
|
237
|
-
status = forms.ChoiceField(
|
|
238
|
-
choices=add_blank_choice(ZoneStatusChoices),
|
|
239
|
-
required=False,
|
|
240
|
-
)
|
|
241
|
-
name = forms.CharField(
|
|
242
|
-
required=False,
|
|
243
|
-
label="Name",
|
|
244
|
-
)
|
|
245
|
-
nameservers = DynamicModelMultipleChoiceField(
|
|
246
|
-
queryset=NameServer.objects.all(),
|
|
247
|
-
required=False,
|
|
248
|
-
)
|
|
249
|
-
tag = TagFilterField(Zone)
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
class ZoneImportForm(NetBoxModelImportForm):
|
|
253
652
|
view = CSVModelChoiceField(
|
|
254
653
|
queryset=View.objects.all(),
|
|
255
654
|
required=False,
|
|
256
655
|
to_field_name="name",
|
|
257
|
-
help_text="View the zone belongs to",
|
|
258
656
|
error_messages={
|
|
259
|
-
"invalid_choice": "View not found
|
|
657
|
+
"invalid_choice": _("View %(value)s not found"),
|
|
260
658
|
},
|
|
659
|
+
label=_("View"),
|
|
261
660
|
)
|
|
262
661
|
status = CSVChoiceField(
|
|
263
662
|
choices=ZoneStatusChoices,
|
|
264
663
|
required=False,
|
|
265
|
-
|
|
664
|
+
label=_("Status"),
|
|
266
665
|
)
|
|
267
|
-
|
|
666
|
+
nameservers = CSVModelMultipleChoiceField(
|
|
667
|
+
queryset=NameServer.objects.all(),
|
|
668
|
+
to_field_name="name",
|
|
268
669
|
required=False,
|
|
269
|
-
|
|
670
|
+
label=_("Nameservers"),
|
|
270
671
|
)
|
|
271
|
-
|
|
672
|
+
default_ttl = TimePeriodField(
|
|
272
673
|
required=False,
|
|
273
|
-
|
|
674
|
+
label=_("Default TTL"),
|
|
675
|
+
)
|
|
676
|
+
soa_ttl = TimePeriodField(
|
|
677
|
+
required=False,
|
|
678
|
+
help_text=_("TTL for the SOA record of the zone"),
|
|
679
|
+
label=_("SOA TTL"),
|
|
274
680
|
)
|
|
275
681
|
soa_mname = CSVModelChoiceField(
|
|
276
682
|
queryset=NameServer.objects.all(),
|
|
277
683
|
required=False,
|
|
278
684
|
to_field_name="name",
|
|
279
|
-
help_text="Primary name server for the zone",
|
|
280
685
|
error_messages={
|
|
281
|
-
"invalid_choice": "Nameserver not found
|
|
686
|
+
"invalid_choice": _("Nameserver %(value)s not found"),
|
|
282
687
|
},
|
|
688
|
+
help_text=_("Primary nameserver for the zone"),
|
|
689
|
+
label=_("SOA MName"),
|
|
283
690
|
)
|
|
284
691
|
soa_rname = forms.CharField(
|
|
285
692
|
required=False,
|
|
286
|
-
help_text="Mailbox of the zone's administrator",
|
|
693
|
+
help_text=_("Mailbox of the zone's administrator"),
|
|
694
|
+
label=_("SOA RName"),
|
|
287
695
|
)
|
|
288
696
|
soa_serial_auto = forms.BooleanField(
|
|
289
697
|
required=False,
|
|
290
|
-
|
|
698
|
+
label=_("Generate SOA Serial"),
|
|
291
699
|
)
|
|
292
700
|
soa_serial = forms.IntegerField(
|
|
293
701
|
required=False,
|
|
294
|
-
|
|
702
|
+
label=_("SOA Serial"),
|
|
295
703
|
)
|
|
296
|
-
soa_refresh =
|
|
704
|
+
soa_refresh = TimePeriodField(
|
|
297
705
|
required=False,
|
|
298
|
-
help_text="Refresh interval for secondary
|
|
706
|
+
help_text=_("Refresh interval for secondary nameservers"),
|
|
707
|
+
label=_("SOA Refresh"),
|
|
299
708
|
)
|
|
300
|
-
soa_retry =
|
|
709
|
+
soa_retry = TimePeriodField(
|
|
301
710
|
required=False,
|
|
302
|
-
help_text="Retry interval for secondary
|
|
711
|
+
help_text=_("Retry interval for secondary nameservers"),
|
|
712
|
+
label=_("SOA Retry"),
|
|
303
713
|
)
|
|
304
|
-
soa_expire =
|
|
714
|
+
soa_expire = TimePeriodField(
|
|
305
715
|
required=False,
|
|
306
|
-
help_text="Expire time after which the zone is considered unavailable",
|
|
716
|
+
help_text=_("Expire time after which the zone is considered unavailable"),
|
|
717
|
+
label=_("SOA Expire"),
|
|
307
718
|
)
|
|
308
|
-
soa_minimum =
|
|
719
|
+
soa_minimum = TimePeriodField(
|
|
309
720
|
required=False,
|
|
310
|
-
help_text="Minimum TTL for negative results, e.g. NXRRSET",
|
|
721
|
+
help_text=_("Minimum TTL for negative results, e.g. NXRRSET, NXDOMAIN"),
|
|
722
|
+
label=_("SOA Minimum TTL"),
|
|
723
|
+
)
|
|
724
|
+
rfc2317_prefix = RFC2317NetworkFormField(
|
|
725
|
+
required=False,
|
|
726
|
+
help_text=_("RFC2317 IPv4 prefix with a length of at least 25 bits"),
|
|
727
|
+
label=_("RFC2317 Prefix"),
|
|
728
|
+
)
|
|
729
|
+
rfc2317_parent_managed = forms.BooleanField(
|
|
730
|
+
required=False,
|
|
731
|
+
help_text=_(
|
|
732
|
+
"IPv4 reverse zone for delegating the RFC2317 PTR records is managed in NetBox DNS"
|
|
733
|
+
),
|
|
734
|
+
label=_("RFC2317 Parent Managed"),
|
|
735
|
+
)
|
|
736
|
+
dnssec_policy = CSVModelChoiceField(
|
|
737
|
+
queryset=DNSSECPolicy.objects.all(),
|
|
738
|
+
required=False,
|
|
739
|
+
to_field_name="name",
|
|
740
|
+
error_messages={
|
|
741
|
+
"invalid_choice": _("DNSSEC policy %(value)s not found"),
|
|
742
|
+
},
|
|
743
|
+
label=_("DNSSEC Policy"),
|
|
311
744
|
)
|
|
312
745
|
registrar = CSVModelChoiceField(
|
|
313
746
|
queryset=Registrar.objects.all(),
|
|
314
747
|
required=False,
|
|
315
748
|
to_field_name="name",
|
|
316
|
-
help_text="Registrar the domain is registered with",
|
|
317
749
|
error_messages={
|
|
318
|
-
"invalid_choice": "Registrar not found
|
|
750
|
+
"invalid_choice": _("Registrar %(value)s not found"),
|
|
319
751
|
},
|
|
752
|
+
label=_("Registrar"),
|
|
320
753
|
)
|
|
321
754
|
registry_domain_id = forms.CharField(
|
|
322
755
|
required=False,
|
|
323
|
-
|
|
756
|
+
label=_("Registry Domain ID"),
|
|
757
|
+
)
|
|
758
|
+
domain_status = CSVChoiceField(
|
|
759
|
+
choices=ZoneEPPStatusChoices,
|
|
760
|
+
required=False,
|
|
761
|
+
label=_("Domain Status"),
|
|
324
762
|
)
|
|
325
763
|
registrant = CSVModelChoiceField(
|
|
326
|
-
queryset=
|
|
764
|
+
queryset=RegistrationContact.objects.all(),
|
|
327
765
|
required=False,
|
|
328
766
|
to_field_name="contact_id",
|
|
329
|
-
help_text="Owner of the domain",
|
|
330
767
|
error_messages={
|
|
331
|
-
"invalid_choice": "Registrant contact ID not found",
|
|
768
|
+
"invalid_choice": _("Registrant contact ID %(value)s not found"),
|
|
332
769
|
},
|
|
770
|
+
label=_("Registrant"),
|
|
333
771
|
)
|
|
334
772
|
admin_c = CSVModelChoiceField(
|
|
335
|
-
queryset=
|
|
773
|
+
queryset=RegistrationContact.objects.all(),
|
|
336
774
|
required=False,
|
|
337
775
|
to_field_name="contact_id",
|
|
338
|
-
help_text="Administrative contact for the domain",
|
|
339
776
|
error_messages={
|
|
340
|
-
"invalid_choice": "Administrative contact ID not found",
|
|
777
|
+
"invalid_choice": _("Administrative contact ID %(value)s not found"),
|
|
341
778
|
},
|
|
779
|
+
label=_("Administrative Contact"),
|
|
342
780
|
)
|
|
343
781
|
tech_c = CSVModelChoiceField(
|
|
344
|
-
queryset=
|
|
782
|
+
queryset=RegistrationContact.objects.all(),
|
|
345
783
|
required=False,
|
|
346
784
|
to_field_name="contact_id",
|
|
347
|
-
help_text="Technical contact for the domain",
|
|
348
785
|
error_messages={
|
|
349
|
-
"invalid_choice": "Technical contact ID not found",
|
|
786
|
+
"invalid_choice": _("Technical contact ID %(value)s not found"),
|
|
350
787
|
},
|
|
788
|
+
label=_("Technical Contact"),
|
|
351
789
|
)
|
|
352
790
|
billing_c = CSVModelChoiceField(
|
|
353
|
-
queryset=
|
|
791
|
+
queryset=RegistrationContact.objects.all(),
|
|
354
792
|
required=False,
|
|
355
793
|
to_field_name="contact_id",
|
|
356
|
-
help_text="Billing contact for the domain",
|
|
357
794
|
error_messages={
|
|
358
|
-
"invalid_choice": "Billing contact ID not found",
|
|
795
|
+
"invalid_choice": _("Billing contact ID not found"),
|
|
359
796
|
},
|
|
797
|
+
label=_("Billing Contact"),
|
|
360
798
|
)
|
|
361
799
|
tenant = CSVModelChoiceField(
|
|
362
800
|
queryset=Tenant.objects.all(),
|
|
363
801
|
required=False,
|
|
364
802
|
to_field_name="name",
|
|
365
|
-
|
|
803
|
+
label=_("Tenant"),
|
|
804
|
+
)
|
|
805
|
+
template = CSVModelChoiceField(
|
|
806
|
+
queryset=ZoneTemplate.objects.all(),
|
|
807
|
+
required=False,
|
|
808
|
+
to_field_name="name",
|
|
809
|
+
label=_("Template"),
|
|
366
810
|
)
|
|
367
811
|
|
|
368
|
-
def
|
|
369
|
-
|
|
370
|
-
if
|
|
371
|
-
|
|
372
|
-
"zone_default_ttl", None
|
|
373
|
-
)
|
|
374
|
-
|
|
375
|
-
return _default_values.get(f"zone_{field}", None)
|
|
376
|
-
|
|
377
|
-
def _clean_field_with_defaults(self, field):
|
|
378
|
-
if self.cleaned_data[field]:
|
|
379
|
-
value = self.cleaned_data[field]
|
|
380
|
-
else:
|
|
381
|
-
value = self._get_default_value(field)
|
|
382
|
-
|
|
383
|
-
if value is None:
|
|
384
|
-
raise ValidationError(f"{field} not set and no default value available")
|
|
385
|
-
|
|
386
|
-
return value
|
|
387
|
-
|
|
388
|
-
def clean_default_ttl(self):
|
|
389
|
-
return self._clean_field_with_defaults("default_ttl")
|
|
390
|
-
|
|
391
|
-
def clean_soa_ttl(self):
|
|
392
|
-
return self._clean_field_with_defaults("soa_ttl")
|
|
393
|
-
|
|
394
|
-
def clean_soa_mname(self):
|
|
395
|
-
soa_mname = self._clean_field_with_defaults("soa_mname")
|
|
396
|
-
if isinstance(soa_mname, str):
|
|
397
|
-
try:
|
|
398
|
-
soa_mname = NameServer.objects.get(name=soa_mname)
|
|
399
|
-
except NameServer.DoesNotExist:
|
|
400
|
-
raise ValidationError(f"Default name server {soa_mname} does not exist")
|
|
401
|
-
|
|
402
|
-
return soa_mname
|
|
403
|
-
|
|
404
|
-
def clean_soa_rname(self):
|
|
405
|
-
return self._clean_field_with_defaults("soa_rname")
|
|
406
|
-
|
|
407
|
-
def clean_soa_serial_auto(self):
|
|
408
|
-
try:
|
|
409
|
-
return self._clean_field_with_defaults("soa_serial_auto")
|
|
410
|
-
except ValidationError:
|
|
411
|
-
if self.cleaned_data["soa_serial"] or self._get_default_value("soa_serial"):
|
|
412
|
-
return None
|
|
413
|
-
|
|
414
|
-
raise
|
|
415
|
-
|
|
416
|
-
def clean_soa_serial(self):
|
|
417
|
-
try:
|
|
418
|
-
return self._clean_field_with_defaults("soa_serial")
|
|
419
|
-
except ValidationError:
|
|
420
|
-
if self.cleaned_data["soa_serial_auto"] or self._get_default_value(
|
|
421
|
-
"soa_serial_auto"
|
|
422
|
-
):
|
|
423
|
-
return None
|
|
812
|
+
def clean_view(self):
|
|
813
|
+
view = self.cleaned_data.get("view")
|
|
814
|
+
if view is None:
|
|
815
|
+
return View.get_default_view()
|
|
424
816
|
|
|
425
|
-
|
|
817
|
+
return view
|
|
426
818
|
|
|
427
|
-
def
|
|
428
|
-
|
|
819
|
+
def clean_nameservers(self):
|
|
820
|
+
nameservers = self.cleaned_data.get("nameservers")
|
|
821
|
+
zone_defaults = settings.PLUGINS_CONFIG.get("netbox_dns")
|
|
429
822
|
|
|
430
|
-
|
|
431
|
-
|
|
823
|
+
if (
|
|
824
|
+
self.data.get("nameservers") is None
|
|
825
|
+
and zone_defaults.get("zone_nameservers") is not None
|
|
826
|
+
):
|
|
827
|
+
nameservers = NameServer.objects.filter(
|
|
828
|
+
name__in=zone_defaults.get("zone_nameservers")
|
|
829
|
+
)
|
|
432
830
|
|
|
433
|
-
|
|
434
|
-
return self._clean_field_with_defaults("soa_expire")
|
|
831
|
+
return nameservers
|
|
435
832
|
|
|
436
|
-
def clean_soa_minimum(self):
|
|
437
|
-
return self._clean_field_with_defaults("soa_minimum")
|
|
438
833
|
|
|
439
|
-
|
|
440
|
-
|
|
834
|
+
class ZoneBulkEditForm(NetBoxModelBulkEditForm):
|
|
835
|
+
model = Zone
|
|
441
836
|
|
|
442
|
-
|
|
837
|
+
fieldsets = (
|
|
838
|
+
FieldSet(
|
|
443
839
|
"view",
|
|
444
|
-
"name",
|
|
445
840
|
"status",
|
|
841
|
+
"nameservers",
|
|
446
842
|
"default_ttl",
|
|
447
843
|
"description",
|
|
844
|
+
name=_("Attributes"),
|
|
845
|
+
),
|
|
846
|
+
FieldSet(
|
|
448
847
|
"soa_ttl",
|
|
449
848
|
"soa_mname",
|
|
450
849
|
"soa_rname",
|
|
451
|
-
"soa_serial_auto",
|
|
452
|
-
"soa_serial",
|
|
453
850
|
"soa_refresh",
|
|
454
851
|
"soa_retry",
|
|
455
852
|
"soa_expire",
|
|
456
853
|
"soa_minimum",
|
|
854
|
+
"soa_serial_auto",
|
|
855
|
+
"soa_serial",
|
|
856
|
+
name=_("SOA"),
|
|
857
|
+
),
|
|
858
|
+
FieldSet(
|
|
859
|
+
"dnssec_policy",
|
|
860
|
+
"parental_agents",
|
|
861
|
+
name=_("DNSSEC"),
|
|
862
|
+
),
|
|
863
|
+
FieldSet(
|
|
864
|
+
"rfc2317_prefix",
|
|
865
|
+
"rfc2317_parent_managed",
|
|
866
|
+
name=_("RFC2317"),
|
|
867
|
+
),
|
|
868
|
+
FieldSet(
|
|
457
869
|
"registrar",
|
|
458
870
|
"registry_domain_id",
|
|
871
|
+
"expiration_date",
|
|
872
|
+
"domain_status",
|
|
459
873
|
"registrant",
|
|
460
874
|
"admin_c",
|
|
461
875
|
"tech_c",
|
|
462
876
|
"billing_c",
|
|
877
|
+
name=_("Domain Registration"),
|
|
878
|
+
),
|
|
879
|
+
FieldSet(
|
|
880
|
+
"tenant_group",
|
|
463
881
|
"tenant",
|
|
464
|
-
|
|
882
|
+
name=_("Tenancy"),
|
|
883
|
+
),
|
|
884
|
+
)
|
|
465
885
|
|
|
886
|
+
nullable_fields = (
|
|
887
|
+
"description",
|
|
888
|
+
"nameservers",
|
|
889
|
+
"rfc2317_prefix",
|
|
890
|
+
"registrar",
|
|
891
|
+
"expiration_date",
|
|
892
|
+
"domain_status",
|
|
893
|
+
"registry_domain_id",
|
|
894
|
+
"registrant",
|
|
895
|
+
"admin_c",
|
|
896
|
+
"tech_c",
|
|
897
|
+
"billing_c",
|
|
898
|
+
"tenant",
|
|
899
|
+
"comments",
|
|
900
|
+
)
|
|
466
901
|
|
|
467
|
-
class ZoneBulkEditForm(NetBoxModelBulkEditForm):
|
|
468
902
|
view = DynamicModelChoiceField(
|
|
469
903
|
queryset=View.objects.all(),
|
|
470
904
|
required=False,
|
|
471
|
-
label="View",
|
|
472
|
-
widget=APISelect(
|
|
473
|
-
attrs={"data-url": reverse_lazy("plugins-api:netbox_dns-api:view-list")}
|
|
474
|
-
),
|
|
905
|
+
label=_("View"),
|
|
475
906
|
)
|
|
476
907
|
status = forms.ChoiceField(
|
|
477
908
|
choices=add_blank_choice(ZoneStatusChoices),
|
|
478
909
|
required=False,
|
|
910
|
+
label=_("Status"),
|
|
479
911
|
)
|
|
480
912
|
nameservers = DynamicModelMultipleChoiceField(
|
|
481
913
|
queryset=NameServer.objects.all(),
|
|
482
914
|
required=False,
|
|
915
|
+
label=_("Nameservers"),
|
|
483
916
|
)
|
|
484
|
-
default_ttl =
|
|
917
|
+
default_ttl = TimePeriodField(
|
|
485
918
|
required=False,
|
|
486
|
-
label="Default TTL",
|
|
487
919
|
validators=[MinValueValidator(1)],
|
|
920
|
+
label=_("Default TTL"),
|
|
921
|
+
)
|
|
922
|
+
description = forms.CharField(
|
|
923
|
+
max_length=200,
|
|
924
|
+
required=False,
|
|
925
|
+
label=_("Description"),
|
|
488
926
|
)
|
|
489
|
-
|
|
490
|
-
soa_ttl = forms.IntegerField(
|
|
927
|
+
soa_ttl = TimePeriodField(
|
|
491
928
|
required=False,
|
|
492
|
-
label="SOA TTL",
|
|
493
929
|
validators=[MinValueValidator(1)],
|
|
930
|
+
label=_("SOA TTL"),
|
|
494
931
|
)
|
|
495
932
|
soa_mname = DynamicModelChoiceField(
|
|
496
933
|
queryset=NameServer.objects.all(),
|
|
497
934
|
required=False,
|
|
498
|
-
label="SOA
|
|
499
|
-
widget=APISelect(
|
|
500
|
-
attrs={
|
|
501
|
-
"data-url": reverse_lazy("plugins-api:netbox_dns-api:nameserver-list")
|
|
502
|
-
}
|
|
503
|
-
),
|
|
935
|
+
label=_("SOA MName"),
|
|
504
936
|
)
|
|
505
937
|
soa_rname = forms.CharField(
|
|
506
938
|
required=False,
|
|
507
|
-
label="SOA
|
|
939
|
+
label=_("SOA RName"),
|
|
508
940
|
)
|
|
509
941
|
soa_serial_auto = forms.NullBooleanField(
|
|
510
942
|
required=False,
|
|
511
943
|
widget=BulkEditNullBooleanSelect(),
|
|
512
|
-
label="Generate SOA Serial",
|
|
944
|
+
label=_("Generate SOA Serial"),
|
|
513
945
|
)
|
|
514
946
|
soa_serial = forms.IntegerField(
|
|
515
947
|
required=False,
|
|
516
|
-
label="SOA Serial",
|
|
517
948
|
validators=[MinValueValidator(1), MaxValueValidator(4294967295)],
|
|
949
|
+
label=_("SOA Serial"),
|
|
518
950
|
)
|
|
519
|
-
soa_refresh =
|
|
951
|
+
soa_refresh = TimePeriodField(
|
|
520
952
|
required=False,
|
|
521
|
-
label="SOA Refresh",
|
|
522
953
|
validators=[MinValueValidator(1)],
|
|
954
|
+
label=_("SOA Refresh"),
|
|
523
955
|
)
|
|
524
|
-
soa_retry =
|
|
956
|
+
soa_retry = TimePeriodField(
|
|
525
957
|
required=False,
|
|
526
|
-
label="SOA Retry",
|
|
527
958
|
validators=[MinValueValidator(1)],
|
|
959
|
+
label=_("SOA Retry"),
|
|
528
960
|
)
|
|
529
|
-
soa_expire =
|
|
961
|
+
soa_expire = TimePeriodField(
|
|
530
962
|
required=False,
|
|
531
|
-
label="SOA Expire",
|
|
532
963
|
validators=[MinValueValidator(1)],
|
|
964
|
+
label=_("SOA Expire"),
|
|
533
965
|
)
|
|
534
|
-
soa_minimum =
|
|
966
|
+
soa_minimum = TimePeriodField(
|
|
535
967
|
required=False,
|
|
536
|
-
label="SOA Minimum TTL",
|
|
537
968
|
validators=[MinValueValidator(1)],
|
|
969
|
+
label=_("SOA Minimum TTL"),
|
|
970
|
+
)
|
|
971
|
+
rfc2317_prefix = RFC2317NetworkFormField(
|
|
972
|
+
required=False,
|
|
973
|
+
validators=[validate_ipv4, validate_prefix, validate_rfc2317],
|
|
974
|
+
help_text=_("RFC2317 IPv4 prefix with a length of at least 25 bits"),
|
|
975
|
+
label=_("RFC2317 Prefix"),
|
|
976
|
+
)
|
|
977
|
+
rfc2317_parent_managed = forms.NullBooleanField(
|
|
978
|
+
required=False,
|
|
979
|
+
widget=BulkEditNullBooleanSelect(),
|
|
980
|
+
help_text=_(
|
|
981
|
+
"IPv4 reverse zone for delegating the RFC2317 PTR records is managed in NetBox DNS"
|
|
982
|
+
),
|
|
983
|
+
label=_("RFC2317 Parent Managed"),
|
|
984
|
+
)
|
|
985
|
+
dnssec_policy = DynamicModelChoiceField(
|
|
986
|
+
queryset=DNSSECPolicy.objects.all(),
|
|
987
|
+
required=False,
|
|
988
|
+
label=_("DNSSEC Policy"),
|
|
989
|
+
)
|
|
990
|
+
parental_agents = SimpleArrayField(
|
|
991
|
+
required=False,
|
|
992
|
+
base_field=forms.GenericIPAddressField(),
|
|
993
|
+
label=_("Parental Agents"),
|
|
538
994
|
)
|
|
539
995
|
registrar = DynamicModelChoiceField(
|
|
540
996
|
queryset=Registrar.objects.all(),
|
|
541
997
|
required=False,
|
|
542
|
-
|
|
543
|
-
attrs={
|
|
544
|
-
"data-url": reverse_lazy("plugins-api:netbox_dns-api:registrar-list")
|
|
545
|
-
}
|
|
546
|
-
),
|
|
998
|
+
label=_("Registrar"),
|
|
547
999
|
)
|
|
548
1000
|
registry_domain_id = forms.CharField(
|
|
549
1001
|
required=False,
|
|
550
|
-
label="Registry Domain ID",
|
|
1002
|
+
label=_("Registry Domain ID"),
|
|
1003
|
+
)
|
|
1004
|
+
expiration_date = forms.DateField(
|
|
1005
|
+
required=False,
|
|
1006
|
+
label=_("Expiration Date"),
|
|
1007
|
+
widget=DatePicker,
|
|
1008
|
+
)
|
|
1009
|
+
domain_status = forms.ChoiceField(
|
|
1010
|
+
choices=add_blank_choice(ZoneEPPStatusChoices),
|
|
1011
|
+
required=False,
|
|
1012
|
+
label=_("Domain Status"),
|
|
551
1013
|
)
|
|
552
1014
|
registrant = DynamicModelChoiceField(
|
|
553
|
-
queryset=
|
|
1015
|
+
queryset=RegistrationContact.objects.all(),
|
|
554
1016
|
required=False,
|
|
555
|
-
|
|
556
|
-
attrs={"data-url": reverse_lazy("plugins-api:netbox_dns-api:contact-list")}
|
|
557
|
-
),
|
|
1017
|
+
label=_("Registrant"),
|
|
558
1018
|
)
|
|
559
1019
|
admin_c = DynamicModelChoiceField(
|
|
560
|
-
queryset=
|
|
1020
|
+
queryset=RegistrationContact.objects.all(),
|
|
561
1021
|
required=False,
|
|
562
|
-
label="Administrative Contact",
|
|
563
|
-
widget=APISelect(
|
|
564
|
-
attrs={"data-url": reverse_lazy("plugins-api:netbox_dns-api:contact-list")}
|
|
565
|
-
),
|
|
1022
|
+
label=_("Administrative Contact"),
|
|
566
1023
|
)
|
|
567
1024
|
tech_c = DynamicModelChoiceField(
|
|
568
|
-
queryset=
|
|
1025
|
+
queryset=RegistrationContact.objects.all(),
|
|
569
1026
|
required=False,
|
|
570
|
-
label="Technical Contact",
|
|
571
|
-
widget=APISelect(
|
|
572
|
-
attrs={"data-url": reverse_lazy("plugins-api:netbox_dns-api:contact-list")}
|
|
573
|
-
),
|
|
1027
|
+
label=_("Technical Contact"),
|
|
574
1028
|
)
|
|
575
1029
|
billing_c = DynamicModelChoiceField(
|
|
576
|
-
queryset=
|
|
1030
|
+
queryset=RegistrationContact.objects.all(),
|
|
577
1031
|
required=False,
|
|
578
|
-
label="Billing Contact",
|
|
579
|
-
widget=APISelect(
|
|
580
|
-
attrs={"data-url": reverse_lazy("plugins-api:netbox_dns-api:contact-list")}
|
|
581
|
-
),
|
|
1032
|
+
label=_("Billing Contact"),
|
|
582
1033
|
)
|
|
583
|
-
|
|
584
|
-
queryset=
|
|
1034
|
+
tenant_group = DynamicModelChoiceField(
|
|
1035
|
+
queryset=TenantGroup.objects.all(),
|
|
585
1036
|
required=False,
|
|
586
|
-
|
|
587
|
-
help_text="Assigned tenant",
|
|
588
|
-
)
|
|
589
|
-
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
|
590
|
-
|
|
591
|
-
model = Zone
|
|
592
|
-
|
|
593
|
-
fieldsets = (
|
|
594
|
-
(
|
|
595
|
-
None,
|
|
596
|
-
(
|
|
597
|
-
"view",
|
|
598
|
-
"status",
|
|
599
|
-
"nameservers",
|
|
600
|
-
"default_ttl",
|
|
601
|
-
"description",
|
|
602
|
-
"tenant",
|
|
603
|
-
),
|
|
604
|
-
),
|
|
605
|
-
(
|
|
606
|
-
"SOA",
|
|
607
|
-
(
|
|
608
|
-
"soa_ttl",
|
|
609
|
-
"soa_mname",
|
|
610
|
-
"soa_rname",
|
|
611
|
-
"soa_serial_auto",
|
|
612
|
-
"soa_serial",
|
|
613
|
-
"soa_refresh",
|
|
614
|
-
"soa_retry",
|
|
615
|
-
"soa_expire",
|
|
616
|
-
"soa_minimum",
|
|
617
|
-
),
|
|
618
|
-
),
|
|
619
|
-
(
|
|
620
|
-
"Domain Registration",
|
|
621
|
-
(
|
|
622
|
-
"registrar",
|
|
623
|
-
"registry_domain_id",
|
|
624
|
-
"registrant",
|
|
625
|
-
"admin_c",
|
|
626
|
-
"tech_c",
|
|
627
|
-
"billing_c",
|
|
628
|
-
),
|
|
629
|
-
),
|
|
1037
|
+
label=_("Tenant Group"),
|
|
630
1038
|
)
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
"
|
|
635
|
-
"registry_domain_id",
|
|
636
|
-
"registrant",
|
|
637
|
-
"admin_c",
|
|
638
|
-
"tech_c",
|
|
639
|
-
"billing_c",
|
|
1039
|
+
tenant = DynamicModelChoiceField(
|
|
1040
|
+
queryset=Tenant.objects.all(),
|
|
1041
|
+
required=False,
|
|
1042
|
+
label=_("Tenant"),
|
|
640
1043
|
)
|
|
641
|
-
|
|
642
|
-
def clean(self):
|
|
643
|
-
"""
|
|
644
|
-
If soa_serial_auto is True, set soa_serial to None.
|
|
645
|
-
"""
|
|
646
|
-
cleaned_data = super().clean()
|
|
647
|
-
if cleaned_data.get("soa_serial_auto"):
|
|
648
|
-
cleaned_data["soa_serial"] = None
|
|
1044
|
+
comments = CommentField()
|