Merge branch 'refactored-views' of https://github.com/Dunedan/binder into Dunedan-refactored-views

This commit is contained in:
Jeffrey Forman 2015-12-26 14:10:11 -05:00
commit ab9b28d525
13 changed files with 263 additions and 279 deletions

View File

@ -17,7 +17,7 @@ class ZoneException(Exception):
class RecordException(Exception):
"""Thrown when there is an issue dealign with a Record.
"""Thrown when there is an issue dealing with a Record.
* Adding or deleting.
"""

View File

@ -17,7 +17,8 @@ class CustomUnicodeListField(forms.CharField):
try:
string_list = [str(cur_rr) for cur_rr in eval(value)]
except:
raise ValidationError("Error in converting Unicode list to list of Strings: %r" % value)
raise ValidationError("Error in converting Unicode list to list "
"of strings: %r" % value)
return string_list
@ -37,7 +38,8 @@ class CustomStringPeriodSuffix(forms.CharField):
if new_string[-1] != ".":
new_string += "."
except:
raise ValidationError("Unable to stick a period on the end of your input: %r" % value)
raise ValidationError("Unable to stick a period on the end of "
"your input: %r" % value)
return new_string
@ -50,13 +52,17 @@ class FormAddForwardRecord(forms.Form):
record_name = forms.RegexField(max_length=100,
regex="^[a-zA-Z0-9-_]+$",
required=False)
record_type = forms.ChoiceField(choices=settings.RECORD_TYPE_CHOICES)
record_type = forms.ChoiceField(choices=settings.RECORD_TYPE_CHOICES,
widget=forms.RadioSelect)
zone_name = forms.CharField(max_length=100)
record_data = forms.GenericIPAddressField()
ttl = forms.ChoiceField(choices=settings.TTL_CHOICES)
ttl = forms.ChoiceField(choices=settings.TTL_CHOICES,
widget=forms.RadioSelect)
create_reverse = forms.BooleanField(required=False)
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
required=False)
required=False,
widget=forms.RadioSelect,
empty_label=None)
class FormAddReverseRecord(forms.Form):
@ -66,12 +72,16 @@ class FormAddReverseRecord(forms.Form):
dns_server = forms.CharField(max_length=100)
record_name = forms.IntegerField(min_value=0, max_value=255)
record_type = forms.RegexField(regex=r"^PTR$",
error_messages={"invalid": "The only valid choice here is PTR."})
error_messages={
"invalid": "The only valid choice here "
"is PTR."})
zone_name = forms.CharField(max_length=100)
record_data = CustomStringPeriodSuffix(required=True)
ttl = forms.ChoiceField(choices=settings.TTL_CHOICES)
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
required=False)
required=False,
widget=forms.RadioSelect,
empty_label=None)
create_reverse = forms.BooleanField(required=False)
@ -83,9 +93,12 @@ class FormAddCnameRecord(forms.Form):
originating_record = forms.CharField(max_length=100)
cname = forms.RegexField(max_length=100, regex="^[a-zA-Z0-9-_]+$")
zone_name = forms.CharField(max_length=256)
ttl = forms.ChoiceField(choices=settings.TTL_CHOICES)
ttl = forms.ChoiceField(choices=settings.TTL_CHOICES,
widget=forms.RadioSelect)
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
required=False)
required=False,
widget=forms.RadioSelect,
empty_label=None)
class FormDeleteRecord(forms.Form):
@ -96,4 +109,6 @@ class FormDeleteRecord(forms.Form):
zone_name = forms.CharField(max_length=256)
rr_list = CustomUnicodeListField()
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
required=False)
required=False,
widget=forms.RadioSelect,
empty_label=None)

View File

@ -1,11 +1,13 @@
# Binder Helpers
# Standard Imports
import logging
import re
import socket
# 3rd Party
import dns.query
import dns.rcode
import dns.reversename
import dns.tsig
import dns.tsigkeyring
@ -13,6 +15,7 @@ import dns.update
# App Imports
from binder import models
from binder.exceptions import KeyringException, RecordException
def add_record(dns_server, zone_name, record_name, record_type, record_data,
@ -89,11 +92,13 @@ def delete_record(dns_server, rr_list, key_name):
"""Delete a list of DNS records passed as strings in rr_items."""
server = models.BindServer.objects.get(hostname=dns_server)
logger = logging.getLogger('binder.helpers')
try:
transfer_key = models.Key.objects.get(name=key_name)
except models.Key.DoesNotExist:
keyring = None
algorithm = None
except models.Key.DoesNotExist as exc:
logger.error(exc)
raise KeyringException("The specified TSIG key %s does not exist in "
"binders configuration." % key_name)
else:
keyring = transfer_key.create_keyring()
algorithm = transfer_key.algorithm
@ -107,13 +112,19 @@ def delete_record(dns_server, rr_list, key_name):
keyring=keyring,
keyalgorithm=algorithm)
dns_update.delete(record)
output = send_dns_update(dns_update,
dns_server,
server.dns_port,
key_name)
delete_response.append({"description": "Delete Record: %s" % current_rr,
"output": output})
try:
output = send_dns_update(dns_update,
dns_server,
server.dns_port,
key_name)
except (KeyringException, RecordException) as exc:
delete_response.append({"description": exc,
"record": current_rr,
"success": False})
else:
delete_response.append({"description": output,
"record": current_rr,
"success": True})
return delete_response
@ -123,11 +134,13 @@ def create_update(dns_server, zone_name, record_name, record_type, record_data,
"""Update/Create DNS record of name and type with passed data and ttl."""
server = models.BindServer.objects.get(hostname=dns_server)
logger = logging.getLogger('binder.helpers')
try:
transfer_key = models.Key.objects.get(name=key_name)
except models.Key.DoesNotExist:
keyring = None
algorithm = None
except models.Key.DoesNotExist as exc:
logger.error(exc)
raise KeyringException("The specified TSIG key %s does not exist in "
"binders configuration." % key_name)
else:
keyring = transfer_key.create_keyring()
algorithm = transfer_key.algorithm
@ -174,13 +187,21 @@ def send_dns_update(dns_message, dns_server, port, key_name):
Returns:
String output
"""
logger = logging.getLogger('binder.helpers')
try:
output = dns.query.tcp(dns_message, dns_server, port=port)
except dns.tsig.PeerBadKey:
output = ("DNS server %s is not configured for TSIG key: %s." %
(dns_server, key_name))
except dns.tsig.PeerBadSignature:
output = ("DNS server %s did like the TSIG signature we sent. Check "
"key %s for correctness." % (dns_server, key_name))
except dns.tsig.PeerBadKey as exc:
logger.error(exc)
raise KeyringException("DNS server %s is not configured for TSIG key: %s." %
(dns_server, key_name))
except dns.tsig.PeerBadSignature as exc:
logger.error(exc)
raise KeyringException("DNS server %s didn't like the TSIG signature "
"we sent. Check key %s for correctness." %
(dns_server, key_name))
logger.debug(output)
return_code = output.rcode()
if return_code != dns.rcode.NOERROR:
raise RecordException('Error when requesting DNS server %s: %s' %
(dns_server, dns.rcode.to_text(return_code)))
return output

View File

@ -1,5 +1,6 @@
# Django settings for binder project.
import os
from django.contrib.messages import constants as messages
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
DEBUG = True
@ -88,6 +89,38 @@ INSTALLED_APPS = (
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
'datefmt' : "%d/%b/%Y %H:%M:%S"
}
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'verbose'
},
},
'loggers': {
'django': {
'handlers': ['console'],
'propagate': True,
'level': 'INFO'
},
'binder': {
'handlers': ['console'],
'level': 'DEBUG'
}
}
}
MESSAGE_TAGS = {
messages.ERROR: 'danger'
}
TTL_CHOICES = ((300, "5 minutes"),
(1800, "30 minutes"),
(3600, "1 hour"),

View File

@ -10,7 +10,6 @@
<script src="{% static "sorttable.js" %}"></script>
</head>
{% endblock header %}
<body>
<script src="{% static "jquery-2.1.3.min.js" %}"></script>
<script src="{% static "bootstrap/js/bootstrap.min.js" %}"></script>
@ -46,23 +45,17 @@
</div>
<div class="row">
<div class="col-md-12">
{% block errors %}
{% if errors %}
<div class="alert alert-error">
Errors were encountered:
<br />
{{ errors }}
</div>
{% endif %}
{% endblock errors %}
{% block body %}
{% endblock body %}
{% if messages %}
<ul id="messages" class="list-unstyled text-center" style="margin-bottom: 2em;">
{% for message in messages %}
<li role="alert" class="alert alert-{{ message.tags }} alert-dismissible"><button aria-label="Close" data-dismiss="alert" class="close" type="button"><span aria-hidden="true">×</span></button>{{ message.message }}</li>
{% endfor %}
</ul>
{% endif %}
{% block body %}{% endblock body %}
</div>
</div>
</div>
{% block footer %}{% endblock footer %}
</body>
{% block footer %}
{% endblock footer %}
</html>

View File

@ -1,9 +1,9 @@
{% extends "base.html" %}
{% block pageheader %}Add CNAME record for {{ originating_record }}{% endblock pageheader %}
{% block pageheader %}Add CNAME record for {{ form.originating_record.value }}.{{ form.zone_name.value }}{% endblock pageheader %}
{% block body %}
<form class="form-horizontal" action="{% url "add_cname_result" %}" method="post">{% csrf_token %}
<form class="form-horizontal" action="{% url "add_cname" dns_server=dns_server zone_name=form.zone_name.value record_name=originating_record %}" method="post">{% csrf_token %}
<legend>Create CNAME record</legend>
<div class="form-group{% if form.dns_server.errors %} has-error{% endif %}">
@ -24,7 +24,7 @@
<div class="form-group{% if form.originating_record.errors %} has-error{% endif %}">
<label for="originating_record" class="col-sm-3 control-label">Originating Record: </label>
<div class="col-sm-5 col-md-4">
<input type="text" id="originating_record" name="originating_record" class="form-control" value="{{originating_record}}" readonly="readonly"/>
<input type="text" id="originating_record" name="originating_record" class="form-control" value="{{ form.originating_record.value }}" readonly="readonly"/>
</div>
{% if form.originating_record.errors %}
<div class="col-sm-4 col-md-5">
@ -41,8 +41,8 @@
<div class="col-sm-5 col-md-4">
<div class="input-group">
<input id="cname" name="cname" type="text" class="form-control"{% if form.cname.value %} value="{{ form.cname.value }}"{% endif %}/>
<span class="input-group-addon">.{{zone_name}}</span>
<input type="hidden" name="zone_name" value="{{zone_name}}"/>
<span class="input-group-addon">.{{ form.zone_name.value }}</span>
<input type="hidden" name="zone_name" value="{{ form.zone_name.value }}"/>
</div>
</div>
{% if form.cname.errors %}
@ -58,10 +58,8 @@
<label for="ttl" class="col-sm-3 control-label">TTL: </label>
<div class="col-sm-5 col-md-4">
<select id="ttl" name="ttl" class="form-control">
{% for ttl, description in ttl_choices %}
<option value="{{ttl}}">
{{ttl}} ({{description}})
</option>
{% for choice in form.ttl %}
<option value="{{ choice.choice_value }}">{{ choice.choice_value }} ({{ choice.choice_label }})</option>
{% endfor %}
</select>
</div>
@ -79,10 +77,10 @@
<label for="key_name" class="col-sm-3 control-label">TSIG Key:</label>
<div class="col-sm-5 col-md-4">
<select id="key_name" name="key_name" class="form-control">
{% for key in tsig_keys %}
<option value="{{key.id}}"{% if key == dns_server.default_transfer_key %} selected="selected"{% endif %}>{{key}}</option>
{% for key in form.key_name %}
<option value="{{ key.choice_value }}"{% if key.choice_value|add:0 == dns_server.default_transfer_key.id %} selected="selected"{% endif %}>{{ key.choice_label }}</option>
{% empty %}
<option selected="selected" value=""/>
<option selected="selected" value="" />
{% endfor %}
</select>
</div>
@ -100,7 +98,7 @@
<div class="col-sm-3"></div>
<div class="col-sm-5 col-md-4">
<button type="submit" class="btn btn-default">Save Changes</button>
<a href="{% url "zone_list" dns_server=dns_server zone_name=zone_name %}" class="btn btn-warning">Cancel</a>
<a href="{% url "zone_list" dns_server=dns_server zone_name=form.zone_name.value %}" class="btn btn-warning">Cancel</a>
</div>
</div>
</form>

View File

@ -1,9 +1,9 @@
{% extends "base.html" %}
{% block pageheader %}Add record in {{ zone_name }}{% endblock pageheader %}
{% block pageheader %}Add record in {{ form.zone_name.value }}{% endblock pageheader %}
{% block body %}
<form class="form-horizontal" action="{% url "add_record_result" %}" method="POST">{% csrf_token %}
<form class="form-horizontal" action="{% url "add_record" dns_server=dns_server zone_name=form.zone_name.value %}" method="POST">{% csrf_token %}
<legend>Create Record</legend>
<div class="form-group{% if form.dns_server.errors %} has-error{% endif %}">
@ -26,8 +26,8 @@
<div class="col-sm-5 col-md-4">
<div class="input-group">
<input id="record_name" name="record_name" type="text" class="form-control"{% if form.record_name.value %} value="{{ form.record_name.value }}"{% endif %} />
<span class="input-group-addon">.{{zone_name}}</span>
<input type="hidden" name="zone_name" value="{{zone_name}}" />
<span class="input-group-addon">.{{ form.zone_name.value }}</span>
<input type="hidden" name="zone_name" value="{{ form.zone_name.value }}" />
</div>
</div>
{% if form.record_name.errors %}
@ -43,9 +43,9 @@
<label for="record_type" class="col-sm-3 control-label">Record Type:</label>
<div class="col-sm-5 col-md-4">
<select id="record_type" name="record_type" class="form-control">
{% if "in-addr.arpa" not in zone_name and "ip6.arpa" not in zone_name %}
{% for type, name in record_type_choices %}
<option value="{{name}}">{{name}}</option>
{% if "in-addr.arpa" not in form.zone_name.value and "ip6.arpa" not in form.zone_name.value %}
{% for choice in form.record_type %}
<option value="{{ choice.choice_value }}">{{ choice.choice_label }}</option>
{% endfor %}
{% else %}
<option value="PTR">PTR</option>
@ -80,10 +80,8 @@
<label for="ttl" class="col-sm-3 control-label">TTL: </label>
<div class="col-sm-5 col-md-4">
<select id="ttl" name="ttl" class="form-control">
{% for ttl, description in ttl_choices %}
<option value="{{ttl}}">
{{ttl}} ({{description}})
</option>
{% for choice in form.ttl %}
<option value="{{ choice.choice_value }}">{{ choice.choice_value }} ({{ choice.choice_label }})</option>
{% endfor %}
</select>
</div>
@ -97,7 +95,7 @@
{% endif %}
</div>
{% if "in-addr.arpa" not in zone_name and "ip.arpa" not in zone_name %}
{% if "in-addr.arpa" not in form.zone_name.value and "ip.arpa" not in form.zone_name.value %}
<div class="form-group">
<label for="create_reverse" class="col-sm-3 control-label checkbox">Create Reverse Record (PTR):</label>
<div class="col-sm-5 col-md-4">
@ -110,10 +108,10 @@
<label for="key_name" class="col-sm-3 control-label">TSIG Key:</label>
<div class="col-sm-5 col-md-4">
<select id="key_name" name="key_name" class="form-control">
{% for key in tsig_keys %}
<option value="{{key.id}}"{% if key == dns_server.default_transfer_key %} selected="selected"{% endif %}>{{key}}</option>
{% for key in form.key_name %}
<option value="{{ key.choice_value }}"{% if key.choice_value|add:0 == dns_server.default_transfer_key.id %} selected="selected"{% endif %}>{{ key.choice_label }}</option>
{% empty %}
<option selected="selected" value=""/>
<option selected="selected" value="" />
{% endfor %}
</select>
</div>
@ -131,7 +129,7 @@
<div class="col-sm-3"></div>
<div class="col-sm-5 col-md-4">
<button type="submit" class="btn btn-default">Save Changes</button>
<a href="{% url "zone_list" dns_server=dns_server zone_name=zone_name %}" class="btn btn-warning">Cancel</a>
<a href="{% url "zone_list" dns_server=dns_server zone_name=form.zone_name.value %}" class="btn btn-warning">Cancel</a>
</div>
</div>
</form>

View File

@ -3,7 +3,7 @@
{% block pageheader %}Delete record(s) in {{ zone_name }}{% endblock pageheader %}
{% block body %}
<form class="form-horizontal" action="{% url "delete_record_result" %}" method="POST">{% csrf_token %}
<form class="form-horizontal" action="{% url "delete_record" dns_server=dns_server zone_name=zone_name %}" method="POST">{% csrf_token %}
<legend>Delete Record</legend>
<div class="row">
@ -39,10 +39,10 @@
<label for="key_name" class="col-sm-3 control-label">TSIG Key:</label>
<div class="col-sm-5 col-md-4">
<select id="key_name" name="key_name" class="form-control">
{% for key in tsig_keys %}
<option value="{{key.id}}"{% if key == dns_server.default_transfer_key %} selected="selected"{% endif %}>{{key}}</option>
{% for key in form.key_name %}
<option value="{{ key.choice_value }}"{% if key.choice_value|add:0 == dns_server.default_transfer_key.id %} selected="selected"{% endif %}>{{ key.choice_label }}</option>
{% empty %}
<option selected="selected" value=""/>
<option selected="selected" value="" />
{% endfor %}
</select>
</div>

View File

@ -3,13 +3,9 @@
{% block pageheader %}Zone listing for {{ zone_name }} on {{ dns_server.hostname }}{% endblock pageheader %}
{% block body %}
{% if not errors %}
<a href="{% url "add_record" dns_server=dns_server zone_name=zone_name %}" class="btn btn-default">Add Record</a>
<p><a href="{% url "add_record" dns_server=dns_server zone_name=zone_name %}" class="btn btn-default">Add Record</a></p>
<form action="{% url "delete_record" %}" method="post">{% csrf_token %}
<input type="hidden" name="dns_server" value="{{ dns_server.hostname }}">
<input type="hidden" name="zone_name" value="{{ zone_name }}">
<form action="{% url "delete_record" dns_server=dns_server zone_name=zone_name %}" method="post">{% csrf_token %}
<table class="sortable table table-condensed table-hover">
<tr>
@ -48,7 +44,6 @@
{% endfor %}
</table>
<button class="btn btn-danger" type="submit">Delete Selected</button>
<p><button class="btn btn-danger" type="submit">Delete Selected</button></p>
</form>
{% endif %}
{% endblock body %}

View File

@ -1,18 +0,0 @@
{% extends "base.html" %}
{% block pageheader %}Record Result{% endblock pageheader %}
{% block body %}
<table class="table">
{% for current_response in response %}
<tr>
<th>Record</th>
<th>Output</th>
</tr>
<tr>
<td>{{ current_response.description }}</td>
<td><pre>{{ current_response.output }}</pre></td>
</tr>
{% endfor %}
</table>
{% endblock body %}

View File

@ -27,18 +27,6 @@ class GetTests(TestCase):
response = self.client.get(reverse("server_list"))
self.assertEqual(response.status_code, 200)
def test_GetResultRedirects(self):
"""GETing a /result/ URL should always redirect to /."""
response = self.client.get(reverse("add_record_result"), follow=True)
self.assertRedirects(response, reverse("index"))
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("delete_record_result"), follow=True)
self.assertRedirects(response, reverse("index"))
self.assertEqual(response.status_code, 200)
response = self.client.get(reverse("add_cname_result"), follow=True)
self.assertRedirects(response, reverse("index"))
self.assertEqual(response.status_code, 200)
def test_GetInvalidServer(self):
"""Get a zone list for a server not in the database."""
server_name = "unconfigured.server.net"
@ -64,28 +52,31 @@ class PostTests(TestCase):
def test_DeleteRecordInitial_Empty(self):
"""Ensure the initial deletion form works as expected with no RR list."""
response = self.client.post(reverse("delete_record"),
{"dns_server": "testserver.test.net",
"zone_name": "testzone1.test.net",
"rr_list": []})
self.assertContains(response,
'<input type="hidden" id="zone_name" name="zone_name" value="testzone1.test.net" />',
html=True)
self.assertContains(response,
'<input type="hidden" id="rr_list" name="rr_list" value="[]" />',
html=True)
self.assertContains(response,
'<input type="hidden" id="dns_server" name="dns_server" value="testserver.test.net" />',
html=True)
dns_server = "testserver.test.net"
zone_name = "testzone1.test.net"
response = self.client.post(reverse("delete_record",
kwargs={'dns_server': dns_server,
'zone_name': zone_name}),
{"rr_list": []}, follow=True)
self.assertRedirects(response,
reverse("zone_list",
kwargs={'dns_server': dns_server,
'zone_name': zone_name}))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Select at least one record for deletion.")
def test_DeleteRecordInitial(self):
"""Ensure the initial deletion form works as expected with RRs mentioned."""
response = self.client.post(reverse("delete_record"), {"dns_server": "testserver.test.net",
"zone_name": "testzone1.test.net",
"rr_list": ["testrecord1.testzone1.test.net",
"testrecord2.testzone1.test.net"]})
dns_server = "testserver.test.net"
zone_name = "testzone1.test.net"
response = self.client.post(reverse("delete_record",
kwargs={'dns_server': dns_server,
'zone_name': zone_name}),
{"rr_list": ["testrecord1.testzone1.test.net",
"testrecord2.testzone1.test.net"]})
self.assertEqual(response.status_code, 200)
self.assertContains(response,
'<input type="hidden" id="zone_name" name="zone_name" value="testzone1.test.net" />', html=True)
self.assertContains(response,

View File

@ -15,11 +15,6 @@ urlpatterns = patterns('',
url(r'^info/(?P<dns_server>[a-zA-Z0-9.-]+)/(?P<zone_name>[a-zA-Z0-9.-]+)/$', 'binder.views.view_zone_records', name="zone_list"),
url(r'^add_record/(?P<dns_server>[a-zA-Z0-9.-]+)/(?P<zone_name>[a-zA-Z0-9.-]+)/$', 'binder.views.view_add_record', name="add_record"),
url(r'^add_record/result/$', 'binder.views.view_add_record_result', name="add_record_result"),
url(r'^delete_record/$', 'binder.views.view_delete_record', name="delete_record"),
url(r'^delete_record/result/$', 'binder.views.view_delete_result', name="delete_record_result"),
url(r'^add_cname/(?P<dns_server>[a-zA-Z0-9.-]+)/(?P<zone_name>[a-zA-Z0-9.-]+)/(?P<record_name>.*?)/$', 'binder.views.view_add_cname_record', name="add_cname"),
url(r'^add_cname_record/result/$', 'binder.views.view_add_cname_result', name="add_cname_result"),
url(r'^delete_record/(?P<dns_server>[a-zA-Z0-9.-]+)/(?P<zone_name>[a-zA-Z0-9.-]+)/$', 'binder.views.view_delete_record', name="delete_record"),
)

View File

@ -1,12 +1,12 @@
# Binder VIews
# 3rd Party
from django.conf import settings
from django.contrib import messages
from django.shortcuts import get_object_or_404, redirect, render
# App Imports
from binder import exceptions, forms, helpers, models
from binder import forms, helpers, models
from binder.exceptions import KeyringException, RecordException, TransferException, ZoneException
def home_index(request):
"""List the main index page for Binder."""
@ -27,184 +27,147 @@ def view_server_list(request):
def view_server_zones(request, dns_server):
"""Display the list of DNS zones a particular DNS host provides."""
errors = ""
zone_array = {}
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
try:
zone_array = this_server.list_zones()
except exceptions.ZoneException, err:
errors = "Unable to list server zones. Error: %s" % err
except ZoneException as exc:
messages.error(request, "Unable to list server zones. Error: %s" % exc)
return render(request, "bcommon/list_server_zones.html",
{"errors": errors,
"dns_server": this_server,
{"dns_server": this_server,
"zone_array": zone_array})
def view_zone_records(request, dns_server, zone_name):
"""Display the list of records for a particular zone."""
errors = ""
zone_array = {}
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
try:
zone_array = this_server.list_zone_records(zone_name)
except exceptions.TransferException, err:
except TransferException as exc:
return render(request, "bcommon/list_zone.html",
{"errors": err,
"zone_name": zone_name,
{"zone_name": zone_name,
"dns_server": this_server})
return render(request, "bcommon/list_zone.html",
{"zone_array": zone_array,
"dns_server": this_server,
"zone_name": zone_name,
"errors": errors})
"zone_name": zone_name})
def view_add_record(request, dns_server, zone_name):
"""View to provide form to add a DNS record."""
"""View to allow to add A records."""
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
if request.method == 'POST':
form = forms.FormAddForwardRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
try:
helpers.add_record(form_cleaned["dns_server"],
str(form_cleaned["zone_name"]),
str(form_cleaned["record_name"]),
str(form_cleaned["record_type"]),
str(form_cleaned["record_data"]),
form_cleaned["ttl"],
form_cleaned["key_name"],
form_cleaned["create_reverse"])
except (KeyringException, RecordException) as exc:
messages.error(request, "Adding %s.%s failed: %s" %
(form_cleaned["record_name"], zone_name, exc))
else:
messages.success(request, "%s.%s was added successfully." %
(form_cleaned["record_name"], zone_name))
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
else:
form = forms.FormAddForwardRecord(initial={'zone_name': zone_name})
return render(request, "bcommon/add_record_form.html",
{"dns_server": this_server,
"zone_name": zone_name,
"tsig_keys": models.Key.objects.all(),
"ttl_choices": settings.TTL_CHOICES,
"record_type_choices": settings.RECORD_TYPE_CHOICES})
def view_add_record_result(request):
"""Process the input given to add a DNS record."""
errors = ""
if request.method == "GET":
return redirect("/")
if "HTTP_REFERER" in request.META:
incoming_zone = request.META["HTTP_REFERER"].split("/")[-2]
if ("in-addr.arpa" in incoming_zone) or ("ip6.arpa" in incoming_zone):
form = forms.FormAddReverseRecord(request.POST)
else:
form = forms.FormAddForwardRecord(request.POST)
else:
form = forms.FormAddForwardRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
try:
response = helpers.add_record(form_cleaned["dns_server"],
str(form_cleaned["zone_name"]),
str(form_cleaned["record_name"]),
str(form_cleaned["record_type"]),
str(form_cleaned["record_data"]),
form_cleaned["ttl"],
form_cleaned["key_name"],
form_cleaned["create_reverse"])
except exceptions.RecordException, err:
# TODO: Start using this exception.
# What would cause this?
errors = err
return render(request, "bcommon/response_result.html",
{"errors": errors,
"response": response})
dns_server = models.BindServer.objects.get(hostname=request.POST["dns_server"])
return render(request, "bcommon/add_record_form.html",
{"dns_server": dns_server,
"zone_name": request.POST["zone_name"],
"tsig_keys": models.Key.objects.all(),
"ttl_choices": settings.TTL_CHOICES,
"record_type_choices": settings.RECORD_TYPE_CHOICES,
"form": form})
def view_add_cname_record(request, dns_server, zone_name, record_name):
"""Process given input to add a CNAME pointer."""
"""View to allow to add CNAME records."""
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
if request.method == 'POST':
form = forms.FormAddCnameRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
try:
helpers.add_cname_record(form_cleaned["dns_server"],
str(form_cleaned["zone_name"]),
str(form_cleaned["cname"]),
'%s.%s' % (str(form_cleaned["originating_record"]),
str(form_cleaned["zone_name"])),
form_cleaned["ttl"],
form_cleaned["key_name"])
except (KeyringException, RecordException) as exc:
messages.error(request, "Adding %s.%s failed: %s" %
(form_cleaned["record_name"], zone_name, exc))
else:
messages.success(request, "%s.%s was added successfully." %
(form_cleaned["record_name"], zone_name))
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
else:
form = forms.FormAddCnameRecord(initial={'originating_record': record_name,
'zone_name': zone_name})
return render(request, "bcommon/add_cname_record_form.html",
{"dns_server": this_server,
"originating_record": "%s.%s" % (record_name, zone_name),
"zone_name": zone_name,
"ttl_choices": settings.TTL_CHOICES,
"tsig_keys": models.Key.objects.all()})
def view_add_cname_result(request):
"""Process input on the CNAME form and provide a response."""
if request.method == "GET":
return redirect("/")
errors = ""
add_cname_response = ""
form = forms.FormAddCnameRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
try:
add_cname_response = helpers.add_cname_record(
form_cleaned["dns_server"],
form_cleaned["zone_name"],
form_cleaned["cname"],
str(form_cleaned["originating_record"]),
form_cleaned["ttl"],
form_cleaned["key_name"])
except exceptions.RecordException, err:
errors = err
return render(request, "bcommon/response_result.html",
{"response": add_cname_response,
"errors": errors})
dns_server = models.BindServer.objects.get(hostname=request.POST["dns_server"])
return render(request, "bcommon/add_cname_record_form.html",
{"dns_server": dns_server,
"zone_name": request.POST["zone_name"],
"record_name": request.POST["cname"],
"originating_record": request.POST["originating_record"],
"ttl_choices": settings.TTL_CHOICES,
"tsig_keys": models.Key.objects.all(),
"form": form})
def view_delete_record(request):
"""Provide the initial form for deleting records."""
if request.method == "GET":
return redirect("/")
dns_server = models.BindServer.objects.get(hostname=request.POST["dns_server"])
zone_name = request.POST["zone_name"]
def view_delete_record(request, dns_server, zone_name):
"""View to handle the deletion of records."""
dns_server = models.BindServer.objects.get(hostname=dns_server)
rr_list = request.POST.getlist("rr_list")
return render(request, "bcommon/delete_record_initial.html",
if len(rr_list) == 0:
messages.error(request, "Select at least one record for deletion.")
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
if request.method == 'POST':
form = forms.FormDeleteRecord(request.POST)
if form.is_valid():
form_cleaned = form.cleaned_data
rr_list = form_cleaned["rr_list"]
try:
response = helpers.delete_record(form_cleaned["dns_server"],
rr_list,
form_cleaned["key_name"])
except KeyringException as exc:
for record in rr_list:
messages.error(request, "Deleting %s.%s failed: %s" %
(record, zone_name, exc))
else:
for record in response:
if record['success'] == True:
messages.success(request, "%s.%s was removed successfully." %
(record['record'], zone_name))
else:
messages.error(request, "Deleting %s.%s failed: %s" %
(record['record'], zone_name, record['description']))
return redirect('zone_list',
dns_server=dns_server,
zone_name=zone_name)
else:
form = forms.FormDeleteRecord(initial={'zone_name': zone_name})
return render(request, "bcommon/delete_record.html",
{"dns_server": dns_server,
"zone_name": zone_name,
"rr_list": rr_list,
"tsig_keys": models.Key.objects.all()})
def view_delete_result(request):
"""View that deletes records and returns the response."""
if request.method == "GET":
return redirect("/")
form = forms.FormDeleteRecord(request.POST)
if form.is_valid():
clean_form = form.cleaned_data
else:
# TODO: What situations would cause this form
# not to validate?
print "in view_delete_result, form errors: %r" % form.errors
delete_result = helpers.delete_record(clean_form["dns_server"],
clean_form["rr_list"],
clean_form["key_name"])
return render(request, "bcommon/response_result.html",
{"response": delete_result})
"rr_list": rr_list,
"form": form})