This is an automated email from the git hooks/post-receive script.
firstyear pushed a change to branch master in repository lib389.
from 3a7802d Ticket 32 - Add TLS external bind support for testing new be2de10 Ticket 60 - add dsrc to dsconf and dsidm new 934741a Ticket 62 - dirsrv offline log
The 2 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference.
Summary of changes: cli/dsconf | 31 +++++--- cli/dscreate | 2 +- cli/dsctl | 2 +- cli/dsidm | 28 ++++--- lib389/__init__.py | 7 +- lib389/cli_base/__init__.py | 19 +++-- lib389/cli_base/dsrc.py | 118 +++++++++++++++++++++++++++ lib389/dirsrv_log.py | 19 +++-- lib389/tests/cli/dsrc_test.py | 180 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 367 insertions(+), 39 deletions(-) create mode 100644 lib389/cli_base/dsrc.py create mode 100644 lib389/tests/cli/dsrc_test.py
This is an automated email from the git hooks/post-receive script.
firstyear pushed a commit to branch master in repository lib389.
commit be2de10af12475ed6ad086a2819bd73866757e68 Author: William Brown firstyear@redhat.com Date: Tue May 30 15:42:13 2017 +1000
Ticket 60 - add dsrc to dsconf and dsidm
Bug Description: Previously we had to always specifiy a backend to the dsidm commands. As well, many options like TLS auth were not accesible.
Fix Description: adding a ~/.dsrc allows an admin not only to shorthand connect to instances IE:
dsidm -v -b dc=example,dc=com -D 'cn=Directory Manager' ldap://localhost ....
becomes:
dsidm -v localhost ....
It allows us to specify *multiple instances* (ie can swap identities easily) and allows us to use SASL options like TLS external from our CLI tools.
https://pagure.io/lib389/issue/60
Author: wibrown
Review by: spichugi (Thanks!) --- cli/dsconf | 31 +++++--- cli/dscreate | 2 +- cli/dsctl | 2 +- cli/dsidm | 28 ++++--- lib389/cli_base/__init__.py | 19 +++-- lib389/cli_base/dsrc.py | 118 +++++++++++++++++++++++++++ lib389/tests/cli/dsrc_test.py | 180 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 352 insertions(+), 28 deletions(-)
diff --git a/cli/dsconf b/cli/dsconf index 7b60a10..e6cb95d 100755 --- a/cli/dsconf +++ b/cli/dsconf @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3
# --- BEGIN COPYRIGHT BLOCK --- # Copyright (C) 2016 Red Hat, Inc. @@ -24,13 +24,15 @@ from lib389.cli_conf import schema as cli_schema from lib389.cli_conf import lint as cli_lint from lib389.cli_base import disconnect_instance, connect_instance
+from lib389.cli_base.dsrc import dsrc_to_ldap, dsrc_arg_concat + log = logging.getLogger("dsconf")
if __name__ == '__main__':
defbase = ldap.get_option(ldap.OPT_DEFBASE)
- parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(allow_abbrev=True) # Build the base ldap options, this keeps in unified.
# Can we get default options for these from .rc file? @@ -44,7 +46,11 @@ if __name__ == '__main__': ) parser.add_argument('-D', '--binddn', help="The account to bind as for executing operations", - default=DN_DM, + default=None, + ) + parser.add_argument('-b', '--basedn', + help="Basedn (root naming context) of the instance to manage", + default=None ) parser.add_argument('-Z', '--starttls', help="Connect with StartTLS", @@ -71,26 +77,31 @@ if __name__ == '__main__': # I gave attribution. -- wibrown log.debug("Inspired by works of: ITS, The University of Adelaide")
- log.debug("Called with: %s", args) + # Now that we have our args, see how they relate with our instance. + dsrc_inst = dsrc_to_ldap("~/.dsrc", args.instance, log.getChild('dsrc')) + + # Now combine this with our arguments + + dsrc_inst = dsrc_arg_concat(args, dsrc_inst) + + log.debug("Called with: %s" % args) + log.debug("Instance details: %s" % dsrc_inst)
# Assert we have a resources to work on. if not hasattr(args, 'func'): log.error("No resource provided to act upon") - log.error("USAGE: dsadm [options] <resource> <action> [action options]") + log.error("USAGE: dsconf [options] <resource> <action> [action options]") sys.exit(1)
- # TODO: Parse instance to a url in some cases. - ldapurl = args.instance - # Connect # We don't need a basedn, because the config objects derive it properly inst = None if args.verbose: - inst = connect_instance(ldapurl=ldapurl, binddn=args.binddn, verbose=args.verbose, starttls=args.starttls) + inst = connect_instance(dsrc_inst=dsrc_inst, verbose=args.verbose) args.func(inst, None, log, args) else: try: - inst = connect_instance(ldapurl=ldapurl, binddn=args.binddn, verbose=args.verbose, starttls=args.starttls) + inst = connect_instance(dsrc_inst=dsrc_inst, verbose=args.verbose) args.func(inst, None, log, args) except Exception as e: log.debug(e, exc_info=True) diff --git a/cli/dscreate b/cli/dscreate index ffcb114..1b1ef7a 100755 --- a/cli/dscreate +++ b/cli/dscreate @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3
# --- BEGIN COPYRIGHT BLOCK --- # Copyright (C) 2016 Red Hat, Inc. diff --git a/cli/dsctl b/cli/dsctl index 6c38bce..bfaba4a 100755 --- a/cli/dsctl +++ b/cli/dsctl @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3
# --- BEGIN COPYRIGHT BLOCK --- # Copyright (C) 2016 Red Hat, Inc. diff --git a/cli/dsidm b/cli/dsidm index 1c62acb..996b71e 100755 --- a/cli/dsidm +++ b/cli/dsidm @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3
# --- BEGIN COPYRIGHT BLOCK --- # Copyright (C) 2016, William Brown <william at blackhats.net.au> @@ -26,13 +26,15 @@ from lib389.cli_idm import user as cli_user
from lib389.cli_base import connect_instance, disconnect_instance
+from lib389.cli_base.dsrc import dsrc_to_ldap, dsrc_arg_concat + log = logging.getLogger("dsidm")
if __name__ == '__main__':
defbase = ldap.get_option(ldap.OPT_DEFBASE)
- parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(allow_abbrev=True) # First, add the LDAP options
parser.add_argument('instance', @@ -40,7 +42,7 @@ if __name__ == '__main__': ) parser.add_argument('-b', '--basedn', help="Basedn (root naming context) of the instance to manage", - default=defbase + default=None ) parser.add_argument('-v', '--verbose', help="Display verbose operation tracing during command execution", @@ -48,7 +50,7 @@ if __name__ == '__main__': ) parser.add_argument('-D', '--binddn', help="The account to bind as for executing operations", - default=DN_DM, + default=None, ) parser.add_argument('-Z', '--starttls', help="Connect with StartTLS", @@ -79,9 +81,17 @@ if __name__ == '__main__': # I gave attribution. -- wibrown log.debug("Inspired by works of: ITS, The University of Adelaide")
+ # Now that we have our args, see how they relate with our instance. + dsrc_inst = dsrc_to_ldap("~/.dsrc", args.instance, log.getChild('dsrc')) + + # Now combine this with our arguments + + dsrc_inst = dsrc_arg_concat(args, dsrc_inst) + log.debug("Called with: %s", args) + log.debug("Instance details: %s" % dsrc_inst)
- if args.basedn is None: + if dsrc_inst['basedn'] is None: log.error("Must provide a basedn!")
ldapurl = args.instance @@ -89,12 +99,12 @@ if __name__ == '__main__': # Connect inst = None if args.verbose: - inst = connect_instance(ldapurl=ldapurl, binddn=args.binddn, verbose=args.verbose, starttls=args.starttls) - args.func(inst, args.basedn, log, args) + inst = connect_instance(dsrc_inst=dsrc_inst, verbose=args.verbose) + args.func(inst, dsrc_inst['basedn'], log, args) else: try: - inst = connect_instance(ldapurl=ldapurl, binddn=args.binddn, verbose=args.verbose, starttls=args.starttls) - args.func(inst, args.basedn, log, args) + inst = connect_instance(dsrc_inst=dsrc_inst, verbose=args.verbose) + args.func(inst, dsrc_inst['basedn'], log, args) except Exception as e: log.debug(e, exc_info=True) log.error("Error: %s" % e.message) diff --git a/lib389/cli_base/__init__.py b/lib389/cli_base/__init__.py index 3ede30f..3c34366 100644 --- a/lib389/cli_base/__init__.py +++ b/lib389/cli_base/__init__.py @@ -68,19 +68,24 @@ def _warn(data, msg=None): return data
# We'll need another of these that does a "connect via instance name?" -def connect_instance(ldapurl, binddn, verbose, starttls): +def connect_instance(dsrc_inst, verbose): dsargs = { - SER_LDAP_URL: ldapurl, - SER_ROOT_DN: binddn + SER_LDAP_URL: dsrc_inst['uri'], + SER_ROOT_DN: dsrc_inst['binddn'], } ds = DirSrv(verbose=verbose) ds.allocate(dsargs) - if not ds.can_autobind() and binddn is not None: - dsargs[SER_ROOT_PW] = getpass("Enter password for %s on %s : " % (binddn, ldapurl)) - elif binddn is None: + if not ds.can_autobind() and dsrc_inst['binddn'] is not None: + dsargs[SER_ROOT_PW] = getpass("Enter password for %s on %s : " % (dsrc_inst['binddn'], dsrc_inst['uri'])) + elif dsrc_inst['binddn'] is None: raise Exception("Must provide a binddn to connect with") ds.allocate(dsargs) - ds.open(starttls=starttls, connOnly=True) + ds.open(saslmethod=dsrc_inst['saslmech'], + certdir=dsrc_inst['tls_cacertdir'], + reqcert=dsrc_inst['tls_reqcert'], + usercert=dsrc_inst['tls_cert'], + userkey=dsrc_inst['tls_key'], + starttls=dsrc_inst['starttls'], connOnly=True) return ds
def disconnect_instance(inst): diff --git a/lib389/cli_base/dsrc.py b/lib389/cli_base/dsrc.py new file mode 100644 index 0000000..4a2d0ac --- /dev/null +++ b/lib389/cli_base/dsrc.py @@ -0,0 +1,118 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# Copyright (C) 2017 Red Hat, Inc. +# All rights reserved. +# +# License: GPL (version 3 or any later version). +# See LICENSE for details. +# --- END COPYRIGHT BLOCK --- + +import sys +import os +import ldap + +MAJOR, MINOR, _, _, _ = sys.version_info + +if MAJOR >= 3: + import configparser + +def dsrc_arg_concat(args, dsrc_inst): + """ + Given a set of argparse args containing: + + instance + binddn + starttls + + and a dsrc_inst (as from dsrc_to_ldap) + + Using this, overlay the settings together to form an instance + + Generally, if dsrc_inst is None, we make a new instance. + + If dsrc_inst is populated we overlay args as needed on top. + """ + if dsrc_inst is None: + new_dsrc_inst = { + 'uri': args.instance, + 'basedn': args.basedn, + 'binddn': args.binddn, + 'saslmech': None, + 'tls_cacertdir': None, + 'tls_cert': None, + 'tls_key': None, + 'tls_reqcert': ldap.OPT_X_TLS_HARD, + 'starttls': args.starttls, + } + # Make new + return new_dsrc_inst + # overlay things. + if args.basedn is not None: + dsrc_inst['basedn'] = args.basedn + if args.binddn is not None: + dsrc_inst['binddn'] = args.binddn + if args.starttls is True: + dsrc_inst['starttls'] = True + return dsrc_inst + +def dsrc_to_ldap(path, instance_name, log): + """ + Given a path to a file, return the required details for an instance. + + The file should be an ini file, and instance should identify a section. + + The ini fileshould have the content: + + [instance] + uri = ldaps://hostname:port + basedn = dc=example,dc=com + binddn = uid=user,.... + saslmech = [EXTERNAL|PLAIN] + tls_cacertdir = /path/to/cadir + tls_cert = /path/to/user.crt + tls_key = /path/to/user.key + tls_reqcert = [never, hard, allow] + starttls = [true, false] + """ + path = os.path.expanduser(path) + log.debug("dsrc path: %s" % path) + # First read our config + # No such file? + config = configparser.SafeConfigParser() + config.read([path]) + + log.debug("dsrc instances: %s" % config.sections()) + + # Does our section exist? + if not config.has_section(instance_name): + # If not, return none. + log.debug("dsrc no such section %s" % instance_name) + return None + + dsrc_inst = {} + # Read all the values + dsrc_inst['uri'] = config.get(instance_name, 'uri') + dsrc_inst['basedn'] = config.get(instance_name, 'basedn', fallback=None) + dsrc_inst['binddn'] = config.get(instance_name, 'binddn', fallback=None) + dsrc_inst['saslmech'] = config.get(instance_name, 'saslmech', fallback=None) + if dsrc_inst['saslmech'] is not None and dsrc_inst['saslmech'] not in ['EXTERNAL', 'PLAIN']: + raise Exception("~/.dsrc [%s] saslmech must be one of EXTERNAL or PLAIN" % instance_name) + + dsrc_inst['tls_cacertdir'] = config.get(instance_name, 'tls_cacertdir', fallback=None) + dsrc_inst['tls_cert'] = config.get(instance_name, 'tls_cert', fallback=None) + dsrc_inst['tls_key'] = config.get(instance_name, 'tls_key', fallback=None) + dsrc_inst['tls_reqcert'] = config.get(instance_name, 'tls_reqcert', fallback='hard') + if dsrc_inst['tls_reqcert'] not in ['never', 'allow', 'hard']: + raise Exception("dsrc tls_reqcert value invalid. ~/.dsrc [%s] tls_reqcert should be one of never, allow or hard" % instance_name) + if dsrc_inst['tls_reqcert'] == 'never': + dsrc_inst['tls_reqcert'] = ldap.OPT_X_TLS_NEVER + elif dsrc_inst['tls_reqcert'] == 'allow': + dsrc_inst['tls_reqcert'] = ldap.OPT_X_TLS_ALLOW + else: + dsrc_inst['tls_reqcert'] = ldap.OPT_X_TLS_HARD + dsrc_inst['starttls'] = config.getboolean(instance_name, 'starttls', fallback=False) + + # Return the dict. + log.debug("dsrc completed with %s" % dsrc_inst) + return dsrc_inst + + diff --git a/lib389/tests/cli/dsrc_test.py b/lib389/tests/cli/dsrc_test.py new file mode 100644 index 0000000..6e2155c --- /dev/null +++ b/lib389/tests/cli/dsrc_test.py @@ -0,0 +1,180 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# Copyright (C) 2016 Red Hat, Inc. +# All rights reserved. +# +# License: GPL (version 3 or any later version). +# See LICENSE for details. +# --- END COPYRIGHT BLOCK --- + +import pytest +import logging +import ldap +import sys + +from lib389.cli_base.dsrc import dsrc_to_ldap + +MAJOR, MINOR, _, _, _ = sys.version_info +if MAJOR >= 3: + import configparser + +log = logging.getLogger(__name__) + +def write_inf(content): + with open('/tmp/dsrc_test.inf', 'w') as f: + f.write(content) + +@pytest.mark.skipif(sys.version_info < (3,0), reason="requires python3") +def test_dsrc_single_section(): + # Write out inf. + write_inf(""" +[localhost] + """) + # Parse it and assert the content + with pytest.raises(configparser.NoOptionError): + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + + write_inf(""" +[localhost] +uri = ldaps://localhost:636 + """) + # Parse it and assert the content + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + assert(i == { + 'uri': 'ldaps://localhost:636', + 'basedn': None, + 'binddn': None, + 'saslmech': None, + 'tls_cacertdir': None, + 'tls_cert': None, + 'tls_key': None, + 'tls_reqcert': ldap.OPT_X_TLS_HARD, + 'starttls': False} + ) + + write_inf(""" +[localhost] +uri = ldaps://localhost:636 +basedn = dc=example,dc=com +binddn = cn=Directory Manager +starttls = true + """) + # Parse it and assert the content + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + assert(i == { + 'uri': 'ldaps://localhost:636', + 'basedn': 'dc=example,dc=com', + 'binddn': 'cn=Directory Manager', + 'saslmech': None, + 'tls_cacertdir': None, + 'tls_cert': None, + 'tls_key': None, + 'tls_reqcert': ldap.OPT_X_TLS_HARD, + 'starttls': True} + ) + +@pytest.mark.skipif(sys.version_info < (3,0), reason="requires python3") +def test_dsrc_two_section(): + write_inf(""" +[localhost] +uri = ldaps://localhost:636 + +[localhost2] +uri = ldaps://localhost:6362 + """) + # Parse it and assert the content + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + assert(i == { + 'uri': 'ldaps://localhost:636', + 'basedn': None, + 'binddn': None, + 'saslmech': None, + 'tls_cacertdir': None, + 'tls_cert': None, + 'tls_key': None, + 'tls_reqcert': ldap.OPT_X_TLS_HARD, + 'starttls': False} + ) + + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost2', log) + assert(i == { + 'uri': 'ldaps://localhost:6362', + 'basedn': None, + 'binddn': None, + 'saslmech': None, + 'tls_cacertdir': None, + 'tls_cert': None, + 'tls_key': None, + 'tls_reqcert': ldap.OPT_X_TLS_HARD, + 'starttls': False} + ) + + # Section doesn't exist + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost3', log) + assert(i is None) + +@pytest.mark.skipif(sys.version_info < (3,0), reason="requires python3") +def test_dsrc_reqcert(): + write_inf(""" +[localhost] +uri = ldaps://localhost:636 +tls_reqcert = invalid + """) + # Parse it and assert the content + with pytest.raises(Exception): + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + + write_inf(""" +[localhost] +uri = ldaps://localhost:636 +tls_reqcert = hard + """) + # Parse it and assert the content + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + assert(i['tls_reqcert'] == ldap.OPT_X_TLS_HARD) + + write_inf(""" +[localhost] +uri = ldaps://localhost:636 +tls_reqcert = allow + """) + # Parse it and assert the content + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + assert(i['tls_reqcert'] == ldap.OPT_X_TLS_ALLOW) + + write_inf(""" +[localhost] +uri = ldaps://localhost:636 +tls_reqcert = never + """) + # Parse it and assert the content + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + assert(i['tls_reqcert'] == ldap.OPT_X_TLS_NEVER) + +@pytest.mark.skipif(sys.version_info < (3,0), reason="requires python3") +def test_dsrc_saslmech(): + write_inf(""" +[localhost] +uri = ldaps://localhost:636 +saslmech = INVALID_MECH + """) + # Parse it and assert the content + with pytest.raises(Exception): + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + + write_inf(""" +[localhost] +uri = ldaps://localhost:636 +saslmech = EXTERNAL + """) + # Parse it and assert the content + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + assert(i['saslmech'] == 'EXTERNAL') + + write_inf(""" +[localhost] +uri = ldaps://localhost:636 +saslmech = PLAIN + """) + # Parse it and assert the content + i = dsrc_to_ldap('/tmp/dsrc_test.inf', 'localhost', log) + assert(i['saslmech'] == 'PLAIN')
This is an automated email from the git hooks/post-receive script.
firstyear pushed a commit to branch master in repository lib389.
commit 934741a64b8a8c4d50109c99790c2ec12d100b00 Author: William Brown firstyear@redhat.com Date: Wed May 31 11:16:37 2017 +1000
Ticket 62 - dirsrv offline log
Bug Description: dirsrv log would use the online ldap server to lookup the access and error path, but this does not work when instance is offline.
Fix Description: Convert this to use the ds_paths module that does correctly account for this. Improve offline state handling so that we can check this properly.
https://pagure.io/lib389/issue/62
Author: wibrown
Review by: spichugi (Thanks!) --- lib389/__init__.py | 7 ++++++- lib389/dirsrv_log.py | 19 +++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/lib389/__init__.py b/lib389/__init__.py index 1967f57..d96a937 100644 --- a/lib389/__init__.py +++ b/lib389/__init__.py @@ -1269,11 +1269,16 @@ class DirSrv(SimpleLDAPObject, object): pid = pid_from_file(self.ds_paths.pid_file) if pid is None: # No pidfile yet ... + self.state = DIRSRV_STATE_OFFLINE return False if pid == 0: + self.state = DIRSRV_STATE_OFFLINE raise ValueError # Wait - return pid_exists(pid) + if not pid_exists(pid): + self.state = DIRSRV_STATE_OFFLINE + return False + return True
def restart(self, timeout=120, post_open=True): ''' diff --git a/lib389/dirsrv_log.py b/lib389/dirsrv_log.py index bf7f301..3b452fc 100644 --- a/lib389/dirsrv_log.py +++ b/lib389/dirsrv_log.py @@ -15,7 +15,6 @@ from datetime import datetime from dateutil.parser import parse as dt_parse from glob import glob from lib389._constants import DN_CONFIG -from lib389.properties import LOG_ACCESS_PATH, LOG_ERROR_PATH from lib389.utils import ensure_bytes, ensure_str
@@ -50,15 +49,9 @@ class DirsrvLog(object): self.prog_timestamp = re.compile('[(?P<day>\d*)/(?P<month>\w*)/(?P<year>\d*):(?P<hour>\d*):(?P<minute>\d*):(?P<second>\d*)(.(?P<nanosecond>\d*))+\s(?P<tz>[+-]\d*)') # noqa self.prog_datetime = re.compile('^(?P<timestamp>[.*])')
- def _get_log_attr(self, attr): - """Get a logging configfurable attribute value - @param attr - a logging configuration attribute - """ - return self.dirsrv.getEntry(DN_CONFIG).__getattr__(attr) - def _get_log_path(self): """Return the current log file location""" - return self._get_log_attr(self.log_path_attr) + raise Exception("Log type not defined.")
def _get_all_log_paths(self): """Return all the log paths""" @@ -185,7 +178,6 @@ class DirsrvAccessLog(DirsrvLog): @param dirsrv - A DirSrv object """ super(DirsrvAccessLog, self).__init__(dirsrv) - self.log_path_attr = LOG_ACCESS_PATH ## We precompile our regex for parse_line to make it faster. self.prog_m1 = re.compile('^(?P<timestamp>[.*])\sconn=(?P<conn>\d*)\sop=(?P<op>\d*)\s(?P<action>\w*)\s(?P<rem>.*)') self.prog_con = re.compile('^(?P<timestamp>[.*])\sconn=(?P<conn>\d*)\sfd=(?P<fd>\d*)\sslot=(?P<slot>\d*)\sconnection\sfrom\s(?P<remote>[^\s]*)\sto\s(?P<local>[^\s]*)') @@ -199,6 +191,10 @@ class DirsrvAccessLog(DirsrvLog): self.result_regexs = [self.prog_notes, self.prog_repl, self.prog_result]
+ def _get_log_path(self): + """Return the current log file location""" + return self.dirsrv.ds_paths.access_log + def parse_line(self, line): """ This knows how to break up an access log line into the specific fields. @@ -249,9 +245,12 @@ class DirsrvErrorLog(DirsrvLog): @param diursrv - A DirSrv object """ super(DirsrvErrorLog, self).__init__(dirsrv) - self.log_path_attr = LOG_ERROR_PATH self.prog_m1 = re.compile('^(?P<timestamp>[.*])\s(?P<message>.*)')
+ def _get_log_path(self): + """Return the current log file location""" + return self.dirsrv.ds_paths.error_log + def parse_line(self, line): """Parse an errors log line @line - a text string from an errors log
389-commits@lists.fedoraproject.org