From 5b584cd8ffa31beae58669129772df09dba8b1c0 Mon Sep 17 00:00:00 2001 From: Piotr Jarolewski Date: Thu, 17 Mar 2016 09:49:39 +0100 Subject: [PATCH] Create new DNS records --- src/ralph/dns/dnsaas.py | 168 +++++++++++++++++++++++++++---------- src/ralph/dns/views.py | 23 ++--- src/ralph/settings/base.py | 2 + 3 files changed, 132 insertions(+), 61 deletions(-) diff --git a/src/ralph/dns/dnsaas.py b/src/ralph/dns/dnsaas.py index c4180877ed..9ab5600b0a 100644 --- a/src/ralph/dns/dnsaas.py +++ b/src/ralph/dns/dnsaas.py @@ -4,6 +4,7 @@ import requests from django.conf import settings +from django.utils.lru_cache import lru_cache from ralph.dns.forms import RecordType @@ -22,6 +23,15 @@ def __init__(self, headers=None): self.session.headers.update(_headers) def get_api_result(self, url): + """ + Returns 'results' from DNSAAS API. + + Args: + url: Url to API + + Returns: + list of records + """ request = self.session.get(url) json_data = request.json() api_results = json_data.get('results', []) @@ -34,13 +44,14 @@ def get_dns_records(self, ipaddresses): """Gets DNS Records for `ipaddresses` by API call""" dns_records = [] ipaddresses = [('ip', i) for i in ipaddresses] - url = '{}/{}/?{}'.format( + url = urljoin( settings.DNSAAS_URL, - 'api/records', - urlencode([ - ('limit', 100), - ('offset', 0) - ] + ipaddresses) + 'api/records/?{}'.format( + urlencode([ + ('limit', 100), + ('offset', 0) + ] + ipaddresses) + ) ) api_results = self.get_api_result(url) ptr_list = set( @@ -53,46 +64,115 @@ def get_dns_records(self, ipaddresses): 'name': item['name'], 'type': RecordType.from_name(item['type'].lower()).id, 'content': item['content'], - 'ptr': item['name'] in ptr_list + 'ptr': item['name'] in ptr_list, + 'owner': settings.DNSAAS_OWNER }) return dns_records - def update_dns_records(self, records): - error = False - for item in records: - url = urljoin( - settings.DNSAAS_URL, 'api/records/{}/'.format(item['pk']) + def update_dns_records(self, record): + """ + Update DNS Record in DNSAAS + + Args: + record: record cleaned data + + Returns: + True or False if an error from api + """ + url = urljoin( + settings.DNSAAS_URL, 'api/records/{}/'.format(record['pk']) + ) + data = { + 'name': record['name'], + 'type': RecordType.raw_from_id(int(record['type'])), + 'content': record['content'], + 'auto_ptr': ( + settings.DNSAAS_AUTO_PTR_ALWAYS if record['ptr'] and + record['type'] == str(RecordType.a.id) + else settings.DNSAAS_AUTO_PTR_NEVER + ), + 'owner': settings.DNSAAS_OWNER + } + request = self.session.patch(url, data=data) + if request.status_code != 200: + return False + return True + + @lru_cache() + def get_domain(self, record): + """ + Return domain URL base on record name. + + Args: + record: Cleaned data from formset + + Return: + Domain URL from API or False if not exists + """ + domain_name = record['name'].split('.', 1) + url = urljoin( + settings.DNSAAS_URL, 'api/domains/?'.format( + urlencode([('name', domain_name[-1])]) ) - data = { - 'name': item['name'], - 'type': RecordType.raw_from_id(int(item['type'])), - 'content': item['content'], - 'auto_ptr': ( - settings.DNSAAS_AUTO_PTR_ALWAYS if item['ptr'] and - item['type'] == RecordType.a.id - else settings.DNSAAS_AUTO_PTR_NEVER - ) - } - request = self.session.patch(url, data=data) - if request.status_code != 200: - logger.error( - 'Error from DNS API {}: {}'.format(url, request.json()) - ) - error = True - - return error - - def delete_dns_records(self, record_ids): - error = False - for record_id in record_ids: - url = urljoin( - settings.DNSAAS_URL, 'api/records/{}/'.format(record_id) + ) + result = self.get_api_result(url) + if result: + return result[0]['url'] + + return False + + def create_dns_records(self, record): + """ + Create new DNS record. + + Args: + records: Record cleaned data + + Returns: + True or False if an error from api + """ + + url = urljoin(settings.DNSAAS_URL, 'api/records/') + domain = self.get_domain(record) + if not domain: + logger.error( + 'Domain not found for record {}'.format(record) ) - request = self.session.delete(url) - if request.status_code != 204: - error = True - logger.error( - 'Error from DNS API {}: {}'.format(url, request.json()) - ) - - return error + return False + + data = { + 'name': record['name'], + 'type': RecordType.raw_from_id(int(record['type'])), + 'content': record['content'], + 'auto_ptr': ( + settings.DNSAAS_AUTO_PTR_ALWAYS if record['ptr'] and + record['type'] == RecordType.a.id + else settings.DNSAAS_AUTO_PTR_NEVER + ), + 'domain': domain, + 'owner': settings.DNSAAS_OWNER + } + request = self.session.post(url, data=data) + if request.status_code != 201: + return False + + return True + + def delete_dns_records(self, record_id): + """ + Delete rcords in DNSAAS + + Args: + record_ids: ID's to delete + + Returns: + True or False if an error from api + """ + url = urljoin( + settings.DNSAAS_URL, 'api/records/{}/'.format(record_id) + ) + request = self.session.delete(url) + if request.status_code != 204: + return False + + return True diff --git a/src/ralph/dns/views.py b/src/ralph/dns/views.py index f3c97913fa..7e280e38ee 100644 --- a/src/ralph/dns/views.py +++ b/src/ralph/dns/views.py @@ -1,10 +1,8 @@ # -*- coding: utf-8 -*- import logging -from django.contrib import messages from django.forms import BaseFormSet, formset_factory from django.http import HttpResponseRedirect -from django.utils.translation import ugettext_lazy as _ from ralph.admin.views.extra import RalphDetailView from ralph.dns.dnsaas import DNSaaS @@ -46,23 +44,14 @@ def get(self, request, *args, **kwargs): def post(self, request, *args, **kwargs): formset = self.get_formset() if formset.is_valid(): - to_delete = [] - to_update = [] - for form in formset.forms: + for i, form in enumerate(formset.forms): if form.cleaned_data.get('DELETE'): - to_delete.append(form.cleaned_data['pk']) + self.dnsaas.delete_dns_records(form.cleaned_data['pk']) elif form.has_changed(): - to_update.append(form.cleaned_data) - - if to_delete and self.dnsaas.delete_dns_records(to_delete): - messages.error( - request, _('An error occurred while deleting a record') - ) - if to_update and self.dnsaas.update_dns_records(to_update): - messages.error( - request, _('An error occurred while updating a record') - ) - + if form.cleaned_data['pk']: + self.dnsaas.update_dns_records(form.cleaned_data) + else: + self.dnsaas.create_dns_records(form.cleaned_data) return HttpResponseRedirect('.') kwargs['formset'] = formset diff --git a/src/ralph/settings/base.py b/src/ralph/settings/base.py index 45c36a7e08..67dd07af52 100644 --- a/src/ralph/settings/base.py +++ b/src/ralph/settings/base.py @@ -291,6 +291,8 @@ def os_env_true(var, default=''): DNSAAS_TOKEN = os.environ.get('DNSAAS_TOKEN', '') DNSAAS_AUTO_PTR_ALWAYS = os.environ.get('DNSAAS_AUTO_PTR_ALWAYS', 2) DNSAAS_AUTO_PTR_NEVER = os.environ.get('DNSAAS_AUTO_PTR_NEVER', 1) +DNSAAS_OWNER = os.environ.get('DNSAAS_OWNER', 'ralph') + if ENABLE_DNSAAS_INTEGRATION: INSTALLED_APPS += ( 'ralph.dns',