Verify DNS changes when updating RRSet

Change-Id: Ic4379b95cdc2fa9d62cfe0394ff7329533f38374
This commit is contained in:
Endre Karlson 2015-05-28 19:42:35 +02:00
parent d5c63b6ddb
commit 48435d84ae
6 changed files with 124 additions and 3 deletions

View File

@ -31,6 +31,9 @@ if is_service_enabled designate; then
echo_summary "Initializing Designate" echo_summary "Initializing Designate"
init_designate init_designate
echo "Configuring Tempest options for Designate"
configure_designate_tempest
echo_summary "Starting Designate" echo_summary "Starting Designate"
start_designate start_designate

View File

@ -206,6 +206,30 @@ function configure_designate {
configure_designate_backend configure_designate_backend
} }
# Configure the needed tempest options
function configure_designate_tempest() {
if is_service_enabled tempest; then
nameservers=$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT_DNS
case $DESIGNATE_BACKEND_DRIVER in
bind9|powerdns)
nameservers="$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT_DNS"
;;
akamai)
nameservers="$DESIGNATE_AKAMAI_NAMESERVERS"
;;
dynect)
nameservers="$DESIGNATE_DYNECT_NAMESERVERS"
;;
esac
if [ ! -z "$DESIGNATE_NAMESERVERS" ]; then
nameservers=$DESIGNATE_NAMESERVERS
fi
iniset $TEMPEST_CONFIG designate nameservers $nameservers
fi
}
# create_designate_accounts - Set up common required designate accounts # create_designate_accounts - Set up common required designate accounts
# Tenant User Roles # Tenant User Roles

View File

@ -13,10 +13,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
import dns.rdatatype
from tempest_lib import exceptions from tempest_lib import exceptions
from functionaltests.common import datagen from functionaltests.common import datagen
from functionaltests.common import dnsclient
from functionaltests.common import utils from functionaltests.common import utils
from functionaltests.api.v2.base import DesignateV2Test from functionaltests.api.v2.base import DesignateV2Test
from functionaltests.api.v2.clients.recordset_client import RecordsetClient from functionaltests.api.v2.clients.recordset_client import RecordsetClient
@ -38,6 +39,29 @@ class RecordsetTest(DesignateV2Test):
.list_recordsets(self.zone.id) .list_recordsets(self.zone.id)
self.assertEqual(resp.status, 200) self.assertEqual(resp.status, 200)
def assert_dns(self, model):
results = dnsclient.query_servers(model.name, model.type)
model_data = model.to_dict()
if model.type == 'AAAA':
model_data['records'] = utils.shorten_ipv6_addrs(
model_data['records'])
for answer in results:
data = {
"type": dns.rdatatype.to_text(answer.rdtype),
"name": str(answer.canonical_name),
# DNSPython wraps TXT values in "" so '+all v=foo' becomes
# '"+all" "+v=foo"'
"records": [i.to_text().replace('"', '')
for i in answer.rrset.items]
}
if answer.rrset.ttl != 0:
data['ttl'] = answer.rrset.ttl
self.assertEqual(model_data, data)
@utils.parameterized({ @utils.parameterized({
'A': dict( 'A': dict(
make_recordset=lambda z: datagen.random_a_recordset(z.name)), make_recordset=lambda z: datagen.random_a_recordset(z.name)),
@ -72,6 +96,8 @@ class RecordsetTest(DesignateV2Test):
RecordsetClient.as_user('default').wait_for_recordset( RecordsetClient.as_user('default').wait_for_recordset(
self.zone.id, recordset_id) self.zone.id, recordset_id)
self.assert_dns(post_model)
put_model = make_recordset(self.zone) put_model = make_recordset(self.zone)
del put_model.name # don't try to update the name del put_model.name # don't try to update the name
resp, put_resp_model = RecordsetClient.as_user('default') \ resp, put_resp_model = RecordsetClient.as_user('default') \
@ -85,6 +111,9 @@ class RecordsetTest(DesignateV2Test):
RecordsetClient.as_user('default').wait_for_recordset( RecordsetClient.as_user('default').wait_for_recordset(
self.zone.id, recordset_id) self.zone.id, recordset_id)
put_model.name = post_model.name
self.assert_dns(put_model)
resp, delete_resp_model = RecordsetClient.as_user('default') \ resp, delete_resp_model = RecordsetClient.as_user('default') \
.delete_recordset(self.zone.id, recordset_id) .delete_recordset(self.zone.id, recordset_id)
self.assertEqual(resp.status, 202, "on delete response") self.assertEqual(resp.status, 202, "on delete response")

View File

@ -60,6 +60,11 @@ cfg.CONF.register_opts([
], group='noauth') ], group='noauth')
cfg.CONF.register_opts([
cfg.ListOpt('nameservers', default=["127.0.0.1:53"])
], group="designate")
def find_config_file(): def find_config_file():
return os.environ.get( return os.environ.get(
'TEMPEST_CONFIG', '/opt/stack/tempest/etc/tempest.conf') 'TEMPEST_CONFIG', '/opt/stack/tempest/etc/tempest.conf')

View File

@ -0,0 +1,48 @@
# Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Author: Endre Karlson <endre.karlson@hp.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import dns.resolver
from oslo_config import cfg
from functionaltests.common import utils
def query(name, type_, server="127.0.0.1", port=53, timeout=3):
resolver = dns.resolver.Resolver()
resolver.nameservers = [server]
resolver.port = int(port)
resolver.timeout = timeout
try:
return resolver.query(name, type_)
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
return False
def query_servers(name, type_, servers=None, timeout=3):
servers = servers or os.environ.get("DESIGNATE_SERVERS",
cfg.CONF.designate.nameservers)
results = []
for srv in servers:
server, port = srv.split(":")
port = port or 53
result = utils.wait_for_condition(
lambda: query(name, type_, server, port))
results.append(result)
return results

View File

@ -18,6 +18,8 @@ import functools
import time import time
import types import types
import netaddr
def def_method(f, *args, **kwargs): def def_method(f, *args, **kwargs):
@functools.wraps(f) @functools.wraps(f)
@ -88,8 +90,9 @@ def parameterized(data):
def wait_for_condition(condition, interval=1, timeout=40): def wait_for_condition(condition, interval=1, timeout=40):
end_time = time.time() + timeout end_time = time.time() + timeout
while time.time() < end_time: while time.time() < end_time:
if condition(): result = condition()
return if result:
return result
time.sleep(interval) time.sleep(interval)
raise Exception("Timed out after {0} seconds".format(timeout)) raise Exception("Timed out after {0} seconds".format(timeout))
@ -110,3 +113,12 @@ def memoized(func):
cache[args] = value cache[args] = value
return value return value
return wrapper return wrapper
def shorten_ipv6_addrs(addrs):
"""Shorten ipv6 addresses"""
new_addrs = []
for a in addrs:
an = netaddr.IPAddress(a, version=6)
new_addrs.append(an.format(netaddr.ipv6_compact))
return new_addrs