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.')
def install_initramdisk_requirements(packages, target_userspace_info, used_repos): """ Performs the installation of packages into the initram disk """ with _prepare_transaction(used_repos=used_repos, target_userspace_info=target_userspace_info) as (context, target_repoids, _unused): if get_target_major_version() == '9': _rebuild_rpm_db(context) repos_opt = [['--enablerepo', repo] for repo in target_repoids] repos_opt = list(itertools.chain(*repos_opt)) cmd = [ 'dnf', 'install', '-y', '--nogpgcheck', '--setopt=module_platform_id=platform:el{}'.format(get_target_major_version()), '--setopt=keepcache=1', '--releasever', api.current_actor().configuration.version.target, '--disablerepo', '*' ] + repos_opt + list(packages) if config.is_verbose(): cmd.append('-v') if rhsm.skip_rhsm(): cmd += ['--disableplugin', 'subscription-manager'] env = {} if get_target_major_version() == '9': # allow handling new RHEL 9 syscalls by systemd-nspawn env = {'SYSTEMD_SECCOMP': '0'} context.call(cmd, env=env)
def process(self): leftover_packages = next(self.consume(LeftoverPackages), LeftoverPackages()) if not leftover_packages.items: self.log.info('No leftover packages, skipping...') return installed_rpms = get_installed_rpms() to_remove = ['-'.join([pkg.name, pkg.version, pkg.release]) for pkg in leftover_packages.items] cmd = ['dnf', 'remove', '-y', '--noautoremove'] + to_remove if rhsm.skip_rhsm(): # ensure we don't use suscription-manager when it should be skipped cmd += ['--disableplugin', 'subscription-manager'] try: stdlib.run(cmd) except stdlib.CalledProcessError: error = 'Failed to remove packages: {}'.format(', '.join(to_remove)) self.log.error(error) return removed_packages = RemovedPackages() removed = list(set(installed_rpms) - set(get_installed_rpms())) for pkg in removed: name, version, release, epoch, packager, arch, pgpsig = pkg.split('|') removed_packages.items.append(RPM( name=name, version=version, epoch=epoch, packager=packager, arch=arch, release=release, pgpsig=pgpsig )) self.produce(removed_packages)
def gather_target_repositories(context): """ Perform basic checks on requirements for RHSM repositories and return the list of target repository ids to use during the upgrade. :param context: An instance of a mounting.IsolatedActions class :type context: mounting.IsolatedActions class :return: List of target system repoids :rtype: List(string) """ # Get the RHSM repos available in the RHEL 8 container available_repos = rhsm.get_available_repo_ids( context, releasever=api.current_actor().configuration.version.target) # FIXME: check that required repo IDs (baseos, appstream) # + or check that all required RHEL repo IDs are available. if not rhsm.skip_rhsm(): if not available_repos or len(available_repos) < 2: raise StopActorExecutionError( message='Cannot find required basic RHEL 8 repositories.', details={ 'hint': ('It is required to have RHEL repositories on the system' ' provided by the subscription-manager. Possibly you' ' are missing a valid SKU for the target system or network' ' connection failed. Check whether your system is attached' ' to a valid SKU providing RHEL 8 repositories.') }) target_repoids = [] for target_repo in api.consume(TargetRepositories): for rhel_repo in target_repo.rhel_repos: if rhel_repo.repoid in available_repos: 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. # The StopActorExecutionError called above might be moved here. pass for custom_repo in target_repo.custom_repos: # TODO: complete processing of custom repositories # HINT: now it will work only for custom repos that exist # + already on the system in a repo file # TODO: should check available_target_repoids + additional custom repos # + outside of rhsm.. # #if custom_repo.repoid in available_target_repoids: target_repoids.append(custom_repo.repoid) api.current_logger().debug("Gathered target repositories: {}".format( ', '.join(target_repoids))) if not target_repoids: raise StopActorExecutionError( message= 'There are no enabled target repositories for the upgrade process to proceed.', details={ 'hint': ('Ensure your system is correctly registered with the subscription manager and that' ' your current subscription is entitled to install the requested target version {version}' ).format( version=api.current_actor().configuration.version.target) }) return target_repoids
def gather_target_repositories(target_rhsm_info): """ Performs basic checks on requirements for RHSM repositories and returns the list of target repository ids to use during the upgrade. """ # FIXME: check that required repo IDs (baseos, appstream) # + or check that all required RHEL repo IDs are available. if not rhsm.skip_rhsm(): if not target_rhsm_info.available_repos or len( target_rhsm_info.available_repos) < 2: raise StopActorExecutionError( message='Cannot find required basic RHEL repositories.', details={ 'hint': ('It is required to have RHEL repository on the system' ' provided by the subscription-manager. Possibly you' ' are missing a valid SKU for the target system or network' ' connection failed. Check whether your system is attached' ' to the valid SKU providing target repositories.') }) target_repoids = [] for target_repo in api.consume(TargetRepositories): for rhel_repo in target_repo.rhel_repos: if rhel_repo.repoid in target_rhsm_info.available_repos: target_repoids.append(rhel_repo.repoid) for custom_repo in target_repo.custom_repos: # TODO: complete processing of custom repositories # HINT: now it will work only for custom repos that exist # + already on the system in a repo file # TODO: should check available_target_repoids + additional custom repos # + outside of rhsm.. # #if custom_repo.repoid in available_target_repoids: target_repoids.append(custom_repo.repoid) return target_repoids
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: raise StopActorExecutionError( message='Cannot find required basic RHEL {} repositories.'.format( target_major_version), details={ 'hint': ('It is required to have RHEL repositories on the system' ' provided by the subscription-manager unless the --no-rhsm' ' options is specified. Possibly you' ' are missing a valid SKU for the target system or network' ' connection failed. Check whether your system is attached' ' to a valid SKU providing RHEL {} repositories.' ' In case the Satellite is used, read the upgrade documentation' ' to setup the satellite and the system properly.'.format( target_major_version)) }) return set(repoids)
def prepare_target_userspace(context, userspace_dir, enabled_repos, packages): """ Implement the creation of the target userspace. """ target_major_version = get_target_major_version() run(['rm', '-rf', userspace_dir]) _create_target_userspace_directories(userspace_dir) with mounting.BindMount(source=userspace_dir, target=os.path.join( context.base_dir, 'el{}target'.format(target_major_version))): repos_opt = [['--enablerepo', repo] for repo in enabled_repos] repos_opt = list(itertools.chain(*repos_opt)) cmd = [ 'dnf', 'install', '-y', '--nogpgcheck', '--setopt=module_platform_id=platform:el{}'.format( target_major_version), '--setopt=keepcache=1', '--releasever', api.current_actor().configuration.version.target, '--installroot', '/el{}target'.format(target_major_version), '--disablerepo', '*' ] + repos_opt + packages if config.is_verbose(): cmd.append('-v') if rhsm.skip_rhsm(): cmd += ['--disableplugin', 'subscription-manager'] try: context.call(cmd, callback_raw=utils.logging_handler) except CalledProcessError as exc: raise StopActorExecutionError( message='Unable to install RHEL {} userspace packages.'.format( target_major_version), details={ 'details': str(exc), 'stderr': exc.stderr })
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.')
def perform(): packages = {'dnf'} for message in api.consume(RequiredTargetUserspacePackages): packages.update(message.packages) rhsm_info = next(api.consume(SourceRHSMInfo), None) if not rhsm_info and not rhsm.skip_rhsm(): api.current_logger().warn( 'Could not receive RHSM information - Is this system registered?') return xfs_info = next(api.consume(XFSPresence), XFSPresence()) storage_info = next(api.consume(StorageInfo), None) if not storage_info: api.current_logger.error('No storage info available cannot proceed.') prod_cert_path = _get_product_certificate_path() with overlaygen.create_source_overlay(mounts_dir=constants.MOUNTS_DIR, scratch_dir=constants.SCRATCH_DIR, storage_info=storage_info, xfs_info=xfs_info) as overlay: with overlay.nspawn() as context: target_version = api.current_actor().configuration.version.target with rhsm.switched_certificate(context, rhsm_info, prod_cert_path, target_version) as target_rhsm_info: api.current_logger().debug( 'Target RHSM Info: SKUs: {skus} Repositories: {repos}'. format(repos=target_rhsm_info.enabled_repos, skus=rhsm_info.attached_skus if rhsm_info else [])) target_repoids = gather_target_repositories(target_rhsm_info) api.current_logger().debug( "Gathered target repositories: {}".format( ', '.join(target_repoids))) if not target_repoids: raise StopActorExecutionError( message= 'There are no enabled target repositories for the upgrade process to proceed.', details={ 'hint': ('Ensure your system is correctly registered with the subscription manager and that' ' your current subscription is entitled to install the requested target version {version}' ).format(version=api.current_actor(). configuration.version.target) }) prepare_target_userspace(context, constants.TARGET_USERSPACE, target_repoids, list(packages)) _prep_repository_access(context, constants.TARGET_USERSPACE) dnfplugin.install(constants.TARGET_USERSPACE) api.produce( UsedTargetRepositories(repos=[ UsedTargetRepository(repoid=repo) for repo in target_repoids ])) api.produce(target_rhsm_info) api.produce( TargetUserSpaceInfo(path=constants.TARGET_USERSPACE, scratch=constants.SCRATCH_DIR, mounts=constants.MOUNTS_DIR))
def _transaction(context, stage, target_repoids, tasks, plugin_info, test=False, cmd_prefix=None, on_aws=False): """ Perform the actual DNF rpm download via our DNF plugin """ # we do not want if stage != 'upgrade': create_config( context=context, target_repoids=target_repoids, debug=config.is_debug(), test=test, tasks=tasks, on_aws=on_aws ) backup_config(context=context) # FIXME: rhsm with guards.guarded_execution(guards.connection_guard(), guards.space_guard()): cmd = [ '/usr/bin/dnf', 'rhel-upgrade', stage, DNF_PLUGIN_DATA_PATH ] if config.is_verbose(): cmd.append('-v') if rhsm.skip_rhsm(): cmd += ['--disableplugin', 'subscription-manager'] if plugin_info: for info in plugin_info: if stage in info.disable_in: cmd += ['--disableplugin', info.name] if cmd_prefix: cmd = cmd_prefix + cmd env = {} if get_target_major_version() == '9': # allow handling new RHEL 9 syscalls by systemd-nspawn env = {'SYSTEMD_SECCOMP': '0'} try: context.call( cmd=cmd, callback_raw=utils.logging_handler, env=env ) except OSError as e: api.current_logger().error('Could not call dnf command: Message: %s', str(e), exc_info=True) raise StopActorExecutionError( message='Failed to execute dnf. Reason: {}'.format(str(e)) ) except CalledProcessError as e: api.current_logger().error('DNF execution failed: ') raise StopActorExecutionError( message='DNF execution failed with non zero exit code.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}'.format( stdout=e.stdout, stderr=e.stderr) ) finally: if stage == 'check': backup_debug_data(context=context)
def _prep_repository_access(context, target_userspace): """ Prepare repository access by copying all relevant certificates and configuration files to the userspace """ target_etc = os.path.join(target_userspace, 'etc') target_yum_repos_d = os.path.join(target_etc, 'yum.repos.d') backup_yum_repos_d = os.path.join(target_etc, 'yum.repos.d.backup') if not rhsm.skip_rhsm(): run(['rm', '-rf', os.path.join(target_etc, 'pki')]) run(['rm', '-rf', os.path.join(target_etc, 'rhsm')]) context.copytree_from('/etc/pki', os.path.join(target_etc, 'pki')) context.copytree_from('/etc/rhsm', os.path.join(target_etc, 'rhsm')) # NOTE: we cannot just remove the original target yum.repos.d dir # as e.g. in case of RHUI a special RHUI repofiles are installed by a pkg # when the target userspace container is created. Removing these files we loose # RHUI target repositories. So ...-> # -> detect such a files... with mounting.NspawnActions(base_dir=target_userspace) as target_context: files_owned_by_rpms = _get_files_owned_by_rpms(target_context, '/etc/yum.repos.d') # -> backup the orig dir & install the new one run(['mv', target_yum_repos_d, backup_yum_repos_d]) context.copytree_from('/etc/yum.repos.d', target_yum_repos_d) # -> find old rhui repo files (we have to remove these as they cause duplicates) rhui_pkgs = _get_all_rhui_pkgs() old_files_owned_by_rhui_rpms = _get_files_owned_by_rpms( context, '/etc/yum.repos.d', rhui_pkgs) for fname in old_files_owned_by_rhui_rpms: api.current_logger().debug('Remove the old repofile: {}'.format(fname)) run(['rm', '-f', os.path.join(target_yum_repos_d, fname)]) # .. continue: remove our leapp rhui repo file (do not care if we are on rhui or not) for rhui_map in rhui.gen_rhui_files_map().values(): for item in rhui_map: if item[1] != rhui.YUM_REPOS_PATH: continue target_leapp_repofile = os.path.join(target_yum_repos_d, item[0]) if not os.path.isfile(target_leapp_repofile): continue # we found it!! run(['rm', '-f', target_leapp_repofile]) break # -> copy expected files back for fname in files_owned_by_rpms: api.current_logger().debug( 'Copy the backed up repo file: {}'.format(fname)) run([ 'mv', os.path.join(backup_yum_repos_d, fname), os.path.join(target_yum_repos_d, fname) ]) # -> remove the backed up dir run(['rm', '-rf', backup_yum_repos_d])
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
def _prep_repository_access(context, target_userspace): """ Prepare repository access by copying all relevant certificates and configuration files to the userspace """ if not rhsm.skip_rhsm(): run(['rm', '-rf', os.path.join(target_userspace, 'etc', 'pki')]) run(['rm', '-rf', os.path.join(target_userspace, 'etc', 'rhsm')]) context.copytree_from('/etc/pki', os.path.join(target_userspace, 'etc', 'pki')) context.copytree_from('/etc/rhsm', os.path.join(target_userspace, 'etc', 'rhsm')) run(['rm', '-rf', os.path.join(target_userspace, 'etc', 'yum.repos.d')]) context.copytree_from('/etc/yum.repos.d', os.path.join(target_userspace, 'etc', 'yum.repos.d'))
def _get_all_available_repoids(context): repofiles = repofileutils.get_parsed_repofiles(context) # TODO: this is not good solution, but keep it as it is now # Issue: #486 if rhsm.skip_rhsm(): # only if rhsm is skipped, the duplicate repos are not detected # automatically and we need to do it extra _inhibit_on_duplicate_repos(repofiles) repoids = [] for rfile in repofiles: if rfile.data: repoids += [repo.repoid for repo in rfile.data] return set(repoids)
def process(self): if not rhsm.skip_rhsm(): for info in self.consume(SourceRHSMInfo): if not info.attached_skus: report_with_remediation( title='The system is not registered or subscribed.', summary= 'The system has to be registered and subscribed to be able to proceed the upgrade.', remediation= ('Register your system with the subscription-manager tool and attach it to proper SKUs' ' to be able to proceed the upgrade.'), severity='high', flags=['inhibitor'])
def enable_rhsm_repos(): """ Try enabling all the RHEL 8 repositories that have been used for the upgrade transaction. In case of custom repositories, the subscription-manager reports an error that it doesn't know them, but it enables the known repositories. """ if rhsm.skip_rhsm(): api.current_logger().debug('Skipping enabling repositories through subscription-manager due to the use of' ' LEAPP_DEVEL_SKIP_RHSM.') return try: run(get_submgr_cmd(get_repos_to_enable())) except CalledProcessError as err: api.current_logger().warning('The subscription-manager could not enable some repositories.\n' 'It is expected behavior in case of custom repositories unknown to' ' the subscription-manager - these need to be enabled manually.\n{0}' .format(str(err)))
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
def process(self): if not rhsm.skip_rhsm(): for info in self.consume(SourceRHSMInfo): if not info.attached_skus: create_report([ reporting.Title( 'The system is not registered or subscribed.'), reporting.Summary( 'The system has to be registered and subscribed to be able to proceed the upgrade.' ), reporting.Severity(reporting.Severity.HIGH), reporting.Tags([reporting.Tags.SANITY]), reporting.Flags([reporting.Flags.INHIBITOR]), reporting.Remediation( hint= 'Register your system with the subscription-manager tool and attach it to proper SKUs' ' to be able to proceed the upgrade.'), reporting.RelatedResource('package', 'subscription-manager') ])
def set_rhsm_release(): """Set the RHSM release to the target RHEL minor version.""" if rhsm.skip_rhsm(): api.current_logger().debug( 'Skipping setting the RHSM release due to --no-rhsm or environment variables.' ) return if config.get_product_type('target') != 'ga': api.current_logger().debug( 'Skipping setting the RHSM release as target product is set to beta/htb' ) return target_version = api.current_actor().configuration.version.target try: rhsm.set_release(mounting.NotIsolatedActions(base_dir='/'), target_version) except CalledProcessError as err: api.current_logger().warning( 'Unable to set the {0} release through subscription-manager. When using dnf,' ' content of the latest RHEL {1} minor version will be downloaded.\n{2}' .format(target_version, get_target_major_version(), str(err)))
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)
def process(): if not rhsm.skip_rhsm(): for info in api.consume(RHSMInfo): if not info.attached_skus: create_report([ reporting.Title( 'The system is not registered or subscribed.'), reporting.Summary( 'The system has to be registered and subscribed to be able to proceed' ' with the upgrade, unless the --no-rhsm option is specified when' ' executing leapp.'), reporting.Severity(reporting.Severity.HIGH), reporting.Tags([reporting.Tags.SANITY]), reporting.Flags([reporting.Flags.INHIBITOR]), reporting.Remediation( hint= 'Register your system with the subscription-manager tool and attach' ' proper SKUs to be able to proceed the upgrade or use the --no-rhsm' ' leapp option if you want to provide target repositories by yourself.' ), reporting.RelatedResource('package', 'subscription-manager') ])
def install_initramdisk_requirements(packages, target_userspace_info, used_repos): """ Performs the installation of packages into the initram disk """ with _prepare_transaction( used_repos=used_repos, target_userspace_info=target_userspace_info) as (context, target_repoids, _unused): repos_opt = [['--enablerepo', repo] for repo in target_repoids] repos_opt = list(itertools.chain(*repos_opt)) cmd = [ 'dnf', 'install', '-y', '--nogpgcheck', '--setopt=module_platform_id=platform:el8', '--setopt=keepcache=1', '--releasever', api.current_actor().configuration.version.target, '--disablerepo', '*' ] + repos_opt + list(packages) if config.is_verbose(): cmd.append('-v') if rhsm.skip_rhsm(): cmd += ['--disableplugin', 'subscription-manager'] context.call(cmd)
def _transaction(context, stage, target_repoids, tasks, plugin_info, test=False, cmd_prefix=None, on_aws=False): """ Perform the actual DNF rpm download via our DNF plugin """ # we do not want if stage not in ['dry-run', 'upgrade']: create_config( context=context, target_repoids=target_repoids, debug=config.is_debug(), test=test, tasks=tasks, on_aws=on_aws ) backup_config(context=context) # FIXME: rhsm with guards.guarded_execution(guards.connection_guard(), guards.space_guard()): cmd_prefix = cmd_prefix or [] common_params = [] if config.is_verbose(): common_params.append('-v') if rhsm.skip_rhsm(): common_params += ['--disableplugin', 'subscription-manager'] if plugin_info: for info in plugin_info: if stage in info.disable_in: common_params += ['--disableplugin', info.name] env = {} if get_target_major_version() == '9': # allow handling new RHEL 9 syscalls by systemd-nspawn env = {'SYSTEMD_SECCOMP': '0'} # We need to reset modules twice, once before we check, and the second time before we actually perform # the upgrade. Not more often as the modules will be reset already. if stage in ('check', 'upgrade') and tasks.modules_to_reset: # We shall only reset modules that are not going to be enabled # This will make sure it is so modules_to_reset = {(module.name, module.stream) for module in tasks.modules_to_reset} modules_to_enable = {(module.name, module.stream) for module in tasks.modules_to_enable} module_reset_list = [module[0] for module in modules_to_reset - modules_to_enable] # Perform module reset cmd = ['/usr/bin/dnf', 'module', 'reset', '--enabled', ] + module_reset_list cmd += ['--disablerepo', '*', '-y', '--installroot', '/installroot'] try: context.call( cmd=cmd_prefix + cmd + common_params, callback_raw=utils.logging_handler, env=env ) except (CalledProcessError, OSError): api.current_logger().debug('Failed to reset modules via dnf with an error. Ignoring.', exc_info=True) cmd = [ '/usr/bin/dnf', 'rhel-upgrade', stage, DNF_PLUGIN_DATA_PATH ] try: context.call( cmd=cmd_prefix + cmd + common_params, callback_raw=utils.logging_handler, env=env ) except OSError as e: api.current_logger().error('Could not call dnf command: Message: %s', str(e), exc_info=True) raise StopActorExecutionError( message='Failed to execute dnf. Reason: {}'.format(str(e)) ) except CalledProcessError as e: api.current_logger().error('DNF execution failed: ') raise StopActorExecutionError( message='DNF execution failed with non zero exit code.\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}'.format( stdout=e.stdout, stderr=e.stderr) ) finally: if stage == 'check': backup_debug_data(context=context)
def process(self): upg_path = rhui.get_upg_path() for provider, info in rhui.RHUI_CLOUD_MAP[upg_path].items(): if has_package(InstalledRPM, info['src_pkg']): is_azure_sap = False azure_sap_pkg = rhui.RHUI_CLOUD_MAP[upg_path]['azure-sap'][ 'src_pkg'] azure_nonsap_pkg = rhui.RHUI_CLOUD_MAP[upg_path]['azure'][ 'src_pkg'] # we need to do this workaround in order to overcome our RHUI handling limitation # in case there are more client packages on the source system if 'azure' in info['src_pkg'] and has_package( InstalledRPM, azure_sap_pkg): is_azure_sap = True provider = 'azure-sap' info = rhui.RHUI_CLOUD_MAP[upg_path]['azure-sap'] 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 # there are several "variants" related to the *AWS* provider (aws, aws-sap) if provider.startswith('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['src_pkg'] != info['target_pkg']: self.produce( RpmTransactionTasks(to_install=[info['target_pkg']])) self.produce( RpmTransactionTasks(to_remove=[info['src_pkg']])) if is_azure_sap: self.produce( RpmTransactionTasks(to_remove=[azure_nonsap_pkg])) self.produce(RHUIInfo(provider=provider)) self.produce( RequiredTargetUserspacePackages( packages=[info['target_pkg']])) return
def process(): if rhsm.skip_rhsm(): _report_unhandled_release() else: _report_set_release()
def process(): rhui_info = next(api.consume(RHUIInfo), None) if not rhsm.skip_rhsm() or rhui_info: # getting RH repositories through RHSM or RHUI; resolved by seatbelts # implemented in other actors return # rhsm skipped; take your seatbelts please is_ctr = _any_custom_repo_defined() is_ctrf = _the_custom_repofile_defined() is_re = _the_enablerepo_option_used() if not is_ctr: # no rhsm, no custom repositories.. this will really not work :) # TODO: add link to the RH article about use of custom repositories!! # NOTE: we can put here now the link to the main document, as this # will be described there or at least the link to the right document # will be delivered here. if is_ctrf: summary_ctrf = '\n\nThe custom repository file has been detected. Maybe it is empty?' else: summary_ctrf = '' reporting.create_report([ reporting.Title( 'Using RHSM has been skipped but no custom or RHUI repositories have been delivered.' ), reporting.Summary( 'Leapp is run in the mode when the Red Hat Subscription Manager' ' is not used (the --no-rhsm option or the LEAPP_NO_RHSM=1' ' environment variable has been set) so leapp is not able to' ' obtain YUM/DNF repositories with the content for the target' ' system in the standard way. The content has to be delivered' ' either by user manually or, in case of public clouds, by a' ' special Leapp package for RHUI environments.'), reporting.Remediation(hint=( 'Create the repository file according to instructions in the' ' referred document on the following path with all' ' repositories that should be used during the upgrade: "{}".' '\n\n{}'.format(CUSTOM_REPO_PATH, summary_ctrf))), reporting.Severity(reporting.Severity.HIGH), reporting.Tags([reporting.Tags.SANITY]), reporting.Flags([reporting.Flags.INHIBITOR]), reporting.ExternalLink(url=_IPU_DOC_URL, title='UPGRADING TO RHEL 8'), reporting.RelatedResource('file', CUSTOM_REPO_PATH), ]) elif not (is_ctrf or is_re): # Some custom repositories have been discovered, but the custom repo # file not - neither the --enablerepo option is used. Inform about # the official recommended way. reporting.create_report([ reporting.Title( 'Detected "CustomTargetRepositories" without using new provided mechanisms used.' ), reporting.Summary( 'Red Hat now provides an official way for using custom' ' repositories during the in-place upgrade through' ' the referred custom repository file or through the' ' --enablerepo option for leapp. The CustomTargetRepositories' ' have been produced from custom (own) actors?'), reporting.Remediation(hint=( 'Follow the new simple way to enable custom repositories' ' during the upgrade (see the referred document) or create' ' the empty custom repository file to acknowledge this report' ' message.')), reporting.Severity(reporting.Severity.INFO), reporting.ExternalLink(url=_IPU_DOC_URL, title='UPGRADING TO RHEL 8'), reporting.RelatedResource('file', CUSTOM_REPO_PATH), ])