netbox-plugin-dns 1.1.0b6__py3-none-any.whl → 1.1.1__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 +1 -1
- netbox_dns/api/nested_serializers.py +17 -16
- netbox_dns/api/serializers.py +1 -1
- netbox_dns/api/serializers_/record.py +1 -0
- netbox_dns/api/serializers_/{contact.py → registration_contact.py} +5 -5
- netbox_dns/api/serializers_/zone.py +5 -5
- netbox_dns/api/serializers_/zone_template.py +5 -5
- netbox_dns/api/urls.py +2 -2
- netbox_dns/api/views.py +7 -35
- netbox_dns/filtersets/__init__.py +1 -1
- netbox_dns/filtersets/nameserver.py +0 -0
- netbox_dns/filtersets/record.py +0 -0
- netbox_dns/filtersets/record_template.py +0 -0
- netbox_dns/filtersets/{contact.py → registration_contact.py} +4 -4
- netbox_dns/filtersets/zone.py +15 -15
- netbox_dns/filtersets/zone_template.py +15 -15
- netbox_dns/forms/__init__.py +1 -1
- netbox_dns/forms/nameserver.py +0 -0
- netbox_dns/forms/record.py +0 -0
- netbox_dns/forms/record_template.py +0 -0
- netbox_dns/forms/{contact.py → registration_contact.py} +16 -16
- netbox_dns/forms/zone.py +13 -13
- netbox_dns/forms/zone_template.py +13 -13
- netbox_dns/graphql/__init__.py +2 -2
- netbox_dns/graphql/filters.py +5 -5
- netbox_dns/graphql/schema.py +24 -44
- netbox_dns/graphql/types.py +38 -12
- netbox_dns/management/commands/rebuild_dnssync.py +18 -0
- netbox_dns/migrations/0007_alter_ordering_options.py +25 -0
- netbox_dns/migrations/{0007_view_prefixes.py → 0008_view_prefixes.py} +1 -1
- netbox_dns/migrations/0009_rename_contact_registrationcontact.py +36 -0
- netbox_dns/models/__init__.py +1 -1
- netbox_dns/models/nameserver.py +8 -3
- netbox_dns/models/record.py +42 -20
- netbox_dns/models/record_template.py +4 -1
- netbox_dns/models/registrar.py +7 -1
- netbox_dns/models/{contact.py → registration_contact.py} +15 -9
- netbox_dns/models/view.py +9 -2
- netbox_dns/models/zone.py +48 -30
- netbox_dns/models/zone_template.py +12 -9
- netbox_dns/navigation.py +7 -7
- netbox_dns/signals/ipam_dnssync.py +6 -2
- netbox_dns/tables/__init__.py +1 -1
- netbox_dns/tables/nameserver.py +1 -7
- netbox_dns/tables/record.py +10 -37
- netbox_dns/tables/record_template.py +0 -17
- netbox_dns/tables/registrar.py +0 -2
- netbox_dns/tables/{contact.py → registration_contact.py} +5 -6
- netbox_dns/tables/view.py +1 -8
- netbox_dns/tables/zone.py +0 -15
- netbox_dns/tables/zone_template.py +2 -16
- netbox_dns/templates/netbox_dns/{contact.html → registrationcontact.html} +1 -1
- netbox_dns/urls/__init__.py +2 -2
- netbox_dns/urls/nameserver.py +14 -38
- netbox_dns/urls/record.py +7 -19
- netbox_dns/urls/record_template.py +18 -27
- netbox_dns/urls/registrar.py +11 -35
- netbox_dns/urls/registration_contact.py +60 -0
- netbox_dns/urls/view.py +8 -22
- netbox_dns/urls/zone.py +8 -46
- netbox_dns/urls/zone_template.py +16 -26
- netbox_dns/utilities/ipam_dnssync.py +26 -24
- netbox_dns/validators/dns_name.py +9 -0
- netbox_dns/views/__init__.py +1 -1
- netbox_dns/views/nameserver.py +7 -3
- netbox_dns/views/record.py +12 -7
- netbox_dns/views/record_template.py +1 -1
- netbox_dns/views/registrar.py +0 -1
- netbox_dns/views/registration_contact.py +94 -0
- netbox_dns/views/view.py +6 -1
- netbox_dns/views/zone.py +7 -6
- netbox_dns/views/zone_template.py +2 -2
- {netbox_plugin_dns-1.1.0b6.dist-info → netbox_plugin_dns-1.1.1.dist-info}/METADATA +14 -14
- {netbox_plugin_dns-1.1.0b6.dist-info → netbox_plugin_dns-1.1.1.dist-info}/RECORD +78 -74
- {netbox_plugin_dns-1.1.0b6.dist-info → netbox_plugin_dns-1.1.1.dist-info}/WHEEL +2 -1
- netbox_plugin_dns-1.1.1.dist-info/top_level.txt +1 -0
- netbox_dns/urls/contact.py +0 -51
- netbox_dns/views/contact.py +0 -95
- {netbox_plugin_dns-1.1.0b6.dist-info → netbox_plugin_dns-1.1.1.dist-info}/LICENSE +0 -0
netbox_dns/models/record.py
CHANGED
|
@@ -10,6 +10,7 @@ from django.urls import reverse
|
|
|
10
10
|
from django.conf import settings
|
|
11
11
|
|
|
12
12
|
from netbox.models import NetBoxModel
|
|
13
|
+
from netbox.models.features import ContactsMixin
|
|
13
14
|
from netbox.search import SearchIndex, register_search
|
|
14
15
|
from netbox.plugins.utils import get_plugin_config
|
|
15
16
|
from utilities.querysets import RestrictedQuerySet
|
|
@@ -100,7 +101,7 @@ class RecordManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
|
|
100
101
|
)
|
|
101
102
|
|
|
102
103
|
|
|
103
|
-
class Record(ObjectModificationMixin, NetBoxModel):
|
|
104
|
+
class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
104
105
|
ACTIVE_STATUS_LIST = (RecordStatusChoices.STATUS_ACTIVE,)
|
|
105
106
|
|
|
106
107
|
unique_ptr_qs = Q(
|
|
@@ -193,7 +194,7 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
193
194
|
objects = RecordManager()
|
|
194
195
|
raw_objects = RestrictedQuerySet.as_manager()
|
|
195
196
|
|
|
196
|
-
clone_fields =
|
|
197
|
+
clone_fields = (
|
|
197
198
|
"zone",
|
|
198
199
|
"type",
|
|
199
200
|
"name",
|
|
@@ -202,10 +203,20 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
202
203
|
"ttl",
|
|
203
204
|
"disable_ptr",
|
|
204
205
|
"description",
|
|
205
|
-
|
|
206
|
+
)
|
|
206
207
|
|
|
207
208
|
class Meta:
|
|
208
|
-
|
|
209
|
+
verbose_name = "Record"
|
|
210
|
+
verbose_name_plural = "Records"
|
|
211
|
+
|
|
212
|
+
ordering = (
|
|
213
|
+
"fqdn",
|
|
214
|
+
"zone",
|
|
215
|
+
"name",
|
|
216
|
+
"type",
|
|
217
|
+
"value",
|
|
218
|
+
"status",
|
|
219
|
+
)
|
|
209
220
|
|
|
210
221
|
def __str__(self):
|
|
211
222
|
try:
|
|
@@ -493,20 +504,33 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
493
504
|
**data,
|
|
494
505
|
)
|
|
495
506
|
|
|
507
|
+
def update_fqdn(self, zone=None):
|
|
508
|
+
if zone is None:
|
|
509
|
+
zone = self.zone
|
|
510
|
+
|
|
511
|
+
_zone = dns_name.from_text(zone.name, origin=dns_name.root)
|
|
512
|
+
name = dns_name.from_text(self.name, origin=None)
|
|
513
|
+
fqdn = dns_name.from_text(self.name, origin=_zone)
|
|
514
|
+
|
|
515
|
+
if not fqdn.is_subdomain(_zone):
|
|
516
|
+
raise ValidationError(
|
|
517
|
+
{
|
|
518
|
+
"name": f"{self.name} is not a name in {zone.name}",
|
|
519
|
+
}
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
_zone.to_unicode()
|
|
523
|
+
name.to_unicode()
|
|
524
|
+
|
|
525
|
+
self.name = name.relativize(_zone).to_text()
|
|
526
|
+
self.fqdn = fqdn.to_text()
|
|
527
|
+
|
|
496
528
|
def validate_name(self, new_zone=None):
|
|
497
529
|
if new_zone is None:
|
|
498
530
|
new_zone = self.zone
|
|
499
531
|
|
|
500
532
|
try:
|
|
501
|
-
|
|
502
|
-
name = dns_name.from_text(self.name, origin=None)
|
|
503
|
-
fqdn = dns_name.from_text(self.name, origin=_zone)
|
|
504
|
-
|
|
505
|
-
_zone.to_unicode()
|
|
506
|
-
name.to_unicode()
|
|
507
|
-
|
|
508
|
-
self.name = name.relativize(_zone).to_text()
|
|
509
|
-
self.fqdn = fqdn.to_text()
|
|
533
|
+
self.update_fqdn(zone=new_zone)
|
|
510
534
|
|
|
511
535
|
except dns.exception.DNSException as exc:
|
|
512
536
|
raise ValidationError(
|
|
@@ -515,13 +539,6 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
515
539
|
}
|
|
516
540
|
)
|
|
517
541
|
|
|
518
|
-
if not fqdn.is_subdomain(_zone):
|
|
519
|
-
raise ValidationError(
|
|
520
|
-
{
|
|
521
|
-
"name": f"{self.name} is not a name in {new_zone.name}",
|
|
522
|
-
}
|
|
523
|
-
)
|
|
524
|
-
|
|
525
542
|
if self.type not in get_plugin_config(
|
|
526
543
|
"netbox_dns", "tolerate_non_rfc1035_types", default=[]
|
|
527
544
|
):
|
|
@@ -613,6 +630,11 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
613
630
|
if not get_plugin_config("netbox_dns", "enforce_unique_rrset_ttl", False):
|
|
614
631
|
return
|
|
615
632
|
|
|
633
|
+
if self.ipam_ip_address is not None and get_plugin_config(
|
|
634
|
+
"netbox_dns", "dnssync_conflict_deactivate", False
|
|
635
|
+
):
|
|
636
|
+
return
|
|
637
|
+
|
|
616
638
|
if self.type == RecordTypeChoices.PTR and self.managed:
|
|
617
639
|
return
|
|
618
640
|
|
netbox_dns/models/registrar.py
CHANGED
|
@@ -59,7 +59,13 @@ class Registrar(NetBoxModel):
|
|
|
59
59
|
return str(self.name)
|
|
60
60
|
|
|
61
61
|
class Meta:
|
|
62
|
-
|
|
62
|
+
verbose_name = "Registrar"
|
|
63
|
+
verbose_name_plural = "Registrars"
|
|
64
|
+
|
|
65
|
+
ordering = (
|
|
66
|
+
"name",
|
|
67
|
+
"iana_id",
|
|
68
|
+
)
|
|
63
69
|
|
|
64
70
|
|
|
65
71
|
@register_search
|
|
@@ -8,12 +8,12 @@ from taggit.managers import TaggableManager
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
__all__ = (
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"RegistrationContact",
|
|
12
|
+
"RegistrationContactIndex",
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
class
|
|
16
|
+
class RegistrationContact(NetBoxModel):
|
|
17
17
|
# +
|
|
18
18
|
# Data fields according to https://www.icann.org/resources/pages/rdds-labeling-policy-2017-02-01-en
|
|
19
19
|
# -
|
|
@@ -87,7 +87,7 @@ class Contact(NetBoxModel):
|
|
|
87
87
|
related_name="netbox_dns_contact_set",
|
|
88
88
|
)
|
|
89
89
|
|
|
90
|
-
clone_fields =
|
|
90
|
+
clone_fields = (
|
|
91
91
|
"name",
|
|
92
92
|
"description",
|
|
93
93
|
"organization",
|
|
@@ -102,10 +102,10 @@ class Contact(NetBoxModel):
|
|
|
102
102
|
"fax_ext",
|
|
103
103
|
"email",
|
|
104
104
|
"tags",
|
|
105
|
-
|
|
105
|
+
)
|
|
106
106
|
|
|
107
107
|
def get_absolute_url(self):
|
|
108
|
-
return reverse("plugins:netbox_dns:
|
|
108
|
+
return reverse("plugins:netbox_dns:registrationcontact", kwargs={"pk": self.pk})
|
|
109
109
|
|
|
110
110
|
def __str__(self):
|
|
111
111
|
if self.name is not None:
|
|
@@ -114,7 +114,13 @@ class Contact(NetBoxModel):
|
|
|
114
114
|
return self.contact_id
|
|
115
115
|
|
|
116
116
|
class Meta:
|
|
117
|
-
|
|
117
|
+
verbose_name = "Registration Contact"
|
|
118
|
+
verbose_name_plural = "Registration Contacts"
|
|
119
|
+
|
|
120
|
+
ordering = (
|
|
121
|
+
"name",
|
|
122
|
+
"contact_id",
|
|
123
|
+
)
|
|
118
124
|
|
|
119
125
|
@property
|
|
120
126
|
def zones(self):
|
|
@@ -127,8 +133,8 @@ class Contact(NetBoxModel):
|
|
|
127
133
|
|
|
128
134
|
|
|
129
135
|
@register_search
|
|
130
|
-
class
|
|
131
|
-
model =
|
|
136
|
+
class RegistrationContactIndex(SearchIndex):
|
|
137
|
+
model = RegistrationContact
|
|
132
138
|
fields = (
|
|
133
139
|
("name", 100),
|
|
134
140
|
("contact_id", 100),
|
netbox_dns/models/view.py
CHANGED
|
@@ -3,6 +3,7 @@ from django.urls import reverse
|
|
|
3
3
|
from django.core.exceptions import ValidationError
|
|
4
4
|
|
|
5
5
|
from netbox.models import NetBoxModel
|
|
6
|
+
from netbox.models.features import ContactsMixin
|
|
6
7
|
from netbox.search import SearchIndex, register_search
|
|
7
8
|
from netbox.context import current_request
|
|
8
9
|
from utilities.exceptions import AbortRequest
|
|
@@ -16,7 +17,7 @@ __all__ = (
|
|
|
16
17
|
)
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
class View(ObjectModificationMixin, NetBoxModel):
|
|
20
|
+
class View(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
20
21
|
name = models.CharField(
|
|
21
22
|
unique=True,
|
|
22
23
|
max_length=255,
|
|
@@ -41,7 +42,10 @@ class View(ObjectModificationMixin, NetBoxModel):
|
|
|
41
42
|
null=True,
|
|
42
43
|
)
|
|
43
44
|
|
|
44
|
-
clone_fields =
|
|
45
|
+
clone_fields = (
|
|
46
|
+
"name",
|
|
47
|
+
"description",
|
|
48
|
+
)
|
|
45
49
|
|
|
46
50
|
@classmethod
|
|
47
51
|
def get_default_view(cls):
|
|
@@ -54,6 +58,9 @@ class View(ObjectModificationMixin, NetBoxModel):
|
|
|
54
58
|
return str(self.name)
|
|
55
59
|
|
|
56
60
|
class Meta:
|
|
61
|
+
verbose_name = "View"
|
|
62
|
+
verbose_name_plural = "Views"
|
|
63
|
+
|
|
57
64
|
ordering = ("name",)
|
|
58
65
|
|
|
59
66
|
def delete(self, *args, **kwargs):
|
netbox_dns/models/zone.py
CHANGED
|
@@ -3,9 +3,8 @@ from math import ceil
|
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
|
|
5
5
|
from dns import name as dns_name
|
|
6
|
-
from dns.rdtypes.ANY import SOA
|
|
7
6
|
from dns.exception import DNSException
|
|
8
|
-
|
|
7
|
+
from dns.rdtypes.ANY import SOA
|
|
9
8
|
from django.core.validators import (
|
|
10
9
|
MinValueValidator,
|
|
11
10
|
MaxValueValidator,
|
|
@@ -19,6 +18,7 @@ from django.dispatch import receiver
|
|
|
19
18
|
from django.conf import settings
|
|
20
19
|
|
|
21
20
|
from netbox.models import NetBoxModel
|
|
21
|
+
from netbox.models.features import ContactsMixin
|
|
22
22
|
from netbox.search import SearchIndex, register_search
|
|
23
23
|
from netbox.plugins.utils import get_plugin_config
|
|
24
24
|
from utilities.querysets import RestrictedQuerySet
|
|
@@ -36,7 +36,7 @@ from netbox_dns.utilities import (
|
|
|
36
36
|
NameFormatError,
|
|
37
37
|
)
|
|
38
38
|
from netbox_dns.validators import (
|
|
39
|
-
|
|
39
|
+
validate_rname,
|
|
40
40
|
validate_domain_name,
|
|
41
41
|
)
|
|
42
42
|
from netbox_dns.mixins import ObjectModificationMixin
|
|
@@ -69,7 +69,7 @@ class ZoneManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
|
|
69
69
|
)
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
class Zone(ObjectModificationMixin, NetBoxModel):
|
|
72
|
+
class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
73
73
|
ACTIVE_STATUS_LIST = (ZoneStatusChoices.STATUS_ACTIVE,)
|
|
74
74
|
|
|
75
75
|
def __init__(self, *args, **kwargs):
|
|
@@ -78,6 +78,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
78
78
|
super().__init__(*args, **kwargs)
|
|
79
79
|
|
|
80
80
|
self._soa_serial_dirty = False
|
|
81
|
+
self._ip_addresses_checked = False
|
|
81
82
|
|
|
82
83
|
view = models.ForeignKey(
|
|
83
84
|
to="View",
|
|
@@ -191,7 +192,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
191
192
|
null=True,
|
|
192
193
|
)
|
|
193
194
|
registrant = models.ForeignKey(
|
|
194
|
-
to="
|
|
195
|
+
to="RegistrationContact",
|
|
195
196
|
on_delete=models.SET_NULL,
|
|
196
197
|
verbose_name="Registrant",
|
|
197
198
|
help_text="The owner of the domain",
|
|
@@ -199,7 +200,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
199
200
|
null=True,
|
|
200
201
|
)
|
|
201
202
|
admin_c = models.ForeignKey(
|
|
202
|
-
to="
|
|
203
|
+
to="RegistrationContact",
|
|
203
204
|
on_delete=models.SET_NULL,
|
|
204
205
|
verbose_name="Admin Contact",
|
|
205
206
|
related_name="admin_c_zones",
|
|
@@ -208,16 +209,16 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
208
209
|
null=True,
|
|
209
210
|
)
|
|
210
211
|
tech_c = models.ForeignKey(
|
|
211
|
-
to="
|
|
212
|
+
to="RegistrationContact",
|
|
212
213
|
on_delete=models.SET_NULL,
|
|
213
|
-
verbose_name="
|
|
214
|
+
verbose_name="Technical Contact",
|
|
214
215
|
related_name="tech_c_zones",
|
|
215
216
|
help_text="The technical contact for the domain",
|
|
216
217
|
blank=True,
|
|
217
218
|
null=True,
|
|
218
219
|
)
|
|
219
220
|
billing_c = models.ForeignKey(
|
|
220
|
-
to="
|
|
221
|
+
to="RegistrationContact",
|
|
221
222
|
on_delete=models.SET_NULL,
|
|
222
223
|
verbose_name="Billing Contact",
|
|
223
224
|
related_name="billing_c_zones",
|
|
@@ -248,7 +249,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
248
249
|
|
|
249
250
|
objects = ZoneManager()
|
|
250
251
|
|
|
251
|
-
clone_fields =
|
|
252
|
+
clone_fields = (
|
|
252
253
|
"view",
|
|
253
254
|
"name",
|
|
254
255
|
"status",
|
|
@@ -262,9 +263,12 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
262
263
|
"soa_expire",
|
|
263
264
|
"soa_minimum",
|
|
264
265
|
"description",
|
|
265
|
-
|
|
266
|
+
)
|
|
266
267
|
|
|
267
268
|
class Meta:
|
|
269
|
+
verbose_name = "Zone"
|
|
270
|
+
verbose_name_plural = "Zones"
|
|
271
|
+
|
|
268
272
|
ordering = (
|
|
269
273
|
"view",
|
|
270
274
|
"name",
|
|
@@ -280,7 +284,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
280
284
|
else:
|
|
281
285
|
try:
|
|
282
286
|
name = dns_name.from_text(self.name, origin=None).to_unicode()
|
|
283
|
-
except
|
|
287
|
+
except DNSException:
|
|
284
288
|
name = self.name
|
|
285
289
|
|
|
286
290
|
try:
|
|
@@ -308,6 +312,14 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
308
312
|
def soa_serial_dirty(self, soa_serial_dirty):
|
|
309
313
|
self._soa_serial_dirty = soa_serial_dirty
|
|
310
314
|
|
|
315
|
+
@property
|
|
316
|
+
def ip_addresses_checked(self):
|
|
317
|
+
return self._ip_addresses_checked
|
|
318
|
+
|
|
319
|
+
@ip_addresses_checked.setter
|
|
320
|
+
def ip_addresses_checked(self, ip_addresses_checked):
|
|
321
|
+
self._ip_addresses_checked = ip_addresses_checked
|
|
322
|
+
|
|
311
323
|
@property
|
|
312
324
|
def display_name(self):
|
|
313
325
|
return name_to_unicode(self.name)
|
|
@@ -621,7 +633,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
621
633
|
raise ValidationError("soa_rname not set and no default value defined")
|
|
622
634
|
try:
|
|
623
635
|
dns_name.from_text(self.soa_rname, origin=dns_name.root)
|
|
624
|
-
|
|
636
|
+
validate_rname(self.soa_rname)
|
|
625
637
|
except (DNSException, ValidationError) as exc:
|
|
626
638
|
raise ValidationError(
|
|
627
639
|
{
|
|
@@ -641,7 +653,7 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
641
653
|
old_zone = Zone.objects.get(pk=self.pk)
|
|
642
654
|
if not self.soa_serial_auto:
|
|
643
655
|
self.check_soa_serial_increment(old_zone.soa_serial, self.soa_serial)
|
|
644
|
-
|
|
656
|
+
elif not old_zone.soa_serial_auto:
|
|
645
657
|
try:
|
|
646
658
|
self.check_soa_serial_increment(
|
|
647
659
|
old_zone.soa_serial, self.get_auto_serial()
|
|
@@ -653,24 +665,26 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
653
665
|
}
|
|
654
666
|
)
|
|
655
667
|
|
|
656
|
-
if
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
raise ValidationError(exc.messages)
|
|
662
|
-
|
|
668
|
+
if (
|
|
669
|
+
not self.ip_addresses_checked
|
|
670
|
+
and old_zone.name != self.name
|
|
671
|
+
or old_zone.view != self.view
|
|
672
|
+
):
|
|
663
673
|
ip_addresses = IPAddress.objects.filter(
|
|
664
674
|
netbox_dns_records__in=self.record_set.filter(
|
|
665
675
|
ipam_ip_address__isnull=False
|
|
666
676
|
)
|
|
667
677
|
)
|
|
668
|
-
|
|
678
|
+
ip_addresses |= get_ip_addresses_by_zone(self)
|
|
679
|
+
|
|
680
|
+
for ip_address in ip_addresses.distinct():
|
|
669
681
|
try:
|
|
670
682
|
check_dns_records(ip_address, zone=self)
|
|
671
683
|
except ValidationError as exc:
|
|
672
684
|
raise ValidationError(exc.messages)
|
|
673
685
|
|
|
686
|
+
self.ip_addresses_checked = True
|
|
687
|
+
|
|
674
688
|
if self.is_reverse_zone:
|
|
675
689
|
self.arpa_network = self.network_from_name
|
|
676
690
|
|
|
@@ -785,12 +799,13 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
785
799
|
|
|
786
800
|
elif changed_fields is not None and {"name", "view", "status"} & changed_fields:
|
|
787
801
|
for address_record in self.record_set.filter(
|
|
788
|
-
type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
|
|
802
|
+
type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
|
|
803
|
+
ipam_ip_address__isnull=True,
|
|
789
804
|
):
|
|
790
805
|
address_record.save(update_fields=["ptr_record"])
|
|
791
806
|
|
|
792
807
|
if changed_fields is not None and "name" in changed_fields:
|
|
793
|
-
for _record in self.record_set.
|
|
808
|
+
for _record in self.record_set.filter(ipam_ip_address__isnull=True):
|
|
794
809
|
_record.save(
|
|
795
810
|
update_fields=["fqdn"],
|
|
796
811
|
save_zone_serial=False,
|
|
@@ -799,13 +814,14 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
799
814
|
)
|
|
800
815
|
|
|
801
816
|
if changed_fields is None or {"name", "view"} & changed_fields:
|
|
802
|
-
|
|
803
|
-
|
|
817
|
+
ip_addresses = IPAddress.objects.filter(
|
|
818
|
+
netbox_dns_records__in=self.record_set.filter(
|
|
804
819
|
ipam_ip_address__isnull=False
|
|
805
|
-
)
|
|
820
|
+
)
|
|
806
821
|
)
|
|
807
|
-
|
|
808
|
-
|
|
822
|
+
ip_addresses |= get_ip_addresses_by_zone(self)
|
|
823
|
+
|
|
824
|
+
for ip_address in ip_addresses.distinct():
|
|
809
825
|
update_dns_records(ip_address)
|
|
810
826
|
|
|
811
827
|
self.save_soa_serial()
|
|
@@ -848,7 +864,9 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
848
864
|
netbox_dns_records__in=self.record_set.filter(
|
|
849
865
|
ipam_ip_address__isnull=False
|
|
850
866
|
)
|
|
851
|
-
)
|
|
867
|
+
)
|
|
868
|
+
.distinct()
|
|
869
|
+
.values_list("pk", flat=True)
|
|
852
870
|
)
|
|
853
871
|
|
|
854
872
|
super().delete(*args, **kwargs)
|
|
@@ -47,7 +47,7 @@ class ZoneTemplate(NetBoxModel):
|
|
|
47
47
|
null=True,
|
|
48
48
|
)
|
|
49
49
|
registrant = models.ForeignKey(
|
|
50
|
-
to="
|
|
50
|
+
to="RegistrationContact",
|
|
51
51
|
on_delete=models.SET_NULL,
|
|
52
52
|
related_name="+",
|
|
53
53
|
help_text="The owner of the domain",
|
|
@@ -55,7 +55,7 @@ class ZoneTemplate(NetBoxModel):
|
|
|
55
55
|
null=True,
|
|
56
56
|
)
|
|
57
57
|
admin_c = models.ForeignKey(
|
|
58
|
-
to="
|
|
58
|
+
to="RegistrationContact",
|
|
59
59
|
on_delete=models.SET_NULL,
|
|
60
60
|
verbose_name="Admin contact",
|
|
61
61
|
related_name="+",
|
|
@@ -64,7 +64,7 @@ class ZoneTemplate(NetBoxModel):
|
|
|
64
64
|
null=True,
|
|
65
65
|
)
|
|
66
66
|
tech_c = models.ForeignKey(
|
|
67
|
-
to="
|
|
67
|
+
to="RegistrationContact",
|
|
68
68
|
on_delete=models.SET_NULL,
|
|
69
69
|
verbose_name="Tech contact",
|
|
70
70
|
related_name="+",
|
|
@@ -73,7 +73,7 @@ class ZoneTemplate(NetBoxModel):
|
|
|
73
73
|
null=True,
|
|
74
74
|
)
|
|
75
75
|
billing_c = models.ForeignKey(
|
|
76
|
-
to="
|
|
76
|
+
to="RegistrationContact",
|
|
77
77
|
on_delete=models.SET_NULL,
|
|
78
78
|
verbose_name="Billing contact",
|
|
79
79
|
related_name="+",
|
|
@@ -82,7 +82,7 @@ class ZoneTemplate(NetBoxModel):
|
|
|
82
82
|
null=True,
|
|
83
83
|
)
|
|
84
84
|
|
|
85
|
-
clone_fields =
|
|
85
|
+
clone_fields = (
|
|
86
86
|
"description",
|
|
87
87
|
"nameservers",
|
|
88
88
|
"record_templates",
|
|
@@ -92,19 +92,22 @@ class ZoneTemplate(NetBoxModel):
|
|
|
92
92
|
"admin_c",
|
|
93
93
|
"tech_c",
|
|
94
94
|
"billing_c",
|
|
95
|
-
|
|
95
|
+
)
|
|
96
96
|
|
|
97
|
-
template_fields =
|
|
97
|
+
template_fields = (
|
|
98
98
|
"tenant",
|
|
99
99
|
"registrar",
|
|
100
100
|
"registrant",
|
|
101
101
|
"admin_c",
|
|
102
102
|
"tech_c",
|
|
103
103
|
"billing_c",
|
|
104
|
-
|
|
104
|
+
)
|
|
105
105
|
|
|
106
106
|
class Meta:
|
|
107
|
-
|
|
107
|
+
verbose_name = "Zone Template"
|
|
108
|
+
verbose_name_plural = "Zone Templates"
|
|
109
|
+
|
|
110
|
+
ordering = ("name",)
|
|
108
111
|
|
|
109
112
|
def __str__(self):
|
|
110
113
|
return str(self.name)
|
netbox_dns/navigation.py
CHANGED
|
@@ -151,21 +151,21 @@ registrar_menu_item = PluginMenuItem(
|
|
|
151
151
|
)
|
|
152
152
|
|
|
153
153
|
contact_menu_item = PluginMenuItem(
|
|
154
|
-
link="plugins:netbox_dns:
|
|
155
|
-
link_text="Contacts",
|
|
156
|
-
permissions=["netbox_dns.
|
|
154
|
+
link="plugins:netbox_dns:registrationcontact_list",
|
|
155
|
+
link_text="Registration Contacts",
|
|
156
|
+
permissions=["netbox_dns.view_registrationcontact"],
|
|
157
157
|
buttons=(
|
|
158
158
|
PluginMenuButton(
|
|
159
|
-
"plugins:netbox_dns:
|
|
159
|
+
"plugins:netbox_dns:registrationcontact_add",
|
|
160
160
|
"Add",
|
|
161
161
|
"mdi mdi-plus-thick",
|
|
162
|
-
permissions=["netbox_dns.
|
|
162
|
+
permissions=["netbox_dns.add_registrationcontact"],
|
|
163
163
|
),
|
|
164
164
|
PluginMenuButton(
|
|
165
|
-
"plugins:netbox_dns:
|
|
165
|
+
"plugins:netbox_dns:registrationcontact_import",
|
|
166
166
|
"Import",
|
|
167
167
|
"mdi mdi-upload",
|
|
168
|
-
permissions=["netbox_dns.
|
|
168
|
+
permissions=["netbox_dns.add_registrationcontact"],
|
|
169
169
|
),
|
|
170
170
|
),
|
|
171
171
|
)
|
|
@@ -215,6 +215,10 @@ def ipam_dnssync_view_prefix_changed(**kwargs):
|
|
|
215
215
|
return
|
|
216
216
|
|
|
217
217
|
check_view = action != "post_remove"
|
|
218
|
+
|
|
219
|
+
ip_addresses = IPAddress.objects.none()
|
|
218
220
|
for prefix in Prefix.objects.filter(pk__in=kwargs.get("pk_set")):
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
ip_addresses |= get_ip_addresses_by_prefix(prefix, check_view=check_view)
|
|
222
|
+
|
|
223
|
+
for ip_address in ip_addresses.distinct():
|
|
224
|
+
update_dns_records(ip_address)
|
netbox_dns/tables/__init__.py
CHANGED
netbox_dns/tables/nameserver.py
CHANGED
|
@@ -22,13 +22,7 @@ class NameServerTable(TenancyColumnsMixin, NetBoxTable):
|
|
|
22
22
|
|
|
23
23
|
class Meta(NetBoxTable.Meta):
|
|
24
24
|
model = NameServer
|
|
25
|
-
fields = (
|
|
26
|
-
"name",
|
|
27
|
-
"description",
|
|
28
|
-
"tags",
|
|
29
|
-
"tenant",
|
|
30
|
-
"tenant_group",
|
|
31
|
-
)
|
|
25
|
+
fields = ("description",)
|
|
32
26
|
default_columns = (
|
|
33
27
|
"name",
|
|
34
28
|
"tags",
|