def generate_report(existing_custom_network_scripts):
    """ Generate reports informing user about possible manual intervention required """

    # Show documentation url if custom network-scripts detected
    title = "custom network-scripts detected"
    summary = (
        "RHEL 9 does not support the legacy network-scripts package that was"
        " deprecated in RHEL 8. Custom network-scripts have been detected.")

    reporting.create_report([
        reporting.Title(title),
        reporting.Summary(summary),
        reporting.Remediation(hint=(
            "Migrate the custom network-scripts to NetworkManager dispatcher"
            " scripts manually before the ugprade. Follow instructions in the"
            " official documentation.")),
        reporting.Severity(reporting.Severity.HIGH),
        reporting.Flags([reporting.Flags.INHIBITOR]),
        reporting.Tags([reporting.Tags.NETWORK, reporting.Tags.SERVICES]),
        reporting.ExternalLink(
            title=
            ("Upgrading from RHEL 8 to 9 - migrating custom network-scripts to"
             " NetworkManager dispatcher scripts"),
            url=DOC_URL,
        ),
    ] + [
        reporting.RelatedResource("file", fname)
        for fname in existing_custom_network_scripts
    ])
Example #2
0
def check_dialogs(inhibit_if_no_userchoice=True):
    results = list(api.consume(DialogModel))
    for dialog in results:
        sections = dialog.answerfile_sections
        summary = (
            'One or more sections in answerfile are missing user choices: {}\n'
            'For more information consult https://leapp.readthedocs.io/en/latest/dialogs.html'
        )
        dialog_resources = [
            reporting.RelatedResource('dialog', s) for s in sections
        ]
        dialogs_remediation = (
            'Please register user choices with leapp answer cli command or by manually editing '
            'the answerfile.')
        # FIXME: Enable more choices once we can do multi-command remediations
        cmd_remediation = [[
            'leapp', 'answer', '--section', "{}={}".format(s, choice)
        ] for s, choices in dialog.answerfile_sections.items()
                           for choice in choices[:1]]
        report_data = [
            reporting.Title('Missing required answers in the answer file'),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Summary(summary.format('\n'.join(sections))),
            reporting.Flags([reporting.Flags.
                             INHIBITOR] if inhibit_if_no_userchoice else []),
            reporting.Remediation(hint=dialogs_remediation,
                                  commands=cmd_remediation)
        ]
        reporting.create_report(report_data + dialog_resources)
Example #3
0
def _inhibit_on_duplicate_repos(repofiles):
    """
    Inhibit the upgrade if any repoid is defined multiple times.

    When that happens, it not only shows misconfigured system, but then
    we can't get details of all the available repos as well.
    """
    duplicates = repofileutils.get_duplicate_repositories(repofiles).keys()

    if not duplicates:
        return
    list_separator_fmt = '\n    - '
    api.current_logger().warning(
        'The following repoids are defined multiple times:{0}{1}'.format(
            list_separator_fmt, list_separator_fmt.join(duplicates)))

    reporting.create_report([
        reporting.Title('A YUM/DNF repository defined multiple times'),
        reporting.Summary(
            'The following repositories are defined multiple times:{0}{1}'.
            format(list_separator_fmt, list_separator_fmt.join(duplicates))),
        reporting.Severity(reporting.Severity.MEDIUM),
        reporting.Tags([reporting.Tags.REPOSITORY]),
        reporting.Flags([reporting.Flags.INHIBITOR]),
        reporting.Remediation(
            hint='Remove the duplicate repository definitions.')
    ])
Example #4
0
def _report_excluded_repos(repos):
    api.current_logger().info(
        "The optional repository is not enabled. Excluding %r "
        "from the upgrade",
        repos,
    )

    report = [
        reporting.Title("Excluded RHEL 8 repositories"),
        reporting.Summary(
            "The following repositories are not supported by "
            "Red Hat and are excluded from the list of repositories "
            "used during the upgrade.\n- {}".format("\n- ".join(repos))
        ),
        reporting.Severity(reporting.Severity.INFO),
        reporting.Tags([reporting.Tags.REPOSITORY]),
        reporting.Flags([reporting.Flags.FAILURE]),
        reporting.Remediation(
            hint=(
                "If you still require to use the excluded repositories "
                "during the upgrade, execute leapp with the following options: {}."
            ).format(" ".join(["--enablerepo {}".format(repo) for repo in repos])),
        ),
    ]
    reporting.create_report(report)
def get_events(pes_json_directory, pes_json_filename):
    """
    Get all the events from the source JSON file exported from PES.

    :return: List of Event tuples, where each event contains event type and input/output pkgs
    """
    try:
        return parse_pes_events(
            fetch.read_or_fetch(pes_json_filename,
                                directory=pes_json_directory,
                                allow_empty=True))
    except (ValueError, KeyError):
        title = 'Missing/Invalid PES data file ({}/{})'.format(
            pes_json_directory, pes_json_filename)
        summary = 'Read documentation at: https://access.redhat.com/articles/3664871 for more information ' \
            'about how to retrieve the files'
        reporting.create_report([
            reporting.Title(title),
            reporting.Summary(summary),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.SANITY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.RelatedResource(
                'file', os.path.join(pes_json_directory, pes_json_filename))
        ])
        raise StopActorExecution()
Example #6
0
    def process(self):
        tftp_client_service = 'tftp-client'
        send_report = False

        for facts in self.consume(FirewalldUsedObjectNames):
            if tftp_client_service in facts.services:
                send_report = True

        if send_report:
            create_report([
                reporting.Title('Unsupported Firewalld Configuration In Use'),
                reporting.Summary(
                    'Firewalld has service "{service}" enabled. '
                    'Service "{service}" has been removed in RHEL-9.'.format(
                        service=tftp_client_service)),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Tags(
                    [reporting.Tags.SANITY, reporting.Tags.FIREWALL]),
                reporting.Flags([reporting.Flags.INHIBITOR]),
                reporting.Remediation(hint=(
                    'Remove all usage of service "{service}" from '
                    'firewalld\'s permanent configuration. '
                    'It may be in use by: zones, policies, or rich rules.\n'
                    'Usage can be found by listing zone and policy '
                    'configuration:\n'
                    '  # firewall-cmd --permanent --list-all-zones\n'
                    '  # firewall-cmd --permanent --list-all-policies\n'
                    'Example to remove usage from a zone:\n'
                    '  # firewall-cmd --permanent --zone public '
                    ' --remove-service {service}\n'.format(
                        service=tftp_client_service))),
            ])
Example #7
0
def check_certkey_directives(facts, report_func):
    """
    Checks if the data model tells ServerKey/ServerCertificate directives
    are used and produces a report.

    :param obj facts: model object containing info about CUPS configuration
    :param func report_func: creates report
    """
    title = ('ServerKey/ServerCertificate directives are substitued '
             'by ServerKeychain directive')
    summary = (
        'The directives were substitued by ServerKeychain directive, '
        'which now takes a directory as value (/etc/cups/ssl is default). '
        'The previous directives took a file as value. '
        'The migration script will copy the files specified in '
        'directive values into /etc/cups/ssl directory '
        'if they are not there already. '
        'This will be handled automatically during the upgrade process.')
    if facts.certkey:
        args = [
            reporting.Title(title),
            reporting.Summary(summary),
            reporting.Tags(
                [reporting.Tags.SERVICES, reporting.Tags.AUTHENTICATION]),
            reporting.Severity(reporting.Severity.MEDIUM),
            reporting.RelatedResource('file', '/etc/cups/cups-files.conf')
        ]

        report_func(args)
Example #8
0
    def process(self):
        removed_file = 'files/removed_drivers.txt'
        conflicting = check_drivers(get_removed_drivers(removed_file),
                                    get_present_drivers())

        if conflicting:
            title = ('Detected loaded kernel drivers which have been removed '
                     'in RHEL 8. Upgrade cannot proceed.')
            URL = (
                'https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html-single/'
                'considerations_in_adopting_rhel_8/index#removed-device-drivers_hardware-enablement'
            )
            summary = ('Support for the following RHEL 7 '
                       'device drivers has been removed in RHEL 8: \n     - {}'
                       '\nPlease see {} for details.'.format(
                           '\n     - '.join(conflicting), URL))
            remediation = (
                'Please disable detected kernel drivers in '
                'order to proceed with the upgrade process using the rmmod or modprobe -r.'
            )
            create_report([
                reporting.Title(title),
                reporting.Summary(summary),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Tags([reporting.Tags.KERNEL, reporting.Tags.DRIVERS
                                ]),
                reporting.Flags([reporting.Flags.INHIBITOR]),
                reporting.Remediation(hint=remediation)
            ] + [
                reporting.RelatedResource('kernel-driver', kd)
                for kd in conflicting
            ])
def _check_default_path_checker(options):
    if not options['default_path_checker']:
        return
    value, pathname = options['default_path_checker']
    if value == 'tur':
        return
    create_report([
        reporting.Title('Unsupported device-mapper-multipath configuration'),
        reporting.Summary(
            'device-mapper-multipath has changed the default path_checker '
            'from "directio" to "tur" in RHEL-8. Further, changing the '
            'default path_checker can cause issues with built-in device '
            'configurations in RHEL-8. Please remove the "path_checker" '
            'option from the defaults section of {}, and add it to the '
            'device configuration of any devices that need it.'.format(
                pathname)),
        reporting.Severity(reporting.Severity.HIGH),
        reporting.Tags([reporting.Tags.SERVICES]),
        reporting.Flags([reporting.Flags.INHIBITOR]),
        reporting.RelatedResource('package', 'device-mapper-multipath'),
        reporting.RelatedResource('file', pathname),
        reporting.Remediation(
            hint='Please remove the "path_checker {}" option from the '
            'defaults section of {}, and add it to the device configuration '
            'of any devices that need it.'.format(value, pathname))
    ])
def process():
    storage = _get_storage_data()
    used_removed_options = set()
    for entry in storage.fstab:
        if entry.fs_vfstype == 'xfs':
            # NOTE: some opts could have a value, like ihashsize=4096 - we want
            # just the name of the option (that's why the double-split)
            options = set([opt.split('=')[0] for opt in entry.fs_mntops.split(',')])
            used_removed_options.update(options.intersection(REMOVED_XFS_OPTIONS))

    if not used_removed_options:
        return

    list_separator_fmt = '\n    - '
    reporting.create_report([
        reporting.Title('Deprecated XFS mount options present in FSTAB.'),
        reporting.Summary(
            'Some XFS mount options are not supported on RHEL 8 and prevent'
            ' system from booting correctly if any of the reported XFS options are used.'
            ' filesystem:{}{}.'.format(
                list_separator_fmt,
                list_separator_fmt.join(list(REMOVED_XFS_OPTIONS)))),
        reporting.Severity(reporting.Severity.HIGH),
        reporting.Flags([reporting.Flags.INHIBITOR]),
        reporting.Tags([reporting.Tags.FILESYSTEM]),
        reporting.RelatedResource('file', '/etc/fstab'),
        reporting.Remediation(hint=(
            'Drop the following mount options from the /etc/fstab file for any'
            ' XFS filesystem: {}.'.format(', '.join(used_removed_options)))),
    ])
Example #11
0
def process():
    if not architecture.matches_architecture(architecture.ARCH_S390X):
        return
    cpuinfo = next(api.consume(CPUInfo), None)
    if cpuinfo is None:
        raise StopActorExecutionError(message=("Missing information about CPU."))

    if not cpuinfo.machine_type:
        # this is not expected to happen, but in case...
        api.curernt_logger().warning("The machine (CPU) type is empty.")

    if cpuinfo.machine_type not in SUPPORTED_MACHINE_TYPES:
        summary = ("The machine is not possible to upgrade because of unsupported"
                   " type of the processor. Regarding the official documentation,"
                   " z13 and z14 processors are supported on the Red Had Enterprise"
                   " Linux 8 system for the IBM Z architecture. If you have one of"
                   " the supported processors, you should see provided the machine"
                   " type in the /proc/cpuinfo file with one of those values: {}."
                   " Detected machine type of the CPU is '{}'."
                   .format(", ".join([str(i) for i in SUPPORTED_MACHINE_TYPES]), cpuinfo.machine_type))
        report = [
            reporting.Title("The processor is not supported by the target system."),
            reporting.Summary(summary),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.SANITY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.ExternalLink(
                title="Considerations in adopting RHEL 8",
                url=("https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/"
                     "html-single/considerations_in_adopting_rhel_8/"
                     "index#changes-in-gcc-in-rhel-8_changes-in-toolchain-since-rhel-7"))
        ]
        reporting.create_report(report)
Example #12
0
 def process(self):
     try:
         quagga_facts = next(self.consume(QuaggaToFrrFacts))
     except StopIteration:
         return
     if 'babeld' in quagga_facts.active_daemons or 'babeld' in quagga_facts.enabled_daemons:
         create_report([
             reporting.Title('Babeld is not available in FRR'),
             reporting.ExternalLink(
                 url='https://access.redhat.com/'
                 'documentation/en-us/red_hat_enterprise_linux/8/html/'
                 'configuring_and_managing_networking/setting-your-rou'
                 'ting-protocols_configuring-and-managing-networking',
                 title='Setting routing protocols in RHEL8'),
             reporting.Summary(
                 'babeld daemon which was a part of quagga implementation in RHEL7 '
                 'is not available in RHEL8 in FRR due to licensing issues.'
             ),
             reporting.Severity(reporting.Severity.HIGH),
             reporting.Tags(COMMON_REPORT_TAGS),
             reporting.Flags([reporting.Flags.INHIBITOR]),
             reporting.Remediation(
                 hint='Please use RIP, OSPF or EIGRP instead of Babel')
         ])
     else:
         self.log.debug('babeld not used, moving on.')
Example #13
0
 def process(self):
     if has_package(InstalledRedHatSignedRPM, 'grep'):
         create_report([
             reporting.Title(
                 'Grep has incompatible changes in the next major version'),
             reporting.Summary(
                 'If a file contains data improperly encoded for the current locale, and this is '
                 'discovered before any of the file\'s contents are output, grep now treats the file '
                 'as binary.\n'
                 'The \'grep -P\' no longer reports an error and exits when given invalid UTF-8 data. '
                 'Instead, it considers the data to be non-matching.\n'
                 'In locales with multibyte character encodings other than UTF-8, grep -P now reports '
                 'an error and exits instead of misbehaving.\n'
                 'When searching binary data, grep now may treat non-text bytes as line terminators. '
                 'This can boost performance significantly.\n'
                 'The \'grep -z\' no longer automatically treats the byte \'\\200\' as binary data.\n'
                 'Context no longer excludes selected lines omitted because of -m. For example, '
                 '\'grep "^" -m1 -A1\' now outputs the first two input lines, not just the first '
                 'line.\n'),
             reporting.Severity(reporting.Severity.LOW),
             reporting.Tags([reporting.Tags.TOOLS]),
             reporting.Remediation(
                 hint=
                 'Please update your scripts to be compatible with the changes.'
             ),
             reporting.RelatedResource('package', 'grep')
         ])
Example #14
0
def process(openssh_messages):
    config = next(openssh_messages, None)
    if list(openssh_messages):
        api.current_logger().warning(
            'Unexpectedly received more than one OpenSshConfig message.')
    if not config:
        raise StopActorExecutionError(
            'Could not check openssh configuration',
            details={'details': 'No OpenSshConfig facts found.'})

    if config.use_privilege_separation is not None and \
       config.use_privilege_separation != "sandbox":
        reporting.create_report([
            reporting.Title(
                'OpenSSH configured not to use privilege separation sandbox'),
            reporting.Summary(
                'OpenSSH is configured to disable privilege '
                'separation sandbox, which is decreasing security '
                'and is no longer supported in RHEL 8'),
            reporting.Severity(reporting.Severity.LOW),
            reporting.Tags([
                reporting.Tags.AUTHENTICATION, reporting.Tags.SECURITY,
                reporting.Tags.NETWORK, reporting.Tags.SERVICES
            ]),
        ])
Example #15
0
def check_ntp(installed_packages):
    service_data = [('ntpd', 'ntp', '/etc/ntp.conf'),
                    ('ntpdate', 'ntpdate', '/etc/ntp/step-tickers'),
                    ('ntp-wait', 'ntp-perl', None)]

    migrate_services = []
    migrate_configs = []
    for service, package, main_config in service_data:
        if package in installed_packages and \
                check_service('{}.service'.format(service)) and \
                (not main_config or is_file(main_config)):
            migrate_services.append(service)
            if main_config:
                migrate_configs.append(service)

    if migrate_configs:
        reporting.create_report([
            reporting.Title('{} configuration will be migrated'.format(' and '.join(migrate_configs))),
            reporting.Summary('{} service(s) detected to be enabled and active'.format(', '.join(migrate_services))),
            reporting.Severity(reporting.Severity.LOW),
            reporting.Tags([reporting.Tags.SERVICES, reporting.Tags.TIME_MANAGEMENT]),
        ] + related)

        # Save configuration files that will be renamed in the upgrade
        config_tgz64 = get_tgz64(files)
    else:
        api.current_logger().info('ntpd/ntpdate configuration will not be migrated')
        migrate_services = []
        config_tgz64 = ''

    return NtpMigrationDecision(migrate_services=migrate_services, config_tgz64=config_tgz64)
def _check_default_detection(options):
    bad = []
    for keyword in ('detect_path_checker', 'detect_prio',
                    'retain_attached_hw_handler'):
        if options[keyword] and not options[keyword][0] and \
                options[keyword][1] not in bad:
            bad.append(options[keyword][1])
    if not bad:
        return
    paths = _create_paths_str(bad)
    create_report([
        reporting.Title(
            'device-mapper-multipath now defaults to detecting settings'),
        reporting.Summary(
            'In RHEL-8, the default value for the "detect_path_checker", '
            '"detect_prio" and "retain_attached_hw_handler" options has '
            'changed to "yes". Further, changing these default values can '
            'cause issues with the built-in device configurations in RHEL-8. '
            'They will be commented out in the defaults section of all '
            'multipath config files. This is unlikely to cause any issues '
            'with existing configurations. If it does, please move these '
            'options from the defaults sections of {} to the device '
            'configuration sections of any devices that need them.'.format(
                paths)),
        reporting.Severity(reporting.Severity.MEDIUM),
        reporting.Tags([reporting.Tags.SERVICES]),
        reporting.RelatedResource('package', 'device-mapper-multipath')
    ])
Example #17
0
def process(openssh_messages):
    config = next(openssh_messages, None)
    if list(openssh_messages):
        api.current_logger().warning('Unexpectedly received more than one OpenSshConfig message.')
    if not config:
        raise StopActorExecutionError(
            'Could not check openssh configuration', details={'details': 'No OpenSshConfig facts found.'}
        )

    if config.protocol:
        reporting.create_report([
            reporting.Title('OpenSSH configured with removed configuration Protocol'),
            reporting.Summary(
                'OpenSSH is configured with removed configuration '
                'option Protocol. If this used to be for enabling '
                'SSHv1, this is no longer supported in RHEL 8. '
                'Otherwise this option can be simply removed.'
            ),
            reporting.Severity(reporting.Severity.LOW),
            reporting.Tags([
                    reporting.Tags.AUTHENTICATION,
                    reporting.Tags.SECURITY,
                    reporting.Tags.NETWORK,
                    reporting.Tags.SERVICES
            ]),
        ])
Example #18
0
    def process(self):
        service_name = 'leapp_resume.service'
        service_templ_fpath = self.get_file_path(service_name)
        shutil.copyfile(service_templ_fpath,
                        os.path.join('/etc/systemd/system/', service_name))

        service_path = '/etc/systemd/system/{}'.format(service_name)
        symlink_path = '/etc/systemd/system/default.target.wants/{}'.format(
            service_name)

        try:
            os.symlink(service_path, symlink_path)
        except OSError as e:
            self.report_error(
                'Could not create a symlink to enable {}'.format(service_name),
                details=str(e))
            return

        create_report([
            reporting.Title('Leapp resume systemd service enabled'),
            reporting.Summary(
                '{} enabled as oneshot systemd service to resume Leapp execution '
                'after reboot.'.format(service_name)),
            reporting.Severity(reporting.Severity.INFO),
            reporting.Tags([reporting.Tags.UPGRADE_PROCESS]),
            reporting.RelatedResource('file', service_path),
            reporting.RelatedResource('file', symlink_path),
            reporting.RelatedResource('service', service_name)
        ])
Example #19
0
def ipa_warn_pkg_installed(ipainfo):
    """
    Warn that unused ipa-server package is installed
    """
    if ipainfo.is_client_configured:
        summary = (
            "The ipa-server package is installed but only IdM client is "
            "configured on this system.")
    else:
        summary = (
            "The ipa-server package is installed but neither IdM server "
            "nor client is configured on this system.")
    entries = [
        reporting.Title(
            "ipa-server package is installed but no IdM is configured"),
        reporting.Summary(summary),
        reporting.Remediation(
            hint="Remove unused ipa-server package",
            commands=[["yum", "remove", "ipa-server"]],
        ),
        reporting.ExternalLink(
            url=MIGRATION_GUIDE,
            title="Migrating IdM from RHEL 7 to 8",
        ),
        reporting.Severity(reporting.Severity.MEDIUM),
        reporting.Tags([reporting.Tags.SERVICES]),
        reporting.RelatedResource("package", "ipa-server"),
    ]
    return reporting.create_report(entries)
Example #20
0
 def process(self):
     if not all(next(self.consume(model), None) for model in self.consumes):
         return
     if self.file_baseurl_in_use():
         warn_msg = (
             "Local repository found (baseurl starts with file:///). "
             "Currently leapp does not support this option.")
         self.log.warning(warn_msg)
         reporting.create_report([
             reporting.Title("Local repository detected"),
             reporting.Summary(warn_msg),
             reporting.Severity(reporting.Severity.HIGH),
             reporting.Tags([reporting.Tags.REPOSITORY]),
             reporting.Flags([reporting.Flags.INHIBITOR]),
             reporting.Remediation(
                 hint=("By using Apache HTTP Server you can expose "
                       "your local repository via http. See the linked "
                       "article for details. ")),
             reporting.ExternalLink(
                 title=("Customizing your Red Hat Enterprise Linux "
                        "in-place upgrade"),
                 url=("https://access.redhat.com/articles/4977891/"
                      "#repos-known-issues"),
             ),
         ])
Example #21
0
def check_digest_values(facts, report_func):
    """
    Checks if the data model tells Digest/BasicDigest values
    of AuthType/DefaultAuthType directives are used
    and produces a report.

    :param obj facts: model object containing info about CUPS configuration
    :param func report_func: creates report
    """
    title = ('CUPS no longer supports Digest and BasicDigest '
             'directive values')
    summary = (
        'Digest and BasicDigest directive values were removed '
        'due to deprecation. '
        'The Basic authentication with TLS encryption will be '
        'set automatically during the upgrade process. '
        'The version of the used TLS is by default dependent on the set system '
        'crypto policies.')
    # NOTE: the remediation instructions are missing as we do not have any
    # doc covering that, mainly because of this is expected to be very rare
    # at all. People usually do not use Digest & BasicDigest.
    if facts.digest:
        args = [
            reporting.Title(title),
            reporting.Summary(summary),
            reporting.Tags([
                reporting.Tags.AUTHENTICATION,
                reporting.Tags.SECURITY,
                reporting.Tags.SERVICES,
            ]),
            reporting.Severity(reporting.Severity.MEDIUM),
            reporting.RelatedResource('file', '/etc/cups/cupsd.conf')
        ]

        report_func(args)
Example #22
0
def _inhibit_on_duplicate_repos(repos_raw_stderr):
    """
    Inhibit the upgrade if any repoid is defined multiple times.

    When that happens, it not only shows misconfigured system, but then we can't get details of all the available
    repos as well.
    """
    duplicates = []
    for duplicate in re.findall(
            r'Repository ([^\s]+) is listed more than once', repos_raw_stderr,
            re.DOTALL | re.MULTILINE):
        duplicates.append(duplicate)

    if not duplicates:
        return
    list_separator_fmt = '\n    - '
    api.current_logger().warn(
        'The following repoids are defined multiple times:{0}{1}'.format(
            list_separator_fmt, list_separator_fmt.join(duplicates)))

    reporting.create_report([
        reporting.Title('A YUM/DNF repository defined multiple times'),
        reporting.Summary(
            'The `yum repoinfo` command reports that the following repositories are defined multiple times:{0}{1}'
            .format(list_separator_fmt, list_separator_fmt.join(duplicates))),
        reporting.Severity(reporting.Severity.MEDIUM),
        reporting.Tags([reporting.Tags.REPOSITORY]),
        reporting.Flags([reporting.Flags.INHIBITOR]),
        reporting.Remediation(
            hint='Remove the duplicit repository definitions.')
    ])
Example #23
0
    def process(self):
        interfaces = next(self.consume(PersistentNetNamesFacts)).interfaces

        if self.single_eth0(interfaces):
            self.disable_persistent_naming()
        elif len(interfaces) > 1 and self.ethX_count(interfaces) > 0:
            create_report([
                reporting.Title('Unsupported network configuration'),
                reporting.Summary(
                    'Detected multiple physical network interfaces where one or more use kernel naming (e.g. eth0). '
                    'Upgrade process can not continue because stability of names can not be guaranteed. '
                    'Please read the article at https://access.redhat.com/solutions/4067471 for more information.'
                ),
                reporting.ExternalLink(
                    title=
                    'How to perform an in-place upgrade to RHEL 8 when using kernel NIC names on RHEL 7',
                    url='https://access.redhat.com/solutions/4067471'),
                reporting.Remediation(
                    hint=
                    'Rename all ethX network interfaces following the attached KB solution article.'
                ),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Tags([reporting.Tags.NETWORK]),
                reporting.Flags([reporting.Flags.INHIBITOR])
            ])
Example #24
0
def get_os_release(path):
    """Retrieve data about System OS release from provided file."""
    try:
        with open(path) as f:
            data = dict(l.strip().split('=', 1) for l in f.readlines()
                        if '=' in l)
            return OSRelease(release_id=data.get('ID', '').strip('"'),
                             name=data.get('NAME', '').strip('"'),
                             pretty_name=data.get('PRETTY_NAME',
                                                  '').strip('"'),
                             version=data.get('VERSION', '').strip('"'),
                             version_id=data.get('VERSION_ID', '').strip('"'),
                             variant=data.get('VARIANT', '').strip('"')
                             or None,
                             variant_id=data.get('VARIANT_ID', '').strip('"')
                             or None)
    except IOError as e:
        reporting.create_report([
            reporting.Title('Error while collecting system OS facts'),
            reporting.Summary(str(e)),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.OS_FACTS, reporting.Tags.SANITY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.RelatedResource('file', path)
        ])
        return None
def report_skipped_packages(title,
                            message,
                            package_repo_pairs,
                            remediation=None):
    """Generate report message about skipped packages"""
    package_repo_pairs = sorted(package_repo_pairs)
    summary = '{} {}\n{}'.format(
        len(package_repo_pairs), message, '\n'.join([
            '- {pkg} (repoid: {repo})'.format(pkg=pkg, repo=repo)
            for pkg, repo in package_repo_pairs
        ]))
    report_content = [
        reporting.Title(title),
        reporting.Summary(summary),
        reporting.Severity(reporting.Severity.HIGH),
        reporting.Tags([reporting.Tags.REPOSITORY]),
    ]
    if remediation:
        report_content += [reporting.Remediation(hint=remediation)]
    report_content += [
        reporting.RelatedResource('package', p) for p, _ in package_repo_pairs
    ]
    reporting.create_report(report_content)
    if is_verbose():
        api.current_logger().info(summary)
Example #26
0
def version2_check(info):
    """ Performs all checks for SAP HANA 2 and creates a report if anything unsupported has been detected """
    found = {}
    for instance in info.instances:
        if _manifest_get(instance.manifest, 'release', None) == '1.00':
            continue
        if not _fullfills_hana_min_version(instance):
            _add_hana_details(found, instance)

    if found:
        detected = _create_detected_instances_list(found)
        reporting.create_report([
            reporting.Title('SAP HANA needs to be updated before upgrade'),
            reporting.Summary((
                'A newer version of SAP HANA is required in order continue with the upgrade.'
                ' {min_hana_version} is required for the target version of RHEL.\n\n'
                'The following SAP HANA instances have been detected to be running with a lower version'
                ' than required on the target system:\n'
                '{detected}').format(
                    detected=detected,
                    min_hana_version=SAP_HANA_MINIMAL_VERSION_STRING)),
            reporting.RemediationHint('Update SAP HANA at least to {}'.format(
                SAP_HANA_MINIMAL_VERSION_STRING)),
            reporting.ExternalLink(
                url='https://launchpad.support.sap.com/#/notes/2235581',
                title='SAP HANA: Supported Operating Systems'),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.SANITY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Audience('sysadmin')
        ])
Example #27
0
    def process(self):
        rootdir = next(self.consume(RootDirectory), None)
        if not rootdir:
            raise StopActorExecutionError('Cannot check root symlinks',
                                          details={
                                              'Problem':
                                              'Did not receive a message with '
                                              'root subdirectories'
                                          })
        absolute_links = [
            item for item in rootdir.items
            if item.target and os.path.isabs(item.target)
        ]

        if absolute_links:
            commands = [
                ' '.join([
                    'ln', '-snf',
                    os.path.relpath(item.target, '/'),
                    os.path.join('/', item.name)
                ]) for item in absolute_links
            ]
            remediation = [['sh', '-c', ' && '.join(commands)]]
            reporting.create_report([
                reporting.Title(
                    'Upgrade requires links in root directory to be relative'),
                reporting.Summary(
                    'After rebooting, parts of the upgrade process can fail if symbolic links in / '
                    'point to absolute paths.\n'
                    'Please change these links to relative ones.'),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Flags([reporting.Flags.INHIBITOR]),
                reporting.Remediation(commands=remediation)
            ])
Example #28
0
def version1_check(info):
    """ Creates a report for SAP HANA instances running on version 1 """
    found = {}
    for instance in info.instances:
        if _manifest_get(instance.manifest, 'release') == '1.00':
            _add_hana_details(found, instance)

    if found:
        detected = _create_detected_instances_list(found)
        reporting.create_report([
            reporting.Title(
                'Found SAP HANA 1 which is not supported with the target version of RHEL'
            ),
            reporting.Summary((
                'SAP HANA 1.00 is not supported with the version of RHEL you are upgrading to.\n\n'
                'The following instances have been detected to be version 1.00:\n'
                '{}'.format(detected))),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.RemediationHint((
                'In order to upgrade RHEL, you will have to upgrade your SAP HANA 1.0 software to '
                '{supported}.'.format(
                    supported=SAP_HANA_MINIMAL_VERSION_STRING))),
            reporting.ExternalLink(
                url='https://launchpad.support.sap.com/#/notes/2235581',
                title='SAP HANA: Supported Operating Systems'),
            reporting.Tags([reporting.Tags.SANITY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Audience('sysadmin')
        ])
def process():
    # blacklist CRB repo if optional repo is not enabled
    reposid_blacklist = _get_disabled_optional_repo()
    if reposid_blacklist:
        api.current_logger().info(
            "The optional repository is not enabled. Blacklisting the CRB repository."
        )
        api.produce(RepositoriesBlacklisted(repoids=reposid_blacklist))

        report = [
            reporting.Title("Excluded RHEL 8 repositories"),
            reporting.Summary(
                "The following repositories are not supported by "
                "Red Hat and are excluded from the list of repositories "
                "used during the upgrade.\n- {}".format(
                    "\n- ".join(reposid_blacklist))),
            reporting.Severity(reporting.Severity.INFO),
            reporting.Tags([reporting.Tags.REPOSITORY]),
            reporting.Flags([reporting.Flags.FAILURE]),
            reporting.ExternalLink(
                url=("https://access.redhat.com/documentation/en-us/"
                     "red_hat_enterprise_linux/8/html/package_manifest/"
                     "codereadylinuxbuilder-repository."),
                title="CodeReady Linux Builder repository",
            ),
        ]
        reporting.create_report(report)
Example #30
0
    def produce_suggested_configuration(self, model, confirmed, command):
        self.produce(
            AuthselectDecision(
                confirmed=confirmed
            )
        )
        if confirmed:
            create_report([
                reporting.Title(
                    'Authselect will be used to configure PAM and nsswitch.conf.'
                ),
                reporting.Summary(
                    'There is a new tool called authselect in RHEL8 that '
                    'replaced authconfig. The upgrade process suggested '
                    'an authselect profile that is similar to your '
                    'current configuration and your system will be switched '
                    'to this profile. Authselect call is: {}. The process will '
                    'also enable "oddjobd" systemd service on startup'.format(command)
                ),
                reporting.Tags([
                    reporting.Tags.AUTHENTICATION,
                    reporting.Tags.SECURITY,
                    reporting.Tags.TOOLS
                ])
            ] + resources)

        else:
            create_report([
                reporting.Title(
                    'Current PAM and nsswitch.conf configuration will be kept.'
                ),
                reporting.Summary(
                    'There is a new tool called authselect in RHEL8 that '
                    'replaced authconfig. The upgrade process suggested '
                    'an authselect profile that is similar to your '
                    'current configuration. However this suggestion was '
                    'refused therefore existing configuration will be kept '
                    'intact.',
                ),
                reporting.Tags([
                    reporting.Tags.AUTHENTICATION,
                    reporting.Tags.SECURITY,
                    reporting.Tags.TOOLS
                ]),
                reporting.Remediation(commands=[[command]]),
                reporting.Severity(reporting.Severity.MEDIUM)
            ] + resources)