On 19/09/14 13:54, Martin Kosek wrote:
I did not review, just found something that hit me in the eyes:


On 09/19/2014 01:25 PM, Martin Basti wrote:
+class OptionDeprecatedWarning(PublicMessage):
+    """
+    **13004** Used when user uses a deprecated option
+    """
+
+    errno = 13004
+    type = "warning"
+ format = _(u"'%(option)s' option is deprecated. %(additional_info)s")
+
+
+class OptionNameServerWarning(PublicMessage):
+    """
+ **13005** Used when user uses a dnszone-add/mod --name-server option
+    """
+
+    errno = 13005
+    type = "warning"
+ format = _(u"'--name-server' is used only for setting up the SOA MNAME attribute.\n" + u"To edit NS record(s) in zone apex, use command 'dnsrecord-mod [zone] @ --ns-rec=nameserver'.")


OptionNameServerWarning has a nice generic name, but the format is not that generic, compared to OptionDeprecatedWarning. I think we should follow the approach as in OptionDeprecatedWarning so that the warning can be reused.

This is not urgent though, you can wait with the fix until Petr2 or somebody else sends you other notes...

Martin

Updated patchset attached

--
Martin Basti

From 32ea9f54ee9ca993034946951bf63b03dbb27b48 Mon Sep 17 00:00:00 2001
From: Martin Basti <[email protected]>
Date: Fri, 22 Aug 2014 17:11:22 +0200
Subject: [PATCH 1/2] Fix DNS plugin to allow to add root zone

Ticket: https://fedorahosted.org/freeipa/ticket/4149
---
 ipalib/plugins/dns.py | 53 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index 75611a615ba8905352a07ea36fcd04054c38014e..ab79a8ef3e636be10aa10c2a22e07e3d31758cbc 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -1783,17 +1783,21 @@ class DNSZoneBase(LDAPObject):
         zone = keys[-1]
         assert isinstance(zone, DNSName)
         assert zone.is_absolute()
-        zone = zone.ToASCII()
+        zone_a = zone.ToASCII()
+
+        # special case when zone is the root zone ('.')
+        if zone == DNSName.root:
+            return super(DNSZoneBase, self).get_dn(zone_a, **options)
 
         # try first relative name, a new zone has to be added as absolute
         # otherwise ObjectViolation is raised
-        zone = zone[:-1]
-        dn = super(DNSZoneBase, self).get_dn(zone, **options)
+        zone_a = zone_a[:-1]
+        dn = super(DNSZoneBase, self).get_dn(zone_a, **options)
         try:
             self.backend.get_entry(dn, [''])
         except errors.NotFound:
-            zone = u"%s." % zone
-            dn = super(DNSZoneBase, self).get_dn(zone, **options)
+            zone_a = u"%s." % zone_a
+            dn = super(DNSZoneBase, self).get_dn(zone_a, **options)
 
         return dn
 
@@ -1825,6 +1829,8 @@ class DNSZoneBase(LDAPObject):
         try:
             api.Command['permission_del'](permission_name, force=True)
         except errors.NotFound, e:
+            if zone == DNSName.root:  # special case root zone
+                raise
             # compatibility, older IPA versions which allows to create zone
             # without absolute zone name
             permission_name_rel = self.permission_name(
@@ -1988,20 +1994,21 @@ class DNSZoneBase_add_permission(LDAPQuery):
         permission_name = self.obj.permission_name(keys[-1])
 
         # compatibility with older IPA versions which allows relative zonenames
-        permission_name_rel = self.obj.permission_name(
-            keys[-1].relativize(DNSName.root)
-        )
-        try:
-            api.Object['permission'].get_dn_if_exists(permission_name_rel)
-        except errors.NotFound:
-            pass
-        else:
-            # permission exists without absolute domain name
-            raise errors.DuplicateEntry(
-                message=_('permission "%(value)s" already exists') % {
-                        'value': permission_name
-                }
+        if keys[-1] != DNSName.root:  # special case root zone
+            permission_name_rel = self.obj.permission_name(
+                keys[-1].relativize(DNSName.root)
             )
+            try:
+                api.Object['permission'].get_dn_if_exists(permission_name_rel)
+            except errors.NotFound:
+                pass
+            else:
+                # permission exists without absolute domain name
+                raise errors.DuplicateEntry(
+                    message=_('permission "%(value)s" already exists') % {
+                            'value': permission_name
+                    }
+                )
 
         permission = api.Command['permission_add_noaci'](permission_name,
                          ipapermissiontype=u'SYSTEM'
@@ -2417,12 +2424,14 @@ class dnszone_add(DNSZoneBase_add):
                                nameserver_ip_address)
 
         # Add entry to realmdomains
-        # except for our own domain, forwarded zones and reverse zones
+        # except for our own domain, forward zones, reverse zones and root zone
         zone = keys[0]
 
         if (zone != DNSName(api.env.domain).make_absolute()
             and not options.get('idnsforwarders')
-            and not zone.is_reverse()):
+            and not zone.is_reverse()
+            and zone != DNSName.root
+        ):
             try:
                 api.Command['realmdomains_mod'](add_domain=unicode(zone),
                                                 force=True)
@@ -2444,11 +2453,11 @@ class dnszone_del(DNSZoneBase_del):
         super(dnszone_del, self).post_callback(ldap, dn, *keys, **options)
 
         # Delete entry from realmdomains
-        # except for our own domain
+        # except for our own domain, and root zone
         zone = keys[0].make_absolute()
 
         if (zone != DNSName(api.env.domain).make_absolute() and
-                not zone.is_reverse()
+                not zone.is_reverse() and zone != DNSName.root
         ):
             try:
                 api.Command['realmdomains_mod'](del_domain=unicode(zone),
-- 
1.8.3.1

From 23f7df6c121c96ba51d1e0e9c5819a84320d71ab Mon Sep 17 00:00:00 2001
From: Martin Basti <[email protected]>
Date: Mon, 25 Aug 2014 12:48:32 +0200
Subject: [PATCH 2/2] DNS test: allow '.' as zone name

https://fedorahosted.org/freeipa/ticket/4149
---
 ipatests/test_xmlrpc/test_dns_plugin.py | 103 ++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/ipatests/test_xmlrpc/test_dns_plugin.py b/ipatests/test_xmlrpc/test_dns_plugin.py
index 595df7e008270fff2788baab965996fe7eaff7d4..79638b00bb9fa414c611f00715d1c9c97ab8476d 100644
--- a/ipatests/test_xmlrpc/test_dns_plugin.py
+++ b/ipatests/test_xmlrpc/test_dns_plugin.py
@@ -3719,3 +3719,106 @@ class test_dns(Declarative):
         ),
 
     ]
+
+
+zone_root = u'.'
+zone_root_dnsname = DNSName(zone_root)
+zone_root_ip = u'172.16.29.222'
+zone_root_dn = DN(('idnsname',zone_root), api.env.container_dns, api.env.basedn)
+zone_root_ns = u'ns'
+zone_root_ns_dnsname = DNSName(zone_root_ns)
+zone_root_ns_dn = DN(('idnsname', zone_root_ns), zone_root_dn)
+zone_root_rname = u'root.example.com.'
+zone_root_rname_dnsname = DNSName(zone_root_rname)
+zone_root_permission = u'Manage DNS zone %s' % zone_root
+zone_root_permission_dn = DN(('cn',zone_root_permission),
+                            api.env.container_permission,api.env.basedn)
+
+class test_root_zone(Declarative):
+
+    @classmethod
+    def setUpClass(cls):
+        super(test_root_zone, cls).setUpClass()
+
+        if not api.Backend.rpcclient.isconnected():
+            api.Backend.rpcclient.connect(fallback=False)
+        try:
+            api.Command['dnszone_add'](zone1,
+               idnssoamname = zone1_ns,
+               idnssoarname = zone1_rname,
+               force = True,
+               )
+            api.Command['dnszone_del'](zone1)
+        except errors.NotFound:
+            raise nose.SkipTest('DNS is not configured')
+        except errors.DuplicateEntry:
+            pass
+
+    cleanup_commands = [
+        ('dnszone_del', [zone_root, ],
+            {'continue': True}),
+        ('permission_del', [zone_root_permission, ], {'force': True}
+        ),
+    ]
+
+    tests = [
+
+        dict(
+            desc='Create zone %r' % zone_root,
+            command=(
+                'dnszone_add', [zone_root], {
+                    'idnssoamname': zone_root_ns,
+                    'idnssoarname': zone_root_rname,
+                    'ip_address' : zone_root_ip,
+                }
+            ),
+            expected={
+                'value': zone_root_dnsname,
+                'summary': None,
+                'result': {
+                    'dn': zone_root_dn,
+                    'idnsname': [zone_root_dnsname],
+                    'idnszoneactive': [u'TRUE'],
+                    'idnssoamname': [zone_root_ns_dnsname],
+                    'nsrecord': [zone_root_ns],
+                    'idnssoarname': [zone_root_rname_dnsname],
+                    'idnssoaserial': [fuzzy_digits],
+                    'idnssoarefresh': [fuzzy_digits],
+                    'idnssoaretry': [fuzzy_digits],
+                    'idnssoaexpire': [fuzzy_digits],
+                    'idnssoaminimum': [fuzzy_digits],
+                    'idnsallowdynupdate': [u'FALSE'],
+                    'idnsupdatepolicy': [u'grant %(realm)s krb5-self * A; '
+                                         u'grant %(realm)s krb5-self * AAAA; '
+                                         u'grant %(realm)s krb5-self * SSHFP;'
+                                         % dict(realm=api.env.realm)],
+                    'idnsallowtransfer': [u'none;'],
+                    'idnsallowquery': [u'any;'],
+                    'objectclass': objectclasses.dnszone,
+                },
+            },
+        ),
+
+        dict(
+            desc='Add per-zone permission for zone %r' % zone_root,
+            command=(
+                'dnszone_add_permission', [zone_root], {}
+            ),
+            expected=dict(
+                result=True,
+                value=zone_root_permission,
+                summary=u'Added system permission "%s"' % zone_root_permission,
+            ),
+        ),
+
+        dict(
+            desc='Delete zone %r' % zone_root,
+            command=('dnszone_del', [zone_root], {}),
+            expected={
+                'value': [zone_root_dnsname],
+                'summary': u'Deleted DNS zone "%s"' % zone_root,
+                'result': {'failed': []},
+            },
+        ),
+
+    ]
-- 
1.8.3.1

From eaccc9184e9601e5c262cccf074a42b37943bfc6 Mon Sep 17 00:00:00 2001
From: Martin Basti <[email protected]>
Date: Fri, 5 Sep 2014 16:09:59 +0200
Subject: [PATCH 1/2] Deprecation of --name-server and --ip-address option in
 DNS

Option --name-server is changing only SOA MNAME, this option has no more
effect to NS records

Option --ip-addres is just ignored

A warning message is sent after use these options

Part of ticket: https://fedorahosted.org/freeipa/ticket/4149
---
 API.txt               |   2 +-
 VERSION               |   4 +-
 ipalib/messages.py    |  21 +++++++++
 ipalib/plugins/dns.py | 125 +++++++++++++++++++++-----------------------------
 4 files changed, 77 insertions(+), 75 deletions(-)

diff --git a/API.txt b/API.txt
index bbd0f507b2faeec0239920cdcff28fe25d618e02..09a80df32e381d7c9a97b28fefb591f184e50f00 100644
--- a/API.txt
+++ b/API.txt
@@ -1152,7 +1152,7 @@ option: StrEnum('idnsforwardpolicy', attribute=True, cli_name='forward_policy',
 option: Bool('idnssecinlinesigning', attribute=True, cli_name='dnssec', default=False, multivalue=False, required=False)
 option: Int('idnssoaexpire', attribute=True, autofill=True, cli_name='expire', default=1209600, maxvalue=2147483647, minvalue=0, multivalue=False, required=True)
 option: Int('idnssoaminimum', attribute=True, autofill=True, cli_name='minimum', default=3600, maxvalue=2147483647, minvalue=0, multivalue=False, required=True)
-option: DNSNameParam('idnssoamname', attribute=True, cli_name='name_server', multivalue=False, required=True)
+option: DNSNameParam('idnssoamname', attribute=True, cli_name='name_server', multivalue=False, required=False)
 option: Int('idnssoarefresh', attribute=True, autofill=True, cli_name='refresh', default=3600, maxvalue=2147483647, minvalue=0, multivalue=False, required=True)
 option: Int('idnssoaretry', attribute=True, autofill=True, cli_name='retry', default=900, maxvalue=2147483647, minvalue=0, multivalue=False, required=True)
 option: DNSNameParam('idnssoarname', attribute=True, cli_name='admin_email', multivalue=False, only_absolute=True, required=True)
diff --git a/VERSION b/VERSION
index 379ead7565f23218cea087ef7ee487a71102fa7f..17672ff0c3d7f8f4771901c9cb828f02f0b8a8f2 100644
--- a/VERSION
+++ b/VERSION
@@ -89,5 +89,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=102
-# Last change: pviktori - allow adding services to roles
+IPA_API_VERSION_MINOR=103
+# Last change: mbasti - make --name-server option optional
diff --git a/ipalib/messages.py b/ipalib/messages.py
index f637e5b17de816f3a88645c65f4a01179d97552c..57ba1d748955bef6f8ef4d42dd595d3ab6df7faf 100644
--- a/ipalib/messages.py
+++ b/ipalib/messages.py
@@ -157,6 +157,27 @@ class DNSSECWarning(PublicMessage):
     type = "warning"
     format = _("DNSSEC support is experimental.\n%(additional_info)s")
 
+
+class OptionDeprecatedWarning(PublicMessage):
+    """
+    **13004** Used when user uses a deprecated option
+    """
+
+    errno = 13004
+    type = "warning"
+    format = _(u"'%(option)s' option is deprecated. %(additional_info)s")
+
+
+class OptionSemanticChangedWarning(PublicMessage):
+    """
+    **13005** Used when option which recently changes its semantic is used
+    """
+
+    errno = 13005
+    type = "warning"
+    format = _(u"semantic of '%(option)s' option was changed: %(current_behavior)s.\n%(hint)s")
+
+
 def iter_messages(variables, base):
     """Return a tuple with all subclasses
     """
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index ab79a8ef3e636be10aa10c2a22e07e3d31758cbc..1b9ecb9d896d4cb663791adf51d6410373127f36 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -42,7 +42,7 @@ from ipalib import messages
 from ipalib.util import (validate_zonemgr, normalize_zonemgr,
                          get_dns_forward_zone_update_policy,
                          get_dns_reverse_zone_update_policy,
-                         get_reverse_zone_default, REVERSE_DNS_ZONES)
+                         get_reverse_zone_default, REVERSE_DNS_ZONES, normalize_zone)
 from ipapython.ipautil import valid_ip, CheckedIPAddress, is_host_resolvable
 from ipapython.dnsutil import DNSName
 
@@ -2088,6 +2088,7 @@ class dnszone(DNSZoneBase):
             cli_name='name_server',
             label=_('Authoritative nameserver'),
             doc=_('Authoritative nameserver domain name'),
+            required=False,
         ),
         DNSNameParam('idnssoarname',
             _rname_validator,
@@ -2317,6 +2318,16 @@ class dnszone(DNSZoneBase):
                     "server.")
                 ))
 
+    def _warning_name_server_option(self, result, context, **options):
+        if getattr(context, 'show_warning_nameserver_option', False):
+            messages.add_message(
+                options['version'],
+                result, messages.OptionSemanticChangedWarning(
+                    option=u"--name-server",
+                    current_behavior=_(u"the option is used only for setting up the SOA MNAME attribute"),
+                    hint=_(u"To edit NS record(s) in zone apex, use command 'dnsrecord-mod [zone] @ --ns-rec=nameserver'.")
+                )
+            )
 
 @register()
 class dnszone_add(DNSZoneBase_add):
@@ -2327,39 +2338,23 @@ class dnszone_add(DNSZoneBase_add):
              label=_('Force'),
              doc=_('Force DNS zone creation even if nameserver is not resolvable.'),
         ),
+
+        # Deprecated
+        # ip-address option is not used anymore, we have to keep it due to compability with clients older than 4.1
         Str('ip_address?', _validate_ipaddr,
-            doc=_('Add forward record for nameserver located in the created zone'),
-            label=_('Nameserver IP address'),
+            doc=_('Add forward record for nameserver located in the created zone (Deprecated)'),
+            label=_('Nameserver IP address (Deprecated)'),
+            flags = ['no_option', ]
         ),
     )
 
-    def interactive_prompt_callback(self, kw):
-        """
-        Interactive mode should prompt for nameserver IP address only if all
-        of the following conditions are true:
-        * New zone is a forward zone
-        * NS is defined inside the new zone (NS can be given either in the
-          form of absolute or relative name)
-        """
-        if kw.get('ip_address', None):
-            return
-
-        try:
-            zone = DNSName(kw['idnsname']).make_absolute()
-        except Exception, e:
-            raise errors.ValidationError(name='idnsname', error=unicode(e))
-
-        try:
-            ns = DNSName(kw['idnssoamname'])
-        except Exception, e:
-            raise errors.ValidationError(name='idnssoamname', error=unicode(e))
-
-        relative_ns = not ns.is_absolute()
-        ns_in_zone = self.obj.get_name_in_zone(zone, ns)
-
-        if not zone.is_reverse() and (relative_ns or ns_in_zone):
-            ip_address = self.Backend.textui.prompt(_(u'Nameserver IP address'))
-            kw['ip_address'] = ip_address
+    def _warning_deprecated_option(self, result, **options):
+        if 'ip_address' in options:
+            messages.add_message(
+                options['version'],
+                result,
+                messages.OptionDeprecatedWarning(option='ip-address', additional_info=u"Value will be ignored.")
+            )
 
     def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
         assert isinstance(dn, DN)
@@ -2367,61 +2362,44 @@ class dnszone_add(DNSZoneBase_add):
         dn = super(dnszone_add, self).pre_callback(ldap, dn, entry_attrs,
             attrs_list, *keys, **options)
 
-        # Check nameserver has a forward record
-        nameserver = entry_attrs['idnssoamname']
-
-        # NS record must contain domain name
-        if valid_ip(nameserver):
-            raise errors.ValidationError(name='name-server',
-                    error=_("Nameserver address is not a domain name"))
-
-        nameserver_ip_address = options.get('ip_address')
+        nameservers = [normalize_zone(x) for x in api.Object.dnsrecord.get_dns_masters()]
+        server = normalize_zone(api.env.host)
         zone = keys[-1]
-        if nameserver.is_absolute():
-            record_in_zone = self.obj.get_name_in_zone(keys[-1], nameserver)
-        else:
-            record_in_zone = nameserver
 
-        if zone.is_reverse():
-            if not nameserver.is_absolute():
+        if entry_attrs.get('idnssoamname'):
+            if zone.is_reverse() and not entry_attrs['idnssoamname'].is_absolute():
                 raise errors.ValidationError(name='name-server',
-                        error=_("Nameserver for reverse zone cannot be "
-                                "a relative DNS name"))
-            elif nameserver_ip_address:
-                raise errors.ValidationError(name='ip_address',
-                        error=_("Nameserver DNS record is created for "
-                                "for forward zones only"))
-        elif (nameserver_ip_address and nameserver.is_absolute() and
-              record_in_zone is None):
-            raise errors.ValidationError(name='ip_address',
-                    error=_("Nameserver DNS record is created only for "
-                            "nameservers in current zone"))
+                    error=_("Nameserver for reverse zone cannot be a relative DNS name"))
 
-        if not nameserver_ip_address and not options['force']:
-             check_ns_rec_resolvable(keys[0], nameserver)
+            # verify if user specified server is resolvable
+            if not options['force']:
+                check_ns_rec_resolvable(keys[0], entry_attrs['idnssoamname'])
+            # show warning about --name-server option
+            context.show_warning_nameserver_option = True
+        else:
+            # user didn't specify SOA mname
+            if server in nameservers:
+                # current ipa server is authoritative nameserver in SOA record
+                entry_attrs['idnssoamname'] = [server]
+            else:
+                # a first DNS capable server is authoritative nameserver in SOA record
+                entry_attrs['idnssoamname'] = [nameservers[0]]
+
+        # all ipa DNS servers should be in NS zone record (as absolute domain name)
+        entry_attrs['nsrecord'] = nameservers
 
-        entry_attrs['nsrecord'] = nameserver
-        entry_attrs['idnssoamname'] = nameserver
         return dn
 
     def execute(self, *keys, **options):
         result = super(dnszone_add, self).execute(*keys, **options)
+        self._warning_deprecated_option(result, **options)
         self.obj._warning_forwarding(result, **options)
         self.obj._warning_dnssec_experimental(result, *keys, **options)
+        self.obj._warning_name_server_option(result, context, **options)
         return result
 
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
         assert isinstance(dn, DN)
-        nameserver_ip_address = options.get('ip_address')
-        if nameserver_ip_address:
-            nameserver = entry_attrs['idnssoamname'][0]
-            if nameserver.is_absolute():
-                dns_record = self.obj.get_name_in_zone(keys[-1], nameserver)
-            else:
-                dns_record = nameserver
-            add_forward_record(keys[-1],
-                               dns_record,
-                               nameserver_ip_address)
 
         # Add entry to realmdomains
         # except for our own domain, forward zones, reverse zones and root zone
@@ -2484,8 +2462,10 @@ class dnszone_mod(DNSZoneBase_mod):
         if not _check_DN_objectclass(ldap, dn, self.obj.object_class):
             self.obj.handle_not_found(*keys)
         nameserver = entry_attrs.get('idnssoamname')
-        if nameserver and not nameserver.is_empty() and not options['force']:
-            check_ns_rec_resolvable(keys[0], nameserver)
+        if nameserver:
+            if not nameserver.is_empty() and not options['force']:
+                check_ns_rec_resolvable(keys[0], nameserver)
+            context.show_warning_nameserver_option = True
 
         return dn
 
@@ -2493,6 +2473,7 @@ class dnszone_mod(DNSZoneBase_mod):
         result = super(dnszone_mod, self).execute(*keys, **options)
         self.obj._warning_forwarding(result, **options)
         self.obj._warning_dnssec_experimental(result, *keys, **options)
+        self.obj._warning_name_server_option(result, context, **options)
         return result
 
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
-- 
1.8.3.1

From 3076d2948f93e9bc853e8f2a08cd12df60889169 Mon Sep 17 00:00:00 2001
From: Martin Basti <[email protected]>
Date: Fri, 12 Sep 2014 13:20:16 +0200
Subject: [PATCH 2/2] Add correct NS records during installation

All ipa-dns capable server is added to root zones as nameserver

During uninstall all NS records pointing to particular replica are
removed.

Part of ticket: https://fedorahosted.org/freeipa/ticket/4149
---
 install/tools/ipa-replica-manage  |   1 +
 ipaserver/install/bindinstance.py | 106 +++++++++++++++++++++-----------------
 2 files changed, 61 insertions(+), 46 deletions(-)

diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index aa710953a7d41348b330498727dbc57818e5ce0b..e44131ebe637f10990ecc5a81f3fb896c92d5313 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -745,6 +745,7 @@ def del_master(realm, hostname, options):
             bind = bindinstance.BindInstance()
             bind.remove_master_dns_records(hostname, realm, realm.lower())
             bind.remove_ipa_ca_dns_records(hostname, realm.lower())
+            bind.remove_server_ns_records(hostname)
     except Exception, e:
         print "Failed to cleanup %s DNS entries: %s" % (hostname, e)
         print "You may need to manually remove them from the tree"
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index dfb086f109371ae97151622e2c44db27256896db..086e0276e8ef824c2367cc35861c616f3df7f00c 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -279,11 +279,11 @@ def read_reverse_zone(default, ip_address):
 
     return normalize_zone(zone)
 
-def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_address=None,
+def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None,
        update_policy=None, force=False):
-    if zone_is_reverse(name):
-        # always normalize reverse zones
-        name = normalize_zone(name)
+
+    # always normalize zones
+    name = normalize_zone(name)
 
     if update_policy is None:
         if zone_is_reverse(name):
@@ -294,27 +294,13 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_addres
     if zonemgr is None:
         zonemgr = 'hostmaster.%s' % name
 
-    if ns_hostname is None:
-        # automatically retrieve list of DNS masters
-        dns_masters = api.Object.dnsrecord.get_dns_masters()
-        if not dns_masters:
-            raise installutils.ScriptError(
-                "No IPA server with DNS support found!")
-        ns_main = dns_masters.pop(0)
-        ns_replicas = dns_masters
-    else:
-        ns_main = ns_hostname
-        ns_replicas = []
-    ns_main = normalize_zone(ns_main)
-
-    if ns_ip_address is not None:
-        ns_ip_address = unicode(ns_ip_address)
+    if ns_hostname:
+        ns_hostname = normalize_zone(ns_hostname)
 
     try:
         api.Command.dnszone_add(unicode(name),
-                                idnssoamname=unicode(ns_main),
+                                idnssoamname=unicode(ns_hostname),
                                 idnssoarname=unicode(zonemgr),
-                                ip_address=ns_ip_address,
                                 idnsallowdynupdate=True,
                                 idnsupdatepolicy=unicode(update_policy),
                                 idnsallowquery=u'any',
@@ -323,11 +309,6 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_addres
     except (errors.DuplicateEntry, errors.EmptyModlist):
         pass
 
-    nameservers = ns_replicas + [ns_main]
-    for hostname in nameservers:
-        hostname = normalize_zone(hostname)
-        add_ns_rr(name, hostname, dns_backup=None, force=True)
-
 def add_rr(zone, name, type, rdata, dns_backup=None, **kwargs):
     addkw = { '%srecord' % str(type.lower()) : unicode(rdata) }
     addkw.update(kwargs)
@@ -368,6 +349,9 @@ def del_fwd_rr(zone, host, ip_address):
     elif addr.version == 6:
         del_rr(zone, host, "AAAA", ip_address)
 
+def del_ns_rr(zone, name, rdata):
+    del_rr(zone, name, 'NS', rdata)
+
 def get_rr(zone, name, type):
     rectype = '%srecord' % unicode(type.lower())
     ret = api.Command.dnsrecord_find(unicode(zone), unicode(name))
@@ -533,16 +517,16 @@ class BindInstance(service.Service):
         if self.first_instance:
             self.step("adding DNS container", self.__setup_dns_container)
 
-        if dns_zone_exists(self.domain):
-            self.step("adding NS record to the zone", self.__add_self_ns)
-        else:
+        if not dns_zone_exists(self.domain):
             self.step("setting up our zone", self.__setup_zone)
+
         if self.reverse_zone is not None:
             self.step("setting up reverse zone", self.__setup_reverse_zone)
 
         self.step("setting up our own record", self.__add_self)
         if self.first_instance:
             self.step("setting up records for other masters", self.__add_others)
+        self.step("adding NS record to the zones", self.__add_self_ns)  # all zones must be created before this step
         self.step("setting up CA record", self.__add_ipa_ca_record)
 
         self.step("setting up kerberos principal", self.__setup_principal)
@@ -615,19 +599,20 @@ class BindInstance(service.Service):
         self._ldap_mod("dns.ldif", self.sub_dict)
 
     def __setup_zone(self):
-        nameserver_ip_address = self.ip_address
-        if not self.host_in_default_domain():
-            # Nameserver is in self.host_domain, no forward record added to self.domain
-            nameserver_ip_address = None
         # Always use force=True as named is not set up yet
         add_zone(self.domain, self.zonemgr, dns_backup=self.dns_backup,
-                ns_hostname=api.env.host, ns_ip_address=nameserver_ip_address,
-                force=True)
+                ns_hostname=api.env.host, force=True)
 
         add_rr(self.domain, "_kerberos", "TXT", self.realm)
 
     def __add_self_ns(self):
-        add_ns_rr(self.domain, api.env.host, self.dns_backup, force=True)
+        # add NS record to all zones
+        ns_hostname = normalize_zone(api.env.host)
+        result = api.Command.dnszone_find()
+        for zone in result['result']:
+            zone = unicode(zone['idnsname'][0])  # we need unicode due to backup
+            root_logger.debug("adding self NS to zone %s apex", zone)
+            add_ns_rr(zone, ns_hostname, self.dns_backup, force=True)
 
     def __setup_reverse_zone(self):
         # Always use force=True as named is not set up yet
@@ -666,14 +651,8 @@ class BindInstance(service.Service):
                     zone, self.domain))
             root_logger.debug("Add DNS zone for host first.")
 
-            if normalize_zone(zone) == normalize_zone(self.host_domain):
-                ns_ip_address = self.ip_address
-            else:
-                ns_ip_address = None
-
             add_zone(zone, self.zonemgr, dns_backup=self.dns_backup,
-                     ns_hostname=self.fqdn, ns_ip_address=ns_ip_address,
-                     force=True)
+                     ns_hostname=self.fqdn, force=True)
 
         # Add forward and reverse records to self
         for addr in addrs:
@@ -921,7 +900,6 @@ class BindInstance(service.Service):
             ("_kpasswd._tcp", "SRV", "0 100 464 %s" % self.host_in_rr),
             ("_kpasswd._udp", "SRV", "0 100 464 %s" % self.host_in_rr),
             ("_ntp._udp", "SRV", "0 100 123 %s" % self.host_in_rr),
-            ("@", "NS", normalize_zone(fqdn)),
         )
 
         for (record, type, rdata) in resource_records:
@@ -935,8 +913,6 @@ class BindInstance(service.Service):
             if rzone is not None:
                 record = get_reverse_record_name(rzone, rdata)
                 del_rr(rzone, record, "PTR", normalize_zone(fqdn))
-                # remove also master NS record from the reverse zone
-                del_rr(rzone, "@", "NS", normalize_zone(fqdn))
 
     def remove_ipa_ca_dns_records(self, fqdn, domain_name):
         host, zone = fqdn.split(".", 1)
@@ -948,6 +924,44 @@ class BindInstance(service.Service):
         for addr in addrs:
             del_fwd_rr(domain_name, IPA_CA_RECORD, addr)
 
+    def remove_server_ns_records(self, fqdn):
+        """
+        Remove all NS records pointing to this server
+        """
+        ns_rdata = normalize_zone(fqdn)
+        if not api.Backend.ldap2.isconnected():
+            root_logger.debug("no ldap2 connection, removing NS records pointing to %s failed", ns_rdata)
+            print "no ldap2 connection"  #TODO remove
+            return  # we can't modify records
+        ldap = api.Backend.ldap2
+
+        # find all NS records pointing to this server
+
+        search_kw = {}
+        search_kw['nsrecord'] = ns_rdata
+        attr_filter = ldap.make_filter(search_kw, rules=ldap.MATCH_ALL)
+        attributes = ['idnsname', 'objectclass']
+        dn = DN(api.env.container_dns, api.env.basedn)
+
+        entries, truncated = ldap.find_entries(attr_filter, attributes, base_dn=dn)
+
+        # remove records
+        if entries:
+            root_logger.debug("Removing all NS records pointing to %s:", ns_rdata)
+
+        for entry in entries:
+            print "entry", repr(entry)
+            if 'idnszone' in entry['objectclass']:
+                # zone record
+                zone = entry.single_value['idnsname']
+                root_logger.debug("zone record %s", zone)
+                del_ns_rr(zone, u'@', ns_rdata)
+            else:
+                zone = entry.dn[1].value  # get zone from DN
+                record = entry.single_value['idnsname']
+                root_logger.debug("record %s in zone %s", record, zone)
+                del_ns_rr(zone, record, ns_rdata)
+
     def check_global_configuration(self):
         """
         Check global DNS configuration in LDAP server and inform user when it
-- 
1.8.3.1

From 25c481e51f46f886c98186fee0231005a064bfab Mon Sep 17 00:00:00 2001
From: Martin Basti <[email protected]>
Date: Tue, 16 Sep 2014 12:23:21 +0200
Subject: [PATCH 1/3] DNS: autofill admin email

Admins email (SOA RNAME) is autofilled with value 'hostmaster'. Bind
will automaticaly append zone part.

Part of ticket: https://fedorahosted.org/freeipa/ticket/4149
---
 API.txt               |  6 +++---
 VERSION               |  4 ++--
 ipalib/plugins/dns.py |  9 ++++-----
 ipalib/util.py        | 11 +----------
 4 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/API.txt b/API.txt
index 09a80df32e381d7c9a97b28fefb591f184e50f00..ae869ffce94a30859eb9ace414374172d238f8b3 100644
--- a/API.txt
+++ b/API.txt
@@ -1155,7 +1155,7 @@ option: Int('idnssoaminimum', attribute=True, autofill=True, cli_name='minimum',
 option: DNSNameParam('idnssoamname', attribute=True, cli_name='name_server', multivalue=False, required=False)
 option: Int('idnssoarefresh', attribute=True, autofill=True, cli_name='refresh', default=3600, maxvalue=2147483647, minvalue=0, multivalue=False, required=True)
 option: Int('idnssoaretry', attribute=True, autofill=True, cli_name='retry', default=900, maxvalue=2147483647, minvalue=0, multivalue=False, required=True)
-option: DNSNameParam('idnssoarname', attribute=True, cli_name='admin_email', multivalue=False, only_absolute=True, required=True)
+option: DNSNameParam('idnssoarname', attribute=True, autofill=True, cli_name='admin_email', default=<DNS name hostmaster>, multivalue=False, required=True)
 option: Int('idnssoaserial', attribute=True, autofill=True, cli_name='serial', maxvalue=4294967295L, minvalue=1, multivalue=False, required=True)
 option: Str('idnsupdatepolicy', attribute=True, autofill=True, cli_name='update_policy', multivalue=False, required=False)
 option: Str('ip_address?')
@@ -1216,7 +1216,7 @@ option: Int('idnssoaminimum', attribute=True, autofill=False, cli_name='minimum'
 option: DNSNameParam('idnssoamname', attribute=True, autofill=False, cli_name='name_server', multivalue=False, query=True, required=False)
 option: Int('idnssoarefresh', attribute=True, autofill=False, cli_name='refresh', default=3600, maxvalue=2147483647, minvalue=0, multivalue=False, query=True, required=False)
 option: Int('idnssoaretry', attribute=True, autofill=False, cli_name='retry', default=900, maxvalue=2147483647, minvalue=0, multivalue=False, query=True, required=False)
-option: DNSNameParam('idnssoarname', attribute=True, autofill=False, cli_name='admin_email', multivalue=False, only_absolute=True, query=True, required=False)
+option: DNSNameParam('idnssoarname', attribute=True, autofill=False, cli_name='admin_email', default=<DNS name hostmaster>, multivalue=False, query=True, required=False)
 option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', maxvalue=4294967295L, minvalue=1, multivalue=False, query=True, required=False)
 option: Str('idnsupdatepolicy', attribute=True, autofill=False, cli_name='update_policy', multivalue=False, query=True, required=False)
 option: Bool('idnszoneactive', attribute=True, autofill=False, cli_name='zone_active', multivalue=False, query=True, required=False)
@@ -1252,7 +1252,7 @@ option: Int('idnssoaminimum', attribute=True, autofill=False, cli_name='minimum'
 option: DNSNameParam('idnssoamname', attribute=True, autofill=False, cli_name='name_server', multivalue=False, required=False)
 option: Int('idnssoarefresh', attribute=True, autofill=False, cli_name='refresh', default=3600, maxvalue=2147483647, minvalue=0, multivalue=False, required=False)
 option: Int('idnssoaretry', attribute=True, autofill=False, cli_name='retry', default=900, maxvalue=2147483647, minvalue=0, multivalue=False, required=False)
-option: DNSNameParam('idnssoarname', attribute=True, autofill=False, cli_name='admin_email', multivalue=False, only_absolute=True, required=False)
+option: DNSNameParam('idnssoarname', attribute=True, autofill=False, cli_name='admin_email', default=<DNS name hostmaster>, multivalue=False, required=False)
 option: Int('idnssoaserial', attribute=True, autofill=False, cli_name='serial', maxvalue=4294967295L, minvalue=1, multivalue=False, required=False)
 option: Str('idnsupdatepolicy', attribute=True, autofill=False, cli_name='update_policy', multivalue=False, required=False)
 option: Str('name_from_ip', attribute=False, autofill=False, cli_name='name_from_ip', multivalue=False, required=False)
diff --git a/VERSION b/VERSION
index 17672ff0c3d7f8f4771901c9cb828f02f0b8a8f2..60c62a3e237be5e4f15525cc35d51479d056834e 100644
--- a/VERSION
+++ b/VERSION
@@ -89,5 +89,5 @@ IPA_DATA_VERSION=20100614120000
 #                                                      #
 ########################################################
 IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=103
-# Last change: mbasti - make --name-server option optional
+IPA_API_VERSION_MINOR=104
+# Last change: mbasti - autofill --admin-email in DNS zone
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index 1b9ecb9d896d4cb663791adf51d6410373127f36..81c16441f82794107ca333ef4ed1047a7a567f8b 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -312,8 +312,8 @@ _output_permissions = (
 
 def _rname_validator(ugettext, zonemgr):
     try:
-        validate_zonemgr(zonemgr)
-    except (ValueError, dns.exception.SyntaxError), e:
+        DNSName(zonemgr)  # test only if it is valid domain name
+    except (ValueError, dns.exception.SyntaxError) as e:
         return unicode(e)
     return None
 
@@ -2092,13 +2092,12 @@ class dnszone(DNSZoneBase):
         ),
         DNSNameParam('idnssoarname',
             _rname_validator,
-            only_absolute=True,
             cli_name='admin_email',
             label=_('Administrator e-mail address'),
             doc=_('Administrator e-mail address'),
-            default_from=lambda idnsname:
-                DNSName(('hostmaster')).derelativize(idnsname),
+            default= DNSName(u'hostmaster'),
             normalizer=normalize_zonemgr,
+            autofill=True,
         ),
         Int('idnssoaserial',
             cli_name='serial',
diff --git a/ipalib/util.py b/ipalib/util.py
index 55c90a99208844386193ceef431b51651bfe2467..a5eff582f254ee7aa5f5dcbef9013898acb6f892 100644
--- a/ipalib/util.py
+++ b/ipalib/util.py
@@ -219,9 +219,6 @@ def normalize_zonemgr(zonemgr):
         name = name.replace('.', '\\.')
         zonemgr = u''.join((name, u'.', domain))
 
-    if not zonemgr.endswith('.'):
-        zonemgr = zonemgr + u'.'
-
     return zonemgr
 
 def normalize_zone(zone):
@@ -273,18 +270,12 @@ def validate_domain_name(domain_name, allow_underscore=False, allow_slash=False)
 
 def validate_zonemgr(zonemgr):
     assert isinstance(zonemgr, DNSName)
-    assert zonemgr.is_absolute()
-    """ See RFC 1033, 1035 """
     if any('@' in label for label in zonemgr.labels):
         raise ValueError(_('too many \'@\' characters'))
-    if len(zonemgr.labels) < 3:
-        raise ValueError(_('missing address domain'))
-    if not zonemgr.labels[0]:
-        raise ValueError(_('missing mail account'))
+
 
 def validate_zonemgr_str(zonemgr):
     zonemgr = normalize_zonemgr(zonemgr)
-    zonemgr = DNSName(zonemgr).make_absolute()
     return validate_zonemgr(zonemgr)
 
 def validate_hostname(hostname, check_fqdn=True, allow_underscore=False, allow_slash=False):
-- 
1.8.3.1

From 30a7237608e072382c46551ceac6e36e1021fd93 Mon Sep 17 00:00:00 2001
From: Martin Basti <[email protected]>
Date: Tue, 16 Sep 2014 16:14:07 +0200
Subject: [PATCH 2/3] WebUI: DNS: Remove ip-address, admin-email options

Part of ticket: https://fedorahosted.org/freeipa/ticket/4149
---
 install/ui/src/freeipa/dns.js | 61 -------------------------------------------
 1 file changed, 61 deletions(-)

diff --git a/install/ui/src/freeipa/dns.js b/install/ui/src/freeipa/dns.js
index c5e7b24d8dd567ef66b401538160fc19add110d4..a1b881e1ee1bbaa67cd6d86e64771f4f10177860 100644
--- a/install/ui/src/freeipa/dns.js
+++ b/install/ui/src/freeipa/dns.js
@@ -303,26 +303,6 @@ return {
                         validators: ['network']
                     }
                 ]
-            },
-            {
-                name: 'other',
-                fields: [
-                    'idnssoamname',
-                    {
-                        name: 'ip_address',
-                        validators: [ 'ip_address' ],
-                        metadata: '@mc-opt:dnszone_add:ip_address'
-                    },
-                    {
-                        name: 'idnssoarname',
-                        required: false
-                    },
-                    {
-                        $type: 'force_dnszone_add_checkbox',
-                        name: 'force',
-                        metadata: '@mc-opt:dnszone_add:force'
-                    }
-                ]
             }
         ],
         policies: [
@@ -683,48 +663,7 @@ IPA.dnszone_adder_dialog = function(spec) {
     var init = function() {
         var zone_w = that.fields.get_field('idnsname').widget;
         var reverse_zone_w = that.fields.get_field('name_from_ip').widget;
-        var ns_w = that.fields.get_field('idnssoamname').widget;
 
-        zone_w.value_changed.attach(that.check_ns_ip);
-        reverse_zone_w.value_changed.attach(that.check_ns_ip);
-        ns_w.value_changed.attach(that.check_ns_ip);
-    };
-
-    that.check_ns_ip = function() {
-        var ip_address_f = that.fields.get_field('ip_address');
-        var zone_w = that.fields.get_field('idnsname').widget;
-        var ns_w = that.fields.get_field('idnssoamname').widget;
-
-        var zone = zone_w.save()[0] || '';
-        var ns = ns_w.save()[0] || '';
-
-        var zone_is_reverse = !zone_w.enabled ||
-                              ends_with(zone, '.in-addr.arpa.') ||
-                              ends_with(zone, '.ip6.arpa.');
-        var relative_ns = true;
-        var ns_in_zone = false;
-
-        if (ns && ns[ns.length-1] === '.') {
-            relative_ns = false;
-            ns = ns.slice(0, -1);
-        }
-
-        if (zone && zone[zone.length-1] === '.') {
-            zone = zone.slice(0, -1);
-        }
-
-        if (ns && zone && ends_with(ns, '.' + zone)) {
-            ns_in_zone = true;
-        }
-
-        if (!zone_is_reverse && (relative_ns || ns_in_zone)) {
-            ip_address_f.set_enabled(true);
-            ip_address_f.set_required(true);
-        } else {
-            ip_address_f.reset();
-            ip_address_f.set_required(false);
-            ip_address_f.set_enabled(false);
-        }
     };
 
     that.create_content = function() {
-- 
1.8.3.1

From f98bc5378c63c74e8a3a9fb7bb132f741058f00a Mon Sep 17 00:00:00 2001
From: Martin Basti <[email protected]>
Date: Fri, 19 Sep 2014 12:38:34 +0200
Subject: [PATCH 3/3] DNS tests: tests update to due to change in options

Affected options --name-server, --ip-address

Part of ticket: https://fedorahosted.org/freeipa/ticket/4149
---
 ipatests/test_cmdline/test_cli.py                  |  78 +---
 ipatests/test_xmlrpc/test_dns_plugin.py            | 467 +++++++++------------
 .../test_dns_realmdomains_integration.py           |  15 +-
 ipatests/test_xmlrpc/test_host_plugin.py           |  19 +-
 4 files changed, 228 insertions(+), 351 deletions(-)

diff --git a/ipatests/test_cmdline/test_cli.py b/ipatests/test_cmdline/test_cli.py
index 489d2ceb3536c2aa08cea0c4fe7ad3321668400f..b450e85113e74cf65ae174ff1394628e0757bf99 100644
--- a/ipatests/test_cmdline/test_cli.py
+++ b/ipatests/test_cmdline/test_cli.py
@@ -139,14 +139,13 @@ class TestCLIParsing(object):
 
     def test_dnsrecord_del_all(self):
         try:
-            self.run_command('dnszone_add', idnsname=u'test-example.com',
-                idnssoamname=u'ns.test-example.com', force=True)
+            self.run_command('dnszone_add', idnsname=u'test-example.com')
         except errors.NotFound:
             raise nose.SkipTest('DNS is not configured')
         try:
             self.run_command('dnsrecord_add',
                 dnszoneidnsname=u'test-example.com',
-                idnsname=u'ns', arecord=u'1.2.3.4')
+                idnsname=u'ns', arecord=u'1.2.3.4', force=True)
             with self.fake_stdin('yes\n'):
                 self.check_command('dnsrecord_del test-example.com ns',
                     'dnsrecord_del',
@@ -168,8 +167,7 @@ class TestCLIParsing(object):
 
     def test_dnsrecord_del_one_by_one(self):
         try:
-            self.run_command('dnszone_add', idnsname=u'test-example.com',
-                idnssoamname=u'ns.test-example.com', force=True)
+            self.run_command('dnszone_add', idnsname=u'test-example.com')
         except errors.NotFound:
             raise nose.SkipTest('DNS is not configured')
         try:
@@ -243,8 +241,7 @@ class TestCLIParsing(object):
     def test_dnsrecord_del_comma(self):
         try:
             self.run_command(
-                'dnszone_add', idnsname=u'test-example.com',
-                idnssoamname=u'ns.test-example.com', force=True)
+                'dnszone_add', idnsname=u'test-example.com')
         except errors.NotFound:
             raise nose.SkipTest('DNS is not configured')
         try:
@@ -266,73 +263,6 @@ class TestCLIParsing(object):
         finally:
             self.run_command('dnszone_del', idnsname=u'test-example.com')
 
-    def test_dnszone_add(self):
-        """
-        Test dnszone-add with nameserver IP passed interatively
-        """
-        # Pass IP of nameserver interactively for nameserver in zone
-        # (absolute name)
-        with self.fake_stdin('1.1.1.1\n'):
-            self.check_command(
-                'dnszone_add example.com --name-server=ns.example.com. '
-                '[email protected]',
-                'dnszone_add',
-                idnsname=u'example.com',
-                idnssoamname=u'ns.example.com.',
-                idnssoarname=u'[email protected]',
-                ip_address=u'1.1.1.1',
-                idnssoaexpire=util.Fuzzy(type=int),
-                idnssoaserial=util.Fuzzy(type=int),
-                idnssoaretry=util.Fuzzy(type=int),
-                idnssoaminimum=util.Fuzzy(type=int),
-                idnssoarefresh=util.Fuzzy(type=int),
-                all=False,
-                raw=False,
-                force=False,
-                version=API_VERSION
-            )
-
-        # Pass IP of nameserver interactively for nameserver in zone
-        # (relative name)
-        with self.fake_stdin('1.1.1.1\n'):
-            self.check_command(
-                'dnszone_add example.com --name-server=ns '
-                '[email protected]',
-                'dnszone_add',
-                idnsname=u'example.com',
-                idnssoamname=u'ns',
-                idnssoarname=u'[email protected]',
-                ip_address=u'1.1.1.1',
-                idnssoaexpire=util.Fuzzy(type=int),
-                idnssoaserial=util.Fuzzy(type=int),
-                idnssoaretry=util.Fuzzy(type=int),
-                idnssoaminimum=util.Fuzzy(type=int),
-                idnssoarefresh=util.Fuzzy(type=int),
-                all=False,
-                raw=False,
-                force=False,
-                version=API_VERSION
-            )
-
-        # Nameserver is outside the zone - no need to pass the IP
-        self.check_command(
-            'dnszone_add example.com --name-server=ns.example.net. '
-            '[email protected]',
-            'dnszone_add',
-            idnsname=u'example.com',
-            idnssoamname=u'ns.example.net.',
-            idnssoarname=u'[email protected]',
-            idnssoaexpire=util.Fuzzy(type=int),
-            idnssoaserial=util.Fuzzy(type=int),
-            idnssoaretry=util.Fuzzy(type=int),
-            idnssoaminimum=util.Fuzzy(type=int),
-            idnssoarefresh=util.Fuzzy(type=int),
-            all=False,
-            raw=False,
-            force=False,
-            version=API_VERSION
-        )
-
     def test_idrange_add(self):
         """
         Test idrange-add with interative prompt
diff --git a/ipatests/test_xmlrpc/test_dns_plugin.py b/ipatests/test_xmlrpc/test_dns_plugin.py
index 79638b00bb9fa414c611f00715d1c9c97ab8476d..77f8f94d595f65906a63cd199951dd401121a37a 100644
--- a/ipatests/test_xmlrpc/test_dns_plugin.py
+++ b/ipatests/test_xmlrpc/test_dns_plugin.py
@@ -22,13 +22,26 @@ Test the `ipalib/plugins/dns.py` module.
 
 import nose
 from ipalib import api, errors
+from ipalib.util import normalize_zone
 from ipapython.dnsutil import DNSName
 from ipapython.dn import DN
 from ipatests.test_xmlrpc import objectclasses
 from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
 
+try:
+    from ipaserver.plugins.ldap2 import ldap2
+except ImportError:
+    have_ldap2 = False
+else:
+    import krbV
+    have_ldap2 = True
+
 _dns_zone_record = DNSName(u'@')
 
+# default value of idnssoamname is local DNS server
+self_server_ns = normalize_zone(api.env.host)
+self_server_ns_dnsname = DNSName(self_server_ns)
+
 zone1 = u'dnszone.test'
 zone1_dnsname = DNSName(zone1)
 zone1_absolute = u'%s.' % zone1
@@ -38,6 +51,7 @@ zone1_dn = DN(('idnsname',zone1_absolute), api.env.container_dns, api.env.basedn
 zone1_ns = u'ns1.%s' % zone1_absolute
 zone1_ns_dnsname = DNSName(zone1_ns)
 zone1_ns_dn = DN(('idnsname','ns1'), zone1_dn)
+zone1_self_server_ns_dn = DN(('idnsname',self_server_ns), zone1_dn)
 zone1_rname = u'root.%s' % zone1_absolute
 zone1_rname_dnsname = DNSName(zone1_rname)
 zone1_permission = u'Manage DNS zone %s' % zone1_absolute
@@ -72,6 +86,7 @@ zone3_rname_dnsname = DNSName(zone3_rname)
 zone3_ns2_arec = u'ns2'
 zone3_ns2_arec_dnsname = DNSName(zone3_ns2_arec)
 zone3_ns2_arec_dn = DN(('idnsname',zone3_ns2_arec), zone3_dn)
+zone3_ns2_arec_absolute = u'%s.%s' % (zone3_ns2_arec, zone3_absolute)
 
 zone4_upper = u'ZONE4.test'
 zone4 = u'zone4.test.'
@@ -173,7 +188,7 @@ wildcard_rec1_addr = u'172.16.15.55'
 wildcard_rec1_test1 = u'a.test.%s' % zone1_absolute
 wildcard_rec1_test2 = u'b.test.%s' % zone1_absolute
 
-nsrev = u'128/25'
+nsrev = u'128/28'
 nsrev_dnsname = DNSName(nsrev)
 nsrev_dn = DN(('idnsname',nsrev), revzone3_classless1_dn)
 
@@ -275,6 +290,45 @@ zone_findtest_forward_dn = DN(('idnsname', zone_findtest_forward), api.env.conta
 
 zone_fw_wildcard = u'*.wildcardforwardzone.test.'
 
+def _get_nameservers_ldap(conn):
+    base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
+    ldap_filter = '(&(objectClass=ipaConfigObject)(cn=DNS))'
+    dns_masters = []
+
+    try:
+        entries = conn.find_entries(filter=ldap_filter, base_dn=base_dn)[0]
+
+        for entry in entries:
+            try:
+                master = entry.dn[1]['cn']
+                dns_masters.append(master)
+            except (IndexError, KeyError):
+                pass
+    except errors.NotFound:
+        return []
+
+    return dns_masters
+
+
+def get_nameservers():
+        ldap = ldap2(shared_instance=False)
+        ldap.connect(ccache=krbV.default_context().default_ccache())
+        nameservers = [normalize_zone(x) for x in _get_nameservers_ldap(ldap)]
+        return nameservers
+
+# get list of nameservers from LDAP
+get_nameservers_error = None
+if have_ldap2:
+    try:
+        nameservers = get_nameservers()
+    except Exception as e:
+        get_nameservers_error = e
+    else:
+        if not nameservers:
+            # if DNS is installed there must be at least one IPA DNS server
+            e = "No DNS servers found in LDAP"
+
+
 class test_dns(Declarative):
 
     @classmethod
@@ -283,11 +337,16 @@ class test_dns(Declarative):
 
         if not api.Backend.rpcclient.isconnected():
             api.Backend.rpcclient.connect(fallback=False)
+
+        if not have_ldap2:
+            raise nose.SkipTest('server plugin not available')
+
+        if get_nameservers_error is not None:
+            raise nose.SkipTest('unable to get list of nameservers (%s)' % get_nameservers_error)
+
         try:
            api.Command['dnszone_add'](zone1,
-               idnssoamname = zone1_ns,
                idnssoarname = zone1_rname,
-               force = True,
            )
            api.Command['dnszone_del'](zone1)
         except errors.NotFound:
@@ -349,9 +408,7 @@ class test_dns(Declarative):
             desc='Create zone %r' % zone1,
             command=(
                 'dnszone_add', [zone1], {
-                    'idnssoamname': zone1_ns,
                     'idnssoarname': zone1_rname,
-                    'ip_address' : zone1_ip,
                 }
             ),
             expected={
@@ -361,8 +418,8 @@ class test_dns(Declarative):
                     'dn': zone1_dn,
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone1_ns_dnsname],
-                    'nsrecord': [zone1_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -386,9 +443,7 @@ class test_dns(Declarative):
             desc='Try to create duplicate zone %r' % zone1,
             command=(
                 'dnszone_add', [zone1], {
-                    'idnssoamname': zone1_ns,
                     'idnssoarname': zone1_rname,
-                    'ip_address' : zone1_ip,
                 }
             ),
             expected=errors.DuplicateEntry(
@@ -412,7 +467,7 @@ class test_dns(Declarative):
                 'dnszone_add', [zone2], {
                     'idnssoamname': zone2_ns,
                     'idnssoarname': zone2_rname,
-                    'force'       : True,
+                    'force': True,
                 }
             ),
             expected={
@@ -423,7 +478,7 @@ class test_dns(Declarative):
                     'idnsname': [zone2_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
                     'idnssoamname': [zone2_ns_dnsname],
-                    'nsrecord': [zone2_ns],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone2_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -439,17 +494,23 @@ class test_dns(Declarative):
                     'idnsallowquery': [u'any;'],
                     'objectclass': objectclasses.dnszone,
                 },
+                'messages': (
+                    {'message': u"semantic of '--name-server' option was changed: the option is used only for setting up"
+                                u" the SOA MNAME attribute.\nTo edit NS record(s) in zone apex, use command "
+                                u"'dnsrecord-mod [zone] @ --ns-rec=nameserver'.",
+                     'code': 13005,
+                     'type': u'warning',
+                     'name': u'OptionSemanticChangedWarning'},
+                )
             },
         ),
 
 
         dict(
-            desc='Create a zone with upper case name with --force',
+            desc='Create a zone with upper case name',
             command=(
                 'dnszone_add', [zone4_upper], {
-                    'idnssoamname': zone4_ns,
                     'idnssoarname': zone4_rname,
-                    'force'       : True,
                 }
             ),
             expected={
@@ -459,8 +520,8 @@ class test_dns(Declarative):
                     'dn': zone4_dn,
                     'idnsname': [zone4_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone4_ns_dnsname],
-                    'nsrecord': [zone4_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone4_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -481,12 +542,10 @@ class test_dns(Declarative):
 
 
         dict(  # https://fedorahosted.org/freeipa/ticket/4268
-            desc='Create a zone with consecutive dash characters with --force',
+            desc='Create a zone with consecutive dash characters',
             command=(
                 'dnszone_add', [zone5], {
-                    'idnssoamname': zone5_ns,
                     'idnssoarname': zone5_rname,
-                    'force'       : True,
                 }
             ),
             expected={
@@ -496,8 +555,8 @@ class test_dns(Declarative):
                     'dn': zone5_dn,
                     'idnsname': [zone5_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone5_ns_dnsname],
-                    'nsrecord': [zone5_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone5_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -527,8 +586,8 @@ class test_dns(Declarative):
                     'dn': zone1_dn,
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -551,8 +610,8 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -631,8 +690,8 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -656,8 +715,8 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -688,7 +747,6 @@ class test_dns(Declarative):
             desc='Create reverse zone %r' % revzone1,
             command=(
                 'dnszone_add', [revzone1], {
-                    'idnssoamname': zone1_ns,
                     'idnssoarname': zone1_rname,
                 }
             ),
@@ -699,8 +757,8 @@ class test_dns(Declarative):
                     'dn': revzone1_dn,
                     'idnsname': [revzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone1_ns_dnsname],
-                    'nsrecord': [zone1_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -719,8 +777,8 @@ class test_dns(Declarative):
 
 
         dict(
-            desc='Search for zones with name server %r' % (zone1_ns),
-            command=('dnszone_find', [], {'idnssoamname': zone1_ns}),
+            desc='Search for zones with admin email %r' % (zone1_rname),
+            command=('dnszone_find', [], {'idnssoarname': zone1_rname}),
             expected={
                 'summary': None,
                 'count': 2,
@@ -729,8 +787,8 @@ class test_dns(Declarative):
                     'dn': revzone1_dn,
                     'idnsname': [revzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -744,8 +802,8 @@ class test_dns(Declarative):
                     'dn': zone1_dn,
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -760,8 +818,8 @@ class test_dns(Declarative):
 
 
         dict(
-            desc='Search for zones with name server %r with --forward-only' % zone1_ns,
-            command=('dnszone_find', [], {'idnssoamname': zone1_ns, 'forward_only' : True}),
+            desc='Search for zones with admin email %r with --forward-only' % zone1_rname,
+            command=('dnszone_find', [], {'idnssoarname': zone1_rname, 'forward_only' : True}),
             expected={
                 'summary': None,
                 'count': 1,
@@ -770,8 +828,8 @@ class test_dns(Declarative):
                     'dn': zone1_dn,
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -841,12 +899,12 @@ class test_dns(Declarative):
             command=('dnsrecord_find', [zone1], {}),
             expected={
                 'summary': None,
-                'count': 4,
+                'count': 3,
                 'truncated': False,
                 'result': [
                     {
                         'dn': zone1_dn,
-                        'nsrecord': (zone1_ns,),
+                        'nsrecord': nameservers,
                         'idnsname': [_dns_zone_record],
                     },
                     {
@@ -855,11 +913,6 @@ class test_dns(Declarative):
                         'idnsname': [DNSName(u'_kerberos')],
                     },
                     {
-                        'dn': zone1_ns_dn,
-                        'idnsname': [DNSName(u'ns1')],
-                        'arecord': [zone1_ip],
-                    },
-                    {
                         'dn': name1_dn,
                         'idnsname': [name1_dnsname],
                         'arecord': [arec2],
@@ -971,7 +1024,7 @@ class test_dns(Declarative):
                     'dn': zone1_dn,
                     'idnsname': [_dns_zone_record],
                     'mxrecord': [u"0 %s" % zone1_ns],
-                    'nsrecord': [zone1_ns],
+                    'nsrecord': nameservers,
                 },
             },
         ),
@@ -1066,7 +1119,7 @@ class test_dns(Declarative):
                     'dn': zone1_dn,
                     'idnsname': [_dns_zone_record],
                     'mxrecord': [u"0 %s" % zone1_ns],
-                    'nsrecord': [zone1_ns],
+                    'nsrecord': nameservers,
                     'locrecord': [u"49 11 42.400 N 16 36 29.600 E 227.64 10.00 10.00 0.10"],
                 },
             },
@@ -1182,7 +1235,7 @@ class test_dns(Declarative):
             desc='Add NS+DNAME record to %r zone record using dnsrecord_add' % (zone2),
             command=('dnsrecord_add', [zone2, u'@'],
                 {'dnamerecord': u'd.%s' % absnxname,
-                 'nsrecord': zone1_ns}),
+                 'nsrecord': zone1_ns, 'force': True}),
             expected = {
                 'value': _dns_zone_record,
                 'summary': None,
@@ -1190,7 +1243,7 @@ class test_dns(Declarative):
                     'objectclass': objectclasses.dnszone,
                     'dnamerecord': [u'd.%s' % absnxname],
                     'dn': zone2_dn,
-                    'nsrecord': [zone2_ns, zone1_ns],
+                    'nsrecord': [zone1_ns] + nameservers,
                     'idnsname': [_dns_zone_record]
                 }
             },
@@ -1351,7 +1404,7 @@ class test_dns(Declarative):
         dict(
             desc='Add NS record to %r using dnsrecord_add' % (ds),
             command=('dnsrecord_add', [zone1, ds],
-                     {'nsrecord': zone1_ns}),
+                     {'nsrecord': zone1_ns, 'force': True}),
             expected={
                 'value': ds_dnsname,
                 'summary': None,
@@ -1491,7 +1544,6 @@ class test_dns(Declarative):
             command=(
                 'dnszone_add', [], {
                     'name_from_ip': revzone1_ip,
-                    'idnssoamname': zone1_ns,
                     'idnssoarname': zone1_rname,
                 }
             ),
@@ -1502,8 +1554,8 @@ class test_dns(Declarative):
                     'dn': revzone1_dn,
                     'idnsname': [revzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone1_ns_dnsname],
-                    'nsrecord': [zone1_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -1526,7 +1578,6 @@ class test_dns(Declarative):
             command=(
                 'dnszone_add', [], {
                     'name_from_ip': revzone2_ip,
-                    'idnssoamname': zone1_ns,
                     'idnssoarname': zone1_rname,
                 }
             ),
@@ -1537,8 +1588,8 @@ class test_dns(Declarative):
                     'dn': revzone2_dn,
                     'idnsname': [revzone2_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone1_ns_dnsname],
-                    'nsrecord': [zone1_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -1623,10 +1674,10 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
+                    'nsrecord': nameservers,
                     'mxrecord': [u'0 ns1.dnszone.test.'],
                     'locrecord': [u"49 11 42.400 N 16 36 29.600 E 227.64 10.00 10.00 0.10"],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -1656,10 +1707,10 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
+                    'nsrecord': nameservers,
                     'mxrecord': [u'0 ns1.dnszone.test.'],
                     'locrecord': [u"49 11 42.400 N 16 36 29.600 E 227.64 10.00 10.00 0.10"],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -1682,10 +1733,10 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_ns],
+                    'nsrecord': nameservers,
                     'mxrecord': [u'0 ns1.dnszone.test.'],
                     'locrecord': [u"49 11 42.400 N 16 36 29.600 E 227.64 10.00 10.00 0.10"],
-                    'idnssoamname': [zone1_ns_dnsname],
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [u'4294967295'],
                     'idnssoarefresh': [u'5478'],
@@ -1833,115 +1884,28 @@ class test_dns(Declarative):
                                      % zone1_permission)
         ),
 
-
         dict(
-            desc='Delete zone %r' % zone1,
-            command=('dnszone_del', [zone1], {}),
-            expected={
-                'value': [zone1_absolute_dnsname],
-                'summary': u'Deleted DNS zone "%s"' % zone1_absolute,
-                'result': {'failed': []},
-            },
-        ),
-
-
-        dict(
-            desc='Try to create zone %r nameserver not in it' % zone1,
-            command=(
-                'dnszone_add', [zone1_absolute], {
-                    'idnssoamname': u'not.in.this.zone.',
-                    'idnssoarname': zone1_rname,
-                    'ip_address' : zone1_ip,
-                }
-            ),
-            expected=errors.ValidationError(name='ip_address',
-                error=u"Nameserver DNS record is created only for nameservers"
-                      u" in current zone"),
-        ),
-
-
-        dict(
-            desc='Create zone %r with relative nameserver' % zone1,
+            desc='Try to create zone %r with relative nameserver' % zone3,
             command=(
-                'dnszone_add', [zone1_absolute], {
+                'dnszone_add', [zone3], {
                     'idnssoamname': u'ns',
-                    'idnssoarname': zone1_rname,
-                    'ip_address' : zone1_ip,
+                    'idnssoarname': zone3_rname,
                 }
             ),
-            expected={
-                'value': zone1_absolute_dnsname,
-                'summary': None,
-                'result': {
-                    'dn': zone1_dn,
-                    'idnsname': [zone1_absolute_dnsname],
-                    'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [DNSName(u'ns')],
-                    'nsrecord': [u'ns'],
-                    'idnssoarname': [zone1_rname_dnsname],
-                    'idnssoaserial': [fuzzy_digits],
-                    'idnssoarefresh': [fuzzy_digits],
-                    'idnssoaretry': [fuzzy_digits],
-                    'idnssoaexpire': [fuzzy_digits],
-                    'idnssoaminimum': [fuzzy_digits],
-                    'idnsallowdynupdate': [u'FALSE'],
-                    'idnsupdatepolicy': [u'grant %(realm)s krb5-self * A; '
-                                         u'grant %(realm)s krb5-self * AAAA; '
-                                         u'grant %(realm)s krb5-self * SSHFP;'
-                                         % dict(realm=api.env.realm)],
-                    'idnsallowtransfer': [u'none;'],
-                    'idnsallowquery': [u'any;'],
-                    'objectclass': objectclasses.dnszone,
-                },
-            },
+            expected=errors.NotFound(reason=u"Nameserver 'ns.%s' does not have a corresponding A/AAAA record"
+                                            % zone3_absolute)
         ),
 
-
-        dict(
-            desc='Delete zone %r' % zone1,
-            command=('dnszone_del', [zone1], {}),
-            expected={
-                'value': [zone1_absolute_dnsname],
-                'summary': u'Deleted DNS zone "%s"' % zone1_absolute,
-                'result': {'failed': []},
-            },
-        ),
-
-
         dict(
-            desc='Create zone %r with nameserver in the zone itself' % zone1,
+            desc='Try to create zone %r with nameserver in the zone itself' % zone3,
             command=(
-                'dnszone_add', [zone1], {
-                    'idnssoamname': zone1_absolute,
-                    'idnssoarname': zone1_rname,
-                    'ip_address' : zone1_ip,
+                'dnszone_add', [zone3], {
+                    'idnssoamname': zone3_absolute,
+                    'idnssoarname': zone3_rname,
                 }
             ),
-            expected={
-                'value': zone1_absolute_dnsname,
-                'summary': None,
-                'result': {
-                    'dn': zone1_dn,
-                    'idnsname': [zone1_absolute_dnsname],
-                    'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone1_absolute_dnsname],
-                    'nsrecord': [zone1_absolute],
-                    'idnssoarname': [zone1_rname_dnsname],
-                    'idnssoaserial': [fuzzy_digits],
-                    'idnssoarefresh': [fuzzy_digits],
-                    'idnssoaretry': [fuzzy_digits],
-                    'idnssoaexpire': [fuzzy_digits],
-                    'idnssoaminimum': [fuzzy_digits],
-                    'idnsallowdynupdate': [u'FALSE'],
-                    'idnsupdatepolicy': [u'grant %(realm)s krb5-self * A; '
-                                         u'grant %(realm)s krb5-self * AAAA; '
-                                         u'grant %(realm)s krb5-self * SSHFP;'
-                                         % dict(realm=api.env.realm)],
-                    'idnsallowtransfer': [u'none;'],
-                    'idnsallowquery': [u'any;'],
-                    'objectclass': objectclasses.dnszone,
-                },
-            },
+            expected=errors.NotFound(reason=u"Nameserver '%s' does not have a corresponding A/AAAA record"
+                                            % zone3_absolute)
         ),
 
 
@@ -1949,9 +1913,7 @@ class test_dns(Declarative):
             desc='Create zone %r' % zone3,
             command=(
                 'dnszone_add', [zone3], {
-                    'idnssoamname': zone3_ns,
                     'idnssoarname': zone3_rname,
-                    'ip_address' : zone3_ip,
                 }
             ),
             expected={
@@ -1961,8 +1923,8 @@ class test_dns(Declarative):
                     'dn': zone3_dn,
                     'idnsname': [zone3_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone3_ns_dnsname],
-                    'nsrecord': [zone3_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone3_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -2000,7 +1962,6 @@ class test_dns(Declarative):
             desc='Create reverse zone %r' % revzone3_classless1,
             command=(
                 'dnszone_add', [revzone3_classless1], {
-                    'idnssoamname': zone3_ns,
                     'idnssoarname': zone3_rname,
                 }
             ),
@@ -2011,8 +1972,8 @@ class test_dns(Declarative):
                     'dn': revzone3_classless1_dn,
                     'idnsname': [revzone3_classless1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone3_ns_dnsname],
-                    'nsrecord': [zone3_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone3_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -2033,7 +1994,6 @@ class test_dns(Declarative):
             desc='Create classless reverse zone %r' % revzone3_classless2,
             command=(
                 'dnszone_add', [revzone3_classless2], {
-                    'idnssoamname': zone3_ns2,
                     'idnssoarname': zone3_rname,
                 }
             ),
@@ -2044,8 +2004,8 @@ class test_dns(Declarative):
                     'dn': revzone3_classless2_dn,
                     'idnsname': [revzone3_classless2_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone3_ns2_dnsname],
-                    'nsrecord': [zone3_ns2],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone3_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -2091,14 +2051,14 @@ class test_dns(Declarative):
 
         dict(
             desc='Add NS record to %r in revzone %r' % (nsrev, revzone3_classless1),
-            command=('dnsrecord_add', [revzone3_classless1, nsrev], {'nsrecord': zone3_ns2}),
+            command=('dnsrecord_add', [revzone3_classless1, nsrev], {'nsrecord': zone3_ns2_arec_absolute}),
             expected={
                 'value': nsrev_dnsname,
                 'summary': None,
                 'result': {
                     'dn': nsrev_dn,
                     'idnsname': [nsrev_dnsname],
-                    'nsrecord': [zone3_ns2],
+                    'nsrecord': [zone3_ns2_arec_absolute],
                     'objectclass': objectclasses.dnsrecord,
                     },
             },
@@ -2139,9 +2099,7 @@ class test_dns(Declarative):
             desc='Create IDN zone %r' % idnzone1,
             command=(
                 'dnszone_add', [idnzone1], {
-                    'idnssoamname': idnzone1_mname,
                     'idnssoarname': idnzone1_rname,
-                    'ip_address' : idnzone1_ip,
                 }
             ),
             expected={
@@ -2151,8 +2109,8 @@ class test_dns(Declarative):
                     'dn': idnzone1_dn,
                     'idnsname': [idnzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [idnzone1_mname_dnsname],
-                    'nsrecord': [idnzone1_mname],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [idnzone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -2183,8 +2141,8 @@ class test_dns(Declarative):
                     'dn': idnzone1_dn,
                     'idnsname': [idnzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [idnzone1_mname],
-                    'idnssoamname': [idnzone1_mname_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [idnzone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -2209,8 +2167,8 @@ class test_dns(Declarative):
                     'dn': idnzone1_dn,
                     'idnsname': [idnzone1_punycoded],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [idnzone1_mname_punycoded],
-                    'idnssoamname': [idnzone1_mname_punycoded],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns],
                     'idnssoarname': [idnzone1_rname_punycoded],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -2237,8 +2195,8 @@ class test_dns(Declarative):
                     {   'dn': idnzone1_dn,
                         'idnsname': [idnzone1_dnsname],
                         'idnszoneactive': [u'TRUE'],
-                        'nsrecord': [idnzone1_mname],
-                        'idnssoamname': [idnzone1_mname_dnsname],
+                        'nsrecord': nameservers,
+                        'idnssoamname': [self_server_ns_dnsname],
                         'idnssoarname': [idnzone1_rname_dnsname],
                         'idnssoaserial': [fuzzy_digits],
                         'idnssoarefresh': [fuzzy_digits],
@@ -2266,8 +2224,8 @@ class test_dns(Declarative):
                     {   'dn': idnzone1_dn,
                         'idnsname': [idnzone1_punycoded],
                         'idnszoneactive': [u'TRUE'],
-                        'nsrecord': [idnzone1_mname_punycoded],
-                        'idnssoamname': [idnzone1_mname_punycoded],
+                        'nsrecord': nameservers,
+                        'idnssoamname': [self_server_ns],
                         'idnssoarname': [idnzone1_rname_punycoded],
                         'idnssoaserial': [fuzzy_digits],
                         'idnssoarefresh': [fuzzy_digits],
@@ -2290,8 +2248,8 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [idnzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [idnzone1_mname],
-                    'idnssoamname': [idnzone1_mname_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [idnzone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -2308,7 +2266,6 @@ class test_dns(Declarative):
             desc='Create reverse zone %r' % revidnzone1,
             command=(
                 'dnszone_add', [revidnzone1], {
-                    'idnssoamname': idnzone1_mname,
                     'idnssoarname': idnzone1_rname,
                 }
             ),
@@ -2319,8 +2276,8 @@ class test_dns(Declarative):
                     'dn': revidnzone1_dn,
                     'idnsname': [revidnzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [idnzone1_mname_dnsname],
-                    'nsrecord': [idnzone1_mname],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [idnzone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -2358,8 +2315,8 @@ class test_dns(Declarative):
                     'dn': idnzone1_dn,
                     'idnsname': [idnzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [idnzone1_mname],
-                    'idnssoamname': [idnzone1_mname_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [idnzone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [u'5478'],
@@ -2400,20 +2357,15 @@ class test_dns(Declarative):
             command=('dnsrecord_find', [idnzone1], {}),
             expected={
                 'summary': None,
-                'count': 3,
+                'count': 2,
                 'truncated': False,
                 'result': [
                     {
                         'dn': idnzone1_dn,
-                        'nsrecord': (idnzone1_mname,),
+                        'nsrecord': nameservers,
                         'idnsname': [_dns_zone_record],
                     },
                     {
-                        'dn': idnzone1_mname_dn,
-                        'idnsname': [DNSName(u'ns1')],
-                        'arecord': [idnzone1_ip],
-                    },
-                    {
                         'dn': idnres1_dn,
                         'idnsname': [idnres1_dnsname],
                         'arecord': [u'127.0.0.1'],
@@ -2428,7 +2380,7 @@ class test_dns(Declarative):
             command=('dnsrecord_find', [idnzone1], {'pkey_only':True,}),
             expected={
                 'summary': None,
-                'count': 3,
+                'count': 2,
                 'truncated': False,
                 'result': [
                     {
@@ -2436,10 +2388,6 @@ class test_dns(Declarative):
                         'idnsname': [_dns_zone_record],
                     },
                     {
-                        'dn': idnzone1_mname_dn,
-                        'idnsname': [DNSName(u'ns1')],
-                    },
-                    {
                         'dn': idnres1_dn,
                         'idnsname': [idnres1_dnsname],
                     },
@@ -2458,7 +2406,7 @@ class test_dns(Declarative):
                 'result': [
                     {
                         'dn': idnzone1_dn,
-                        'nsrecord': (idnzone1_mname,),
+                        'nsrecord': nameservers,
                         'idnsname': [_dns_zone_record],
                     },
                 ],
@@ -2576,7 +2524,7 @@ class test_dns(Declarative):
                     'dn': idnzone1_dn,
                     'idnsname': [_dns_zone_record],
                     'mxrecord': [u"0 %s" % idnzone1_mname],
-                    'nsrecord': [idnzone1_mname],
+                    'nsrecord': nameservers,
                 },
             },
         ),
@@ -2594,7 +2542,7 @@ class test_dns(Declarative):
                     'dn': idnzone1_dn,
                     'idnsname': [_dns_zone_record],
                     'mxrecord': [u"0 %s" % idnzone1_mname, u"10 %s" % idnzone1_mname],
-                    'nsrecord': [idnzone1_mname],
+                    'nsrecord': nameservers,
                 },
             },
         ),
@@ -2609,7 +2557,7 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [_dns_zone_record],
                     'mxrecord': [u"0 %s" % idnzone1_mname],
-                    'nsrecord': [idnzone1_mname],
+                    'nsrecord': nameservers,
                 },
             },
         ),
@@ -2627,7 +2575,7 @@ class test_dns(Declarative):
                     'idnsname': [_dns_zone_record],
                     'mxrecord': [u"0 %s" % idnzone1_mname],
                     'kxrecord': [u"0 %s" % idnzone1_mname],
-                    'nsrecord': [idnzone1_mname],
+                    'nsrecord': nameservers,
                 },
             },
         ),
@@ -2643,7 +2591,7 @@ class test_dns(Declarative):
                     'idnsname': [u'@'],
                     'mxrecord': [u"0 %s" % idnzone1_mname_punycoded],
                     'kxrecord': [u"0 %s" % idnzone1_mname_punycoded],
-                    'nsrecord': [idnzone1_mname_punycoded],
+                    'nsrecord': nameservers,
                 },
             },
         ),
@@ -2783,6 +2731,14 @@ class test_dns(Declarative):
 
 
         dict(
+            desc='Add A denormalized record in zone %r' % (idnzone1),
+            command=('dnsrecord_add', [idnzone1, u'gro\xdf'], {'arecord': u'172.16.0.1'}),
+            expected=errors.ConversionError(name='name',
+                error=u'domain name \'gro\xdf\' should be normalized to: gross')
+        ),
+
+
+        dict(
             desc='Add A record to %r in zone %r' % (wildcard_rec1, zone1),
             command=('dnsrecord_add', [zone1, wildcard_rec1], {'arecord': wildcard_rec1_addr}),
             expected={
@@ -2854,14 +2810,6 @@ class test_dns(Declarative):
 
 
         dict(
-            desc='Add A denormalized record in zone %r' % (idnzone1),
-            command=('dnsrecord_add', [idnzone1, u'gro\xdf'], {'arecord': u'172.16.0.1'}),
-            expected=errors.ConversionError(name='name',
-                error=u'domain name \'gro\xdf\' should be normalized to: gross')
-        ),
-
-
-        dict(
             desc='Try to create forward zone %r with wildcard domain name' % zone_fw_wildcard,
             command=(
                 'dnsforwardzone_add', [zone_fw_wildcard], {'idnsforwardpolicy': u'none'}
@@ -3221,9 +3169,7 @@ class test_dns(Declarative):
             desc='Try to create duplicate zone which is already forward zone %r' % fwzone1,
             command=(
                 'dnszone_add', [fwzone1], {
-                    'idnssoamname': u'ns',
                     'idnssoarname': zone1_rname,
-                    'ip_address': zone1_ip,
                 }
             ),
             expected=errors.DuplicateEntry(
@@ -3366,9 +3312,7 @@ class test_dns(Declarative):
             desc='Create zone %r' % zone_findtest_master,
             command=(
                 'dnszone_add', [zone_findtest_master], {
-                    'idnssoamname': zone_findtest_master_ns,
                     'idnssoarname': zone_findtest_master_rname,
-                    'ip_address': zone1_ip,
                 }
             ),
             expected={
@@ -3378,8 +3322,8 @@ class test_dns(Declarative):
                     'dn': zone_findtest_master_dn,
                     'idnsname': [zone_findtest_master_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone_findtest_master_ns_dnsname],
-                    'nsrecord': [zone_findtest_master_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone_findtest_master_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -3449,8 +3393,8 @@ class test_dns(Declarative):
                     'dn': zone_findtest_master_dn,
                     'idnsname': [zone_findtest_master_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone_findtest_master_ns],
-                    'idnssoamname': [zone_findtest_master_ns_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone_findtest_master_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -3536,17 +3480,18 @@ class test_dns(Declarative):
                     'dn': zone1_dn,
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'FALSE'],
-                    'nsrecord': [zone1_absolute],
-                    'idnssoamname': [zone1_absolute_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
                     'idnssoaretry': [fuzzy_digits],
                     'idnssoaexpire': [fuzzy_digits],
                     'idnssoaminimum': [fuzzy_digits],
-                    'idnsallowtransfer': [u'none;'],
-                    'idnsallowquery': [u'any;'],
-                    'arecord': [arec1,],
+                    'idnsallowtransfer': [u'172.16.31.80;'],
+                    'idnsallowquery': [u'!192.0.2.0/24;any;'],
+                    'mxrecord': [u'0 ns1.dnszone.test.'],
+                    'locrecord': [u"49 11 42.400 N 16 36 29.600 E 227.64 10.00 10.00 0.10"],
                 },
             },
         ),
@@ -3573,17 +3518,18 @@ class test_dns(Declarative):
                     'dn': zone1_dn,
                     'idnsname': [zone1_absolute_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [zone1_absolute],
-                    'idnssoamname': [zone1_absolute_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [zone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
                     'idnssoaretry': [fuzzy_digits],
                     'idnssoaexpire': [fuzzy_digits],
                     'idnssoaminimum': [fuzzy_digits],
-                    'idnsallowtransfer': [u'none;'],
-                    'idnsallowquery': [u'any;'],
-                    'arecord': [arec1,],
+                    'idnsallowtransfer': [u'172.16.31.80;'],
+                    'idnsallowquery': [u'!192.0.2.0/24;any;'],
+                    'mxrecord': [u'0 ns1.dnszone.test.'],
+                    'locrecord': [u"49 11 42.400 N 16 36 29.600 E 227.64 10.00 10.00 0.10"],
                 },
             },
         ),
@@ -3609,8 +3555,8 @@ class test_dns(Declarative):
                     'dn': idnzone1_dn,
                     'idnsname': [idnzone1_dnsname],
                     'idnszoneactive': [u'FALSE'],
-                    'nsrecord': [idnzone1_mname],
-                    'idnssoamname': [idnzone1_mname_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [idnzone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -3647,8 +3593,8 @@ class test_dns(Declarative):
                     'dn': idnzone1_dn,
                     'idnsname': [idnzone1_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'nsrecord': [idnzone1_mname],
-                    'idnssoamname': [idnzone1_mname_dnsname],
+                    'nsrecord': nameservers,
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnssoarname': [idnzone1_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -3718,6 +3664,16 @@ class test_dns(Declarative):
             },
         ),
 
+        dict(
+            desc='Delete zone %r' % zone1,
+            command=('dnszone_del', [zone1], {}),
+            expected={
+                'value': [zone1_absolute_dnsname],
+                'summary': u'Deleted DNS zone "%s"' % zone1_absolute,
+                'result': {'failed': []},
+            },
+        ),
+
     ]
 
 
@@ -3742,11 +3698,16 @@ class test_root_zone(Declarative):
 
         if not api.Backend.rpcclient.isconnected():
             api.Backend.rpcclient.connect(fallback=False)
+
+        if not have_ldap2:
+            raise nose.SkipTest('server plugin not available')
+
+        if get_nameservers_error is not None:
+            raise nose.SkipTest('unable to get list of nameservers (%s)' % get_nameservers_error)
+
         try:
             api.Command['dnszone_add'](zone1,
-               idnssoamname = zone1_ns,
                idnssoarname = zone1_rname,
-               force = True,
                )
             api.Command['dnszone_del'](zone1)
         except errors.NotFound:
@@ -3767,9 +3728,7 @@ class test_root_zone(Declarative):
             desc='Create zone %r' % zone_root,
             command=(
                 'dnszone_add', [zone_root], {
-                    'idnssoamname': zone_root_ns,
                     'idnssoarname': zone_root_rname,
-                    'ip_address' : zone_root_ip,
                 }
             ),
             expected={
@@ -3779,8 +3738,8 @@ class test_root_zone(Declarative):
                     'dn': zone_root_dn,
                     'idnsname': [zone_root_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [zone_root_ns_dnsname],
-                    'nsrecord': [zone_root_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': nameservers,
                     'idnssoarname': [zone_root_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -3811,14 +3770,4 @@ class test_root_zone(Declarative):
             ),
         ),
 
-        dict(
-            desc='Delete zone %r' % zone_root,
-            command=('dnszone_del', [zone_root], {}),
-            expected={
-                'value': [zone_root_dnsname],
-                'summary': u'Deleted DNS zone "%s"' % zone_root,
-                'result': {'failed': []},
-            },
-        ),
-
     ]
diff --git a/ipatests/test_xmlrpc/test_dns_realmdomains_integration.py b/ipatests/test_xmlrpc/test_dns_realmdomains_integration.py
index 80a4e841e43ca80f840d551f94f76e56a61ab192..38f3cbe794d55abcc0dd51cf141bff3910147814 100644
--- a/ipatests/test_xmlrpc/test_dns_realmdomains_integration.py
+++ b/ipatests/test_xmlrpc/test_dns_realmdomains_integration.py
@@ -23,6 +23,7 @@ Test integration of DNS and realmdomains.
 """
 
 from ipalib import api, errors
+from ipalib.util import normalize_zone
 from ipapython.dn import DN
 from ipapython.dnsutil import DNSName
 from ipatests.test_xmlrpc import objectclasses
@@ -43,6 +44,8 @@ dnszone_2_absolute = "%s." % dnszone_2
 dnszone_2_dn = DN(('idnsname', dnszone_2_absolute), api.env.container_dns,
                   api.env.basedn)
 
+self_server_ns = normalize_zone(api.env.host)
+self_server_ns_dnsname = DNSName(self_server_ns)
 
 def assert_realmdomain_and_txt_record_present(response):
     zone = response['value']
@@ -92,9 +95,7 @@ class test_dns_realmdomains_integration(Declarative):
                  'during dnszone_add',
             command=(
                 'dnszone_add', [dnszone_1], {
-                    'idnssoamname': idnssoamname,
                     'idnssoarname': idnssoarname,
-                    'ip_address': u'1.2.3.4',
                 }
             ),
             expected={
@@ -104,8 +105,8 @@ class test_dns_realmdomains_integration(Declarative):
                     'dn': dnszone_1_dn,
                     'idnsname': [DNSName(dnszone_1_absolute)],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [DNSName(idnssoamname)],
-                    'nsrecord': [idnssoamname],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': lambda x: True,
                     'idnssoarname': [DNSName(idnssoarname)],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -131,11 +132,9 @@ class test_dns_realmdomains_integration(Declarative):
                  'during dnszone_add for forwarded zone',
             command=(
                 'dnszone_add', [dnszone_2], {
-                    'idnssoamname': idnssoamname,
                     'idnssoarname': idnssoarname,
                     'idnsforwarders': u'1.2.3.4',
                     'idnsforwardpolicy': u'only',
-                    'force': True,
                 }
             ),
             expected={
@@ -154,10 +153,10 @@ class test_dns_realmdomains_integration(Declarative):
                     'dn': dnszone_2_dn,
                     'idnsname': [DNSName(dnszone_2_absolute)],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [DNSName(idnssoamname)],
+                    'idnssoamname': [self_server_ns_dnsname],
                     'idnsforwarders': [u'1.2.3.4'],
                     'idnsforwardpolicy': [u'only'],
-                    'nsrecord': [idnssoamname],
+                    'nsrecord': lambda x: True,
                     'idnssoarname': [DNSName(idnssoarname)],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
diff --git a/ipatests/test_xmlrpc/test_host_plugin.py b/ipatests/test_xmlrpc/test_host_plugin.py
index 7c0312bae5e9e652085aac8f1970610044504281..479afd100e974d1380fc7d940782d4bd5a2f158f 100644
--- a/ipatests/test_xmlrpc/test_host_plugin.py
+++ b/ipatests/test_xmlrpc/test_host_plugin.py
@@ -26,6 +26,7 @@ import os
 import tempfile
 from ipapython import ipautil
 from ipalib import api, errors, x509
+from ipalib.util import normalize_zone
 from ipapython.dn import DN
 from ipapython.dnsutil import DNSName
 from nose.tools import raises, assert_raises
@@ -37,6 +38,8 @@ from ipatests.test_xmlrpc import objectclasses
 from ipatests.test_xmlrpc.testcert import get_testcert
 import base64
 
+self_server_ns = normalize_zone(api.env.host)
+self_server_ns_dnsname = DNSName(self_server_ns)
 
 fqdn1 = u'testhost1.%s' % api.env.domain
 short1 = u'testhost1'
@@ -1052,9 +1055,7 @@ class test_host_dns(Declarative):
             desc='Create zone %r' % dnszone,
             command=(
                 'dnszone_add', [dnszone], {
-                    'idnssoamname': dnszone_ns,
                     'idnssoarname': dnszone_rname,
-                    'ip_address' : dnszone_ip,
                 }
             ),
             expected={
@@ -1064,8 +1065,8 @@ class test_host_dns(Declarative):
                     'dn': dnszone_dn,
                     'idnsname': [dnszone_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [dnszone_ns_dnsname],
-                    'nsrecord': [dnszone_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': lambda x: True,
                     'idnssoarname': [dnszone_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -1089,7 +1090,6 @@ class test_host_dns(Declarative):
             desc='Create reverse zone %r' % revzone,
             command=(
                 'dnszone_add', [revzone], {
-                    'idnssoamname': dnszone_ns,
                     'idnssoarname': dnszone_rname,
                 }
             ),
@@ -1100,8 +1100,8 @@ class test_host_dns(Declarative):
                     'dn': revzone_dn,
                     'idnsname': [revzone_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [dnszone_ns_dnsname],
-                    'nsrecord': [dnszone_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': lambda x: True,
                     'idnssoarname': [dnszone_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
@@ -1123,7 +1123,6 @@ class test_host_dns(Declarative):
             desc='Create reverse zone %r' % revipv6zone,
             command=(
                 'dnszone_add', [revipv6zone], {
-                    'idnssoamname': dnszone_ns,
                     'idnssoarname': dnszone_rname,
                 }
             ),
@@ -1134,8 +1133,8 @@ class test_host_dns(Declarative):
                     'dn': revipv6zone_dn,
                     'idnsname': [revipv6zone_dnsname],
                     'idnszoneactive': [u'TRUE'],
-                    'idnssoamname': [dnszone_ns_dnsname],
-                    'nsrecord': [dnszone_ns],
+                    'idnssoamname': [self_server_ns_dnsname],
+                    'nsrecord': lambda x: True,
                     'idnssoarname': [dnszone_rname_dnsname],
                     'idnssoaserial': [fuzzy_digits],
                     'idnssoarefresh': [fuzzy_digits],
-- 
1.8.3.1

_______________________________________________
Freeipa-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to