]> Frank Brehm's Git Trees - my-stuff/py-logrotate.git/commitdiff
Module LogRotateStatusFile.py weitergemacht
authorFrank Brehm <frank@brehm-online.com>
Tue, 14 Jun 2011 21:23:50 +0000 (21:23 +0000)
committerFrank Brehm <frank@brehm-online.com>
Tue, 14 Jun 2011 21:23:50 +0000 (21:23 +0000)
git-svn-id: http://svn.brehm-online.com/svn/my-stuff/python/PyLogrotate/trunk@251 ec8d2aa5-1599-4edb-8739-2b3a1bc399aa

LogRotateHandler.py
LogRotateStatusFile.py
test/status-version-2 [new file with mode: 0644]
test/status-version-3 [new file with mode: 0644]

index 65d6ad1d6662870274e003f65ce31a83632347e7..ec45e5df14a41467ae42ce6d9e38a1bded38c618 100755 (executable)
@@ -223,6 +223,15 @@ class LogrotateHandler(object):
 
         self.logger.debug( _("Logrotating ready for work") )
 
+        # Create status file object
+        self.state_file = LogrotateStatusFile(
+            file_name = self.state_file_name,
+            local_dir = self.local_dir,
+            verbose   = self.verbose,
+            test_mode = self.test,
+            logger    = self.logger,
+        )
+
     #------------------------------------------------------------
     def __str__(self):
         '''
@@ -249,7 +258,7 @@ class LogrotateHandler(object):
             'verbose':         self.verbose,
         }
         if self.state_file:
-            structure['state_file'] = str(self.state_file)
+            structure['state_file'] = self.state_file.as_dict()
 
         return pp.pformat(structure)
 
index e36a17f2a2650f0a00576d6f8547bf3605adbcfe..c8387c7ee1d0fcd30a121804e00a044ef91d021d 100755 (executable)
@@ -19,6 +19,11 @@ import os
 import os.path
 import gettext
 import logging
+import pprint
+
+from datetime import tzinfo, timedelta, datetime, date, time
+
+from LogRotateCommon import split_parts 
 
 revision = '$Revision$'
 revision = re.sub( r'\$', '', revision )
@@ -38,6 +43,25 @@ class LogrotateStatusFileError(Exception):
     Base class for exceptions in this module.
     '''
 
+#========================================================================
+
+ZERO = timedelta(0)
+
+class UTC(tzinfo):
+    """UTC"""
+
+    def utcoffset(self, dt):
+        return ZERO
+
+    def tzname(self, dt):
+        return "UTC"
+
+    def dst(self, dt):
+        return ZERO
+
+utc = UTC()
+
+
 #========================================================================
 
 class LogrotateStatusFile(object):
@@ -56,7 +80,7 @@ class LogrotateStatusFile(object):
                         logger     = None,
     ):
         '''
-        Costructor.
+        Constructor.
 
         @param config_file: the file name of the status file
         @type config_file:  str
@@ -72,7 +96,7 @@ class LogrotateStatusFile(object):
         @type local_dir:    str or None
 
         @return: None
-       '''
+        '''
 
         self.local_dir = local_dir
         '''
@@ -172,6 +196,45 @@ class LogrotateStatusFile(object):
             # add ch to logger
             self.logger.addHandler(ch)
 
+        # Initial read
+        self._read(must_exists = False)
+
+    #-------------------------------------------------------
+    def as_dict(self):
+        '''
+        Transforms the elements of the object into a dict
+
+        @return: structure as dict
+        @rtype:  dict
+        '''
+
+        res = {}
+        res['local_dir']             = self.local_dir
+        res['t']                     = self.t
+        res['verbose']               = self.verbose
+        res['file_name']             = self.file_name
+        res['file_name_is_absolute'] = self.file_name_is_absolute
+        res['fd']                    = self.fd
+        res['status_version']        = self.status_version
+        res['test_mode']             = self.test_mode
+        res['logger']                = self.logger
+        res['file_state']            = self.file_state
+
+        return res
+
+    #------------------------------------------------------------
+    def __str__(self):
+        '''
+        Typecasting function for translating object structure
+        into a string
+
+        @return: structure as string
+        @rtype:  str
+        '''
+
+        pp = pprint.PrettyPrinter(indent=4)
+        return pp.pformat(self.as_dict())
+
     #-------------------------------------------------------
     def _read(self, must_exists = True):
         '''
@@ -225,7 +288,88 @@ class LogrotateStatusFile(object):
             raise LogrotateStatusFileError(msg)
         self.fd = fd
 
-        
+        try:
+            # Reading the lines of the status file
+            i = 0
+            for line in fd:
+                i += 1
+                line = line.strip()
+                if self.verbose > 4:
+                    msg = _("Performing status file line '%(line)s' (file: '%(file)s', row: %(row)d)") \
+                            % {'line': line, 'file': self.file_name, 'row': i, }
+                    self.logger.debug(msg)
+
+                # check for file heading
+                if i == 1:
+                    match = re.search(r'^logrotate\s+state\s+-+\s+version\s+([23])$', line, re.IGNORECASE)
+                    if match:
+                        # Correct file header
+                        self.status_version = int(match.group(1))
+                        if self.verbose > 1:
+                            msg = _("Idendified version of status file: %d") % (self.status_version)
+                            self.logger.debug(msg)
+                        continue
+                    else:
+                        # Wrong header
+                        msg = _("Incompatible version of status file '%(file)s': %(header)s") \
+                                % { 'file': self.file_name, 'header': line }
+                        fd.close()
+                        raise LogrotateStatusFileError(msg)
+
+                if line == '':
+                    continue
+
+                parts = split_parts(line)
+                logfile = parts[0]
+                rdate   = parts[1]
+                if self.verbose > 2:
+                    msg = _("Found logfile '%(file)s' with rotation date '%(date)s'.") \
+                            % { 'file': logfile, 'date': rdate }
+                    self.logger.debug(msg)
+
+                if logfile and rdate:
+                    match = re.search(r'\s*(\d+)[_\-](\d+)[_\-](\d+)(?:[\s\-_]+(\d+)[_\-:](\d+)[_\-:](\d+))?', rdate)
+                    if not match:
+                        msg = _("Could not determine date format: '%(date)s' (file: '%(file)s', row: %(row)d)") \
+                                % {'date': rdate, 'file': logfile, 'row': i, }
+                        self.logger.warning(msg)
+                        continue
+                    d = {
+                        'Y': int(match.group(1)),
+                        'm': int(match.group(2)),
+                        'd': int(match.group(3)),
+                        'H': 0,
+                        'M': 0,
+                        'S': 0,
+                    }
+                    if match.group(4) is not None:
+                        d['H'] = int(match.group(4))
+                    if match.group(5) is not None:
+                        d['M'] = int(match.group(5))
+                    if match.group(6) is not None:
+                        d['S'] = int(match.group(6))
+
+                    dt = None
+                    try:
+                        dt = datetime(d['Y'], d['m'], d['d'], d['H'], d['M'], d['S'], tzinfo = utc)
+                    except ValueError, e:
+                        msg = _("Invalid date: '%(date)s' (file: '%(file)s', row: %(row)d)") \
+                                % {'date': rdate, 'file': logfile, 'row': i, }
+                        self.logger.warning(msg)
+                        continue
+
+                    self.file_state[logfile] = dt
+
+                else:
+
+                    msg = _("Neither a logfile nor a date found in line '%(line)s' (file: '%(file)s', row: %(row)d)") \
+                            % {'line': line, 'file': logfile, 'row': i, }
+                    self.logger.warning(msg)
+
+        finally:
+            fd.close
+
+        self.fd = None
 
         return True
 
diff --git a/test/status-version-2 b/test/status-version-2
new file mode 100644 (file)
index 0000000..7459d1e
--- /dev/null
@@ -0,0 +1,37 @@
+logrotate state -- version 2
+"/var/log/apt/term.log" 2010-6-3
+"/var/log/aptitude" 2010-6-3
+"/var/log/dpkg.log" 2010-6-3
+"/var/log/exim4/mainlog" 2010-6-7
+"/var/log/exim4/rejectlog" 2010-6-3
+"/var/log/exim4/paniclog" 2010-6-3
+"/var/log/mysql.log" 2010-6-7
+"/var/log/mysql/mysql.log" 2010-6-3
+"/var/log/mysql/mysql-slow.log" 2010-6-9
+"/var/log/syslog" 2010-6-9
+"/var/log/mail.info" 2010-6-3
+"/var/log/mail.warn" 2010-6-3
+"/var/log/mail.err" 2010-6-3
+"/var/log/mail.log" 2010-6-3
+"/var/log/daemon.log" 2010-6-6
+"/var/log/kern.log" 2010-6-6
+"/var/log/auth.log" 2010-6-6
+"/var/log/user.log" 2010-6-6
+"/var/log/lpr.log" 2010-6-3
+"/var/log/cron.log" 2010-6-3
+"/var/log/debug" 2010-6-6
+"/var/log/messages" 2010-6-6
+"/var/log/wtmp" 2010-6-3
+"/var/log/btmp" 2010-6-3
+"/var/log/apache2/access.log" 2010-6-8
+"/var/log/apache2/error.log" 2010-6-8
+"/var/log/apache2/other_vhosts_access.log" 2010-6-8
+"/var/log/clamav/clamav.log" 2010-6-8
+"/var/log/clamav/freshclam.log" 2010-6-8
+"/var/log/uucp.log" 2010-6-8
+"/var/log/ulog/syslogemu.log" 2010-6-8
+"/var/log/ulog/ulogd.log" 2010-6-8
+"/var/log/named/complete-debug.log" 2010-10-27
+"/var/log/named/debug.log" 2010-10-27
+"/var/log/named/named.log" 2010-10-27
+"/var/log/named/query.log" 2010-10-27
diff --git a/test/status-version-3 b/test/status-version-3
new file mode 100644 (file)
index 0000000..b8096aa
--- /dev/null
@@ -0,0 +1,19 @@
+Logrotate State -- Version 3
+"/var/log/all"                      2011-05-31_01:10:01
+"/var/log/debug"                    2011-05-31_01:10:01
+"/var/log/facility/auth"            2009-09-14_05:40:03
+"/var/log/facility/authpriv"        2009-07-24_01:10:01
+"/var/log/facility/cron"            2011-06-14_01:10:01
+"/var/log/facility/daemon"          2010-12-06_02:10:01
+"/var/log/facility/kern"            2011-05-19_01:10:02
+"/var/log/facility/local0"          2009-02-20_02:10:01
+"/var/log/facility/local7"          2009-08-19_01:10:02
+"/var/log/facility/syslog"          2011-04-01_01:10:02
+"/var/log/facility/user"            2011-05-31_01:10:01
+"/var/log/fw/iptables.log"          2011-06-11_01:10:01
+"/var/log/fw/ulogd.log"             2011-05-31_01:10:01
+"/var/log/kdm.log"                  2011-06-01_01:10:02
+"/var/log/messages"                 2011-05-30_01:10:02
+"/var/log/portage/elog/summary.log" 2011-06-06_01:10:01
+"/var/log/syslog"                   2011-05-30_01:10:02
+"/var/log/wtmp"                     2010-09-12_01:10:02