Add 'extra_conf' field to DNS zones and reverse DNS zones (i.e. prefixes)

This commit is contained in:
rdujardin 2016-08-18 17:55:37 +02:00
parent 339fcdc541
commit c86a74ec30
17 changed files with 103 additions and 16 deletions

View File

@ -12,7 +12,7 @@ class ZoneSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Zone 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): class ZoneNestedSerializer(ZoneSerializer):

View File

@ -3,7 +3,7 @@ from django.db.models import Count
from ipam.models import IPAddress from ipam.models import IPAddress
from utilities.forms import ( from utilities.forms import (
BootstrapMixin, ConfirmationForm, APISelect, Livesearch, CSVDataField, BulkImportForm, BootstrapMixin, ConfirmationForm, APISelect, Livesearch, CSVDataField, BulkImportForm, SmallTextarea
) )
from .models import ( from .models import (
@ -22,7 +22,7 @@ class ZoneForm(forms.ModelForm, BootstrapMixin):
class Meta: class Meta:
model = Zone 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 = { labels = {
'soa_name': 'SOA Name', 'soa_name': 'SOA Name',
'soa_contact': 'SOA Contact', 'soa_contact': 'SOA Contact',
@ -30,6 +30,7 @@ class ZoneForm(forms.ModelForm, BootstrapMixin):
'soa_retry': 'SOA Retry', 'soa_retry': 'SOA Retry',
'soa_expire': 'SOA Expire', 'soa_expire': 'SOA Expire',
'soa_minimum': 'SOA Minimum', 'soa_minimum': 'SOA Minimum',
'extra_conf': 'Extra Conf',
'description': 'Description', 'description': 'Description',
} }
help_texts = { help_texts = {
@ -40,6 +41,10 @@ class ZoneForm(forms.ModelForm, BootstrapMixin):
'soa_retry': "Retry time, in seconds", 'soa_retry': "Retry time, in seconds",
'soa_expire': "Expire time, in seconds", 'soa_expire': "Expire time, in seconds",
'soa_minimum': "Negative result TTL, 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: class Meta:
model = Zone 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): class ZoneImportForm(BulkImportForm, BootstrapMixin):
@ -64,6 +69,7 @@ class ZoneBulkEditForm(forms.Form, BootstrapMixin):
soa_retry = forms.IntegerField(required=False, label='SOA Retry') soa_retry = forms.IntegerField(required=False, label='SOA Retry')
soa_expire = forms.IntegerField(required=False, label='SOA Expire') soa_expire = forms.IntegerField(required=False, label='SOA Expire')
soa_minimum = forms.IntegerField(required=False, label='SOA Minimum') 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') description = forms.CharField(max_length=100, required=False, label='Description')

View File

@ -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),
),
]

View File

@ -30,6 +30,7 @@ class Zone(CreatedUpdatedModel):
soa_retry = models.PositiveIntegerField() soa_retry = models.PositiveIntegerField()
soa_expire = models.PositiveIntegerField() soa_expire = models.PositiveIntegerField()
soa_minimum = models.PositiveIntegerField() soa_minimum = models.PositiveIntegerField()
extra_conf = models.CharField(max_length=500, blank=True)
description = models.CharField(max_length=100, blank=True) description = models.CharField(max_length=100, blank=True)
class Meta: class Meta:
@ -82,6 +83,7 @@ class Zone(CreatedUpdatedModel):
str(self.soa_retry), str(self.soa_retry),
str(self.soa_expire), str(self.soa_expire),
str(self.soa_minimum), str(self.soa_minimum),
'"{}"'.format(self.extra_conf) if self.extra_conf else '',
self.description, self.description,
]) ])
@ -185,6 +187,7 @@ def export_bind_forward():
zones_list.append({ zones_list.append({
'num': len(zones_list), 'num': len(zones_list),
'id': z.name, 'id': z.name,
'extra_conf': z.extra_conf,
'content': z.to_bind(records) 'content': z.to_bind(records)
}) })
@ -201,14 +204,15 @@ def export_bind_reverse():
z = p.to_bind(child_ip) z = p.to_bind(child_ip)
for zz in z: for zz in z:
if not zz['id'] in zones: if not zz['id'] in zones:
zones[zz['id']] = zz['content'] zones[zz['id']] = (zz['content'], p.extra_conf)
zones_list = [] zones_list = []
for zid, zc in zones.items(): for zid, zc in zones.items():
zones_list.append({ zones_list.append({
'num': len(zones_list), 'num': len(zones_list),
'id': zid, 'id': zid,
'content': zc, 'content': zc[0],
'extra_conf': zc[1],
}) })
return zones_list return zones_list

View File

@ -40,8 +40,7 @@ def zone(request, pk):
record_count = len(records) record_count = len(records)
# DNS records # DNS records
dns_records = Record.objects.filter(zone=zone) dns_records_table = RecordZoneTable(records)
dns_records_table = RecordZoneTable(dns_records)
return render(request, 'dns/zone.html', { return render(request, 'dns/zone.html', {
'zone': zone, 'zone': zone,
@ -82,7 +81,7 @@ class ZoneBulkEditView(PermissionRequiredMixin, BulkEditView):
def update_objects(self, pk_list, form): def update_objects(self, pk_list, form):
fields_to_update = {} 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]: if form.cleaned_data[field]:
fields_to_update[field] = 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() zbuf = StringIO.StringIO()
zfile = zipfile.ZipFile(zbuf, mode='w') zfile = zipfile.ZipFile(zbuf, mode='w')
temp = [] temp = []
cf = ''
for z in zones_list: for z in zones_list:
temp.append(StringIO.StringIO()) temp.append(StringIO.StringIO())
temp[len(temp) - 1].write(z['content']) temp[len(temp) - 1].write(z['content'])
zfile.writestr(z['id'], str(temp[len(temp) - 1].getvalue())) 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() zfile.close()
response = HttpResponse( response = HttpResponse(
zbuf.getvalue(), zbuf.getvalue(),

View File

@ -136,7 +136,7 @@ class PrefixSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Prefix 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): class PrefixNestedSerializer(PrefixSerializer):

View File

@ -6,7 +6,7 @@ from django.db.models import Count
from dcim.models import Site, Device, Interface from dcim.models import Site, Device, Interface
from tenancy.forms import bulkedit_tenant_choices from tenancy.forms import bulkedit_tenant_choices
from tenancy.models import Tenant 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 ( from .models import (
Aggregate, IPAddress, Prefix, PREFIX_STATUS_CHOICES, RIR, Role, VLAN, VLANGroup, VLAN_STATUS_CHOICES, VRF, 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: class Meta:
model = Prefix 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 = { labels = {
'ttl': 'Rev. DNS - TTL', 'ttl': 'Rev. DNS - TTL',
'soa_name': 'Rev. DNS - SOA Name', 'soa_name': 'Rev. DNS - SOA Name',
@ -167,6 +167,7 @@ class PrefixForm(forms.ModelForm, BootstrapMixin):
'soa_retry': 'Rev. DNS - SOA Retry', 'soa_retry': 'Rev. DNS - SOA Retry',
'soa_expire': 'Rev. DNS - SOA Expire', 'soa_expire': 'Rev. DNS - SOA Expire',
'soa_minimum': 'Rev. DNS - SOA Minimum', 'soa_minimum': 'Rev. DNS - SOA Minimum',
'extra_conf': 'Rev. DNS - Extra Conf',
} }
help_texts = { help_texts = {
'prefix': "IPv4 or IPv6 network", 'prefix': "IPv4 or IPv6 network",
@ -182,6 +183,10 @@ class PrefixForm(forms.ModelForm, BootstrapMixin):
'soa_retry': "Retry time, in seconds", 'soa_retry': "Retry time, in seconds",
'soa_expire': "Expire time, in seconds", 'soa_expire': "Expire time, in seconds",
'soa_minimum': "Negative result TTL, 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): def __init__(self, *args, **kwargs):
@ -228,7 +233,7 @@ class PrefixFromCSVForm(forms.ModelForm):
class Meta: class Meta:
model = Prefix model = Prefix
fields = ['prefix', 'vrf', 'tenant', 'site', 'vlan_group_name', 'vlan_vid', 'status_name', 'role', 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): def clean(self):
@ -287,6 +292,7 @@ class PrefixBulkEditForm(forms.Form, BootstrapMixin):
soa_retry = forms.IntegerField(required=False, label='Reverse DNS - SOA Retry') soa_retry = forms.IntegerField(required=False, label='Reverse DNS - SOA Retry')
soa_expire = forms.IntegerField(required=False, label='Reverse DNS - SOA Expire') soa_expire = forms.IntegerField(required=False, label='Reverse DNS - SOA Expire')
soa_minimum = forms.IntegerField(required=False, label='Reverse DNS - SOA Minimum') 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(): def prefix_vrf_choices():

View File

@ -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),
),
]

View File

@ -259,6 +259,7 @@ class Prefix(CreatedUpdatedModel):
soa_expire = models.PositiveIntegerField(blank=True, null=True) soa_expire = models.PositiveIntegerField(blank=True, null=True)
soa_minimum = 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) description = models.CharField(max_length=100, blank=True)
class Meta: class Meta:
@ -331,6 +332,7 @@ class Prefix(CreatedUpdatedModel):
str(self.soa_retry) if self.soa_retry else '', str(self.soa_retry) if self.soa_retry else '',
str(self.soa_expire) if self.soa_expire else '', str(self.soa_expire) if self.soa_expire else '',
str(self.soa_minimum) if self.soa_minimum else '', str(self.soa_minimum) if self.soa_minimum else '',
'"{}"'.format(self.extra_conf) if self.extra_conf else '',
]) ])
@property @property

View File

@ -409,7 +409,7 @@ class PrefixBulkEditView(PermissionRequiredMixin, BulkEditView):
fields_to_update[field] = None fields_to_update[field] = None
elif form.cleaned_data[field]: elif form.cleaned_data[field]:
fields_to_update[field] = 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]: if form.cleaned_data[field]:
fields_to_update[field] = form.cleaned_data[field] fields_to_update[field] = form.cleaned_data[field]

View File

@ -33,6 +33,7 @@
<tr><td> <tr><td>
<pre id="bind_export_{{ z.num }}" style="overflow: auto; overflow-x: auto; overflow-y: auto; word-wrap: break-word; white-space: pre;">{{ z.content }}</pre> <pre id="bind_export_{{ z.num }}" style="overflow: auto; overflow-x: auto; overflow-y: auto; word-wrap: break-word; white-space: pre;">{{ z.content }}</pre>
</td></tr> </td></tr>
{% if z.extra_conf %}<tr><td><pre style="overflow: auto; overflow-x: auto; overflow-y: auto; word-wrap: break-word; white-space: pre;">{{ z.extra_conf }}</pre></td></tr>{% endif %}
</table> </table>
</div> </div>
{% endfor %} {% endfor %}

View File

@ -86,6 +86,16 @@
<td>SOA Minimum</td> <td>SOA Minimum</td>
<td>{{ zone.soa_minimum }}</td> <td>{{ zone.soa_minimum }}</td>
</tr> </tr>
<tr>
<td>Extra Conf</td>
<td>
{% if zone.extra_conf %}
{{ zone.extra_conf }}
{% else %}
-
{% endif %}
</td>
</tr>
<tr> <tr>
<td>Description</td> <td>Description</td>
<td> <td>

View File

@ -14,6 +14,7 @@
<td>{{ zone.soa_retry }}</td> <td>{{ zone.soa_retry }}</td>
<td>{{ zone.soa_expire }}</td> <td>{{ zone.soa_expire }}</td>
<td>{{ zone.soa_minimum }}</td> <td>{{ zone.soa_minimum }}</td>
<td>{{ zone.extra_conf }}</td>
<td>{{ zone.description }}</td> <td>{{ zone.description }}</td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -68,6 +68,11 @@
<td>Negative result TTL, in seconds</td> <td>Negative result TTL, in seconds</td>
<td>1800</td> <td>1800</td>
</tr> </tr>
<tr>
<td>Extra Conf</td>
<td>Extra conf related to the zone, to put in your DNS server main conf file</td>
<td>"notify: 10.120.0.1 NOKEY\nprovide-xfr: 10.120.0.1 NOKEY"</td>
</tr>
<tr> <tr>
<td>Description</td> <td>Description</td>
<td>Description (optional)</td> <td>Description (optional)</td>
@ -76,7 +81,7 @@
</tbody> </tbody>
</table> </table>
<h4>Example</h4> <h4>Example</h4>
<pre>foo.net,10800,@,ns.foo.net. noc.foo.net.,3600,3600,604800,1800,Mail servers zone</pre> <pre>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</pre>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -131,6 +131,10 @@
<td>Reverse DNS - SOA Minimum</td> <td>Reverse DNS - SOA Minimum</td>
<td>{{ prefix.soa_minimum }}</td> <td>{{ prefix.soa_minimum }}</td>
</tr> </tr>
<tr>
<td>Reverse DNS - Extra Conf</td>
<td>{{ prefix.extra_conf }}</td>
</tr>
<tr> <tr>
<td>Created</td> <td>Created</td>
<td>{{ prefix.created }}</td> <td>{{ prefix.created }}</td>

View File

@ -21,6 +21,7 @@
<td>{{ prefix.soa_expire }}</td> <td>{{ prefix.soa_expire }}</td>
<td>{{ prefix.soa_minimum }}</td> <td>{{ prefix.soa_minimum }}</td>
<td>{{ prefix.description }}</td> <td>{{ prefix.description }}</td>
<td>{{ prefix.extra_conf }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}

View File

@ -108,10 +108,15 @@
<td>Negative result TTL, in seconds</td> <td>Negative result TTL, in seconds</td>
<td>1800</td> <td>1800</td>
</tr> </tr>
<tr>
<td>Reverse DNS - Extra Conf</td>
<td>Extra conf related to the zone, to put in your DNS server main conf file</td>
<td>"notify: 10.120.0.1 NOKEY\nprovide-xfr: 10.120.0.1 NOKEY"</td>
</tr>
</tbody> </tbody>
</table> </table>
<h4>Example</h4> <h4>Example</h4>
<pre>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</pre> <pre>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"</pre>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}