netbox-plugin-dns 0.21.4__py3-none-any.whl → 1.4.7__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.
Files changed (232) hide show
  1. netbox_dns/__init__.py +106 -41
  2. netbox_dns/api/field_serializers.py +25 -0
  3. netbox_dns/api/nested_serializers.py +95 -52
  4. netbox_dns/api/serializers.py +14 -296
  5. netbox_dns/api/serializers_/__init__.py +0 -0
  6. netbox_dns/api/serializers_/dnssec_key_template.py +69 -0
  7. netbox_dns/api/serializers_/dnssec_policy.py +165 -0
  8. netbox_dns/api/serializers_/nameserver.py +56 -0
  9. netbox_dns/api/serializers_/prefix.py +18 -0
  10. netbox_dns/api/serializers_/record.py +105 -0
  11. netbox_dns/api/serializers_/record_template.py +71 -0
  12. netbox_dns/api/serializers_/registrar.py +45 -0
  13. netbox_dns/api/serializers_/registration_contact.py +50 -0
  14. netbox_dns/api/serializers_/view.py +81 -0
  15. netbox_dns/api/serializers_/zone.py +247 -0
  16. netbox_dns/api/serializers_/zone_template.py +157 -0
  17. netbox_dns/api/urls.py +13 -2
  18. netbox_dns/api/views.py +96 -58
  19. netbox_dns/choices/__init__.py +4 -0
  20. netbox_dns/choices/dnssec_key_template.py +67 -0
  21. netbox_dns/choices/dnssec_policy.py +40 -0
  22. netbox_dns/choices/record.py +104 -0
  23. netbox_dns/choices/utilities.py +4 -0
  24. netbox_dns/choices/zone.py +119 -0
  25. netbox_dns/fields/__init__.py +4 -0
  26. netbox_dns/fields/address.py +22 -16
  27. netbox_dns/fields/choice_array.py +33 -0
  28. netbox_dns/fields/ipam.py +15 -0
  29. netbox_dns/fields/network.py +42 -18
  30. netbox_dns/fields/rfc2317.py +97 -0
  31. netbox_dns/fields/timeperiod.py +33 -0
  32. netbox_dns/filters.py +7 -0
  33. netbox_dns/filtersets/__init__.py +12 -0
  34. netbox_dns/filtersets/dnssec_key_template.py +57 -0
  35. netbox_dns/filtersets/dnssec_policy.py +101 -0
  36. netbox_dns/filtersets/nameserver.py +46 -0
  37. netbox_dns/filtersets/record.py +135 -0
  38. netbox_dns/filtersets/record_template.py +59 -0
  39. netbox_dns/{filters → filtersets}/registrar.py +8 -1
  40. netbox_dns/{filters/contact.py → filtersets/registration_contact.py} +9 -3
  41. netbox_dns/filtersets/view.py +45 -0
  42. netbox_dns/filtersets/zone.py +254 -0
  43. netbox_dns/filtersets/zone_template.py +165 -0
  44. netbox_dns/forms/__init__.py +5 -1
  45. netbox_dns/forms/dnssec_key_template.py +250 -0
  46. netbox_dns/forms/dnssec_policy.py +654 -0
  47. netbox_dns/forms/nameserver.py +121 -27
  48. netbox_dns/forms/record.py +215 -104
  49. netbox_dns/forms/record_template.py +285 -0
  50. netbox_dns/forms/registrar.py +108 -31
  51. netbox_dns/forms/registration_contact.py +282 -0
  52. netbox_dns/forms/view.py +331 -20
  53. netbox_dns/forms/zone.py +769 -373
  54. netbox_dns/forms/zone_template.py +463 -0
  55. netbox_dns/graphql/__init__.py +25 -22
  56. netbox_dns/graphql/enums.py +41 -0
  57. netbox_dns/graphql/filter_lookups.py +13 -0
  58. netbox_dns/graphql/filters/__init__.py +12 -0
  59. netbox_dns/graphql/filters/dnssec_key_template.py +63 -0
  60. netbox_dns/graphql/filters/dnssec_policy.py +124 -0
  61. netbox_dns/graphql/filters/nameserver.py +32 -0
  62. netbox_dns/graphql/filters/record.py +89 -0
  63. netbox_dns/graphql/filters/record_template.py +55 -0
  64. netbox_dns/graphql/filters/registrar.py +30 -0
  65. netbox_dns/graphql/filters/registration_contact.py +27 -0
  66. netbox_dns/graphql/filters/view.py +28 -0
  67. netbox_dns/graphql/filters/zone.py +147 -0
  68. netbox_dns/graphql/filters/zone_template.py +97 -0
  69. netbox_dns/graphql/schema.py +89 -7
  70. netbox_dns/graphql/types.py +355 -0
  71. netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
  72. netbox_dns/locale/en/LC_MESSAGES/django.mo +0 -0
  73. netbox_dns/locale/fr/LC_MESSAGES/django.mo +0 -0
  74. netbox_dns/management/commands/cleanup_database.py +175 -156
  75. netbox_dns/management/commands/cleanup_rrset_ttl.py +64 -0
  76. netbox_dns/management/commands/rebuild_dnssync.py +23 -0
  77. netbox_dns/management/commands/setup_dnssync.py +140 -0
  78. netbox_dns/migrations/0001_squashed_netbox_dns_0_15.py +0 -27
  79. netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +557 -0
  80. netbox_dns/migrations/{0013_add_nameserver_zone_record_description.py → 0002_contact_description_registrar_description.py} +4 -9
  81. netbox_dns/migrations/0003_default_view.py +15 -0
  82. netbox_dns/migrations/0004_create_and_assign_default_view.py +26 -0
  83. netbox_dns/migrations/0005_alter_zone_view_not_null.py +18 -0
  84. netbox_dns/migrations/0006_templating.py +172 -0
  85. netbox_dns/migrations/0007_alter_ordering_options.py +25 -0
  86. netbox_dns/migrations/0008_view_prefixes.py +18 -0
  87. netbox_dns/migrations/0009_rename_contact_registrationcontact.py +36 -0
  88. netbox_dns/migrations/0010_view_ip_address_filter.py +18 -0
  89. netbox_dns/migrations/0011_rename_related_fields.py +63 -0
  90. netbox_dns/migrations/0012_natural_ordering.py +88 -0
  91. netbox_dns/migrations/0013_zonetemplate_soa_mname_zonetemplate_soa_rname.py +30 -0
  92. netbox_dns/migrations/0014_alter_unique_constraints_lowercase.py +42 -0
  93. netbox_dns/migrations/0015_dnssec.py +168 -0
  94. netbox_dns/migrations/{0015_add_record_status.py → 0016_dnssec_policy_status.py} +5 -4
  95. netbox_dns/migrations/0017_dnssec_policy_zone_zone_template.py +41 -0
  96. netbox_dns/migrations/0018_zone_domain_status_zone_expiration_date.py +23 -0
  97. netbox_dns/migrations/0019_dnssecpolicy_parental_agents.py +25 -0
  98. netbox_dns/migrations/0020_netbox_3_4.py +1 -1
  99. netbox_dns/migrations/0020_remove_dnssecpolicy_parental_agents_and_more.py +29 -0
  100. netbox_dns/migrations/0021_alter_record_ptr_record.py +25 -0
  101. netbox_dns/migrations/0021_record_ip_address.py +1 -1
  102. netbox_dns/migrations/0022_alter_record_ipam_ip_address.py +26 -0
  103. netbox_dns/migrations/0023_disable_ptr_false.py +27 -0
  104. netbox_dns/migrations/0024_zonetemplate_parental_agents.py +25 -0
  105. netbox_dns/migrations/0025_remove_zone_inline_signing_and_more.py +22 -0
  106. netbox_dns/migrations/0026_alter_dnssecpolicy_nsec3_opt_out.py +18 -0
  107. netbox_dns/migrations/0026_domain_registration.py +1 -1
  108. netbox_dns/migrations/0027_zone_comments.py +18 -0
  109. netbox_dns/migrations/0028_alter_zone_default_ttl_alter_zone_soa_minimum_and_more.py +54 -0
  110. netbox_dns/migrations/0028_rfc2317_fields.py +44 -0
  111. netbox_dns/migrations/0029_alter_registrationcontact_street.py +18 -0
  112. netbox_dns/migrations/0029_record_fqdn.py +30 -0
  113. netbox_dns/mixins/__init__.py +1 -0
  114. netbox_dns/mixins/object_modification.py +57 -0
  115. netbox_dns/models/__init__.py +5 -1
  116. netbox_dns/models/dnssec_key_template.py +114 -0
  117. netbox_dns/models/dnssec_policy.py +203 -0
  118. netbox_dns/models/nameserver.py +61 -30
  119. netbox_dns/models/record.py +781 -234
  120. netbox_dns/models/record_template.py +198 -0
  121. netbox_dns/models/registrar.py +34 -15
  122. netbox_dns/models/{contact.py → registration_contact.py} +72 -43
  123. netbox_dns/models/view.py +129 -9
  124. netbox_dns/models/zone.py +806 -242
  125. netbox_dns/models/zone_template.py +209 -0
  126. netbox_dns/navigation.py +176 -76
  127. netbox_dns/signals/__init__.py +0 -0
  128. netbox_dns/signals/dnssec.py +32 -0
  129. netbox_dns/signals/ipam_dnssync.py +216 -0
  130. netbox_dns/tables/__init__.py +5 -1
  131. netbox_dns/tables/dnssec_key_template.py +49 -0
  132. netbox_dns/tables/dnssec_policy.py +140 -0
  133. netbox_dns/tables/ipam_dnssync.py +12 -0
  134. netbox_dns/tables/nameserver.py +14 -17
  135. netbox_dns/tables/record.py +117 -59
  136. netbox_dns/tables/record_template.py +91 -0
  137. netbox_dns/tables/registrar.py +20 -10
  138. netbox_dns/tables/{contact.py → registration_contact.py} +22 -11
  139. netbox_dns/tables/view.py +47 -3
  140. netbox_dns/tables/zone.py +62 -31
  141. netbox_dns/tables/zone_template.py +78 -0
  142. netbox_dns/template_content.py +124 -38
  143. netbox_dns/templates/netbox_dns/dnsseckeytemplate.html +70 -0
  144. netbox_dns/templates/netbox_dns/dnssecpolicy.html +163 -0
  145. netbox_dns/templates/netbox_dns/nameserver.html +31 -28
  146. netbox_dns/templates/netbox_dns/record/managed.html +2 -1
  147. netbox_dns/templates/netbox_dns/record/related.html +17 -6
  148. netbox_dns/templates/netbox_dns/record.html +140 -93
  149. netbox_dns/templates/netbox_dns/recordtemplate.html +96 -0
  150. netbox_dns/templates/netbox_dns/registrar.html +41 -34
  151. netbox_dns/templates/netbox_dns/registrationcontact.html +76 -0
  152. netbox_dns/templates/netbox_dns/view/button.html +10 -0
  153. netbox_dns/templates/netbox_dns/view/prefix.html +44 -0
  154. netbox_dns/templates/netbox_dns/view/related.html +33 -0
  155. netbox_dns/templates/netbox_dns/view.html +62 -18
  156. netbox_dns/templates/netbox_dns/zone/base.html +6 -3
  157. netbox_dns/templates/netbox_dns/zone/child.html +6 -5
  158. netbox_dns/templates/netbox_dns/zone/child_zone.html +18 -0
  159. netbox_dns/templates/netbox_dns/zone/delegation_record.html +18 -0
  160. netbox_dns/templates/netbox_dns/zone/managed_record.html +1 -1
  161. netbox_dns/templates/netbox_dns/zone/record.html +6 -5
  162. netbox_dns/templates/netbox_dns/zone/registration.html +43 -24
  163. netbox_dns/templates/netbox_dns/zone/rfc2317_child_zone.html +18 -0
  164. netbox_dns/templates/netbox_dns/zone.html +178 -119
  165. netbox_dns/templates/netbox_dns/zonetemplate/child.html +46 -0
  166. netbox_dns/templates/netbox_dns/zonetemplate.html +124 -0
  167. netbox_dns/templatetags/netbox_dns.py +10 -0
  168. netbox_dns/urls.py +50 -210
  169. netbox_dns/utilities/__init__.py +3 -0
  170. netbox_dns/{utilities.py → utilities/conversions.py} +55 -7
  171. netbox_dns/utilities/dns.py +11 -0
  172. netbox_dns/utilities/ipam_dnssync.py +370 -0
  173. netbox_dns/validators/__init__.py +4 -0
  174. netbox_dns/validators/dns_name.py +116 -0
  175. netbox_dns/validators/dns_value.py +147 -0
  176. netbox_dns/validators/dnssec.py +148 -0
  177. netbox_dns/validators/rfc2317.py +28 -0
  178. netbox_dns/views/__init__.py +5 -1
  179. netbox_dns/views/dnssec_key_template.py +78 -0
  180. netbox_dns/views/dnssec_policy.py +146 -0
  181. netbox_dns/views/nameserver.py +34 -15
  182. netbox_dns/views/record.py +156 -15
  183. netbox_dns/views/record_template.py +93 -0
  184. netbox_dns/views/registrar.py +32 -13
  185. netbox_dns/views/registration_contact.py +101 -0
  186. netbox_dns/views/view.py +58 -14
  187. netbox_dns/views/zone.py +130 -33
  188. netbox_dns/views/zone_template.py +82 -0
  189. netbox_plugin_dns-1.4.7.dist-info/METADATA +132 -0
  190. netbox_plugin_dns-1.4.7.dist-info/RECORD +201 -0
  191. {netbox_plugin_dns-0.21.4.dist-info → netbox_plugin_dns-1.4.7.dist-info}/WHEEL +2 -1
  192. {netbox_plugin_dns-0.21.4.dist-info → netbox_plugin_dns-1.4.7.dist-info/licenses}/LICENSE +2 -1
  193. netbox_plugin_dns-1.4.7.dist-info/top_level.txt +1 -0
  194. netbox_dns/filters/__init__.py +0 -6
  195. netbox_dns/filters/nameserver.py +0 -18
  196. netbox_dns/filters/record.py +0 -53
  197. netbox_dns/filters/view.py +0 -18
  198. netbox_dns/filters/zone.py +0 -112
  199. netbox_dns/forms/contact.py +0 -211
  200. netbox_dns/graphql/contact.py +0 -19
  201. netbox_dns/graphql/nameserver.py +0 -19
  202. netbox_dns/graphql/record.py +0 -19
  203. netbox_dns/graphql/registrar.py +0 -19
  204. netbox_dns/graphql/view.py +0 -19
  205. netbox_dns/graphql/zone.py +0 -19
  206. netbox_dns/management/commands/setup_coupling.py +0 -75
  207. netbox_dns/management/commands/update_soa.py +0 -22
  208. netbox_dns/middleware.py +0 -226
  209. netbox_dns/migrations/0001_initial.py +0 -115
  210. netbox_dns/migrations/0002_zone_default_ttl.py +0 -18
  211. netbox_dns/migrations/0003_soa_managed_records.py +0 -112
  212. netbox_dns/migrations/0004_create_ptr_for_a_aaaa_records.py +0 -80
  213. netbox_dns/migrations/0005_update_ns_records.py +0 -41
  214. netbox_dns/migrations/0006_zone_soa_serial_auto.py +0 -29
  215. netbox_dns/migrations/0007_alter_zone_soa_serial_auto.py +0 -17
  216. netbox_dns/migrations/0008_zone_status_names.py +0 -21
  217. netbox_dns/migrations/0009_netbox32.py +0 -71
  218. netbox_dns/migrations/0010_update_soa_records.py +0 -58
  219. netbox_dns/migrations/0011_add_view_model.py +0 -70
  220. netbox_dns/migrations/0012_adjust_zone_and_record.py +0 -17
  221. netbox_dns/migrations/0014_add_view_description.py +0 -16
  222. netbox_dns/migrations/0016_cleanup_ptr_records.py +0 -38
  223. netbox_dns/migrations/0017_alter_record_ttl.py +0 -17
  224. netbox_dns/migrations/0018_zone_arpa_network.py +0 -51
  225. netbox_dns/migrations/0019_update_ns_ttl.py +0 -19
  226. netbox_dns/templates/netbox_dns/contact.html +0 -71
  227. netbox_dns/templates/netbox_dns/related_dns_objects.html +0 -21
  228. netbox_dns/templatetags/view_helpers.py +0 -15
  229. netbox_dns/validators.py +0 -57
  230. netbox_dns/views/contact.py +0 -83
  231. netbox_plugin_dns-0.21.4.dist-info/METADATA +0 -101
  232. netbox_plugin_dns-0.21.4.dist-info/RECORD +0 -110
@@ -0,0 +1,203 @@
1
+ from django.db import models
2
+ from django.utils.translation import gettext_lazy as _
3
+
4
+ from netbox.models import NetBoxModel
5
+ from netbox.search import SearchIndex, register_search
6
+ from netbox.models.features import ContactsMixin
7
+ from netbox.plugins.utils import get_plugin_config
8
+
9
+ from netbox_dns.choices import DNSSECPolicyDigestChoices, DNSSECPolicyStatusChoices
10
+ from netbox_dns.fields import ChoiceArrayField
11
+
12
+
13
+ __all__ = (
14
+ "DNSSECPolicy",
15
+ "DNSSECPolicyIndex",
16
+ )
17
+
18
+
19
+ class DNSSECPolicy(ContactsMixin, NetBoxModel):
20
+ class Meta:
21
+ verbose_name = _("DNSSEC Policy")
22
+ verbose_name_plural = _("DNSSEC Policies")
23
+
24
+ ordering = ("name",)
25
+
26
+ clone_fields = (
27
+ "name",
28
+ "key_templates",
29
+ "description",
30
+ "tenant",
31
+ )
32
+
33
+ def __str__(self):
34
+ return str(self.name)
35
+
36
+ name = models.CharField(
37
+ verbose_name=_("Name"),
38
+ max_length=255,
39
+ unique=True,
40
+ )
41
+ description = models.CharField(
42
+ verbose_name=_("Description"),
43
+ max_length=200,
44
+ blank=True,
45
+ )
46
+ status = models.CharField(
47
+ verbose_name=_("Status"),
48
+ choices=DNSSECPolicyStatusChoices,
49
+ default=DNSSECPolicyStatusChoices.STATUS_ACTIVE,
50
+ blank=False,
51
+ null=False,
52
+ )
53
+
54
+ inline_signing = models.BooleanField(
55
+ verbose_name=_("Inline Signing"),
56
+ help_text=_("Use inline signing"),
57
+ default=True,
58
+ )
59
+ key_templates = models.ManyToManyField(
60
+ verbose_name=_("Key Templates"),
61
+ to="DNSSECKeyTemplate",
62
+ related_name="policies",
63
+ blank=True,
64
+ )
65
+ dnskey_ttl = models.PositiveIntegerField(
66
+ verbose_name=_("DNSKEY TTL"),
67
+ blank=True,
68
+ null=True,
69
+ )
70
+ purge_keys = models.PositiveIntegerField(
71
+ verbose_name=_("Purge Keys"),
72
+ blank=True,
73
+ null=True,
74
+ )
75
+ publish_safety = models.PositiveIntegerField(
76
+ verbose_name=_("Publish Safety"),
77
+ blank=True,
78
+ null=True,
79
+ )
80
+ retire_safety = models.PositiveIntegerField(
81
+ verbose_name=_("Retire Safety"),
82
+ blank=True,
83
+ null=True,
84
+ )
85
+ signatures_jitter = models.PositiveIntegerField(
86
+ verbose_name=_("Signatures Jitter"),
87
+ blank=True,
88
+ null=True,
89
+ )
90
+ signatures_refresh = models.PositiveIntegerField(
91
+ verbose_name=_("Signatures Refresh"),
92
+ blank=True,
93
+ null=True,
94
+ )
95
+ signatures_validity = models.PositiveIntegerField(
96
+ verbose_name=_("Signatures Validity"),
97
+ blank=True,
98
+ null=True,
99
+ )
100
+ signatures_validity_dnskey = models.PositiveIntegerField(
101
+ verbose_name=_("Signatures Validity for DNSKEY"),
102
+ blank=True,
103
+ null=True,
104
+ )
105
+ max_zone_ttl = models.PositiveIntegerField(
106
+ verbose_name=_("Max Zone TTL"),
107
+ blank=True,
108
+ null=True,
109
+ )
110
+ zone_propagation_delay = models.PositiveIntegerField(
111
+ verbose_name=_("Zone Propagation Delay"),
112
+ blank=True,
113
+ null=True,
114
+ )
115
+
116
+ create_cdnskey = models.BooleanField(
117
+ verbose_name=_("Create CDNSKEY"),
118
+ null=False,
119
+ default=True,
120
+ )
121
+ cds_digest_types = ChoiceArrayField(
122
+ base_field=models.CharField(
123
+ choices=DNSSECPolicyDigestChoices,
124
+ ),
125
+ verbose_name=_("CDS Digest Types"),
126
+ blank=True,
127
+ null=True,
128
+ default=list,
129
+ )
130
+ parent_ds_ttl = models.PositiveIntegerField(
131
+ verbose_name=_("Parent DS TTL"),
132
+ blank=True,
133
+ null=True,
134
+ )
135
+ parent_propagation_delay = models.PositiveIntegerField(
136
+ verbose_name=_("Parent Propagation Delay"),
137
+ blank=True,
138
+ null=True,
139
+ )
140
+
141
+ use_nsec3 = models.BooleanField(
142
+ verbose_name=_("Use NSEC3"),
143
+ null=False,
144
+ default=True,
145
+ )
146
+ nsec3_iterations = models.PositiveIntegerField(
147
+ verbose_name=_("NSEC3 Iterations"),
148
+ blank=True,
149
+ null=True,
150
+ )
151
+ nsec3_opt_out = models.BooleanField(
152
+ verbose_name=_("NSEC3 Opt-Out"),
153
+ blank=True,
154
+ null=True,
155
+ )
156
+ nsec3_salt_size = models.PositiveIntegerField(
157
+ verbose_name=_("NSEC3 Salt Size"),
158
+ blank=True,
159
+ null=True,
160
+ )
161
+
162
+ tenant = models.ForeignKey(
163
+ verbose_name=_("Tenant"),
164
+ to="tenancy.Tenant",
165
+ on_delete=models.PROTECT,
166
+ related_name="netbox_dns_dnssec_policy",
167
+ blank=True,
168
+ null=True,
169
+ )
170
+
171
+ def get_status_color(self):
172
+ return DNSSECPolicyStatusChoices.colors.get(self.status)
173
+
174
+ @property
175
+ def purge_keys_value(self):
176
+ return self.purge_keys if self.purge_keys is not None else 776000
177
+
178
+ @property
179
+ def publish_safety_value(self):
180
+ return self.publish_safety if self.publish_safety is not None else 3600
181
+
182
+ def get_effective_value(self, attribute):
183
+ if not hasattr(self, attribute):
184
+ raise AttributeError(f"DNSSECPolicy does not have attribute {attribute}")
185
+
186
+ if (value := getattr(self, attribute)) is None:
187
+ return self.get_fallback_setting(attribute)
188
+
189
+ return value
190
+
191
+ @classmethod
192
+ def get_fallback_setting(cls, attribute):
193
+ return get_plugin_config("netbox_dns", f"dnssec_{attribute}")
194
+
195
+
196
+ @register_search
197
+ class DNSSECPolicyIndex(SearchIndex):
198
+ model = DNSSECPolicy
199
+
200
+ fields = (
201
+ ("name", 100),
202
+ ("description", 500),
203
+ )
@@ -2,32 +2,72 @@ from dns import name as dns_name
2
2
 
3
3
  from django.core.exceptions import ValidationError
4
4
  from django.db import models, transaction
5
- from django.db.models import Q
6
- from django.urls import reverse
5
+ from django.db.models import Q, UniqueConstraint
6
+ from django.db.models.functions import Lower
7
+ from django.utils.translation import gettext_lazy as _
7
8
 
8
9
  from netbox.models import NetBoxModel
9
10
  from netbox.search import SearchIndex, register_search
11
+ from netbox.models.features import ContactsMixin
12
+ from netbox.plugins.utils import get_plugin_config
10
13
 
11
14
  from netbox_dns.utilities import (
12
15
  name_to_unicode,
13
16
  normalize_name,
14
17
  NameFormatError,
15
18
  )
19
+ from netbox_dns.choices import RecordTypeChoices
16
20
  from netbox_dns.validators import validate_fqdn
21
+ from netbox_dns.mixins import ObjectModificationMixin
17
22
 
18
- from .record import Record, RecordTypeChoices
19
23
 
24
+ __all__ = (
25
+ "NameServer",
26
+ "NameServerIndex",
27
+ )
28
+
29
+
30
+ class NameServer(ObjectModificationMixin, ContactsMixin, NetBoxModel):
31
+ class Meta:
32
+ verbose_name = _("Nameserver")
33
+ verbose_name_plural = _("Nameservers")
34
+
35
+ ordering = ("name",)
36
+
37
+ constraints = [
38
+ UniqueConstraint(
39
+ Lower("name"),
40
+ name="name_unique_ci",
41
+ violation_error_message=_(
42
+ "There is already a nameserver with this name"
43
+ ),
44
+ ),
45
+ ]
46
+
47
+ clone_fields = (
48
+ "name",
49
+ "description",
50
+ "tenant",
51
+ )
52
+
53
+ def __str__(self):
54
+ try:
55
+ return dns_name.from_text(self.name, origin=None).to_unicode()
56
+ except dns_name.IDNAException:
57
+ return self.name
20
58
 
21
- class NameServer(NetBoxModel):
22
59
  name = models.CharField(
23
- unique=True,
60
+ verbose_name=_("Name"),
24
61
  max_length=255,
62
+ db_collation="natural_sort",
25
63
  )
26
64
  description = models.CharField(
65
+ verbose_name=_("Description"),
27
66
  max_length=200,
28
67
  blank=True,
29
68
  )
30
69
  tenant = models.ForeignKey(
70
+ verbose_name=_("Tenant"),
31
71
  to="tenancy.Tenant",
32
72
  on_delete=models.PROTECT,
33
73
  related_name="netbox_dns_nameservers",
@@ -35,25 +75,17 @@ class NameServer(NetBoxModel):
35
75
  null=True,
36
76
  )
37
77
 
38
- clone_fields = ["name", "description"]
39
-
40
- class Meta:
41
- ordering = ("name",)
42
-
43
- def __str__(self):
44
- try:
45
- return dns_name.from_text(self.name, origin=None).to_unicode()
46
- except dns_name.IDNAException:
47
- return self.name
48
-
49
78
  @property
50
79
  def display_name(self):
51
80
  return name_to_unicode(self.name)
52
81
 
53
- def get_absolute_url(self):
54
- return reverse("plugins:netbox_dns:nameserver", kwargs={"pk": self.pk})
82
+ def clean_fields(self, exclude=None):
83
+ if get_plugin_config("netbox_dns", "convert_names_to_lowercase", False):
84
+ self.name = self.name.lower()
55
85
 
56
- def clean(self):
86
+ super().clean_fields(exclude=exclude)
87
+
88
+ def clean(self, *args, **kwargs):
57
89
  try:
58
90
  self.name = normalize_name(self.name)
59
91
  except NameFormatError as exc:
@@ -61,7 +93,7 @@ class NameServer(NetBoxModel):
61
93
  {
62
94
  "name": str(exc),
63
95
  }
64
- ) from None
96
+ )
65
97
 
66
98
  try:
67
99
  validate_fqdn(self.name)
@@ -70,20 +102,20 @@ class NameServer(NetBoxModel):
70
102
  {
71
103
  "name": exc,
72
104
  }
73
- ) from None
105
+ )
106
+
107
+ super().clean(*args, **kwargs)
74
108
 
75
109
  def save(self, *args, **kwargs):
76
110
  self.full_clean()
77
111
 
78
- name_changed = (
79
- self.pk is not None and self.name != NameServer.objects.get(pk=self.pk).name
80
- )
112
+ changed_fields = self.changed_fields
81
113
 
82
114
  with transaction.atomic():
83
115
  super().save(*args, **kwargs)
84
116
 
85
- if name_changed:
86
- soa_zones = self.zones_soa.all()
117
+ if changed_fields is not None and "name" in changed_fields:
118
+ soa_zones = self.soa_zones.all()
87
119
  for soa_zone in soa_zones:
88
120
  soa_zone.update_soa_record()
89
121
 
@@ -93,10 +125,8 @@ class NameServer(NetBoxModel):
93
125
 
94
126
  def delete(self, *args, **kwargs):
95
127
  with transaction.atomic():
96
- zones = self.zones.all()
97
- for zone in zones:
98
- Record.objects.filter(
99
- Q(zone=zone),
128
+ for zone in self.zones.all():
129
+ zone.records.filter(
100
130
  Q(managed=True),
101
131
  Q(value=f"{self.name}."),
102
132
  Q(type=RecordTypeChoices.NS),
@@ -108,6 +138,7 @@ class NameServer(NetBoxModel):
108
138
  @register_search
109
139
  class NameServerIndex(SearchIndex):
110
140
  model = NameServer
141
+
111
142
  fields = (
112
143
  ("name", 100),
113
144
  ("description", 500),