Imported Upstream version 4.8.10

This commit is contained in:
Mario Fetka
2021-10-03 11:06:28 +02:00
parent 10dfc9587b
commit 03a8170b15
2361 changed files with 1883897 additions and 338759 deletions

View File

@@ -22,30 +22,39 @@
Handles common operations like option parsing and logging
"""
import logging
import sys
import os
import traceback
from optparse import OptionGroup
from optparse import OptionGroup # pylint: disable=deprecated-module
from ipaplatform.osinfo import osinfo
from ipapython import version
from ipapython import config
from ipapython import ipa_log_manager
from ipapython.ipa_log_manager import standard_logging_setup
SUCCESS = 0
SERVER_INSTALL_ERROR = 1
SERVER_NOT_CONFIGURED = 2
logger = logging.getLogger(__name__)
class ScriptError(StandardError):
class ScriptError(Exception):
"""An exception that records an error message and a return value
"""
def __init__(self, msg='', rval=1):
if msg is None:
msg = ''
self.msg = msg
super(ScriptError, self).__init__(msg)
self.rval = rval
def __str__(self):
return self.msg
@property
def msg(self):
return str(self)
class AdminTool(object):
class AdminTool:
"""Base class for command-line admin tools
To run the tool, call the main() classmethod with a list of command-line
@@ -86,7 +95,6 @@ class AdminTool(object):
usage = None
description = None
log = None
_option_parsers = dict()
@classmethod
@@ -154,6 +162,7 @@ class AdminTool(object):
def __init__(self, options, args):
self.options = options
self.args = args
self.log_file_initialized = False
self.safe_options = self.option_parser.get_safe_opts(options)
def execute(self):
@@ -169,7 +178,11 @@ class AdminTool(object):
self.ask_for_options()
self.setup_logging()
return_value = self.run()
except BaseException, exception:
except BaseException as exception:
if isinstance(exception, ScriptError):
# pylint: disable=no-member
if exception.rval and exception.rval > return_value:
return_value = exception.rval # pylint: disable=no-member
traceback = sys.exc_info()[2]
error_message, return_value = self.handle_error(exception)
if return_value:
@@ -200,7 +213,6 @@ class AdminTool(object):
Any options that might be asked for should also be validated here.
"""
pass
def setup_logging(self, log_file_mode='w'):
"""Set up logging
@@ -224,18 +236,28 @@ class AdminTool(object):
- a plain print for things that should not be log (for example,
interactive prompting)
To log, use `self.log.info()`, `self.log.warning()`, etc.
To log, use a module-level logger.
Logging to file is only set up after option validation and prompting;
before that, all output will go to the console only.
"""
root_logger = logging.getLogger()
for handler in root_logger.handlers:
if (isinstance(handler, logging.StreamHandler) and
handler.stream is sys.stderr): # pylint: disable=no-member
root_logger.removeHandler(handler)
break
self._setup_logging(log_file_mode=log_file_mode)
if self.log_file_name:
self.log_file_initialized = True
def _setup_logging(self, log_file_mode='w', no_file=False):
if no_file:
log_file_name = None
elif self.options.log_file:
log_file_name = self.options.log_file
self.log_file_name = log_file_name
else:
log_file_name = self.log_file_name
if self.options.verbose:
@@ -249,21 +271,20 @@ class AdminTool(object):
verbose = False
else:
verbose = True
ipa_log_manager.standard_logging_setup(
standard_logging_setup(
log_file_name, console_format=console_format,
filemode=log_file_mode, debug=debug, verbose=verbose)
self.log = ipa_log_manager.log_mgr.get_logger(self)
if log_file_name:
self.log.debug('Logging to %s' % log_file_name)
logger.debug('Logging to %s', log_file_name)
elif not no_file:
self.log.debug('Not logging to a file')
logger.debug('Not logging to a file')
def handle_error(self, exception):
"""Given an exception, return a message (or None) and process exit code
"""
if isinstance(exception, ScriptError):
return exception.msg, exception.rval or 1
return exception.msg, exception.rval
elif isinstance(exception, SystemExit):
if isinstance(exception.code, int):
return None, exception.code
@@ -281,16 +302,27 @@ class AdminTool(object):
assumed to have run successfully, and the return value is used as the
SystemExit code.
"""
self.log.debug('%s was invoked with arguments %s and options: %s',
self.command_name, self.args, self.safe_options)
self.log.debug('IPA version %s' % version.VENDOR_VERSION)
logger.debug('%s was invoked with arguments %s and options: %s',
self.command_name, self.args, self.safe_options)
logger.debug('IPA version %s', version.VENDOR_VERSION)
logger.debug('IPA platform %s', osinfo.platform)
logger.debug('IPA os-release %s %s', osinfo.name, osinfo.version)
def log_failure(self, error_message, return_value, exception, backtrace):
self.log.debug(''.join(traceback.format_tb(backtrace)))
self.log.debug('The %s command failed, exception: %s: %s',
self.command_name, type(exception).__name__, exception)
logger.debug('%s', ''.join(traceback.format_tb(backtrace)))
logger.debug('The %s command failed, exception: %s: %s',
self.command_name, type(exception).__name__, exception)
if error_message:
self.log.error(error_message)
logger.error('%s', error_message)
if return_value == 0:
# A script may raise an exception but still want quit gracefully,
# like the case of ipa-client-install called from
# ipa-server-install.
return
message = "The %s command failed." % self.command_name
if self.log_file_initialized and return_value != SERVER_NOT_CONFIGURED:
message += " See %s for more information" % self.log_file_name
logger.error('%s', message)
def log_success(self):
self.log.info('The %s command was successful', self.command_name)
logger.info('The %s command was successful', self.command_name)