Refactors the views used to add and delete records.
Notable changes are: * Refactored views, utilizing more of Djangos features, resulting in simpler code. * URLs are now the same when initially filling out a form and when editing a submitted form which contained errors. * Instead of a result page showing the response from the DNS server (which is now logged using Djangos "logging" functionality) the user is now redirected back to the record listing of the current zone when the action was successful or stays on the form page when an error occured. Proper success/error messages are shown in both cases by utilizing Djangos "messages" functionality.
This commit is contained in:
parent
7b3a24364c
commit
e13b42cd13
|
@ -17,7 +17,7 @@ class ZoneException(Exception):
|
||||||
|
|
||||||
class RecordException(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.
|
* Adding or deleting.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -17,7 +17,8 @@ class CustomUnicodeListField(forms.CharField):
|
||||||
try:
|
try:
|
||||||
string_list = [str(cur_rr) for cur_rr in eval(value)]
|
string_list = [str(cur_rr) for cur_rr in eval(value)]
|
||||||
except:
|
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
|
return string_list
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +38,8 @@ class CustomStringPeriodSuffix(forms.CharField):
|
||||||
if new_string[-1] != ".":
|
if new_string[-1] != ".":
|
||||||
new_string += "."
|
new_string += "."
|
||||||
except:
|
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
|
return new_string
|
||||||
|
|
||||||
|
@ -50,13 +52,17 @@ class FormAddForwardRecord(forms.Form):
|
||||||
record_name = forms.RegexField(max_length=100,
|
record_name = forms.RegexField(max_length=100,
|
||||||
regex="^[a-zA-Z0-9-_]+$",
|
regex="^[a-zA-Z0-9-_]+$",
|
||||||
required=False)
|
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)
|
zone_name = forms.CharField(max_length=100)
|
||||||
record_data = forms.GenericIPAddressField()
|
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)
|
create_reverse = forms.BooleanField(required=False)
|
||||||
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
|
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
|
||||||
required=False)
|
required=False,
|
||||||
|
widget=forms.RadioSelect,
|
||||||
|
empty_label=None)
|
||||||
|
|
||||||
|
|
||||||
class FormAddReverseRecord(forms.Form):
|
class FormAddReverseRecord(forms.Form):
|
||||||
|
@ -66,12 +72,16 @@ class FormAddReverseRecord(forms.Form):
|
||||||
dns_server = forms.CharField(max_length=100)
|
dns_server = forms.CharField(max_length=100)
|
||||||
record_name = forms.IntegerField(min_value=0, max_value=255)
|
record_name = forms.IntegerField(min_value=0, max_value=255)
|
||||||
record_type = forms.RegexField(regex=r"^PTR$",
|
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)
|
zone_name = forms.CharField(max_length=100)
|
||||||
record_data = CustomStringPeriodSuffix(required=True)
|
record_data = CustomStringPeriodSuffix(required=True)
|
||||||
ttl = forms.ChoiceField(choices=settings.TTL_CHOICES)
|
ttl = forms.ChoiceField(choices=settings.TTL_CHOICES)
|
||||||
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
|
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
|
||||||
required=False)
|
required=False,
|
||||||
|
widget=forms.RadioSelect,
|
||||||
|
empty_label=None)
|
||||||
create_reverse = forms.BooleanField(required=False)
|
create_reverse = forms.BooleanField(required=False)
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,9 +93,12 @@ class FormAddCnameRecord(forms.Form):
|
||||||
originating_record = forms.CharField(max_length=100)
|
originating_record = forms.CharField(max_length=100)
|
||||||
cname = forms.RegexField(max_length=100, regex="^[a-zA-Z0-9-_]+$")
|
cname = forms.RegexField(max_length=100, regex="^[a-zA-Z0-9-_]+$")
|
||||||
zone_name = forms.CharField(max_length=256)
|
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(),
|
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
|
||||||
required=False)
|
required=False,
|
||||||
|
widget=forms.RadioSelect,
|
||||||
|
empty_label=None)
|
||||||
|
|
||||||
|
|
||||||
class FormDeleteRecord(forms.Form):
|
class FormDeleteRecord(forms.Form):
|
||||||
|
@ -96,4 +109,6 @@ class FormDeleteRecord(forms.Form):
|
||||||
zone_name = forms.CharField(max_length=256)
|
zone_name = forms.CharField(max_length=256)
|
||||||
rr_list = CustomUnicodeListField()
|
rr_list = CustomUnicodeListField()
|
||||||
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
|
key_name = forms.ModelChoiceField(queryset=Key.objects.all(),
|
||||||
required=False)
|
required=False,
|
||||||
|
widget=forms.RadioSelect,
|
||||||
|
empty_label=None)
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
# Binder Helpers
|
# Binder Helpers
|
||||||
|
|
||||||
# Standard Imports
|
# Standard Imports
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
# 3rd Party
|
# 3rd Party
|
||||||
import dns.query
|
import dns.query
|
||||||
|
import dns.rcode
|
||||||
import dns.reversename
|
import dns.reversename
|
||||||
import dns.tsig
|
import dns.tsig
|
||||||
import dns.tsigkeyring
|
import dns.tsigkeyring
|
||||||
|
@ -13,6 +15,7 @@ import dns.update
|
||||||
|
|
||||||
# App Imports
|
# App Imports
|
||||||
from binder import models
|
from binder import models
|
||||||
|
from binder.exceptions import KeyringException, RecordException
|
||||||
|
|
||||||
|
|
||||||
def add_record(dns_server, zone_name, record_name, record_type, record_data,
|
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."""
|
"""Delete a list of DNS records passed as strings in rr_items."""
|
||||||
server = models.BindServer.objects.get(hostname=dns_server)
|
server = models.BindServer.objects.get(hostname=dns_server)
|
||||||
|
|
||||||
|
logger = logging.getLogger('binder.helpers')
|
||||||
try:
|
try:
|
||||||
transfer_key = models.Key.objects.get(name=key_name)
|
transfer_key = models.Key.objects.get(name=key_name)
|
||||||
except models.Key.DoesNotExist:
|
except models.Key.DoesNotExist as exc:
|
||||||
keyring = None
|
logger.error(exc)
|
||||||
algorithm = None
|
raise KeyringException("The specified TSIG key %s does not exist in "
|
||||||
|
"binders configuration." % key_name)
|
||||||
else:
|
else:
|
||||||
keyring = transfer_key.create_keyring()
|
keyring = transfer_key.create_keyring()
|
||||||
algorithm = transfer_key.algorithm
|
algorithm = transfer_key.algorithm
|
||||||
|
@ -107,13 +112,19 @@ def delete_record(dns_server, rr_list, key_name):
|
||||||
keyring=keyring,
|
keyring=keyring,
|
||||||
keyalgorithm=algorithm)
|
keyalgorithm=algorithm)
|
||||||
dns_update.delete(record)
|
dns_update.delete(record)
|
||||||
output = send_dns_update(dns_update,
|
try:
|
||||||
dns_server,
|
output = send_dns_update(dns_update,
|
||||||
server.dns_port,
|
dns_server,
|
||||||
key_name)
|
server.dns_port,
|
||||||
|
key_name)
|
||||||
delete_response.append({"description": "Delete Record: %s" % current_rr,
|
except (KeyringException, RecordException) as exc:
|
||||||
"output": output})
|
delete_response.append({"description": exc,
|
||||||
|
"record": current_rr,
|
||||||
|
"success": False})
|
||||||
|
else:
|
||||||
|
delete_response.append({"description": output,
|
||||||
|
"record": current_rr,
|
||||||
|
"success": True})
|
||||||
|
|
||||||
return delete_response
|
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."""
|
"""Update/Create DNS record of name and type with passed data and ttl."""
|
||||||
server = models.BindServer.objects.get(hostname=dns_server)
|
server = models.BindServer.objects.get(hostname=dns_server)
|
||||||
|
|
||||||
|
logger = logging.getLogger('binder.helpers')
|
||||||
try:
|
try:
|
||||||
transfer_key = models.Key.objects.get(name=key_name)
|
transfer_key = models.Key.objects.get(name=key_name)
|
||||||
except models.Key.DoesNotExist:
|
except models.Key.DoesNotExist as exc:
|
||||||
keyring = None
|
logger.error(exc)
|
||||||
algorithm = None
|
raise KeyringException("The specified TSIG key %s does not exist in "
|
||||||
|
"binders configuration." % key_name)
|
||||||
else:
|
else:
|
||||||
keyring = transfer_key.create_keyring()
|
keyring = transfer_key.create_keyring()
|
||||||
algorithm = transfer_key.algorithm
|
algorithm = transfer_key.algorithm
|
||||||
|
@ -174,13 +187,21 @@ def send_dns_update(dns_message, dns_server, port, key_name):
|
||||||
Returns:
|
Returns:
|
||||||
String output
|
String output
|
||||||
"""
|
"""
|
||||||
|
logger = logging.getLogger('binder.helpers')
|
||||||
try:
|
try:
|
||||||
output = dns.query.tcp(dns_message, dns_server, port=port)
|
output = dns.query.tcp(dns_message, dns_server, port=port)
|
||||||
except dns.tsig.PeerBadKey:
|
except dns.tsig.PeerBadKey as exc:
|
||||||
output = ("DNS server %s is not configured for TSIG key: %s." %
|
logger.error(exc)
|
||||||
(dns_server, key_name))
|
raise KeyringException("DNS server %s is not configured for TSIG key: %s." %
|
||||||
except dns.tsig.PeerBadSignature:
|
(dns_server, key_name))
|
||||||
output = ("DNS server %s did like the TSIG signature we sent. Check "
|
except dns.tsig.PeerBadSignature as exc:
|
||||||
"key %s for correctness." % (dns_server, key_name))
|
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
|
return output
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Django settings for binder project.
|
# Django settings for binder project.
|
||||||
import os
|
import os
|
||||||
|
from django.contrib.messages import constants as messages
|
||||||
|
|
||||||
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
|
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
@ -88,6 +89,38 @@ INSTALLED_APPS = (
|
||||||
|
|
||||||
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
|
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"),
|
TTL_CHOICES = ((300, "5 minutes"),
|
||||||
(1800, "30 minutes"),
|
(1800, "30 minutes"),
|
||||||
(3600, "1 hour"),
|
(3600, "1 hour"),
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
<script src="{% static "sorttable.js" %}"></script>
|
<script src="{% static "sorttable.js" %}"></script>
|
||||||
</head>
|
</head>
|
||||||
{% endblock header %}
|
{% endblock header %}
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<script src="{% static "jquery-2.1.3.min.js" %}"></script>
|
<script src="{% static "jquery-2.1.3.min.js" %}"></script>
|
||||||
<script src="{% static "bootstrap/js/bootstrap.min.js" %}"></script>
|
<script src="{% static "bootstrap/js/bootstrap.min.js" %}"></script>
|
||||||
|
@ -35,6 +34,8 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
@ -44,23 +45,17 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
{% block errors %}
|
{% if messages %}
|
||||||
{% if errors %}
|
<ul id="messages" class="list-unstyled text-center" style="margin-bottom: 2em;">
|
||||||
<div class="alert alert-error">
|
{% for message in messages %}
|
||||||
Errors were encountered:
|
<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>
|
||||||
<br />
|
{% endfor %}
|
||||||
{{ errors }}
|
</ul>
|
||||||
</div>
|
{% endif %}
|
||||||
{% endif %}
|
{% block body %}{% endblock body %}
|
||||||
{% endblock errors %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
{% endblock body %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% block footer %}{% endblock footer %}
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
{% block footer %}
|
|
||||||
{% endblock footer %}
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{% extends "base.html" %}
|
{% 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 %}
|
{% 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>
|
<legend>Create CNAME record</legend>
|
||||||
|
|
||||||
<div class="form-group{% if form.dns_server.errors %} has-error{% endif %}">
|
<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 %}">
|
<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>
|
<label for="originating_record" class="col-sm-3 control-label">Originating Record: </label>
|
||||||
<div class="col-sm-5 col-md-4">
|
<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>
|
</div>
|
||||||
{% if form.originating_record.errors %}
|
{% if form.originating_record.errors %}
|
||||||
<div class="col-sm-4 col-md-5">
|
<div class="col-sm-4 col-md-5">
|
||||||
|
@ -41,8 +41,8 @@
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="cname" name="cname" type="text" class="form-control"{% if form.cname.value %} value="{{ form.cname.value }}"{% endif %}/>
|
<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>
|
<span class="input-group-addon">.{{ form.zone_name.value }}</span>
|
||||||
<input type="hidden" name="zone_name" value="{{zone_name}}"/>
|
<input type="hidden" name="zone_name" value="{{ form.zone_name.value }}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if form.cname.errors %}
|
{% if form.cname.errors %}
|
||||||
|
@ -58,10 +58,8 @@
|
||||||
<label for="ttl" class="col-sm-3 control-label">TTL: </label>
|
<label for="ttl" class="col-sm-3 control-label">TTL: </label>
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<select id="ttl" name="ttl" class="form-control">
|
<select id="ttl" name="ttl" class="form-control">
|
||||||
{% for ttl, description in ttl_choices %}
|
{% for choice in form.ttl %}
|
||||||
<option value="{{ttl}}">
|
<option value="{{ choice.choice_value }}">{{ choice.choice_value }} ({{ choice.choice_label }})</option>
|
||||||
{{ttl}} ({{description}})
|
|
||||||
</option>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -79,10 +77,10 @@
|
||||||
<label for="key_name" class="col-sm-3 control-label">TSIG Key:</label>
|
<label for="key_name" class="col-sm-3 control-label">TSIG Key:</label>
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<select id="key_name" name="key_name" class="form-control">
|
<select id="key_name" name="key_name" class="form-control">
|
||||||
{% for key in tsig_keys %}
|
{% for key in form.key_name %}
|
||||||
<option value="{{key.id}}"{% if key == dns_server.default_transfer_key %} selected="selected"{% endif %}>{{key}}</option>
|
<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 %}
|
{% empty %}
|
||||||
<option selected="selected" value=""/>
|
<option selected="selected" value="" />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,7 +98,7 @@
|
||||||
<div class="col-sm-3"></div>
|
<div class="col-sm-3"></div>
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<button type="submit" class="btn btn-default">Save Changes</button>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{% extends "base.html" %}
|
{% 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 %}
|
{% 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>
|
<legend>Create Record</legend>
|
||||||
|
|
||||||
<div class="form-group{% if form.dns_server.errors %} has-error{% endif %}">
|
<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="col-sm-5 col-md-4">
|
||||||
<div class="input-group">
|
<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 %} />
|
<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>
|
<span class="input-group-addon">.{{ form.zone_name.value }}</span>
|
||||||
<input type="hidden" name="zone_name" value="{{zone_name}}" />
|
<input type="hidden" name="zone_name" value="{{ form.zone_name.value }}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if form.record_name.errors %}
|
{% if form.record_name.errors %}
|
||||||
|
@ -43,9 +43,9 @@
|
||||||
<label for="record_type" class="col-sm-3 control-label">Record Type:</label>
|
<label for="record_type" class="col-sm-3 control-label">Record Type:</label>
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<select id="record_type" name="record_type" class="form-control">
|
<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 %}
|
{% if "in-addr.arpa" not in form.zone_name.value and "ip6.arpa" not in form.zone_name.value %}
|
||||||
{% for type, name in record_type_choices %}
|
{% for choice in form.record_type %}
|
||||||
<option value="{{name}}">{{name}}</option>
|
<option value="{{ choice.choice_value }}">{{ choice.choice_label }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<option value="PTR">PTR</option>
|
<option value="PTR">PTR</option>
|
||||||
|
@ -80,10 +80,8 @@
|
||||||
<label for="ttl" class="col-sm-3 control-label">TTL: </label>
|
<label for="ttl" class="col-sm-3 control-label">TTL: </label>
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<select id="ttl" name="ttl" class="form-control">
|
<select id="ttl" name="ttl" class="form-control">
|
||||||
{% for ttl, description in ttl_choices %}
|
{% for choice in form.ttl %}
|
||||||
<option value="{{ttl}}">
|
<option value="{{ choice.choice_value }}">{{ choice.choice_value }} ({{ choice.choice_label }})</option>
|
||||||
{{ttl}} ({{description}})
|
|
||||||
</option>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -97,7 +95,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</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">
|
<div class="form-group">
|
||||||
<label for="create_reverse" class="col-sm-3 control-label checkbox">Create Reverse Record (PTR):</label>
|
<label for="create_reverse" class="col-sm-3 control-label checkbox">Create Reverse Record (PTR):</label>
|
||||||
<div class="col-sm-5 col-md-4">
|
<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>
|
<label for="key_name" class="col-sm-3 control-label">TSIG Key:</label>
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<select id="key_name" name="key_name" class="form-control">
|
<select id="key_name" name="key_name" class="form-control">
|
||||||
{% for key in tsig_keys %}
|
{% for key in form.key_name %}
|
||||||
<option value="{{key.id}}"{% if key == dns_server.default_transfer_key %} selected="selected"{% endif %}>{{key}}</option>
|
<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 %}
|
{% empty %}
|
||||||
<option selected="selected" value=""/>
|
<option selected="selected" value="" />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -131,7 +129,7 @@
|
||||||
<div class="col-sm-3"></div>
|
<div class="col-sm-3"></div>
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<button type="submit" class="btn btn-default">Save Changes</button>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
{% block pageheader %}Delete record(s) in {{ zone_name }}{% endblock pageheader %}
|
{% block pageheader %}Delete record(s) in {{ zone_name }}{% endblock pageheader %}
|
||||||
|
|
||||||
{% block body %}
|
{% 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>
|
<legend>Delete Record</legend>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -39,10 +39,10 @@
|
||||||
<label for="key_name" class="col-sm-3 control-label">TSIG Key:</label>
|
<label for="key_name" class="col-sm-3 control-label">TSIG Key:</label>
|
||||||
<div class="col-sm-5 col-md-4">
|
<div class="col-sm-5 col-md-4">
|
||||||
<select id="key_name" name="key_name" class="form-control">
|
<select id="key_name" name="key_name" class="form-control">
|
||||||
{% for key in tsig_keys %}
|
{% for key in form.key_name %}
|
||||||
<option value="{{key.id}}"{% if key == dns_server.default_transfer_key %} selected="selected"{% endif %}>{{key}}</option>
|
<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 %}
|
{% empty %}
|
||||||
<option selected="selected" value=""/>
|
<option selected="selected" value="" />
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
|
@ -3,13 +3,9 @@
|
||||||
{% block pageheader %}Zone listing for {{ zone_name }} on {{ dns_server.hostname }}{% endblock pageheader %}
|
{% block pageheader %}Zone listing for {{ zone_name }} on {{ dns_server.hostname }}{% endblock pageheader %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% if not errors %}
|
<p><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>
|
|
||||||
|
|
||||||
<form action="{% url "delete_record" %}" method="post">{% csrf_token %}
|
<form action="{% url "delete_record" dns_server=dns_server zone_name=zone_name %}" method="post">{% csrf_token %}
|
||||||
|
|
||||||
<input type="hidden" name="dns_server" value="{{ dns_server.hostname }}">
|
|
||||||
<input type="hidden" name="zone_name" value="{{ zone_name }}">
|
|
||||||
|
|
||||||
<table class="sortable table table-condensed table-hover">
|
<table class="sortable table table-condensed table-hover">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -48,7 +44,6 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<button class="btn btn-danger" type="submit">Delete Selected</button>
|
<p><button class="btn btn-danger" type="submit">Delete Selected</button></p>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
|
@ -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 %}
|
|
|
@ -27,18 +27,6 @@ class GetTests(TestCase):
|
||||||
response = self.client.get(reverse("server_list"))
|
response = self.client.get(reverse("server_list"))
|
||||||
self.assertEqual(response.status_code, 200)
|
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):
|
def test_GetInvalidServer(self):
|
||||||
"""Get a zone list for a server not in the database."""
|
"""Get a zone list for a server not in the database."""
|
||||||
server_name = "unconfigured.server.net"
|
server_name = "unconfigured.server.net"
|
||||||
|
@ -64,20 +52,18 @@ class PostTests(TestCase):
|
||||||
|
|
||||||
def test_DeleteRecordInitial_Empty(self):
|
def test_DeleteRecordInitial_Empty(self):
|
||||||
"""Ensure the initial deletion form works as expected with no RR list."""
|
"""Ensure the initial deletion form works as expected with no RR list."""
|
||||||
|
dns_server = "testserver.test.net"
|
||||||
|
zone_name = "testzone1.test.net"
|
||||||
response = self.client.post(reverse("delete_record"),
|
response = self.client.post(reverse("delete_record"),
|
||||||
{"dns_server": "testserver.test.net",
|
{"dns_server": dns_server,
|
||||||
"zone_name": "testzone1.test.net",
|
"zone_name": zone_name,
|
||||||
"rr_list": []})
|
"rr_list": []}, follow=True)
|
||||||
|
self.assertRedirects(response,
|
||||||
self.assertContains(response,
|
reverse("zone_list",
|
||||||
'<input type="hidden" id="zone_name" name="zone_name" value="testzone1.test.net" />',
|
kwargs={'dns_server': dns_server,
|
||||||
html=True)
|
'zone_name': zone_name}))
|
||||||
self.assertContains(response,
|
self.assertEqual(response.status_code, 200)
|
||||||
'<input type="hidden" id="rr_list" name="rr_list" value="[]" />',
|
self.assertContains(response, "Select at least one record for deletion.")
|
||||||
html=True)
|
|
||||||
self.assertContains(response,
|
|
||||||
'<input type="hidden" id="dns_server" name="dns_server" value="testserver.test.net" />',
|
|
||||||
html=True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_DeleteRecordInitial(self):
|
def test_DeleteRecordInitial(self):
|
||||||
|
@ -86,6 +72,8 @@ class PostTests(TestCase):
|
||||||
"zone_name": "testzone1.test.net",
|
"zone_name": "testzone1.test.net",
|
||||||
"rr_list": ["testrecord1.testzone1.test.net",
|
"rr_list": ["testrecord1.testzone1.test.net",
|
||||||
"testrecord2.testzone1.test.net"]})
|
"testrecord2.testzone1.test.net"]})
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertContains(response,
|
self.assertContains(response,
|
||||||
'<input type="hidden" id="zone_name" name="zone_name" value="testzone1.test.net" />', html=True)
|
'<input type="hidden" id="zone_name" name="zone_name" value="testzone1.test.net" />', html=True)
|
||||||
self.assertContains(response,
|
self.assertContains(response,
|
||||||
|
|
|
@ -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'^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/(?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/(?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"),
|
||||||
)
|
)
|
||||||
|
|
237
binder/views.py
237
binder/views.py
|
@ -1,12 +1,12 @@
|
||||||
# Binder VIews
|
# Binder VIews
|
||||||
|
|
||||||
# 3rd Party
|
# 3rd Party
|
||||||
from django.conf import settings
|
from django.contrib import messages
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
|
||||||
# App Imports
|
# 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):
|
def home_index(request):
|
||||||
"""List the main index page for Binder."""
|
"""List the main index page for Binder."""
|
||||||
|
@ -27,184 +27,147 @@ def view_server_list(request):
|
||||||
|
|
||||||
def view_server_zones(request, dns_server):
|
def view_server_zones(request, dns_server):
|
||||||
"""Display the list of DNS zones a particular DNS host provides."""
|
"""Display the list of DNS zones a particular DNS host provides."""
|
||||||
errors = ""
|
|
||||||
zone_array = {}
|
zone_array = {}
|
||||||
|
|
||||||
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
|
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
zone_array = this_server.list_zones()
|
zone_array = this_server.list_zones()
|
||||||
except exceptions.ZoneException, err:
|
except ZoneException as exc:
|
||||||
errors = "Unable to list server zones. Error: %s" % err
|
messages.error(request, "Unable to list server zones. Error: %s" % exc)
|
||||||
|
|
||||||
return render(request, "bcommon/list_server_zones.html",
|
return render(request, "bcommon/list_server_zones.html",
|
||||||
{"errors": errors,
|
{"dns_server": this_server,
|
||||||
"dns_server": this_server,
|
|
||||||
"zone_array": zone_array})
|
"zone_array": zone_array})
|
||||||
|
|
||||||
|
|
||||||
def view_zone_records(request, dns_server, zone_name):
|
def view_zone_records(request, dns_server, zone_name):
|
||||||
"""Display the list of records for a particular zone."""
|
"""Display the list of records for a particular zone."""
|
||||||
errors = ""
|
|
||||||
zone_array = {}
|
zone_array = {}
|
||||||
|
|
||||||
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
|
this_server = get_object_or_404(models.BindServer, hostname=dns_server)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
zone_array = this_server.list_zone_records(zone_name)
|
zone_array = this_server.list_zone_records(zone_name)
|
||||||
except exceptions.TransferException, err:
|
except TransferException as exc:
|
||||||
return render(request, "bcommon/list_zone.html",
|
return render(request, "bcommon/list_zone.html",
|
||||||
{"errors": err,
|
{"zone_name": zone_name,
|
||||||
"zone_name": zone_name,
|
|
||||||
"dns_server": this_server})
|
"dns_server": this_server})
|
||||||
|
|
||||||
return render(request, "bcommon/list_zone.html",
|
return render(request, "bcommon/list_zone.html",
|
||||||
{"zone_array": zone_array,
|
{"zone_array": zone_array,
|
||||||
"dns_server": this_server,
|
"dns_server": this_server,
|
||||||
"zone_name": zone_name,
|
"zone_name": zone_name})
|
||||||
"errors": errors})
|
|
||||||
|
|
||||||
|
|
||||||
def view_add_record(request, dns_server, 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)
|
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",
|
return render(request, "bcommon/add_record_form.html",
|
||||||
{"dns_server": this_server,
|
{"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})
|
"form": form})
|
||||||
|
|
||||||
|
|
||||||
def view_add_cname_record(request, dns_server, zone_name, record_name):
|
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)
|
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",
|
return render(request, "bcommon/add_cname_record_form.html",
|
||||||
{"dns_server": this_server,
|
{"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})
|
"form": form})
|
||||||
|
|
||||||
|
|
||||||
def view_delete_record(request):
|
def view_delete_record(request, dns_server, zone_name):
|
||||||
"""Provide the initial form for deleting records."""
|
"""View to handle the deletion of records."""
|
||||||
if request.method == "GET":
|
dns_server = models.BindServer.objects.get(hostname=dns_server)
|
||||||
return redirect("/")
|
|
||||||
|
|
||||||
dns_server = models.BindServer.objects.get(hostname=request.POST["dns_server"])
|
|
||||||
zone_name = request.POST["zone_name"]
|
|
||||||
rr_list = request.POST.getlist("rr_list")
|
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,
|
{"dns_server": dns_server,
|
||||||
"zone_name": zone_name,
|
"zone_name": zone_name,
|
||||||
"rr_list": rr_list,
|
"rr_list": rr_list,
|
||||||
"tsig_keys": models.Key.objects.all()})
|
"form": form})
|
||||||
|
|
||||||
|
|
||||||
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})
|
|
||||||
|
|
Loading…
Reference in New Issue