netbox-plugin-dns 1.0b2__py3-none-any.whl → 1.0.2__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 +3 -3
- netbox_dns/api/serializers_/view.py +6 -1
- netbox_dns/fields/network.py +20 -21
- netbox_dns/fields/rfc2317.py +2 -2
- netbox_dns/filtersets/view.py +1 -1
- netbox_dns/filtersets/zone.py +4 -4
- netbox_dns/forms/record.py +30 -2
- netbox_dns/forms/view.py +6 -3
- netbox_dns/forms/zone.py +71 -102
- netbox_dns/graphql/types.py +1 -4
- netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +4 -2
- netbox_dns/migrations/0003_default_view.py +15 -0
- netbox_dns/migrations/0004_create_and_assign_default_view.py +26 -0
- netbox_dns/migrations/0005_alter_zone_view_not_null.py +18 -0
- netbox_dns/mixins/__init__.py +1 -0
- netbox_dns/mixins/object_modification.py +26 -0
- netbox_dns/models/nameserver.py +7 -6
- netbox_dns/models/record.py +94 -35
- netbox_dns/models/view.py +56 -1
- netbox_dns/models/zone.py +101 -67
- netbox_dns/signals/ipam_coupling.py +1 -2
- netbox_dns/tables/view.py +12 -2
- netbox_dns/template_content.py +1 -1
- netbox_dns/templates/netbox_dns/record.html +1 -1
- netbox_dns/templates/netbox_dns/view.html +4 -0
- netbox_dns/templates/netbox_dns/zone.html +2 -4
- netbox_dns/urls/__init__.py +17 -0
- netbox_dns/urls/contact.py +51 -0
- netbox_dns/urls/nameserver.py +69 -0
- netbox_dns/urls/record.py +41 -0
- netbox_dns/urls/registrar.py +63 -0
- netbox_dns/urls/view.py +39 -0
- netbox_dns/urls/zone.py +57 -0
- netbox_dns/validators/dns_name.py +24 -11
- netbox_dns/views/record.py +10 -18
- {netbox_plugin_dns-1.0b2.dist-info → netbox_plugin_dns-1.0.2.dist-info}/LICENSE +2 -1
- {netbox_plugin_dns-1.0b2.dist-info → netbox_plugin_dns-1.0.2.dist-info}/METADATA +15 -14
- {netbox_plugin_dns-1.0b2.dist-info → netbox_plugin_dns-1.0.2.dist-info}/RECORD +39 -28
- netbox_dns/urls.py +0 -297
- {netbox_plugin_dns-1.0b2.dist-info → netbox_plugin_dns-1.0.2.dist-info}/WHEEL +0 -0
netbox_dns/models/zone.py
CHANGED
|
@@ -15,15 +15,15 @@ from django.db.models import Q, Max, ExpressionWrapper, BooleanField
|
|
|
15
15
|
from django.urls import reverse
|
|
16
16
|
from django.db.models.signals import m2m_changed
|
|
17
17
|
from django.dispatch import receiver
|
|
18
|
+
from django.conf import settings
|
|
18
19
|
|
|
19
20
|
from netbox.models import NetBoxModel
|
|
20
21
|
from netbox.search import SearchIndex, register_search
|
|
22
|
+
from netbox.plugins.utils import get_plugin_config
|
|
21
23
|
from utilities.querysets import RestrictedQuerySet
|
|
22
24
|
from utilities.choices import ChoiceSet
|
|
23
25
|
from ipam.models import IPAddress
|
|
24
26
|
|
|
25
|
-
from netbox.plugins.utils import get_plugin_config
|
|
26
|
-
|
|
27
27
|
from netbox_dns.fields import NetworkField, RFC2317NetworkField
|
|
28
28
|
from netbox_dns.utilities import (
|
|
29
29
|
arpa_to_prefix,
|
|
@@ -35,11 +35,14 @@ from netbox_dns.validators import (
|
|
|
35
35
|
validate_fqdn,
|
|
36
36
|
validate_domain_name,
|
|
37
37
|
)
|
|
38
|
+
from netbox_dns.mixins import ObjectModificationMixin
|
|
38
39
|
|
|
39
40
|
# +
|
|
40
|
-
# This is a hack designed to break cyclic imports between Record and Zone
|
|
41
|
+
# This is a hack designed to break cyclic imports between View, Record and Zone
|
|
41
42
|
# -
|
|
42
43
|
import netbox_dns.models.record as record
|
|
44
|
+
import netbox_dns.models.view as view
|
|
45
|
+
import netbox_dns.models.nameserver as nameserver
|
|
43
46
|
|
|
44
47
|
|
|
45
48
|
class ZoneManager(models.Manager.from_queryset(RestrictedQuerySet)):
|
|
@@ -75,14 +78,13 @@ class ZoneStatusChoices(ChoiceSet):
|
|
|
75
78
|
]
|
|
76
79
|
|
|
77
80
|
|
|
78
|
-
class Zone(NetBoxModel):
|
|
81
|
+
class Zone(ObjectModificationMixin, NetBoxModel):
|
|
79
82
|
ACTIVE_STATUS_LIST = (ZoneStatusChoices.STATUS_ACTIVE,)
|
|
80
83
|
|
|
81
84
|
view = models.ForeignKey(
|
|
82
85
|
to="View",
|
|
83
86
|
on_delete=models.PROTECT,
|
|
84
|
-
|
|
85
|
-
null=True,
|
|
87
|
+
null=False,
|
|
86
88
|
)
|
|
87
89
|
name = models.CharField(
|
|
88
90
|
max_length=255,
|
|
@@ -285,11 +287,20 @@ class Zone(NetBoxModel):
|
|
|
285
287
|
except dns_name.IDNAException:
|
|
286
288
|
name = self.name
|
|
287
289
|
|
|
288
|
-
if self.view:
|
|
290
|
+
if not self.view.default_view:
|
|
289
291
|
return f"[{self.view}] {name}"
|
|
290
292
|
|
|
291
293
|
return str(name)
|
|
292
294
|
|
|
295
|
+
@staticmethod
|
|
296
|
+
def get_defaults():
|
|
297
|
+
return {
|
|
298
|
+
field[5:]: value
|
|
299
|
+
for field, value in settings.PLUGINS_CONFIG.get("netbox_dns").items()
|
|
300
|
+
if field.startswith("zone_")
|
|
301
|
+
and field not in ("zone_soa_mname", "zone_nameservers")
|
|
302
|
+
}
|
|
303
|
+
|
|
293
304
|
@property
|
|
294
305
|
def display_name(self):
|
|
295
306
|
return name_to_unicode(self.name)
|
|
@@ -317,11 +328,11 @@ class Zone(NetBoxModel):
|
|
|
317
328
|
|
|
318
329
|
def get_rfc2317_parent_zone(self):
|
|
319
330
|
if not self.is_rfc2317_zone:
|
|
320
|
-
return
|
|
331
|
+
return None
|
|
321
332
|
|
|
322
333
|
return (
|
|
323
334
|
Zone.objects.filter(
|
|
324
|
-
self.
|
|
335
|
+
view=self.view,
|
|
325
336
|
arpa_network__net_contains=self.rfc2317_prefix,
|
|
326
337
|
)
|
|
327
338
|
.order_by("arpa_network__net_mask_length")
|
|
@@ -342,12 +353,6 @@ class Zone(NetBoxModel):
|
|
|
342
353
|
)
|
|
343
354
|
)
|
|
344
355
|
|
|
345
|
-
@property
|
|
346
|
-
def view_filter(self):
|
|
347
|
-
if self.view is None:
|
|
348
|
-
return Q(view__isnull=True)
|
|
349
|
-
return Q(view=self.view)
|
|
350
|
-
|
|
351
356
|
def record_count(self, managed=False):
|
|
352
357
|
return record.Record.objects.filter(zone=self, managed=managed).count()
|
|
353
358
|
|
|
@@ -417,19 +422,15 @@ class Zone(NetBoxModel):
|
|
|
417
422
|
if not nameservers:
|
|
418
423
|
ns_errors.append(f"No nameservers are configured for zone {self}")
|
|
419
424
|
|
|
420
|
-
for
|
|
421
|
-
name = dns_name.from_text(
|
|
425
|
+
for _nameserver in nameservers:
|
|
426
|
+
name = dns_name.from_text(_nameserver.name, origin=None)
|
|
422
427
|
parent = name.parent()
|
|
423
428
|
|
|
424
429
|
if len(parent) < 2:
|
|
425
430
|
continue
|
|
426
431
|
|
|
427
|
-
view_condition = (
|
|
428
|
-
Q(view__isnull=True) if self.view is None else Q(view_id=self.view.pk)
|
|
429
|
-
)
|
|
430
|
-
|
|
431
432
|
try:
|
|
432
|
-
ns_zone = Zone.objects.get(
|
|
433
|
+
ns_zone = Zone.objects.get(view_id=self.view.pk, name=parent.to_text())
|
|
433
434
|
except ObjectDoesNotExist:
|
|
434
435
|
continue
|
|
435
436
|
|
|
@@ -437,7 +438,7 @@ class Zone(NetBoxModel):
|
|
|
437
438
|
address_records = record.Record.objects.filter(
|
|
438
439
|
Q(zone=ns_zone),
|
|
439
440
|
Q(status__in=record.Record.ACTIVE_STATUS_LIST),
|
|
440
|
-
Q(Q(name=f"{
|
|
441
|
+
Q(Q(name=f"{_nameserver.name}.") | Q(name=relative_name)),
|
|
441
442
|
Q(
|
|
442
443
|
Q(type=record.RecordTypeChoices.A)
|
|
443
444
|
| Q(type=record.RecordTypeChoices.AAAA)
|
|
@@ -446,11 +447,23 @@ class Zone(NetBoxModel):
|
|
|
446
447
|
|
|
447
448
|
if not address_records:
|
|
448
449
|
ns_warnings.append(
|
|
449
|
-
f"Nameserver {
|
|
450
|
+
f"Nameserver {_nameserver.name} does not have an active address record in zone {ns_zone}"
|
|
450
451
|
)
|
|
451
452
|
|
|
452
453
|
return ns_warnings, ns_errors
|
|
453
454
|
|
|
455
|
+
def check_soa_serial_increment(self, old_serial, new_serial):
|
|
456
|
+
MAX_SOA_SERIAL_INCREMENT = 2**31 - 1
|
|
457
|
+
SOA_SERIAL_WRAP = 2**32
|
|
458
|
+
|
|
459
|
+
if old_serial is None:
|
|
460
|
+
return
|
|
461
|
+
|
|
462
|
+
if (new_serial - old_serial) % SOA_SERIAL_WRAP > MAX_SOA_SERIAL_INCREMENT:
|
|
463
|
+
raise ValidationError(
|
|
464
|
+
{"soa_serial": f"soa_serial must not decrease for zone {self.name}."}
|
|
465
|
+
)
|
|
466
|
+
|
|
454
467
|
def get_auto_serial(self):
|
|
455
468
|
records = record.Record.objects.filter(zone_id=self.pk).exclude(
|
|
456
469
|
type=record.RecordTypeChoices.SOA
|
|
@@ -492,19 +505,6 @@ class Zone(NetBoxModel):
|
|
|
492
505
|
def network_from_name(self):
|
|
493
506
|
return arpa_to_prefix(self.name)
|
|
494
507
|
|
|
495
|
-
def check_name_conflict(self):
|
|
496
|
-
if self.view is None:
|
|
497
|
-
if (
|
|
498
|
-
Zone.objects.exclude(pk=self.pk)
|
|
499
|
-
.filter(name=self.name.rstrip("."), view__isnull=True)
|
|
500
|
-
.exists()
|
|
501
|
-
):
|
|
502
|
-
raise ValidationError(
|
|
503
|
-
{
|
|
504
|
-
"name": f"A zone with name {self.name} and no view already exists."
|
|
505
|
-
}
|
|
506
|
-
)
|
|
507
|
-
|
|
508
508
|
def update_rfc2317_parent_zone(self):
|
|
509
509
|
if not self.is_rfc2317_zone:
|
|
510
510
|
return
|
|
@@ -555,8 +555,33 @@ class Zone(NetBoxModel):
|
|
|
555
555
|
ptr_zone.save_soa_serial()
|
|
556
556
|
ptr_zone.update_soa_record()
|
|
557
557
|
|
|
558
|
+
def clean_fields(self, exclude=None):
|
|
559
|
+
defaults = settings.PLUGINS_CONFIG.get("netbox_dns")
|
|
560
|
+
|
|
561
|
+
if self.view_id is None:
|
|
562
|
+
self.view_id = view.View.get_default_view().pk
|
|
563
|
+
|
|
564
|
+
for field, value in self.get_defaults().items():
|
|
565
|
+
if getattr(self, field) in (None, ""):
|
|
566
|
+
if value not in (None, ""):
|
|
567
|
+
setattr(self, field, value)
|
|
568
|
+
|
|
569
|
+
if self.soa_mname_id is None:
|
|
570
|
+
default_soa_mname = defaults.get("zone_soa_mname")
|
|
571
|
+
try:
|
|
572
|
+
self.soa_mname = nameserver.NameServer.objects.get(
|
|
573
|
+
name=default_soa_mname
|
|
574
|
+
)
|
|
575
|
+
except nameserver.NameServer.DoesNotExist:
|
|
576
|
+
raise ValidationError(
|
|
577
|
+
f"Default soa_mname instance {default_soa_mname} does not exist"
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
super().clean_fields(exclude=exclude)
|
|
581
|
+
|
|
558
582
|
def clean(self, *args, **kwargs):
|
|
559
|
-
self.
|
|
583
|
+
if self.soa_ttl is None:
|
|
584
|
+
self.soa_ttl = self.default_ttl
|
|
560
585
|
|
|
561
586
|
try:
|
|
562
587
|
self.name = normalize_name(self.name)
|
|
@@ -576,6 +601,8 @@ class Zone(NetBoxModel):
|
|
|
576
601
|
}
|
|
577
602
|
) from None
|
|
578
603
|
|
|
604
|
+
if self.soa_rname in (None, ""):
|
|
605
|
+
raise ValidationError("soa_rname not set and no default value defined")
|
|
579
606
|
try:
|
|
580
607
|
dns_name.from_text(self.soa_rname, origin=dns_name.root)
|
|
581
608
|
validate_fqdn(self.soa_rname)
|
|
@@ -586,12 +613,29 @@ class Zone(NetBoxModel):
|
|
|
586
613
|
}
|
|
587
614
|
) from None
|
|
588
615
|
|
|
589
|
-
if
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
616
|
+
if not self.soa_serial_auto:
|
|
617
|
+
if self.soa_serial is None:
|
|
618
|
+
raise ValidationError(
|
|
619
|
+
{
|
|
620
|
+
"soa_serial": f"soa_serial is not defined and soa_serial_auto is disabled for zone {self.name}."
|
|
621
|
+
}
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
if self.pk is not None:
|
|
625
|
+
old_zone = Zone.objects.get(pk=self.pk)
|
|
626
|
+
if not self.soa_serial_auto:
|
|
627
|
+
self.check_soa_serial_increment(old_zone.soa_serial, self.soa_serial)
|
|
628
|
+
else:
|
|
629
|
+
try:
|
|
630
|
+
self.check_soa_serial_increment(
|
|
631
|
+
old_zone.soa_serial, self.get_auto_serial()
|
|
632
|
+
)
|
|
633
|
+
except ValidationError:
|
|
634
|
+
raise ValidationError(
|
|
635
|
+
{
|
|
636
|
+
"soa_serial_auto": f"Enabling soa_serial_auto would decrease soa_serial for zone {self.name}."
|
|
637
|
+
}
|
|
638
|
+
)
|
|
595
639
|
|
|
596
640
|
if self.is_reverse_zone:
|
|
597
641
|
self.arpa_network = self.network_from_name
|
|
@@ -619,7 +663,7 @@ class Zone(NetBoxModel):
|
|
|
619
663
|
self.rfc2317_parent_zone = None
|
|
620
664
|
|
|
621
665
|
overlapping_zones = Zone.objects.filter(
|
|
622
|
-
self.
|
|
666
|
+
view=self.view,
|
|
623
667
|
rfc2317_prefix__net_overlap=self.rfc2317_prefix,
|
|
624
668
|
active=True,
|
|
625
669
|
).exclude(pk=self.pk)
|
|
@@ -635,20 +679,12 @@ class Zone(NetBoxModel):
|
|
|
635
679
|
self.rfc2317_parent_managed = False
|
|
636
680
|
self.rfc2317_parent_zone = None
|
|
637
681
|
|
|
682
|
+
super().clean(*args, **kwargs)
|
|
683
|
+
|
|
638
684
|
def save(self, *args, **kwargs):
|
|
639
685
|
self.full_clean()
|
|
640
686
|
|
|
641
|
-
|
|
642
|
-
if not new_zone:
|
|
643
|
-
old_zone = Zone.objects.get(pk=self.pk)
|
|
644
|
-
|
|
645
|
-
name_changed = not new_zone and old_zone.name != self.name
|
|
646
|
-
view_changed = not new_zone and old_zone.view != self.view
|
|
647
|
-
status_changed = not new_zone and old_zone.status != self.status
|
|
648
|
-
rfc2317_changed = not new_zone and (
|
|
649
|
-
old_zone.rfc2317_prefix != self.rfc2317_prefix
|
|
650
|
-
or old_zone.rfc2317_parent_managed != self.rfc2317_parent_managed
|
|
651
|
-
)
|
|
687
|
+
changed_fields = self.changed_fields
|
|
652
688
|
|
|
653
689
|
if self.soa_serial_auto:
|
|
654
690
|
self.soa_serial = self.get_auto_serial()
|
|
@@ -656,10 +692,10 @@ class Zone(NetBoxModel):
|
|
|
656
692
|
super().save(*args, **kwargs)
|
|
657
693
|
|
|
658
694
|
if (
|
|
659
|
-
|
|
695
|
+
changed_fields is None or {"name", "view", "status"} & changed_fields
|
|
660
696
|
) and self.is_reverse_zone:
|
|
661
697
|
zones = Zone.objects.filter(
|
|
662
|
-
self.
|
|
698
|
+
view=self.view,
|
|
663
699
|
arpa_network__net_contains_or_equals=self.arpa_network,
|
|
664
700
|
)
|
|
665
701
|
address_records = record.Record.objects.filter(
|
|
@@ -688,14 +724,12 @@ class Zone(NetBoxModel):
|
|
|
688
724
|
child_zone.update_rfc2317_parent_zone()
|
|
689
725
|
|
|
690
726
|
if (
|
|
691
|
-
|
|
692
|
-
or
|
|
693
|
-
|
|
694
|
-
or status_changed
|
|
695
|
-
or rfc2317_changed
|
|
727
|
+
changed_fields is None
|
|
728
|
+
or {"name", "view", "status", "rfc2317_prefix", "rfc2317_parent_managed"}
|
|
729
|
+
& changed_fields
|
|
696
730
|
) and self.is_rfc2317_zone:
|
|
697
731
|
zones = Zone.objects.filter(
|
|
698
|
-
self.
|
|
732
|
+
view=self.view,
|
|
699
733
|
arpa_network__net_contains=self.rfc2317_prefix,
|
|
700
734
|
)
|
|
701
735
|
address_records = record.Record.objects.filter(
|
|
@@ -718,7 +752,7 @@ class Zone(NetBoxModel):
|
|
|
718
752
|
|
|
719
753
|
self.update_rfc2317_parent_zone()
|
|
720
754
|
|
|
721
|
-
elif
|
|
755
|
+
elif changed_fields is not None and {"name", "view", "status"} & changed_fields:
|
|
722
756
|
for address_record in self.record_set.filter(
|
|
723
757
|
type__in=(record.RecordTypeChoices.A, record.RecordTypeChoices.AAAA)
|
|
724
758
|
):
|
|
@@ -727,7 +761,7 @@ class Zone(NetBoxModel):
|
|
|
727
761
|
# Fix name in IP Address when zone name is changed
|
|
728
762
|
if (
|
|
729
763
|
get_plugin_config("netbox_dns", "feature_ipam_coupling")
|
|
730
|
-
and
|
|
764
|
+
and "name" in changed_fields
|
|
731
765
|
):
|
|
732
766
|
for ip in IPAddress.objects.filter(
|
|
733
767
|
custom_field_data__ipaddress_dns_zone_id=self.pk
|
|
@@ -735,7 +769,7 @@ class Zone(NetBoxModel):
|
|
|
735
769
|
ip.dns_name = f'{ip.custom_field_data["ipaddress_dns_record_name"]}.{self.name}'
|
|
736
770
|
ip.save(update_fields=["dns_name"])
|
|
737
771
|
|
|
738
|
-
if
|
|
772
|
+
if changed_fields is not None and "name" in changed_fields:
|
|
739
773
|
for _record in self.record_set.all():
|
|
740
774
|
_record.save(
|
|
741
775
|
update_fields=["fqdn"],
|
|
@@ -5,6 +5,7 @@ from rest_framework.exceptions import PermissionDenied as APIPermissionDenied
|
|
|
5
5
|
|
|
6
6
|
from netbox.signals import post_clean
|
|
7
7
|
from netbox.context import current_request
|
|
8
|
+
from netbox.plugins.utils import get_plugin_config
|
|
8
9
|
from ipam.models import IPAddress
|
|
9
10
|
|
|
10
11
|
from netbox_dns.models import Zone
|
|
@@ -18,8 +19,6 @@ from netbox_dns.utilities.ipam_coupling import (
|
|
|
18
19
|
DNSPermissionDenied,
|
|
19
20
|
)
|
|
20
21
|
|
|
21
|
-
from netbox.plugins.utils import get_plugin_config
|
|
22
|
-
|
|
23
22
|
|
|
24
23
|
@receiver(post_clean, sender=IPAddress)
|
|
25
24
|
def ip_address_check_permissions_save(instance, **kwargs):
|
netbox_dns/tables/view.py
CHANGED
|
@@ -10,9 +10,19 @@ class ViewTable(TenancyColumnsMixin, NetBoxTable):
|
|
|
10
10
|
name = tables.Column(
|
|
11
11
|
linkify=True,
|
|
12
12
|
)
|
|
13
|
+
default_view = tables.BooleanColumn(
|
|
14
|
+
verbose_name="Default View",
|
|
15
|
+
)
|
|
13
16
|
tags = TagColumn(url_name="plugins:netbox_dns:view_list")
|
|
14
17
|
|
|
15
18
|
class Meta(NetBoxTable.Meta):
|
|
16
19
|
model = View
|
|
17
|
-
fields = (
|
|
18
|
-
|
|
20
|
+
fields = (
|
|
21
|
+
"name",
|
|
22
|
+
"default_view",
|
|
23
|
+
"description",
|
|
24
|
+
"tenant",
|
|
25
|
+
"tenant_group",
|
|
26
|
+
"tags",
|
|
27
|
+
)
|
|
28
|
+
default_columns = ("name", "default_view")
|
netbox_dns/template_content.py
CHANGED
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
<td>{{ unicode_name }}</td>
|
|
21
21
|
</tr>
|
|
22
22
|
{% endif %}
|
|
23
|
-
{% if object.view %}
|
|
24
23
|
<tr>
|
|
25
24
|
<th scope="row">View</th>
|
|
26
25
|
<td>
|
|
@@ -29,7 +28,6 @@
|
|
|
29
28
|
</a>
|
|
30
29
|
</td>
|
|
31
30
|
</tr>
|
|
32
|
-
{% endif %}
|
|
33
31
|
{% if object.description %}
|
|
34
32
|
<tr>
|
|
35
33
|
<th scope="row">Description</th>
|
|
@@ -116,11 +114,11 @@
|
|
|
116
114
|
<td>{{ object.soa_ttl }}</td>
|
|
117
115
|
</tr>
|
|
118
116
|
<tr>
|
|
119
|
-
<th scope="row">
|
|
117
|
+
<th scope="row">MName</th>
|
|
120
118
|
<td><a href="{% url 'plugins:netbox_dns:nameserver' pk=object.soa_mname.pk %}">{{ object.soa_mname }}</a></td>
|
|
121
119
|
</tr>
|
|
122
120
|
<tr>
|
|
123
|
-
<th scope="row">
|
|
121
|
+
<th scope="row">RName</th>
|
|
124
122
|
<td>{{ object.soa_rname }}</td>
|
|
125
123
|
</tr>
|
|
126
124
|
{% if object.soa_serial_auto %}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from .contact import contact_urlpatterns
|
|
2
|
+
from .nameserver import nameserver_urlpatterns
|
|
3
|
+
from .record import record_urlpatterns
|
|
4
|
+
from .registrar import registrar_urlpatterns
|
|
5
|
+
from .view import view_urlpatterns
|
|
6
|
+
from .zone import zone_urlpatterns
|
|
7
|
+
|
|
8
|
+
app_name = "netbox_dns"
|
|
9
|
+
|
|
10
|
+
urlpatterns = (
|
|
11
|
+
contact_urlpatterns
|
|
12
|
+
+ nameserver_urlpatterns
|
|
13
|
+
+ record_urlpatterns
|
|
14
|
+
+ registrar_urlpatterns
|
|
15
|
+
+ view_urlpatterns
|
|
16
|
+
+ zone_urlpatterns
|
|
17
|
+
)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from django.urls import path
|
|
2
|
+
|
|
3
|
+
from netbox.views.generic import ObjectChangeLogView, ObjectJournalView
|
|
4
|
+
|
|
5
|
+
from netbox_dns.models import Contact
|
|
6
|
+
from netbox_dns.views import (
|
|
7
|
+
ContactListView,
|
|
8
|
+
ContactView,
|
|
9
|
+
ContactDeleteView,
|
|
10
|
+
ContactEditView,
|
|
11
|
+
ContactBulkImportView,
|
|
12
|
+
ContactBulkEditView,
|
|
13
|
+
ContactBulkDeleteView,
|
|
14
|
+
ContactZoneListView,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
contact_urlpatterns = [
|
|
18
|
+
path("contacts/", ContactListView.as_view(), name="contact_list"),
|
|
19
|
+
path("contacts/add/", ContactEditView.as_view(), name="contact_add"),
|
|
20
|
+
path("contacts/import/", ContactBulkImportView.as_view(), name="contact_import"),
|
|
21
|
+
path("contacts/edit/", ContactBulkEditView.as_view(), name="contact_bulk_edit"),
|
|
22
|
+
path(
|
|
23
|
+
"contacts/delete/",
|
|
24
|
+
ContactBulkDeleteView.as_view(),
|
|
25
|
+
name="contact_bulk_delete",
|
|
26
|
+
),
|
|
27
|
+
path("contacts/<int:pk>/", ContactView.as_view(), name="contact"),
|
|
28
|
+
path("contacts/<int:pk>/edit/", ContactEditView.as_view(), name="contact_edit"),
|
|
29
|
+
path(
|
|
30
|
+
"contacts/<int:pk>/delete/",
|
|
31
|
+
ContactDeleteView.as_view(),
|
|
32
|
+
name="contact_delete",
|
|
33
|
+
),
|
|
34
|
+
path(
|
|
35
|
+
"contacts/<int:pk>/zones/",
|
|
36
|
+
ContactZoneListView.as_view(),
|
|
37
|
+
name="contact_zones",
|
|
38
|
+
),
|
|
39
|
+
path(
|
|
40
|
+
"contacts/<int:pk>/journal/",
|
|
41
|
+
ObjectJournalView.as_view(),
|
|
42
|
+
name="contact_journal",
|
|
43
|
+
kwargs={"model": Contact},
|
|
44
|
+
),
|
|
45
|
+
path(
|
|
46
|
+
"contacts/<int:pk>/changelog/",
|
|
47
|
+
ObjectChangeLogView.as_view(),
|
|
48
|
+
name="contact_changelog",
|
|
49
|
+
kwargs={"model": Contact},
|
|
50
|
+
),
|
|
51
|
+
]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from django.urls import path
|
|
2
|
+
|
|
3
|
+
from netbox.views.generic import ObjectChangeLogView, ObjectJournalView
|
|
4
|
+
|
|
5
|
+
from netbox_dns.models import NameServer
|
|
6
|
+
from netbox_dns.views import (
|
|
7
|
+
NameServerListView,
|
|
8
|
+
NameServerView,
|
|
9
|
+
NameServerEditView,
|
|
10
|
+
NameServerDeleteView,
|
|
11
|
+
NameServerBulkImportView,
|
|
12
|
+
NameServerBulkEditView,
|
|
13
|
+
NameServerBulkDeleteView,
|
|
14
|
+
NameServerZoneListView,
|
|
15
|
+
NameServerSOAZoneListView,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
nameserver_urlpatterns = [
|
|
19
|
+
path("nameservers/", NameServerListView.as_view(), name="nameserver_list"),
|
|
20
|
+
path("nameservers/add/", NameServerEditView.as_view(), name="nameserver_add"),
|
|
21
|
+
path(
|
|
22
|
+
"nameservers/import/",
|
|
23
|
+
NameServerBulkImportView.as_view(),
|
|
24
|
+
name="nameserver_import",
|
|
25
|
+
),
|
|
26
|
+
path(
|
|
27
|
+
"nameservers/edit/",
|
|
28
|
+
NameServerBulkEditView.as_view(),
|
|
29
|
+
name="nameserver_bulk_edit",
|
|
30
|
+
),
|
|
31
|
+
path(
|
|
32
|
+
"nameservers/delete/",
|
|
33
|
+
NameServerBulkDeleteView.as_view(),
|
|
34
|
+
name="nameserver_bulk_delete",
|
|
35
|
+
),
|
|
36
|
+
path("nameservers/<int:pk>/", NameServerView.as_view(), name="nameserver"),
|
|
37
|
+
path(
|
|
38
|
+
"nameservers/<int:pk>/edit",
|
|
39
|
+
NameServerEditView.as_view(),
|
|
40
|
+
name="nameserver_edit",
|
|
41
|
+
),
|
|
42
|
+
path(
|
|
43
|
+
"nameservers/<int:pk>/delete",
|
|
44
|
+
NameServerDeleteView.as_view(),
|
|
45
|
+
name="nameserver_delete",
|
|
46
|
+
),
|
|
47
|
+
path(
|
|
48
|
+
"nameservers/<int:pk>/journal/",
|
|
49
|
+
ObjectJournalView.as_view(),
|
|
50
|
+
name="nameserver_journal",
|
|
51
|
+
kwargs={"model": NameServer},
|
|
52
|
+
),
|
|
53
|
+
path(
|
|
54
|
+
"nameservers/<int:pk>/changelog/",
|
|
55
|
+
ObjectChangeLogView.as_view(),
|
|
56
|
+
name="nameserver_changelog",
|
|
57
|
+
kwargs={"model": NameServer},
|
|
58
|
+
),
|
|
59
|
+
path(
|
|
60
|
+
"nameservers/<int:pk>/zones/",
|
|
61
|
+
NameServerZoneListView.as_view(),
|
|
62
|
+
name="nameserver_zones",
|
|
63
|
+
),
|
|
64
|
+
path(
|
|
65
|
+
"nameservers/<int:pk>/soazones/",
|
|
66
|
+
NameServerSOAZoneListView.as_view(),
|
|
67
|
+
name="nameserver_soa_zones",
|
|
68
|
+
),
|
|
69
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from django.urls import path
|
|
2
|
+
|
|
3
|
+
from netbox.views.generic import ObjectChangeLogView, ObjectJournalView
|
|
4
|
+
|
|
5
|
+
from netbox_dns.models import Record
|
|
6
|
+
from netbox_dns.views import (
|
|
7
|
+
RecordListView,
|
|
8
|
+
RecordView,
|
|
9
|
+
RecordEditView,
|
|
10
|
+
RecordDeleteView,
|
|
11
|
+
RecordBulkImportView,
|
|
12
|
+
RecordBulkEditView,
|
|
13
|
+
RecordBulkDeleteView,
|
|
14
|
+
ManagedRecordListView,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
record_urlpatterns = [
|
|
18
|
+
path("records/", RecordListView.as_view(), name="record_list"),
|
|
19
|
+
path("records/add/", RecordEditView.as_view(), name="record_add"),
|
|
20
|
+
path("records/import/", RecordBulkImportView.as_view(), name="record_import"),
|
|
21
|
+
path("records/edit/", RecordBulkEditView.as_view(), name="record_bulk_edit"),
|
|
22
|
+
path("records/delete/", RecordBulkDeleteView.as_view(), name="record_bulk_delete"),
|
|
23
|
+
path("records/<int:pk>/", RecordView.as_view(), name="record"),
|
|
24
|
+
path("records/<int:pk>/edit/", RecordEditView.as_view(), name="record_edit"),
|
|
25
|
+
path("records/<int:pk>/delete/", RecordDeleteView.as_view(), name="record_delete"),
|
|
26
|
+
path(
|
|
27
|
+
"records/<int:pk>/journal/",
|
|
28
|
+
ObjectJournalView.as_view(),
|
|
29
|
+
name="record_journal",
|
|
30
|
+
kwargs={"model": Record},
|
|
31
|
+
),
|
|
32
|
+
path(
|
|
33
|
+
"records/<int:pk>/changelog/",
|
|
34
|
+
ObjectChangeLogView.as_view(),
|
|
35
|
+
name="record_changelog",
|
|
36
|
+
kwargs={"model": Record},
|
|
37
|
+
),
|
|
38
|
+
path(
|
|
39
|
+
"managedrecords/", ManagedRecordListView.as_view(), name="managed_record_list"
|
|
40
|
+
),
|
|
41
|
+
]
|