]> Frank Brehm's Git Trees - pixelpark/pp-admin-tools.git/commitdiff
Fixing prompt timeout
authorFrank Brehm <frank.brehm@pixelpark.com>
Thu, 15 Jun 2023 14:19:33 +0000 (16:19 +0200)
committerFrank Brehm <frank.brehm@pixelpark.com>
Thu, 15 Jun 2023 14:19:33 +0000 (16:19 +0200)
lib/pp_admintools/app/clean_empty_ldap_groups.py
lib/pp_admintools/app/ldap.py
locale/de_DE/LC_MESSAGES/pp_admintools.po

index 14e6001bf0ad199ea45865cb76aa98c998164b9b..b25c3a8618ddece722318fc580ef7e131ebf1170 100644 (file)
@@ -30,7 +30,7 @@ from .. import pp
 from ..argparse_actions import LimitedIntegerOptionAction
 from ..xlate import XLATOR
 
-__version__ = '0.2.0'
+__version__ = '0.3.0'
 LOG = logging.getLogger(__name__)
 
 _ = XLATOR.gettext
@@ -48,9 +48,14 @@ class CleanEmptyLdapGroupsUserError(LdapAppError):
 class CleanEmptyLdapGroupsApplication(BaseLdapApplication):
     """Application class for removing empty groups from LDAP."""
 
+    use_default_ldap_connection = False
+    use_multiple_ldap_connections = False
+    show_cmdline_ldap_timeout = True
     show_simulate_option = True
     show_quiet_option = False
 
+    default_prompt_timeout = 10
+
     default_max_cycles = 20
     max_max_cycles = 1000
 
@@ -61,10 +66,6 @@ class CleanEmptyLdapGroupsApplication(BaseLdapApplication):
     # -------------------------------------------------------------------------
     def __init__(self, appname=None, base_dir=None):
         """Initialize the CleanEmptyLdapGroupsApplication object."""
-        self.use_default_ldap_connection = False
-        self.use_multiple_ldap_connections = True
-        self.show_cmdline_ldap_timeout = True
-
         self.dns_todo = CIStringSet()
         self.dns_done = CIStringSet()
 
@@ -72,6 +73,8 @@ class CleanEmptyLdapGroupsApplication(BaseLdapApplication):
         self.last_nr_groups_done = 0
         self._base_dn = None
         self._max_cycles = self.default_max_cycles
+        self.instance = None
+        self.connect_info = None
 
         list_oc = format_list(self.group_object_classes, do_repr=True)
         list_attr = format_list(self.member_attributes, do_repr=True)
@@ -189,6 +192,9 @@ class CleanEmptyLdapGroupsApplication(BaseLdapApplication):
 
         self.check_instances()
 
+        self.instance = self.ldap_instances[0]
+        self.connect_info = self.cfg.ldap_connection[self.instance]
+
     # -------------------------------------------------------------------------
     def check_instances(self):
         """Check given instances for admin and read/write access."""
@@ -224,11 +230,20 @@ class CleanEmptyLdapGroupsApplication(BaseLdapApplication):
 
         LOG.debug(_('Searching for empty groups ...'))
 
-        inst = self.ldap_instances[0]
-        self.get_empty_groups(inst)
+        i = 0
+        while True:
+            i += 1
+            self.get_empty_groups()
+            if not len(self.dns_todo):
+                LOG.info(_('No more empty groups left for removing.'))
+                break
+            self.empty_line()
+            msg = _('Lap {} on searching for empty groups to remove.').format(i)
+            LOG.info(msg)
+            self.remove_empty_groups()
 
     # -------------------------------------------------------------------------
-    def get_empty_groups(self, inst):
+    def get_empty_groups(self):
         """Retrieve all LDAP groups without members."""
         self.dns_todo = CIStringSet()
 
@@ -240,13 +255,58 @@ class CleanEmptyLdapGroupsApplication(BaseLdapApplication):
 
         # LOG.debug('LDAP filter: ' + ldap_filter)
         dns = self.get_all_entry_dns(
-            inst=inst, ldap_filter=ldap_filter, base_dn=self.base_dn, no_complain=True)
+            inst=self.instance, ldap_filter=ldap_filter, base_dn=self.base_dn, no_complain=True)
         for dn in dns:
             if dn not in self.dns_done:
                 self.dns_todo.add(dn)
         if self.verbose > 1:
             LOG.debug('Found Group-DNs:\n' + pp(self.dns_todo.as_list()))
 
+    # -------------------------------------------------------------------------
+    def remove_empty_groups(self):
+        """Ask for removing and remove it then."""
+        for dn in self.dns_todo:
+            self.remove_empty_group(dn)
+
+    # -------------------------------------------------------------------------
+    def remove_empty_group(self, dn):
+        """Ask for removing the given group and remove it then."""
+        self.dns_done.add(dn)
+
+        LOG.debug(_('Searching for member attributes of {!r} ...').format(dn))
+        entry = self.get_entry(dn, self.instance)
+        attributes = self.normalized_attributes(entry)
+        if self.verbose > 2:
+            LOG.debug(_('Got attributes:') + '\n' + pp(attributes))
+        member_attribs_found = False
+        for attrib in self.member_attributes:
+            if attrib in attributes and len(attributes[attrib]):
+                member_attribs_found = True
+                if self.verbose > 1:
+                    LOG.debug(_('Found attribute {at!r} in group {g!r}.').format(
+                        at=attrib, g=dn))
+        if member_attribs_found:
+            msg = _('Group {!r} is not empty!').format(dn)
+            LOG.warn(msg)
+            return
+
+        if self.request_for_remove(dn):
+            msg = _('Removing group {!r} ...').format(dn)
+            LOG.info(msg)
+            self.delete_entry(self.instance, dn)
+        else:
+            msg = _("Dont't removing group {!r}.").format(dn)
+            LOG.debug(msg)
+
+    # -------------------------------------------------------------------------
+    def request_for_remove(self, dn):
+        """Request from operator whther to really remove it."""
+        print()
+        msg = self.colored(_('Do you really want to remove the group {!r}').format(dn), 'CYAN')
+        msg += ' ' + _('[{yes}/{no}]?').format(
+            yes=self.colored(_('yes'), 'RED'), no=self.colored(_('No'), 'GREEN')) + ' '
+        return self.ask_for_yes_or_no(msg, default_on_empty=False)
+
 
 # =============================================================================
 if __name__ == '__main__':
index d9255d83f885c13aac735f1f8262ea043fe62673..dd0b544f3fb3ddaf2176c0d87c6a17cb18a134ad 100644 (file)
@@ -45,7 +45,7 @@ from ..config.ldap import DEFAULT_TIMEOUT
 from ..config.ldap import LdapConfiguration, LdapConnectionInfo
 from ..xlate import XLATOR, format_list
 
-__version__ = '0.11.7'
+__version__ = '0.11.8'
 LOG = logging.getLogger(__name__)
 
 _ = XLATOR.gettext
@@ -310,6 +310,7 @@ class BaseLdapApplication(BaseDPXApplication):
         """
         res = super(BaseLdapApplication, self).as_dict(short=short)
 
+        res['default_default_ldap_instance'] = self.default_default_ldap_instance
         res['pattern_re_ldap_dn'] = self.pattern_re_ldap_dn
         res['password_file'] = self.password_file
         res['show_cmdline_ldap_timeout'] = self.show_cmdline_ldap_timeout
@@ -463,6 +464,12 @@ class BaseLdapApplication(BaseDPXApplication):
         if v:
             self.cfg.ldap_timeout = v
 
+        if self.prompt_timeout > self.cfg.ldap_timeout:
+            msg = _('Limiting console timeout to {} seconds due to LDAP timeout.').format(
+                self.cfg.ldap_timeout)
+            LOG.warn(msg)
+            self.prompt_timeout = self.cfg.ldap_timeout
+
         self._init_default_connection()
 
         if self.use_default_ldap_connection:
index 5392876713ccef1778736dfc1d6c2aa0dc47efcc..d6a1605700d74b53bfc7eb1969c8704334389078 100644 (file)
@@ -434,7 +434,7 @@ msgstr "Überprüfe Attribute mit DN-Syntax von Eintrag {!r} …"
 
 #: lib/pp_admintools/app/check_ldap_dn_attributes.py:219
 msgid "Got attributes:"
-msgstr "Gefindene Attribute:"
+msgstr "Gefundene Attribute:"
 
 #: lib/pp_admintools/app/dns_deploy_zones.py:122
 msgid "Generation of the BIND9 configuration file for slave zones."