From c86a74ec30bf0ace77f88b3ccf0d41e076df3b2b Mon Sep 17 00:00:00 2001 From: rdujardin Date: Thu, 18 Aug 2016 17:55:37 +0200 Subject: [PATCH] Add 'extra_conf' field to DNS zones and reverse DNS zones (i.e. prefixes) --- netbox/dns/api/serializers.py | 2 +- netbox/dns/forms.py | 12 ++++++++--- netbox/dns/migrations/0006_zone_extra_conf.py | 20 +++++++++++++++++++ netbox/dns/models.py | 8 ++++++-- netbox/dns/views.py | 8 +++++--- netbox/ipam/api/serializers.py | 2 +- netbox/ipam/forms.py | 12 ++++++++--- .../ipam/migrations/0011_prefix_extra_conf.py | 20 +++++++++++++++++++ netbox/ipam/models.py | 2 ++ netbox/ipam/views.py | 2 +- netbox/templates/dns/bind_export.html | 1 + netbox/templates/dns/zone.html | 10 ++++++++++ netbox/templates/dns/zone_bulk_edit.html | 1 + netbox/templates/dns/zone_import.html | 7 ++++++- netbox/templates/ipam/prefix.html | 4 ++++ netbox/templates/ipam/prefix_bulk_edit.html | 1 + netbox/templates/ipam/prefix_import.html | 7 ++++++- 17 files changed, 103 insertions(+), 16 deletions(-) create mode 100644 netbox/dns/migrations/0006_zone_extra_conf.py create mode 100644 netbox/ipam/migrations/0011_prefix_extra_conf.py diff --git a/netbox/dns/api/serializers.py b/netbox/dns/api/serializers.py index 504827301..cf7a378a3 100644 --- a/netbox/dns/api/serializers.py +++ b/netbox/dns/api/serializers.py @@ -12,7 +12,7 @@ class ZoneSerializer(serializers.ModelSerializer): class Meta: model = Zone - fields = ['id', 'name', 'ttl', 'soa_name', 'soa_contact', 'soa_serial', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'description'] + fields = ['id', 'name', 'ttl', 'soa_name', 'soa_contact', 'soa_serial', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'extra_conf', 'description'] class ZoneNestedSerializer(ZoneSerializer): diff --git a/netbox/dns/forms.py b/netbox/dns/forms.py index 06ee42562..d8ffa972c 100644 --- a/netbox/dns/forms.py +++ b/netbox/dns/forms.py @@ -3,7 +3,7 @@ from django.db.models import Count from ipam.models import IPAddress from utilities.forms import ( - BootstrapMixin, ConfirmationForm, APISelect, Livesearch, CSVDataField, BulkImportForm, + BootstrapMixin, ConfirmationForm, APISelect, Livesearch, CSVDataField, BulkImportForm, SmallTextarea ) from .models import ( @@ -22,7 +22,7 @@ class ZoneForm(forms.ModelForm, BootstrapMixin): class Meta: model = Zone - fields = ['name', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'description'] + fields = ['name', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'extra_conf', 'description'] labels = { 'soa_name': 'SOA Name', 'soa_contact': 'SOA Contact', @@ -30,6 +30,7 @@ class ZoneForm(forms.ModelForm, BootstrapMixin): 'soa_retry': 'SOA Retry', 'soa_expire': 'SOA Expire', 'soa_minimum': 'SOA Minimum', + 'extra_conf': 'Extra Conf', 'description': 'Description', } help_texts = { @@ -40,6 +41,10 @@ class ZoneForm(forms.ModelForm, BootstrapMixin): 'soa_retry': "Retry time, in seconds", 'soa_expire': "Expire time, in seconds", 'soa_minimum': "Negative result TTL, in seconds", + 'extra_conf': "Extra conf related to the zone, to put in your DNS server main conf file", + } + widgets = { + 'extra_conf': SmallTextarea(attrs={'rows': 3}), } @@ -47,7 +52,7 @@ class ZoneFromCSVForm(forms.ModelForm): class Meta: model = Zone - fields = ['name', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'description'] + fields = ['name', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'extra_conf', 'description'] class ZoneImportForm(BulkImportForm, BootstrapMixin): @@ -64,6 +69,7 @@ class ZoneBulkEditForm(forms.Form, BootstrapMixin): soa_retry = forms.IntegerField(required=False, label='SOA Retry') soa_expire = forms.IntegerField(required=False, label='SOA Expire') soa_minimum = forms.IntegerField(required=False, label='SOA Minimum') + extra_conf = forms.CharField(max_length=500, required=False, widget=SmallTextarea(attrs={'rows': 3}), label='Extra Conf') description = forms.CharField(max_length=100, required=False, label='Description') diff --git a/netbox/dns/migrations/0006_zone_extra_conf.py b/netbox/dns/migrations/0006_zone_extra_conf.py new file mode 100644 index 000000000..b65d72404 --- /dev/null +++ b/netbox/dns/migrations/0006_zone_extra_conf.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-18 14:55 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dns', '0005_auto_20160728_0854'), + ] + + operations = [ + migrations.AddField( + model_name='zone', + name='extra_conf', + field=models.CharField(blank=True, max_length=500), + ), + ] diff --git a/netbox/dns/models.py b/netbox/dns/models.py index 61fd417f7..74e4921b9 100644 --- a/netbox/dns/models.py +++ b/netbox/dns/models.py @@ -30,6 +30,7 @@ class Zone(CreatedUpdatedModel): soa_retry = models.PositiveIntegerField() soa_expire = models.PositiveIntegerField() soa_minimum = models.PositiveIntegerField() + extra_conf = models.CharField(max_length=500, blank=True) description = models.CharField(max_length=100, blank=True) class Meta: @@ -82,6 +83,7 @@ class Zone(CreatedUpdatedModel): str(self.soa_retry), str(self.soa_expire), str(self.soa_minimum), + '"{}"'.format(self.extra_conf) if self.extra_conf else '', self.description, ]) @@ -185,6 +187,7 @@ def export_bind_forward(): zones_list.append({ 'num': len(zones_list), 'id': z.name, + 'extra_conf': z.extra_conf, 'content': z.to_bind(records) }) @@ -201,14 +204,15 @@ def export_bind_reverse(): z = p.to_bind(child_ip) for zz in z: if not zz['id'] in zones: - zones[zz['id']] = zz['content'] + zones[zz['id']] = (zz['content'], p.extra_conf) zones_list = [] for zid, zc in zones.items(): zones_list.append({ 'num': len(zones_list), 'id': zid, - 'content': zc, + 'content': zc[0], + 'extra_conf': zc[1], }) return zones_list diff --git a/netbox/dns/views.py b/netbox/dns/views.py index 7e3ec1492..8a1f84d25 100644 --- a/netbox/dns/views.py +++ b/netbox/dns/views.py @@ -40,8 +40,7 @@ def zone(request, pk): record_count = len(records) # DNS records - dns_records = Record.objects.filter(zone=zone) - dns_records_table = RecordZoneTable(dns_records) + dns_records_table = RecordZoneTable(records) return render(request, 'dns/zone.html', { 'zone': zone, @@ -82,7 +81,7 @@ class ZoneBulkEditView(PermissionRequiredMixin, BulkEditView): def update_objects(self, pk_list, form): fields_to_update = {} - for field in ['name', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum']: + for field in ['name', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'extra_conf']: if form.cleaned_data[field]: fields_to_update[field] = form.cleaned_data[field] @@ -184,10 +183,13 @@ def bind_export(request, zones_list, context): zbuf = StringIO.StringIO() zfile = zipfile.ZipFile(zbuf, mode='w') temp = [] + cf = '' for z in zones_list: temp.append(StringIO.StringIO()) temp[len(temp) - 1].write(z['content']) zfile.writestr(z['id'], str(temp[len(temp) - 1].getvalue())) + cf += '{}:\n\t{}\n'.format(z['id'], z['extra_conf'] if z['extra_conf'] else '') + zfile.writestr('extra_confs.txt', cf) zfile.close() response = HttpResponse( zbuf.getvalue(), diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py index e5b089b1e..3b58245c3 100644 --- a/netbox/ipam/api/serializers.py +++ b/netbox/ipam/api/serializers.py @@ -136,7 +136,7 @@ class PrefixSerializer(serializers.ModelSerializer): class Meta: model = Prefix - fields = ['id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'description', 'ttl', 'soa_name', 'soa_contact', 'soa_serial', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum'] + fields = ['id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'description', 'ttl', 'soa_name', 'soa_contact', 'soa_serial', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'extra_conf'] class PrefixNestedSerializer(PrefixSerializer): diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 73d7de604..6fcf921cb 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -6,7 +6,7 @@ from django.db.models import Count from dcim.models import Site, Device, Interface from tenancy.forms import bulkedit_tenant_choices from tenancy.models import Tenant -from utilities.forms import BootstrapMixin, APISelect, Livesearch, CSVDataField, BulkImportForm, SlugField +from utilities.forms import BootstrapMixin, APISelect, Livesearch, CSVDataField, BulkImportForm, SlugField, SmallTextarea from .models import ( Aggregate, IPAddress, Prefix, PREFIX_STATUS_CHOICES, RIR, Role, VLAN, VLANGroup, VLAN_STATUS_CHOICES, VRF, @@ -158,7 +158,7 @@ class PrefixForm(forms.ModelForm, BootstrapMixin): class Meta: model = Prefix - fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan', 'status', 'role', 'description', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum'] + fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan', 'status', 'role', 'description', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'extra_conf'] labels = { 'ttl': 'Rev. DNS - TTL', 'soa_name': 'Rev. DNS - SOA Name', @@ -167,6 +167,7 @@ class PrefixForm(forms.ModelForm, BootstrapMixin): 'soa_retry': 'Rev. DNS - SOA Retry', 'soa_expire': 'Rev. DNS - SOA Expire', 'soa_minimum': 'Rev. DNS - SOA Minimum', + 'extra_conf': 'Rev. DNS - Extra Conf', } help_texts = { 'prefix': "IPv4 or IPv6 network", @@ -182,6 +183,10 @@ class PrefixForm(forms.ModelForm, BootstrapMixin): 'soa_retry': "Retry time, in seconds", 'soa_expire': "Expire time, in seconds", 'soa_minimum': "Negative result TTL, in seconds", + 'extra_conf': "Extra conf related to the zone, to put in your DNS server main conf file", + } + widgets = { + 'extra_conf': SmallTextarea(attrs={'rows': 3}), } def __init__(self, *args, **kwargs): @@ -228,7 +233,7 @@ class PrefixFromCSVForm(forms.ModelForm): class Meta: model = Prefix fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan_group_name', 'vlan_vid', 'status_name', 'role', - 'description', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum'] + 'description', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'extra_conf'] def clean(self): @@ -287,6 +292,7 @@ class PrefixBulkEditForm(forms.Form, BootstrapMixin): soa_retry = forms.IntegerField(required=False, label='Reverse DNS - SOA Retry') soa_expire = forms.IntegerField(required=False, label='Reverse DNS - SOA Expire') soa_minimum = forms.IntegerField(required=False, label='Reverse DNS - SOA Minimum') + extra_conf = forms.CharField(max_length=500, required=False, label='Reverse DNS - Extra Conf', widget=SmallTextarea(attrs={'rows': 3})) def prefix_vrf_choices(): diff --git a/netbox/ipam/migrations/0011_prefix_extra_conf.py b/netbox/ipam/migrations/0011_prefix_extra_conf.py new file mode 100644 index 000000000..c17225637 --- /dev/null +++ b/netbox/ipam/migrations/0011_prefix_extra_conf.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-08-18 14:55 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipam', '0010_merge'), + ] + + operations = [ + migrations.AddField( + model_name='prefix', + name='extra_conf', + field=models.CharField(blank=True, max_length=500), + ), + ] diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index e82126beb..a23f60f29 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -259,6 +259,7 @@ class Prefix(CreatedUpdatedModel): soa_expire = models.PositiveIntegerField(blank=True, null=True) soa_minimum = models.PositiveIntegerField(blank=True, null=True) + extra_conf = models.CharField(max_length=500, blank=True) description = models.CharField(max_length=100, blank=True) class Meta: @@ -331,6 +332,7 @@ class Prefix(CreatedUpdatedModel): str(self.soa_retry) if self.soa_retry else '', str(self.soa_expire) if self.soa_expire else '', str(self.soa_minimum) if self.soa_minimum else '', + '"{}"'.format(self.extra_conf) if self.extra_conf else '', ]) @property diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index ee129b50a..9408f6911 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -409,7 +409,7 @@ class PrefixBulkEditView(PermissionRequiredMixin, BulkEditView): fields_to_update[field] = None elif form.cleaned_data[field]: fields_to_update[field] = form.cleaned_data[field] - for field in ['site', 'status', 'role', 'description', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum']: + for field in ['site', 'status', 'role', 'description', 'ttl', 'soa_name', 'soa_contact', 'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'extra_conf']: if form.cleaned_data[field]: fields_to_update[field] = form.cleaned_data[field] diff --git a/netbox/templates/dns/bind_export.html b/netbox/templates/dns/bind_export.html index 4784d46a9..4a5cc6303 100644 --- a/netbox/templates/dns/bind_export.html +++ b/netbox/templates/dns/bind_export.html @@ -33,6 +33,7 @@
{{ z.content }}
+ {% if z.extra_conf %}
{{ z.extra_conf }}
{% endif %} {% endfor %} diff --git a/netbox/templates/dns/zone.html b/netbox/templates/dns/zone.html index 457b0eee4..c296ca241 100644 --- a/netbox/templates/dns/zone.html +++ b/netbox/templates/dns/zone.html @@ -86,6 +86,16 @@ SOA Minimum {{ zone.soa_minimum }} + + Extra Conf + + {% if zone.extra_conf %} + {{ zone.extra_conf }} + {% else %} + - + {% endif %} + + Description diff --git a/netbox/templates/dns/zone_bulk_edit.html b/netbox/templates/dns/zone_bulk_edit.html index 6d61fc60a..0d3410539 100644 --- a/netbox/templates/dns/zone_bulk_edit.html +++ b/netbox/templates/dns/zone_bulk_edit.html @@ -14,6 +14,7 @@ {{ zone.soa_retry }} {{ zone.soa_expire }} {{ zone.soa_minimum }} + {{ zone.extra_conf }} {{ zone.description }} {% endfor %} diff --git a/netbox/templates/dns/zone_import.html b/netbox/templates/dns/zone_import.html index e24a6ebce..231197faf 100644 --- a/netbox/templates/dns/zone_import.html +++ b/netbox/templates/dns/zone_import.html @@ -68,6 +68,11 @@ Negative result TTL, in seconds 1800 + + Extra Conf + Extra conf related to the zone, to put in your DNS server main conf file + "notify: 10.120.0.1 NOKEY\nprovide-xfr: 10.120.0.1 NOKEY" + Description Description (optional) @@ -76,7 +81,7 @@

Example

-
foo.net,10800,@,ns.foo.net. noc.foo.net.,3600,3600,604800,1800,Mail servers zone
+
foo.net,10800,@,ns.foo.net. noc.foo.net.,3600,3600,604800,1800,"notify: 10.120.0.1 NOKEY\nprovide-xfr: 10.120.0.1 NOKEY",Mail servers zone
{% endblock %} diff --git a/netbox/templates/ipam/prefix.html b/netbox/templates/ipam/prefix.html index 0a37b65c0..e2db6636a 100644 --- a/netbox/templates/ipam/prefix.html +++ b/netbox/templates/ipam/prefix.html @@ -131,6 +131,10 @@ Reverse DNS - SOA Minimum {{ prefix.soa_minimum }} + + Reverse DNS - Extra Conf + {{ prefix.extra_conf }} + Created {{ prefix.created }} diff --git a/netbox/templates/ipam/prefix_bulk_edit.html b/netbox/templates/ipam/prefix_bulk_edit.html index f76a6a1d5..5f6f6eb1d 100644 --- a/netbox/templates/ipam/prefix_bulk_edit.html +++ b/netbox/templates/ipam/prefix_bulk_edit.html @@ -21,6 +21,7 @@ {{ prefix.soa_expire }} {{ prefix.soa_minimum }} {{ prefix.description }} + {{ prefix.extra_conf }} {% endfor %} {% endblock %} diff --git a/netbox/templates/ipam/prefix_import.html b/netbox/templates/ipam/prefix_import.html index 37b3f3902..ba028bba1 100644 --- a/netbox/templates/ipam/prefix_import.html +++ b/netbox/templates/ipam/prefix_import.html @@ -108,10 +108,15 @@ Negative result TTL, in seconds 1800 + + Reverse DNS - Extra Conf + Extra conf related to the zone, to put in your DNS server main conf file + "notify: 10.120.0.1 NOKEY\nprovide-xfr: 10.120.0.1 NOKEY" +

Example

-
192.168.42.0/24,65000:123,ABC01,HQ,Customers,801,Active,Customer,7th floor WiFi,10800,@,ns.foo.net. noc.foo.net.,3600,3600,604800,1800
+
192.168.42.0/24,65000:123,ABC01,HQ,Customers,801,Active,Customer,7th floor WiFi,10800,@,ns.foo.net. noc.foo.net.,3600,3600,604800,1800,"notify: 10.120.0.1 NOKEY\nprovide-xfr: 10.120.0.1 NOKEY"
{% endblock %}