]> Frank Brehm's Git Trees - my-stuff/py-logrotate.git/commitdiff
Mit Einlesen der Konfiguration angefangen
authorFrank Brehm <frank@brehm-online.com>
Wed, 20 Apr 2011 13:07:35 +0000 (13:07 +0000)
committerFrank Brehm <frank@brehm-online.com>
Wed, 20 Apr 2011 13:07:35 +0000 (13:07 +0000)
git-svn-id: http://svn.brehm-online.com/svn/my-stuff/python/PyLogrotate/trunk@207 ec8d2aa5-1599-4edb-8739-2b3a1bc399aa

LogRotateConfig.py [new file with mode: 0755]
LogRotateHandler.py
logrotate.py

diff --git a/LogRotateConfig.py b/LogRotateConfig.py
new file mode 100755 (executable)
index 0000000..46ee9fe
--- /dev/null
@@ -0,0 +1,361 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# $Id$
+# $URL$
+
+'''
+@author: Frank Brehm
+@contact: frank@brehm-online.com
+@license: GPL3
+@copyright: (c) 2010-2011 by Frank Brehm, Berlin
+@version: 0.0.2
+@summary: module the configuration parsing object for Python logrotating
+'''
+
+import re
+import sys
+import gettext
+import pprint
+import os.path
+
+revision = '$Revision$'
+revision = re.sub( r'\$', '', revision )
+revision = re.sub( r'Revision: ', r'r', revision )
+revision = re.sub( r'\s*$', '', revision )
+
+__author__    = 'Frank Brehm'
+__copyright__ = '(C) 2011 by Frank Brehm, Berlin'
+__contact__    = 'frank@brehm-online.com'
+__version__    = '0.0.2 ' + revision
+__license__    = 'GPL3'
+
+
+#========================================================================
+# Module variables
+
+# @var: dict with all valid taboo pattern types as keys
+#       and the resulting regex template for the filename as value
+pattern_types = {
+    'ext':    r'%s$',
+    'file':   r'^%s$',
+    'prefix': r'^%s',
+}
+
+#========================================================================
+
+class LogrotateConfigurationError(Exception):
+    '''
+    Base class for exceptions in this module.
+    '''
+
+#========================================================================
+
+class LogrotateConfigurationReader(object):
+    '''
+    Class for reading the configuration for Python logrotating
+
+    @author: Frank Brehm
+    @contact: frank@brehm-online.com
+    '''
+
+    #-------------------------------------------------------
+    def __init__( self, config_file,
+                        verbose    = 0,
+                        logger     = None,
+                        local_dir  = None,
+    ):
+        '''
+        Costructor.
+
+        @param config_file: the configuration file to use
+        @type config_file:  str
+        @param verbose:     verbosity (debug) level
+        @type verbose:      int
+        @param logger:      logger object to use for logging a.s.o.
+        @type logger:       logging.getLogger or None
+        @param local_dir:   The directory, where the i18n-files (*.mo)
+                            are located. If None, then system default
+                            (/usr/share/locale) is used.
+        @type local_dir:    str or None
+
+        @return: None
+        '''
+
+        self.local_dir = local_dir
+        '''
+        @ivar: The directory, where the i18n-files (*.mo) are located.
+        @type: str or None
+        '''
+
+        self.t = gettext.translation(
+            'LogRotateConfig',
+            local_dir,
+            fallback = True
+        )
+        '''
+        @ivar: a gettext translation object
+        @type: gettext.translation
+        '''
+
+        _ = self.t.lgettext
+
+        self.verbose = verbose
+        '''
+        @ivar: verbosity level (0 - 9)
+        @type: int
+        '''
+
+        self.config_file = config_file
+        '''
+        @ivar: the initial configuration file to use
+        @type: str
+        '''
+
+        self.logger = logger
+        '''
+        @ivar: logger object
+        @type: logging.getLogger
+        '''
+
+        if not logger:
+
+            #################################################
+            # Create a logger object, if necessary
+            self.logger = logging.getLogger('logrotate_cfg')
+
+            self.logger.setLevel(logging.DEBUG)
+
+            pp = pprint.PrettyPrinter(indent=4)
+            # create console handler and set level to debug
+            ch = logging.StreamHandler()
+            #ch.setLevel(logging.DEBUG)
+            if verbose:
+                ch.setLevel(logging.DEBUG)
+            else:
+                ch.setLevel(logging.INFO)
+
+            # create formatter
+            formatter = logging.Formatter(
+                '[%(asctime)s]: %(name)s %(levelname)-8s - %(message)s'
+            )
+
+            # add formatter to ch
+            ch.setFormatter(formatter)
+
+            # add ch to logger
+            self.logger.addHandler(ch)
+
+        #############################################
+        # the rest of instance variables:
+
+        self.default = {}
+        '''
+        @ivar: the dafault values for  directives
+        @type: dict
+        '''
+        self.reset_defaults()
+
+        self.taboo = []
+        '''
+        @ivar: taboo patterns for including files of whole directories
+        @type: list
+        '''
+        self.add_taboo(r'\.rpmnew',        'ext');
+        self.add_taboo(r'\.rpmorig',       'ext');
+        self.add_taboo(r'\.rpmsave',       'ext');
+        self.add_taboo(r',v',              'ext');
+        self.add_taboo(r'\.swp',           'ext');
+        self.add_taboo(r'~',               'ext');
+        self.add_taboo(r'\.',              'prefix');
+        self.add_taboo(r'\.bak',           'ext');
+        self.add_taboo(r'\.old',           'ext');
+        self.add_taboo(r'\.rej',           'ext');
+        self.add_taboo(r'CVS',             'file');
+        self.add_taboo(r'RCS',             'file');
+        self.add_taboo(r'\.disabled',      'ext');
+        self.add_taboo(r'\.dpkg-old',      'ext');
+        self.add_taboo(r'\.dpkg-dist',     'ext');
+        self.add_taboo(r'\.dpkg-new',      'ext');
+        self.add_taboo(r'\.cfsaved',       'ext');
+        self.add_taboo(r'\.ucf-old',       'ext');
+        self.add_taboo(r'\.ucf-dist',      'ext');
+        self.add_taboo(r'\.ucf-new',       'ext');
+        self.add_taboo(r'\.cfsaved',       'ext');
+        self.add_taboo(r'\.rhn-cfg-tmp-*', 'ext');
+
+        self.config_files = {}
+        '''
+        @ivar: dict with all called and included configuration files
+               to avoid double including
+        @type: dict
+        '''
+
+        self.config_was_read = False
+        '''
+        @ivar: flag whether the configuration file was read.
+        @type: bool
+        '''
+
+        self.config = {}
+        '''
+        @ivar: the configuration, how it was read from cofiguration file(s)
+        @type: dict
+        '''
+
+        self.logger.debug( _("Logrotate config reader initialised") )
+
+    #------------------------------------------------------------
+    def __str__(self):
+        '''
+        Typecasting function for translating object structure
+        into a string
+
+        @return: structure as string
+        @rtype:  str
+        '''
+
+        pp = pprint.PrettyPrinter(indent=4)
+        structure = {
+            'config':          self.config,
+            'config_file':     self.config_file,
+            'config_files':    self.config_files,
+            'config_was_read': self.config_was_read,
+            'default':         self.default,
+            'local_dir':       self.local_dir,
+            'taboo':           self.taboo,
+            'verbose':         self.verbose,
+        }
+        return pp.pformat(structure)
+
+    #------------------------------------------------------------
+    def reset_defaults(self):
+        '''
+        Resetting self.default to the hard coded values
+        '''
+
+        _ = self.t.lgettext
+
+        if self.verbose > 3:
+            self.logger.debug( _("Resetting default values for directives "
+                    + "to hard coded values") )
+
+        self.default = {}
+
+        self.default['compress']      = None
+        self.default['copytruncate']  = None
+        self.default['create']        = {
+            'mode':  None,
+            'owner': None,
+            'group': None,
+        },
+        self.default['period']        = 7
+        self.default['dateext']       = None
+        self.default['datepattern']   = '%Y-%m-%d'
+        self.default['delaycompress'] = None
+        self.default['extension']     = ""
+        self.default['ifempty']       = 1
+        self.default['maxage']        = None
+        self.default['missingok']     = None
+        self.default['olddir']        = {
+            'dirname':    '',
+            'dateformat': None,
+            'mode':       None,
+            'owner':      None,
+            'group':      None,
+        },
+        self.default['rotate']        = 4
+        self.default['size']          = None
+
+    #------------------------------------------------------------
+    def add_taboo(self, pattern, pattern_type = 'file'):
+        '''
+        Add a pattern to the list of taboo patterns self.taboo
+        Raises a general exception, if pattern_type is invalid
+
+        @param pattern:      The patten to append to the taboo list
+        @type pattern:       str
+        @param pattern_type: The type of the taboo pattern
+                            ('ext', 'file' or 'prefix')
+        @type pattern_type:  str
+
+        @return: None
+        '''
+
+        _ = self.t.lgettext
+
+        if not pattern_type in pattern_types:
+            raise Exception( _('Invalid pattern type "%s" given') % (pattern_type) )
+
+        pattern = ( pattern_types[pattern_type] % pattern )
+        if self.verbose > 3:
+            self.logger.debug( _("New taboo pattern: '%s'.") % (pattern) )
+
+        self.taboo.append(pattern)
+
+    #------------------------------------------------------------
+    def get_config(self):
+        '''
+        Returns the configuration, how it was read from configuration file(s)
+
+        @return: configuration
+        @rtype:  dict or None
+        '''
+
+        if not self.config_was_read:
+            if not self._read():
+                return None
+
+        return self.config
+
+    #------------------------------------------------------------
+    def _read(self):
+        '''
+        Reads the configuration from configuration file and all
+        included files
+        '''
+
+        _ = self.t.lgettext
+        self.logger.debug( _("Try reading configuration from '%s' ...")
+                            % (self.config_file) )
+
+        if not os.path.exists(self.config_file):
+            raise LogrotateConfigurationError(
+                _("File '%s' doesn't exists.") % (self.config_file)
+            )
+
+        self.config_file = os.path.abspath(self.config_file)
+
+        if not os.path.isfile(self.config_file):
+            raise LogrotateConfigurationError(
+                _("'%s' is not a regular file.") % (self.config_file)
+            )
+
+        self.config_files[self.config_file] = True
+
+        self.logger.info( _("Reading configuration from '%s' ...")
+                            % (self.config_file) )
+
+        cfile = None
+        try:
+            cfile = open(self.config_file, 'Ur')
+        except IOError, e:
+            raise LogrotateConfigurationError(
+                ( _("Could not read configuration file '%s'")
+                    % (self.config_file) )
+                + ': ' + str(e)
+            )
+        lines = cfile.readlines()
+        cfile.close()
+
+        return True
+
+#========================================================================
+
+if __name__ == "__main__":
+    pass
+
+
+#========================================================================
+
+# vim: fileencoding=utf-8 filetype=python ts=4 expandtab
index 4638fc1bcdb97b75cc43003f440fec6c39cca76d..0fe4e8f4ccb8acddfc2e46c4082e5783d1a73d6e 100755 (executable)
@@ -9,7 +9,7 @@
 @contact: frank@brehm-online.com
 @license: GPL3
 @copyright: (c) 2010-2011 by Frank Brehm, Berlin
-@version: 0.0.1
+@version: 0.1.0
 @summary: Application handler module for Python logrotating
 '''
 
@@ -21,6 +21,9 @@ import gettext
 import logging
 import pprint
 
+from LogRotateConfig import LogrotateConfigurationError
+from LogRotateConfig import LogrotateConfigurationReader
+
 revision = '$Revision$'
 revision = re.sub( r'\$', '', revision )
 revision = re.sub( r'Revision: ', r'r', revision )
@@ -29,7 +32,7 @@ revision = re.sub( r'\s*$', '', revision )
 __author__    = 'Frank Brehm'
 __copyright__ = '(C) 2011 by Frank Brehm, Berlin'
 __contact__    = 'frank@brehm-online.com'
-__version__    = '0.0.1 ' + revision
+__version__    = '0.1.0 ' + revision
 __license__    = 'GPL3'
 
 
@@ -137,6 +140,12 @@ class LogrotateHandler(object):
         @type: str
         '''
 
+        self.config = {}
+        '''
+        @ivar: the configuration, how it was read from cofiguration file(s)
+        @type: dict
+        '''
+
         #################################################
         # Create a logger object
         self.logger = logging.getLogger('pylogrotate')
@@ -157,7 +166,8 @@ class LogrotateHandler(object):
             ch.setLevel(logging.INFO)
 
         # create formatter
-        formatter = logging.Formatter('[%(asctime)s]: %(name)s %(levelname)-8s - %(message)s')
+        formatter = logging.Formatter('[%(asctime)s]: %(name)s %(levelname)-8s'
+                                        + ' - %(message)s')
 
         # add formatter to ch
         ch.setFormatter(formatter)
@@ -167,6 +177,12 @@ class LogrotateHandler(object):
 
         self.logger.debug( _("Logrotating initialised") )
 
+        if not self.read_configuration():
+            self.logger.error( _('Could not read configuration') )
+            sys.exit(1)
+
+        self.logger.debug( _("Logrotating ready for work") )
+
     #------------------------------------------------------------
     def __str__(self):
         '''
@@ -179,6 +195,7 @@ class LogrotateHandler(object):
 
         pp = pprint.PrettyPrinter(indent=4)
         structure = {
+            'config':      self.config,
             'config_file': self.config_file,
             'force':       self.force,
             'local_dir':   self.local_dir,
@@ -189,6 +206,36 @@ class LogrotateHandler(object):
         }
         return pp.pformat(structure)
 
+    #------------------------------------------------------------
+    def read_configuration(self):
+        '''
+        Reads the configuration from self.config_file
+
+        @return: Success of reading
+        @rtype:  bool
+        '''
+
+        _ = self.t.lgettext
+
+        config_reader = LogrotateConfigurationReader(
+            config_file = self.config_file,
+            verbose     = self.verbose,
+            logger      = self.logger,
+            local_dir   = self.local_dir,
+        )
+
+        if self.verbose > 2:
+            self.logger.debug( _("Configuration reader object structure")
+                            + ':\n' + str(config_reader) )
+
+        try:
+            self.config = config_reader.get_config()
+        except LogrotateConfigurationError, e:
+            self.logger.error( str(e) )
+            sys.exit(10)
+
+        return True
+
 #========================================================================
 
 if __name__ == "__main__":
index 6134ad19c864d92dea2c105c4985aab3afc1b7c5..ab6c338877f6879991396375f449de3b5fddf4ba 100755 (executable)
@@ -9,7 +9,7 @@
 @contact: frank@brehm-online.com
 @license: GPL3
 @copyright: (c) 2010-2011 by Frank Brehm, Berlin
-@version: 0.2.0
+@version: 0.2.2
 @summary: rotates and compress system logs
 '''
 
@@ -32,7 +32,7 @@ revision = re.sub( r'Revision: ', r'r', revision )
 __author__    = 'Frank Brehm'
 __copyright__ = '(C) 2011 by Frank Brehm, Berlin'
 __contact__    = 'frank@brehm-online.com'
-__version__    = '0.2.1 ' + revision
+__version__    = '0.2.2 ' + revision
 __license__    = 'GPL3'