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

processor reading function implemented

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.

SVN Path:     http://gpitrsvn.gpi.uni-karlsruhe.de/repos/TFSoftware/trunk
SVN Revision: 4353
SVN UUID:     67feda4a-a26e-11df-9d6e-31afc202ad0c
parent f56a8899
#!/usr/bin/env python
## @file csback2cron.py
# @brief Generate a crontab for the csback software suite.
# @brief Generate a crontab file for the csback software suite.
#
# -----------------------------------------------------------------------------
#
......@@ -8,7 +8,7 @@
# @author Daniel Armbruster
# \date 11/09/2011
#
# Purpose: Generate a crontab for the csback toolkit using a configuration
# Purpose: Generate a crontab file for the csback toolkit using a configuration
# file.
#
# ----
......@@ -28,17 +28,17 @@
# along with csback. If not, see <http://www.gnu.org/licenses/>.
# ----
#
# Copyright (c) 2011 by Daniel Armbruster
# Copyright (c) 2011-2012 by Daniel Armbruster
#
# REVISIONS and CHANGES
# 11/09/2011 V0.1 Daniel Armbruster
# 14/09/2011 V0.8 Now multiple exclude flags in CONFIGFILE are supported
# 15/09/2011 V0.8.1 Added several improvements
# 08/01/2012 V0.9 New configuration file syntax. Complete rework.
#
# TODO
# 1) Implement a private function for Processor class to check crontab timestamp
# syntax.
# 2. Implement dynamic time for csbackmail.
#
# =============================================================================
......@@ -46,102 +46,192 @@ import sys
import getopt
import os
import pwd
import string
from datetime import datetime
if sys.version_info == (2,)
from ConfigParser import ConfigParser
from ConfigParser import ParsingError
from ConfigParser import NoSectionError
from ConfigParser import NoOptionError
elif sys.version_info == (3,)
from configparser import ConfigParser
from configparser import ParsingError
from configparser import NoSectionError
from configparser import NoOptionError
else
sys.stderr.write("csback2cron: Incompatible python version.")
version="cscron2back V0.8.1"
license="GPL"
__version__ = "V0.1"
__subversion__ = "$Id$"
__license__ = "GPLv2"
__author__ = "Daniel Armbruster"
__copyright__ = "Copyright (c) 2012 by Daniel Armbruster"
DEFAULTPATH = os.path.expanduser("~/.csback/csbackrc")
# -----------------------------------------------------------------------------
class Error(Exception):
def __init__(self, msg):
self.msg = msg
def display(self):
sys.stderr.write("csback2cron (ERROR): " + self.msg + "\n")
# -----------------------------------------------------------------------------
class Usage(Error):
def display(self):
usage_text = version + "\nLicense:" + license + "\n" + """
Author: Daniel Armbruster
Usage: csback2cron [-v] [-o] [-i CONFIGFILE] <CRONTABFILENAME>
or: csback2cron -h
Note: If [-i CONFIGFILE] isn't passed as a argument, csback2cron uses
~/.csbackrc as default.\n"""
usage_text = "Version: "+__version__+"\nLicense: "+__license__+ \
"\n"+__subversion__+"\nAuthor: "+__author__+ """
Usage: csback2cron [-v|--verbose] [-o|--overwrite] [-i|--infile ARG]
<CRONTABFILENAME>
or: csback2cron -h|--help
Note: If [-i|--infile CONFIGFILE] isn't passed as a argument, csback2cron
uses ~/.csback/csbackrc as default.\n"""
sys.stderr.write("csback2cron: " + self.msg + "\n")
sys.stderr.write(usage_text)
# -----------------------------------------------------------------------------
def help():
help_text = version + "\nLicense:" + license + "\n" + """
Author: Daniel Armbruster
Usage: csback2cron [-v] [-o] [-i CONFIGFILE] <CRONTABFILENAME>
or: csback2cron -h
"""
Printing helptext to stdout.
"""
help_text = "Version: "+__version__+"\nLicense: "+__license__+"\n"+ \
__subversion__+"\nAuthor: "+__author__+"""
Usage: csback2cron [-v|--verbose] [-o|--overwrite] [-i|--infile CONFIGFILE]
<CRONTABFILENAME>
or: csback2cron -h|--help
-------------------------------------------------------------------------------
-v/--verbose Be verbose.
-h/--help Display this help.
-i CONFIGFILE Path to csbackrc - the configuration file of csback.
-v|--verbose Be verbose.
-h|--help Display this help.
-i|--infile ARG If ARG is the path to csbackrc - the configuration file for
the csback crontab generation.
If this argument wasn't passed csback2cron assumes
~/.csbackrc as default argument.
~/.csback/csbackrc as default path to the configuration
file.
-o/--overwrite Overwrite already existing crontab.
<CRONTABFILENAME> Outputfilename of the generated crontab.\n"""
print(help_text)
print(help_text)
# -----------------------------------------------------------------------------
def get_username():
return pwd.getpwuid(os.getuid()).pw_name
class Converter():
pass
# -----------------------------------------------------------------------------
class Processor():
def __init__(self, configfile, crontabfile, verbose=False):
self.__configfile = str(configfile)
self.__crontabfile = str(crontabfile)
self.configfile = configfile
self.crontabfile = crontabfile
self.config = ConfigParser(Processor.DEFAULTS)
self.__verbose = verbose
self.__sLines = []
self.mail = {}
self.backups = []
self.tests = []
def read(self):
try:
if not os.path.isfile(self.__configfile):
raise Error("Given CONFIGFILE is not a regular file.")
if os.stat(self.__configfile).st_size == 0:
raise Error("Given CONFIGFILE is an empty file.")
if self.__verbose:
print("csback2cron: Reading CONFIGFILE ... ")
configfile = open(self.__configfile)
if not os.path.isfile(self.__configfile):
raise Error("Given CONFIGFILE is not a regular file.")
if os.stat(self.__configfile).st_size == 0:
raise Error("Given CONFIGFILE is an empty file.")
if self.__verbose:
sys.stdout.write("csback2cron: Reading CONFIGFILE ... ")
try:
self.config.read(configfile)
except ParsingError as err:
raise Error("{0}".format(err.message))
# fetch mail section
if self.config.has_section('mail'):
try:
lines = [line.rstrip() for line in configfile \
if len(line.rstrip()) and line[0] != '#']
finally:
configfile.close()
if len(lines) < 2:
raise Error("CONFIGFILE not readable.")
# get mail= line
tmp = str(list(filter((lambda x: x[0:5] == "mail="), lines))[0])
lines.remove(tmp)
if len(tmp) == 0 or len(tmp[5:]) == 0:
self.__sendmail = False
self.mail['addresses'] = self.config.get('addresses').split(',')
self.mail['addresses'] = [add.strip() \
for add in self.mail['addresses']]
if self.config.has_option('mail', 'logging'):
self.mail['logging'] = self.config.getboolean('mail', 'logging')
else:
self.mail['logging'] = False
except NoOptionError as err:
raise Error("{0}", err.message)
except ValueError:
raise Error("Argument error in [mail] section.")
else:
self.mail = {}
# fetch backups section
try:
backupKeys = dict(self.config.items('backups'))
if 'keys' in backupKeys:
backups = set(backupKeys['keys'].split(","))
backups = ['backup_'+key.strip() for key in backups]
# fetch every backup section
for key in backups:
if not self.config.has_section(key):
raise Error("Section {0} in configfile not defined.".format(key))
backup = {'id': key}
try:
backup['cronexpr'] = config.get(key, 'cronexpr')
backup['srcdir'] = config.get(key, 'srcdir')
backup['targetdir'] = config.get(key, 'targetdir')
backup['exclude'] = config.get(key, 'exclude').split(", ")
if self.config.has_option(key, 'recursive'):
backup['recursive'] = self.config.getboolean(key, 'recursive')
if self.config.has_option(key, 'logging'):
backup['logging'] = self.config.getboolean(key, 'logging')
if self.config.has_option(key, 'followlinks'):
backup['followlinks'] = self.config.getboolean(key, 'followlinks')
if self.config.has_option(key, 'test'):
backup['test'] = self.config.getboolean(key, 'test')
if self.config.has_option(key, 'tolerant'):
backup['tolerant'] = self.config.getboolean(key, 'tolerant')
except NoOptionError as err:
raise Error("{0}".format(err.message))
except ValueError:
raise Error("Argument error in [{0}] section.".format(key))
else:
self.backups.append(backup)
else:
raise Error(\
"Key 'keys' in configfile section [backups] not defined.")
except NoSectionError:
self.backups = {}
# fetch tests section
try:
testKeys = dict(self.config.items('tests'))
if 'keys' in testKeys:
tests = set(testKeys['keys'].split(","))
tests = ['test_'+key.strip() for key in tests]
# fetch every test section
for key in tests:
if not self.config.has_section(key):
raise Error("Section {0} in configfile not defined.".format(key))
test = {'id': key}
try:
test['cronexpr'] = config.get(key, 'cronexpr')
test['dir'] = config.get(key, 'dir')
if self.config.has_option(key, 'srcdir'):
test['srcdir'] = self.config.get(key, 'srcdir')
else:
test['srcdir'] = test['dir']
test['exclude'] = config.get(key, 'exclude').split(", ")
if self.config.has_option(key, 'recursive'):
test['recursive'] = self.config.getboolean(key, 'recursive')
if self.config.has_option(key, 'logging'):
test['logging'] = self.config.getboolean(key, 'logging')
if self.config.has_option(key, 'followlinks'):
test['followlinks'] = self.config.getboolean(key, 'followlinks')
if self.config.has_option(key, 'tolerant'):
test['tolerant'] = self.config.getboolean(key, 'tolerant')
except NoOptionError as err:
raise Error("{0}".format(err.message))
except ValueError:
raise Error("Argument error in [{0}] section.".format(key))
else:
self.tests.append(test)
else:
self.__sendmail = True
self.__addresses = tmp[5:]
# collect setting lines
if not os.path.isfile(self.__configfile):
raise Error("Given CONFIGFILE is not a regular file.")
if os.stat(self.__configfile).st_size == 0:
raise Error("Given CONFIGFILE is a empty file.")
if len(lines) == 0:
raise Error("No setting lines in CONFIGFILE given.")
for line in lines:
l = line.split(" ")
if len(l) >= 2 and not os.path.isdir(l[1]):
raise Error(l[1] + " is not a directory.")
if len(l) == 3 and os.path.isdir(l[2]):
l.insert(2,'')
d = dict(zip(self.__keylist, l))
self.__sLines.append(d)
except Error as err:
err.display()
sys.exit()
return 2
raise Error(\
"Key 'keys' in configfile section [tests] not defined.")
except NoSectionError:
self.tests = {}
def convert(self):
def write(self):
# header lines
......@@ -224,10 +314,8 @@ class Processor():
res[self.__flags[3]] = res[self.__flags[3]].rstrip()
return res
__flags = ['-c', '-t', '-b', '-e']
__keylist = ['cronexpr', 'source', 'flags', 'target']
#def __check_cronexpr(self, expr):
DEFAULTS = {'logging': True, 'recursive': True, 'followlinks': False, \
'tolerant': False, 'test': True, 'exclude' : ''}
# -----------------------------------------------------------------------------
def main(argv=None):
......@@ -236,14 +324,11 @@ def main(argv=None):
try:
try:
opts, args = getopt.getopt(argv[1:], "hovi:", ["help", "overwrite",\
"verbose"])
"verbose", "infile="])
except getopt.GetoptError as err:
raise Usage(err.msg)
if len(args) == 1:
outputfile = args[0]
else:
raise Usage("Only one CRONTABFILENAME is allowed.")
inputfile = '/home/' + get_username()+ '/.csbackrc'
# fetch arguments
inputfile = DEFAULTPATH
verbose = False
overwrite = False
for opt, a in opts:
......@@ -258,8 +343,12 @@ def main(argv=None):
inputfile = a
else:
raise Usage("Unhandled option chosen.")
if len(args) == 0:
raise Usage("CRONTABFILENAME not given.")
if len(args) == 1:
outputfile = args[0]
else:
raise Usage("Invalid arguments")
# checks
if not overwrite and os.path.isfile(outputfile):
raise Usage(outputfile +\
" already exists. Enable [-o] to overwrite file.")
......
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