netbox-plugin-dns 1.1.0__py3-none-any.whl → 1.1.0b1__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.

Files changed (84) hide show
  1. netbox_dns/__init__.py +6 -9
  2. netbox_dns/api/nested_serializers.py +16 -17
  3. netbox_dns/api/serializers.py +1 -1
  4. netbox_dns/api/serializers_/{registration_contact.py → contact.py} +5 -5
  5. netbox_dns/api/serializers_/record.py +0 -1
  6. netbox_dns/api/serializers_/zone.py +5 -5
  7. netbox_dns/api/serializers_/zone_template.py +5 -5
  8. netbox_dns/api/urls.py +2 -2
  9. netbox_dns/api/views.py +35 -9
  10. netbox_dns/fields/ipam.py +3 -0
  11. netbox_dns/filtersets/__init__.py +1 -1
  12. netbox_dns/filtersets/{registration_contact.py → contact.py} +4 -4
  13. netbox_dns/filtersets/record.py +1 -1
  14. netbox_dns/filtersets/zone.py +15 -15
  15. netbox_dns/filtersets/zone_template.py +15 -15
  16. netbox_dns/forms/__init__.py +1 -1
  17. netbox_dns/forms/{registration_contact.py → contact.py} +16 -16
  18. netbox_dns/forms/view.py +7 -95
  19. netbox_dns/forms/zone.py +17 -22
  20. netbox_dns/forms/zone_template.py +13 -13
  21. netbox_dns/graphql/__init__.py +2 -2
  22. netbox_dns/graphql/filters.py +5 -5
  23. netbox_dns/graphql/schema.py +44 -24
  24. netbox_dns/graphql/types.py +12 -40
  25. netbox_dns/management/commands/{setup_dnssync.py → setup_autodns.py} +28 -48
  26. netbox_dns/migrations/{0008_view_prefixes.py → 0007_view_prefixes.py} +1 -1
  27. netbox_dns/models/__init__.py +1 -1
  28. netbox_dns/models/{registration_contact.py → contact.py} +9 -15
  29. netbox_dns/models/nameserver.py +3 -8
  30. netbox_dns/models/record.py +28 -93
  31. netbox_dns/models/record_template.py +1 -4
  32. netbox_dns/models/registrar.py +1 -7
  33. netbox_dns/models/view.py +2 -9
  34. netbox_dns/models/zone.py +22 -59
  35. netbox_dns/models/zone_template.py +9 -12
  36. netbox_dns/navigation.py +7 -7
  37. netbox_dns/signals/ipam_autodns.py +138 -0
  38. netbox_dns/tables/__init__.py +1 -1
  39. netbox_dns/tables/{registration_contact.py → contact.py} +6 -5
  40. netbox_dns/tables/nameserver.py +7 -1
  41. netbox_dns/tables/record.py +30 -43
  42. netbox_dns/tables/record_template.py +17 -0
  43. netbox_dns/tables/registrar.py +2 -0
  44. netbox_dns/tables/view.py +8 -1
  45. netbox_dns/tables/zone.py +15 -0
  46. netbox_dns/tables/zone_template.py +16 -2
  47. netbox_dns/template_content.py +2 -14
  48. netbox_dns/templates/netbox_dns/{registrationcontact.html → contact.html} +1 -1
  49. netbox_dns/templates/netbox_dns/view.html +7 -3
  50. netbox_dns/urls/__init__.py +2 -2
  51. netbox_dns/urls/contact.py +51 -0
  52. netbox_dns/urls/nameserver.py +38 -14
  53. netbox_dns/urls/record.py +19 -7
  54. netbox_dns/urls/record_template.py +27 -18
  55. netbox_dns/urls/registrar.py +35 -11
  56. netbox_dns/urls/view.py +20 -12
  57. netbox_dns/urls/zone.py +46 -8
  58. netbox_dns/urls/zone_template.py +26 -16
  59. netbox_dns/utilities/__init__.py +1 -1
  60. netbox_dns/utilities/{ipam_dnssync.py → ipam_autodns.py} +32 -122
  61. netbox_dns/validators/dns_name.py +0 -9
  62. netbox_dns/views/__init__.py +1 -1
  63. netbox_dns/views/contact.py +95 -0
  64. netbox_dns/views/nameserver.py +3 -7
  65. netbox_dns/views/record.py +7 -12
  66. netbox_dns/views/record_template.py +1 -1
  67. netbox_dns/views/registrar.py +1 -0
  68. netbox_dns/views/view.py +2 -32
  69. netbox_dns/views/zone.py +6 -7
  70. netbox_dns/views/zone_template.py +2 -2
  71. {netbox_plugin_dns-1.1.0.dist-info → netbox_plugin_dns-1.1.0b1.dist-info}/METADATA +2 -3
  72. netbox_plugin_dns-1.1.0b1.dist-info/RECORD +140 -0
  73. netbox_dns/management/commands/rebuild_dnssync.py +0 -18
  74. netbox_dns/migrations/0007_alter_ordering_options.py +0 -25
  75. netbox_dns/migrations/0009_rename_contact_registrationcontact.py +0 -27
  76. netbox_dns/signals/ipam_dnssync.py +0 -224
  77. netbox_dns/tables/ipam_dnssync.py +0 -11
  78. netbox_dns/templates/netbox_dns/view/button.html +0 -9
  79. netbox_dns/templates/netbox_dns/view/prefix.html +0 -41
  80. netbox_dns/urls/registration_contact.py +0 -60
  81. netbox_dns/views/registration_contact.py +0 -94
  82. netbox_plugin_dns-1.1.0.dist-info/RECORD +0 -146
  83. {netbox_plugin_dns-1.1.0.dist-info → netbox_plugin_dns-1.1.0b1.dist-info}/LICENSE +0 -0
  84. {netbox_plugin_dns-1.1.0.dist-info → netbox_plugin_dns-1.1.0b1.dist-info}/WHEEL +0 -0
netbox_dns/models/zone.py CHANGED
@@ -3,8 +3,9 @@ from math import ceil
3
3
  from datetime import datetime
4
4
 
5
5
  from dns import name as dns_name
6
- from dns.exception import DNSException
7
6
  from dns.rdtypes.ANY import SOA
7
+ from dns.exception import DNSException
8
+
8
9
  from django.core.validators import (
9
10
  MinValueValidator,
10
11
  MaxValueValidator,
@@ -18,7 +19,6 @@ from django.dispatch import receiver
18
19
  from django.conf import settings
19
20
 
20
21
  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
@@ -28,7 +28,6 @@ from netbox_dns.choices import RecordClassChoices, RecordTypeChoices, ZoneStatus
28
28
  from netbox_dns.fields import NetworkField, RFC2317NetworkField
29
29
  from netbox_dns.utilities import (
30
30
  update_dns_records,
31
- check_dns_records,
32
31
  get_ip_addresses_by_zone,
33
32
  arpa_to_prefix,
34
33
  name_to_unicode,
@@ -36,7 +35,7 @@ from netbox_dns.utilities import (
36
35
  NameFormatError,
37
36
  )
38
37
  from netbox_dns.validators import (
39
- validate_rname,
38
+ validate_fqdn,
40
39
  validate_domain_name,
41
40
  )
42
41
  from netbox_dns.mixins import ObjectModificationMixin
@@ -69,7 +68,7 @@ class ZoneManager(models.Manager.from_queryset(RestrictedQuerySet)):
69
68
  )
70
69
 
71
70
 
72
- class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
71
+ class Zone(ObjectModificationMixin, NetBoxModel):
73
72
  ACTIVE_STATUS_LIST = (ZoneStatusChoices.STATUS_ACTIVE,)
74
73
 
75
74
  def __init__(self, *args, **kwargs):
@@ -78,7 +77,6 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
78
77
  super().__init__(*args, **kwargs)
79
78
 
80
79
  self._soa_serial_dirty = False
81
- self._ip_addresses_checked = False
82
80
 
83
81
  view = models.ForeignKey(
84
82
  to="View",
@@ -192,7 +190,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
192
190
  null=True,
193
191
  )
194
192
  registrant = models.ForeignKey(
195
- to="RegistrationContact",
193
+ to="Contact",
196
194
  on_delete=models.SET_NULL,
197
195
  verbose_name="Registrant",
198
196
  help_text="The owner of the domain",
@@ -200,7 +198,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
200
198
  null=True,
201
199
  )
202
200
  admin_c = models.ForeignKey(
203
- to="RegistrationContact",
201
+ to="Contact",
204
202
  on_delete=models.SET_NULL,
205
203
  verbose_name="Admin Contact",
206
204
  related_name="admin_c_zones",
@@ -209,16 +207,16 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
209
207
  null=True,
210
208
  )
211
209
  tech_c = models.ForeignKey(
212
- to="RegistrationContact",
210
+ to="Contact",
213
211
  on_delete=models.SET_NULL,
214
- verbose_name="Technical Contact",
212
+ verbose_name="Tech Contact",
215
213
  related_name="tech_c_zones",
216
214
  help_text="The technical contact for the domain",
217
215
  blank=True,
218
216
  null=True,
219
217
  )
220
218
  billing_c = models.ForeignKey(
221
- to="RegistrationContact",
219
+ to="Contact",
222
220
  on_delete=models.SET_NULL,
223
221
  verbose_name="Billing Contact",
224
222
  related_name="billing_c_zones",
@@ -249,7 +247,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
249
247
 
250
248
  objects = ZoneManager()
251
249
 
252
- clone_fields = (
250
+ clone_fields = [
253
251
  "view",
254
252
  "name",
255
253
  "status",
@@ -263,12 +261,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
263
261
  "soa_expire",
264
262
  "soa_minimum",
265
263
  "description",
266
- )
264
+ ]
267
265
 
268
266
  class Meta:
269
- verbose_name = "Zone"
270
- verbose_name_plural = "Zones"
271
-
272
267
  ordering = (
273
268
  "view",
274
269
  "name",
@@ -284,7 +279,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
284
279
  else:
285
280
  try:
286
281
  name = dns_name.from_text(self.name, origin=None).to_unicode()
287
- except DNSException:
282
+ except dns_name.IDNAException:
288
283
  name = self.name
289
284
 
290
285
  try:
@@ -312,14 +307,6 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
312
307
  def soa_serial_dirty(self, soa_serial_dirty):
313
308
  self._soa_serial_dirty = soa_serial_dirty
314
309
 
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
-
323
310
  @property
324
311
  def display_name(self):
325
312
  return name_to_unicode(self.name)
@@ -633,7 +620,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
633
620
  raise ValidationError("soa_rname not set and no default value defined")
634
621
  try:
635
622
  dns_name.from_text(self.soa_rname, origin=dns_name.root)
636
- validate_rname(self.soa_rname)
623
+ validate_fqdn(self.soa_rname)
637
624
  except (DNSException, ValidationError) as exc:
638
625
  raise ValidationError(
639
626
  {
@@ -653,7 +640,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
653
640
  old_zone = Zone.objects.get(pk=self.pk)
654
641
  if not self.soa_serial_auto:
655
642
  self.check_soa_serial_increment(old_zone.soa_serial, self.soa_serial)
656
- elif not old_zone.soa_serial_auto:
643
+ else:
657
644
  try:
658
645
  self.check_soa_serial_increment(
659
646
  old_zone.soa_serial, self.get_auto_serial()
@@ -665,26 +652,6 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
665
652
  }
666
653
  )
667
654
 
668
- if (
669
- not self.ip_addresses_checked
670
- and old_zone.name != self.name
671
- or old_zone.view != self.view
672
- ):
673
- ip_addresses = IPAddress.objects.filter(
674
- netbox_dns_records__in=self.record_set.filter(
675
- ipam_ip_address__isnull=False
676
- )
677
- )
678
- ip_addresses |= get_ip_addresses_by_zone(self)
679
-
680
- for ip_address in ip_addresses.distinct():
681
- try:
682
- check_dns_records(ip_address, zone=self)
683
- except ValidationError as exc:
684
- raise ValidationError(exc.messages)
685
-
686
- self.ip_addresses_checked = True
687
-
688
655
  if self.is_reverse_zone:
689
656
  self.arpa_network = self.network_from_name
690
657
 
@@ -799,13 +766,12 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
799
766
 
800
767
  elif changed_fields is not None and {"name", "view", "status"} & changed_fields:
801
768
  for address_record in self.record_set.filter(
802
- type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
803
- ipam_ip_address__isnull=True,
769
+ type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
804
770
  ):
805
771
  address_record.save(update_fields=["ptr_record"])
806
772
 
807
773
  if changed_fields is not None and "name" in changed_fields:
808
- for _record in self.record_set.filter(ipam_ip_address__isnull=True):
774
+ for _record in self.record_set.all():
809
775
  _record.save(
810
776
  update_fields=["fqdn"],
811
777
  save_zone_serial=False,
@@ -814,14 +780,13 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
814
780
  )
815
781
 
816
782
  if changed_fields is None or {"name", "view"} & changed_fields:
817
- ip_addresses = IPAddress.objects.filter(
818
- netbox_dns_records__in=self.record_set.filter(
783
+ update_ip_addresses = IPAddress.objects.filter(
784
+ pk__in=self.record_set.filter(
819
785
  ipam_ip_address__isnull=False
820
- )
786
+ ).values_list("ipam_ip_address", flat=True)
821
787
  )
822
- ip_addresses |= get_ip_addresses_by_zone(self)
823
-
824
- for ip_address in ip_addresses.distinct():
788
+ update_ip_addresses |= get_ip_addresses_by_zone(self)
789
+ for ip_address in update_ip_addresses:
825
790
  update_dns_records(ip_address)
826
791
 
827
792
  self.save_soa_serial()
@@ -864,9 +829,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
864
829
  netbox_dns_records__in=self.record_set.filter(
865
830
  ipam_ip_address__isnull=False
866
831
  )
867
- )
868
- .distinct()
869
- .values_list("pk", flat=True)
832
+ ).values_list("pk", flat=True)
870
833
  )
871
834
 
872
835
  super().delete(*args, **kwargs)
@@ -47,7 +47,7 @@ class ZoneTemplate(NetBoxModel):
47
47
  null=True,
48
48
  )
49
49
  registrant = models.ForeignKey(
50
- to="RegistrationContact",
50
+ to="Contact",
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="RegistrationContact",
58
+ to="Contact",
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="RegistrationContact",
67
+ to="Contact",
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="RegistrationContact",
76
+ to="Contact",
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,22 +92,19 @@ 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
- verbose_name = "Zone Template"
108
- verbose_name_plural = "Zone Templates"
109
-
110
- ordering = ("name",)
107
+ ordering = ["name"]
111
108
 
112
109
  def __str__(self):
113
110
  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:registrationcontact_list",
155
- link_text="Registration Contacts",
156
- permissions=["netbox_dns.view_registrationcontact"],
154
+ link="plugins:netbox_dns:contact_list",
155
+ link_text="Contacts",
156
+ permissions=["netbox_dns.view_contact"],
157
157
  buttons=(
158
158
  PluginMenuButton(
159
- "plugins:netbox_dns:registrationcontact_add",
159
+ "plugins:netbox_dns:contact_add",
160
160
  "Add",
161
161
  "mdi mdi-plus-thick",
162
- permissions=["netbox_dns.add_registrationcontact"],
162
+ permissions=["netbox_dns.add_contact"],
163
163
  ),
164
164
  PluginMenuButton(
165
- "plugins:netbox_dns:registrationcontact_import",
165
+ "plugins:netbox_dns:contact_import",
166
166
  "Import",
167
167
  "mdi mdi-upload",
168
- permissions=["netbox_dns.add_registrationcontact"],
168
+ permissions=["netbox_dns.add_contact"],
169
169
  ),
170
170
  ),
171
171
  )
@@ -0,0 +1,138 @@
1
+ from netaddr import IPNetwork
2
+
3
+ from django.dispatch import receiver
4
+ from django.db.models.signals import pre_delete, pre_save, post_save, m2m_changed
5
+ from django.core.exceptions import ValidationError
6
+
7
+ from netbox.context import current_request
8
+ from netbox.signals import post_clean
9
+ from ipam.models import IPAddress, Prefix
10
+ from utilities.exceptions import AbortRequest
11
+
12
+ from netbox_dns.models import view as _view
13
+ from netbox_dns.utilities import (
14
+ update_dns_records,
15
+ delete_dns_records,
16
+ get_views_by_prefix,
17
+ get_ip_addresses_by_prefix,
18
+ get_ip_addresses_by_view,
19
+ )
20
+
21
+
22
+ @receiver(post_clean, sender=IPAddress)
23
+ def ipam_autodns_ipaddress_post_clean(instance, **kwargs):
24
+ if not isinstance(instance.address, IPNetwork):
25
+ return
26
+
27
+ try:
28
+ update_dns_records(instance, commit=False)
29
+ except ValidationError as exc:
30
+ if hasattr(exc, "error_dict"):
31
+ for field in ("name", "ttl", "value", "type"):
32
+ value = exc.error_dict.pop(field, None)
33
+ if value is not None:
34
+ raise ValidationError({"dns_name": value})
35
+
36
+ raise exc
37
+
38
+
39
+ @receiver(pre_delete, sender=IPAddress)
40
+ def ipam_autodns_ipaddress_pre_delete(instance, **kwargs):
41
+ delete_dns_records(instance)
42
+
43
+
44
+ @receiver(pre_save, sender=IPAddress)
45
+ def ipam_autodns_ipaddress_post_save(instance, **kwargs):
46
+ update_dns_records(instance, commit=False)
47
+
48
+
49
+ @receiver(post_save, sender=IPAddress)
50
+ def ipam_autodns_ipaddress_post_save(instance, **kwargs):
51
+ update_dns_records(instance)
52
+
53
+
54
+ @receiver(pre_save, sender=Prefix)
55
+ def ipam_autodns_prefix_pre_save(instance, **kwargs):
56
+ """
57
+ Changes that modify the prefix hierarchy cannot be validated properly before
58
+ commiting them. So the solution in this case is to remove a prefix whose
59
+ VRF or network has changed from all views it currently is assigned to.
60
+ """
61
+ if instance.pk is None or not instance.netbox_dns_views.exists():
62
+ return
63
+
64
+ saved_prefix = Prefix.objects.get(pk=instance.pk)
65
+ if saved_prefix.prefix != instance.prefix or saved_prefix.vrf != instance.vrf:
66
+ for view in saved_prefix.netbox_dns_views.all():
67
+ view.prefixes.remove(saved_prefix)
68
+
69
+
70
+ @receiver(pre_delete, sender=Prefix)
71
+ def ipam_autodns_prefix_pre_delete(instance, **kwargs):
72
+ parent = instance.get_parents().last()
73
+ request = current_request.get()
74
+
75
+ if parent is not None and get_views_by_prefix(instance) != get_views_by_prefix(
76
+ parent
77
+ ):
78
+ try:
79
+ for prefix in instance.get_children().filter(
80
+ _depth=instance.depth + 1, netbox_dns_views__isnull=True
81
+ ):
82
+ for ip_address in get_ip_addresses_by_prefix(prefix):
83
+ update_dns_records(ip_address, commit=False)
84
+ except ValidationError as exc:
85
+ if request is not None:
86
+ raise AbortRequest(
87
+ f"Prefix deletion would cause DNS errors: {exc.messages[0]} "
88
+ "Please review DNS View assignments for this and the parent prefix"
89
+ )
90
+ else:
91
+ raise exc
92
+
93
+ # +
94
+ # CAUTION: This only works because the NetBox workaround for an ancient
95
+ # Django bug (see https://code.djangoproject.com/ticket/17688) has already
96
+ # removed the relations between the prefix and the views when this signal
97
+ # handler runs.
98
+ #
99
+ # Should anything be fixed, this code will stop working and need to be
100
+ # revisited.
101
+ #
102
+ # The NetBox workaround only works for requests, not for model level
103
+ # operations. The following code replicates it for non-requests.
104
+ # -
105
+ if request is None:
106
+ for view in instance.netbox_dns_views.all():
107
+ view.snapshot()
108
+ view.prefixes.remove(instance)
109
+
110
+ for ip_address in get_ip_addresses_by_prefix(instance):
111
+ update_dns_records(ip_address)
112
+
113
+
114
+ @receiver(m2m_changed, sender=_view.View.prefixes.through)
115
+ def ipam_autodns_view_prefix_changed(**kwargs):
116
+ action = kwargs.get("action")
117
+ request = current_request.get()
118
+
119
+ # +
120
+ # Handle all post_add and post_remove signals except the ones directly
121
+ # handled by the pre_delete handler for the Prefix model.
122
+ #
123
+ # Yes. This IS ugly.
124
+ # -
125
+ if action not in ("post_add", "post_remove") or (
126
+ request is not None
127
+ and action == "post_remove"
128
+ and (
129
+ request.path.startswith("/ipam/prefixes/")
130
+ or request.path.startswith("/api/ipam/prefixes/")
131
+ )
132
+ ):
133
+ return
134
+
135
+ check_view = action != "post_remove"
136
+ for prefix in Prefix.objects.filter(pk__in=kwargs.get("pk_set")):
137
+ for ip_address in get_ip_addresses_by_prefix(prefix, check_view=check_view):
138
+ update_dns_records(ip_address)
@@ -2,7 +2,7 @@ from .view import *
2
2
  from .zone import *
3
3
  from .nameserver import *
4
4
  from .record import *
5
- from .registration_contact import *
5
+ from .contact import *
6
6
  from .registrar import *
7
7
  from .zone_template import *
8
8
  from .record_template import *
@@ -2,23 +2,24 @@ import django_tables2 as tables
2
2
 
3
3
  from netbox.tables import NetBoxTable, TagColumn
4
4
 
5
- from netbox_dns.models import RegistrationContact
5
+ from netbox_dns.models import Contact
6
6
 
7
7
 
8
- __all__ = ("RegistrationContactTable",)
8
+ __all__ = ("ContactTable",)
9
9
 
10
10
 
11
- class RegistrationContactTable(NetBoxTable):
11
+ class ContactTable(NetBoxTable):
12
12
  contact_id = tables.Column(
13
13
  linkify=True,
14
14
  )
15
15
  tags = TagColumn(
16
- url_name="plugins:netbox_dns:registrationcontact_list",
16
+ url_name="plugins:netbox_dns:contact_list",
17
17
  )
18
18
 
19
19
  class Meta(NetBoxTable.Meta):
20
- model = RegistrationContact
20
+ model = Contact
21
21
  fields = (
22
+ "contact_id",
22
23
  "name",
23
24
  "description",
24
25
  "organization",
@@ -22,7 +22,13 @@ class NameServerTable(TenancyColumnsMixin, NetBoxTable):
22
22
 
23
23
  class Meta(NetBoxTable.Meta):
24
24
  model = NameServer
25
- fields = ("description",)
25
+ fields = (
26
+ "name",
27
+ "description",
28
+ "tags",
29
+ "tenant",
30
+ "tenant_group",
31
+ )
26
32
  default_columns = (
27
33
  "name",
28
34
  "tags",
@@ -1,6 +1,4 @@
1
1
  import django_tables2 as tables
2
- from django.utils.html import format_html
3
-
4
2
 
5
3
  from netbox.tables import (
6
4
  NetBoxTable,
@@ -13,10 +11,6 @@ from tenancy.tables import TenancyColumnsMixin
13
11
  from netbox_dns.models import Record
14
12
  from netbox_dns.utilities import value_to_unicode
15
13
 
16
- import logging
17
-
18
- logger = logging.getLogger("netbox_dns")
19
-
20
14
 
21
15
  __all__ = (
22
16
  "RecordTable",
@@ -29,18 +23,10 @@ class RecordBaseTable(TenancyColumnsMixin, NetBoxTable):
29
23
  zone = tables.Column(
30
24
  linkify=True,
31
25
  )
32
- view = tables.Column(
33
- accessor="zone__view",
34
- linkify=True,
35
- )
36
26
  type = tables.Column()
37
27
  name = tables.Column(
38
28
  linkify=True,
39
29
  )
40
- fqdn = tables.Column(
41
- verbose_name="FQDN",
42
- linkify=True,
43
- )
44
30
  value = tables.TemplateColumn(
45
31
  template_code="{{ value|truncatechars:64 }}",
46
32
  )
@@ -79,8 +65,20 @@ class RecordTable(RecordBaseTable):
79
65
  class Meta(NetBoxTable.Meta):
80
66
  model = Record
81
67
  fields = (
68
+ "name",
69
+ "zone",
70
+ "ttl",
71
+ "type",
72
+ "value",
73
+ "unicode_value",
82
74
  "status",
75
+ "disable_ptr",
76
+ "ptr_record",
77
+ "tags",
78
+ "active",
83
79
  "description",
80
+ "tenant",
81
+ "tenant_group",
84
82
  )
85
83
  default_columns = (
86
84
  "name",
@@ -102,16 +100,21 @@ class ManagedRecordTable(RecordBaseTable):
102
100
  verbose_name="IPAM IP Address",
103
101
  linkify=True,
104
102
  )
105
- related_ip_address = tables.Column(
106
- verbose_name="Related IP Address",
107
- empty_values=(),
108
- orderable=False,
109
- )
110
103
  actions = ActionsColumn(actions=("changelog",))
111
104
 
112
105
  class Meta(NetBoxTable.Meta):
113
106
  model = Record
114
- fields = ()
107
+ fields = (
108
+ "name",
109
+ "zone",
110
+ "ttl",
111
+ "type",
112
+ "value",
113
+ "unicode_value",
114
+ "address_record",
115
+ "ipam_ip_address",
116
+ "active",
117
+ )
115
118
  default_columns = (
116
119
  "name",
117
120
  "zone",
@@ -121,35 +124,19 @@ class ManagedRecordTable(RecordBaseTable):
121
124
  "active",
122
125
  )
123
126
 
124
- def render_related_ip_address(self, record):
125
- if record.ipam_ip_address is not None:
126
- address = record.ipam_ip_address
127
- elif (
128
- hasattr(record, "address_record")
129
- and record.address_record.ipam_ip_address is not None
130
- ):
131
- address = record.address_record.ipam_ip_address
132
- else:
133
- return format_html("—")
134
-
135
- return format_html(f"<a href='{address.get_absolute_url()}'>{address}</a>")
136
-
137
- def value_related_ip_address(self, record):
138
- if record.ipam_ip_address is not None:
139
- return record.ipam_ip_address
140
- elif (
141
- hasattr(record, "address_record")
142
- and record.address_record.ipam_ip_address is not None
143
- ):
144
- return record.address_record.ipam_ip_address
145
-
146
127
 
147
128
  class RelatedRecordTable(RecordBaseTable):
148
129
  actions = ActionsColumn(actions=())
149
130
 
150
131
  class Meta(NetBoxTable.Meta):
151
132
  model = Record
152
- fields = ()
133
+ fields = (
134
+ "name",
135
+ "zone",
136
+ "type",
137
+ "value",
138
+ "unicode_value",
139
+ )
153
140
  default_columns = (
154
141
  "name",
155
142
  "zone",
@@ -43,8 +43,18 @@ class RecordTemplateTable(TenancyColumnsMixin, NetBoxTable):
43
43
  class Meta(NetBoxTable.Meta):
44
44
  model = RecordTemplate
45
45
  fields = (
46
+ "name",
47
+ "record_name",
48
+ "ttl",
49
+ "type",
50
+ "value",
51
+ "unicode_value",
46
52
  "status",
53
+ "disable_ptr",
54
+ "tags",
47
55
  "description",
56
+ "tenant",
57
+ "tenant_group",
48
58
  )
49
59
  default_columns = (
50
60
  "name",
@@ -62,7 +72,14 @@ class RecordTemplateDisplayTable(RecordTemplateTable):
62
72
  class Meta(NetBoxTable.Meta):
63
73
  model = RecordTemplate
64
74
  fields = (
75
+ "name",
76
+ "record_name",
77
+ "ttl",
78
+ "type",
79
+ "value",
80
+ "unicode_value",
65
81
  "status",
82
+ "disable_ptr",
66
83
  "description",
67
84
  )
68
85
  default_columns = (
@@ -19,11 +19,13 @@ class RegistrarTable(NetBoxTable):
19
19
  class Meta(NetBoxTable.Meta):
20
20
  model = Registrar
21
21
  fields = (
22
+ "name",
22
23
  "description",
23
24
  "iana_id",
24
25
  "referral_url",
25
26
  "whois_server",
26
27
  "abuse_email",
27
28
  "abuse_phone",
29
+ "tags",
28
30
  )
29
31
  default_columns = ("name", "iana_id", "referral_url")