mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add new version of DNS plugin: complete rework with baseldap + unit tests.
Ticket #36 Ticket #450
This commit is contained in:
parent
4ad8055341
commit
5db7c4ec34
@ -178,6 +178,7 @@ Requires: gnupg
|
||||
Requires: pyOpenSSL
|
||||
Requires: python-nss >= 0.9-8
|
||||
Requires: python-lxml
|
||||
Requires: python-netaddr
|
||||
|
||||
%description python
|
||||
IPA is an integrated solution to provide centrally managed Identity (machine,
|
||||
|
584
ipalib/plugins/dns2.py
Normal file
584
ipalib/plugins/dns2.py
Normal file
@ -0,0 +1,584 @@
|
||||
# Authors:
|
||||
# Pavel Zuna <pzuna@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2010 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; version 2 only
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
"""
|
||||
Domain Name System (DNS)
|
||||
|
||||
Manage DNS zone and resource records.
|
||||
|
||||
EXAMPLES:
|
||||
|
||||
Add new zone:
|
||||
ipa dnszone-add example.com --name_server nameserver.example.com
|
||||
--admin_email admin@example.com
|
||||
|
||||
edd second nameserver for example.com:
|
||||
ipa dnsrecord-add example.com @ --ns-rec nameserver2.example.com
|
||||
|
||||
Delete previously added nameserver from example.com:
|
||||
ipa dnsrecord-del example.com @ --ns-rec nameserver2.example.com
|
||||
|
||||
Add new A record for www.example.com: (random IP)
|
||||
ipa dnsrecord-add example.com www --a-rec 80.142.15.2
|
||||
|
||||
Add new PTR record for www.example.com
|
||||
ipa dnsrecord 15.142.80.in-addr.arpa 2 --ptr-rec www.example.com.
|
||||
|
||||
Show zone example.com:
|
||||
ipa dnszone-show example.com
|
||||
|
||||
Find zone with "example" in it's domain name:
|
||||
ipa dnszone-find example
|
||||
|
||||
Find records for resources with "www" in their name in zone example.com:
|
||||
ipa dnsrecord-find example.com www
|
||||
|
||||
Find A records with value 10.10.0.1 in zone example.com
|
||||
ipa dnsrecord-find example.com --a-rec 10.10.0.1
|
||||
|
||||
Show records for resource www in zone example.com
|
||||
ipa dnsrecord-show example.com www
|
||||
|
||||
Delete zone example.com with all resource records:
|
||||
ipa dnszone-del example.com
|
||||
|
||||
Resolve a host name to see if it exists (will add default IPA domain
|
||||
if one is not included):
|
||||
ipa dns-resolve www.example.com
|
||||
ipa dns-resolve www
|
||||
|
||||
"""
|
||||
|
||||
import netaddr
|
||||
import time
|
||||
|
||||
from ipalib import api, errors, output
|
||||
from ipalib import Command
|
||||
from ipalib import Flag, Int, List, Str, StrEnum
|
||||
from ipalib.plugins.baseldap import *
|
||||
from ipalib import _, ngettext
|
||||
from ipapython import dnsclient
|
||||
|
||||
# supported resource record types
|
||||
_record_types = (
|
||||
u'A', u'AAAA', u'A6', u'AFSDB', u'APL', u'CERT', u'CNAME', u'DHCID', u'DLV',
|
||||
u'DNAME', u'DNSKEY', u'DS', u'HINFO', u'HIP', u'IPSECKEY', u'KEY', u'KX',
|
||||
u'LOC', u'MD', u'MINFO', u'MX', u'NAPTR', u'NS', u'NSEC', u'NSEC3',
|
||||
u'NSEC3PARAM', u'NXT', u'PTR', u'RRSIG', u'RP', u'SIG', u'SPF', u'SRV',
|
||||
u'SSHFP', u'TA', u'TKEY', u'TSIG', u'TXT',
|
||||
)
|
||||
|
||||
# attributes derived from record types
|
||||
_record_attributes = [str('%srecord' % t.lower()) for t in _record_types]
|
||||
|
||||
# supported DNS classes, IN = internet, rest is almost never used
|
||||
_record_classes = (u'IN', u'CS', u'CH', u'HS')
|
||||
|
||||
# normalizer for admin email
|
||||
def _rname_normalizer(value):
|
||||
value = value.replace('@', '.')
|
||||
if not value.endswith('.'):
|
||||
value += '.'
|
||||
return value
|
||||
|
||||
def _create_zone_serial(**kwargs):
|
||||
"""Generate serial number for zones."""
|
||||
return int('%s01' % time.strftime('%Y%d%m'))
|
||||
|
||||
def _validate_ipaddr(ugettext, ipaddr):
|
||||
try:
|
||||
ip = netaddr.IPAddress(ipaddr)
|
||||
except netaddr.AddrFormatError:
|
||||
return u'invalid address format'
|
||||
return None
|
||||
|
||||
def _validate_ipnet(ugettext, ipnet):
|
||||
try:
|
||||
net = netaddr.IPNetwork(ipnet)
|
||||
except (UnboundLocalError, ValueError):
|
||||
return u'invalid format'
|
||||
return None
|
||||
|
||||
_record_validators = {
|
||||
u'A': _validate_ipaddr,
|
||||
u'AAAA': _validate_ipaddr,
|
||||
u'APL': _validate_ipnet,
|
||||
}
|
||||
|
||||
|
||||
class dnszone(LDAPObject):
|
||||
"""
|
||||
DNS Zone, container for resource records.
|
||||
"""
|
||||
container_dn = api.env.container_dns
|
||||
object_name = 'DNS zone'
|
||||
object_name_plural = 'DNS zones'
|
||||
object_class = ['top', 'idnsrecord', 'idnszone']
|
||||
default_attributes = [
|
||||
'idnsname', 'idnszoneactive', 'idnssoamname', 'idnssoarname',
|
||||
'idnssoaserial', 'idnssoarefresh', 'idnssoaretry', 'idnssoaexpire',
|
||||
'idnssoaminimum'
|
||||
] + _record_attributes
|
||||
label = _('DNS zone')
|
||||
|
||||
takes_params = (
|
||||
Str('idnsname',
|
||||
cli_name='name',
|
||||
label=_('Zone name'),
|
||||
doc=_('Zone name (FQDN)'),
|
||||
normalizer=lambda value: value.lower(),
|
||||
primary_key=True,
|
||||
),
|
||||
Str('idnssoamname',
|
||||
cli_name='name_server',
|
||||
label=_('Authoritative name server'),
|
||||
doc=_('Authoritative name server'),
|
||||
),
|
||||
Str('idnssoarname',
|
||||
cli_name='admin_email',
|
||||
label=_('Administrator e-mail address'),
|
||||
doc=_('Administrator e-mail address'),
|
||||
default_from=lambda idnsname: 'root.%s' % idnsname,
|
||||
normalizer=_rname_normalizer,
|
||||
),
|
||||
Int('idnssoaserial?',
|
||||
cli_name='serial',
|
||||
label=_('SOA serial'),
|
||||
doc=_('SOA record serial number'),
|
||||
create_default=_create_zone_serial,
|
||||
autofill=True,
|
||||
),
|
||||
Int('idnssoarefresh?',
|
||||
cli_name='refresh',
|
||||
label=_('SOA refresh'),
|
||||
doc=_('SOA record refresh time'),
|
||||
default=3600,
|
||||
autofill=True,
|
||||
),
|
||||
Int('idnssoaretry?',
|
||||
cli_name='retry',
|
||||
label=_('SOA retry'),
|
||||
doc=_('SOA record retry time'),
|
||||
default=900,
|
||||
autofill=True,
|
||||
),
|
||||
Int('idnssoaexpire?',
|
||||
cli_name='expire',
|
||||
label=_('SOA expire'),
|
||||
doc=_('SOA record expire time'),
|
||||
default=1209600,
|
||||
autofill=True,
|
||||
),
|
||||
Int('idnssoaminimum?',
|
||||
cli_name='minimum',
|
||||
label=_('SOA minimum'),
|
||||
doc=_('SOA record minimum value'),
|
||||
default=3600,
|
||||
autofill=True,
|
||||
),
|
||||
Int('idnssoamaximum?',
|
||||
cli_name='maximum',
|
||||
label=_('SOA maximum'),
|
||||
doc=_('SOA record maximum value'),
|
||||
),
|
||||
Int('dnsttl?',
|
||||
cli_name='ttl',
|
||||
label=_('SOA time to live'),
|
||||
doc=_('SOA record time to live'),
|
||||
),
|
||||
StrEnum('dnsclass?',
|
||||
cli_name='class',
|
||||
label=_('SOA class'),
|
||||
doc=_('SOA record class'),
|
||||
values=_record_classes,
|
||||
),
|
||||
Str('idnsupdatepolicy?',
|
||||
cli_name='update_policy',
|
||||
label=_('BIND update policy'),
|
||||
doc=_('BIND update policy'),
|
||||
),
|
||||
)
|
||||
|
||||
def check_container_exists(self):
|
||||
try:
|
||||
self.backend.get_entry(self.container_dn, [])
|
||||
except errors.NotFound:
|
||||
raise errors.NotFound(reason=_('DNS is not configured'))
|
||||
|
||||
api.register(dnszone)
|
||||
|
||||
|
||||
class dnszone_add(LDAPCreate):
|
||||
"""
|
||||
Create new DNS zone (SOA record).
|
||||
"""
|
||||
takes_options = (
|
||||
Flag('idnsallowdynupdate',
|
||||
cli_name='allow_dynupdate',
|
||||
label=_('Dynamic update'),
|
||||
doc=_('allow dynamic update?'),
|
||||
attribute=True,
|
||||
),
|
||||
)
|
||||
|
||||
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||
self.obj.check_container_exists()
|
||||
entry_attrs['idnszoneactive'] = 'TRUE'
|
||||
entry_attrs['idnsallowdynupdate'] = str(
|
||||
entry_attrs.get('idnsallowdynupdate', False)
|
||||
).upper()
|
||||
return dn
|
||||
|
||||
api.register(dnszone_add)
|
||||
|
||||
|
||||
class dnszone_del(LDAPDelete):
|
||||
"""
|
||||
Delete DNS zone (SOA record).
|
||||
"""
|
||||
|
||||
api.register(dnszone_del)
|
||||
|
||||
|
||||
class dnszone_mod(LDAPUpdate):
|
||||
"""
|
||||
Modify DNS zone (SOA record).
|
||||
"""
|
||||
takes_options = (
|
||||
Flag('idnsallowdynupdate',
|
||||
cli_name='allow_dynupdate',
|
||||
label=_('Dynamic update'),
|
||||
doc=_('allow dynamic update?'),
|
||||
attribute=True,
|
||||
),
|
||||
)
|
||||
|
||||
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||
entry_attrs['idnsallowdynupdate'] = str(
|
||||
entry_attrs.get('idnsallowdynupdate', False)
|
||||
).upper()
|
||||
return dn
|
||||
|
||||
api.register(dnszone_mod)
|
||||
|
||||
|
||||
class dnszone_find(LDAPSearch):
|
||||
"""
|
||||
Search for DNS zones (SOA records).
|
||||
"""
|
||||
|
||||
api.register(dnszone_find)
|
||||
|
||||
|
||||
class dnszone_show(LDAPRetrieve):
|
||||
"""
|
||||
Display information about a DNS zone (SOA record).
|
||||
"""
|
||||
|
||||
api.register(dnszone_show)
|
||||
|
||||
|
||||
class dnszone_disable(LDAPQuery):
|
||||
"""
|
||||
Disable DNS Zone.
|
||||
"""
|
||||
has_output = output.standard_value
|
||||
msg_summary = _('Disabled DNS zone "%(value)s"')
|
||||
|
||||
def execute(self, *keys, **options):
|
||||
ldap = self.obj.backend
|
||||
|
||||
dn = self.obj.get_dn(*keys, **options)
|
||||
|
||||
try:
|
||||
ldap.update_entry(dn, {'idnszoneactive': 'FALSE'})
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
|
||||
return dict(result=True, value=keys[-1])
|
||||
|
||||
api.register(dnszone_disable)
|
||||
|
||||
|
||||
class dnszone_enable(LDAPQuery):
|
||||
"""
|
||||
Enable DNS Zone.
|
||||
"""
|
||||
has_output = output.standard_value
|
||||
msg_summary = _('Enabled DNS zone "%(value)s"')
|
||||
|
||||
def execute(self, *keys, **options):
|
||||
ldap = self.obj.backend
|
||||
|
||||
dn = self.obj.get_dn(*keys, **options)
|
||||
|
||||
try:
|
||||
ldap.update_entry(dn, {'idnszoneactive': 'TRUE'})
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
|
||||
return dict(result=True, value=keys[-1])
|
||||
|
||||
api.register(dnszone_enable)
|
||||
|
||||
|
||||
class dnsrecord(LDAPObject):
|
||||
"""
|
||||
DNS record.
|
||||
"""
|
||||
parent_object = 'dnszone'
|
||||
container_dn = api.env.container_dns
|
||||
object_name = 'DNS resource record'
|
||||
object_name_plural = 'DNS resource records'
|
||||
object_class = ['top', 'idnsrecord']
|
||||
default_attributes = _record_attributes + ['idnsname']
|
||||
|
||||
label = _('DNS resource record')
|
||||
|
||||
takes_params = (
|
||||
Str('idnsname',
|
||||
cli_name='name',
|
||||
label=_('Record name'),
|
||||
doc=_('Record name'),
|
||||
primary_key=True,
|
||||
),
|
||||
Int('dnsttl?',
|
||||
cli_name='ttl',
|
||||
label=_('Time to live'),
|
||||
doc=_('Time to live'),
|
||||
),
|
||||
StrEnum('dnsclass?',
|
||||
cli_name='class',
|
||||
label=_('Class'),
|
||||
doc=_('DNS class'),
|
||||
values=_record_classes,
|
||||
),
|
||||
)
|
||||
|
||||
def is_pkey_zone_record(*keys):
|
||||
idnsname = keys[-1]
|
||||
if idnsname == '@' or idnsname == ('%s.' % keys[-2]):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_dn(self, *keys, **options):
|
||||
if self.is_pkey_zone_record(*keys):
|
||||
return self.api.Object[self.parent_object].get_dn(*keys[:-1], **options)
|
||||
return super(dnsrecord, self).get_dn(*keys, **options)
|
||||
|
||||
api.register(dnsrecord)
|
||||
|
||||
|
||||
class dnsrecord_cmd_w_record_options(Command):
|
||||
"""
|
||||
Base class for DNS record commands with record options.
|
||||
"""
|
||||
record_param_doc = 'comma-separated list of %s records'
|
||||
|
||||
def get_record_options(self):
|
||||
for t in _record_types:
|
||||
t = t.encode('utf-8')
|
||||
doc = self.record_param_doc % t
|
||||
validator = _record_validators.get(t)
|
||||
if validator:
|
||||
yield List(
|
||||
'%srecord?' % t.lower(), validator,
|
||||
cli_name='%s_rec' % t.lower(), doc=doc,
|
||||
label='%s record' % t, attribute=True
|
||||
)
|
||||
else:
|
||||
yield List(
|
||||
'%srecord?' % t.lower(), cli_name='%s_rec' % t.lower(),
|
||||
doc=doc, label='%s record' % t, attribute=True
|
||||
)
|
||||
|
||||
def record_options_2_entry(self, **options):
|
||||
return dict((t, options.get(t, [])) for t in _record_attributes)
|
||||
|
||||
|
||||
class dnsrecord_mod_record(LDAPQuery, dnsrecord_cmd_w_record_options):
|
||||
"""
|
||||
Base class for adding/removing records from DNS resource entries.
|
||||
"""
|
||||
has_output = output.standard_entry
|
||||
|
||||
def get_options(self):
|
||||
for option in super(dnsrecord_mod_record, self).get_options():
|
||||
yield option
|
||||
for option in self.get_record_options():
|
||||
yield option
|
||||
|
||||
def execute(self, *keys, **options):
|
||||
ldap = self.obj.backend
|
||||
|
||||
dn = self.obj.get_dn(*keys, **options)
|
||||
|
||||
entry_attrs = self.record_options_2_entry(**options)
|
||||
|
||||
try:
|
||||
(dn, old_entry_attrs) = ldap.get_entry(dn, entry_attrs.keys())
|
||||
except errors.NotFound:
|
||||
self.obj.handle_not_found(*keys)
|
||||
|
||||
self.update_old_entry_callback(entry_attrs, old_entry_attrs)
|
||||
|
||||
try:
|
||||
ldap.update_entry(dn, old_entry_attrs)
|
||||
except errors.EmptyModlist:
|
||||
pass
|
||||
|
||||
if options.get('all', False):
|
||||
attrs_list = ['*']
|
||||
else:
|
||||
attrs_list = list(
|
||||
set(self.obj.default_attributes + entry_attrs.keys())
|
||||
)
|
||||
|
||||
try:
|
||||
(dn, entry_attrs) = ldap.get_entry(dn, attrs_list)
|
||||
except errors.NotFound:
|
||||
self.obj.handle_not_found(*keys)
|
||||
|
||||
if self.obj.is_pkey_zone_record(*keys):
|
||||
entry_attrs[self.obj.primary_key.name] = [u'@']
|
||||
|
||||
self.post_callback(keys, entry_attrs)
|
||||
|
||||
return dict(result=entry_attrs, value=keys[-1])
|
||||
|
||||
def update_old_entry_callback(self, entry_attrs, old_entry_attrs):
|
||||
pass
|
||||
|
||||
def post_callback(self, keys, entry_attrs):
|
||||
pass
|
||||
|
||||
|
||||
class dnsrecord_add_record(dnsrecord_mod_record):
|
||||
"""
|
||||
Add records to DNS resource.
|
||||
"""
|
||||
INTERNAL = True
|
||||
|
||||
def update_old_entry_callback(self, entry_attrs, old_entry_attrs):
|
||||
for (a, v) in entry_attrs.iteritems():
|
||||
if not isinstance(v, (list, tuple)):
|
||||
v = [v]
|
||||
old_entry_attrs.setdefault(a, [])
|
||||
old_entry_attrs[a] += v
|
||||
|
||||
api.register(dnsrecord_add_record)
|
||||
|
||||
|
||||
class dnsrecord_add(LDAPCreate, dnsrecord_cmd_w_record_options):
|
||||
"""
|
||||
Add new DNS resource record.
|
||||
"""
|
||||
def get_options(self):
|
||||
for option in super(dnsrecord_add, self).get_options():
|
||||
yield option
|
||||
for option in self.get_record_options():
|
||||
yield option
|
||||
|
||||
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
|
||||
if call_func.func_name == 'add_entry':
|
||||
if isinstance(exc, errors.DuplicateEntry):
|
||||
self.obj.methods.add_record(
|
||||
*keys, **self.record_options_2_entry(**options)
|
||||
)
|
||||
return
|
||||
raise exc
|
||||
|
||||
api.register(dnsrecord_add)
|
||||
|
||||
|
||||
class dnsrecord_delentry(LDAPDelete):
|
||||
"""
|
||||
Delete DNS record entry.
|
||||
"""
|
||||
INTERNAL = True
|
||||
|
||||
api.register(dnsrecord_delentry)
|
||||
|
||||
|
||||
class dnsrecord_del(dnsrecord_mod_record):
|
||||
"""
|
||||
Delete DNS resource record.
|
||||
"""
|
||||
def update_old_entry_callback(self, entry_attrs, old_entry_attrs):
|
||||
for (a, v) in entry_attrs.iteritems():
|
||||
if not isinstance(v, (list, tuple)):
|
||||
v = [v]
|
||||
for val in v:
|
||||
try:
|
||||
old_entry_attrs[a].remove(val)
|
||||
except (KeyError, ValueError):
|
||||
pass
|
||||
|
||||
def post_callback(self, keys, entry_attrs):
|
||||
if not self.obj.is_pkey_zone_record(*keys):
|
||||
for a in _record_attributes:
|
||||
if a in entry_attrs and entry_attrs[a]:
|
||||
return
|
||||
self.obj.methods.delentry(*keys)
|
||||
|
||||
api.register(dnsrecord_del)
|
||||
|
||||
|
||||
class dnsrecord_show(LDAPRetrieve, dnsrecord_cmd_w_record_options):
|
||||
"""
|
||||
Display DNS resource.
|
||||
"""
|
||||
def has_output_params(self):
|
||||
for option in self.get_record_options():
|
||||
yield option
|
||||
|
||||
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||
if self.obj.is_pkey_zone_record(*keys):
|
||||
entry_attrs[self.obj.primary_key.name] = [u'@']
|
||||
return dn
|
||||
|
||||
api.register(dnsrecord_show)
|
||||
|
||||
|
||||
class dnsrecord_find(LDAPSearch, dnsrecord_cmd_w_record_options):
|
||||
"""
|
||||
Search for DNS resources.
|
||||
"""
|
||||
def get_options(self):
|
||||
for option in super(dnsrecord_find, self).get_options():
|
||||
yield option
|
||||
for option in self.get_record_options():
|
||||
yield option.clone(query=True)
|
||||
|
||||
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
|
||||
record_attrs = self.record_options_2_entry(**options)
|
||||
record_filter = ldap.make_filter(record_attrs, rules=ldap.MATCH_ALL)
|
||||
filter = ldap.combine_filters(
|
||||
(filter, record_filter), rules=ldap.MATCH_ALL
|
||||
)
|
||||
return (filter, base_dn, ldap.SCOPE_SUBTREE)
|
||||
|
||||
def post_callback(self, ldap, entries, truncated, *args, **options):
|
||||
if entries:
|
||||
zone_obj = self.api.Object[self.obj.parent_object]
|
||||
zone_dn = zone_obj.get_dn(args[0])
|
||||
if entries[0][0] == zone_dn:
|
||||
entries[0][1][zone_obj.primary_key.name] = [u'@']
|
||||
|
||||
api.register(dnsrecord_find)
|
||||
|
341
tests/test_xmlrpc/test_dns_plugin.py
Normal file
341
tests/test_xmlrpc/test_dns_plugin.py
Normal file
@ -0,0 +1,341 @@
|
||||
# Authors:
|
||||
# Pavel Zuna <pzuna@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2010 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; version 2 only
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
"""
|
||||
Test the `ipalib/plugins/dns.py` module.
|
||||
"""
|
||||
|
||||
from ipalib import api, errors
|
||||
from tests.test_xmlrpc import objectclasses
|
||||
from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
|
||||
|
||||
dnszone1 = u'dnszone.test'
|
||||
dnsres1 = u'testdnsres'
|
||||
|
||||
class test_dns(Declarative):
|
||||
|
||||
cleanup_commands = [
|
||||
('dnszone_del', [dnszone1], {}),
|
||||
('dnsrecord_del', [dnszone1, dnsres1], {}),
|
||||
]
|
||||
|
||||
tests = [
|
||||
|
||||
dict(
|
||||
desc='Try to retrieve non-existent zone %r' % dnszone1,
|
||||
command=('dnszone_show', [dnszone1], {}),
|
||||
expected=errors.NotFound(reason='DNS zone not found'),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to update non-existent zone %r' % dnszone1,
|
||||
command=('dnszone_mod', [dnszone1], {'idnssoamname': u'foobar'}),
|
||||
expected=errors.NotFound(reason='DNS zone not found'),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to delete non-existent zone %r' % dnszone1,
|
||||
command=('dnszone_del', [dnszone1], {}),
|
||||
expected=errors.NotFound(reason='DNS zone not found'),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Create zone %r' % dnszone1,
|
||||
command=(
|
||||
'dnszone_add', [dnszone1], {
|
||||
'idnssoamname': u'ns1.%s' % dnszone1,
|
||||
'idnssoarname': u'root.%s' % dnszone1,
|
||||
}
|
||||
),
|
||||
expected={
|
||||
'value': dnszone1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'dn': u'idnsname=%s,cn=dns,%s' % (dnszone1, api.env.basedn),
|
||||
'idnsname': [dnszone1],
|
||||
'idnszoneactive': [u'TRUE'],
|
||||
'idnssoamname': [u'ns1.%s' % dnszone1],
|
||||
'idnssoarname': [u'root.%s.' % dnszone1],
|
||||
'idnssoaserial': [fuzzy_digits],
|
||||
'idnssoarefresh': [fuzzy_digits],
|
||||
'idnssoaretry': [fuzzy_digits],
|
||||
'idnssoaexpire': [fuzzy_digits],
|
||||
'idnssoaminimum': [fuzzy_digits],
|
||||
'idnsallowdynupdate': [u'FALSE'],
|
||||
'objectclass': [u'top', u'idnsrecord', u'idnszone'],
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to create duplicate zone %r' % dnszone1,
|
||||
command=(
|
||||
'dnszone_add', [dnszone1], {
|
||||
'idnssoamname': u'ns1.%s' % dnszone1,
|
||||
'idnssoarname': u'root.%s' % dnszone1,
|
||||
}
|
||||
),
|
||||
expected=errors.DuplicateEntry(),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Retrieve zone %r' % dnszone1,
|
||||
command=('dnszone_show', [dnszone1], {}),
|
||||
expected={
|
||||
'value': dnszone1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'dn': u'idnsname=%s,cn=dns,%s' % (dnszone1, api.env.basedn),
|
||||
'idnsname': [dnszone1],
|
||||
'idnszoneactive': [u'TRUE'],
|
||||
'idnssoamname': [u'ns1.%s' % dnszone1],
|
||||
'idnssoarname': [u'root.%s.' % dnszone1],
|
||||
'idnssoaserial': [fuzzy_digits],
|
||||
'idnssoarefresh': [fuzzy_digits],
|
||||
'idnssoaretry': [fuzzy_digits],
|
||||
'idnssoaexpire': [fuzzy_digits],
|
||||
'idnssoaminimum': [fuzzy_digits],
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Update zone %r' % dnszone1,
|
||||
command=('dnszone_mod', [dnszone1], {'idnssoarefresh': 5478}),
|
||||
expected={
|
||||
'value': dnszone1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'idnsname': [dnszone1],
|
||||
'idnszoneactive': [u'TRUE'],
|
||||
'idnssoamname': [u'ns1.%s' % dnszone1],
|
||||
'idnssoarname': [u'root.%s.' % dnszone1],
|
||||
'idnssoaserial': [fuzzy_digits],
|
||||
'idnssoarefresh': [u'5478'],
|
||||
'idnssoaretry': [fuzzy_digits],
|
||||
'idnssoaexpire': [fuzzy_digits],
|
||||
'idnssoaminimum': [fuzzy_digits],
|
||||
'idnsallowdynupdate': [u'FALSE'],
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Search for zones with name server %r' % (u'ns1.%s' % dnszone1),
|
||||
command=('dnszone_find', [], {'idnssoamname': u'ns1.%s' % dnszone1}),
|
||||
expected={
|
||||
'summary': None,
|
||||
'count': 1,
|
||||
'truncated': False,
|
||||
'result': [{
|
||||
'dn': u'idnsname=%s,cn=dns,%s' % (dnszone1, api.env.basedn),
|
||||
'idnsname': [dnszone1],
|
||||
'idnszoneactive': [u'TRUE'],
|
||||
'idnssoamname': [u'ns1.%s' % dnszone1],
|
||||
'idnssoarname': [u'root.%s.' % dnszone1],
|
||||
'idnssoaserial': [fuzzy_digits],
|
||||
'idnssoarefresh': [u'5478'],
|
||||
'idnssoaretry': [fuzzy_digits],
|
||||
'idnssoaexpire': [fuzzy_digits],
|
||||
'idnssoaminimum': [fuzzy_digits],
|
||||
}],
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Disable zone %r' % dnszone1,
|
||||
command=('dnszone_disable', [dnszone1], {}),
|
||||
expected={
|
||||
'value': dnszone1,
|
||||
'summary': u'Disabled DNS zone "%s"' % dnszone1,
|
||||
'result': True,
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Check if zone %r is really disabled' % dnszone1,
|
||||
command=('dnszone_show', [dnszone1], {}),
|
||||
expected={
|
||||
'value': dnszone1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'dn': u'idnsname=%s,cn=dns,%s' % (dnszone1, api.env.basedn),
|
||||
'idnsname': [dnszone1],
|
||||
'idnszoneactive': [u'FALSE'],
|
||||
'idnssoamname': [u'ns1.%s' % dnszone1],
|
||||
'idnssoarname': [u'root.%s.' % dnszone1],
|
||||
'idnssoaserial': [fuzzy_digits],
|
||||
'idnssoarefresh': [fuzzy_digits],
|
||||
'idnssoaretry': [fuzzy_digits],
|
||||
'idnssoaexpire': [fuzzy_digits],
|
||||
'idnssoaminimum': [fuzzy_digits],
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Enable zone %r' % dnszone1,
|
||||
command=('dnszone_enable', [dnszone1], {}),
|
||||
expected={
|
||||
'value': dnszone1,
|
||||
'summary': u'Enabled DNS zone "%s"' % dnszone1,
|
||||
'result': True,
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Check if zone %r is really enabled' % dnszone1,
|
||||
command=('dnszone_show', [dnszone1], {}),
|
||||
expected={
|
||||
'value': dnszone1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'dn': u'idnsname=%s,cn=dns,%s' % (dnszone1, api.env.basedn),
|
||||
'idnsname': [dnszone1],
|
||||
'idnszoneactive': [u'TRUE'],
|
||||
'idnssoamname': [u'ns1.%s' % dnszone1],
|
||||
'idnssoarname': [u'root.%s.' % dnszone1],
|
||||
'idnssoaserial': [fuzzy_digits],
|
||||
'idnssoarefresh': [fuzzy_digits],
|
||||
'idnssoaretry': [fuzzy_digits],
|
||||
'idnssoaexpire': [fuzzy_digits],
|
||||
'idnssoaminimum': [fuzzy_digits],
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to retrieve non-existent record %r in zone %r' % (dnsres1, dnszone1),
|
||||
command=('dnsrecord_show', [dnszone1, dnsres1], {}),
|
||||
expected=errors.NotFound(reason='DNS resource record not found'),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Try to delete non-existent record %r in zone %r' % (dnsres1, dnszone1),
|
||||
command=('dnsrecord_del', [dnszone1, dnsres1], {}),
|
||||
expected=errors.NotFound(reason='DNS resource record not found'),
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Create record %r in zone %r' % (dnszone1, dnsres1),
|
||||
command=('dnsrecord_add', [dnszone1, dnsres1], {'arecord': u'127.0.0.1'}),
|
||||
expected={
|
||||
'value': dnsres1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'dn': u'idnsname=%s,idnsname=%s,cn=dns,%s' % (dnsres1, dnszone1, api.env.basedn),
|
||||
'idnsname': [dnsres1],
|
||||
'objectclass': [u'top', u'idnsrecord'],
|
||||
'arecord': [u'127.0.0.1'],
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Search for all records in zone %r' % dnszone1,
|
||||
command=('dnsrecord_find', [dnszone1], {}),
|
||||
expected={
|
||||
'summary': None,
|
||||
'count': 2,
|
||||
'truncated': False,
|
||||
'result': [
|
||||
{
|
||||
'dn': u'idnsname=%s,cn=dns,%s' % (dnszone1, api.env.basedn),
|
||||
'idnsname': [u'@'],
|
||||
},
|
||||
{
|
||||
'dn': u'idnsname=%s,idnsname=%s,cn=dns,%s' % (dnsres1, dnszone1, api.env.basedn),
|
||||
'idnsname': [dnsres1],
|
||||
'arecord': [u'127.0.0.1'],
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Add A record to %r in zone %r' % (dnszone1, dnsres1),
|
||||
command=('dnsrecord_add', [dnszone1, dnsres1], {'arecord': u'10.10.0.1'}),
|
||||
expected={
|
||||
'value': dnsres1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'dn': u'idnsname=%s,idnsname=%s,cn=dns,%s' % (dnsres1, dnszone1, api.env.basedn),
|
||||
'idnsname': [dnsres1],
|
||||
'arecord': [u'127.0.0.1', u'10.10.0.1'],
|
||||
'objectclass': [u'top', u'idnsrecord'],
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Remove A record from %r in zone %r' % (dnszone1, dnsres1),
|
||||
command=('dnsrecord_del', [dnszone1, dnsres1], {'arecord': u'127.0.0.1'}),
|
||||
expected={
|
||||
'value': dnsres1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'idnsname': [dnsres1],
|
||||
'arecord': [u'10.10.0.1'],
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Delete record %r in zone %r' % (dnsres1, dnszone1),
|
||||
command=('dnsrecord_del', [dnszone1, dnsres1], {}),
|
||||
expected={
|
||||
'value': dnsres1,
|
||||
'summary': None,
|
||||
'result': {
|
||||
'idnsname': [dnsres1],
|
||||
'arecord': [u'10.10.0.1'],
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
|
||||
dict(
|
||||
desc='Delete zone %r' % dnszone1,
|
||||
command=('dnszone_del', [dnszone1], {}),
|
||||
expected={
|
||||
'value': dnszone1,
|
||||
'summary': None,
|
||||
'result': True,
|
||||
},
|
||||
),
|
||||
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user