On 16/09/14 10:29, Petr Spacek wrote:
On 16.9.2014 10:09, Martin Kosek wrote:
On 09/16/2014 09:57 AM, Martin Basti wrote:
On 16/09/14 09:32, Martin Basti wrote:
On 15/09/14 20:31, Martin Kosek wrote:
On 09/15/2014 05:16 PM, Martin Basti wrote:
On 15/09/14 17:10, Petr Spacek wrote:
On 12.9.2014 15:19, Martin Basti wrote:
On 03/09/14 12:45, Martin Basti wrote:
On 03/09/14 12:27, Martin Kosek wrote:
On 09/02/2014 05:46 PM, Petr Spacek wrote:
On 25.8.2014 14:52, Martin Basti wrote:
Patches attached.

Ticket: https://fedorahosted.org/freeipa/ticket/4149

There is a bug in bind-dyndb-ldap (or worse in dirsrv), which cause the
named
service is stopped after deleting zone.
Bug ticket: https://fedorahosted.org/bind-dyndb-ldap/ticket/138
Functional ACK, it works for me. It can be pushed if Python gurus are
okay
with
the code.
Is it safe to commit the change given that bind-dyndb-ldap still crash
when
"."
is removed? Wouldn't it break our CI tests?

Maybe we should wait until fixed bind-dydnb-ldap is released. Hopefully it
would be soon.

Martin

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel
It will broke tests, don't push it until bind-dyndb-ldap is fixed.
Currently I'm testing bind-dyndb-ldap related patch.

Added patches 120 and 121, which are required by DNS to work correctly. Patches 120 and 121 add all DNS replicas to zone apex as NS, --name-server
option doesn't add NS record, only changes the SOA MNAME attribute

Original and new patches attached.

NACK, unfortunately it doesn't work for me:
# ipa dnszone-add tri.test. --name-server=ns.test.
Administrator e-mail address [hostmaster.tri.test.]:
ipa: WARNING: '--name-server' is used only for setting up the SOA MNAME
record.
To edit NS record(s) in zone apex, use command 'dnsrecord-mod [zone] @
--ns-rec=nameserver'.
   Zone name: tri.test.
   Active zone: TRUE
   Authoritative nameserver: ns.test.
   Administrator e-mail address: hostmaster.tri.test.
   SOA serial: 1410793406
   SOA refresh: 3600
   SOA retry: 900
   SOA expire: 1209600
   SOA minimum: 3600
BIND update policy: grant IPA.EXAMPLE krb5-self * A; grant IPA.EXAMPLE
krb5-self * AAAA; grant IPA.EXAMPLE krb5-self * SSHFP;
   Dynamic update: FALSE
   Allow query: any;
   Allow transfer: none;

[root@vm-035 rpms]# ipa dnszone-show tri.test. --all --raw
   dn: idnsname=tri.test.,cn=dns,dc=ipa,dc=example
   idnsname: tri.test.
   idnszoneactive: TRUE
   idnssoamname: ns.test.
   idnssoarname: hostmaster.tri.test.
   idnssoaserial: 1410793408
   idnssoarefresh: 3600
   idnssoaretry: 900
   idnssoaexpire: 1209600
   idnssoaminimum: 3600
   idnsallowquery: any;
   idnsallowtransfer: none;
   idnsAllowDynUpdate: FALSE
idnsUpdatePolicy: grant IPA.EXAMPLE krb5-self * A; grant IPA.EXAMPLE
krb5-self * AAAA; grant IPA.EXAMPLE krb5-self * SSHFP;
   nsrecord: vm-035.idm.lab.eng.brq.redhat.com.
   objectClass: idnszone
   objectClass: top
   objectClass: idnsrecord

[root@vm-035 rpms]# ipa dnsrecord-mod @ tri.test. --ns-rec=$(hostname).
ipa: ERROR: tri.test.: DNS resource record not found

NACKing NACK
ipa dnsrecord-mod @ tri.test. --ns-rec=$(hostname).
you switched order zone and record, it should be
ipa dnsrecord-mod tri.test. @ --ns-rec=$(hostname).


BTW, since we are so nicely breaking the dnszone-add interface, can we also
get rid of always asking for "Administrator e-mail address"?

# ipa dnszone-add tri.test. --name-server=ns.test.
Administrator e-mail address [hostmaster.tri.test.]:
...

Is there any risk in filling that with default as any other attribute? IMO it would simplify adding zones for one more redundant step. CCing Rob in case he knows some historical reasons why this is requested every time.

Martin
There is no risk, because ipa-replica-prepare do that with default values

Then let us do this, as we are already simplifying the dnszone-add command.

However, this will not work with root zone ".", and I'm not sure how often an admin email is used. I think whois is better utility to get contact email.

Also RIPE-203 [1] recommends to use 'hostmaster' alias.

[1] http://www.ripe.net/ripe/docs/ripe-203

This will likely generate tons of invalid e-mail addresses which is somehow unfortunate.

Please keep in mind that:
1) E-mail hostmaster@ipa.domain.example. will be useful only if ipa.domain.example. has MX record or at least A/AAAA record (which is usually not the case for domains).

2) WHOIS is not useful for internal domains which is the main deployment scenario for IPA, right?

DNS zone "." is quite an exception, you are not adding that zone every day. So
I would not keep asking for admin mail just for this one. You can add a
interactive prompt callback to ask in this case and otherwise just use the
default - up to you.

As for the mail alias, this can be an RFE.

It would be nice to have some IPA-global default like 'DNS administrator e-mail address' and to use this value for all DNS zones by default.


Updated patches attached.
Design page: http://www.freeipa.org/page/V4/DNS:_Automatic_Zone_NS/SOA_Record_Maintenance

--
Martin Basti

From a750dec1ebdbf3455c9dd22dee24fe669e425153 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
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 c0b884e14ec7777d672535267f34f004def75a02 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
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 84d07b2cb62baa2d54092a2a4ca1ea94cf559cc1 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
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    |  22 ++++++++++
 ipalib/plugins/dns.py | 119 ++++++++++++++++++++------------------------------
 4 files changed, 72 insertions(+), 75 deletions(-)

diff --git a/API.txt b/API.txt
index 4fa27559269e05088d2e8858d0e0f3b723315fc7..02848a35f12e4fb1fbd7b2f4234326e43ecce07c 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..aac13a6997474424bd5859b179102069737b5aa2 100644
--- a/ipalib/messages.py
+++ b/ipalib/messages.py
@@ -157,6 +157,28 @@ 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 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'.")
+
+
 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..e3df474cbab574aa4a8120774ac3db9a4231bb59 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,10 @@ 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.OptionNameServerWarning())
 
 @register()
 class dnszone_add(DNSZoneBase_add):
@@ -2327,39 +2332,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 +2356,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 +2456,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 +2467,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 73bba724eae248caa18726878f120896e06a042d Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
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 c72f31685ab37dd11ccc4921ee2473c8508a1154 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
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               |  2 +-
 VERSION               |  4 ++--
 ipalib/plugins/dns.py |  9 ++++-----
 ipalib/util.py        | 11 +----------
 4 files changed, 8 insertions(+), 18 deletions(-)

diff --git a/API.txt b/API.txt
index 02848a35f12e4fb1fbd7b2f4234326e43ecce07c..460e65674f77d75cc7a558c875ed5cbac4c693ee 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', multivalue=False, only_absolute=True, 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?')
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 e3df474cbab574aa4a8120774ac3db9a4231bb59..03ff77cbb0a40f5c7345f533280b33302e0aefd2 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 27c60b266f3fcf99ca52314767287d1378ce1ed4 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
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 0e7b9f12120598b964a68ac952d57a5b2a2e81e5 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
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            | 466 +++++++++------------
 .../test_dns_realmdomains_integration.py           |  15 +-
 ipatests/test_xmlrpc/test_host_plugin.py           |  19 +-
 4 files changed, 227 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. '
-                '--admin-email=ad...@example.com',
-                'dnszone_add',
-                idnsname=u'example.com',
-                idnssoamname=u'ns.example.com.',
-                idnssoarname=u'ad...@example.com',
-                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 '
-                '--admin-email=ad...@example.com',
-                'dnszone_add',
-                idnsname=u'example.com',
-                idnssoamname=u'ns',
-                idnssoarname=u'ad...@example.com',
-                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. '
-            '--admin-email=ad...@example.com',
-            'dnszone_add',
-            idnsname=u'example.com',
-            idnssoamname=u'ns.example.net.',
-            idnssoarname=u'ad...@example.com',
-            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..042679f26113d8b5db197313e46482adc6f1ad53 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,22 @@ class test_dns(Declarative):
                     'idnsallowquery': [u'any;'],
                     'objectclass': objectclasses.dnszone,
                 },
+                'messages': (
+                    {'message': 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'.",
+                     'code': 13005,
+                     'type': u'warning',
+                     'name': u'OptionNameServerWarning'},
+                )
             },
         ),
 
 
         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 +519,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 +541,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 +554,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 +585,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 +609,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 +689,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 +714,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 +746,6 @@ class test_dns(Declarative):
             desc='Create reverse zone %r' % revzone1,
             command=(
                 'dnszone_add', [revzone1], {
-                    'idnssoamname': zone1_ns,
                     'idnssoarname': zone1_rname,
                 }
             ),
@@ -699,8 +756,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 +776,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 +786,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 +801,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 +817,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 +827,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 +898,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 +912,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 +1023,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 +1118,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 +1234,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 +1242,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 +1403,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 +1543,6 @@ class test_dns(Declarative):
             command=(
                 'dnszone_add', [], {
                     'name_from_ip': revzone1_ip,
-                    'idnssoamname': zone1_ns,
                     'idnssoarname': zone1_rname,
                 }
             ),
@@ -1502,8 +1553,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 +1577,6 @@ class test_dns(Declarative):
             command=(
                 'dnszone_add', [], {
                     'name_from_ip': revzone2_ip,
-                    'idnssoamname': zone1_ns,
                     'idnssoarname': zone1_rname,
                 }
             ),
@@ -1537,8 +1587,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 +1673,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 +1706,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 +1732,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 +1883,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 +1912,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 +1922,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 +1961,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 +1971,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 +1993,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 +2003,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 +2050,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 +2098,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 +2108,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 +2140,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 +2166,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 +2194,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 +2223,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 +2247,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 +2265,6 @@ class test_dns(Declarative):
             desc='Create reverse zone %r' % revidnzone1,
             command=(
                 'dnszone_add', [revidnzone1], {
-                    'idnssoamname': idnzone1_mname,
                     'idnssoarname': idnzone1_rname,
                 }
             ),
@@ -2319,8 +2275,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 +2314,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 +2356,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 +2379,7 @@ class test_dns(Declarative):
             command=('dnsrecord_find', [idnzone1], {'pkey_only':True,}),
             expected={
                 'summary': None,
-                'count': 3,
+                'count': 2,
                 'truncated': False,
                 'result': [
                     {
@@ -2436,10 +2387,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 +2405,7 @@ class test_dns(Declarative):
                 'result': [
                     {
                         'dn': idnzone1_dn,
-                        'nsrecord': (idnzone1_mname,),
+                        'nsrecord': nameservers,
                         'idnsname': [_dns_zone_record],
                     },
                 ],
@@ -2576,7 +2523,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 +2541,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 +2556,7 @@ class test_dns(Declarative):
                 'result': {
                     'idnsname': [_dns_zone_record],
                     'mxrecord': [u"0 %s" % idnzone1_mname],
-                    'nsrecord': [idnzone1_mname],
+                    'nsrecord': nameservers,
                 },
             },
         ),
@@ -2627,7 +2574,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 +2590,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 +2730,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 +2809,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 +3168,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 +3311,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 +3321,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 +3392,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 +3479,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 +3517,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 +3554,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 +3592,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 +3663,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 +3697,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 +3727,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 +3737,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 +3769,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 a98fed1b64853e548d489f1bc12d012d18f986a7..c89fac9bf6caeb0305ec7a90233f81e045123212 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'
@@ -1055,9 +1058,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={
@@ -1067,8 +1068,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],
@@ -1092,7 +1093,6 @@ class test_host_dns(Declarative):
             desc='Create reverse zone %r' % revzone,
             command=(
                 'dnszone_add', [revzone], {
-                    'idnssoamname': dnszone_ns,
                     'idnssoarname': dnszone_rname,
                 }
             ),
@@ -1103,8 +1103,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],
@@ -1126,7 +1126,6 @@ class test_host_dns(Declarative):
             desc='Create reverse zone %r' % revipv6zone,
             command=(
                 'dnszone_add', [revipv6zone], {
-                    'idnssoamname': dnszone_ns,
                     'idnssoarname': dnszone_rname,
                 }
             ),
@@ -1137,8 +1136,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
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to