netbox-plugin-dns 1.3.3__py3-none-any.whl → 1.3.5__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/management/commands/cleanup_database.py +174 -145
- netbox_dns/management/commands/cleanup_rrset_ttl.py +12 -6
- netbox_dns/management/commands/rebuild_dnssync.py +1 -1
- netbox_dns/models/record.py +26 -1
- netbox_dns/models/zone.py +6 -1
- netbox_dns/utilities/ipam_dnssync.py +11 -4
- {netbox_plugin_dns-1.3.3.dist-info → netbox_plugin_dns-1.3.5.dist-info}/METADATA +1 -1
- {netbox_plugin_dns-1.3.3.dist-info → netbox_plugin_dns-1.3.5.dist-info}/RECORD +12 -14
- netbox_dns/management/commands/remove_orphaned_ptr_records.py +0 -35
- netbox_dns/management/commands/update_soa.py +0 -22
- {netbox_plugin_dns-1.3.3.dist-info → netbox_plugin_dns-1.3.5.dist-info}/WHEEL +0 -0
- {netbox_plugin_dns-1.3.3.dist-info → netbox_plugin_dns-1.3.5.dist-info}/licenses/LICENSE +0 -0
- {netbox_plugin_dns-1.3.3.dist-info → netbox_plugin_dns-1.3.5.dist-info}/top_level.txt +0 -0
netbox_dns/__init__.py
CHANGED
|
@@ -1,176 +1,205 @@
|
|
|
1
|
-
from netaddr import IPAddress
|
|
1
|
+
from netaddr import IPAddress
|
|
2
2
|
|
|
3
3
|
from django.core.management.base import BaseCommand
|
|
4
4
|
|
|
5
5
|
from netbox_dns.models import Zone, Record
|
|
6
|
-
from netbox_dns.choices import
|
|
6
|
+
from netbox_dns.choices import RecordTypeChoices
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if passive_zones:
|
|
12
|
-
if verbose:
|
|
13
|
-
print("Renaming 'passive' zone status to 'parked'")
|
|
14
|
-
|
|
15
|
-
for zone in passive_zones:
|
|
16
|
-
zone.status = ZoneStatusChoices.STATUS_PARKED
|
|
17
|
-
zone.save()
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def zone_cleanup_ns_records(verbose=False):
|
|
21
|
-
ns_name = "@"
|
|
22
|
-
|
|
23
|
-
for zone in Zone.objects.all():
|
|
24
|
-
nameservers = zone.nameservers.all()
|
|
25
|
-
nameserver_names = [f'{ns.name.rstrip(".")}.' for ns in nameservers]
|
|
26
|
-
|
|
27
|
-
delete_ns = zone.records.filter(
|
|
28
|
-
name=ns_name, type=RecordTypeChoices.NS
|
|
29
|
-
).exclude(value__in=nameserver_names)
|
|
30
|
-
for record in delete_ns:
|
|
31
|
-
if verbose:
|
|
32
|
-
print(f"Deleting obsolete NS record {record}")
|
|
33
|
-
record.delete()
|
|
34
|
-
|
|
35
|
-
for ns in nameserver_names:
|
|
36
|
-
ns_records = zone.records.filter(
|
|
37
|
-
name=ns_name,
|
|
38
|
-
type=RecordTypeChoices.NS,
|
|
39
|
-
value=ns,
|
|
40
|
-
)
|
|
9
|
+
class Command(BaseCommand):
|
|
10
|
+
help = "Clean up NetBox DNS database"
|
|
41
11
|
|
|
42
|
-
|
|
12
|
+
def handle(self, *model_names, **options):
|
|
13
|
+
self._zone_cleanup_ns_records(**options)
|
|
14
|
+
self._zone_cleanup_soa_records(**options)
|
|
15
|
+
self._zone_update_arpa_network(**options)
|
|
16
|
+
self._record_cleanup_disable_ptr(**options)
|
|
17
|
+
self._record_update_ptr_records(**options)
|
|
18
|
+
self._record_update_ip_address(**options)
|
|
19
|
+
self._record_remove_orphaned_ptr_records(**options)
|
|
20
|
+
self._record_remove_orphaned_address_records(**options)
|
|
21
|
+
|
|
22
|
+
if options.get("verbosity"):
|
|
23
|
+
self.stdout.write("Database cleanup completed.")
|
|
24
|
+
|
|
25
|
+
def _zone_cleanup_ns_records(self, **options):
|
|
26
|
+
if options.get("verbosity"):
|
|
27
|
+
self.stdout.write("Cleaning up the NS records for all zones")
|
|
28
|
+
|
|
29
|
+
ns_name = "@"
|
|
30
|
+
|
|
31
|
+
for zone in Zone.objects.all():
|
|
32
|
+
nameservers = zone.nameservers.all()
|
|
33
|
+
nameserver_names = [f'{ns.name.rstrip(".")}.' for ns in nameservers]
|
|
34
|
+
|
|
35
|
+
delete_ns = zone.records.filter(
|
|
36
|
+
name=ns_name, type=RecordTypeChoices.NS
|
|
37
|
+
).exclude(value__in=nameserver_names)
|
|
43
38
|
for record in delete_ns:
|
|
44
|
-
if
|
|
45
|
-
|
|
39
|
+
if options.get("verbosity") > 1:
|
|
40
|
+
self.stdout.write(
|
|
41
|
+
f"Removing obsolete NS record '{record}' with value '{record.value}'"
|
|
42
|
+
)
|
|
46
43
|
record.delete()
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
for ns in nameserver_names:
|
|
46
|
+
ns_records = zone.records.filter(
|
|
50
47
|
name=ns_name,
|
|
51
48
|
type=RecordTypeChoices.NS,
|
|
52
49
|
value=ns,
|
|
53
50
|
)
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
value=ns,
|
|
70
|
-
ttl=None,
|
|
71
|
-
managed=True,
|
|
72
|
-
)
|
|
52
|
+
delete_ns = ns_records[1:]
|
|
53
|
+
for record in delete_ns:
|
|
54
|
+
if options.get("verbosity") > 1:
|
|
55
|
+
self.stdout.write(
|
|
56
|
+
f"Removing duplicate NS record '{record}' with value '{record.value}'"
|
|
57
|
+
)
|
|
58
|
+
record.delete()
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
ns_record = zone.records.get(
|
|
62
|
+
name=ns_name,
|
|
63
|
+
type=RecordTypeChoices.NS,
|
|
64
|
+
value=ns,
|
|
65
|
+
)
|
|
73
66
|
|
|
67
|
+
if ns_record.ttl is not None or not ns_record.managed:
|
|
68
|
+
if options.get("verbosity") > 1:
|
|
69
|
+
self.stdout.write(
|
|
70
|
+
f"Updating NS record '{ns_record}' with value '{record.value}'"
|
|
71
|
+
)
|
|
72
|
+
ns_record.ttl = None
|
|
73
|
+
ns_record.managed = True
|
|
74
|
+
ns_record.save()
|
|
75
|
+
|
|
76
|
+
except Record.DoesNotExist:
|
|
77
|
+
if options.get("verbosity") > 1:
|
|
78
|
+
self.stdout.write(
|
|
79
|
+
f"Creating NS record for '{ns.rstrip('.')}' in zone '{zone}'"
|
|
80
|
+
)
|
|
81
|
+
Record.objects.create(
|
|
82
|
+
name=ns_name,
|
|
83
|
+
zone=zone,
|
|
84
|
+
type=RecordTypeChoices.NS,
|
|
85
|
+
value=ns,
|
|
86
|
+
ttl=None,
|
|
87
|
+
managed=True,
|
|
88
|
+
)
|
|
74
89
|
|
|
75
|
-
def
|
|
76
|
-
|
|
90
|
+
def _zone_cleanup_soa_records(self, **options):
|
|
91
|
+
if options.get("verbosity"):
|
|
92
|
+
self.stdout.write("Cleaning up the SOA record for all zones")
|
|
77
93
|
|
|
78
|
-
|
|
79
|
-
delete_soa = zone.records.filter(name=soa_name, type=RecordTypeChoices.SOA)[1:]
|
|
80
|
-
for record in delete_soa:
|
|
81
|
-
if verbose:
|
|
82
|
-
print(f"Deleting duplicate SOA record {record}")
|
|
83
|
-
record.delete()
|
|
94
|
+
soa_name = "@"
|
|
84
95
|
|
|
85
|
-
zone.
|
|
96
|
+
for zone in Zone.objects.all():
|
|
97
|
+
delete_soa = zone.records.filter(name=soa_name, type=RecordTypeChoices.SOA)[
|
|
98
|
+
1:
|
|
99
|
+
]
|
|
100
|
+
for record in delete_soa:
|
|
101
|
+
if options.get("verbosity") > 1:
|
|
102
|
+
self.stdout.write(
|
|
103
|
+
f"Deleting duplicate SOA record '{record}' for zone '{zone}'"
|
|
104
|
+
)
|
|
105
|
+
record.delete()
|
|
86
106
|
|
|
107
|
+
zone.update_soa_record()
|
|
87
108
|
|
|
88
|
-
def
|
|
89
|
-
|
|
90
|
-
|
|
109
|
+
def _zone_update_arpa_network(self, **options):
|
|
110
|
+
if options.get("verbosity"):
|
|
111
|
+
self.stdout.write("Updating the ARPA network for reverse zones")
|
|
91
112
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
113
|
+
for zone in Zone.objects.filter(name__endswith=".arpa"):
|
|
114
|
+
if zone.arpa_network != (arpa_network := zone.network_from_name):
|
|
115
|
+
if options.get("verbosity") > 1:
|
|
116
|
+
self.stdout.write(
|
|
117
|
+
f"Setting the ARPA network for zone '{zone}' to '{arpa_network}'"
|
|
118
|
+
)
|
|
96
119
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
except AddrFormatError:
|
|
100
|
-
prefix = None
|
|
120
|
+
zone.arpa_network = arpa_network
|
|
121
|
+
zone.save()
|
|
101
122
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
address = address + "0" * (32 - mask)
|
|
123
|
+
def _record_cleanup_disable_ptr(self, **options):
|
|
124
|
+
if options.get("verbosity"):
|
|
125
|
+
self.stdout.write("Updating 'Disable PTR' for non-address records")
|
|
106
126
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
records = Record.objects.filter(
|
|
128
|
+
disable_ptr=True,
|
|
129
|
+
).exclude(type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA))
|
|
130
|
+
|
|
131
|
+
for record in records:
|
|
132
|
+
if options.get("verbosity") > 1:
|
|
133
|
+
self.stdout.write(
|
|
134
|
+
f"Setting 'Disable PTR' to False for record '{record}'"
|
|
110
135
|
)
|
|
111
|
-
except AddrFormatError:
|
|
112
|
-
prefix = None
|
|
113
|
-
# TODO: End
|
|
114
|
-
|
|
115
|
-
if zone.arpa_network != prefix:
|
|
116
|
-
if verbose:
|
|
117
|
-
print(f"Updating ARPA prefix for zone '{zone}' to '{prefix}'")
|
|
118
|
-
zone.arpa_network = prefix
|
|
119
|
-
zone.save()
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def record_cleanup_disable_ptr(verbose=False):
|
|
123
|
-
Record.objects.filter(
|
|
124
|
-
disable_ptr=False,
|
|
125
|
-
).exclude(
|
|
126
|
-
type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
|
|
127
|
-
).update(disable_ptr=True)
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def record_update_ptr_records(verbose=False):
|
|
131
|
-
for record in Record.objects.filter(
|
|
132
|
-
type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
|
|
133
|
-
):
|
|
134
|
-
record.save(update_fields=["ptr_record"])
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
def record_update_ip_address(verbose=False):
|
|
138
|
-
for record in Record.objects.filter(
|
|
139
|
-
type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA, RecordTypeChoices.PTR)
|
|
140
|
-
):
|
|
141
|
-
if record.is_ptr_record:
|
|
142
|
-
if record.ip_address != record.address_from_name:
|
|
143
|
-
if verbose:
|
|
144
|
-
print(
|
|
145
|
-
f"Updating IP address of pointer record {record} to {record.address_from_name}"
|
|
146
|
-
)
|
|
147
|
-
record.ip_address = record.address_from_name
|
|
148
|
-
record.save()
|
|
149
|
-
else:
|
|
150
|
-
if record.ip_address != IPAddress(record.value):
|
|
151
|
-
if verbose:
|
|
152
|
-
print(
|
|
153
|
-
f"Updating IP address of address record {record} to {IPAddress(record.value)}"
|
|
154
|
-
)
|
|
155
|
-
record.ip_address = record.value
|
|
156
|
-
record.save()
|
|
157
136
|
|
|
137
|
+
record.disable_ptr = False
|
|
138
|
+
record.save(update_fields=["disable_ptr"])
|
|
158
139
|
|
|
159
|
-
|
|
160
|
-
|
|
140
|
+
def _record_update_ptr_records(self, **options):
|
|
141
|
+
if options.get("verbosity"):
|
|
142
|
+
self.stdout.write("Updating the PTR record for all address records")
|
|
143
|
+
|
|
144
|
+
for record in Record.objects.filter(
|
|
145
|
+
type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
|
|
146
|
+
):
|
|
147
|
+
record.save(update_fields=["ptr_record"])
|
|
161
148
|
|
|
162
|
-
def
|
|
163
|
-
|
|
164
|
-
"
|
|
149
|
+
def _record_update_ip_address(self, **options):
|
|
150
|
+
if options.get("verbosity"):
|
|
151
|
+
self.stdout.write("Updating the IP address for all address and PTR records")
|
|
152
|
+
|
|
153
|
+
for record in Record.objects.filter(
|
|
154
|
+
type__in=(
|
|
155
|
+
RecordTypeChoices.A,
|
|
156
|
+
RecordTypeChoices.AAAA,
|
|
157
|
+
RecordTypeChoices.PTR,
|
|
158
|
+
)
|
|
159
|
+
):
|
|
160
|
+
if record.is_ptr_record:
|
|
161
|
+
if record.ip_address != record.address_from_name:
|
|
162
|
+
if options.get("verbosity") > 1:
|
|
163
|
+
self.stdout.write(
|
|
164
|
+
f"Setting the IP Address for pointer record '{record}' to '{record.address_from_name}'"
|
|
165
|
+
)
|
|
166
|
+
record.ip_address = record.address_from_name
|
|
167
|
+
record.save()
|
|
168
|
+
else:
|
|
169
|
+
if record.ip_address != IPAddress(record.value):
|
|
170
|
+
if options.get("verbosity") > 1:
|
|
171
|
+
self.stdout.write(
|
|
172
|
+
f"Updating the IP address for address record '{record}' to '{IPAddress(record.value)}'"
|
|
173
|
+
)
|
|
174
|
+
record.ip_address = record.value
|
|
175
|
+
record.save()
|
|
176
|
+
|
|
177
|
+
def _record_remove_orphaned_ptr_records(self, **options):
|
|
178
|
+
if options.get("verbosity"):
|
|
179
|
+
self.stdout.write("Removing orphaned managed PTR records")
|
|
180
|
+
|
|
181
|
+
orphaned_ptr_records = Record.objects.filter(
|
|
182
|
+
type=RecordTypeChoices.PTR,
|
|
183
|
+
managed=True,
|
|
184
|
+
address_records__isnull=True,
|
|
165
185
|
)
|
|
166
186
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
187
|
+
for record in orphaned_ptr_records:
|
|
188
|
+
if options.get("verbosity") > 1:
|
|
189
|
+
self.stdout.write("Removing orphaned PTR record '{record}'")
|
|
190
|
+
record.delete()
|
|
191
|
+
|
|
192
|
+
def _record_remove_orphaned_address_records(self, **options):
|
|
193
|
+
if options.get("verbosity"):
|
|
194
|
+
self.stdout.write("Removing orphaned managed address records")
|
|
195
|
+
|
|
196
|
+
orphaned_address_records = Record.objects.filter(
|
|
197
|
+
type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
|
|
198
|
+
managed=True,
|
|
199
|
+
ipam_ip_address__isnull=True,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
for record in orphaned_address_records:
|
|
203
|
+
if options.get("verbosity") > 1:
|
|
204
|
+
self.stdout.write("Removing orphaned address record '{record}'")
|
|
205
|
+
record.delete()
|
|
@@ -22,11 +22,12 @@ class Command(BaseCommand):
|
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
def handle(self, *model_names, **options):
|
|
25
|
-
self.
|
|
25
|
+
self._cleanup_rrset_ttl(**options)
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
def _cleanup_rrset_ttl(self, **options):
|
|
28
|
+
if options.get("verbosity"):
|
|
29
|
+
self.stdout.write("Cleaning up diverging RRset TTL values")
|
|
28
30
|
|
|
29
|
-
def cleanup_rrset_ttl(self, **options):
|
|
30
31
|
ttl_records = (
|
|
31
32
|
Record.objects.filter(ttl__isnull=False)
|
|
32
33
|
.exclude(type=RecordTypeChoices.SOA)
|
|
@@ -37,11 +38,13 @@ class Command(BaseCommand):
|
|
|
37
38
|
name=record.name,
|
|
38
39
|
zone=record.zone,
|
|
39
40
|
type=record.type,
|
|
40
|
-
).exclude(type=RecordTypeChoices.PTR,
|
|
41
|
+
).exclude(type=RecordTypeChoices.PTR, managed=True)
|
|
41
42
|
|
|
42
43
|
if records.count() == 1:
|
|
43
44
|
if options.get("verbosity") > 2:
|
|
44
|
-
self.stdout.write(
|
|
45
|
+
self.stdout.write(
|
|
46
|
+
f"Ignoring single record '{record.pk}' ('{record}')"
|
|
47
|
+
)
|
|
45
48
|
continue
|
|
46
49
|
|
|
47
50
|
if options.get("max"):
|
|
@@ -52,7 +55,10 @@ class Command(BaseCommand):
|
|
|
52
55
|
for record in records.exclude(ttl=ttl):
|
|
53
56
|
if options.get("verbosity") > 1:
|
|
54
57
|
self.stdout.write(
|
|
55
|
-
f"
|
|
58
|
+
f"Setting TTL for record '{record.pk}' ('{record}') to {ttl}"
|
|
56
59
|
)
|
|
57
60
|
record.ttl = ttl
|
|
58
61
|
record.save(update_fields=["ttl"], update_rrset_ttl=False)
|
|
62
|
+
|
|
63
|
+
if options.get("verbosity"):
|
|
64
|
+
self.stdout.write("RRSet TTL cleanup completed.")
|
|
@@ -12,7 +12,7 @@ class Command(BaseCommand):
|
|
|
12
12
|
parser.add_argument(
|
|
13
13
|
"--force",
|
|
14
14
|
action="store_true",
|
|
15
|
-
help="Update records even if DNS name was not changed (required for rebuilding filtered views",
|
|
15
|
+
help="Update records even if DNS name was not changed (required for rebuilding filtered views)",
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
def handle(self, *model_names, **options):
|
netbox_dns/models/record.py
CHANGED
|
@@ -418,6 +418,26 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
418
418
|
):
|
|
419
419
|
return
|
|
420
420
|
|
|
421
|
+
# +
|
|
422
|
+
# If the existing PTR record no longer matches the address record,
|
|
423
|
+
# check whether there is an existing PTR record that does. In that
|
|
424
|
+
# case, mark the old PTR record for cleanup and use the existing one.
|
|
425
|
+
# -
|
|
426
|
+
try:
|
|
427
|
+
existing_ptr_record = Record.objects.get(
|
|
428
|
+
name=ptr_name,
|
|
429
|
+
zone=ptr_zone,
|
|
430
|
+
type=RecordTypeChoices.PTR,
|
|
431
|
+
value=ptr_value,
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
self.cleanup_ptr_record = self.ptr_record
|
|
435
|
+
self.ptr_record = existing_ptr_record
|
|
436
|
+
ptr_record = self.ptr_record
|
|
437
|
+
|
|
438
|
+
except Record.DoesNotExist:
|
|
439
|
+
pass
|
|
440
|
+
|
|
421
441
|
# +
|
|
422
442
|
# If there is an RFC2317 CNAME for the PTR record and it is either
|
|
423
443
|
# not required or needs to be changed, remove it.
|
|
@@ -435,10 +455,12 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
435
455
|
# modified to match the new name, zone, value and TTL.
|
|
436
456
|
# -
|
|
437
457
|
if ptr_record.address_records.count() == 1:
|
|
458
|
+
ptr_record.snapshot()
|
|
438
459
|
ptr_record.zone = ptr_zone
|
|
439
460
|
ptr_record.name = ptr_name
|
|
440
461
|
ptr_record.value = ptr_value
|
|
441
462
|
ptr_record.ttl = self.ttl
|
|
463
|
+
ptr_record.managed = True
|
|
442
464
|
ptr_record.save(
|
|
443
465
|
update_rfc2317_cname=update_rfc2317_cname,
|
|
444
466
|
save_zone_serial=save_zone_serial,
|
|
@@ -447,7 +469,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
447
469
|
|
|
448
470
|
# +
|
|
449
471
|
# Either there was no PTR record or the existing PTR record could not be re-used,
|
|
450
|
-
# so we need to either
|
|
472
|
+
# so we need to either find a matching PTR record or create a new one.
|
|
451
473
|
# -
|
|
452
474
|
try:
|
|
453
475
|
ptr_record = Record.objects.get(
|
|
@@ -846,6 +868,9 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
846
868
|
if self._state.adding:
|
|
847
869
|
self.check_unique_rrset_ttl()
|
|
848
870
|
|
|
871
|
+
if not self.is_address_record:
|
|
872
|
+
self.disable_ptr = False
|
|
873
|
+
|
|
849
874
|
if not self.is_active:
|
|
850
875
|
return
|
|
851
876
|
|
netbox_dns/models/zone.py
CHANGED
|
@@ -550,7 +550,12 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
550
550
|
try:
|
|
551
551
|
soa_record = self.records.get(type=RecordTypeChoices.SOA, name=soa_name)
|
|
552
552
|
|
|
553
|
-
if
|
|
553
|
+
if (
|
|
554
|
+
soa_record.ttl != soa_ttl
|
|
555
|
+
or soa_record.value != soa_rdata.to_text()
|
|
556
|
+
or not soa_record.managed
|
|
557
|
+
):
|
|
558
|
+
soa_record.snapshot()
|
|
554
559
|
soa_record.ttl = soa_ttl
|
|
555
560
|
soa_record.value = soa_rdata.to_text()
|
|
556
561
|
soa_record.managed = True
|
|
@@ -177,6 +177,8 @@ def update_dns_records(ip_address, view=None, force=False):
|
|
|
177
177
|
address_records = ip_address.netbox_dns_records.filter(zone__view=view)
|
|
178
178
|
|
|
179
179
|
for record in address_records:
|
|
180
|
+
record.snapshot()
|
|
181
|
+
|
|
180
182
|
if record.zone not in zones or ip_address.custom_field_data.get(
|
|
181
183
|
"ipaddress_dns_disabled"
|
|
182
184
|
):
|
|
@@ -227,10 +229,15 @@ def delete_dns_records(ip_address, view=None):
|
|
|
227
229
|
# TODO: Find something better. This is really awful.
|
|
228
230
|
# -
|
|
229
231
|
address_records = Record.objects.filter(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
232
|
+
Q(
|
|
233
|
+
Q(ipam_ip_address=ip_address)
|
|
234
|
+
| Q(
|
|
235
|
+
type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
|
|
236
|
+
managed=True,
|
|
237
|
+
ip_address=ip_address.address,
|
|
238
|
+
ipam_ip_address__isnull=True,
|
|
239
|
+
)
|
|
240
|
+
),
|
|
234
241
|
)
|
|
235
242
|
|
|
236
243
|
if view is not None:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
netbox_dns/__init__.py,sha256
|
|
1
|
+
netbox_dns/__init__.py,sha256=-aNWTjZrScH61wzPGKzqdWwZf8ojcrz1HXDy7OBqi1o,4890
|
|
2
2
|
netbox_dns/apps.py,sha256=JCW5eS-AQBUubDJve1DjP-IRFKTFGQh1NLGWzJpC5MI,151
|
|
3
3
|
netbox_dns/navigation.py,sha256=ZF2-bKRfuxXnLArSCvozyRXRd7GME14sVJZdmDEMhBk,7741
|
|
4
4
|
netbox_dns/template_content.py,sha256=nwjbWkMc02vpTmcFQdiAA1TdopJiZ0MkRy6qa18_wLI,4848
|
|
@@ -74,12 +74,10 @@ netbox_dns/graphql/filters/zone_template.py,sha256=6ZxBN_VPXvBDGXXwcYlkX6wJXx_Il
|
|
|
74
74
|
netbox_dns/locale/de/LC_MESSAGES/django.mo,sha256=fSlYDunygrkHE4TAIlHI0ol67Lz3qiu2hUkeirewlOQ,29995
|
|
75
75
|
netbox_dns/locale/en/LC_MESSAGES/django.mo,sha256=GDnSZkfHs3yjtTsll7dksEEej4B50F8pc9RGytZNubM,393
|
|
76
76
|
netbox_dns/locale/fr/LC_MESSAGES/django.mo,sha256=hZjbClaXZndP8VtqAiXWBdYEFVD9CQrKJXelL6kMOPE,30021
|
|
77
|
-
netbox_dns/management/commands/cleanup_database.py,sha256=
|
|
78
|
-
netbox_dns/management/commands/cleanup_rrset_ttl.py,sha256=
|
|
79
|
-
netbox_dns/management/commands/rebuild_dnssync.py,sha256=
|
|
80
|
-
netbox_dns/management/commands/remove_orphaned_ptr_records.py,sha256=vYYvI2yr4U1EiAoWm26PkULzaz3rr_Yfaw2eg9i4oIw,1142
|
|
77
|
+
netbox_dns/management/commands/cleanup_database.py,sha256=bkMdDlZpSzqIRx18N86wyda2ufFzNlejefyeRdHg5Nk,7951
|
|
78
|
+
netbox_dns/management/commands/cleanup_rrset_ttl.py,sha256=7W4_qRzm_Crnb1L4X8lfrXRJanBqDGLC1yCLvrIaGG4,2256
|
|
79
|
+
netbox_dns/management/commands/rebuild_dnssync.py,sha256=SlY-NsMu4BJ7Bi1lnswfVHjhCzsgL6hRue6pJXSO_0w,1247
|
|
81
80
|
netbox_dns/management/commands/setup_dnssync.py,sha256=qtVj6egSjclaQbuI60hLfl-zg89VJVbX-TB17f1k77Y,5730
|
|
82
|
-
netbox_dns/management/commands/update_soa.py,sha256=Rj_Xk-qpwkAVRubVnM5OqSTwgzi93E0PqjwGb3rYjf0,660
|
|
83
81
|
netbox_dns/migrations/0001_squashed_netbox_dns_0_15.py,sha256=3U0810NWSHPu2dTSHpfzlleDgwMS04FhJ_CkO76SDaw,10283
|
|
84
82
|
netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py,sha256=ML6Hp17lrXiaG0eUlBjKMm6HUNhw0AHPnKrb9AN-F6E,20279
|
|
85
83
|
netbox_dns/migrations/0002_contact_description_registrar_description.py,sha256=ZrI-L3jJ5GzdVx21pomgM4waE-njixHQjl_grjsGr0I,583
|
|
@@ -120,12 +118,12 @@ netbox_dns/models/__init__.py,sha256=CuwFENIVUv0FNMDlY18Am-mvN5kBGkPOGavCP0cle7c
|
|
|
120
118
|
netbox_dns/models/dnssec_key_template.py,sha256=Nv0vjdkOFWMptRYR1sT60bM6D8n_SnCpPZhI7WE5_UQ,2588
|
|
121
119
|
netbox_dns/models/dnssec_policy.py,sha256=REsE8p04bgJVF8yJuWuUITXpsZmvVlXWyQuJ9I6dEMs,5268
|
|
122
120
|
netbox_dns/models/nameserver.py,sha256=oVfyc_iWRzxVE2tIhfRb1Vuj2gZmlfFFzEtXj9ZEr6s,3848
|
|
123
|
-
netbox_dns/models/record.py,sha256=
|
|
121
|
+
netbox_dns/models/record.py,sha256=7f4h3ngUvPpQ4IQroTJAWO8wD2fqy1u8j-LuA23PWtM,32761
|
|
124
122
|
netbox_dns/models/record_template.py,sha256=Qr43_YZm1z3Od1cBdDY9wpNlV-UCzvpn2c6_dDzFzN8,5145
|
|
125
123
|
netbox_dns/models/registrar.py,sha256=-ozazecvd-oryEoDlOUvTWhEQKKQp3my6YVTEzWlUuI,1747
|
|
126
124
|
netbox_dns/models/registration_contact.py,sha256=9ehnTjg8KUrUYJKRRu2SaJX-NE5dO4wy90FRPlT2ys4,3620
|
|
127
125
|
netbox_dns/models/view.py,sha256=pwo7i8gtukIRgAC1A4rm58jcEpIbsSW_IUq6vSv-mRo,4618
|
|
128
|
-
netbox_dns/models/zone.py,sha256=
|
|
126
|
+
netbox_dns/models/zone.py,sha256=qZ5yYNbj4mYm61zfq-aFL_5sVSxJo1PQSMY4cAj8vEQ,35953
|
|
129
127
|
netbox_dns/models/zone_template.py,sha256=ShPg6_ts6W-dpdGzUg3oZnGHEEQ-_Jf0EdYwVWzaPwI,5093
|
|
130
128
|
netbox_dns/signals/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
131
129
|
netbox_dns/signals/dnssec.py,sha256=o4MOEg6ftxoDWFAhDtajkXzb7Nb6KuUHjtx1zNu7C1w,1040
|
|
@@ -171,7 +169,7 @@ netbox_dns/templatetags/netbox_dns.py,sha256=DND1DMPzv636Rak3M6Hor_Vw6pjqUfSTquo
|
|
|
171
169
|
netbox_dns/utilities/__init__.py,sha256=cSGf-nGaRWx9b-Xrh3dLMJYoWNsZ6FF-qdmV4F1uOgg,74
|
|
172
170
|
netbox_dns/utilities/conversions.py,sha256=qYnzecmR28l8Je_H0vFvzJ2sikTiEiyxr6drl_aRocg,3016
|
|
173
171
|
netbox_dns/utilities/dns.py,sha256=UBiyQe8thiOTnKOmU9e2iRHHnGF9toVLe4efU623kX4,322
|
|
174
|
-
netbox_dns/utilities/ipam_dnssync.py,sha256=
|
|
172
|
+
netbox_dns/utilities/ipam_dnssync.py,sha256=qVbJAL2GcTpKZaz4XBfTc4Gn8xREukQy0VvhK6jIpQ8,10493
|
|
175
173
|
netbox_dns/validators/__init__.py,sha256=X0hPZlC3VZcXMcvXKZ2_5LSoEJdXPNSBr4QtEIFSBJ0,94
|
|
176
174
|
netbox_dns/validators/dns_name.py,sha256=1MKnYAmkSTIQGf6zInqkpbIj5SCeCM0YGKmYOqFzUK4,3770
|
|
177
175
|
netbox_dns/validators/dns_value.py,sha256=cADhgTohXAtOLPzaoMKO9DahEUiDanpdiuKonrwFw0E,5278
|
|
@@ -188,8 +186,8 @@ netbox_dns/views/registration_contact.py,sha256=5bJWjNBisqCkBo6d2TJyyBJlc95WM7Vc
|
|
|
188
186
|
netbox_dns/views/view.py,sha256=xLXt7sKrda3FpNXsBSJk8L8P2XhZ1sVb5OOXovCsKEU,3089
|
|
189
187
|
netbox_dns/views/zone.py,sha256=rxf0ETFnBF88JbhxUZWtcid_CAm7tssYfp2EFjk7zyg,7160
|
|
190
188
|
netbox_dns/views/zone_template.py,sha256=5P9DT3XBRL-TiM5zFhBTMlMusL4bP2jTu3GHxKz5ojc,2553
|
|
191
|
-
netbox_plugin_dns-1.3.
|
|
192
|
-
netbox_plugin_dns-1.3.
|
|
193
|
-
netbox_plugin_dns-1.3.
|
|
194
|
-
netbox_plugin_dns-1.3.
|
|
195
|
-
netbox_plugin_dns-1.3.
|
|
189
|
+
netbox_plugin_dns-1.3.5.dist-info/licenses/LICENSE,sha256=I3tDu11bZfhFm3EkV4zOD5TmWgLjnUNLEFwrdjniZYs,1112
|
|
190
|
+
netbox_plugin_dns-1.3.5.dist-info/METADATA,sha256=eG5VsqM5B-Boc4GvUAc8VG7GuUQTXiFkcrMHEz0I1WA,7787
|
|
191
|
+
netbox_plugin_dns-1.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
192
|
+
netbox_plugin_dns-1.3.5.dist-info/top_level.txt,sha256=sA1Rwl1mRKvMC6XHe2ylZ1GF-Q1NGd08XedK9Y4xZc4,11
|
|
193
|
+
netbox_plugin_dns-1.3.5.dist-info/RECORD,,
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
from django.core.management.base import BaseCommand
|
|
2
|
-
|
|
3
|
-
from netbox_dns.models import Record
|
|
4
|
-
from netbox_dns.choices import RecordTypeChoices
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class Command(BaseCommand):
|
|
8
|
-
help = "Remove managed PTR records without an address record"
|
|
9
|
-
|
|
10
|
-
def handle(self, *model_names, **options):
|
|
11
|
-
orphaned_ptr_records = Record.objects.filter(
|
|
12
|
-
type=RecordTypeChoices.PTR,
|
|
13
|
-
address_records__isnull=True,
|
|
14
|
-
managed=True,
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
if not orphaned_ptr_records.exists():
|
|
18
|
-
if options.get("verbosity") >= 1:
|
|
19
|
-
self.stdout.write("No orphaned PTR records found")
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
if options.get("verbosity") >= 1:
|
|
23
|
-
self.stdout.write(
|
|
24
|
-
f"Removing {orphaned_ptr_records.count()} orphaned PTR record(s) ..."
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
for record in orphaned_ptr_records:
|
|
28
|
-
if options.get("verbosity") >= 2:
|
|
29
|
-
self.stdout.write(
|
|
30
|
-
f"removing PTR record {record} from zone {record.zone}"
|
|
31
|
-
)
|
|
32
|
-
record.delete()
|
|
33
|
-
|
|
34
|
-
if options.get("verbosity") >= 1:
|
|
35
|
-
self.stdout.write("... done.")
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from django.core.management.base import BaseCommand
|
|
2
|
-
|
|
3
|
-
from netbox_dns.models import Zone
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Command(BaseCommand):
|
|
7
|
-
help = "Create or update SOA records for all zones"
|
|
8
|
-
|
|
9
|
-
def add_arguments(self, parser):
|
|
10
|
-
parser.add_argument(
|
|
11
|
-
"--verbose", action="store_true", help="Increase output verbosity"
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
def handle(self, *model_names, **options):
|
|
15
|
-
zones = Zone.objects.all()
|
|
16
|
-
|
|
17
|
-
for zone in zones:
|
|
18
|
-
if options["verbose"]:
|
|
19
|
-
self.stdout.write(f"Updating the SOA record for zone {zone.name}")
|
|
20
|
-
zone.update_soa_record()
|
|
21
|
-
|
|
22
|
-
self.stdout.write("All SOA records have been updated")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|