netbox-plugin-dns 1.1.0__py3-none-any.whl → 1.1.0b2__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 (83) hide show
  1. netbox_dns/__init__.py +6 -8
  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 +4 -91
  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} +15 -19
  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 +29 -60
  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 +28 -51
  35. netbox_dns/models/zone_template.py +9 -12
  36. netbox_dns/navigation.py +7 -7
  37. netbox_dns/signals/{ipam_dnssync.py → ipam_autodns.py} +24 -78
  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 +1 -1
  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} +41 -80
  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.0b2.dist-info}/METADATA +1 -2
  72. netbox_plugin_dns-1.1.0b2.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/tables/ipam_dnssync.py +0 -11
  77. netbox_dns/templates/netbox_dns/view/button.html +0 -9
  78. netbox_dns/templates/netbox_dns/view/prefix.html +0 -41
  79. netbox_dns/urls/registration_contact.py +0 -60
  80. netbox_dns/views/registration_contact.py +0 -94
  81. netbox_plugin_dns-1.1.0.dist-info/RECORD +0 -146
  82. {netbox_plugin_dns-1.1.0.dist-info → netbox_plugin_dns-1.1.0b2.dist-info}/LICENSE +0 -0
  83. {netbox_plugin_dns-1.1.0.dist-info → netbox_plugin_dns-1.1.0b2.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
@@ -36,7 +36,7 @@ from netbox_dns.utilities import (
36
36
  NameFormatError,
37
37
  )
38
38
  from netbox_dns.validators import (
39
- validate_rname,
39
+ validate_fqdn,
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, ContactsMixin, NetBoxModel):
72
+ class Zone(ObjectModificationMixin, NetBoxModel):
73
73
  ACTIVE_STATUS_LIST = (ZoneStatusChoices.STATUS_ACTIVE,)
74
74
 
75
75
  def __init__(self, *args, **kwargs):
@@ -78,7 +78,6 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
78
78
  super().__init__(*args, **kwargs)
79
79
 
80
80
  self._soa_serial_dirty = False
81
- self._ip_addresses_checked = False
82
81
 
83
82
  view = models.ForeignKey(
84
83
  to="View",
@@ -192,7 +191,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
192
191
  null=True,
193
192
  )
194
193
  registrant = models.ForeignKey(
195
- to="RegistrationContact",
194
+ to="Contact",
196
195
  on_delete=models.SET_NULL,
197
196
  verbose_name="Registrant",
198
197
  help_text="The owner of the domain",
@@ -200,7 +199,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
200
199
  null=True,
201
200
  )
202
201
  admin_c = models.ForeignKey(
203
- to="RegistrationContact",
202
+ to="Contact",
204
203
  on_delete=models.SET_NULL,
205
204
  verbose_name="Admin Contact",
206
205
  related_name="admin_c_zones",
@@ -209,16 +208,16 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
209
208
  null=True,
210
209
  )
211
210
  tech_c = models.ForeignKey(
212
- to="RegistrationContact",
211
+ to="Contact",
213
212
  on_delete=models.SET_NULL,
214
- verbose_name="Technical Contact",
213
+ verbose_name="Tech Contact",
215
214
  related_name="tech_c_zones",
216
215
  help_text="The technical contact for the domain",
217
216
  blank=True,
218
217
  null=True,
219
218
  )
220
219
  billing_c = models.ForeignKey(
221
- to="RegistrationContact",
220
+ to="Contact",
222
221
  on_delete=models.SET_NULL,
223
222
  verbose_name="Billing Contact",
224
223
  related_name="billing_c_zones",
@@ -249,7 +248,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
249
248
 
250
249
  objects = ZoneManager()
251
250
 
252
- clone_fields = (
251
+ clone_fields = [
253
252
  "view",
254
253
  "name",
255
254
  "status",
@@ -263,12 +262,9 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
263
262
  "soa_expire",
264
263
  "soa_minimum",
265
264
  "description",
266
- )
265
+ ]
267
266
 
268
267
  class Meta:
269
- verbose_name = "Zone"
270
- verbose_name_plural = "Zones"
271
-
272
268
  ordering = (
273
269
  "view",
274
270
  "name",
@@ -284,7 +280,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
284
280
  else:
285
281
  try:
286
282
  name = dns_name.from_text(self.name, origin=None).to_unicode()
287
- except DNSException:
283
+ except dns_name.IDNAException:
288
284
  name = self.name
289
285
 
290
286
  try:
@@ -312,14 +308,6 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
312
308
  def soa_serial_dirty(self, soa_serial_dirty):
313
309
  self._soa_serial_dirty = soa_serial_dirty
314
310
 
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
311
  @property
324
312
  def display_name(self):
325
313
  return name_to_unicode(self.name)
@@ -633,7 +621,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
633
621
  raise ValidationError("soa_rname not set and no default value defined")
634
622
  try:
635
623
  dns_name.from_text(self.soa_rname, origin=dns_name.root)
636
- validate_rname(self.soa_rname)
624
+ validate_fqdn(self.soa_rname)
637
625
  except (DNSException, ValidationError) as exc:
638
626
  raise ValidationError(
639
627
  {
@@ -653,7 +641,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
653
641
  old_zone = Zone.objects.get(pk=self.pk)
654
642
  if not self.soa_serial_auto:
655
643
  self.check_soa_serial_increment(old_zone.soa_serial, self.soa_serial)
656
- elif not old_zone.soa_serial_auto:
644
+ else:
657
645
  try:
658
646
  self.check_soa_serial_increment(
659
647
  old_zone.soa_serial, self.get_auto_serial()
@@ -665,26 +653,19 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
665
653
  }
666
654
  )
667
655
 
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(
656
+ if old_zone.name != self.name or old_zone.view != self.view:
657
+ update_ip_addresses = IPAddress.objects.filter(
658
+ pk__in=self.record_set.filter(
675
659
  ipam_ip_address__isnull=False
676
- )
660
+ ).values_list("ipam_ip_address", flat=True)
677
661
  )
678
- ip_addresses |= get_ip_addresses_by_zone(self)
679
-
680
- for ip_address in ip_addresses.distinct():
662
+ update_ip_addresses |= get_ip_addresses_by_zone(self)
663
+ for ip_address in update_ip_addresses:
681
664
  try:
682
665
  check_dns_records(ip_address, zone=self)
683
666
  except ValidationError as exc:
684
667
  raise ValidationError(exc.messages)
685
668
 
686
- self.ip_addresses_checked = True
687
-
688
669
  if self.is_reverse_zone:
689
670
  self.arpa_network = self.network_from_name
690
671
 
@@ -799,13 +780,12 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
799
780
 
800
781
  elif changed_fields is not None and {"name", "view", "status"} & changed_fields:
801
782
  for address_record in self.record_set.filter(
802
- type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA),
803
- ipam_ip_address__isnull=True,
783
+ type__in=(RecordTypeChoices.A, RecordTypeChoices.AAAA)
804
784
  ):
805
785
  address_record.save(update_fields=["ptr_record"])
806
786
 
807
787
  if changed_fields is not None and "name" in changed_fields:
808
- for _record in self.record_set.filter(ipam_ip_address__isnull=True):
788
+ for _record in self.record_set.all():
809
789
  _record.save(
810
790
  update_fields=["fqdn"],
811
791
  save_zone_serial=False,
@@ -814,14 +794,13 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
814
794
  )
815
795
 
816
796
  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(
797
+ update_ip_addresses = IPAddress.objects.filter(
798
+ pk__in=self.record_set.filter(
819
799
  ipam_ip_address__isnull=False
820
- )
800
+ ).values_list("ipam_ip_address", flat=True)
821
801
  )
822
- ip_addresses |= get_ip_addresses_by_zone(self)
823
-
824
- for ip_address in ip_addresses.distinct():
802
+ update_ip_addresses |= get_ip_addresses_by_zone(self)
803
+ for ip_address in update_ip_addresses:
825
804
  update_dns_records(ip_address)
826
805
 
827
806
  self.save_soa_serial()
@@ -864,9 +843,7 @@ class Zone(ObjectModificationMixin, ContactsMixin, NetBoxModel):
864
843
  netbox_dns_records__in=self.record_set.filter(
865
844
  ipam_ip_address__isnull=False
866
845
  )
867
- )
868
- .distinct()
869
- .values_list("pk", flat=True)
846
+ ).values_list("pk", flat=True)
870
847
  )
871
848
 
872
849
  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
  )
@@ -1,6 +1,5 @@
1
1
  from netaddr import IPNetwork
2
2
 
3
- from django.conf import settings
4
3
  from django.dispatch import receiver
5
4
  from django.db.models.signals import pre_delete, pre_save, post_save, m2m_changed
6
5
  from django.core.exceptions import ValidationError
@@ -18,55 +17,21 @@ from netbox_dns.utilities import (
18
17
  delete_dns_records,
19
18
  get_views_by_prefix,
20
19
  get_ip_addresses_by_prefix,
20
+ get_ip_addresses_by_view,
21
21
  )
22
22
 
23
- DNSSYNC_CUSTOM_FIELDS = {
23
+ AUTODNS_CUSTOM_FIELDS = {
24
24
  "ipaddress_dns_disabled": False,
25
25
  "ipaddress_dns_record_ttl": None,
26
26
  "ipaddress_dns_record_disable_ptr": False,
27
27
  }
28
28
 
29
- IPADDRESS_ACTIVE_STATUS = settings.PLUGINS_CONFIG["netbox_dns"][
30
- "dnssync_ipaddress_active_status"
31
- ]
32
- ENFORCE_UNIQUE_RECORDS = settings.PLUGINS_CONFIG["netbox_dns"]["enforce_unique_records"]
33
-
34
29
 
35
30
  @receiver(post_clean, sender=IPAddress)
36
- def ipam_dnssync_ipaddress_post_clean(instance, **kwargs):
31
+ def ipam_autodns_ipaddress_post_clean(instance, **kwargs):
37
32
  if not isinstance(instance.address, IPNetwork):
38
33
  return
39
34
 
40
- if instance.custom_field_data.get("ipaddress_dns_disabled"):
41
- return
42
-
43
- # +
44
- # Check for uniqueness of IP address and dns_name. If unique records are
45
- # enforced, report an error when trying to create the same IP address with
46
- # the same dns_name. Ignore existing IP addresses that have their CF
47
- # "ipaddress_dns_disabled" set to "True".
48
- # -
49
- duplicate_addresses = IPAddress.objects.filter(
50
- address=instance.address,
51
- vrf=instance.vrf,
52
- dns_name=instance.dns_name,
53
- status__in=IPADDRESS_ACTIVE_STATUS,
54
- )
55
- if instance.pk is not None:
56
- duplicate_addresses = duplicate_addresses.exclude(pk=instance.pk)
57
-
58
- if ENFORCE_UNIQUE_RECORDS and instance.status in IPADDRESS_ACTIVE_STATUS:
59
- for ip_address in duplicate_addresses.only("custom_field_data"):
60
- if not ip_address.custom_field_data.get("ipaddress_dns_disabled"):
61
- raise ValidationError(
62
- {
63
- "dns_name": "Unique DNS records are enforced and there is already "
64
- f"an active IP address {instance.address} with DNS name {instance.dns_name}. "
65
- "Plesase choose a different name or disable record creation for this "
66
- "IP address."
67
- }
68
- )
69
-
70
35
  # +
71
36
  # Check NetBox DNS record permission for changes to IPAddress custom fields
72
37
  #
@@ -77,26 +42,24 @@ def ipam_dnssync_ipaddress_post_clean(instance, **kwargs):
77
42
  instance.pk is not None
78
43
  and any(
79
44
  (
80
- cf_data.get(cf, cf_default)
81
- != IPAddress.objects.get(pk=instance.pk).custom_field_data.get(
82
- cf, cf_default
83
- )
84
- for cf, cf_default in DNSSYNC_CUSTOM_FIELDS.items()
45
+ cf_data.get(cf)
46
+ != IPAddress.objects.get(pk=instance.pk).custom_field_data.get(cf)
47
+ for cf in AUTODNS_CUSTOM_FIELDS.keys()
85
48
  )
86
49
  )
87
- and not check_record_permission()
50
+ and not check_record_permission(request)
88
51
  ) or (
89
52
  instance.pk is None
90
53
  and any(
91
54
  (
92
- cf_data.get(cf, cf_default) != cf_default
93
- for cf, cf_default in DNSSYNC_CUSTOM_FIELDS.items()
55
+ cf_data.get(cf) != cf_default
56
+ for cf, cf_default in AUTODNS_CUSTOM_FIELDS.items()
94
57
  )
95
58
  )
96
- and not check_record_permission(change=False, delete=False)
59
+ and not check_record_permission(request, change=False, delete=False)
97
60
  ):
98
61
  raise ValidationError(
99
- f"User '{request.user}' is not allowed to alter DNSsync custom fields"
62
+ f"User '{request.user}' is not allowed to alter AutoDNS custom fields"
100
63
  )
101
64
 
102
65
  try:
@@ -106,51 +69,38 @@ def ipam_dnssync_ipaddress_post_clean(instance, **kwargs):
106
69
 
107
70
 
108
71
  @receiver(pre_delete, sender=IPAddress)
109
- def ipam_dnssync_ipaddress_pre_delete(instance, **kwargs):
72
+ def ipam_autodns_ipaddress_pre_delete(instance, **kwargs):
110
73
  delete_dns_records(instance)
111
74
 
112
75
 
113
76
  @receiver(pre_save, sender=IPAddress)
114
- def ipam_dnssync_ipaddress_pre_save(instance, **kwargs):
77
+ def ipam_autodns_ipaddress_pre_save(instance, **kwargs):
115
78
  check_dns_records(instance)
116
79
 
117
80
 
118
81
  @receiver(post_save, sender=IPAddress)
119
- def ipam_dnssync_ipaddress_post_save(instance, **kwargs):
82
+ def ipam_autodns_ipaddress_post_save(instance, **kwargs):
120
83
  update_dns_records(instance)
121
84
 
122
85
 
123
86
  @receiver(pre_save, sender=Prefix)
124
- def ipam_dnssync_prefix_pre_save(instance, **kwargs):
87
+ def ipam_autodns_prefix_pre_save(instance, **kwargs):
125
88
  """
126
89
  Changes that modify the prefix hierarchy cannot be validated properly before
127
- commiting them. So the solution in this case is to ask the user to deassign
128
- the prefix from any views it is assigned to and retry.
90
+ commiting them. So the solution in this case is to remove a prefix whose
91
+ VRF or network has changed from all views it currently is assigned to.
129
92
  """
130
- request = current_request.get()
131
-
132
93
  if instance.pk is None or not instance.netbox_dns_views.exists():
133
94
  return
134
95
 
135
- saved_prefix = Prefix.objects.prefetch_related("netbox_dns_views").get(
136
- pk=instance.pk
137
- )
96
+ saved_prefix = Prefix.objects.get(pk=instance.pk)
138
97
  if saved_prefix.prefix != instance.prefix or saved_prefix.vrf != instance.vrf:
139
- dns_views = ", ".join([view.name for view in instance.netbox_dns_views.all()])
140
- if request is not None:
141
- raise AbortRequest(
142
- f"This prefix is currently assigned to the following DNS views: {dns_views}"
143
- f"Please deassign it from these views before making changes to the prefix "
144
- f"or VRF."
145
- )
146
-
147
- raise ValidationError(
148
- f"Prefix is assigned to DNS views {dns_views}. Prefix and VRF must not be changed"
149
- )
98
+ for view in saved_prefix.netbox_dns_views.all():
99
+ view.prefixes.remove(saved_prefix)
150
100
 
151
101
 
152
102
  @receiver(pre_delete, sender=Prefix)
153
- def ipam_dnssync_prefix_pre_delete(instance, **kwargs):
103
+ def ipam_autodns_prefix_pre_delete(instance, **kwargs):
154
104
  parent = instance.get_parents().last()
155
105
  request = current_request.get()
156
106
 
@@ -194,7 +144,7 @@ def ipam_dnssync_prefix_pre_delete(instance, **kwargs):
194
144
 
195
145
 
196
146
  @receiver(m2m_changed, sender=_view.View.prefixes.through)
197
- def ipam_dnssync_view_prefix_changed(**kwargs):
147
+ def ipam_autodns_view_prefix_changed(**kwargs):
198
148
  action = kwargs.get("action")
199
149
  request = current_request.get()
200
150
 
@@ -215,10 +165,6 @@ def ipam_dnssync_view_prefix_changed(**kwargs):
215
165
  return
216
166
 
217
167
  check_view = action != "post_remove"
218
-
219
- ip_addresses = IPAddress.objects.none()
220
168
  for prefix in Prefix.objects.filter(pk__in=kwargs.get("pk_set")):
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)
169
+ for ip_address in get_ip_addresses_by_prefix(prefix, check_view=check_view):
170
+ 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",