Ejemplo n.º 1
0
    def _consume_data(self):
        """
        Wrapper function to consume majority input data.

        It doesn't consume TargetRepositories, which are consumed in the
        own function.
        """
        self.packages = {'dnf'}
        for message in api.consume(RequiredTargetUserspacePackages):
            self.packages.update(message.packages)

        # Get the RHSM information (available repos, attached SKUs, etc.) of the source (RHEL 7) system
        self.rhsm_info = next(api.consume(RHSMInfo), None)
        self.rhui_info = next(api.consume(RHUIInfo), None)
        if not self.rhsm_info and not rhsm.skip_rhsm():
            api.current_logger().warning(
                'Could not receive RHSM information - Is this system registered?'
            )
            raise StopActorExecution()
        if rhsm.skip_rhsm() and self.rhsm_info:
            # this should not happen. if so, raise an error as something in
            # other actors is wrong really
            raise StopActorExecutionError(
                "RHSM is not handled but the RHSMInfo message has been produced."
            )

        self.custom_repofiles = list(api.consume(CustomTargetRepositoryFile))
        self.xfs_info = next(api.consume(XFSPresence), XFSPresence())
        self.storage_info = next(api.consume(StorageInfo), None)
        if not self.storage_info:
            raise StopActorExecutionError(
                'No storage info available cannot proceed.')
Ejemplo n.º 2
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.º 3
0
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()
Ejemplo n.º 4
0
def inhibit_upgrade(title):
    summary = 'Read documentation at: https://access.redhat.com/articles/3664871 for more information ' \
        'about how to retrieve the files'
    reporting.report_generic(title=title,
                             summary=summary,
                             severity='high',
                             flags=['inhibitor'])
    raise StopActorExecution()
Ejemplo n.º 5
0
def skip_check():
    """ Check if has environment variable to skip this actor checks """
    if os.getenv('LEAPP_SKIP_CHECK_SIGNED_PACKAGES'):
        reporting.report_generic(
            title='Skipped signed packages check',
            severity='low',
            summary=
            'Signed packages check skipped via LEAPP_SKIP_CHECK_SIGNED_PACKAGES env var'
        )
        raise StopActorExecution()
Ejemplo n.º 6
0
def inhibit_upgrade(title):
    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.UPGRADE_PROCESS]),
        reporting.Flags([reporting.Flags.INHIBITOR])
    ])
    raise StopActorExecution()
Ejemplo n.º 7
0
def get_boot_partition():
    """
    Get /boot partition
    """
    try:
        # call grub2-probe to identify /boot partition
        result = run(['grub2-probe', '--target=device', '/boot'])
    except CalledProcessError:
        api.current_logger().warning(
            'Could not get name of underlying /boot partition')
        raise StopActorExecution()
    return result['stdout'].strip()
Ejemplo n.º 8
0
def has_grub(blk_dev):
    """
    Check whether GRUB is present on block device
    """
    try:
        blk = os.open(blk_dev, os.O_RDONLY)
        mbr = os.read(blk, 512)
    except OSError:
        api.current_logger().warning(
            'Could not read first sector of {} in order to identify the bootloader'
            .format(blk_dev))
        raise StopActorExecution()
    os.close(blk)
    return 'GRUB' in mbr
Ejemplo n.º 9
0
def scan_events(path):
    """ Scan JSON file containing PES events """
    try:
        events = parse_file(path)
    except (ValueError, KeyError):
        title = 'Missing/Invalid PES data file ({})'.format(path)
        summary = 'Read documentation at: https://access.redhat.com/articles/3664871 for more information ' \
            'about how to retrieve the files'
        reporting.report_generic(title=title,
                                 summary=summary,
                                 severity='high',
                                 flags=['inhibitor'])
        raise StopActorExecution()

    process_events(filter_events(events))
Ejemplo n.º 10
0
def has_grub(blk_dev):
    """
    Check whether GRUB is present on block device
    """
    try:
        result = run([
            'dd', 'status=none', 'if={}'.format(blk_dev), 'bs=512', 'count=1'
        ],
                     encoding=None)
    except CalledProcessError:
        api.current_logger().warning(
            'Could not read first sector of {} in order to identify the bootloader'
            .format(blk_dev))
        raise StopActorExecution()
    return b'GRUB' in result['stdout']
Ejemplo n.º 11
0
def blk_dev_from_partition(partition):
    """
    Find parent device of /boot partition
    """
    try:
        result = run(['lsblk', '-spnlo', 'name', partition])
    except CalledProcessError:
        api.current_logger().warning(
            'Could not get parent device of {} partition'.format(partition))
        raise StopActorExecution()
    # lsblk "-s" option prints dependencies in inverse order, so the parent device will always
    # be the last or the only device.
    # Command result example:
    # 'result', {'signal': 0, 'pid': 3872, 'exit_code': 0, 'stderr': u'', 'stdout': u'/dev/vda1\n/dev/vda\n'}
    return result['stdout'].strip().split()[-1]
Ejemplo n.º 12
0
    def _consume_data(self):
        """
        Wrapper function to consume majority input data.

        It doesn't consume TargetRepositories, which are consumed in the
        own function.
        """
        self.packages = {'dnf'}
        self.files = []
        _cftuples = set()

        def _update_files(copy_files):
            # add just uniq CopyFile objects to omit duplicate copying of files
            for cfile in copy_files:
                cftuple = (cfile.src, cfile.dst)
                if cftuple not in _cftuples:
                    _cftuples.add(cftuple)
                    self.files.append(cfile)

        for task in api.consume(TargetUserSpacePreupgradeTasks):
            self.packages.update(task.install_rpms)
            _update_files(task.copy_files)

        for message in api.consume(RequiredTargetUserspacePackages):
            self.packages.update(message.packages)

        # Get the RHSM information (available repos, attached SKUs, etc.) of the source system
        self.rhsm_info = next(api.consume(RHSMInfo), None)
        self.rhui_info = next(api.consume(RHUIInfo), None)
        if not self.rhsm_info and not rhsm.skip_rhsm():
            api.current_logger().warning(
                'Could not receive RHSM information - Is this system registered?'
            )
            raise StopActorExecution()
        if rhsm.skip_rhsm() and self.rhsm_info:
            # this should not happen. if so, raise an error as something in
            # other actors is wrong really
            raise StopActorExecutionError(
                "RHSM is not handled but the RHSMInfo message has been produced."
            )

        self.custom_repofiles = list(api.consume(CustomTargetRepositoryFile))
        self.xfs_info = next(api.consume(XFSPresence), XFSPresence())
        self.storage_info = next(api.consume(StorageInfo), None)
        if not self.storage_info:
            raise StopActorExecutionError(
                'No storage info available cannot proceed.')
Ejemplo n.º 13
0
def get_events(pes_events_filepath):
    """
    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_file(pes_events_filepath)
    except (ValueError, KeyError):
        title = 'Missing/Invalid PES data file ({})'.format(
            pes_events_filepath)
        summary = 'Read documentation at: https://access.redhat.com/articles/3664871 for more information ' \
            'about how to retrieve the files'
        reporting.report_generic(title=title,
                                 summary=summary,
                                 severity='high',
                                 flags=['inhibitor'])
        raise StopActorExecution()
Ejemplo n.º 14
0
def _consume_data():
    """Wrapper function to consume all input data."""
    packages = {'dnf'}
    for message in api.consume(RequiredTargetUserspacePackages):
        packages.update(message.packages)

    # Get the RHSM information (available repos, attached SKUs, etc.) of the source (RHEL 7) system
    rhsm_info = next(api.consume(RHSMInfo), None)
    if not rhsm_info and not rhsm.skip_rhsm():
        api.current_logger().warn(
            'Could not receive RHSM information - Is this system registered?')
        raise StopActorExecution()

    xfs_info = next(api.consume(XFSPresence), XFSPresence())
    storage_info = next(api.consume(StorageInfo), None)
    if not storage_info:
        raise StopActorExecutionError(
            'No storage info available cannot proceed.')
    return packages, rhsm_info, xfs_info, storage_info
Ejemplo n.º 15
0
def check_os_version(supported_version):
    """ Check OS version and inhibit upgrade if not the same as supported ones """
    if not isinstance(supported_version, dict):
        api.current_logger().warning('The supported version value is invalid.')
        raise StopActorExecution()

    facts_messages = api.consume(OSReleaseFacts)
    facts = next(facts_messages, None)
    if list(facts_messages):
        api.current_logger().warning(
            'Unexpectedly received more than one OSReleaseFacts message.')
    if not facts:
        raise StopActorExecutionError(
            'Could not check OS version',
            details={'details': 'No OSReleaseFacts facts found.'})

    if facts.release_id not in supported_version:
        reporting.report_generic(
            title='Unsupported OS',
            summary='Only RHEL is supported by the upgrade process',
            flags=['inhibitor'],
        )
        return

    if not isinstance(supported_version[facts.release_id], list):
        raise StopActorExecutionError(
            'Invalid versions',
            details={
                'details':
                'OS versions are invalid, please provide a valid list.'
            },
        )

    if facts.version_id not in supported_version[facts.release_id]:
        reporting.report_generic(
            title='Unsupported OS version',
            summary='The supported OS versions for the upgrade process: {}'.
            format(', '.join(supported_version[facts.release_id])),
            flags=['inhibitor'],
        )
Ejemplo n.º 16
0
def _get_rhsm_available_repoids(context):
    target_major_version = get_target_major_version()
    # FIXME: check that required repo IDs (baseos, appstream)
    # + or check that all required RHEL repo IDs are available.
    if rhsm.skip_rhsm():
        return set()
    # Get the RHSM repos available in the target RHEL container
    # TODO: very similar thing should happens for all other repofiles in container
    #
    repoids = rhsm.get_available_repo_ids(context)
    if not repoids or len(repoids) < 2:
        reporting.create_report([
            reporting.Title(
                'Cannot find required basic RHEL target repositories.'),
            reporting.Summary(
                'This can happen when a repository ID was entered incorrectly either while using the --enablerepo'
                ' option of leapp or in a third party actor that produces a CustomTargetRepositoryMessage.'
            ),
            reporting.Tags([reporting.Tags.REPOSITORY]),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Remediation(hint=(
                'It is required to have RHEL repositories on the system'
                ' provided by the subscription-manager unless the --no-rhsm'
                ' option is specified. You might be missing a valid SKU for'
                ' the target system or have a failed network connection.'
                ' Check whether your system is attached to a valid SKU that is'
                ' providing RHEL {} repositories.'
                ' If you are using Red Hat Satellite, read the upgrade documentation'
                ' to set up Satellite and the system properly.'
            ).format(target_major_version)),
            reporting.ExternalLink(
                # TODO: How to handle different documentation links for each version?
                url='https://red.ht/preparing-for-upgrade-to-rhel8',
                title='Preparing for the upgrade')
        ])
        raise StopActorExecution()
    return set(repoids)
Ejemplo n.º 17
0
def check_os_version(supported_version):
    """ Check OS version and inhibit upgrade if not the same as supported ones """
    if not isinstance(supported_version, dict):
        api.current_logger().warning('The supported version value is invalid.')
        raise StopActorExecution()

    release_id, version_id = version.current_version()

    if not version.matches_release(supported_version.keys(), release_id):
        reporting.create_report([
            reporting.Title('Unsupported OS'),
            reporting.Summary('Only RHEL is supported by the upgrade process'),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags(COMMON_REPORT_TAGS),
            reporting.Flags([reporting.Flags.INHIBITOR])
        ] + related)

        return

    if not isinstance(supported_version[release_id], list):
        raise StopActorExecutionError(
            'Invalid versions',
            details={'details': 'OS versions are invalid, please provide a valid list.'},
        )

    if not version.matches_version(supported_version[release_id], version_id):
        reporting.create_report([
            reporting.Title('Unsupported OS version'),
            reporting.Summary(
                'The supported OS versions for the upgrade process: {}'.format(
                    ', '.join(supported_version[release_id])
                )
            ),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Tags(COMMON_REPORT_TAGS),
            reporting.Flags([reporting.Flags.INHIBITOR])
        ] + related)
Ejemplo n.º 18
0
def gather_target_repositories(context, indata):
    """
    Get available required target repositories and inhibit or raise error if basic checks do not pass.

    In case of repositories provided by Red Hat, it's checked whether the basic
    required repositories are available (or at least defined) in the given
    context. If not, raise StopActorExecutionError.

    For the custom target repositories we expect all of them have to be defined.
    If any custom target repository is missing, raise StopActorExecutionError.

    If any repository is defined multiple times, produce the inhibitor Report
    msg.

    :param context: An instance of a mounting.IsolatedActions class
    :type context: mounting.IsolatedActions class
    :return: List of target system repoids
    :rtype: List(string)
    """
    rh_available_repoids = _get_rh_available_repoids(context, indata)
    all_available_repoids = _get_all_available_repoids(context)

    target_repoids = []
    missing_custom_repoids = []
    for target_repo in api.consume(TargetRepositories):
        for rhel_repo in target_repo.rhel_repos:
            if rhel_repo.repoid in rh_available_repoids:
                target_repoids.append(rhel_repo.repoid)
            else:
                # TODO: We shall report that the RHEL repos that we deem necessary for
                # the upgrade are not available; but currently it would just print bunch of
                # data everytime as we maps EUS and other repositories as well. But these
                # do not have to be necessary available on the target system in the time
                # of the upgrade. Let's skip it for now until it's clear how we will deal
                # with it.
                pass
        for custom_repo in target_repo.custom_repos:
            if custom_repo.repoid in all_available_repoids:
                target_repoids.append(custom_repo.repoid)
            else:
                missing_custom_repoids.append(custom_repo.repoid)
    api.current_logger().debug("Gathered target repositories: {}".format(
        ', '.join(target_repoids)))
    if not target_repoids:
        reporting.create_report([
            reporting.Title('There are no enabled target repositories'),
            reporting.Summary(
                'This can happen when a system is not correctly registered with the subscription manager'
                ' or, when the leapp --no-rhsm option has been used, no custom repositories have been'
                ' passed on the command line.'),
            reporting.Tags([reporting.Tags.REPOSITORY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Remediation(hint=(
                'Ensure the system is correctly registered with the subscription manager and that'
                ' the current subscription is entitled to install the requested target version {version}.'
                ' If you used the --no-rhsm option (or the LEAPP_NO_RHSM=1 environment variable is set),'
                ' ensure the custom repository file is provided with'
                ' properly defined repositories and that the --enablerepo option for leapp is set if the'
                ' repositories are defined in any repofiles under the /etc/yum.repos.d/ directory.'
                ' For more information on custom repository files, see the documentation.'
                ' Finally, verify that the "/etc/leapp/files/repomap.json" file is up-to-date.'
            ).format(
                version=api.current_actor().configuration.version.target)),
            reporting.ExternalLink(
                # TODO: How to handle different documentation links for each version?
                url='https://red.ht/preparing-for-upgrade-to-rhel8',
                title='Preparing for the upgrade'),
            reporting.RelatedResource("file", "/etc/leapp/files/repomap.json"),
            reporting.RelatedResource("file", "/etc/yum.repos.d/")
        ])
        raise StopActorExecution()
    if missing_custom_repoids:
        reporting.create_report([
            reporting.Title(
                'Some required custom target repositories have not been found'
            ),
            reporting.Summary(
                'This can happen when a repository ID was entered incorrectly either'
                ' while using the --enablerepo option of leapp, or in a third party actor that produces a'
                ' CustomTargetRepositoryMessage.\n'
                'The following repositories IDs could not be found in the target configuration:\n'
                '- {}\n'.format('\n- '.join(missing_custom_repoids))),
            reporting.Tags([reporting.Tags.REPOSITORY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.ExternalLink(
                # TODO: How to handle different documentation links for each version?
                url='https://access.redhat.com/articles/4977891',
                title=
                'Customizing your Red Hat Enterprise Linux in-place upgrade'),
            reporting.Remediation(hint=(
                'Consider using the custom repository file, which is documented in the official'
                ' upgrade documentation. Check whether a repository ID has been'
                ' entered incorrectly with the --enablerepo option of leapp.'
                ' Check the leapp logs to see the list of all available repositories.'
            ))
        ])
        raise StopActorExecution()
    return set(target_repoids)
Ejemplo n.º 19
0
def _get_product_certificate_path():
    """
    Retrieve the required / used product certificate for RHSM.
    """
    architecture = api.current_actor().configuration.architecture
    target_version = api.current_actor().configuration.version.target
    target_product_type = get_product_type('target')
    certs_dir = api.get_common_folder_path(PROD_CERTS_FOLDER)

    # We do not need any special certificates to reach repos from non-ga channels, only beta requires special cert.
    if target_product_type != 'beta':
        target_product_type = 'ga'

    prod_certs = {
        'x86_64': {
            'ga': '479.pem',
            'beta': '486.pem',
        },
        'aarch64': {
            'ga': '419.pem',
            'beta': '363.pem',
        },
        'ppc64le': {
            'ga': '279.pem',
            'beta': '362.pem',
        },
        's390x': {
            'ga': '72.pem',
            'beta': '433.pem',
        }
    }

    try:
        cert = prod_certs[architecture][target_product_type]
    except KeyError as e:
        raise StopActorExecutionError(message=(
            'Failed to determine what certificate to use for {}.'.format(e)))

    cert_path = os.path.join(certs_dir, target_version, cert)
    if not os.path.isfile(cert_path):
        additional_summary = ''
        if target_product_type != 'ga':
            additional_summary = (
                ' This can happen when upgrading a beta system and the chosen target version does not have'
                ' beta certificates attached (for example, because the GA has been released already).'
            )

        reporting.create_report([
            reporting.Title(
                'Cannot find the product certificate file for the chosen target system.'
            ),
            reporting.Summary(
                'Expected certificate: {cert} with path {path} but it could not be found.{additional}'
                .format(cert=cert,
                        path=cert_path,
                        additional=additional_summary)),
            reporting.Tags([reporting.Tags.REPOSITORY]),
            reporting.Flags([reporting.Flags.INHIBITOR]),
            reporting.Severity(reporting.Severity.HIGH),
            reporting.Remediation(hint=(
                'Set the corresponding target os version in the LEAPP_DEVEL_TARGET_RELEASE environment variable for'
                'which the {cert} certificate is provided'.format(cert=cert))),
        ])
        raise StopActorExecution()

    return cert_path