Ejemplo n.º 1
0
def update_grub_core(grub_dev):
    """
    Update GRUB core after upgrade from RHEL7 to RHEL8

    On legacy systems, GRUB core does not get automatically updated when GRUB packages
    are updated.
    """
    cmd = ['grub2-install', grub_dev]
    if config.is_debug():
        cmd += ['-v']
    try:
        run(cmd)
    except CalledProcessError as err:
        reporting.create_report([
            reporting.Title('GRUB core update failed'),
            reporting.Summary(str(err)),
            reporting.Tags([reporting.Tags.BOOT]),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Remediation(
                hint=
                'Please run "grub2-install <GRUB_DEVICE>" manually after upgrade'
            )
        ])
        api.current_logger().warning(
            'GRUB core update on {} failed'.format(grub_dev))
        raise StopActorExecution()
    reporting.create_report([
        reporting.Title('GRUB core successfully updated'),
        reporting.Summary(
            'GRUB core on {} was successfully updated'.format(grub_dev)),
        reporting.Tags([reporting.Tags.BOOT]),
        reporting.Severity(reporting.Severity.INFO)
    ])
Ejemplo n.º 2
0
def _transaction(context, stage, target_repoids, tasks, test=False):
    """
    Perform the actual DNF rpm download via our DNF plugin
    """

    create_config(context=context,
                  target_repoids=target_repoids,
                  debug=config.is_debug(),
                  test=test,
                  tasks=tasks)
    backup_config(context=context)

    with guards.guarded_execution(guards.connection_guard(),
                                  guards.space_guard()):
        try:
            context.call(cmd=[
                '/usr/bin/dnf', 'rhel-upgrade', stage, DNF_PLUGIN_DATA_PATH
            ],
                         callback_raw=utils.logging_handler)
        except OSError as e:
            api.current_logger().error(
                'Could not call dnf command: Message: %s',
                str(e),
                exc_info=True)
            raise StopActorExecutionError(
                message='Failed to execute dnf. Reason: {}'.format(str(e)))
        except CalledProcessError as e:
            api.current_logger().error('DNF execution failed: ')
            raise StopActorExecutionError(
                message=
                'DNF execution failed with non zero exit code.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}'
                .format(stdout=e.stdout, stderr=e.stderr))
        finally:
            if stage == 'check':
                backup_debug_data(context=context)
Ejemplo n.º 3
0
def _logfile_logging_handler(fd_info, line):  # pylint: disable=unused-argument
    """
    Log into logfile

    :param fd_info: Contains File descriptor type (not used)
    :type fd_info: tuple
    :param line: data to be printed to a logfile
    :type line: string
    """
    def _raise_level(handlers):
        for handler in handlers:
            handler.setLevel(handler.level + 1)

    def _restore_level(handlers, levels):
        for handler, level in zip(handlers, levels):
            handler.setLevel(level)

    if is_debug():
        # raise logging level of stream handlers above DEBUG to avoid duplicated output to stdout/stderr
        logger_handlers = api.current_logger().root.handlers
        stream_handlers = [
            handler for handler in logger_handlers
            if isinstance(handler, logging.StreamHandler)
        ]
        handler_levels = [handler.level for handler in stream_handlers]
        _raise_level(stream_handlers)
        api.current_logger().debug(line)
        _restore_level(stream_handlers, handler_levels)
    else:
        api.current_logger().debug(line)
Ejemplo n.º 4
0
def _transaction(context, stage, target_repoids, tasks, plugin_info, test=False, cmd_prefix=None, on_aws=False):
    """
    Perform the actual DNF rpm download via our DNF plugin
    """

    # we do not want
    if stage != 'upgrade':
        create_config(
            context=context,
            target_repoids=target_repoids,
            debug=config.is_debug(),
            test=test, tasks=tasks,
            on_aws=on_aws
        )
    backup_config(context=context)

    # FIXME: rhsm
    with guards.guarded_execution(guards.connection_guard(), guards.space_guard()):
        cmd = [
            '/usr/bin/dnf',
            'rhel-upgrade',
            stage,
            DNF_PLUGIN_DATA_PATH
        ]
        if config.is_verbose():
            cmd.append('-v')
        if rhsm.skip_rhsm():
            cmd += ['--disableplugin', 'subscription-manager']
        if plugin_info:
            for info in plugin_info:
                if stage in info.disable_in:
                    cmd += ['--disableplugin', info.name]
        if cmd_prefix:
            cmd = cmd_prefix + cmd
        env = {}
        if get_target_major_version() == '9':
            # allow handling new RHEL 9 syscalls by systemd-nspawn
            env = {'SYSTEMD_SECCOMP': '0'}
        try:
            context.call(
                cmd=cmd,
                callback_raw=utils.logging_handler,
                env=env
            )
        except OSError as e:
            api.current_logger().error('Could not call dnf command: Message: %s', str(e), exc_info=True)
            raise StopActorExecutionError(
                message='Failed to execute dnf. Reason: {}'.format(str(e))
            )
        except CalledProcessError as e:
            api.current_logger().error('DNF execution failed: ')
            raise StopActorExecutionError(
                message='DNF execution failed with non zero exit code.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}'.format(
                    stdout=e.stdout, stderr=e.stderr)
            )
        finally:
            if stage == 'check':
                backup_debug_data(context=context)
Ejemplo n.º 5
0
def _logging_handler(fd_info, buffer):
    '''Custom log handler to always show DNF stdout to console and stderr only in DEBUG mode'''
    (_unused, fd_type) = fd_info

    if fd_type == STDOUT:
        sys.stdout.write(buffer)
    else:
        if is_debug():
            sys.stderr.write(buffer)
Ejemplo n.º 6
0
def backup_debug_data(context):
    """
    Performs the backup of DNF debug data
    """
    if config.is_debug():
        # The debugdata is a folder generated by dnf when using the --debugsolver dnf option. We switch on the
        # debug_solver dnf config parameter in our rhel-upgrade dnf plugin when LEAPP_DEBUG env var set to 1.
        try:
            context.copytree_from('/debugdata', DNF_DEBUG_DATA_PATH)
        except OSError as e:
            api.current_logger().warning('Failed to copy debugdata. Message: {}'.format(str(e)), exc_info=True)
Ejemplo n.º 7
0
def test_is_debug(monkeypatch):
    matrix = ((('1', '1'), True), (('0', '1'), False), (('1', '0'), True),
              (('0', '0'), False), ((0, 1), False), ((1, 1), False),
              ((1, 0), False), ((0, 0), False), (('1', 0), True), ((0, '1'),
                                                                   False))
    for (debug, verbose), expected in matrix:
        monkeypatch.setattr(os, 'environ', {
            'LEAPP_DEBUG': debug,
            'LEAPP_VERBOSE': verbose
        })
        assert is_debug() == expected
Ejemplo n.º 8
0
def logging_handler(fd_info, buf):
    """
    Custom log handler to always show stdout to console and stderr only in DEBUG mode
    """
    (_unused, fd_type) = fd_info

    if fd_type == STDOUT:
        sys.stdout.write(buf)
    else:
        if config.is_debug():
            sys.stderr.write(buf)
Ejemplo n.º 9
0
def logging_handler(fd_info, buf):
    """
    Custom log handler to always show stdout to console and stderr only in DEBUG mode
    """
    (_unused, fd_type) = fd_info
    if fd_type != STDOUT and not config.is_debug():
        return
    target = sys.stdout if fd_type == STDOUT else sys.stderr
    if sys.version_info > (3, 0):
        os.writev(target.fileno(), [buf])
    else:
        target.write(buf)
Ejemplo n.º 10
0
def _console_logging_handler(fd_info, a_buffer):
    """
    Log into either STDOUT or to STDERR.

    Buffer Output Discrimination is based on fd_type in fd_info while in a leapp debug mode.

    :param fd_info: Contains File descriptor type
    :type fd_info: tuple
    :param a_buffer: buffer interface
    :type a_buffer: bytes array
    """
    if is_debug():
        __write_raw(fd_info, a_buffer)
Ejemplo n.º 11
0
def logging_handler(fd_info, buf):
    """
    Custom log handler to always show stdout to console and stderr only in DEBUG mode
    """
    (_unused, fd_type) = fd_info

    if isinstance(buf, bytes) and str is not bytes:
        buf = buf.decode('utf-8')
    if fd_type == STDOUT:
        sys.stdout.write(buf)
    else:
        if config.is_debug():
            sys.stderr.write(buf)
Ejemplo n.º 12
0
def configure_logger(log_file=None):
    global _logger
    if not _logger:
        log_format = '%(asctime)s.%(msecs)-3d %(levelname)-8s PID: %(process)d %(name)s: %(message)s'
        log_date_format = '%Y-%m-%d %H:%M:%S'
        path = os.getenv('LEAPP_LOGGER_CONFIG', '/etc/leapp/logger.conf')

        if path and os.path.isfile(path):
            logging.config.fileConfig(path)
        else:  # Fall back logging configuration
            logging.Formatter.converter = time.gmtime
            logging.basicConfig(
                level=logging.DEBUG,
                format=log_format,
                datefmt=log_date_format,
                stream=sys.stderr,
            )
            logging.getLogger('urllib3').setLevel(logging.WARN)
            handler = LeappAuditHandler()
            handler.setFormatter(
                logging.Formatter(fmt=log_format, datefmt=log_date_format))
            logging.getLogger('leapp').addHandler(handler)
            logging.StreamHandler().setLevel(logging.ERROR)

        if log_file:
            file_handler = logging.FileHandler(
                os.path.join('/var/log/leapp/', log_file))
            file_handler.setFormatter(
                logging.Formatter(fmt=log_format, datefmt=log_date_format))
            file_handler.setLevel(logging.DEBUG)
            logging.getLogger('leapp').addHandler(file_handler)

        if is_verbose():
            for handler in logging.getLogger().handlers:
                if isinstance(handler, logging.StreamHandler):
                    handler.setLevel(
                        logging.DEBUG if is_debug() else logging.INFO)

        _logger = logging.getLogger('leapp')
        _logger.info('Logging has been initialized')

    return _logger
Ejemplo n.º 13
0
def _transaction(context, stage, target_repoids, tasks, plugin_info, test=False, cmd_prefix=None, on_aws=False):
    """
    Perform the actual DNF rpm download via our DNF plugin
    """

    # we do not want
    if stage not in ['dry-run', 'upgrade']:
        create_config(
            context=context,
            target_repoids=target_repoids,
            debug=config.is_debug(),
            test=test, tasks=tasks,
            on_aws=on_aws
        )
    backup_config(context=context)

    # FIXME: rhsm
    with guards.guarded_execution(guards.connection_guard(), guards.space_guard()):
        cmd_prefix = cmd_prefix or []
        common_params = []
        if config.is_verbose():
            common_params.append('-v')
        if rhsm.skip_rhsm():
            common_params += ['--disableplugin', 'subscription-manager']
        if plugin_info:
            for info in plugin_info:
                if stage in info.disable_in:
                    common_params += ['--disableplugin', info.name]
        env = {}
        if get_target_major_version() == '9':
            # allow handling new RHEL 9 syscalls by systemd-nspawn
            env = {'SYSTEMD_SECCOMP': '0'}

            # We need to reset modules twice, once before we check, and the second time before we actually perform
            # the upgrade. Not more often as the modules will be reset already.
            if stage in ('check', 'upgrade') and tasks.modules_to_reset:
                # We shall only reset modules that are not going to be enabled
                # This will make sure it is so
                modules_to_reset = {(module.name, module.stream) for module in tasks.modules_to_reset}
                modules_to_enable = {(module.name, module.stream) for module in tasks.modules_to_enable}
                module_reset_list = [module[0] for module in modules_to_reset - modules_to_enable]
                # Perform module reset
                cmd = ['/usr/bin/dnf', 'module', 'reset', '--enabled', ] + module_reset_list
                cmd += ['--disablerepo', '*', '-y', '--installroot', '/installroot']
                try:
                    context.call(
                        cmd=cmd_prefix + cmd + common_params,
                        callback_raw=utils.logging_handler,
                        env=env
                    )
                except (CalledProcessError, OSError):
                    api.current_logger().debug('Failed to reset modules via dnf with an error. Ignoring.',
                                               exc_info=True)

        cmd = [
            '/usr/bin/dnf',
            'rhel-upgrade',
            stage,
            DNF_PLUGIN_DATA_PATH
        ]
        try:
            context.call(
                cmd=cmd_prefix + cmd + common_params,
                callback_raw=utils.logging_handler,
                env=env
            )
        except OSError as e:
            api.current_logger().error('Could not call dnf command: Message: %s', str(e), exc_info=True)
            raise StopActorExecutionError(
                message='Failed to execute dnf. Reason: {}'.format(str(e))
            )
        except CalledProcessError as e:
            api.current_logger().error('DNF execution failed: ')
            raise StopActorExecutionError(
                message='DNF execution failed with non zero exit code.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}'.format(
                    stdout=e.stdout, stderr=e.stderr)
            )
        finally:
            if stage == 'check':
                backup_debug_data(context=context)