Exemple #1
0
    def update_rhel_subscription(self, overlayfs_info):
        sys_var = ""
        for msg in self.consume(OSReleaseFacts):
            if msg.variant_id:
                sys_var = msg.variant_id
                break

        # Make sure Subscription Manager OS Release is unset
        cmd = ['subscription-manager', 'release', '--unset']
        _unused, error = preparetransaction.guard_container_call(
            overlayfs_info,
            cmd,
            guards=(preparetransaction.connection_guard(),)
        )
        if error:
            error.summary = 'Cannot remove version preference.'
            return error

        var_prodcert = {'server': '230.pem'}
        if sys_var not in var_prodcert:
            return preparetransaction.ErrorData(
                summary="Failed to to retrieve Product Cert file.",
                details="Product cert file not available for System Variant '{}'.".format(sys_var))

        prod_cert_path = self.get_file_path(var_prodcert[sys_var])
        for path in ('/etc/pki/product-default', '/etc/pki/product'):
            if not os.path.isdir(path):
                continue

            existing_certs = [os.path.join(path, f) for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]
            if not existing_certs:
                continue

            error = preparetransaction.copy_file_to_container(overlayfs_info, prod_cert_path, path)
            if error:
                return error

            # FIXME: it's removing all certs from /etc/pki/product - but we should remove only the
            # + EngID provided by a redhat-release-* rpm in the directory (Maybe another RH cert
            # + but we should not remove user's 3rd party certs (e.g. for custom repositories it
            # + would be problem later). Needs a little investigation here about the impact, even
            # + in the container.
            for cert in existing_certs:
                # FIXME: fails on insufficient permissions
                cmd = ['rm', '-f', cert]
                _unused, error = preparetransaction.guard_container_call(overlayfs_info, cmd)
                if error:
                    return error

        cmd = ['subscription-manager', 'refresh']
        _unused, error = preparetransaction.guard_container_call(
            overlayfs_info,
            cmd,
            guards=(preparetransaction.connection_guard(),)
        )
        return error
Exemple #2
0
 def get_rhsm_system_release(self):
     """
     Get system release set by RHSM or None on error.
     """
     cmd = ['subscription-manager', 'release']
     prev_rhsm_release, error = preparetransaction.guard_call(
         cmd, guards=(preparetransaction.connection_guard(), ))
     if error:
         preparetransaction.produce_error(
             error, summary='Cannot get release setting.')
         return None
     return prev_rhsm_release[0]
Exemple #3
0
    def process(self):
        skip_rhsm = os.getenv('LEAPP_DEVEL_SKIP_RHSM', '0') == '1'
        mounts_dir = os.getenv('LEAPP_CONTAINER_ROOT',
                               '/var/lib/leapp/scratch')
        container_root = os.path.join(mounts_dir, 'mounts')
        error_flag = False

        if skip_rhsm:
            self.log.warning(
                "LEAPP_DEVEL_SKIP_RHSM has been used. The upgrade is unsupported."
            )

        if not skip_rhsm and not self.is_system_registered_and_attached():
            error = preparetransaction.ErrorData(
                summary='The system is not registered or subscribed.',
                details=(
                    'The system has to be registered and subscribed to be able'
                    ' to proceed the upgrade. Register your system with the'
                    ' subscription-manager tool and attach'
                    ' it to proper SKUs to be able to proceed the upgrade.'))
            preparetransaction.produce_error(error)
            return

        # TODO: Find a better place where to run this (perhaps even gate this behind user prompt/question)
        # FIXME: fails on insufficient permissions
        cmd = ['/usr/bin/dnf', 'clean', 'all']
        _unused, error = preparetransaction.guard_call(cmd)
        if error:
            preparetransaction.produce_error(
                error, summary='Cannot perform dnf cleanup.')
            return

        # prepare container #
        # TODO: wrap in one function (create ofs dirs, mount), or even context
        #       manager (enter -> create dirs, mount; exit -> umount)?
        xfs_presence = next(self.consume(XFSPresence), XFSPresence())
        if xfs_presence.present and xfs_presence.without_ftype:
            error = preparetransaction.create_disk_image(mounts_dir)
            if error:
                self.produce_error(error)

        ofs_info, error = preparetransaction.create_overlayfs_dirs(
            container_root)
        if not ofs_info:
            preparetransaction.produce_error(error)
            return

        error = preparetransaction.mount_overlayfs(ofs_info)
        if error:
            preparetransaction.produce_error(error)
            preparetransaction.remove_overlayfs_dirs(container_root)
            preparetransaction.remove_disk_image(mounts_dir)
            return

        prev_rhsm_release = None
        if not skip_rhsm:
            prev_rhsm_release = self.get_rhsm_system_release()
            if prev_rhsm_release is None:
                # TODO: error is produced inside - will be refactored later
                # with the whole actor
                return
            # switch EngID to use RHEL 8 subscriptions #
            error = self.update_rhel_subscription(ofs_info)

        if not error:
            dnfplugin_spath = self.get_file_path('rhel_upgrade.py')
            dnfplugin_dpath = '/lib/python2.7/site-packages/dnf-plugins'

            error = preparetransaction.copy_file_to_container(
                ofs_info, dnfplugin_spath, dnfplugin_dpath)
            if error:
                return error

        error = self.dnf_plugin_rpm_download(ofs_info)
        if not error:
            error = preparetransaction.copy_file_from_container(
                ofs_info,
                '/etc/yum.repos.d/redhat.repo',
                '/etc/yum.repos.d/',
                'redhat.repo.upgrade',
            )

        if error:
            preparetransaction.produce_error(error)
            error_flag = True

        # If Subscription Manager OS Release was set before, make sure we do not change it
        if not skip_rhsm and 'Release:' in prev_rhsm_release:
            release = prev_rhsm_release.split(':')[1].strip()
            cmd = ['subscription-manager', 'release', '--set', release]
            _unused, error = preparetransaction.guard_call(
                cmd, guards=(preparetransaction.connection_guard(), ))
            if error:
                preparetransaction.produce_error(
                    error, summary='Cannot set minor release version.')
                error_flag = True

        # clean #
        error = preparetransaction.umount_overlayfs(ofs_info)
        if error:
            preparetransaction.produce_error(error)
            error_flag = True

        preparetransaction.remove_overlayfs_dirs(container_root)
        preparetransaction.remove_disk_image(mounts_dir)

        # produce msg for upgrading actor
        if not error_flag:
            self.produce_used_target_repos()
Exemple #4
0
    def dnf_plugin_rpm_download(self, overlayfs_info):
        dnf_command = ['/usr/bin/dnf', 'rhel-upgrade', 'download']

        # get list of repo IDs of target repositories that should be used for upgrade
        error = self._setup_target_repos(overlayfs_info)
        if error:
            return error
        if not self.target_repoids:
            return preparetransaction.ErrorData(
                summary='Cannot find any required target repository.',
                details='The list of available required repositories is empty.'
            )

        debugsolver = True if os.environ.get('LEAPP_DEBUG',
                                             '0') == '1' else False

        yum_script_path = self.get_tool_path('handleyumconfig')
        cmd = ['--', '/bin/bash', '-c', yum_script_path]
        _unused, error = preparetransaction.guard_container_call(
            overlayfs_info, cmd)
        if error:
            return error

        error = preparetransaction.mount_dnf_cache(overlayfs_info)
        if error:
            return error

        data = next(self.consume(FilteredRpmTransactionTasks),
                    FilteredRpmTransactionTasks())

        plugin_data = {
            'pkgs_info': {
                'local_rpms': [pkg for pkg in data.local_rpms],
                'to_install': [pkg for pkg in data.to_install],
                'to_remove': [pkg for pkg in data.to_remove]
            },
            'dnf_conf': {
                'allow_erasing': True,
                'best': True,
                'debugsolver': debugsolver,
                'disable_repos': True,
                'enable_repos': self.target_repoids,
                'gpgcheck': False,
                'platform_id': 'platform:el8',
                'releasever': '8',
                'test_flag': True,
            }
        }

        with open(
                os.path.join(overlayfs_info.merged, 'var', 'lib', 'leapp',
                             'dnf-plugin-data.txt'), 'w+') as data:
            json.dump(plugin_data, data)
            data.flush()

        copy_error = preparetransaction.copy_file_from_container(
            overlayfs_info,
            '/var/lib/leapp/dnf-plugin-data.txt',
            '/var/log/leapp/',
            'dnf-plugin-data.txt',
        )

        if copy_error:
            preparetransaction.produce_warning(copy_error)

        # FIXME: fails on insufficient permissions
        cmd = [
            '--', '/bin/bash', '-c',
            ' '.join(dnf_command + ['/var/lib/leapp/dnf-plugin-data.txt'])
        ]
        _unused, error = preparetransaction.guard_container_call(
            overlayfs_info,
            cmd,
            guards=(preparetransaction.connection_guard(),
                    preparetransaction.space_guard()),
            print_output=True)

        if os.environ.get('LEAPP_DEBUG', '0') == '1':
            # We want the debug data available where we would expect it usually.
            debug_data_path = '/var/log/leapp/dnf-debugdata/'

            # The debugdata is a folder generated by dnf when using the --debugsolver dnf option. We switch on the
            # debug_solver dnf config parameter in our rhel-upgrade dnf plugin when LEAPP_DEBUG env var set to 1.
            cmd = [
                'cp', '-a',
                os.path.join(overlayfs_info.merged, 'debugdata'),
                debug_data_path
            ]
            _unused, dbg_error = preparetransaction.guard_call(cmd)
            if dbg_error:
                preparetransaction.produce_warning(
                    dbg_error, summary='Cannot copy new debugdata.')

        if error:
            umount_error = preparetransaction.umount_dnf_cache(overlayfs_info)
            if umount_error:
                preparetransaction.produce_error(umount_error)
            return error

        return preparetransaction.umount_dnf_cache(overlayfs_info)