Improve error handling in ipa-httpd-kdcproxy

The pre start script 'ipa-httpd-kdcproxy' for httpd.service now handles
connection and authentication errors more gracefully. If the script is
not able to conenct to LDAP, it only prints a warning and exits with
status code 0. All other errors are still reported as fatal error and
result in a non-zero exit code.

This fixes a problem with offline RPM updates. A restart of Apache no
longer fails when LDAP is not running.

Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Christian Heimes 2015-07-07 16:05:48 +02:00 committed by Tomas Babej
parent 6fa123447f
commit 25d1afdc54

View File

@ -37,8 +37,26 @@ DEBUG = False
TIME_LIMIT = 2
class CheckError(Exception):
"""An unrecoverable error has occured"""
class Error(Exception):
"""Base error class"""
class ConfigFileError(Error):
"""Something is wrong with the config file"""
class CheckError(Error):
"""An unrecoverable error has occured
The exit code is 0.
"""
class FatalError(Error):
"""A fatal error has occured
Fatal errors cause the command to exit with a non-null exit code.
"""
class KDCProxyConfig(object):
@ -64,14 +82,16 @@ class KDCProxyConfig(object):
self.con.ldapi = True
self.con.do_bind(timeout=self.time_limit)
except errors.NetworkError as e:
msg = 'Failed to get setting from dirsrv: %s' % e
self.log.exception(msg)
msg = 'Unable to connect to dirsrv: %s' % e
raise CheckError(msg)
except errors.AuthorizationError as e:
msg = 'Authorization error: %s' % e
raise CheckError(msg)
except Exception as e:
msg = ('Unknown error while retrieving setting from %s: %s' %
(self.ldap_uri, e))
self.log.exception(msg)
raise CheckError(msg)
raise FatalError(msg)
def _find_entry(self, dn, attrs, filter, scope=IPAdmin.SCOPE_BASE):
"""Find an LDAP entry, handles NotFound and Limit"""
@ -87,7 +107,7 @@ class KDCProxyConfig(object):
msg = ('Unknown error while retrieving setting from %s: %s' %
(self.ldap_uri, e))
self.log.exception(msg)
raise CheckError(msg)
raise FatalError(msg)
return entries[0]
def is_host_enabled(self):
@ -105,19 +125,21 @@ class KDCProxyConfig(object):
if not os.path.exists(self.conflink):
return False
if not os.path.islink(self.conflink):
raise CheckError("'%s' already exists, but it is not a symlink" %
self.conflink)
raise ConfigFileError(
"'%s' already exists, but it is not a symlink"
% self.conflink)
dest = os.readlink(self.conflink)
if dest != self.conf:
raise CheckError("'%s' points to '%s', expected '%s'"
% (self.conflink, dest, self.conf))
raise ConfigFileError(
"'%s' points to '%s', expected '%s'"
% (self.conflink, dest, self.conf))
return True
def create_symlink(self):
"""Create symlink to enable KDC proxy support"""
try:
valid = self.validate_symlink()
except CheckError as e:
except ConfigFileError as e:
self.log.warn("Cannot enable KDC proxy: %s " % e)
return False
@ -165,16 +187,29 @@ class KDCProxyConfig(object):
def main(debug=DEBUG, time_limit=TIME_LIMIT):
# initialize API without file logging
if not api.isdone('bootstrap'):
api.bootstrap(context='kdcproxyshim', log=None, debug=debug)
api.bootstrap(context='ipa-httpd-kdcproxy', log=None, debug=debug)
standard_logging_setup(verbose=True, debug=debug)
with KDCProxyConfig(time_limit) as cfg:
if cfg.is_host_enabled():
if cfg.create_symlink():
api.log.info('KDC proxy enabled')
else:
if cfg.remove_symlink():
api.log.info('KDC proxy disabled')
try:
cfg = KDCProxyConfig(time_limit)
with cfg:
if cfg.is_host_enabled():
if cfg.create_symlink():
api.log.info('KDC proxy enabled')
return 0
else:
if cfg.remove_symlink():
api.log.info('KDC proxy disabled')
return 0
except CheckError as e:
api.log.warn(str(e))
api.log.warn('Disabling KDC proxy')
cfg.remove_symlink()
return 0
except Exception as e:
api.log.error(str(e))
return 1
if __name__ == '__main__':
main()
sys.exit(main())