Commits

George Notaras committed 775c6f8

Added initial support for action that sets the TTL of all the zone records.

  • Participants
  • Parent commits 20fdad8

Comments (0)

Files changed (4)

src/powerdns_manager/actions.py

 from django.contrib import messages
 from django.shortcuts import render_to_response
 from django.template import RequestContext
+from django.db.models.loading import cache
 
 from powerdns_manager.forms import ZoneTypeSelectionForm
+from powerdns_manager.forms import TtlSelectionForm
+
 
 
 # Action for
     }
     return render_to_response(
         'powerdns_manager/actions/set_domain_type.html', info_dict, context_instance=RequestContext(request), mimetype='text/html')
+set_domain_type_bulk.short_description = "Set domain type"
+
+
+
+def set_ttl_bulk(modeladmin, request, queryset):
+    """Actions that resets TTL information on all resource records of the zone
+    to the specified value.
     
+    This action first displays a page which provides an input box to enter
+    the new TTL.
+    
+    It checks if the user has change permission.
+    
+    Based on: https://github.com/django/django/blob/1.4.2/django/contrib/admin/actions.py
+    
+    Important
+    ---------
+    In order to work requires some special form fields (see the template).
+    
+    """
+    opts = modeladmin.model._meta
+    app_label = opts.app_label
+    
+    Domain = cache.get_model('powerdns_manager', 'Domain')
+    Record = cache.get_model('powerdns_manager', 'Record')
+    
+    perm_domain_change = '%s.%s' % (opts.app_label, opts.get_change_permission())
+    perm_record_change = '%s.change_record' % opts.app_label
+    
+    if not request.user.has_perms([perm_domain_change, perm_record_change]):
+        raise PermissionDenied
+    
+    # Check that the user has change permission for the Re model
+    if not modeladmin.has_change_permission(request):
+        raise PermissionDenied
+    
+    # The user has set a new TTL value through the forms.TtlSelectionForm form.
+    # Make the changes to the selected objects and return a None to display the
+    # change list view again.
+    #if request.method == 'POST':
+    if request.POST.get('post'):
+        form = TtlSelectionForm(request.POST)
+        if form.is_valid():
+            new_ttl = form.cleaned_data['new_ttl']
+            reset_zone_minimum = form.cleaned_data['reset_zone_minimum']
+            
+            n = queryset.count()
+            record_count = 0
+            
+            if n and new_ttl:
+                for domain_obj in queryset:
+                    # Find all resource records of this domain
+                    qs = Record.objects.filter(domain=domain_obj)
+                    # Now set the new TTL
+                    for rr in qs:
+                        rr.ttl = int(new_ttl)
+                        # If this is the SOA record and ``reset_zone_minimum`` has
+                        # been checked, set the minimum TTL of the SOA record equal
+                        # to the ``new_ttl`` value
+                        if reset_zone_minimum and rr.type == 'SOA':
+                            bits = rr.content.split()
+                            # SOA content:  primary hostmaster serial refresh retry expire default_ttl
+                            bits[6] = str(new_ttl)
+                            rr.content = ' '.join(bits)
+                        # Save the resource record
+                        rr.save()
+                        rr_display = force_unicode(rr)
+                        modeladmin.log_change(request, rr, rr_display)
+                    record_count += len(qs)
+                messages.info(request, 'Successfully updated %d zones (%d total records).' % (n, record_count))
+            # Return None to display the change list page again.
+            return None
+    else:
+        form = TtlSelectionForm()
+    
+    info_dict = {
+        'form': form,
+        'queryset': queryset,
+        'opts': opts,
+        'app_label': app_label,
+        'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
+    }
+    return render_to_response(
+        'powerdns_manager/actions/set_ttl.html', info_dict, context_instance=RequestContext(request), mimetype='text/html')
+set_ttl_bulk.short_description = "Set Resource Records TTL"
+
+

src/powerdns_manager/admin.py

 from powerdns_manager.forms import RrsigRecordModelForm
 from powerdns_manager.models import zone_saved
 from powerdns_manager.actions import set_domain_type_bulk
+from powerdns_manager.actions import set_ttl_bulk
+
 
 
 class BaseTabularRecordInline(admin.TabularInline):
     verbose_name = 'zone'
     verbose_name_plural = 'zones'
     save_on_top = True
-    actions = [set_domain_type_bulk, ]
+    actions = [set_domain_type_bulk, set_ttl_bulk]
     
     #
     # Build the ``inlines`` list. Only inlines for enabled RR types are included.

src/powerdns_manager/forms.py

 from django.core.validators import validate_ipv6_address
 from django.core.exceptions import ValidationError
 
+from powerdns_manager import settings
+
 
 
 class BaseRecordModelForm(forms.ModelForm):
     domaintype = forms.ChoiceField(choices=Domain.DOMAIN_TYPE_CHOICES, required=True, label=_('Zone type'), help_text="""Select the zone type. Native refers to native SQL replication. Master/Slave refers to DNS server based zone transfers.""")
 
 
+
+class TtlSelectionForm(forms.Form):
+    """This form is used in intermediate page that sets the RR TTL in bulk."""
+    new_ttl = forms.IntegerField(min_value=settings.PDNS_DEFAULT_RR_TTL, required=True, label=_('New TTL'), help_text="""Enter the new Time-To-Live (TTL) in seconds.""")
+    reset_zone_minimum = forms.BooleanField(required=False, label=_('Reset minimum TTL of the zones?'), help_text="""If checked, the minimum TTL of the selected zones will be reset to the new TTL value.""")
+
+

src/powerdns_manager/templates/powerdns_manager/actions/set_ttl.html

+{% extends "admin/base_site.html" %}
+{% load i18n l10n static %}
+{% load url from future %}
+{% load admin_urls %}
+
+{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
+
+{% block breadcrumbs %}
+	<div class="breadcrumbs">
+		<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
+		&rsaquo; <a href="{% url 'admin:app_list' app_label=app_label %}">{{ app_label|capfirst|escape }}</a>
+		&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
+		&rsaquo; {% trans 'Set TTL on records of selected zones' %}
+	</div>
+{% endblock %}
+
+{% block title %}{% trans 'Set TTL' %}{% endblock %}
+
+{% block content %}
+    <div id="content-main">
+        
+        <form action="" method="post">{% csrf_token %}
+        <div>
+            {% if form.errors %}
+                <p class="errornote">
+                {% blocktrans count counter=form.errors.items|length %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
+                </p>
+            {% endif %}
+
+            <h1>{% trans 'Set TTL' %}</h1>
+            <p>{% trans "Enter the new TTL in seconds." %}</p>
+            
+            <fieldset class="module aligned">
+    
+                <div class="form-row">
+                    {{ form.new_ttl.errors }}
+                    <label for="id_new_ttl" class="">{% trans 'TTL' %}:</label>{{ form.new_ttl }}
+                </div>
+                
+                <div class="form-row">
+                    {{ form.reset_zone_minimum.errors }}
+                    <label for="id_reset_zone_minimum" class="">{% trans 'Reset zone minimum TTL' %}:</label>{{ form.reset_zone_minimum }}
+                </div>
+
+            </fieldset>
+
+            {# Special Fields #}
+            {# These are needed for the action code to work. This an undocumented Django feature #}
+            {% for obj in queryset %}
+                <input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
+            {% endfor %}
+            <input type="hidden" name="action" value="set_ttl_bulk" />
+            <input type="hidden" name="post" value="yes" />
+            
+            <div class="submit-row">
+                <input type="submit" value="{% trans 'Save' %}" class="default" />
+            </div>
+
+            <script type="text/javascript">document.getElementById("id_new_ttl").focus();</script>
+        </div>
+        </form>
+
+    </div> <!-- content-main -->
+{% endblock %}