netbox-plugin-dns 1.1.2__py3-none-any.whl → 1.1.4__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.
Potentially problematic release.
This version of netbox-plugin-dns might be problematic. Click here for more details.
- netbox_dns/__init__.py +14 -6
- netbox_dns/api/nested_serializers.py +3 -2
- netbox_dns/api/serializers_/nameserver.py +2 -1
- netbox_dns/api/serializers_/record.py +5 -4
- netbox_dns/api/serializers_/record_template.py +2 -1
- netbox_dns/api/serializers_/view.py +2 -1
- netbox_dns/api/serializers_/zone.py +12 -11
- netbox_dns/api/serializers_/zone_template.py +8 -7
- netbox_dns/api/views.py +9 -4
- netbox_dns/choices/record.py +4 -2
- netbox_dns/choices/zone.py +8 -4
- netbox_dns/fields/address.py +5 -22
- netbox_dns/fields/network.py +2 -1
- netbox_dns/fields/rfc2317.py +7 -3
- netbox_dns/filtersets/nameserver.py +3 -2
- netbox_dns/filtersets/record.py +14 -9
- netbox_dns/filtersets/record_template.py +3 -2
- netbox_dns/filtersets/view.py +3 -2
- netbox_dns/filtersets/zone.py +24 -22
- netbox_dns/filtersets/zone_template.py +15 -14
- netbox_dns/forms/nameserver.py +41 -17
- netbox_dns/forms/record.py +61 -32
- netbox_dns/forms/record_template.py +49 -28
- netbox_dns/forms/registrar.py +21 -17
- netbox_dns/forms/registration_contact.py +37 -25
- netbox_dns/forms/view.py +49 -27
- netbox_dns/forms/zone.py +173 -120
- netbox_dns/forms/zone_template.py +53 -43
- netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
- netbox_dns/locale/en/LC_MESSAGES/django.mo +0 -0
- netbox_dns/management/commands/rebuild_dnssync.py +14 -1
- netbox_dns/models/nameserver.py +6 -2
- netbox_dns/models/record.py +74 -40
- netbox_dns/models/record_template.py +17 -9
- netbox_dns/models/registrar.py +11 -7
- netbox_dns/models/registration_contact.py +23 -11
- netbox_dns/models/view.py +15 -6
- netbox_dns/models/zone.py +83 -50
- netbox_dns/models/zone_template.py +12 -10
- netbox_dns/navigation.py +30 -28
- netbox_dns/signals/ipam_dnssync.py +21 -14
- netbox_dns/tables/ipam_dnssync.py +2 -1
- netbox_dns/tables/nameserver.py +2 -0
- netbox_dns/tables/record.py +21 -11
- netbox_dns/tables/record_template.py +12 -5
- netbox_dns/tables/registrar.py +2 -0
- netbox_dns/tables/registration_contact.py +2 -0
- netbox_dns/tables/view.py +3 -1
- netbox_dns/tables/zone.py +15 -2
- netbox_dns/tables/zone_template.py +7 -0
- netbox_dns/templates/netbox_dns/nameserver.html +6 -5
- netbox_dns/templates/netbox_dns/record/managed.html +2 -1
- netbox_dns/templates/netbox_dns/record/related.html +26 -14
- netbox_dns/templates/netbox_dns/record.html +39 -20
- netbox_dns/templates/netbox_dns/recordtemplate.html +27 -15
- netbox_dns/templates/netbox_dns/registrar.html +11 -10
- netbox_dns/templates/netbox_dns/registrationcontact.html +16 -15
- netbox_dns/templates/netbox_dns/view/button.html +2 -1
- netbox_dns/templates/netbox_dns/view/prefix.html +7 -4
- netbox_dns/templates/netbox_dns/view/related.html +26 -10
- netbox_dns/templates/netbox_dns/view.html +11 -14
- netbox_dns/templates/netbox_dns/zone/base.html +2 -1
- netbox_dns/templates/netbox_dns/zone/child.html +3 -2
- netbox_dns/templates/netbox_dns/zone/record.html +3 -2
- netbox_dns/templates/netbox_dns/zone/registration.html +8 -7
- netbox_dns/templates/netbox_dns/zone.html +28 -30
- netbox_dns/templates/netbox_dns/zonetemplate.html +27 -17
- netbox_dns/utilities/ipam_dnssync.py +15 -4
- netbox_dns/validators/dns_name.py +11 -4
- netbox_dns/validators/dns_value.py +55 -9
- netbox_dns/validators/rfc2317.py +6 -3
- netbox_dns/views/nameserver.py +4 -2
- netbox_dns/views/record_template.py +4 -3
- netbox_dns/views/registrar.py +3 -1
- netbox_dns/views/registration_contact.py +2 -1
- netbox_dns/views/view.py +2 -1
- netbox_dns/views/zone.py +6 -4
- netbox_dns/views/zone_template.py +8 -7
- {netbox_plugin_dns-1.1.2.dist-info → netbox_plugin_dns-1.1.4.dist-info}/METADATA +2 -2
- netbox_plugin_dns-1.1.4.dist-info/RECORD +150 -0
- netbox_plugin_dns-1.1.2.dist-info/RECORD +0 -148
- {netbox_plugin_dns-1.1.2.dist-info → netbox_plugin_dns-1.1.4.dist-info}/LICENSE +0 -0
- {netbox_plugin_dns-1.1.2.dist-info → netbox_plugin_dns-1.1.4.dist-info}/WHEEL +0 -0
- {netbox_plugin_dns-1.1.2.dist-info → netbox_plugin_dns-1.1.4.dist-info}/top_level.txt +0 -0
netbox_dns/models/zone.py
CHANGED
|
@@ -16,6 +16,8 @@ from django.urls import reverse
|
|
|
16
16
|
from django.db.models.signals import m2m_changed
|
|
17
17
|
from django.dispatch import receiver
|
|
18
18
|
from django.conf import settings
|
|
19
|
+
from django.utils.translation import gettext_lazy as _
|
|
20
|
+
from django.utils.translation import pgettext_lazy as _p
|
|
19
21
|
|
|
20
22
|
from netbox.models import NetBoxModel
|
|
21
23
|
from netbox.models.features import ContactsMixin
|
|
@@ -51,6 +53,9 @@ __all__ = (
|
|
|
51
53
|
"ZoneIndex",
|
|
52
54
|
)
|
|
53
55
|
|
|
56
|
+
ZONE_ACTIVE_STATUS_LIST = get_plugin_config("netbox_dns", "zone_active_status")
|
|
57
|
+
RECORD_ACTIVE_STATUS_LIST = get_plugin_config("netbox_dns", "record_active_status")
|
|
58
|
+
|
|
54
59
|
|
|
55
60
|
class ZoneManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
|
56
61
|
"""
|
|
@@ -63,15 +68,13 @@ class ZoneManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
|
|
63
68
|
.get_queryset()
|
|
64
69
|
.annotate(
|
|
65
70
|
active=ExpressionWrapper(
|
|
66
|
-
Q(status__in=
|
|
71
|
+
Q(status__in=ZONE_ACTIVE_STATUS_LIST), output_field=BooleanField()
|
|
67
72
|
)
|
|
68
73
|
)
|
|
69
74
|
)
|
|
70
75
|
|
|
71
76
|
|
|
72
77
|
class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
73
|
-
ACTIVE_STATUS_LIST = (ZoneStatusChoices.STATUS_ACTIVE,)
|
|
74
|
-
|
|
75
78
|
def __init__(self, *args, **kwargs):
|
|
76
79
|
kwargs.pop("template", None)
|
|
77
80
|
|
|
@@ -81,95 +84,101 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
81
84
|
self._ip_addresses_checked = False
|
|
82
85
|
|
|
83
86
|
view = models.ForeignKey(
|
|
87
|
+
verbose_name=_p("DNS", "View"),
|
|
84
88
|
to="View",
|
|
85
89
|
on_delete=models.PROTECT,
|
|
86
90
|
null=False,
|
|
87
91
|
)
|
|
88
92
|
name = models.CharField(
|
|
93
|
+
verbose_name=_("Name"),
|
|
89
94
|
max_length=255,
|
|
90
95
|
)
|
|
91
96
|
status = models.CharField(
|
|
97
|
+
verbose_name=_("Status"),
|
|
92
98
|
max_length=50,
|
|
93
99
|
choices=ZoneStatusChoices,
|
|
94
100
|
default=ZoneStatusChoices.STATUS_ACTIVE,
|
|
95
101
|
blank=True,
|
|
96
102
|
)
|
|
97
103
|
nameservers = models.ManyToManyField(
|
|
104
|
+
verbose_name=_("Nameserver"),
|
|
98
105
|
to="NameServer",
|
|
99
106
|
related_name="zones",
|
|
100
107
|
blank=True,
|
|
101
108
|
)
|
|
102
109
|
default_ttl = models.PositiveIntegerField(
|
|
110
|
+
verbose_name=_("Default TTL"),
|
|
103
111
|
blank=True,
|
|
104
|
-
verbose_name="Default TTL",
|
|
105
112
|
validators=[MinValueValidator(1)],
|
|
106
113
|
)
|
|
107
114
|
soa_ttl = models.PositiveIntegerField(
|
|
115
|
+
verbose_name=_("SOA TTL"),
|
|
108
116
|
blank=False,
|
|
109
117
|
null=False,
|
|
110
|
-
verbose_name="SOA TTL",
|
|
111
118
|
validators=[MinValueValidator(1)],
|
|
112
119
|
)
|
|
113
120
|
soa_mname = models.ForeignKey(
|
|
121
|
+
verbose_name=_("SOA MName"),
|
|
114
122
|
to="NameServer",
|
|
115
123
|
related_name="zones_soa",
|
|
116
|
-
verbose_name="SOA MName",
|
|
117
124
|
on_delete=models.PROTECT,
|
|
118
125
|
blank=False,
|
|
119
126
|
null=False,
|
|
120
127
|
)
|
|
121
128
|
soa_rname = models.CharField(
|
|
129
|
+
verbose_name=_("SOA RName"),
|
|
122
130
|
max_length=255,
|
|
123
131
|
blank=False,
|
|
124
132
|
null=False,
|
|
125
|
-
verbose_name="SOA RName",
|
|
126
133
|
)
|
|
127
134
|
soa_serial = models.BigIntegerField(
|
|
135
|
+
verbose_name=_("SOA Serial"),
|
|
128
136
|
blank=True,
|
|
129
137
|
null=True,
|
|
130
|
-
verbose_name="SOA Serial",
|
|
131
138
|
validators=[MinValueValidator(1), MaxValueValidator(4294967295)],
|
|
132
139
|
)
|
|
133
140
|
soa_refresh = models.PositiveIntegerField(
|
|
141
|
+
verbose_name=_("SOA Refresh"),
|
|
134
142
|
blank=False,
|
|
135
143
|
null=False,
|
|
136
|
-
verbose_name="SOA Refresh",
|
|
137
144
|
validators=[MinValueValidator(1)],
|
|
138
145
|
)
|
|
139
146
|
soa_retry = models.PositiveIntegerField(
|
|
147
|
+
verbose_name=_("SOA Retry"),
|
|
140
148
|
blank=False,
|
|
141
149
|
null=False,
|
|
142
|
-
verbose_name="SOA Retry",
|
|
143
150
|
validators=[MinValueValidator(1)],
|
|
144
151
|
)
|
|
145
152
|
soa_expire = models.PositiveIntegerField(
|
|
153
|
+
verbose_name=_("SOA Expire"),
|
|
146
154
|
blank=False,
|
|
147
155
|
null=False,
|
|
148
|
-
verbose_name="SOA Expire",
|
|
149
156
|
validators=[MinValueValidator(1)],
|
|
150
157
|
)
|
|
151
158
|
soa_minimum = models.PositiveIntegerField(
|
|
159
|
+
verbose_name=_("SOA Minimum TTL"),
|
|
152
160
|
blank=False,
|
|
153
161
|
null=False,
|
|
154
|
-
verbose_name="SOA Minimum TTL",
|
|
155
162
|
validators=[MinValueValidator(1)],
|
|
156
163
|
)
|
|
157
164
|
soa_serial_auto = models.BooleanField(
|
|
158
|
-
verbose_name="Generate SOA Serial",
|
|
159
|
-
help_text="Automatically generate the SOA
|
|
165
|
+
verbose_name=_("Generate SOA Serial"),
|
|
166
|
+
help_text=_("Automatically generate the SOA serial number"),
|
|
160
167
|
default=True,
|
|
161
168
|
)
|
|
162
169
|
description = models.CharField(
|
|
170
|
+
verbose_name=_("Description"),
|
|
163
171
|
max_length=200,
|
|
164
172
|
blank=True,
|
|
165
173
|
)
|
|
166
174
|
arpa_network = NetworkField(
|
|
167
|
-
verbose_name="ARPA Network",
|
|
168
|
-
help_text="Network related to a reverse lookup zone (.arpa)",
|
|
175
|
+
verbose_name=_("ARPA Network"),
|
|
176
|
+
help_text=_("Network related to a reverse lookup zone (.arpa)"),
|
|
169
177
|
blank=True,
|
|
170
178
|
null=True,
|
|
171
179
|
)
|
|
172
180
|
tenant = models.ForeignKey(
|
|
181
|
+
verbose_name=_("Tenant"),
|
|
173
182
|
to="tenancy.Tenant",
|
|
174
183
|
on_delete=models.PROTECT,
|
|
175
184
|
related_name="netbox_dns_zones",
|
|
@@ -177,72 +186,66 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
177
186
|
null=True,
|
|
178
187
|
)
|
|
179
188
|
registrar = models.ForeignKey(
|
|
189
|
+
verbose_name=_("Registrar"),
|
|
180
190
|
to="Registrar",
|
|
181
191
|
on_delete=models.SET_NULL,
|
|
182
|
-
verbose_name="Registrar",
|
|
183
|
-
help_text="The external registrar the domain is registered with",
|
|
184
192
|
blank=True,
|
|
185
193
|
null=True,
|
|
186
194
|
)
|
|
187
195
|
registry_domain_id = models.CharField(
|
|
188
|
-
verbose_name="Registry Domain ID",
|
|
189
|
-
help_text="The ID of the domain assigned by the registry",
|
|
196
|
+
verbose_name=_("Registry Domain ID"),
|
|
190
197
|
max_length=50,
|
|
191
198
|
blank=True,
|
|
192
199
|
null=True,
|
|
193
200
|
)
|
|
194
201
|
registrant = models.ForeignKey(
|
|
202
|
+
verbose_name=_("Registrant"),
|
|
195
203
|
to="RegistrationContact",
|
|
196
204
|
on_delete=models.SET_NULL,
|
|
197
|
-
verbose_name="Registrant",
|
|
198
|
-
help_text="The owner of the domain",
|
|
199
205
|
blank=True,
|
|
200
206
|
null=True,
|
|
201
207
|
)
|
|
202
208
|
admin_c = models.ForeignKey(
|
|
209
|
+
verbose_name="Administrative Contact",
|
|
203
210
|
to="RegistrationContact",
|
|
204
211
|
on_delete=models.SET_NULL,
|
|
205
|
-
verbose_name="Admin Contact",
|
|
206
212
|
related_name="admin_c_zones",
|
|
207
|
-
help_text="The administrative contact for the domain",
|
|
208
213
|
blank=True,
|
|
209
214
|
null=True,
|
|
210
215
|
)
|
|
211
216
|
tech_c = models.ForeignKey(
|
|
217
|
+
verbose_name=_("Technical Contact"),
|
|
212
218
|
to="RegistrationContact",
|
|
213
219
|
on_delete=models.SET_NULL,
|
|
214
|
-
verbose_name="Technical Contact",
|
|
215
220
|
related_name="tech_c_zones",
|
|
216
|
-
help_text="The technical contact for the domain",
|
|
217
221
|
blank=True,
|
|
218
222
|
null=True,
|
|
219
223
|
)
|
|
220
224
|
billing_c = models.ForeignKey(
|
|
225
|
+
verbose_name=_("Billing Contact"),
|
|
221
226
|
to="RegistrationContact",
|
|
222
227
|
on_delete=models.SET_NULL,
|
|
223
|
-
verbose_name="Billing Contact",
|
|
224
228
|
related_name="billing_c_zones",
|
|
225
|
-
help_text="The billing contact for the domain",
|
|
226
229
|
blank=True,
|
|
227
230
|
null=True,
|
|
228
231
|
)
|
|
229
232
|
rfc2317_prefix = RFC2317NetworkField(
|
|
230
|
-
verbose_name="
|
|
231
|
-
help_text="RFC2317 IPv4 prefix
|
|
233
|
+
verbose_name=_("RFC2317 Prefix"),
|
|
234
|
+
help_text=_("RFC2317 IPv4 prefix with a length of at least 25 bits"),
|
|
232
235
|
blank=True,
|
|
233
236
|
null=True,
|
|
234
237
|
)
|
|
235
238
|
rfc2317_parent_managed = models.BooleanField(
|
|
236
|
-
verbose_name="RFC2317 Parent Managed",
|
|
237
|
-
help_text="The parent zone for the RFC2317 zone is managed by NetBox DNS",
|
|
239
|
+
verbose_name=_("RFC2317 Parent Managed"),
|
|
240
|
+
help_text=_("The parent zone for the RFC2317 zone is managed by NetBox DNS"),
|
|
238
241
|
default=False,
|
|
239
242
|
)
|
|
240
243
|
rfc2317_parent_zone = models.ForeignKey(
|
|
244
|
+
verbose_name=_("RFC2317 Parent Zone"),
|
|
241
245
|
to="self",
|
|
242
246
|
on_delete=models.SET_NULL,
|
|
243
|
-
verbose_name="RFC2317 Parent Zone",
|
|
244
247
|
related_name="rfc2317_child_zones",
|
|
245
|
-
help_text="Parent zone for RFC2317 reverse zones",
|
|
248
|
+
help_text=_("Parent zone for RFC2317 reverse zones"),
|
|
246
249
|
blank=True,
|
|
247
250
|
null=True,
|
|
248
251
|
)
|
|
@@ -266,8 +269,8 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
266
269
|
)
|
|
267
270
|
|
|
268
271
|
class Meta:
|
|
269
|
-
verbose_name = "Zone"
|
|
270
|
-
verbose_name_plural = "Zones"
|
|
272
|
+
verbose_name = _("Zone")
|
|
273
|
+
verbose_name_plural = _("Zones")
|
|
271
274
|
|
|
272
275
|
ordering = (
|
|
273
276
|
"view",
|
|
@@ -297,11 +300,21 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
297
300
|
|
|
298
301
|
@staticmethod
|
|
299
302
|
def get_defaults():
|
|
303
|
+
default_fields = (
|
|
304
|
+
"zone_default_ttl",
|
|
305
|
+
"zone_soa_ttl",
|
|
306
|
+
"zone_soa_serial",
|
|
307
|
+
"zone_soa_refresh",
|
|
308
|
+
"zone_soa_retry",
|
|
309
|
+
"zone_soa_expire",
|
|
310
|
+
"zone_soa_minimum",
|
|
311
|
+
"zone_soa_rname",
|
|
312
|
+
)
|
|
313
|
+
|
|
300
314
|
return {
|
|
301
315
|
field[5:]: value
|
|
302
316
|
for field, value in settings.PLUGINS_CONFIG.get("netbox_dns").items()
|
|
303
|
-
if field
|
|
304
|
-
and field not in ("zone_soa_mname", "zone_nameservers")
|
|
317
|
+
if field in default_fields
|
|
305
318
|
}
|
|
306
319
|
|
|
307
320
|
@property
|
|
@@ -335,7 +348,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
335
348
|
|
|
336
349
|
@property
|
|
337
350
|
def is_active(self):
|
|
338
|
-
return self.status in
|
|
351
|
+
return self.status in ZONE_ACTIVE_STATUS_LIST
|
|
339
352
|
|
|
340
353
|
@property
|
|
341
354
|
def is_reverse_zone(self):
|
|
@@ -453,7 +466,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
453
466
|
ns_errors = []
|
|
454
467
|
|
|
455
468
|
if not nameservers:
|
|
456
|
-
ns_errors.append(
|
|
469
|
+
ns_errors.append(
|
|
470
|
+
_("No nameservers are configured for zone {zone}").format(zone=self)
|
|
471
|
+
)
|
|
457
472
|
|
|
458
473
|
for _nameserver in nameservers:
|
|
459
474
|
name = dns_name.from_text(_nameserver.name, origin=None)
|
|
@@ -470,14 +485,16 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
470
485
|
relative_name = name.relativize(parent).to_text()
|
|
471
486
|
address_records = Record.objects.filter(
|
|
472
487
|
Q(zone=ns_zone),
|
|
473
|
-
Q(status__in=
|
|
488
|
+
Q(status__in=RECORD_ACTIVE_STATUS_LIST),
|
|
474
489
|
Q(Q(name=f"{_nameserver.name}.") | Q(name=relative_name)),
|
|
475
490
|
Q(Q(type=RecordTypeChoices.A) | Q(type=RecordTypeChoices.AAAA)),
|
|
476
491
|
)
|
|
477
492
|
|
|
478
493
|
if not address_records:
|
|
479
494
|
ns_warnings.append(
|
|
480
|
-
|
|
495
|
+
_(
|
|
496
|
+
"Nameserver {nameserver} does not have an active address record in zone {zone}"
|
|
497
|
+
).format(nameserver=_nameserver.name, zone=ns_zone)
|
|
481
498
|
)
|
|
482
499
|
|
|
483
500
|
return ns_warnings, ns_errors
|
|
@@ -491,7 +508,11 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
491
508
|
|
|
492
509
|
if (new_serial - old_serial) % SOA_SERIAL_WRAP > MAX_SOA_SERIAL_INCREMENT:
|
|
493
510
|
raise ValidationError(
|
|
494
|
-
{
|
|
511
|
+
{
|
|
512
|
+
"soa_serial": _(
|
|
513
|
+
"soa_serial must not decrease for zone {zone}."
|
|
514
|
+
).format(zone=self.name)
|
|
515
|
+
}
|
|
495
516
|
)
|
|
496
517
|
|
|
497
518
|
def get_auto_serial(self):
|
|
@@ -602,7 +623,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
602
623
|
self.soa_mname = NameServer.objects.get(name=default_soa_mname)
|
|
603
624
|
except NameServer.DoesNotExist:
|
|
604
625
|
raise ValidationError(
|
|
605
|
-
|
|
626
|
+
_("Default soa_mname instance {nameserver} does not exist").format(
|
|
627
|
+
nameserver=default_soa_mname
|
|
628
|
+
)
|
|
606
629
|
)
|
|
607
630
|
|
|
608
631
|
super().clean_fields(exclude=exclude)
|
|
@@ -630,7 +653,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
630
653
|
) from None
|
|
631
654
|
|
|
632
655
|
if self.soa_rname in (None, ""):
|
|
633
|
-
raise ValidationError("soa_rname not set and no default value defined")
|
|
656
|
+
raise ValidationError(_("soa_rname not set and no default value defined"))
|
|
634
657
|
try:
|
|
635
658
|
dns_name.from_text(self.soa_rname, origin=dns_name.root)
|
|
636
659
|
validate_rname(self.soa_rname)
|
|
@@ -645,7 +668,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
645
668
|
if self.soa_serial is None:
|
|
646
669
|
raise ValidationError(
|
|
647
670
|
{
|
|
648
|
-
"soa_serial":
|
|
671
|
+
"soa_serial": _(
|
|
672
|
+
"soa_serial is not defined and soa_serial_auto is disabled for zone {zone}."
|
|
673
|
+
).format(zone=self.name)
|
|
649
674
|
}
|
|
650
675
|
)
|
|
651
676
|
|
|
@@ -663,7 +688,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
663
688
|
except ValidationError:
|
|
664
689
|
raise ValidationError(
|
|
665
690
|
{
|
|
666
|
-
"soa_serial_auto":
|
|
691
|
+
"soa_serial_auto": _(
|
|
692
|
+
"Enabling soa_serial_auto would decrease soa_serial for zone {zone}."
|
|
693
|
+
).format(zone=self.name)
|
|
667
694
|
}
|
|
668
695
|
)
|
|
669
696
|
|
|
@@ -697,7 +724,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
697
724
|
if self.arpa_network is not None:
|
|
698
725
|
raise ValidationError(
|
|
699
726
|
{
|
|
700
|
-
"rfc2317_prefix":
|
|
727
|
+
"rfc2317_prefix": _(
|
|
728
|
+
"A regular reverse zone can not be used as an RFC2317 zone."
|
|
729
|
+
)
|
|
701
730
|
}
|
|
702
731
|
)
|
|
703
732
|
|
|
@@ -707,7 +736,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
707
736
|
if rfc2317_parent_zone is None:
|
|
708
737
|
raise ValidationError(
|
|
709
738
|
{
|
|
710
|
-
"rfc2317_parent_managed":
|
|
739
|
+
"rfc2317_parent_managed": _(
|
|
740
|
+
"Parent zone not found in view {view}."
|
|
741
|
+
).format(view=self.view)
|
|
711
742
|
}
|
|
712
743
|
)
|
|
713
744
|
|
|
@@ -724,7 +755,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
724
755
|
if overlapping_zones.exists():
|
|
725
756
|
raise ValidationError(
|
|
726
757
|
{
|
|
727
|
-
"rfc2317_prefix":
|
|
758
|
+
"rfc2317_prefix": _(
|
|
759
|
+
"RFC2317 prefix overlaps with zone {zone}."
|
|
760
|
+
).format(zone=overlapping_zones.first())
|
|
728
761
|
}
|
|
729
762
|
)
|
|
730
763
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from django.db import models
|
|
2
2
|
from django.urls import reverse
|
|
3
|
+
from django.utils.translation import gettext_lazy as _
|
|
3
4
|
|
|
4
5
|
from netbox.models import NetBoxModel
|
|
5
6
|
from netbox.search import SearchIndex, register_search
|
|
@@ -13,25 +14,29 @@ __all__ = (
|
|
|
13
14
|
|
|
14
15
|
class ZoneTemplate(NetBoxModel):
|
|
15
16
|
name = models.CharField(
|
|
16
|
-
verbose_name="Template
|
|
17
|
+
verbose_name=_("Template Name"),
|
|
17
18
|
unique=True,
|
|
18
19
|
max_length=200,
|
|
19
20
|
)
|
|
20
21
|
description = models.CharField(
|
|
22
|
+
verbose_name=_("Description"),
|
|
21
23
|
max_length=200,
|
|
22
24
|
blank=True,
|
|
23
25
|
)
|
|
24
26
|
nameservers = models.ManyToManyField(
|
|
27
|
+
verbose_name=_("Nameservers"),
|
|
25
28
|
to="NameServer",
|
|
26
29
|
related_name="+",
|
|
27
30
|
blank=True,
|
|
28
31
|
)
|
|
29
32
|
record_templates = models.ManyToManyField(
|
|
33
|
+
verbose_name=_("Record Templates"),
|
|
30
34
|
to="RecordTemplate",
|
|
31
35
|
related_name="zone_templates",
|
|
32
36
|
blank=True,
|
|
33
37
|
)
|
|
34
38
|
tenant = models.ForeignKey(
|
|
39
|
+
verbose_name=_("Tenant"),
|
|
35
40
|
to="tenancy.Tenant",
|
|
36
41
|
on_delete=models.SET_NULL,
|
|
37
42
|
related_name="+",
|
|
@@ -39,45 +44,42 @@ class ZoneTemplate(NetBoxModel):
|
|
|
39
44
|
null=True,
|
|
40
45
|
)
|
|
41
46
|
registrar = models.ForeignKey(
|
|
47
|
+
verbose_name=_("Registrar"),
|
|
42
48
|
to="Registrar",
|
|
43
49
|
on_delete=models.SET_NULL,
|
|
44
50
|
related_name="+",
|
|
45
|
-
help_text="The external registrar the domain is registered with",
|
|
46
51
|
blank=True,
|
|
47
52
|
null=True,
|
|
48
53
|
)
|
|
49
54
|
registrant = models.ForeignKey(
|
|
55
|
+
verbose_name=_("Registrant"),
|
|
50
56
|
to="RegistrationContact",
|
|
51
57
|
on_delete=models.SET_NULL,
|
|
52
58
|
related_name="+",
|
|
53
|
-
help_text="The owner of the domain",
|
|
54
59
|
blank=True,
|
|
55
60
|
null=True,
|
|
56
61
|
)
|
|
57
62
|
admin_c = models.ForeignKey(
|
|
63
|
+
verbose_name=_("Administrative Contact"),
|
|
58
64
|
to="RegistrationContact",
|
|
59
65
|
on_delete=models.SET_NULL,
|
|
60
|
-
verbose_name="Admin contact",
|
|
61
66
|
related_name="+",
|
|
62
|
-
help_text="The administrative contact for the domain",
|
|
63
67
|
blank=True,
|
|
64
68
|
null=True,
|
|
65
69
|
)
|
|
66
70
|
tech_c = models.ForeignKey(
|
|
71
|
+
verbose_name=_("Technical Contact"),
|
|
67
72
|
to="RegistrationContact",
|
|
68
73
|
on_delete=models.SET_NULL,
|
|
69
|
-
verbose_name="Tech contact",
|
|
70
74
|
related_name="+",
|
|
71
|
-
help_text="The technical contact for the domain",
|
|
72
75
|
blank=True,
|
|
73
76
|
null=True,
|
|
74
77
|
)
|
|
75
78
|
billing_c = models.ForeignKey(
|
|
79
|
+
verbose_name=_("Billing Contact"),
|
|
76
80
|
to="RegistrationContact",
|
|
77
81
|
on_delete=models.SET_NULL,
|
|
78
|
-
verbose_name="Billing contact",
|
|
79
82
|
related_name="+",
|
|
80
|
-
help_text="The billing contact for the domain",
|
|
81
83
|
blank=True,
|
|
82
84
|
null=True,
|
|
83
85
|
)
|
|
@@ -104,7 +106,7 @@ class ZoneTemplate(NetBoxModel):
|
|
|
104
106
|
)
|
|
105
107
|
|
|
106
108
|
class Meta:
|
|
107
|
-
verbose_name = "Zone Template"
|
|
109
|
+
verbose_name = _("Zone Template")
|
|
108
110
|
verbose_name_plural = "Zone Templates"
|
|
109
111
|
|
|
110
112
|
ordering = ("name",)
|