]> Frank Brehm's Git Trees - pixelpark/admin-tools.git/commitdiff
Completing pp_lib/quota_check.py
authorFrank Brehm <frank.brehm@pixelpark.com>
Fri, 24 Mar 2017 15:54:00 +0000 (16:54 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Fri, 24 Mar 2017 15:54:00 +0000 (16:54 +0100)
etc/test-home.ini.default
pp_lib/global_version.py
pp_lib/quota_check.py
pp_lib/test_home_app.py

index 46b40e9bbbfa5ebcdd6b637f90be2483c31610f5..bb82a6f81c293078b114de9f5cb45ca365c9c0c3 100644 (file)
 # Must be valid Mail addresses
 #reply_to = frank.brehm@pixelpark.com
 
+# A single complete mail address to use for the
+# sender address, if not given, will be generated by the complete username
+# of the executing user (gecos) and the FQDN of the current host
+#mail_from = Root <root@host.pixelpark.net>
+
 # The method to send the mail. Valid values are:
 #  * smtp - the mail is sent via SMTP to a given MTA
 #mail_method = smtp | sendmail
index 9b2b2b265b5e1ff0c880dfc21ec79b0c90317d7d..40df3d493d43de85f50cf7923e41eac5838ee9b7 100644 (file)
@@ -9,7 +9,7 @@
 
 __author__ = 'Frank Brehm <frank.brehm@pixelpark.com>'
 __contact__ = 'frank.brehm@pixelpark.com'
-__version__ = '0.4.1'
+__version__ = '0.4.2'
 __license__ = 'LGPL3+'
 
 # vim: fileencoding=utf-8 filetype=python ts=4
index 7c9d2b1e39a64182e17b9afd21576b69ebfa9427..24e8631ef16f2a2723549a98589adc1450f312b9 100644 (file)
@@ -25,6 +25,7 @@ import pipes
 import gzip
 import shutil
 import time
+import locale
 
 from subprocess import Popen, PIPE
 
@@ -41,7 +42,7 @@ from .common import pp, terminal_can_colors, to_bytes, to_bool, to_str
 
 from .cfg_app import PpCfgAppError, PpConfigApplication
 
-__version__ = '0.5.1'
+__version__ = '0.5.2'
 LOG = logging.getLogger(__name__)
 UTC = datetime.timezone.utc
 
@@ -75,6 +76,13 @@ class PpQuotaCheckApp(PpConfigApplication):
     # -------------------------------------------------------------------------
     def __init__(self, appname=None, version=__version__):
 
+        self.default_mail_recipients = [
+            'admin.berlin@pixelpark.com'
+        ]
+        self.default_mail_cc = []
+
+        self.default_reply_to = 'noreply@pixelpark.com'
+
         self.chroot_homedir = self.default_chroot_homedir
         self.home_root_abs = self.default_home_root
         self.home_root_rel = os.path.relpath(self.home_root_abs, os.sep)
@@ -515,8 +523,6 @@ class PpQuotaCheckApp(PpConfigApplication):
                 'gecos': dir_owner,
             }
             check['data'][home_rel] = result
-            if i > 10:
-                break
 
         end_ts = datetime.datetime.now(UTC)
         duration = end_ts - self.now
@@ -548,28 +554,99 @@ class PpQuotaCheckApp(PpConfigApplication):
         check['stats']['total_gb'] = float(total_kb) / 1024.0 / 1024.0
 
     # -------------------------------------------------------------------------
-    def send_results(self):
-
-        if not self.unnecessary_dirs:
-            LOG.debug("No unnecessary home directories, nothing to inform.")
-            return
-
-        subject = 'Nicht benötigte Home-Verzeichnisse'
-        body = textwrap.dedent('''\
-            Die folgenden Home-Verzeichnisse befinden sich weder
-            in der lokalen passwd-Datei, im LDAP oder in der exclude-Liste.
-            Sie können damit archiviert und gelöscht werden.''')
-        body += '\n\n'
-        for home in self.unnecessary_dirs:
-            body += ' - ' + home + '\n'
+    def send_results(self, total_dirs_top):
+
+        locale_conv = locale.localeconv()
+        dp = ','
+        ts = '.'
+        if 'decimal_point' in locale_conv and locale_conv['decimal_point'] != '.':
+            dp = locale_conv['decimal_point']
+        if 'thousands_sep' in locale_conv:
+            ts = locale_conv['thousands_sep']
+
+        subject = "Quota weekly summary (>= {:.0f} MB)".format(self.quota_kb / 1024)
+
+        body = "Hallo Berlin dudes!\n\n"
+
+        if total_dirs_top.keys():
+
+            max_len_home = 2
+            max_len_size = 4
+            for home in total_dirs_top.keys():
+                if len(home) > max_len_home:
+                    max_len_home = len(home)
+                size = total_dirs_top[home]['util_kb_avg'] / 1024
+                size_out = "{:,.0f} MB".format(size)
+                size_out = size_out.replace('.', ';').replace(',', ts).replace(';', dp)
+                if len(size_out) > max_len_size:
+                    max_len_size = len(size_out)
+
+            for home in sorted(
+                    total_dirs_top.keys(),
+                    key=lambda x: total_dirs_top[x]['util_kb_avg'],
+                    reverse=True):
+                size = total_dirs_top[home]['util_kb_avg'] / 1024
+                user = total_dirs_top[home]['user']
+                gecos = total_dirs_top[home]['gecos']
+                size_out = "{:,.0f} MB".format(size)
+                size_out = size_out.replace('.', ';').replace(',', ts).replace(';', dp)
+                line = " * {h:<{wh}} - {s:>{ws}} ({u} -> {g})\n".format(
+                    h=home, wh=max_len_home, s=size_out, ws=max_len_size, u=user, g=gecos)
+                body += line
+
+        else:
+
+            body += ("No home directory found with a recursive size "
+                    "greater or equal than {:.f} MB.").format(
+                self.quota_kb / 1024)
+
+        body += "\n\n" + self.mail_from + '\n'
+
+        LOG.debug("Subject: {!r}".format(subject))
+        LOG.debug("Body:\n{}".format(body))
 
         self.send_mail(subject, body)
 
     # -------------------------------------------------------------------------
     def perform_statistics(self):
 
-
-
+        if 'checks' in self.status_data and len(self.status_data['checks'].keys()):
+            total_dirs = {}
+            for check_date in self.status_data['checks'].keys():
+                check = self.status_data['checks'][check_date]
+                if not 'data' in check or not check['data'].keys():
+                    continue
+                # Consolidating data ...
+                for home in check['data'].keys():
+                    pdata = check['data'][home]
+                    old_kb = 0
+                    nr_checks = 0
+                    if home in total_dirs:
+                        old_kb = total_dirs[home]['util_kb']
+                        nr_checks = total_dirs[home]['nr_checks']
+                    nr_checks += 1
+                    util_kb = old_kb + pdata['util_kb']
+                    total_dirs[home] = {
+                        'gecos': pdata['gecos'],
+                        'gid': pdata['gid'],
+                        'uid': pdata['uid'],
+                        'user': pdata['user'],
+                        'util_kb': util_kb,
+                        'nr_checks': nr_checks,
+                        'util_kb_avg': util_kb / nr_checks,
+                    }
+
+            total_dirs_top = {}
+            for home in total_dirs.keys():
+                if total_dirs[home]['util_kb_avg'] < self.quota_kb:
+                    continue
+                total_dirs_top[home] = total_dirs[home]
+            del total_dirs
+
+            if self.verbose > 1:
+                LOG.debug("Got top home directories:\n{}".format(pp(total_dirs_top)))
+
+            self.send_results(total_dirs_top)
 
         # Rotate status file and rewrite an empty status file
         self.rotate_status_file(self.now)
@@ -577,6 +654,7 @@ class PpQuotaCheckApp(PpConfigApplication):
         self.status_data['last_check'] = self.now
         self.write_status_data()
 
+
 # =============================================================================
 
 if __name__ == "__main__":
index 04021e3cf265e8c483dbd0cf54c7d075a5258e8b..1c89a699ac723199e922c81cb1b493d7c4c6080f 100644 (file)
@@ -32,7 +32,7 @@ from .common import pp, terminal_can_colors, to_bytes, to_bool
 
 from .cfg_app import PpCfgAppError, PpConfigApplication
 
-__version__ = '0.4.3'
+__version__ = '0.4.4'
 LOG = logging.getLogger(__name__)
 
 
@@ -60,6 +60,13 @@ class PpTestHomeApp(PpConfigApplication):
     # -------------------------------------------------------------------------
     def __init__(self, appname=None, version=__version__):
 
+        self.default_mail_recipients = [
+            'admin.berlin@pixelpark.com'
+        ]
+        self.default_mail_cc = []
+
+        self.default_reply_to = 'noreply@pixelpark.com'
+
         self.chroot_homedir = self.default_chroot_homedir
         self.home_root_abs = self.default_home_root
         self.home_root_rel = os.path.relpath(self.home_root_abs, os.sep)