diff --git a/commands/command_utils.py b/commands/command_utils.py index 338978dd..af78efdf 100644 --- a/commands/command_utils.py +++ b/commands/command_utils.py @@ -13,7 +13,7 @@ LEAPP_UPGRADE_FLAVOUR_DEFAULT = 'default' LEAPP_UPGRADE_FLAVOUR_SAP_HANA = 'saphana' LEAPP_UPGRADE_PATHS = 'upgrade_paths.json' -VERSION_REGEX = re.compile(r"^([1-9]\d*)\.(\d+)$") +VERSION_REGEX = re.compile(r"^([1-9]\d*)(\.(\d+))?$") def check_version(version): diff --git a/commands/upgrade/breadcrumbs.py b/commands/upgrade/breadcrumbs.py index 16903ee0..46f116fb 100644 --- a/commands/upgrade/breadcrumbs.py +++ b/commands/upgrade/breadcrumbs.py @@ -61,7 +61,7 @@ class _BreadCrumbs(object): if not os.path.exists('/etc/rhsm'): # If there's no /etc/rhsm folder just skip it return - os.path.mkdir('/etc/rhsm/facts') + os.mkdir('/etc/rhsm/facts') try: with open('/etc/rhsm/facts/leapp.facts', 'w') as f: json.dump(_flattened({ diff --git a/repos/system_upgrade/common/actors/addupgradebootentry/libraries/addupgradebootentry.py b/repos/system_upgrade/common/actors/addupgradebootentry/libraries/addupgradebootentry.py index 4e1c4204..3474867a 100644 --- a/repos/system_upgrade/common/actors/addupgradebootentry/libraries/addupgradebootentry.py +++ b/repos/system_upgrade/common/actors/addupgradebootentry/libraries/addupgradebootentry.py @@ -18,7 +18,7 @@ def add_boot_entry(configs=None): '/usr/sbin/grubby', '--add-kernel', '{0}'.format(kernel_dst_path), '--initrd', '{0}'.format(initram_dst_path), - '--title', 'RHEL-Upgrade-Initramfs', + '--title', 'ELevate-Upgrade-Initramfs', '--copy-default', '--make-default', '--args', '{DEBUG}{NET} enforcing=0 rd.plymouth=0 plymouth.enable=0'.format(DEBUG=debug, NET=ip_arg) diff --git a/repos/system_upgrade/common/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py b/repos/system_upgrade/common/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py index ddc37e52..a9c40691 100644 --- a/repos/system_upgrade/common/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py +++ b/repos/system_upgrade/common/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py @@ -42,7 +42,7 @@ run_args_add = [ '/usr/sbin/grubby', '--add-kernel', '/abc', '--initrd', '/def', - '--title', 'RHEL-Upgrade-Initramfs', + '--title', 'ELevate-Upgrade-Initramfs', '--copy-default', '--make-default', '--args', diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh index 491b85ec..059cf506 100755 --- a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh +++ b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh @@ -9,7 +9,7 @@ type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh get_rhel_major_release() { local os_version - os_version=$(grep -o '^VERSION="[0-9][0-9]*\.' /etc/initrd-release | grep -o '[0-9]*') + os_version=$(grep -o '^VERSION="[0-9][0-9]*' /etc/initrd-release | grep -o '[0-9]*') [ -z "$os_version" ] && { # This should not happen as /etc/initrd-release is supposed to have API # stability, but check is better than broken system. @@ -377,4 +377,3 @@ getarg 'rd.break=leapp-logs' && emergency_shell -n upgrade "Break after LEAPP sa sync mount -o "remount,$old_opts" "$NEWROOT" exit $result - diff --git a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/90sys-upgrade/initrd-system-upgrade-generator b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/90sys-upgrade/initrd-system-upgrade-generator index 5cc6fd92..fe81626f 100755 --- a/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/90sys-upgrade/initrd-system-upgrade-generator +++ b/repos/system_upgrade/common/actors/commonleappdracutmodules/files/dracut/90sys-upgrade/initrd-system-upgrade-generator @@ -1,7 +1,7 @@ #!/bin/sh get_rhel_major_release() { - _os_version=$(cat /etc/initrd-release | grep -o '^VERSION="[0-9][0-9]*\.' | grep -o '[0-9]*') + _os_version=$(cat /etc/initrd-release | grep -o '^VERSION="[0-9][0-9]*' | grep -o '[0-9]*') [ -z "$_os_version" ] && { # This should not happen as /etc/initrd-release is supposed to have API # stability, but check is better than broken system. diff --git a/repos/system_upgrade/common/actors/efibootorderfix/finalization/actor.py b/repos/system_upgrade/common/actors/efibootorderfix/finalization/actor.py index f42909f0..4a2bc8ad 100644 --- a/repos/system_upgrade/common/actors/efibootorderfix/finalization/actor.py +++ b/repos/system_upgrade/common/actors/efibootorderfix/finalization/actor.py @@ -1,17 +1,118 @@ +import os +import re + +from leapp.libraries.stdlib import run, api from leapp.actors import Actor -from leapp.libraries.common import efi_reboot_fix +from leapp.models import InstalledTargetKernelVersion, KernelCmdlineArg, FirmwareFacts, MountEntry from leapp.tags import FinalizationPhaseTag, IPUWorkflowTag +from leapp.exceptions import StopActorExecutionError class EfiFinalizationFix(Actor): """ - Adjust EFI boot entry for final reboot + Ensure that EFI boot order is updated, which is particularly necessary + when upgrading to a different OS distro. Also rebuilds grub config + if necessary. """ name = 'efi_finalization_fix' - consumes = () + consumes = (KernelCmdlineArg, InstalledTargetKernelVersion, FirmwareFacts, MountEntry) produces = () tags = (FinalizationPhaseTag, IPUWorkflowTag) def process(self): - efi_reboot_fix.maybe_emit_updated_boot_entry() + is_system_efi = False + ff = next(self.consume(FirmwareFacts), None) + + dirname = { + 'AlmaLinux': 'almalinux', + 'CentOS Linux': 'centos', + 'CentOS Stream': 'centos', + 'Oracle Linux Server': 'redhat', + 'Red Hat Enterprise Linux': 'redhat', + 'Rocky Linux': 'rocky', + 'Scientific Linux': 'redhat', + 'EuroLinux': 'eurolinux', + } + + efi_shimname_dict = { + 'x86_64': 'shimx64.efi', + 'aarch64': 'shimaa64.efi' + } + + def devparts(dev): + """ + NVMe block devices aren't named like SCSI/ATA/etc block devices and must be parsed differently. + SCSI/ATA/etc devices have a syntax resembling /dev/sdb4 for the 4th partition on the 2nd disk. + NVMe devices have a syntax resembling /dev/nvme0n2p4 for the 4th partition on the 2nd disk. + """ + if '/dev/nvme' in dev: + """ + NVMe + """ + part = next(re.finditer(r'p\d+$', dev)).group(0) + dev = dev[:-len(part)] + part = part[1:] + else: + """ + Non-NVMe (SCSI, ATA, etc) + """ + part = next(re.finditer(r'\d+$', dev)).group(0) + dev = dev[:-len(part)] + return [dev, part]; + + with open('/etc/system-release', 'r') as sr: + release_line = next(line for line in sr if 'release' in line) + distro = release_line.split(' release ', 1)[0] + + efi_bootentry_label = distro + distro_dir = dirname.get(distro, 'default') + shim_filename = efi_shimname_dict.get(api.current_actor().configuration.architecture, 'shimx64.efi') + + shim_path = '/boot/efi/EFI/' + distro_dir + '/' + shim_filename + grub_cfg_path = '/boot/efi/EFI/' + distro_dir + '/grub.cfg' + bootmgr_path = '\\EFI\\' + distro_dir + '\\' + shim_filename + + has_efibootmgr = os.path.exists('/sbin/efibootmgr') + has_shim = os.path.exists(shim_path) + has_grub_cfg = os.path.exists(grub_cfg_path) + + if not ff: + raise StopActorExecutionError( + 'Could not identify system firmware', + details={'details': 'Actor did not receive FirmwareFacts message.'} + ) + + if not has_efibootmgr: + return + + for fact in self.consume(FirmwareFacts): + if fact.firmware == 'efi': + is_system_efi = True + break + + if is_system_efi and has_shim: + efidevlist = [] + with open('/proc/mounts', 'r') as fp: + for line in fp: + if '/boot/efi' in line: + efidevpath = line.split(' ', 1)[0] + efidevpart = efidevpath.split('/')[-1] + if os.path.exists('/proc/mdstat'): + with open('/proc/mdstat', 'r') as mds: + for line in mds: + if line.startswith(efidevpart): + mddev = line.split(' ') + for md in mddev: + if '[' in md: + efimd = md.split('[', 1)[0] + efidp = efidevpath.replace(efidevpart, efimd) + efidevlist.append(efidp) + if len(efidevlist) == 0: + efidevlist.append(efidevpath) + for devpath in efidevlist: + efidev, efipart = devparts(devpath) + run(['/sbin/efibootmgr', '-c', '-d', efidev, '-p', efipart, '-l', bootmgr_path, '-L', efi_bootentry_label]) + + if not has_grub_cfg: + run(['/sbin/grub2-mkconfig', '-o', grub_cfg_path]) diff --git a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py index 9e213f64..52cfe14f 100644 --- a/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py +++ b/repos/system_upgrade/common/actors/ipuworkflowconfig/libraries/ipuworkflowconfig.py @@ -47,15 +47,20 @@ def get_os_release(path): :return: `OSRelease` model if the file can be parsed :raises: `IOError` """ + os_version = '.'.join(platform.dist()[1].split('.')[:2]) try: with open(path) as f: data = dict(l.strip().split('=', 1) for l in f.readlines() if '=' in l) + release_id = data.get('ID', '').strip('"') + version_id = data.get('VERSION_ID', '').strip('"') + if release_id == 'centos' and '.' not in os_version: + os_version = "{}.999".format(version_id) return OSRelease( - release_id=data.get('ID', '').strip('"'), + release_id=release_id, name=data.get('NAME', '').strip('"'), pretty_name=data.get('PRETTY_NAME', '').strip('"'), version=data.get('VERSION', '').strip('"'), - version_id=data.get('VERSION_ID', '').strip('"'), + version_id=os_version, variant=data.get('VARIANT', '').strip('"') or None, variant_id=data.get('VARIANT_ID', '').strip('"') or None ) diff --git a/repos/system_upgrade/common/actors/redhatsignedrpmscanner/actor.py b/repos/system_upgrade/common/actors/redhatsignedrpmscanner/actor.py index 1085beee..8416fd39 100644 --- a/repos/system_upgrade/common/actors/redhatsignedrpmscanner/actor.py +++ b/repos/system_upgrade/common/actors/redhatsignedrpmscanner/actor.py @@ -17,11 +17,28 @@ class RedHatSignedRpmScanner(Actor): tags = (IPUWorkflowTag, FactsPhaseTag) def process(self): - RH_SIGS = ['199e2f91fd431d51', + RH_SIGS = ['199e2f91fd431d51', # rhel '5326810137017186', '938a80caf21541eb', 'fd372689897da07a', - '45689c882fa658e0'] + '45689c882fa658e0', + '24c6a8a7f4a80eb5', # centos + '05b555b38483c65d', + '4eb84e71f2ee9d55', + 'a963bbdbf533f4fa', + '6c7cb6ef305d49d6', + '51d6647ec21ad6ea', # almalinux + 'd36cb86cb86b3716', + '2ae81e8aced7258b', + '15af5dac6d745a60', # rockylinux + '702d426d350d275d', + '72f97b74ec551f03', # ol + '82562ea9ad986da3', + 'bc4d06a08d8b756f', + '75c333f418cd4a9e', # eurolinux + 'b413acad6275f250', + 'f7ad3e5a1c9fd080', + 'b0b4183f192a7d7d'] # scientific signed_pkgs = InstalledRedHatSignedRPM() unsigned_pkgs = InstalledUnsignedRPM() @@ -46,7 +63,12 @@ class RedHatSignedRpmScanner(Actor): """ return ( # pylint: disable-msg=consider-using-ternary pkg.name == 'gpg-pubkey' - and pkg.packager.startswith('Red Hat, Inc.') + and (pkg.packager.startswith('Red Hat, Inc.') + or pkg.packager.startswith('CentOS') + or pkg.packager.startswith('AlmaLinux') + or pkg.packager.startswith('infrastructure@rockylinux.org') + or pkg.packager.startswith('EuroLinux') + or pkg.packager.startswith('Scientific Linux')) or all_signed ) diff --git a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py index 1cc5d64f..11c61e36 100644 --- a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py +++ b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py @@ -11,7 +11,11 @@ OBSOLETED_KEYS_MAP = { "gpg-pubkey-37017186-45761324", "gpg-pubkey-db42a60e-37ea5438", ], - 9: ["gpg-pubkey-d4082792-5b32db75"], + 9: [ + "gpg-pubkey-d4082792-5b32db75", + "gpg-pubkey-3abb34f8-5ffd890e", + "gpg-pubkey-6275f250-5e26cb2e", + ], } diff --git a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py index 9dfa0f14..3dc8e6db 100644 --- a/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py +++ b/repos/system_upgrade/common/actors/targetuserspacecreator/libraries/userspacegen.py @@ -400,9 +400,9 @@ def _prep_repository_access(context, target_userspace): 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') - _copy_certificates(context, target_userspace) if not rhsm.skip_rhsm(): + _copy_certificates(context, target_userspace) run(['rm', '-rf', os.path.join(target_etc, 'rhsm')]) context.copytree_from('/etc/rhsm', os.path.join(target_etc, 'rhsm')) # NOTE: we cannot just remove the original target yum.repos.d dir diff --git a/repos/system_upgrade/common/libraries/config/version.py b/repos/system_upgrade/common/libraries/config/version.py index 0f1e5874..5eb80c9c 100644 --- a/repos/system_upgrade/common/libraries/config/version.py +++ b/repos/system_upgrade/common/libraries/config/version.py @@ -15,8 +15,8 @@ OP_MAP = { _SUPPORTED_VERSIONS = { # Note: 'rhel-alt' is detected when on 'rhel' with kernel 4.x - '7': {'rhel': ['7.9'], 'rhel-alt': [], 'rhel-saphana': ['7.9']}, - '8': {'rhel': ['8.6', '8.8', '8.9'], 'rhel-saphana': ['8.6', '8.8']}, + '7': {'rhel': ['7.9'], 'rhel-alt': [], 'rhel-saphana': ['7.9'], 'centos': ['7.9'], 'eurolinux': ['7.9'], 'ol': ['7.9'], 'scientific': ['7.9']}, + '8': {'rhel': ['8.5', '8.6', '8.8', '8.9', '8.10'], 'rhel-saphana': ['8.6', '8.8', '8.9', '8.10'], 'centos': ['8.5', '8.999'], 'almalinux': ['8.6', '8.7', '8.8', '8.9', '8.10'], 'eurolinux': ['8.6', '8.7', '8.8', '8.9', '8.10'], 'ol': ['8.6', '8.7', '8.8', '8.9', '8.10'], 'rocky': ['8.6', '8.7', '8.8', '8.9', '8.10']}, } diff --git a/repos/system_upgrade/common/libraries/module.py b/repos/system_upgrade/common/libraries/module.py index abde69e7..7d4e8aa4 100644 --- a/repos/system_upgrade/common/libraries/module.py +++ b/repos/system_upgrade/common/libraries/module.py @@ -1,4 +1,3 @@ -import os import warnings from leapp.libraries.common.config.version import get_source_major_version @@ -23,14 +22,20 @@ def _create_or_get_dnf_base(base=None): # have repositories only for the exact system version (including the minor number). In a case when # /etc/yum/vars/releasever is present, read its contents so that we can access repositores on such systems. conf = dnf.conf.Conf() - pkg_manager = 'yum' if get_source_major_version() == '7' else 'dnf' - releasever_path = '/etc/{0}/vars/releasever'.format(pkg_manager) - if os.path.exists(releasever_path): - with open(releasever_path) as releasever_file: - releasever = releasever_file.read().strip() - conf.substitutions['releasever'] = releasever - else: - conf.substitutions['releasever'] = get_source_major_version() + + # preload releasever from what we know, this will be our fallback + conf.substitutions['releasever'] = get_source_major_version() + + # dnf on EL7 doesn't load vars from /etc/yum, so we need to help it a bit + if get_source_major_version() == '7': + try: + with open('/etc/yum/vars/releasever') as releasever_file: + conf.substitutions['releasever'] = releasever_file.read().strip() + except IOError: + pass + + # load all substitutions from etc + conf.substitutions.update_from_etc('/') base = dnf.Base(conf=conf) base.init_plugins() diff --git a/repos/system_upgrade/common/libraries/rhsm.py b/repos/system_upgrade/common/libraries/rhsm.py index 4a5b0eb0..9fdec233 100644 --- a/repos/system_upgrade/common/libraries/rhsm.py +++ b/repos/system_upgrade/common/libraries/rhsm.py @@ -92,7 +92,7 @@ def _handle_rhsm_exceptions(hint=None): def skip_rhsm(): """Check whether we should skip RHSM related code.""" - return get_env('LEAPP_NO_RHSM', '0') == '1' + return True def with_rhsm(f):