Commit 9e0d50b6 authored by Daniel Armbruster's avatar Daniel Armbruster Committed by thomas.forbriger
Browse files

Applied changes considered in ticket:160.

This is a legacy commit from before 2015-05-18.
It may be incomplete as well as inconsistent.
See COPYING.legacy and README.history for details.

The logfilehandler now is implemented as a sysloghandler. So the user itself is
repsonsible for his logger configuration. Default syslog-ng and logrotate
configuration files are provided. 
Notice that the configuration file for syslog-ng is written for syslog-ng V3.0.


SVN Path:     http://gpitrsvn.gpi.uni-karlsruhe.de/repos/TFSoftware/trunk
SVN Revision: 4392
SVN UUID:     67feda4a-a26e-11df-9d6e-31afc202ad0c
parent 5bf1ae77
# This is <csback_logrotate.conf>
# =============================================================================
# csback logrotate snippet by Daniel Armbruster
# -------------------------------------------
# $Id$
# =============================================================================
/var/log/csback.log {
compress
rotate 5
maxage 365
missingok
notifempty
dateext
nomail
size +4096k
create 644 root root
sharedscipts
postrotate
/etc/init.d/syslog reload > /dev/null 2>&1 || true
endscript
}
# This is <csback_syslog-ng.conf>
# =============================================================================
# csback syslog-ng V3.0 snippet by Daniel Armbruster
#
# Copy the content of this file to /etc/syslog-ng/syslog-ng.conf or simply add
#
# include "path/to/this/file";
#
# -----------------------------------------------------------------------------
# $Id$
# =============================================================================
options {
long_hostnames(off);
keep_hostname(no);
};
source csback {
tcp(ip(127.0.0.1) port(3333));
udp(ip(127.0.0.1) port(3333));
};
filter fil_csback { match('^csback' value(MSGHDR)); };
destination csbacklog { file("/var/log/csback.log" perm(0644)); };
log { source(csback); filter(fil_csback); destination(csbacklog); };
......@@ -102,7 +102,7 @@ def help():
of a directory is executed but this directory is realized
e.g. as a ring buffer.
-l|--logging Switch on logging to files. Logfiles will be located in
~/.csback/log/.
/var/log/ .
-L|--lock Lock the directories working at. This flag is useful in
case csbackchk was run simultaneously with other csback
processes working in the same directory. Setting this
......@@ -209,6 +209,9 @@ def main(argv=None):
logger.getLogger().info("Start checking checksums ...")
for path in paths:
logger.getLogger().info( \
"Check of files in '{0}' with checksumfile in '{1}'".format(path[1], \
path[0]))
if not csfile.hasCsFile(path[0]):
raise Error(213,"PATH does not contain a checksumfile.")
lock = pidlock.PidLocker(path[0])
......@@ -224,6 +227,8 @@ def main(argv=None):
else:
checksumfile.read()
checksumfile.check(regexes, beTolerant)
logger.getLogger().info( \
"Check of files in '{0}' finished.".format(path[1]))
except Usage as err:
err.display()
......
......@@ -103,7 +103,7 @@ def help():
in PATH or rather Paths' subdirectories. So target must
have the same subdirectory structure as PATH.
-l|--logging Switch on logging to files. Logfiles will be located in
~/.csback/log/.
/var/log/ .
--hash ARG Set the hash function algorithm. Valid values are:
sha224, sha256, sha384, sha512. (default: sha256)
-L|--lock Lock the directories working at. This flag is useful in
......@@ -219,7 +219,7 @@ def main(argv=None):
logger.getLogger().info("Start updating checksumfile(s) ...")
for path in pathes:
logger.getLogger().debug( \
logger.getLogger().info( \
"Updating checksumfile in '{0}' with files from '{1}' ...".format( \
path[0], path[1]))
lock = pidlock.PidLocker(path[0])
......@@ -233,6 +233,8 @@ def main(argv=None):
lock.cancel(os.getpid())
else:
checksumfile.update(regexes)
logger.getLogger().info( \
"Finished updating checksumfile in '{0}'.".format(path[0]))
except Usage as err:
err.display()
......
......@@ -52,6 +52,7 @@ import pwd
import logging
import logging.handlers
import csfile
import socket
__version__ = "V0.1"
__subversion__ = "$Id$"
......@@ -59,6 +60,11 @@ __license__ = "GPLv2"
__author__ = "Daniel Armbruster"
__copyright__ = "Copyright (c) 2012 by Daniel Armbruster"
# ----------------------------------------------------------------------------
# variables
logFileDir = '/var/log/'
# ----------------------------------------------------------------------------
class CsbackLog :
"""
......@@ -69,25 +75,17 @@ class CsbackLog :
self.logger = logging.getLogger(applicationName)
self.logger.setLevel(logging.DEBUG)
self.logger.addHandler(logging.NullHandler())
self.csbacklogger = logging.LoggerAdapter(self.logger, CsbackLog.logInfo)
csfile.csfileLogInfo = CsbackLog.logInfo
csfile.csfileLoggerName = str(applicationName)+'.csfile'
def configure(self, address=('localhost', 3333)):
def configure(self, address=('localhost', 3333), \
socktype=socket.SOCK_STREAM):
"""
Function to configure the csback logging mechanism. The only function which
has to be called once if logging to files is desired.
"""
# check log pathes and create directories if necessary
try:
os.makedirs(CsbackLog.logFileDir)
except OSError:
self.csbacklogger.debug("Csback log directories allready exist.")
else:
self.csbacklogger.debug("Created csback log directories.")
# add rotatedFileHandler to logger
sysloghandler = logging.handlers.SysLogHandler(address=address)
# add syslogHandler to logger
sysloghandler = logging.handlers.SysLogHandler(address=address, \
socktype=socktype)
sysloghandler.setLevel(logging.INFO)
sysloghandler.setFormatter(logging.Formatter(CsbackLog.formatter))
......@@ -100,15 +98,9 @@ class CsbackLog :
self.logger.addHandler(handler)
def getLogger(self):
return self.csbacklogger
return self.logger
formatter = '%(asctime)-15s %(hostname)-6s %(name)-8s[%(pid)s]: \
(%(user)-4s) %(levelname)-8s %(message)s'
logInfo = {'hostname': os.uname()[1], \
'user': pwd.getpwuid(os.getuid()).pw_name, \
'pid': os.getpid()}
logFileDir = os.path.expanduser("~/.csback/log")
logFileName = "csback.log"
formatter = '%(name)-8s[%(process)d]: %(levelname)-8s %(message)s'
# ----------------------------------------------------------------------------
if __name__ == "__main__":
......
......@@ -76,7 +76,7 @@ class Usage(Error):
Usage: csbackmail [-v|--verbose] [-d|--debug] [-l|--logging] -P|--port ARG
-H|--host ARG -u|--username ARG -p|--password ARG
-r|--receiver ADDRESS [-r|--receiver ADDRESS [...]]
-s|--sender ADDRESS [-L|--lock] [PATH [PATH [...]]]
-s|--sender ADDRESS [PATH [PATH [...]]]
or: csbackmail -h|--help\n"""
sys.stderr.write("csbackmail [line "+self.line+"]: "+self.msg+"\n")
sys.stderr.write(usage_text)
......@@ -91,14 +91,14 @@ def help():
Usage: csbackmail [-v|--verbose] [-d|--debug] [-l|--logging] -P|--port ARG
-H|--host ARG -u|--username ARG -p|--password ARG
-r|--receiver ADDRESS [-r|--receiver ADDRESS [...]]
-s|--sender ADDRESS [-L|--lock] [PATH [PATH [...]]]
-s|--sender ADDRESS [PATH [PATH [...]]]
or: csbackmail -h|--help
-------------------------------------------------------------------------------
-v|--verbose Be verbose.
-h|--help Display this help.
-d|--debug Debug mode. Be really verbose.
-l|--logging Switch on logging to logfile. Logfile will be located in
~/.csback/log/.
-l|--logging Switch on logging to logfile. Logfile(s) will be located in
/var/log/ .
-r|--receiver ADDR Email address(es) of the receiver(s). (obligatory)
-s|--sender ADDR Email address of the sender (Sending over SMTP).
(obligatory)
......@@ -107,7 +107,7 @@ def help():
-u|--username ARG Username for SMTP server login.
-p|--password ARG Password for SMTP server login.
PATH Path(s) of the logfile(s) to check. If not specified the
logfiles in ~/.csback/log/ were investigated.
logfiles in /var/log/ were investigated.
"""
sys.stdout.write(help_text)
......@@ -134,7 +134,7 @@ def main(argv=None):
debugMode = False
receivers = []
sender = ''
port = int()
port = -1
host = ''
username = ''
password = ''
......@@ -174,10 +174,10 @@ def main(argv=None):
logFilePathes = [str(arg).rstrip(os.sep)+os.sep for arg in args]
# fetch default logfiles
elif 0 == len(args):
logger.getLogger().info("Taking default logfiles in ~/.csback/log/")
logFilePathes = [os.path.join(csbacklog.CsbackLog.logFileDir, logfile) \
for logfile in os.listdir(csbacklog.CsbackLog.logFileDir) \
if None != re.match('csback\.log|csback\.log\.[1-5]', logfile)]
logger.getLogger().info("Taking default logfiles in /var/log/")
logFilePathes = [os.path.join(csbacklog.logFileDir, logfile) \
for logfile in os.listdir(csbacklog.logFileDir) \
if None != re.match('^csback\.log$', logfile)]
logFilePathes.reverse()
else:
raise Usage(183,"Invalid argument(s).")
......@@ -194,9 +194,18 @@ def main(argv=None):
if None == re.match( \
'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$', add):
raise Error(196, "Email address of receiver not valid.")
if 0 == len(host):
raise Usage(198, "Hostname missing.")
if 0 == len(username):
raise Usage(200, "Username missing.")
if 0 == len(password):
raise Usage(202, "Password missing.")
if -1 == port:
raise Usage(202, "Port missing.")
infoDequeue = deque(maxlen=10)
warningDequeue = deque(maxlen=10)
infoDeque = deque(maxlen=10)
warningDeque = deque(maxlen=10)
errorList = []
criticalList = []
# read logfiles
......@@ -205,9 +214,9 @@ def main(argv=None):
for path in logFilePathes:
for line in open(path, 'r+').readlines():
if line.find('INFO'):
infoDequeue.appendleft("logfile:"+path+"\n"+line)
infoDeque.appendleft("logfile:"+path+"\n"+line)
elif line.find('WARNING'):
warningDequeue.appendleft("logfile:"+path+"\n"+line)
warningDeque.appendleft("logfile:"+path+"\n"+line)
elif line.find('ERROR'):
errorList.append("logfile:"+path+"\n"+line)
elif line.find('CRITICAL'):
......@@ -224,7 +233,7 @@ def main(argv=None):
msg += 'csbackmail.py logfile status\n'
msg += '============================\n'
msg += 'Number of read logfiles: {0}\n\n'.format(len(logFilePathes))
infoList = list(infoDequeue)
infoList = list(infoDeque)
subject = ''
if len(infoList):
logger.getLogger().debug("Adding INFO logfile lines to mail content.")
......@@ -234,7 +243,7 @@ def main(argv=None):
msg += '--------------------------\n'
for line in infoList:
msg += line
warningList = list(warningDequeue)
warningList = list(warningDeque)
if len(warningList):
logger.getLogger().debug( \
"Adding WARNING logfile lines to mail content.")
......
......@@ -157,8 +157,8 @@
# of files/directories to be excluded from the backup.
# recursive Include files of subdirectories. (default yes) Refers as well
# to the copy command if copy enabled.
# logging Switch on the logging mechanism to the csback logfiles in
# ~/.csback/log/ . (default yes)
# logging Switch on the logging mechanism to the csback logfile in
# /var/log/csback.log . (default yes)
# followlinks Follow softlinks in srcdir. (default no)
# copy Use rsync to copy data before from 'srcdir' to 'targetdir'.
# (default no)
......@@ -179,10 +179,10 @@
# exclude Comma (followed by a whitespace) seperated regular expressions
# matching listed files to be excluded from the backup.
# recursive Include files of listed subdirectories. (default yes)
# logging Switch on the logging mechanism to the csback logfiles in
# ~/.csback/log/ . (default yes)
# logging Switch on the logging mechanism to the csback logfile in
# /var/log/csback.log . (default yes)
# followlinks Follow softlinks in srcdir. (default no)
# tolerant While checking don't report anything if a file which is listed is
# tolerant While checking only issue a WARNING if a file which is listed is
# missing. (default no)
#
# Comments:
......
......@@ -60,11 +60,11 @@ __copyright__ = "Copyright (c) 2012 by Daniel Armbruster"
chunkSize = 1024 * 128 # 128kB
csfileLoggerName = ''
csfileLogInfo = {}
BASENAME = "checksumfile"
CSSUFFIX = ".cs"
RESULTSUFFIX = ".result"
LOCKFILENAME = '.lock'
# -----------------------------------------------------------------------------
# functions
......@@ -125,15 +125,14 @@ class CsFile:
self.__cslines = []
self.__hashfunc = hashfunc
self.srcdir = srcdir
self.logger = logging.LoggerAdapter(logging.getLogger( \
csfileLoggerName+".CsFile"), csfileLogInfo)
self.logger = logging.getLogger(csfileLoggerName+".CsFile")
def read(self):
"""
Read a checksumfile.
"""
if not os.access(self.filedir, os.F_OK):
raise CsFileError(136, "Invalid directory path.")
raise CsFileError(135, "Invalid directory path.")
path = os.path.join(self.filedir, BASENAME+CSSUFFIX)
# no checksumfile available -> create new file
if os.access(self.filedir, os.F_OK) and not os.path.isfile(path):
......@@ -141,7 +140,7 @@ class CsFile:
try:
csfile = open(path, 'w')
except IOError as err:
raise CsFileError(144, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
raise CsFileError(143, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
+err.filename)
else:
csfile.close()
......@@ -153,7 +152,7 @@ class CsFile:
self.__cslines = [CsLine(line.split(), self.srcdir) \
for line in csfile if len(line.rstrip()) and line[0] != '#']
except IOError as err:
raise CsFileError(156, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
raise CsFileError(155, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
+err.filename)
else:
csfile.close()
......@@ -175,9 +174,9 @@ class CsFile:
if isinstance(csline, CsLine):
csfile.write(str(csline) + '\n')
else:
raise CsFileError(178, "Argument must be of type CsLine.")
raise CsFileError(177, "Argument must be of type CsLine.")
except IOError as err:
raise CsFileError(180, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
raise CsFileError(179, "[Errno "+str(err.errno)+"] "+err.strerror+": " \
+err.filename)
else:
self.logger.debug("Finished appending to checksumfile '%s'", path)
......@@ -189,7 +188,7 @@ class CsFile:
checksum file in current directory.
"""
if not isinstance(regexes, list):
raise CsFileError(192, "Pass regular expressions in a list.")
raise CsFileError(191, "Pass regular expressions in a list.")
self.logger.debug("Updating checksumfile ...")
# fetch cslines in current csfile
self.read()
......@@ -203,6 +202,7 @@ class CsFile:
regexes.append(BASENAME+CSSUFFIX)
regexes.append(BASENAME+RESULTSUFFIX)
regexes.append(BASENAME+RESULTSUFFIX+r'\.[1-2]')
regexes.append(LOCKFILENAME)
for regex in regexes:
matching = set(file for file in newFiles \
if None != re.match(regex, file))
......@@ -210,6 +210,7 @@ class CsFile:
regexes.remove(BASENAME+CSSUFFIX)
regexes.append(BASENAME+RESULTSUFFIX)
regexes.remove(BASENAME+RESULTSUFFIX+r'\.[1-2]')
regexes.append(LOCKFILENAME)
# exclude registered files
newFiles -= registeredFiles
# generate cslines of newFiles
......@@ -230,7 +231,7 @@ class CsFile:
If the third argument (beTolerant) is set to True the checking process will
be successful, too, if a file listed in a checksumfile is not available
anymore. Then the warning will be issued. Otherwise a error will be printed
anymore. Then a warning will be issued. Otherwise a error will be printed
to the result logfile. In case a checksum does not match or rather changed
an critical message will be printed to the results logfile.
......@@ -250,7 +251,7 @@ class CsFile:
logInfo = {'hostname': os.uname()[1], 'pid': os.getpid()}
resulthandler.setLevel(logging.INFO)
resulthandler.setFormatter(logging.Formatter(format))
logger = logging.getLogger(csfileLoggerName+".CsFile.chk")
logger = logging.getLogger("result")
logger.addHandler(resulthandler)
resultLogger = logging.LoggerAdapter(logger, logInfo)
......@@ -288,8 +289,7 @@ class CsLine:
Class to handle a checksum and further data for a registered file.
"""
def __init__(self, *args):
self.logger = logging.LoggerAdapter(logging.getLogger( \
csfileLoggerName+".CsLine"), csfileLogInfo)
self.logger = logging.getLogger(csfileLoggerName+".CsLine")
if isinstance(args[0], list) and isinstance(args[1], str):
argList = args[0]
self.checksum = argList[0]
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment