Example #1
0
def check_chrony(chrony_installed):
    """Report potential issues in chrony configuration."""
    if not chrony_installed:
        api.current_logger().info('chrony package is not installed')
        return

    if is_config_default():
        reporting.create_report([
            reporting.Title('chrony using default configuration'),
            reporting.Summary(
                'default chrony configuration in RHEL8 uses leapsectz directive, which cannot be used with '
                'leap smearing NTP servers, and uses a single pool directive instead of four server directives'
            ),
            reporting.Severity(reporting.Severity.MEDIUM),
            reporting.Tags(
                [reporting.Tags.SERVICES, reporting.Tags.TIME_MANAGEMENT])
        ] + related)

    else:
        reporting.create_report([
            reporting.Title('chrony using non-default configuration'),
            reporting.Summary('chrony behavior will not change in RHEL8'),
            reporting.Severity(reporting.Severity.LOW),
            reporting.Tags(
                [reporting.Tags.SERVICES, reporting.Tags.TIME_MANAGEMENT])
        ] + related)
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)
    ])
Example #3
0
    def process(self):
        for decision in self.consume(SelinuxRelabelDecision):
            if decision.set_relabel:
                try:
                    with open('/.autorelabel', 'w'):
                        pass
                    create_report([
                        reporting.Title('SElinux scheduled for relabelling'),
                        reporting.Summary(
                            '/.autorelabel file touched on root in order to schedule SElinux relabelling.'
                        ),
                        reporting.Severity(reporting.Severity.INFO),
                        reporting.Tags(COMMON_REPORT_TAGS),
                    ] + related)

                except EnvironmentError as e:
                    # FIXME: add an "action required" flag later
                    create_report([
                        reporting.Title(
                            'Could not schedule SElinux for relabelling'),
                        reporting.Summary(
                            '/.autorelabel file could not be created: {}.'.
                            format(e)),
                        reporting.Severity(reporting.Severity.HIGH),
                        reporting.Tags(COMMON_REPORT_TAGS),
                        reporting.Remediation(
                            hint=
                            'Please set autorelabelling manually after the upgrade.'
                        ),
                        reporting.Flags([reporting.Flags.FAILURE])
                    ] + related)
                    self.log.critical(
                        'Could not schedule SElinux for relabelling: %s.' % e)
Example #4
0
    def process(self):
        if architecture.matches_architecture(architecture.ARCH_S390X):
            # s390x archs use ZIPL instead of GRUB
            return

        ff = next(self.consume(FirmwareFacts), None)
        if ff and ff.firmware == 'bios':
            dev = next(self.consume(GrubDevice), None)
            if dev:
                self.produce(UpdateGrub(grub_device=dev.grub_device))
                create_report([
                    reporting.Title(
                        'GRUB core will be updated during upgrade'),
                    reporting.Summary(GRUB_SUMMARY),
                    reporting.Severity(reporting.Severity.HIGH),
                    reporting.Tags([reporting.Tags.BOOT]),
                ])
            else:
                create_report([
                    reporting.Title(
                        'Leapp could not identify where GRUB core is located'),
                    reporting.Summary(
                        'We assume GRUB core is located on the same device as /boot. Leapp needs to '
                        'update GRUB core as it is not done automatically on legacy (BIOS) systems. '
                    ),
                    reporting.Severity(reporting.Severity.HIGH),
                    reporting.Tags([reporting.Tags.BOOT]),
                    reporting.Remediation(
                        hint=
                        'Please run "grub2-install <GRUB_DEVICE> command manually after upgrade'
                    ),
                ])
Example #5
0
def process():
    conflicts = _detect_dracut_modules_conflicts(UpgradeInitramfsTasks)
    if conflicts:
        report = [
            reporting.Title(
                'Conflicting requirements of dracut modules for the upgrade initramfs'
            ),
            reporting.Summary(
                SUMMARY_DRACUT_FMT.format(_printable_modules(conflicts))),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.SANITY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
        ]
        reporting.create_report(report)

    conflicts = _detect_dracut_modules_conflicts(TargetInitramfsTasks)
    if conflicts:
        report = [
            reporting.Title(
                'Conflicting requirements of dracut modules for the target initramfs'
            ),
            reporting.Summary(
                SUMMARY_DRACUT_FMT.format(_printable_modules(conflicts))),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.SANITY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
        ]
        reporting.create_report(report)
Example #6
0
def check_memcached(memcached_installed):
    """Report potential issues in memcached configuration."""
    if not memcached_installed:
        api.current_logger().info('memcached package is not installed')
        return

    default_memcached_conf = is_sysconfig_default()
    disabled_udp_port = is_udp_disabled()

    if default_memcached_conf:
        reporting.create_report([
            reporting.Title('memcached service is using default configuration'),
            reporting.Summary('memcached in RHEL8 listens on loopback only and has UDP port disabled by default'),
            reporting.Severity(reporting.Severity.MEDIUM),
            reporting.Tags(COMMON_REPORT_TAGS),
        ] + related)

    elif not disabled_udp_port:
        reporting.create_report([
            reporting.Title('memcached has enabled UDP port'),
            reporting.Summary(
                'memcached in RHEL7 has UDP port enabled by default, but it is disabled by default in RHEL8'
            ),
            reporting.Severity(reporting.Severity.MEDIUM),
            reporting.Tags(COMMON_REPORT_TAGS),
        ] + related)

    else:
        reporting.create_report([
            reporting.Title('memcached has already disabled UDP port'),
            reporting.Summary('memcached in RHEL8 has UDP port disabled by default'),
            reporting.Severity(reporting.Severity.LOW),
            reporting.Tags(COMMON_REPORT_TAGS),
        ] + related)
Example #7
0
    def process(self):
        openssh_messages = self.consume(OpenSshConfig)
        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.'})

        resources = [
            reporting.RelatedResource('package', 'openssh-server'),
            reporting.RelatedResource('file', '/etc/ssh/sshd_config')
        ]
        if not config.permit_root_login:
            # TODO find out whether the file was modified and will be
            # replaced by the update. If so, this message is bogus
            create_report([
                reporting.Title(
                    'Possible problems with remote login using root account'),
                reporting.Summary(
                    'OpenSSH configuration file does not explicitly state '
                    'the option PermitRootLogin in sshd_config file, '
                    'which will default in RHEL8 to "prohibit-password".'),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Tags(COMMON_REPORT_TAGS),
                reporting.Remediation(
                    hint='If you depend on remote root logins using '
                    'passwords, consider setting up a different '
                    'user for remote administration or adding '
                    '"PermitRootLogin yes" to sshd_config.'),
                reporting.Flags([reporting.Flags.INHIBITOR])
            ] + resources)

        # Check if there is at least one PermitRootLogin other than "no"
        # in match blocks (other than Match All).
        # This usually means some more complicated setup depending on the
        # default value being globally "yes" and being overwritten by this
        # match block
        if semantics_changes(config):
            create_report([
                reporting.Title('OpenSSH configured to allow root login'),
                reporting.Summary(
                    'OpenSSH is configured to deny root logins in match '
                    'blocks, but not explicitly enabled in global or '
                    '"Match all" context. This update changes the '
                    'default to disable root logins using paswords '
                    'so your server migth get inaccessible.'),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Tags(COMMON_REPORT_TAGS),
                reporting.Remediation(
                    hint='Consider using different user for administrative '
                    'logins or make sure your configration file '
                    'contains the line "PermitRootLogin yes" '
                    'in global context if desired.'),
                reporting.Flags([reporting.Flags.INHIBITOR])
            ] + resources)
def process():
    kernel_name = 'kernel'
    if version.is_rhel_realtime():
        api.current_logger().info('The Real Time kernel boot detected.')
        kernel_name = 'kernel-rt'

    pkgs = get_pkgs(kernel_name)
    if not pkgs:
        # Hypothatical, user is not allowed to install any kernel that is not signed by RH
        # In case we would like to be cautious, we could check whether there are no other
        # kernels installed as well.
        api.current_logger().error(
            'Cannot find any installed kernel signed by Red Hat.')
        raise StopActorExecutionError(
            'Cannot find any installed kernel signed by Red Hat.')

    if len(pkgs) > 1 and architecture.matches_architecture(
            architecture.ARCH_S390X):
        # It's temporary solution, so no need to try automatize everything.
        title = 'Multiple kernels installed'
        summary = (
            'The upgrade process does not handle well the case when multiple kernels'
            ' are installed on s390x. There is a severe risk of the bootloader configuration'
            ' getting corrupted during the upgrade.')
        remediation = (
            'Boot into the most up-to-date kernel and remove all older'
            ' kernels installed on the machine before running Leapp again.')
        reporting.create_report([
            reporting.Title(title),
            reporting.Summary(summary),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.KERNEL, reporting.Tags.BOOT]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Remediation(hint=remediation),
            reporting.RelatedResource('package', 'kernel')
        ])

    current_evr = get_current_kernel_evr()
    newest_evr = get_newest_evr(pkgs)

    api.current_logger().debug('Current kernel EVR: {}'.format(current_evr))
    api.current_logger().debug('Newest kernel EVR: {}'.format(newest_evr))

    if current_evr != newest_evr:
        title = 'Newest installed kernel not in use'
        summary = ('To ensure a stable upgrade, the machine needs to be'
                   ' booted into the latest installed kernel.')
        remediation = ('Boot into the most up-to-date kernel installed'
                       ' on the machine before running Leapp again.')
        reporting.create_report([
            reporting.Title(title),
            reporting.Summary(summary),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.KERNEL, reporting.Tags.BOOT]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Remediation(hint=remediation),
            reporting.RelatedResource('package', 'kernel')
        ])
Example #9
0
    def process(self):
        unsupported_tables = []
        unsupported_ipset_types = []
        list_separator_fmt = '\n    -'
        for facts in self.consume(FirewalldFacts):
            for table in facts.ebtablesTablesInUse:
                if not private.isEbtablesTableSupported(table):
                    unsupported_tables.append(table)
            for ipset_type in facts.ipsetTypesInUse:
                if not private.isIpsetTypeSupportedByNftables(ipset_type):
                    unsupported_ipset_types.append(ipset_type)

        if unsupported_tables:
            format_tuple = (
                list_separator_fmt,
                list_separator_fmt.join(list(set(unsupported_tables))),
            )
            create_report([
                reporting.Title(
                    'Firewalld is using an unsupported ebtables table.'),
                reporting.Summary(
                    'ebtables in RHEL-8 does not support these tables:{}{}'.
                    format(*format_tuple)),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Tags([
                    reporting.Tags.FIREWALL, reporting.Tags.SECURITY,
                    reporting.Tags.NETWORK
                ]),
                reporting.Flags([reporting.Flags.INHIBITOR]),
                reporting.Remediation(
                    hint=
                    'Remove firewalld direct rules that use these ebtables tables:{}{}'
                    .format(*format_tuple))
            ] + related)

        if unsupported_ipset_types:
            format_tuple = (
                list_separator_fmt,
                list_separator_fmt.join(list(set(unsupported_ipset_types))),
            )
            create_report([
                reporting.Title(
                    'Firewalld is using an unsupported ipset type.'),
                reporting.Summary(
                    'These ipset types are not supported by firewalld\'s nftables backend:{}{}'
                    .format(*format_tuple)),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Tags([
                    reporting.Tags.FIREWALL, reporting.Tags.SECURITY,
                    reporting.Tags.NETWORK
                ]),
                reporting.Flags([reporting.Flags.INHIBITOR]),
                reporting.Remediation(
                    hint='Remove ipsets of these types from firewalld:{}{}'.
                    format(*format_tuple))
            ] + related)
Example #10
0
 def process(self):
     arch = self.configuration.architecture
     for provider, info in rhui.RHUI_CLOUD_MAP[arch].items():
         if has_package(InstalledRPM, info['el7_pkg']):
             if not rhsm.skip_rhsm():
                 create_report([
                     reporting.Title(
                         'Upgrade initiated with RHSM on public cloud with RHUI infrastructure'
                     ),
                     reporting.Summary(
                         'Leapp detected this system is on public cloud with RHUI infrastructure '
                         'but the process was initiated without "--no-rhsm" command line option '
                         'which implies RHSM usage (valid subscription is needed).'
                     ),
                     reporting.Severity(reporting.Severity.INFO),
                     reporting.Tags([reporting.Tags.PUBLIC_CLOUD]),
                 ])
                 return
             # AWS RHUI package is provided and signed by RH but the Azure one not
             if not has_package(InstalledRPM, info['leapp_pkg']):
                 create_report([
                     reporting.Title('Package "{}" is missing'.format(
                         info['leapp_pkg'])),
                     reporting.Summary(
                         'On {} using RHUI infrastructure, a package "{}" is needed for'
                         'in-place upgrade'.format(provider.upper(),
                                                   info['leapp_pkg'])),
                     reporting.Severity(reporting.Severity.HIGH),
                     reporting.RelatedResource('package',
                                               info['leapp_pkg']),
                     reporting.Flags([reporting.Flags.INHIBITOR]),
                     reporting.Tags(
                         [reporting.Tags.PUBLIC_CLOUD,
                          reporting.Tags.RHUI]),
                     reporting.Remediation(commands=[[
                         'yum', 'install', '-y', info['leapp_pkg']
                     ]])
                 ])
                 return
             if provider == 'aws':
                 # We have to disable Amazon-id plugin in the initramdisk phase as the network
                 # is down at the time
                 self.produce(
                     DNFPluginTask(name='amazon-id',
                                   disable_in=['upgrade']))
             # if RHEL7 and RHEL8 packages differ, we cannot rely on simply updating them
             if info['el7_pkg'] != info['el8_pkg']:
                 self.produce(
                     RpmTransactionTasks(to_install=[info['el8_pkg']]))
                 self.produce(
                     RpmTransactionTasks(to_remove=[info['el7_pkg']]))
             self.produce(RHUIInfo(provider=provider))
             self.produce(
                 RequiredTargetUserspacePackages(
                     packages=[info['el8_pkg']]))
             return
Example #11
0
    def process(self):

        fact = next(self.consume(SELinuxFacts), None)
        if not fact:
            return

        enabled = fact.enabled
        conf_status = fact.static_mode

        if conf_status == 'disabled':
            if enabled:
                create_report([
                    reporting.Title(
                        'SElinux disabled in configuration file but currently enabled'
                    ),
                    reporting.Summary(
                        'This message is to inform user about non-standard SElinux configuration.'
                    ),
                    reporting.Severity(reporting.Severity.LOW),
                    reporting.Tags(
                        [reporting.Tags.SELINUX, reporting.Tags.SECURITY])
                ])
            create_report([
                reporting.Title('SElinux disabled'),
                reporting.Summary('SElinux disabled, continuing...'),
                reporting.Tags(
                    [reporting.Tags.SELINUX, reporting.Tags.SECURITY])
            ])
            return

        if conf_status in ('enforcing', 'permissive'):
            self.produce(SelinuxRelabelDecision(set_relabel=True))
            create_report([
                reporting.Title('SElinux relabeling has been scheduled'),
                reporting.Summary(
                    'SElinux relabeling has been scheduled as the status was permissive/enforcing.'
                ),
                reporting.Severity(reporting.Severity.INFO),
                reporting.Tags(
                    [reporting.Tags.SELINUX, reporting.Tags.SECURITY])
            ])

        if conf_status == 'enforcing':
            self.produce(SelinuxPermissiveDecision(set_permissive=True))
            create_report([
                reporting.Title('SElinux will be set to permissive mode'),
                reporting.Summary(
                    'SElinux will be set to permissive mode. Current mode: enforcing. This action is '
                    'required by the upgrade process'),
                reporting.Severity(reporting.Severity.LOW),
                reporting.Tags(
                    [reporting.Tags.SELINUX, reporting.Tags.SECURITY])
            ])
Example #12
0
    def produce_current_configuration(self, model):
        self.produce(
            AuthselectDecision(
                confirmed=False
            )
        )

        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 was unable '
                'to find an authselect profile that would be equivalent '
                'to your current configuration. Therefore your '
                'configuration will be left intact.'
            ),
            reporting.Tags([
                reporting.Tags.AUTHENTICATION,
                reporting.Tags.SECURITY,
                reporting.Tags.TOOLS
            ]),
            reporting.Severity(reporting.Severity.INFO)
        ] + resources)
Example #13
0
    def produce_authconfig_configuration(self, model, command):
        self.produce(
            AuthselectDecision(
                confirmed=True
            )
        )

        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 detected '
                'that authconfig was used to generate current '
                'configuration and it will automatically convert it '
                'to authselect. 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)
Example #14
0
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))
    ])
Example #15
0
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 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 #16
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
Example #17
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)
Example #18
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 #19
0
    def process(self):

        hint = 'In order to unload the module from the running system, check the accompanied command.'
        command = ['modprobe', '-r', 'btrfs']

        for fact in self.consume(ActiveKernelModulesFacts):
            for active_module in fact.kernel_modules:
                if active_module.filename == 'btrfs':
                    create_report([
                        reporting.Title('Btrfs has been removed from RHEL8'),
                        reporting.Summary(
                            'The Btrfs file system was introduced as Technology Preview with the '
                            'initial release of Red Hat Enterprise Linux 6 and Red Hat Enterprise Linux 7. As of '
                            'versions 6.6 and 7.4 this technology has been deprecated and removed in RHEL8.'
                        ),
                        reporting.ExternalLink(
                            title='Considerations in adopting RHEL 8 - btrfs has been removed.',
                            url='https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/considerations_in_adopting_rhel_8/file-systems-and-storage_considerations-in-adopting-rhel-8#btrfs-has-been-removed_file-systems-and-storage'  # noqa: E501; pylint: disable=line-too-long
                        ),
                        reporting.ExternalLink(
                            title='How do I prevent a kernel module from loading automatically?',
                            url='https://access.redhat.com/solutions/41278'
                        ),
                        reporting.Severity(reporting.Severity.HIGH),
                        reporting.Flags([reporting.Flags.INHIBITOR]),
                        reporting.Tags([reporting.Tags.FILESYSTEM]),
                        reporting.Remediation(hint=hint, commands=[command]),
                        reporting.RelatedResource('kernel-driver', 'btrfs')
                    ])
                    break
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()
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 #22
0
    def process(self):
        model = next(self.consume(SSSDConfig8to9), None)
        if not model:
            return

        # enable_files_domain is set explicitly, change of default has no effect
        if model.enable_files_domain_set:
            return

        # there is explicit files domain, implicit files domain has no effect
        if model.explicit_files_domain:
            return

        # smartcard authentication is disabled, implicit files domain has no effect
        if not model.pam_cert_auth:
            return

        create_report([
            reporting.Title('SSSD implicit files domain is now disabled by default.'),
            reporting.Summary('Default value of [sssd]/enable_files_domain has '
                              'changed from true to false.'),
            reporting.Tags(COMMON_REPORT_TAGS),
            reporting.Remediation(
                hint='If you use smartcard authentication for local users, '
                     'set this option to true explicitly and call '
                     '"authselect enable-feature with-files-domain".'
            ),
            reporting.Severity(reporting.Severity.MEDIUM)
        ] + related)
Example #23
0
def process():
    if not architecture.matches_architecture(architecture.ARCH_S390X):
        return

    pkgs = _get_kernel_rpms()
    if not pkgs:
        # Hypothatical, user is not allowed to install any kernel that is not signed by RH
        # In case we would like to be cautious, we could check whether there are no other
        # kernels installed as well.
        api.current_logger().log.error(
            'Cannot find any installed kernel signed by Red Hat.')
        raise StopActorExecutionError(
            'Cannot find any installed kernel signed by Red Hat.')
    if len(pkgs) > 1:
        # It's temporary solution, so no need to try automatize everything.
        title = 'Multiple kernels installed'
        summary = (
            'The upgrade process does not handle well the case when multiple kernels'
            ' are installed on s390x. There is a severe risk of the bootloader configuration'
            ' getting corrupted during the upgrade.')
        remediation = (
            'Boot into the most up-to-date kernel and remove all older'
            ' kernels installed on the machine before running Leapp again.')
        reporting.create_report([
            reporting.Title(title),
            reporting.Summary(summary),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags([reporting.Tags.KERNEL, reporting.Tags.BOOT]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Remediation(hint=remediation),
            reporting.RelatedResource('package', 'kernel')
        ])
Example #24
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
            ])
Example #25
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 #26
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 #27
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')
        ])
Example #28
0
    def process(self):
        if not architecture.matches_architecture(architecture.ARCH_S390X):
            return

        cmdline = library.get_kernel_cmdline()
        if library.znet_is_set(cmdline):
            _report = [
                reporting.Title(
                    'Detected the rd.znet parameter in kernel cmdline'),
                reporting.Severity(reporting.Severity.HIGH),
                reporting.Tags(([reporting.Tags.SANITY])),
                reporting.Flags(([reporting.Flags.INHIBITOR])),
                reporting.Summary(
                    'Upgrade on s390x machines with the rd.znet kernel'
                    ' parameter is not supported and the upgrade has been'
                    ' inhibited.')
            ]

            if not library.vlan_is_used():
                hint = (
                    'If you want to continue, remove the rd.znet parameter from'
                    ' the kernel cmdline using grubby and zipl tools and reboot.'
                    ' But only in case you are sure you do not the parameter'
                    ' specified to have working network. E.g. in case you are'
                    ' using VLAN, you should not do that.')
                _report.append(reporting.Remediation(hint=hint))
            reporting.create_report(_report)
def inhibit(node_type):
    create_report([
        reporting.Title("Use of HA cluster detected. Upgrade can't proceed."),
        reporting.Summary(
            "HA cluster is not supported by the inplace upgrade.\n"
            "HA cluster configuration file(s) found."
            " It seems to be a cluster {0}.".format(node_type)),
        reporting.Severity(reporting.Severity.HIGH),
        reporting.Tags([reporting.Tags.HIGH_AVAILABILITY]),
        reporting.Flags([reporting.Flags.INHIBITOR]),
        reporting.ExternalLink(
            url="https://access.redhat.com/articles/2059253",
            title=(
                "Recommended Practices for Applying Software Updates"
                " to a RHEL High Availability or Resilient Storage Cluster"),
        ),
        reporting.Remediation(
            hint=(
                "Destroy the existing HA cluster"
                " or (if you have already removed HA cluster packages) remove"
                " configuration files {0} and {1}".format(
                    CIB_LOCATION,
                    COROSYNC_CONF_LOCATION,
                )),
            commands=[[
                "sh", "-c",
                "pcs cluster stop --all --wait && pcs cluster destroy --all"
            ]]),
        reporting.RelatedResource('file', COROSYNC_CONF_LOCATION),
        reporting.RelatedResource('file', CIB_LOCATION)
    ])
Example #30
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", "-y", "ipa-server"]],
        ),
        reporting.ExternalLink(
            url=MIGRATION_GUIDES[get_source_major_version()],
            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)