netbox-plugin-dns 1.1.1__py3-none-any.whl → 1.1.3__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 +8 -6
- netbox_dns/api/nested_serializers.py +3 -2
- netbox_dns/api/serializers_/nameserver.py +2 -1
- netbox_dns/api/serializers_/record.py +5 -4
- netbox_dns/api/serializers_/record_template.py +2 -1
- netbox_dns/api/serializers_/view.py +3 -1
- netbox_dns/api/serializers_/zone.py +12 -11
- netbox_dns/api/serializers_/zone_template.py +8 -7
- netbox_dns/api/views.py +9 -4
- netbox_dns/choices/record.py +4 -2
- netbox_dns/choices/zone.py +6 -4
- netbox_dns/fields/address.py +2 -1
- netbox_dns/fields/network.py +2 -1
- netbox_dns/fields/rfc2317.py +7 -3
- netbox_dns/filtersets/nameserver.py +3 -2
- netbox_dns/filtersets/record.py +10 -9
- netbox_dns/filtersets/record_template.py +3 -2
- netbox_dns/filtersets/view.py +3 -2
- netbox_dns/filtersets/zone.py +24 -22
- netbox_dns/filtersets/zone_template.py +15 -14
- netbox_dns/forms/nameserver.py +41 -17
- netbox_dns/forms/record.py +43 -26
- netbox_dns/forms/record_template.py +49 -28
- netbox_dns/forms/registrar.py +21 -17
- netbox_dns/forms/registration_contact.py +37 -25
- netbox_dns/forms/view.py +75 -34
- netbox_dns/forms/zone.py +167 -120
- netbox_dns/forms/zone_template.py +53 -43
- netbox_dns/graphql/schema.py +0 -10
- netbox_dns/graphql/types.py +1 -0
- netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
- netbox_dns/locale/en/LC_MESSAGES/django.mo +0 -0
- netbox_dns/management/commands/rebuild_dnssync.py +14 -1
- netbox_dns/migrations/0010_view_ip_address_filter.py +18 -0
- netbox_dns/mixins/object_modification.py +30 -8
- netbox_dns/models/nameserver.py +6 -2
- netbox_dns/models/record.py +95 -40
- netbox_dns/models/record_template.py +16 -8
- netbox_dns/models/registrar.py +11 -7
- netbox_dns/models/registration_contact.py +23 -11
- netbox_dns/models/view.py +54 -5
- netbox_dns/models/zone.py +77 -50
- netbox_dns/models/zone_template.py +12 -10
- netbox_dns/navigation.py +30 -28
- netbox_dns/signals/ipam_dnssync.py +25 -18
- netbox_dns/tables/ipam_dnssync.py +2 -1
- netbox_dns/tables/nameserver.py +2 -0
- netbox_dns/tables/record.py +21 -11
- netbox_dns/tables/record_template.py +12 -5
- netbox_dns/tables/registrar.py +2 -0
- netbox_dns/tables/registration_contact.py +2 -0
- netbox_dns/tables/view.py +4 -2
- netbox_dns/tables/zone.py +15 -2
- netbox_dns/tables/zone_template.py +7 -0
- netbox_dns/templates/netbox_dns/nameserver.html +6 -5
- netbox_dns/templates/netbox_dns/record/managed.html +2 -1
- netbox_dns/templates/netbox_dns/record/related.html +26 -14
- netbox_dns/templates/netbox_dns/record.html +39 -20
- netbox_dns/templates/netbox_dns/recordtemplate.html +27 -15
- netbox_dns/templates/netbox_dns/registrar.html +11 -10
- netbox_dns/templates/netbox_dns/registrationcontact.html +16 -15
- netbox_dns/templates/netbox_dns/view/button.html +2 -1
- netbox_dns/templates/netbox_dns/view/prefix.html +7 -4
- netbox_dns/templates/netbox_dns/view/related.html +26 -10
- netbox_dns/templates/netbox_dns/view.html +22 -9
- netbox_dns/templates/netbox_dns/zone/base.html +2 -1
- netbox_dns/templates/netbox_dns/zone/child.html +3 -2
- netbox_dns/templates/netbox_dns/zone/record.html +3 -2
- netbox_dns/templates/netbox_dns/zone/registration.html +8 -7
- netbox_dns/templates/netbox_dns/zone.html +28 -30
- netbox_dns/templates/netbox_dns/zonetemplate.html +27 -17
- netbox_dns/utilities/ipam_dnssync.py +71 -28
- netbox_dns/validators/dns_name.py +11 -4
- netbox_dns/validators/dns_value.py +9 -4
- netbox_dns/validators/rfc2317.py +6 -3
- netbox_dns/views/nameserver.py +4 -2
- netbox_dns/views/record_template.py +4 -3
- netbox_dns/views/registrar.py +3 -1
- netbox_dns/views/registration_contact.py +2 -1
- netbox_dns/views/view.py +2 -1
- netbox_dns/views/zone.py +6 -4
- netbox_dns/views/zone_template.py +8 -7
- {netbox_plugin_dns-1.1.1.dist-info → netbox_plugin_dns-1.1.3.dist-info}/METADATA +1 -1
- netbox_plugin_dns-1.1.3.dist-info/RECORD +150 -0
- {netbox_plugin_dns-1.1.1.dist-info → netbox_plugin_dns-1.1.3.dist-info}/WHEEL +1 -1
- netbox_plugin_dns-1.1.1.dist-info/RECORD +0 -147
- {netbox_plugin_dns-1.1.1.dist-info → netbox_plugin_dns-1.1.3.dist-info}/LICENSE +0 -0
- {netbox_plugin_dns-1.1.1.dist-info → netbox_plugin_dns-1.1.3.dist-info}/top_level.txt +0 -0
netbox_dns/models/record.py
CHANGED
|
@@ -8,15 +8,17 @@ from django.db import transaction, models
|
|
|
8
8
|
from django.db.models import Q, ExpressionWrapper, BooleanField, Min
|
|
9
9
|
from django.urls import reverse
|
|
10
10
|
from django.conf import settings
|
|
11
|
+
from django.utils.translation import gettext_lazy as _
|
|
11
12
|
|
|
12
13
|
from netbox.models import NetBoxModel
|
|
14
|
+
from ipam.models import IPAddress
|
|
13
15
|
from netbox.models.features import ContactsMixin
|
|
14
16
|
from netbox.search import SearchIndex, register_search
|
|
15
17
|
from netbox.plugins.utils import get_plugin_config
|
|
16
18
|
from utilities.querysets import RestrictedQuerySet
|
|
17
19
|
|
|
18
20
|
from netbox_dns.fields import AddressField
|
|
19
|
-
from netbox_dns.utilities import arpa_to_prefix, name_to_unicode
|
|
21
|
+
from netbox_dns.utilities import arpa_to_prefix, name_to_unicode, get_query_from_filter
|
|
20
22
|
from netbox_dns.validators import validate_generic_name, validate_record_value
|
|
21
23
|
from netbox_dns.mixins import ObjectModificationMixin
|
|
22
24
|
from netbox_dns.choices import RecordTypeChoices, RecordStatusChoices
|
|
@@ -41,6 +43,20 @@ def record_data_from_ip_address(ip_address, zone):
|
|
|
41
43
|
cf_data = ip_address.custom_field_data
|
|
42
44
|
|
|
43
45
|
if cf_data.get("ipaddress_dns_disabled"):
|
|
46
|
+
# +
|
|
47
|
+
# DNS record creation disabled for this address
|
|
48
|
+
# -
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
if (
|
|
52
|
+
zone.view.ip_address_filter is not None
|
|
53
|
+
and not IPAddress.objects.filter(
|
|
54
|
+
Q(pk=ip_address.pk), get_query_from_filter(zone.view.ip_address_filter)
|
|
55
|
+
).exists()
|
|
56
|
+
):
|
|
57
|
+
# +
|
|
58
|
+
# IP address does not match the filter
|
|
59
|
+
# -
|
|
44
60
|
return None
|
|
45
61
|
|
|
46
62
|
data = {
|
|
@@ -110,58 +126,67 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
110
126
|
)
|
|
111
127
|
|
|
112
128
|
name = models.CharField(
|
|
129
|
+
verbose_name=_("Name"),
|
|
113
130
|
max_length=255,
|
|
114
131
|
)
|
|
115
132
|
zone = models.ForeignKey(
|
|
116
|
-
"Zone",
|
|
133
|
+
verbose_name=_("Zone"),
|
|
134
|
+
to="Zone",
|
|
117
135
|
on_delete=models.CASCADE,
|
|
118
136
|
)
|
|
119
137
|
fqdn = models.CharField(
|
|
138
|
+
verbose_name=_("FQDN"),
|
|
120
139
|
max_length=255,
|
|
121
140
|
null=True,
|
|
122
141
|
blank=True,
|
|
123
142
|
default=None,
|
|
124
143
|
)
|
|
125
144
|
type = models.CharField(
|
|
145
|
+
verbose_name=_("Type"),
|
|
126
146
|
choices=RecordTypeChoices,
|
|
127
147
|
max_length=10,
|
|
128
148
|
)
|
|
129
149
|
value = models.CharField(
|
|
150
|
+
verbose_name=_("Value"),
|
|
130
151
|
max_length=65535,
|
|
131
152
|
)
|
|
132
153
|
status = models.CharField(
|
|
154
|
+
verbose_name=_("Status"),
|
|
133
155
|
max_length=50,
|
|
134
156
|
choices=RecordStatusChoices,
|
|
135
157
|
default=RecordStatusChoices.STATUS_ACTIVE,
|
|
136
158
|
blank=False,
|
|
137
159
|
)
|
|
138
160
|
ttl = models.PositiveIntegerField(
|
|
139
|
-
verbose_name="TTL",
|
|
161
|
+
verbose_name=_("TTL"),
|
|
140
162
|
null=True,
|
|
141
163
|
blank=True,
|
|
142
164
|
)
|
|
143
165
|
managed = models.BooleanField(
|
|
166
|
+
verbose_name=_("Managed"),
|
|
144
167
|
null=False,
|
|
145
168
|
default=False,
|
|
146
169
|
)
|
|
147
170
|
ptr_record = models.OneToOneField(
|
|
148
|
-
"
|
|
171
|
+
verbose_name="PTR Record",
|
|
172
|
+
to="self",
|
|
149
173
|
on_delete=models.SET_NULL,
|
|
150
174
|
related_name="address_record",
|
|
151
|
-
verbose_name="PTR record",
|
|
152
175
|
null=True,
|
|
153
176
|
blank=True,
|
|
154
177
|
)
|
|
155
178
|
disable_ptr = models.BooleanField(
|
|
156
|
-
verbose_name="Disable PTR",
|
|
157
|
-
help_text="Disable PTR record creation",
|
|
179
|
+
verbose_name=_("Disable PTR"),
|
|
180
|
+
help_text=_("Disable PTR record creation"),
|
|
158
181
|
default=False,
|
|
159
182
|
)
|
|
160
183
|
description = models.CharField(
|
|
184
|
+
verbose_name=_("Description"),
|
|
161
185
|
max_length=200,
|
|
162
186
|
blank=True,
|
|
163
187
|
)
|
|
164
188
|
tenant = models.ForeignKey(
|
|
189
|
+
verbose_name=_("Tenant"),
|
|
165
190
|
to="tenancy.Tenant",
|
|
166
191
|
on_delete=models.PROTECT,
|
|
167
192
|
related_name="netbox_dns_records",
|
|
@@ -169,13 +194,13 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
169
194
|
null=True,
|
|
170
195
|
)
|
|
171
196
|
ip_address = AddressField(
|
|
172
|
-
verbose_name="Related IP Address",
|
|
173
|
-
help_text="IP address related to an address (A/AAAA) or PTR record",
|
|
197
|
+
verbose_name=_("Related IP Address"),
|
|
198
|
+
help_text=_("IP address related to an address (A/AAAA) or PTR record"),
|
|
174
199
|
blank=True,
|
|
175
200
|
null=True,
|
|
176
201
|
)
|
|
177
202
|
ipam_ip_address = models.ForeignKey(
|
|
178
|
-
verbose_name="IPAM IP Address",
|
|
203
|
+
verbose_name=_("IPAM IP Address"),
|
|
179
204
|
to="ipam.IPAddress",
|
|
180
205
|
on_delete=models.CASCADE,
|
|
181
206
|
related_name="netbox_dns_records",
|
|
@@ -183,10 +208,10 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
183
208
|
null=True,
|
|
184
209
|
)
|
|
185
210
|
rfc2317_cname_record = models.ForeignKey(
|
|
186
|
-
"
|
|
211
|
+
verbose_name=_("RFC2317 CNAME Record"),
|
|
212
|
+
to="self",
|
|
187
213
|
on_delete=models.SET_NULL,
|
|
188
214
|
related_name="rfc2317_ptr_records",
|
|
189
|
-
verbose_name="RFC2317 CNAME record",
|
|
190
215
|
null=True,
|
|
191
216
|
blank=True,
|
|
192
217
|
)
|
|
@@ -206,8 +231,8 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
206
231
|
)
|
|
207
232
|
|
|
208
233
|
class Meta:
|
|
209
|
-
verbose_name = "Record"
|
|
210
|
-
verbose_name_plural = "Records"
|
|
234
|
+
verbose_name = _("Record")
|
|
235
|
+
verbose_name_plural = _("Records")
|
|
211
236
|
|
|
212
237
|
ordering = (
|
|
213
238
|
"fqdn",
|
|
@@ -473,22 +498,29 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
473
498
|
self.rfc2317_cname_record = None
|
|
474
499
|
|
|
475
500
|
def update_from_ip_address(self, ip_address, zone=None):
|
|
501
|
+
"""
|
|
502
|
+
Update an address record according to data from an IPAddress object.
|
|
503
|
+
|
|
504
|
+
Returns a tuple of two booleans: (update, delete).
|
|
505
|
+
|
|
506
|
+
update: The record was updated and needs to be cleaned and/or saved
|
|
507
|
+
delete: The record is no longer needed and needs to be deleted
|
|
508
|
+
"""
|
|
476
509
|
if zone is None:
|
|
477
510
|
zone = self.zone
|
|
478
511
|
|
|
479
512
|
data = record_data_from_ip_address(ip_address, zone)
|
|
480
513
|
|
|
481
514
|
if data is None:
|
|
482
|
-
|
|
483
|
-
return
|
|
515
|
+
return False, True
|
|
484
516
|
|
|
485
517
|
if all((getattr(self, attr) == data[attr] for attr in data.keys())):
|
|
486
|
-
return
|
|
518
|
+
return False, False
|
|
487
519
|
|
|
488
520
|
for attr, value in data.items():
|
|
489
521
|
setattr(self, attr, value)
|
|
490
522
|
|
|
491
|
-
return
|
|
523
|
+
return True, False
|
|
492
524
|
|
|
493
525
|
@classmethod
|
|
494
526
|
def create_from_ip_address(cls, ip_address, zone):
|
|
@@ -515,7 +547,9 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
515
547
|
if not fqdn.is_subdomain(_zone):
|
|
516
548
|
raise ValidationError(
|
|
517
549
|
{
|
|
518
|
-
"name":
|
|
550
|
+
"name": _("{name} is not a name in {zone}").format(
|
|
551
|
+
name=self.name, zone=zone.name
|
|
552
|
+
),
|
|
519
553
|
}
|
|
520
554
|
)
|
|
521
555
|
|
|
@@ -559,13 +593,13 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
559
593
|
{
|
|
560
594
|
"name": exc,
|
|
561
595
|
}
|
|
562
|
-
)
|
|
596
|
+
)
|
|
563
597
|
|
|
564
598
|
def validate_value(self):
|
|
565
599
|
try:
|
|
566
600
|
validate_record_value(self.type, self.value)
|
|
567
601
|
except ValidationError as exc:
|
|
568
|
-
raise ValidationError({"value": exc})
|
|
602
|
+
raise ValidationError({"value": exc})
|
|
569
603
|
|
|
570
604
|
def check_unique_record(self, new_zone=None):
|
|
571
605
|
if not get_plugin_config("netbox_dns", "enforce_unique_records", False):
|
|
@@ -585,7 +619,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
585
619
|
status__in=Record.ACTIVE_STATUS_LIST,
|
|
586
620
|
)
|
|
587
621
|
|
|
588
|
-
if self.
|
|
622
|
+
if not self._state.adding:
|
|
589
623
|
records = records.exclude(pk=self.pk)
|
|
590
624
|
|
|
591
625
|
if records.exists():
|
|
@@ -599,9 +633,13 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
599
633
|
|
|
600
634
|
raise ValidationError(
|
|
601
635
|
{
|
|
602
|
-
"value":
|
|
636
|
+
"value": _(
|
|
637
|
+
"There is already an active {type} record for name {name} in zone {zone} with value {value}."
|
|
638
|
+
).format(
|
|
639
|
+
type=self.type, name=self.name, zone=self.zone, value=self.value
|
|
640
|
+
)
|
|
603
641
|
}
|
|
604
|
-
)
|
|
642
|
+
)
|
|
605
643
|
|
|
606
644
|
def handle_conflicting_address_records(self):
|
|
607
645
|
if self.ipam_ip_address is None or not self.is_active:
|
|
@@ -624,7 +662,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
624
662
|
record.save(update_fields=["status"])
|
|
625
663
|
|
|
626
664
|
def check_unique_rrset_ttl(self):
|
|
627
|
-
if self.
|
|
665
|
+
if not self._state.adding:
|
|
628
666
|
return
|
|
629
667
|
|
|
630
668
|
if not get_plugin_config("netbox_dns", "enforce_unique_rrset_ttl", False):
|
|
@@ -658,12 +696,19 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
658
696
|
conflicting_ttls = ", ".join({str(record.ttl) for record in records})
|
|
659
697
|
raise ValidationError(
|
|
660
698
|
{
|
|
661
|
-
"ttl":
|
|
699
|
+
"ttl": _(
|
|
700
|
+
"There is at least one active {type} record for name {name} in zone {zone} and TTL is different ({ttls})."
|
|
701
|
+
).format(
|
|
702
|
+
type=self.type,
|
|
703
|
+
name=self.name,
|
|
704
|
+
zone=self.zone,
|
|
705
|
+
ttls=conflicting_ttls,
|
|
706
|
+
)
|
|
662
707
|
}
|
|
663
|
-
)
|
|
708
|
+
)
|
|
664
709
|
|
|
665
710
|
def update_rrset_ttl(self, ttl=None):
|
|
666
|
-
if self.
|
|
711
|
+
if self._state.adding:
|
|
667
712
|
return
|
|
668
713
|
|
|
669
714
|
if not get_plugin_config("netbox_dns", "enforce_unique_rrset_ttl", False):
|
|
@@ -699,7 +744,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
699
744
|
self.validate_name(new_zone=new_zone)
|
|
700
745
|
self.validate_value()
|
|
701
746
|
self.check_unique_record(new_zone=new_zone)
|
|
702
|
-
if self.
|
|
747
|
+
if self._state.adding:
|
|
703
748
|
self.check_unique_rrset_ttl()
|
|
704
749
|
|
|
705
750
|
if not self.is_active:
|
|
@@ -738,24 +783,30 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
738
783
|
):
|
|
739
784
|
raise ValidationError(
|
|
740
785
|
{
|
|
741
|
-
"value":
|
|
786
|
+
"value": _(
|
|
787
|
+
"There is already an active record for name {name} in zone {zone}, RFC2317 CNAME is not allowed."
|
|
788
|
+
).format(name=ptr_cname_name, zone=ptr_cname_zone)
|
|
742
789
|
}
|
|
743
|
-
)
|
|
790
|
+
)
|
|
744
791
|
|
|
745
792
|
if self.type == RecordTypeChoices.SOA and self.name != "@":
|
|
746
793
|
raise ValidationError(
|
|
747
794
|
{
|
|
748
|
-
"name":
|
|
795
|
+
"name": _(
|
|
796
|
+
"SOA records are only allowed with name @ and are created automatically by NetBox DNS"
|
|
797
|
+
)
|
|
749
798
|
}
|
|
750
|
-
)
|
|
799
|
+
)
|
|
751
800
|
|
|
752
801
|
if self.type == RecordTypeChoices.CNAME:
|
|
753
802
|
if records.exclude(type=RecordTypeChoices.NSEC).exists():
|
|
754
803
|
raise ValidationError(
|
|
755
804
|
{
|
|
756
|
-
"type":
|
|
805
|
+
"type": _(
|
|
806
|
+
"There is already an active record for name {name} in zone {zone}, CNAME is not allowed."
|
|
807
|
+
).format(name=self.name, zone=self.zone)
|
|
757
808
|
}
|
|
758
|
-
)
|
|
809
|
+
)
|
|
759
810
|
|
|
760
811
|
elif (
|
|
761
812
|
records.filter(type=RecordTypeChoices.CNAME).exists()
|
|
@@ -763,17 +814,21 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
763
814
|
):
|
|
764
815
|
raise ValidationError(
|
|
765
816
|
{
|
|
766
|
-
"type":
|
|
817
|
+
"type": _(
|
|
818
|
+
"There is already an active CNAME record for name {name} in zone {zone}, no other record allowed."
|
|
819
|
+
).format(name=self.name, zone=self.zone)
|
|
767
820
|
}
|
|
768
|
-
)
|
|
821
|
+
)
|
|
769
822
|
|
|
770
823
|
elif self.type in RecordTypeChoices.SINGLETONS:
|
|
771
824
|
if records.filter(type=self.type).exists():
|
|
772
825
|
raise ValidationError(
|
|
773
826
|
{
|
|
774
|
-
"type":
|
|
827
|
+
"type": _(
|
|
828
|
+
"There is already an active {type} record for name {name} in zone {zone}, more than one are not allowed."
|
|
829
|
+
).format(type=self.type, name=self.name, zone=self.zone)
|
|
775
830
|
}
|
|
776
|
-
)
|
|
831
|
+
)
|
|
777
832
|
|
|
778
833
|
super().clean(*args, **kwargs)
|
|
779
834
|
|
|
@@ -787,7 +842,7 @@ class Record(ObjectModificationMixin, ContactsMixin, NetBoxModel):
|
|
|
787
842
|
):
|
|
788
843
|
self.full_clean()
|
|
789
844
|
|
|
790
|
-
if self.
|
|
845
|
+
if not self._state.adding and update_rrset_ttl:
|
|
791
846
|
self.update_rrset_ttl()
|
|
792
847
|
|
|
793
848
|
if self.is_ptr_record:
|
|
@@ -4,6 +4,7 @@ from dns import name as dns_name
|
|
|
4
4
|
from django.core.exceptions import ValidationError
|
|
5
5
|
from django.db import models
|
|
6
6
|
from django.urls import reverse
|
|
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
|
|
@@ -23,40 +24,45 @@ __all__ = (
|
|
|
23
24
|
|
|
24
25
|
class RecordTemplate(NetBoxModel):
|
|
25
26
|
name = models.CharField(
|
|
26
|
-
verbose_name="Template
|
|
27
|
+
verbose_name=_("Template Name"),
|
|
27
28
|
unique=True,
|
|
28
29
|
max_length=200,
|
|
29
30
|
)
|
|
30
31
|
record_name = models.CharField(
|
|
31
|
-
verbose_name="Name",
|
|
32
|
+
verbose_name=_("Name"),
|
|
32
33
|
max_length=255,
|
|
33
34
|
)
|
|
34
35
|
description = models.CharField(
|
|
36
|
+
verbose_name=_("Description"),
|
|
35
37
|
max_length=200,
|
|
36
38
|
blank=True,
|
|
37
39
|
)
|
|
38
40
|
type = models.CharField(
|
|
41
|
+
verbose_name=_("Type"),
|
|
39
42
|
choices=RecordTypeChoices,
|
|
40
43
|
)
|
|
41
44
|
value = models.CharField(
|
|
45
|
+
verbose_name=_("Value"),
|
|
42
46
|
max_length=65535,
|
|
43
47
|
)
|
|
44
48
|
status = models.CharField(
|
|
49
|
+
verbose_name=_("Status"),
|
|
45
50
|
choices=RecordStatusChoices,
|
|
46
51
|
default=RecordStatusChoices.STATUS_ACTIVE,
|
|
47
52
|
blank=False,
|
|
48
53
|
)
|
|
49
54
|
ttl = models.PositiveIntegerField(
|
|
50
|
-
verbose_name="TTL",
|
|
55
|
+
verbose_name=_("TTL"),
|
|
51
56
|
null=True,
|
|
52
57
|
blank=True,
|
|
53
58
|
)
|
|
54
59
|
disable_ptr = models.BooleanField(
|
|
55
|
-
verbose_name="Disable PTR",
|
|
56
|
-
help_text="Disable PTR record creation",
|
|
60
|
+
verbose_name=_("Disable PTR"),
|
|
61
|
+
help_text=_("Disable PTR record creation"),
|
|
57
62
|
default=False,
|
|
58
63
|
)
|
|
59
64
|
tenant = models.ForeignKey(
|
|
65
|
+
verbose_name=_("Tenant"),
|
|
60
66
|
to="tenancy.Tenant",
|
|
61
67
|
on_delete=models.PROTECT,
|
|
62
68
|
related_name="+",
|
|
@@ -85,8 +91,8 @@ class RecordTemplate(NetBoxModel):
|
|
|
85
91
|
)
|
|
86
92
|
|
|
87
93
|
class Meta:
|
|
88
|
-
verbose_name = "Record Template"
|
|
89
|
-
verbose_name_plural = "Record Templates"
|
|
94
|
+
verbose_name = _("Record Template")
|
|
95
|
+
verbose_name_plural = _("Record Templates")
|
|
90
96
|
|
|
91
97
|
ordering = ("name",)
|
|
92
98
|
|
|
@@ -155,7 +161,9 @@ class RecordTemplate(NetBoxModel):
|
|
|
155
161
|
record = Record.objects.create(**record_data)
|
|
156
162
|
except ValidationError as exc:
|
|
157
163
|
raise ValidationError(
|
|
158
|
-
|
|
164
|
+
_("Error while processing record template {template}: {error}").format(
|
|
165
|
+
template=self, error=exc.messages[0]
|
|
166
|
+
)
|
|
159
167
|
)
|
|
160
168
|
|
|
161
169
|
if tags := self.tags.all():
|
netbox_dns/models/registrar.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from django.db import models
|
|
2
2
|
from django.urls import reverse
|
|
3
|
+
from django.utils.translation import gettext_lazy as _
|
|
3
4
|
|
|
4
5
|
from netbox.models import NetBoxModel
|
|
5
6
|
from netbox.search import SearchIndex, register_search
|
|
@@ -16,38 +17,41 @@ class Registrar(NetBoxModel):
|
|
|
16
17
|
# Data fields according to https://www.icann.org/resources/pages/rdds-labeling-policy-2017-02-01-en
|
|
17
18
|
# -
|
|
18
19
|
name = models.CharField(
|
|
20
|
+
verbose_name=_("Name"),
|
|
19
21
|
unique=True,
|
|
20
22
|
max_length=255,
|
|
21
23
|
)
|
|
22
24
|
description = models.CharField(
|
|
25
|
+
verbose_name=_("Description"),
|
|
23
26
|
blank=True,
|
|
24
27
|
max_length=200,
|
|
25
28
|
)
|
|
26
29
|
iana_id = models.IntegerField(
|
|
27
|
-
verbose_name="IANA ID",
|
|
30
|
+
verbose_name=_("IANA ID"),
|
|
28
31
|
null=True,
|
|
29
32
|
blank=True,
|
|
30
33
|
)
|
|
31
34
|
referral_url = models.URLField(
|
|
32
|
-
verbose_name="Referral URL",
|
|
35
|
+
verbose_name=_("Referral URL"),
|
|
33
36
|
max_length=255,
|
|
34
37
|
blank=True,
|
|
35
38
|
)
|
|
36
39
|
whois_server = models.CharField(
|
|
37
|
-
verbose_name="WHOIS Server",
|
|
40
|
+
verbose_name=_("WHOIS Server"),
|
|
38
41
|
max_length=255,
|
|
39
42
|
blank=True,
|
|
40
43
|
)
|
|
41
44
|
address = models.CharField(
|
|
45
|
+
verbose_name=_("Address"),
|
|
42
46
|
max_length=200,
|
|
43
47
|
blank=True,
|
|
44
48
|
)
|
|
45
49
|
abuse_email = models.EmailField(
|
|
46
|
-
verbose_name="Abuse Email",
|
|
50
|
+
verbose_name=_("Abuse Email"),
|
|
47
51
|
blank=True,
|
|
48
52
|
)
|
|
49
53
|
abuse_phone = models.CharField(
|
|
50
|
-
verbose_name="Abuse Phone",
|
|
54
|
+
verbose_name=_("Abuse Phone"),
|
|
51
55
|
max_length=50,
|
|
52
56
|
blank=True,
|
|
53
57
|
)
|
|
@@ -59,8 +63,8 @@ class Registrar(NetBoxModel):
|
|
|
59
63
|
return str(self.name)
|
|
60
64
|
|
|
61
65
|
class Meta:
|
|
62
|
-
verbose_name = "Registrar"
|
|
63
|
-
verbose_name_plural = "Registrars"
|
|
66
|
+
verbose_name = _("Registrar")
|
|
67
|
+
verbose_name_plural = _("Registrars")
|
|
64
68
|
|
|
65
69
|
ordering = (
|
|
66
70
|
"name",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from django.db import models
|
|
2
2
|
from django.urls import reverse
|
|
3
|
+
from django.utils.translation import gettext_lazy as _
|
|
3
4
|
|
|
4
5
|
from netbox.models import NetBoxModel
|
|
5
6
|
from netbox.search import SearchIndex, register_search
|
|
@@ -18,70 +19,81 @@ class RegistrationContact(NetBoxModel):
|
|
|
18
19
|
# Data fields according to https://www.icann.org/resources/pages/rdds-labeling-policy-2017-02-01-en
|
|
19
20
|
# -
|
|
20
21
|
contact_id = models.CharField(
|
|
21
|
-
verbose_name="Contact ID",
|
|
22
|
+
verbose_name=_("Contact ID"),
|
|
22
23
|
max_length=50,
|
|
23
24
|
unique=True,
|
|
24
25
|
)
|
|
25
26
|
name = models.CharField(
|
|
27
|
+
verbose_name=_("Name"),
|
|
26
28
|
blank=True,
|
|
27
29
|
max_length=100,
|
|
28
30
|
)
|
|
29
31
|
description = models.CharField(
|
|
32
|
+
verbose_name=_("Description"),
|
|
30
33
|
blank=True,
|
|
31
34
|
max_length=200,
|
|
32
35
|
)
|
|
33
36
|
organization = models.CharField(
|
|
37
|
+
verbose_name=_("Organization"),
|
|
34
38
|
blank=True,
|
|
35
39
|
max_length=200,
|
|
36
40
|
)
|
|
37
41
|
street = models.CharField(
|
|
42
|
+
verbose_name=_("Street"),
|
|
38
43
|
blank=True,
|
|
39
44
|
max_length=50,
|
|
40
45
|
)
|
|
41
46
|
city = models.CharField(
|
|
47
|
+
verbose_name=_("City"),
|
|
42
48
|
blank=True,
|
|
43
49
|
max_length=50,
|
|
44
50
|
)
|
|
45
51
|
state_province = models.CharField(
|
|
46
|
-
verbose_name="State/Province",
|
|
52
|
+
verbose_name=_("State/Province"),
|
|
47
53
|
blank=True,
|
|
48
54
|
max_length=255,
|
|
49
55
|
)
|
|
50
56
|
postal_code = models.CharField(
|
|
51
|
-
verbose_name="Postal Code",
|
|
57
|
+
verbose_name=_("Postal Code"),
|
|
52
58
|
blank=True,
|
|
53
59
|
max_length=20,
|
|
54
60
|
)
|
|
55
61
|
country = models.CharField(
|
|
56
|
-
verbose_name="Country (ISO 3166)",
|
|
62
|
+
verbose_name=_("Country (ISO 3166)"),
|
|
57
63
|
blank=True,
|
|
58
64
|
max_length=2,
|
|
59
65
|
)
|
|
60
66
|
phone = models.CharField(
|
|
61
|
-
verbose_name="Phone",
|
|
67
|
+
verbose_name=_("Phone"),
|
|
62
68
|
blank=True,
|
|
63
69
|
max_length=50,
|
|
64
70
|
)
|
|
65
71
|
phone_ext = models.CharField(
|
|
66
|
-
verbose_name="Phone Extension",
|
|
72
|
+
verbose_name=_("Phone Extension"),
|
|
67
73
|
blank=True,
|
|
68
74
|
max_length=50,
|
|
69
75
|
)
|
|
70
76
|
fax = models.CharField(
|
|
71
|
-
verbose_name="Fax",
|
|
77
|
+
verbose_name=_("Fax"),
|
|
72
78
|
blank=True,
|
|
73
79
|
max_length=50,
|
|
74
80
|
)
|
|
75
81
|
fax_ext = models.CharField(
|
|
76
|
-
verbose_name="Fax Extension",
|
|
82
|
+
verbose_name=_("Fax Extension"),
|
|
77
83
|
blank=True,
|
|
78
84
|
max_length=50,
|
|
79
85
|
)
|
|
80
86
|
email = models.EmailField(
|
|
81
|
-
verbose_name="Email",
|
|
87
|
+
verbose_name=_("Email"),
|
|
82
88
|
blank=True,
|
|
83
89
|
)
|
|
84
90
|
|
|
91
|
+
# +
|
|
92
|
+
# TODO: Retained for backwards compatibility with older versions where
|
|
93
|
+
# 'RegistrationContact' was still ambiguously named 'Contact'.
|
|
94
|
+
#
|
|
95
|
+
# Removing it requires a data migration.
|
|
96
|
+
# -
|
|
85
97
|
tags = TaggableManager(
|
|
86
98
|
through="extras.TaggedItem",
|
|
87
99
|
related_name="netbox_dns_contact_set",
|
|
@@ -114,8 +126,8 @@ class RegistrationContact(NetBoxModel):
|
|
|
114
126
|
return self.contact_id
|
|
115
127
|
|
|
116
128
|
class Meta:
|
|
117
|
-
verbose_name = "Registration Contact"
|
|
118
|
-
verbose_name_plural = "Registration Contacts"
|
|
129
|
+
verbose_name = _("Registration Contact")
|
|
130
|
+
verbose_name_plural = _("Registration Contacts")
|
|
119
131
|
|
|
120
132
|
ordering = (
|
|
121
133
|
"name",
|