On Wed, 2014-06-11 at 17:41 +0200, Martin Basti wrote:
> On Mon, 2014-06-02 at 13:57 +0200, Martin Basti wrote:
> > Rebased patches attached
> > 
> > _______________________________________________
> > Freeipa-devel mailing list
> > Freeipa-devel@redhat.com
> > https://www.redhat.com/mailman/listinfo/freeipa-devel
> 
> Rebased patches attached
> _______________________________________________
> Freeipa-devel mailing list
> Freeipa-devel@redhat.com
> https://www.redhat.com/mailman/listinfo/freeipa-devel

Fixed patch attached
Error caused by rebase
-- 
Martin^2 Basti
>From adaed5394aeee6d21e022fadc27681e82a48d8e0 Mon Sep 17 00:00:00 2001
From: Martin Basti <mba...@redhat.com>
Date: Fri, 23 May 2014 17:57:20 +0200
Subject: [PATCH] Create BASE zone class

Zones and forward zones have a lot of common code,
this patch remove duplications by creating a DNSBase
class and its subclasses

design: http://www.freeipa.org/page/V4/Forward_zones

Ticket: https://fedorahosted.org/freeipa/ticket/3210
---
 ipalib/plugins/dns.py | 832 ++++++++++++++++++++------------------------------
 1 file changed, 339 insertions(+), 493 deletions(-)

diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index 62a5dcffee8b2e820def4cf215d44d0bbf623b74..94f5337ebaa543b277af9bea262fc0fbddadbffe 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -1692,39 +1692,320 @@ def _records_idn_postprocess(record, **options):
         record[attr] = rrs
 
 
+class DNSZoneBase(LDAPObject):
+    """
+    Base class for DNS Zone
+    """
+    container_dn = api.env.container_dns
+    object_class = ['top']
+    possible_objectclasses = ['ipadnszone']
+    default_attributes = [
+        'idnsname', 'idnszoneactive', 'idnsforwarders', 'idnsforwardpolicy'
+    ]
+
+    takes_params = (
+        DNSNameParam('idnsname',
+            only_absolute=True,
+            cli_name='name',
+            label=_('Zone name'),
+            doc=_('Zone name (FQDN)'),
+            default_from=lambda name_from_ip: _reverse_zone_name(name_from_ip),
+            primary_key=True,
+        ),
+        Str('name_from_ip?', _validate_ipnet,
+            label=_('Reverse zone IP network'),
+            doc=_('IP network to create reverse zone name from'),
+            flags=('virtual_attribute',),
+        ),
+        Bool('idnszoneactive?',
+            cli_name='zone_active',
+            label=_('Active zone'),
+            doc=_('Is zone active?'),
+            flags=['no_create', 'no_update'],
+            attribute=True,
+        ),
+        Str('idnsforwarders*',
+            _validate_bind_forwarder,
+            cli_name='forwarder',
+            label=_('Zone forwarders'),
+            doc=_('Per-zone forwarders. A custom port can be specified '
+                  'for each forwarder using a standard format "IP_ADDRESS port PORT"'),
+            csv=True,
+        ),
+        StrEnum('idnsforwardpolicy?',
+            cli_name='forward_policy',
+            label=_('Forward policy'),
+            doc=_('Per-zone conditional forwarding policy. Set to "none" to '
+                  'disable forwarding to global forwarder for this zone. In '
+                  'that case, conditional zone forwarders are disregarded.'),
+            values=(u'only', u'first', u'none'),
+        ),
+
+    )
+
+    def get_dn(self, *keys, **options):
+        zone = keys[-1]
+        assert isinstance(zone, DNSName)
+        assert zone.is_absolute()
+        zone = zone.ToASCII()
+
+        #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)
+        try:
+            self.backend.get_entry(dn, [''])
+        except errors.NotFound:
+            zone = u"%s." % zone
+            dn = super(DNSZoneBase, self).get_dn(zone, **options)
+
+        return dn
+
+    def permission_name(self, zone):
+        assert isinstance(zone, DNSName)
+        return u"Manage DNS zone %s" % zone.ToASCII()
+
+    def get_name_in_zone(self, zone, hostname):
+        """
+        Get name of a record that is to be added to a new zone. I.e. when
+        we want to add record "ipa.lab.example.com" in a zone "example.com",
+        this function should return "ipa.lab". Returns None when record cannot
+        be added to a zone. Returns '@' when the hostname is the zone record.
+        """
+        assert isinstance(zone, DNSName)
+        assert zone.is_absolute()
+        assert isinstance(hostname, DNSName)
+
+        if not hostname.is_absolute():
+            return hostname
+
+        if hostname.is_subdomain(zone):
+            return hostname.relativize(zone)
+
+        return None
+
+
+class DNSZoneBase_add(LDAPCreate):
+
+    has_output_params = LDAPCreate.has_output_params + dnszone_output_params
+
+    def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
+        assert isinstance(dn, DN)
+        if not dns_container_exists(self.api.Backend.ldap2):
+            raise errors.NotFound(reason=_('DNS is not configured'))
+
+        try:
+            entry = ldap.get_entry(dn)
+        except errors.NotFound:
+            pass
+        else:
+            if _check_entry_objectclass(entry, self.obj.object_class):
+                self.obj.handle_duplicate_entry(*keys)
+            else:
+                raise errors.DuplicateEntry(
+                    message=_(u'Only one zone type is allowed per zone name')
+                    )
+
+        entry_attrs['idnszoneactive'] = 'TRUE'
+
+        return dn
+
+
+class DNSZoneBase_del(LDAPDelete):
+
+    def pre_callback(self, ldap, dn, *nkeys, **options):
+        assert isinstance(dn, DN)
+        if not _check_DN_objectclass(ldap, dn, self.obj.object_class):
+            self.obj.handle_not_found(*nkeys)
+        return dn
+
+    def post_callback(self, ldap, dn, *keys, **options):
+        try:
+            api.Command['permission_del'](self.obj.permission_name(keys[-1]),
+                    force=True)
+        except errors.NotFound:
+            pass
+
+        return True
+
+class DNSZoneBase_mod(LDAPUpdate):
+    has_output_params = LDAPUpdate.has_output_params + dnszone_output_params
+
+
+
+class DNSZoneBase_find(LDAPSearch):
+    __doc__ = _('Search for DNS zones (SOA records).')
+
+    has_output_params = LDAPSearch.has_output_params + dnszone_output_params
+
+    def args_options_2_params(self, *args, **options):
+        # FIXME: Check that name_from_ip is valid. This is necessary because
+        #        custom validation rules, including _validate_ipnet, are not
+        #        used when doing a search. Once we have a parameter type for
+        #        IP network objects, this will no longer be necessary, as the
+        #        parameter type will handle the validation itself (see
+        #        <https://fedorahosted.org/freeipa/ticket/2266>).
+        if 'name_from_ip' in options:
+            self.obj.params['name_from_ip'](unicode(options['name_from_ip']))
+        return super(DNSZoneBase_find, self).args_options_2_params(*args, **options)
+
+    def args_options_2_entry(self, *args, **options):
+        if 'name_from_ip' in options:
+            if 'idnsname' not in options:
+                options['idnsname'] = self.obj.params['idnsname'].get_default(**options)
+            del options['name_from_ip']
+        search_kw = super(DNSZoneBase_find, self).args_options_2_entry(*args,
+                                                                   **options)
+        name = search_kw.get('idnsname')
+        if name:
+            search_kw['idnsname'] = [name, name.relativize(DNSName.root)]
+        return search_kw
+
+    def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
+        assert isinstance(base_dn, DN)
+        filter = _create_idn_filter(self, ldap, *args, **options)
+        return (filter, base_dn, scope)
+
+
+class DNSZoneBase_show(LDAPRetrieve):
+    has_output_params = LDAPRetrieve.has_output_params + dnszone_output_params
+
+    def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
+        assert isinstance(dn, DN)
+        if not _check_DN_objectclass(ldap, dn, self.obj.object_class):
+            self.obj.handle_not_found(*keys)
+        return dn
+
+
+class DNSZoneBase_disable(LDAPQuery):
+    has_output = output.standard_value
+
+    def execute(self, *keys, **options):
+        ldap = self.obj.backend
+
+        dn = self.obj.get_dn(*keys, **options)
+        entry = ldap.get_entry(dn, ['idnszoneactive', 'objectclass'])
+        if not _check_entry_objectclass(entry, self.obj.object_class):
+            self.obj.handle_not_found(*keys)
+
+        entry['idnszoneactive'] = ['FALSE']
+
+        try:
+            ldap.update_entry(entry)
+        except errors.EmptyModlist:
+            pass
+
+        return dict(result=True, value=pkey_to_value(keys[-1], options))
+
+
+class DNSZoneBase_enable(LDAPQuery):
+    has_output = output.standard_value
+
+    def execute(self, *keys, **options):
+        ldap = self.obj.backend
+
+        dn = self.obj.get_dn(*keys, **options)
+        entry = ldap.get_entry(dn, ['idnszoneactive', 'objectclass'])
+        if not _check_entry_objectclass(entry, self.obj.object_class):
+            self.obj.handle_not_found(*keys)
+
+        entry['idnszoneactive'] = ['TRUE']
+
+        try:
+            ldap.update_entry(entry)
+        except errors.EmptyModlist:
+            pass
+
+        return dict(result=True, value=pkey_to_value(keys[-1], options))
+
+
+class DNSZoneBase_add_permission(LDAPQuery):
+    has_output = _output_permissions
+    msg_summary = _('Added system permission "%(value)s"')
+
+    def execute(self, *keys, **options):
+        ldap = self.obj.backend
+        dn = self.obj.get_dn(*keys, **options)
+
+        try:
+            entry_attrs = ldap.get_entry(dn, ['objectclass'])
+        except errors.NotFound:
+            self.obj.handle_not_found(*keys)
+        else:
+            if not _check_entry_objectclass(entry_attrs, self.obj.object_class):
+                self.obj.handle_not_found(*keys)
+
+        permission_name = self.obj.permission_name(keys[-1])
+        permission = api.Command['permission_add_noaci'](permission_name,
+                         ipapermissiontype=u'SYSTEM'
+                     )['result']
+
+        dnszone_ocs = entry_attrs.get('objectclass')
+        if dnszone_ocs:
+            for oc in dnszone_ocs:
+                if oc.lower() == 'ipadnszone':
+                    break
+            else:
+                dnszone_ocs.append('ipadnszone')
+
+        entry_attrs['managedby'] = [permission['dn']]
+        ldap.update_entry(entry_attrs)
+
+        return dict(
+            result=True,
+            value=pkey_to_value(permission_name, options),
+        )
+
+
+class DNSZoneBase_remove_permission(LDAPQuery):
+    has_output = _output_permissions
+    msg_summary = _('Removed system permission "%(value)s"')
+
+    def execute(self, *keys, **options):
+        ldap = self.obj.backend
+        dn = self.obj.get_dn(*keys, **options)
+        try:
+            entry = ldap.get_entry(dn, ['managedby', 'objectclass'])
+        except errors.NotFound:
+            self.obj.handle_not_found(*keys)
+        else:
+            if not _check_entry_objectclass(entry, self.obj.object_class):
+                self.obj.handle_not_found(*keys)
+
+        entry['managedby'] = None
+
+        try:
+            ldap.update_entry(entry)
+        except errors.EmptyModlist:
+            # managedBy attribute is clean, lets make sure there is also no
+            # dangling DNS zone permission
+            pass
+
+        permission_name = self.obj.permission_name(keys[-1])
+        api.Command['permission_del'](permission_name, force=True)
+
+        return dict(
+            result=True,
+            value=pkey_to_value(permission_name, options),
+        )
+
 @register()
-class dnszone(LDAPObject):
+class dnszone(DNSZoneBase):
     """
     DNS Zone, container for resource records.
     """
-    container_dn = api.env.container_dns
     object_name = _('DNS zone')
     object_name_plural = _('DNS zones')
-    object_class = ['top', 'idnsrecord', 'idnszone']
-    possible_objectclasses = ['ipadnszone']
-    default_attributes = [
-        'idnsname', 'idnszoneactive', 'idnssoamname', 'idnssoarname',
-        'idnssoaserial', 'idnssoarefresh', 'idnssoaretry', 'idnssoaexpire',
-        'idnssoaminimum', 'idnsallowquery', 'idnsallowtransfer',
-        'idnsforwarders', 'idnsforwardpolicy', 'idnssecinlinesigning',
+    object_class = DNSZoneBase.object_class + ['idnsrecord', 'idnszone']
+    default_attributes = DNSZoneBase.default_attributes +[
+        'idnssoamname', 'idnssoarname','idnssoaserial', 'idnssoarefresh',
+        'idnssoaretry', 'idnssoaexpire','idnssoaminimum', 'idnsallowquery',
+        'idnsallowtransfer', 'idnssecinlinesigning',
     ] + _record_attributes
     label = _('DNS Zones')
     label_singular = _('DNS Zone')
 
-    takes_params = (
-        DNSNameParam('idnsname',
-            only_absolute=True,
-            cli_name='name',
-            label=_('Zone name'),
-            doc=_('Zone name (FQDN)'),
-            default_from=lambda name_from_ip: _reverse_zone_name(name_from_ip),
-            primary_key=True,
-        ),
-        Str('name_from_ip?', _validate_ipnet,
-            label=_('Reverse zone IP network'),
-            doc=_('IP network to create reverse zone name from'),
-            flags=('virtual_attribute',),
-        ),
+    takes_params = DNSZoneBase.takes_params + (
         DNSNameParam('idnssoamname',
             cli_name='name_server',
             label=_('Authoritative nameserver'),
@@ -1805,13 +2086,6 @@ class dnszone(LDAPObject):
             default_from=lambda idnsname: default_zone_update_policy(idnsname),
             autofill=True
         ),
-        Bool('idnszoneactive?',
-            cli_name='zone_active',
-            label=_('Active zone'),
-            doc=_('Is zone active?'),
-            flags=['no_create', 'no_update'],
-            attribute=True,
-        ),
         Bool('idnsallowdynupdate?',
             cli_name='dynamic_update',
             label=_('Dynamic update'),
@@ -1838,22 +2112,6 @@ class dnszone(LDAPObject):
             default=u'none;',  # no one can issue queries by default
             autofill=True,
         ),
-        Str('idnsforwarders*',
-            _validate_bind_forwarder,
-            cli_name='forwarder',
-            label=_('Zone forwarders'),
-            doc=_('Per-zone forwarders. A custom port can be specified '
-                  'for each forwarder using a standard format "IP_ADDRESS port PORT"'),
-            csv=True,
-        ),
-        StrEnum('idnsforwardpolicy?',
-            cli_name='forward_policy',
-            label=_('Forward policy'),
-            doc=_('Per-zone conditional forwarding policy. Set to "none" to '
-                  'disable forwarding to global forwarder for this zone. In '
-                  'that case, conditional zone forwarders are disregarded.'),
-            values=(u'only', u'first', u'none'),
-        ),
         Bool('idnsallowsyncptr?',
             cli_name='allow_sync_ptr',
             label=_('Allow PTR sync'),
@@ -1867,47 +2125,6 @@ class dnszone(LDAPObject):
         ),
     )
 
-    def get_dn(self, *keys, **options):
-        zone = keys[-1]
-        assert isinstance(zone, DNSName)
-        assert zone.is_absolute()
-        zone = zone.ToASCII()
-
-        #try first relative name, a new zone has to be added as absolute
-        #otherwise ObjectViolation is raised
-        zone = zone[:-1]
-        dn = super(dnszone, self).get_dn(zone, **options)
-        try:
-            self.backend.get_entry(dn, [''])
-        except errors.NotFound:
-            zone = u"%s." % zone
-            dn = super(dnszone, self).get_dn(zone, **options)
-
-        return dn
-
-    def permission_name(self, zone):
-        assert isinstance(zone, DNSName)
-        return u"Manage DNS zone %s" % zone.ToASCII()
-
-    def get_name_in_zone(self, zone, hostname):
-        """
-        Get name of a record that is to be added to a new zone. I.e. when
-        we want to add record "ipa.lab.example.com" in a zone "example.com",
-        this function should return "ipa.lab". Returns None when record cannot
-        be added to a zone. Returns '@' when the hostname is the zone record.
-        """
-        assert isinstance(zone, DNSName)
-        assert zone.is_absolute()
-        assert isinstance(hostname, DNSName)
-
-        if not hostname.is_absolute():
-            return hostname
-
-        if hostname.is_subdomain(zone):
-            return hostname.relativize(zone)
-
-        return None
-
     def _rr_zone_postprocess(self, record, **options):
         #Decode IDN ACE form to Unicode, raw records are passed directly from LDAP
         if options.get('raw', False):
@@ -1917,11 +2134,10 @@ class dnszone(LDAPObject):
 
 
 @register()
-class dnszone_add(LDAPCreate):
+class dnszone_add(DNSZoneBase_add):
     __doc__ = _('Create new DNS zone (SOA record).')
 
-    has_output_params = LDAPCreate.has_output_params + dnszone_output_params
-    takes_options = LDAPCreate.takes_options + (
+    takes_options = DNSZoneBase_add.takes_options + (
         Flag('force',
              label=_('Force'),
              doc=_('Force DNS zone creation even if nameserver is not resolvable.'),
@@ -1962,22 +2178,9 @@ class dnszone_add(LDAPCreate):
 
     def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
         assert isinstance(dn, DN)
-        if not dns_container_exists(self.api.Backend.ldap2):
-            raise errors.NotFound(reason=_('DNS is not configured'))
 
-        try:
-            entry = ldap.get_entry(dn)
-        except errors.NotFound:
-            pass
-        else:
-            if _check_entry_objectclass(entry, self.obj.object_class):
-                self.obj.handle_duplicate_entry(*keys)
-            else:
-                raise errors.DuplicateEntry(
-                    message=_(u'Only one zone type is allowed per zone name')
-                    )
-
-        entry_attrs['idnszoneactive'] = 'TRUE'
+        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']
@@ -2048,23 +2251,13 @@ class dnszone_add(LDAPCreate):
 
 
 @register()
-class dnszone_del(LDAPDelete):
+class dnszone_del(DNSZoneBase_del):
     __doc__ = _('Delete DNS zone (SOA record).')
 
     msg_summary = _('Deleted DNS zone "%(value)s"')
 
-    def pre_callback(self, ldap, dn, *nkeys, **options):
-        assert isinstance(dn, DN)
-        if not _check_DN_objectclass(ldap, dn, self.obj.object_class):
-            self.obj.handle_not_found(*nkeys)
-        return dn
-
     def post_callback(self, ldap, dn, *keys, **options):
-        try:
-            api.Command['permission_del'](self.obj.permission_name(keys[-1]),
-                    force=True)
-        except errors.NotFound:
-            pass
+        super(dnszone_del, self).post_callback(ldap, dn, *keys, **options)
 
         # Delete entry from realmdomains
         # except for our own domain
@@ -2083,18 +2276,16 @@ class dnszone_del(LDAPDelete):
 
 
 @register()
-class dnszone_mod(LDAPUpdate):
+class dnszone_mod(DNSZoneBase_mod):
     __doc__ = _('Modify DNS zone (SOA record).')
 
-    takes_options = LDAPUpdate.takes_options + (
+    takes_options = DNSZoneBase_mod.takes_options + (
         Flag('force',
              label=_('Force'),
              doc=_('Force nameserver change even if nameserver not in DNS'),
         ),
     )
 
-    has_output_params = LDAPUpdate.has_output_params + dnszone_output_params
-
     def pre_callback(self, ldap, dn, entry_attrs, attrs_list,  *keys, **options):
         if not _check_DN_objectclass(ldap, dn, self.obj.object_class):
             self.obj.handle_not_found(*keys)
@@ -2112,35 +2303,10 @@ class dnszone_mod(LDAPUpdate):
 
 
 @register()
-class dnszone_find(LDAPSearch):
+class dnszone_find(DNSZoneBase_find):
     __doc__ = _('Search for DNS zones (SOA records).')
 
-    has_output_params = LDAPSearch.has_output_params + dnszone_output_params
-
-    def args_options_2_params(self, *args, **options):
-        # FIXME: Check that name_from_ip is valid. This is necessary because
-        #        custom validation rules, including _validate_ipnet, are not
-        #        used when doing a search. Once we have a parameter type for
-        #        IP network objects, this will no longer be necessary, as the
-        #        parameter type will handle the validation itself (see
-        #        <https://fedorahosted.org/freeipa/ticket/2266>).
-        if 'name_from_ip' in options:
-            self.obj.params['name_from_ip'](unicode(options['name_from_ip']))
-        return super(dnszone_find, self).args_options_2_params(*args, **options)
-
-    def args_options_2_entry(self, *args, **options):
-        if 'name_from_ip' in options:
-            if 'idnsname' not in options:
-                options['idnsname'] = self.obj.params['idnsname'].get_default(**options)
-            del options['name_from_ip']
-        search_kw = super(dnszone_find, self).args_options_2_entry(*args,
-                                                                   **options)
-        name = search_kw.get('idnsname')
-        if name:
-            search_kw['idnsname'] = [name, name.relativize(DNSName.root)]
-        return search_kw
-
-    takes_options = LDAPSearch.takes_options + (
+    takes_options = DNSZoneBase_find.takes_options + (
         Flag('forward_only',
             label=_('Forward zones only'),
             cli_name='forward_only',
@@ -2151,7 +2317,8 @@ class dnszone_find(LDAPSearch):
     def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
         assert isinstance(base_dn, DN)
 
-        filter = _create_idn_filter(self, ldap, *args, **options)
+        filter, base, dn = super(dnszone_find, self).pre_callback(ldap, filter,
+            attrs_list, base_dn, scope, *args, **options)
 
         if options.get('forward_only', False):
             search_kw = {}
@@ -2174,17 +2341,9 @@ class dnszone_find(LDAPSearch):
 
 
 @register()
-class dnszone_show(LDAPRetrieve):
+class dnszone_show(DNSZoneBase_show):
     __doc__ = _('Display information about a DNS zone (SOA record).')
 
-    has_output_params = LDAPRetrieve.has_output_params + dnszone_output_params
-
-    def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
-        assert isinstance(dn, DN)
-        if not _check_DN_objectclass(ldap, dn, self.obj.object_class):
-            self.obj.handle_not_found(*keys)
-        return dn
-
     def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
         assert isinstance(dn, DN)
         self.obj._rr_zone_postprocess(entry_attrs, **options)
@@ -2193,10 +2352,8 @@ class dnszone_show(LDAPRetrieve):
 
 
 @register()
-class dnszone_disable(LDAPQuery):
+class dnszone_disable(DNSZoneBase_disable):
     __doc__ = _('Disable DNS Zone.')
-
-    has_output = output.standard_value
     msg_summary = _('Disabled DNS zone "%(value)s"')
 
     def execute(self, *keys, **options):
@@ -2219,10 +2376,8 @@ class dnszone_disable(LDAPQuery):
 
 
 @register()
-class dnszone_enable(LDAPQuery):
+class dnszone_enable(DNSZoneBase_enable):
     __doc__ = _('Enable DNS Zone.')
-
-    has_output = output.standard_value
     msg_summary = _('Enabled DNS zone "%(value)s"')
 
     def execute(self, *keys, **options):
@@ -2243,82 +2398,16 @@ class dnszone_enable(LDAPQuery):
         return dict(result=True, value=pkey_to_value(keys[-1], options))
 
 
+
 @register()
-class dnszone_add_permission(LDAPQuery):
+class dnszone_add_permission(DNSZoneBase_add_permission):
     __doc__ = _('Add a permission for per-zone access delegation.')
 
-    has_output = _output_permissions
-    msg_summary = _('Added system permission "%(value)s"')
-
-    def execute(self, *keys, **options):
-        ldap = self.obj.backend
-        dn = self.obj.get_dn(*keys, **options)
-
-        try:
-            entry_attrs = ldap.get_entry(dn, ['objectclass'])
-        except errors.NotFound:
-            self.obj.handle_not_found(*keys)
-        else:
-            if not _check_entry_objectclass(entry_attrs, self.obj.object_class):
-                self.obj.handle_not_found(*keys)
-
-        permission_name = self.obj.permission_name(keys[-1])
-        permission = api.Command['permission_add_noaci'](permission_name,
-                         ipapermissiontype=u'SYSTEM'
-                     )['result']
-
-        dnszone_ocs = entry_attrs.get('objectclass')
-        if dnszone_ocs:
-            for oc in dnszone_ocs:
-                if oc.lower() == 'ipadnszone':
-                    break
-            else:
-                dnszone_ocs.append('ipadnszone')
-
-        entry_attrs['managedby'] = [permission['dn']]
-        ldap.update_entry(entry_attrs)
-
-        return dict(
-            result=True,
-            value=pkey_to_value(permission_name, options),
-        )
-
 
 @register()
-class dnszone_remove_permission(LDAPQuery):
+class dnszone_remove_permission(DNSZoneBase_remove_permission):
     __doc__ = _('Remove a permission for per-zone access delegation.')
 
-    has_output = _output_permissions
-    msg_summary = _('Removed system permission "%(value)s"')
-
-    def execute(self, *keys, **options):
-        ldap = self.obj.backend
-        dn = self.obj.get_dn(*keys, **options)
-        try:
-            entry = ldap.get_entry(dn, ['managedby', 'objectclass'])
-        except errors.NotFound:
-            self.obj.handle_not_found(*keys)
-        else:
-            if not _check_entry_objectclass(entry, self.obj.object_class):
-                self.obj.handle_not_found(*keys)
-
-        entry['managedby'] = None
-
-        try:
-            ldap.update_entry(entry)
-        except errors.EmptyModlist:
-            # managedBy attribute is clean, lets make sure there is also no
-            # dangling DNS zone permission
-            pass
-
-        permission_name = self.obj.permission_name(keys[-1])
-        api.Command['permission_del'](permission_name, force=True)
-
-        return dict(
-            result=True,
-            value=pkey_to_value(permission_name, options),
-        )
-
 
 @register()
 class dnsrecord(LDAPObject):
@@ -3570,108 +3659,27 @@ class dnsconfig_show(LDAPRetrieve):
 
 
 @register()
-class dnsforwardzone(LDAPObject):
+class dnsforwardzone(DNSZoneBase):
     """
     DNS Forward zone, container for resource records.
     """
-    container_dn = api.env.container_dns
     object_name = _('DNS forward zone')
     object_name_plural = _('DNS forward zones')
-    object_class = ['top', 'idnsforwardzone']
-    possible_objectclasses = ['ipadnszone']
-    default_attributes = [
-        'idnsname', 'idnszoneactive', 'idnsforwarders', 'idnsforwardpolicy'
-    ]
+    object_class = DNSZoneBase.object_class + ['idnsforwardzone']
     label = _('DNS Forward Zones')
     label_singular = _('DNS Forward Zone')
     default_forward_policy = u'first'
 
-    takes_params = (
-        DNSNameParam('idnsname',
-            only_absolute=True,
-            cli_name='name',
-            label=_('Forward zone name'),
-            doc=_('Forward zone name (FQDN)'),
-            default_from=lambda name_from_ip: _reverse_zone_name(name_from_ip),
-            primary_key=True,
-        ),
-        Str('name_from_ip?', _validate_ipnet,
-            label=_('Reverse zone IP network'),
-            doc=_('IP network to create reverse zone name from'),
-            flags=('virtual_attribute',),
-        ),
-        Bool('idnszoneactive?',
-            cli_name='zone_active',
-            label=_('Active zone'),
-            doc=_('Is zone active?'),
-            flags=['no_create', 'no_update'],
-            attribute=True,
-        ),
-        Str('idnsforwarders*',
-            _validate_bind_forwarder,
-            cli_name='forwarder',
-            label=_('Zone forwarders'),
-            doc=_('Per-zone forwarders. A custom port can be specified '
-                  'for each forwarder using a standard format "IP_ADDRESS port PORT"'),
-            csv=True,
-        ),
-        StrEnum('idnsforwardpolicy?',
-            cli_name='forward_policy',
-            label=_('Forward policy'),
-            doc=_('Per-zone conditional forwarding policy. Set to "none" to '
-                  'disable forwarding.'),
-            values=(u'only', u'first', u'none'),
-        ),
-
-    )
-
-    def get_dn(self, *keys, **options):
-        zone = keys[-1]
-        assert isinstance(zone, DNSName)
-        assert zone.is_absolute()
-        zone = zone.ToASCII()
-
-        #try first relative name, a new zone has to be added as absolute
-        #otherwise ObjectViolation is raised
-        zone = zone[:-1]
-        dn = super(dnsforwardzone, self).get_dn(zone, **options)
-        try:
-            self.backend.get_entry(dn, [''])
-        except errors.NotFound:
-            zone = u"%s." % zone
-            dn = super(dnsforwardzone, self).get_dn(zone, **options)
-
-        return dn
-
-    def permission_name(self, zone):
-        assert isinstance(zone, DNSName)
-        return u"Manage DNS zone %s" % zone.ToASCII()
-
 
 @register()
-class dnsforwardzone_add(LDAPCreate):
+class dnsforwardzone_add(DNSZoneBase_add):
     __doc__ = _('Create new DNS forward zone.')
 
-    has_output_params = LDAPCreate.has_output_params + dnszone_output_params
-
     def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
         assert isinstance(dn, DN)
-        if not dns_container_exists(self.api.Backend.ldap2):
-            raise errors.NotFound(reason=_('DNS is not configured'))
 
-        try:
-            entry = ldap.get_entry(dn)
-        except errors.NotFound:
-            pass
-        else:
-            if _check_entry_objectclass(entry, self.obj.object_class):
-                self.obj.handle_duplicate_entry(*keys)
-            else:
-                raise errors.DuplicateEntry(
-                    message=_(u'Only one zone type is allowed per zone name')
-                    )
-
-        entry_attrs['idnszoneactive'] = 'TRUE'
+        dn = super(dnsforwardzone_add, self).pre_callback(ldap, dn,
+            entry_attrs, attrs_list, *keys, **options)
 
         if not 'idnsforwardpolicy' in entry_attrs:
             entry_attrs['idnsforwardpolicy'] = self.obj.default_forward_policy
@@ -3683,39 +3691,18 @@ class dnsforwardzone_add(LDAPCreate):
 
         return dn
 
-    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
-        assert isinstance(dn, DN)
-        return dn
-
 
 @register()
-class dnsforwardzone_del(LDAPDelete):
+class dnsforwardzone_del(DNSZoneBase_del):
     __doc__ = _('Delete DNS forward zone.')
 
     msg_summary = _('Deleted DNS forward zone "%(value)s"')
 
-    def pre_callback(self, ldap, dn, *nkeys, **options):
-        assert isinstance(dn, DN)
-        if not _check_DN_objectclass(ldap, dn, self.obj.object_class):
-            self.obj.handle_not_found(*nkeys)
-        return dn
-
-    def post_callback(self, ldap, dn, *keys, **options):
-        try:
-            api.Command['permission_del'](self.obj.permission_name(keys[-1]),
-                                          force=True)
-        except errors.NotFound:
-            pass
-
-        return True
-
 
 @register()
-class dnsforwardzone_mod(LDAPUpdate):
+class dnsforwardzone_mod(DNSZoneBase_mod):
     __doc__ = _('Modify DNS forward zone.')
 
-    has_output_params = LDAPUpdate.has_output_params + dnszone_output_params
-
     def pre_callback(self, ldap, dn, entry_attrs, attrs_list,  *keys, **options):
         try:
             entry = ldap.get_entry(dn)
@@ -3744,184 +3731,43 @@ class dnsforwardzone_mod(LDAPUpdate):
 
         return dn
 
-    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
-        return dn
-
 
 @register()
-class dnsforwardzone_find(LDAPSearch):
+class dnsforwardzone_find(DNSZoneBase_find):
     __doc__ = _('Search for DNS forward zones.')
 
-    has_output_params = LDAPSearch.has_output_params + dnszone_output_params
-
-    def args_options_2_params(self, *args, **options):
-        # FIXME: Check that name_from_ip is valid. This is necessary because
-        #        custom validation rules, including _validate_ipnet, are not
-        #        used when doing a search. Once we have a parameter type for
-        #        IP network objects, this will no longer be necessary, as the
-        #        parameter type will handle the validation itself (see
-        #        <https://fedorahosted.org/freeipa/ticket/2266>).
-        if 'name_from_ip' in options:
-            self.obj.params['name_from_ip'](unicode(options['name_from_ip']))
-        return super(dnsforwardzone_find, self).args_options_2_params(*args, **options)
-
-    def args_options_2_entry(self, *args, **options):
-        if 'name_from_ip' in options:
-            if 'idnsname' not in options:
-                options['idnsname'] = self.obj.params['idnsname'].get_default(**options)
-            del options['name_from_ip']
-        search_kw = super(dnsforwardzone_find, self).args_options_2_entry(*args,
-                                                                   **options)
-        name = search_kw.get('idnsname')
-        if name:
-            search_kw['idnsname'] = [name, name.relativize(DNSName.root)]
-        return search_kw
-
     def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
         assert isinstance(base_dn, DN)
-
-        filter = _create_idn_filter(self, ldap, *args, **options)
+        filter, base, dn = super(dnsforwardzone_find, self).pre_callback(
+            ldap, filter, attrs_list, base_dn, scope, *args, **options)
 
         return (filter, base_dn, scope)
 
-    def post_callback(self, ldap, entries, truncated, *args, **options):
-        return truncated
-
 
 @register()
-class dnsforwardzone_show(LDAPRetrieve):
+class dnsforwardzone_show(DNSZoneBase_show):
     __doc__ = _('Display information about a DNS forward zone.')
 
     has_output_params = LDAPRetrieve.has_output_params + dnszone_output_params
 
-    def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
-        assert isinstance(dn, DN)
-        if not _check_DN_objectclass(ldap, dn, self.obj.object_class):
-            self.obj.handle_not_found(*keys)
-        return dn
-
 
 @register()
-class dnsforwardzone_disable(LDAPQuery):
+class dnsforwardzone_disable(DNSZoneBase_disable):
     __doc__ = _('Disable DNS Forward Zone.')
-
-    has_output = output.standard_value
     msg_summary = _('Disabled DNS forward zone "%(value)s"')
 
-    def execute(self, *keys, **options):
-        ldap = self.obj.backend
-
-        dn = self.obj.get_dn(*keys, **options)
-        entry = ldap.get_entry(dn, ['idnszoneactive', 'objectclass'])
-        if not _check_entry_objectclass(entry, self.obj.object_class):
-            self.obj.handle_not_found(*keys)
-
-        entry['idnszoneactive'] = ['FALSE']
-
-        try:
-            ldap.update_entry(entry)
-        except errors.EmptyModlist:
-            pass
-
-        return dict(result=True, value=pkey_to_value(keys[-1], options))
-
 
 @register()
-class dnsforwardzone_enable(LDAPQuery):
+class dnsforwardzone_enable(DNSZoneBase_enable):
     __doc__ = _('Enable DNS Forward Zone.')
-
-    has_output = output.standard_value
     msg_summary = _('Enabled DNS forward zone "%(value)s"')
 
-    def execute(self, *keys, **options):
-        ldap = self.obj.backend
-
-        dn = self.obj.get_dn(*keys, **options)
-        entry = ldap.get_entry(dn, ['idnszoneactive', 'objectclass'])
-        if not _check_entry_objectclass(entry, self.obj.object_class):
-            self.obj.handle_not_found(*keys)
-        entry['idnszoneactive'] = ['TRUE']
-
-        try:
-            ldap.update_entry(entry)
-        except errors.EmptyModlist:
-            pass
-
-        return dict(result=True, value=pkey_to_value(keys[-1], options))
-
 
 @register()
-class dnsforwardzone_add_permission(LDAPQuery):
-    __doc__ = _('Add a permission for per-zone access delegation.')
-
-    has_output = _output_permissions
-    msg_summary = _('Added system permission "%(value)s"')
-
-    def execute(self, *keys, **options):
-        ldap = self.obj.backend
-        dn = self.obj.get_dn(*keys, **options)
-
-        try:
-            entry_attrs = ldap.get_entry(dn, ['objectclass'])
-        except errors.NotFound:
-            self.obj.handle_not_found(*keys)
-        else:
-            if not _check_entry_objectclass(entry_attrs, self.obj.object_class):
-                self.obj.handle_not_found(*keys)
-
-        permission_name = self.obj.permission_name(keys[-1])
-        permission = api.Command['permission_add_noaci'](permission_name,
-                         ipapermissiontype=u'SYSTEM'
-                     )['result']
-
-        dnszone_ocs = entry_attrs.get('objectclass')
-        if dnszone_ocs:
-            for oc in dnszone_ocs:
-                if oc.lower() == 'ipadnszone':
-                    break
-            else:
-                dnszone_ocs.append('ipadnszone')
-
-        entry_attrs['managedby'] = [permission['dn']]
-        ldap.update_entry(entry_attrs)
-
-        return dict(
-            result=True,
-            value=pkey_to_value(permission_name, options),
-        )
+class dnsforwardzone_add_permission(DNSZoneBase_add_permission):
+    __doc__ = _('Add a permission for per-forward zone access delegation.')
 
 
 @register()
-class dnsforwardzone_remove_permission(LDAPQuery):
-    __doc__ = _('Remove a permission for per-zone access delegation.')
-
-    has_output = _output_permissions
-    msg_summary = _('Removed system permission "%(value)s"')
-
-    def execute(self, *keys, **options):
-        ldap = self.obj.backend
-        dn = self.obj.get_dn(*keys, **options)
-        try:
-            entry = ldap.get_entry(dn, ['managedby', 'objectclass'])
-        except errors.NotFound:
-            self.obj.handle_not_found(*keys)
-        else:
-            if not _check_entry_objectclass(entry, self.obj.object_class):
-                self.obj.handle_not_found(*keys)
-
-        entry['managedby'] = None
-
-        try:
-            ldap.update_entry(entry)
-        except errors.EmptyModlist:
-            # managedBy attribute is clean, lets make sure there is also no
-            # dangling DNS zone permission
-            pass
-
-        permission_name = self.obj.permission_name(keys[-1])
-        api.Command['permission_del'](permission_name, force=True)
-
-        return dict(
-            result=True,
-            value=pkey_to_value(permission_name, options),
-        )
+class dnsforwardzone_remove_permission(DNSZoneBase_remove_permission):
+    __doc__ = _('Remove a permission for per-forward zone access delegation.')
-- 
1.8.3.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to