diff --git a/netbox/dns/filters.py b/netbox/dns/filters.py
index dcf38b6b3..173320c0c 100644
--- a/netbox/dns/filters.py
+++ b/netbox/dns/filters.py
@@ -1,10 +1,12 @@
import django_filters
+from django.db.models import Q
from ipam.models import IPAddress
from .models import (
Zone,
Record,
)
+from .forms import record_type_choices
class ZoneFilter(django_filters.FilterSet):
name = django_filters.CharFilter(
@@ -23,14 +25,27 @@ class RecordFilter(django_filters.FilterSet):
to_field_name='name',
lookup_type='icontains',
queryset=Zone.objects.all(),
- label='Zone (name)',
+ label='Zone (Name)',
)
+ record_type = django_filters.MultipleChoiceFilter(
+ name='record_type',
+ label='Type',
+ choices=record_type_choices
+ )
name = django_filters.CharFilter(
name='name',
lookup_type='icontains',
label='Name',
)
+ name_or_value = django_filters.MethodFilter(
+ name='name_or_value',
+ )
class Meta:
model=Record
field = ['name','record_type','value']
+
+ def filter_name_or_value(self, queryset, value):
+ if not value:
+ return queryset
+ return queryset.filter(Q(name__icontains=value) | Q(value__icontains=value))
diff --git a/netbox/dns/forms.py b/netbox/dns/forms.py
index 6ac1f3c2a..5ba65ae34 100644
--- a/netbox/dns/forms.py
+++ b/netbox/dns/forms.py
@@ -116,12 +116,19 @@ def record_zone_choices():
zone_choices = Zone.objects.annotate(record_count=Count('records'))
return [(z.name, '{} ({})'.format(z.name, z.record_count)) for z in zone_choices]
-#def record_name_choices():
- #name_choices =
+def record_type_choices():
+ type_choices = {}
+ records = Record.objects.all()
+ for r in records:
+ if not r.record_type in type_choices:
+ type_choices[r.record_type]=1
+ else:
+ type_choices[r.record_type]+=1
+ return [(t, '{} ({})'.format(t, count)) for t,count in type_choices.items()]
class RecordFilterForm(forms.Form, BootstrapMixin):
zone__name = forms.MultipleChoiceField(required=False, choices=record_zone_choices, label='Zone',
widget=forms.SelectMultiple(attrs={'size': 8}))
- #name = forms.MultipleChoiceField(required=False, choices=record_name_choices, label='Name', widget=forms.SelectMultiple(attrs={'size': 8}))
- record_type = forms.CharField(max_length=100, required=False, label='Type')
+ record_type = forms.MultipleChoiceField(required=False, choices=record_type_choices, label='Type',
+ widget=forms.SelectMultiple(attrs={'size': 8}))
diff --git a/netbox/dns/models.py b/netbox/dns/models.py
index 5e2528ee9..4ca2aff37 100644
--- a/netbox/dns/models.py
+++ b/netbox/dns/models.py
@@ -7,6 +7,8 @@ from django.db import models
from ipam.models import IPAddress
from utilities.models import CreatedUpdatedModel
+import time
+
class Zone(CreatedUpdatedModel):
"""
A Zone represents a DNS zone. It contains SOA data but no records, records are represented as Record objects.
@@ -43,6 +45,28 @@ class Zone(CreatedUpdatedModel):
str(self.soa_minimum),
])
+ def to_bind(self,records):
+ bind_records = ''
+ for r in records:
+ bind_records += r.to_bind()+'\n'
+ bind_export = '\n'.join([
+ '; gen by netbox ( '+time.strftime('%A %B %d %Y %H:%M:%S',time.localtime())+' ) ',
+ '',
+ '$TTL '+str(self.ttl),
+ self.soa_name.ljust(30)+' IN '+'SOA '+self.soa_contact+' (',
+ ' '+self.soa_serial.ljust(30)+' ; serial',
+ ' '+str(self.soa_refresh).ljust(30)+' ; refresh',
+ ' '+str(self.soa_retry).ljust(30)+' ; retry',
+ ' '+str(self.soa_expire).ljust(30)+' ; expire',
+ ' '+str(self.soa_minimum).ljust(29)+') ; minimum',
+ '',
+ '',
+ '',
+ ])
+ bind_export += '\n'+bind_records
+ bind_export += '\n'+'; end '
+ return bind_export
+
class Record(CreatedUpdatedModel):
@@ -66,6 +90,7 @@ class Record(CreatedUpdatedModel):
return reverse('dns:record', args=[self.pk])
def clean(self):
+ record_type = record_type.upper()
if not self.address and not self.value:
raise ValidationError("DNS records must have either an IP address or a text value")
@@ -79,5 +104,17 @@ class Record(CreatedUpdatedModel):
str(self.value) if self.value else '',
])
- #def to_json(self):
- # return JSON
+ def to_bind(self):
+ return ''.join([
+ (self.name if self.name!='@' else '').ljust(30),
+ ' IN ',
+ self.record_type.upper().ljust(10),
+ ' ',
+ (str(self.priority) if self.priority else '').ljust(4),
+ ' ',
+ (str(self.address).split('/')[0] if self.address else self.value).ljust(25),
+ ' ',
+ ' ; gen by netbox ( '+time.strftime('%A %B %d %Y %H:%M:%S',time.localtime())+' ) '
+ ])
+
+
diff --git a/netbox/dns/views.py b/netbox/dns/views.py
index da914fb29..c2c55c6c6 100644
--- a/netbox/dns/views.py
+++ b/netbox/dns/views.py
@@ -3,6 +3,7 @@ from django_tables2 import RequestConfig
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db.models import Count
from django.shortcuts import get_object_or_404, render
+from django.http import HttpResponse
from ipam.models import IPAddress
from utilities.paginator import EnhancedPaginator
@@ -30,12 +31,24 @@ def zone(request, pk):
zone = get_object_or_404(Zone.objects.all(), pk=pk)
records = Record.objects.filter(zone=zone)
record_count = len(records)
+ bind_export = zone.to_bind(records)
- return render(request, 'dns/zone.html', {
- 'zone': zone,
- 'records': records,
- 'record_count': record_count,
- })
+ if request.GET.get('bind_export'):
+ response = HttpResponse(
+ bind_export,
+ content_type='text/plain'
+ )
+ response['Content-Disposition'] = 'attachment; filename="netbox_{}.txt"'\
+ .format(zone.name)
+ return response
+
+ else:
+ return render(request, 'dns/zone.html', {
+ 'zone': zone,
+ 'records': records,
+ 'record_count': record_count,
+ 'bind_export': bind_export,
+ })
class ZoneEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dns.change_zone'
@@ -94,9 +107,11 @@ class RecordListView(ObjectListView):
def record(request, pk):
record = get_object_or_404(Record.objects.all(), pk=pk)
+ bind_export = record.to_bind()
return render(request, 'dns/record.html', {
'record': record,
+ 'bind_export': bind_export,
})
class RecordEditView(PermissionRequiredMixin, ObjectEditView):
diff --git a/netbox/templates/dns/record.html b/netbox/templates/dns/record.html
index 1dbf25d30..95d35e15b 100644
--- a/netbox/templates/dns/record.html
+++ b/netbox/templates/dns/record.html
@@ -102,4 +102,36 @@
+
+
+
+
+
+
+ {{ bind_export }} |
+
+
+
+
+
+{% endblock %}
+{% block javascript %}
+
{% endblock %}
diff --git a/netbox/templates/dns/record_list.html b/netbox/templates/dns/record_list.html
index d9cac2a2f..d642af2c0 100644
--- a/netbox/templates/dns/record_list.html
+++ b/netbox/templates/dns/record_list.html
@@ -31,7 +31,7 @@
+
+
+
+
+
+
+ {{ bind_export }} |
+
+
+
+
+
+{% endblock %}
+{% block javascript %}
+
{% endblock %}