diff --git a/repos/system_upgrade/el7toel8/actors/addupgradebootentry/libraries/addupgradebootentry.py b/repos/system_upgrade/el7toel8/actors/addupgradebootentry/libraries/addupgradebootentry.py index c15dd521ddab514bb6d90547c81b2c6aba023e5b..4270bd8f96f9f3b84514e351a947add1e06273c8 100644 --- a/repos/system_upgrade/el7toel8/actors/addupgradebootentry/libraries/addupgradebootentry.py +++ b/repos/system_upgrade/el7toel8/actors/addupgradebootentry/libraries/addupgradebootentry.py @@ -17,7 +17,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', 'Anolis-Upgrade-Initramfs', '--copy-default', '--make-default', '--args', '{DEBUG} enforcing=0 rd.plymouth=0 plymouth.enable=0'.format(DEBUG=debug) diff --git a/repos/system_upgrade/el7toel8/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py b/repos/system_upgrade/el7toel8/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py index bb89c9f901c4a63dcb608170eb67b9c4b3e87b68..ccc53ae42e3c652d58d202d4e2a2c8946b65dca5 100644 --- a/repos/system_upgrade/el7toel8/actors/addupgradebootentry/tests/unit_test_addupgradebootentry.py +++ b/repos/system_upgrade/el7toel8/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', 'Anolis-Upgrade-Initramfs', '--copy-default', '--make-default', '--args', diff --git a/repos/system_upgrade/el7toel8/actors/authenticationconfigurationcollector/actor.py b/repos/system_upgrade/el7toel8/actors/authenticationconfigurationcollector/actor.py new file mode 100644 index 0000000000000000000000000000000000000000..7a72360237e7a7856116e57eec0ba54d9818a4fe --- /dev/null +++ b/repos/system_upgrade/el7toel8/actors/authenticationconfigurationcollector/actor.py @@ -0,0 +1,25 @@ +from leapp.actors import Actor +from leapp.tags import IPUWorkflowTag, ConfigurationCollectionPhaseTag +from leapp.models import ConfigurationSynchronization + +import subprocess +import json + + +class AuthenticationConfigurationCollector(Actor): + """ + Keep authentication configuration the same after migration. This is collection phase. + """ + + name = 'authentication_configuration_collector' + consumes = () + produces = (ConfigurationSynchronization, ) + tags = (IPUWorkflowTag, ConfigurationCollectionPhaseTag, ) + + def process(self): + PermitRootLogin = subprocess.check_output('cat /etc/ssh/sshd_config | grep "^PermitRootLogin" || echo "DefaultValue"', shell=True) + PasswordAuthentication = subprocess.check_output('cat /etc/ssh/sshd_config | egrep "^PasswordAuthentication" || echo "DefaultValue"', shell=True) + PermitRootLogin = str(PermitRootLogin).strip() + PasswordAuthentication = str(PasswordAuthentication).strip() + + self.produce(ConfigurationSynchronization(sshd_auth_configuration=json.dumps({"PermitRootLogin": PermitRootLogin, "PasswordAuthentication": PasswordAuthentication, }))) diff --git a/repos/system_upgrade/el7toel8/actors/authenticationconfigurationsynchronizer/actor.py b/repos/system_upgrade/el7toel8/actors/authenticationconfigurationsynchronizer/actor.py new file mode 100644 index 0000000000000000000000000000000000000000..d65707467b9cb0fe99b72d26f9b8e403c085114c --- /dev/null +++ b/repos/system_upgrade/el7toel8/actors/authenticationconfigurationsynchronizer/actor.py @@ -0,0 +1,37 @@ +from leapp.actors import Actor +from leapp.tags import IPUWorkflowTag, ConfigurationSynchronizationPhaseTag +from leapp.models import ConfigurationSynchronization + +import subprocess +import json + + +class AuthenticationConfigurationSynchronizer(Actor): + """ + Keep authentication configuration the same after migration. This is synchronization phase. + """ + + name = 'authentication_configuration_synchronizer' + consumes = (ConfigurationSynchronization, ) + produces = () + tags = (IPUWorkflowTag, ConfigurationSynchronizationPhaseTag, ) + + def process(self): + for configuration in self.consume(ConfigurationSynchronization): + if configuration.sshd_auth_configuration is None: + continue + + sshd_auth_configuration = json.loads(configuration.sshd_auth_configuration) + PermitRootLogin = sshd_auth_configuration["PermitRootLogin"] + PasswordAuthentication = sshd_auth_configuration["PasswordAuthentication"] + + if PermitRootLogin == "DefaultValue": + PermitRootLogin = "PermitRootLogin yes" + if PasswordAuthentication == "DefaultValue": + PasswordAuthentication = "# PasswordAuthentication yes" + + subprocess.run("sed -i '/PasswordAuthentication/d' /etc/ssh/sshd_config", shell=True) + subprocess.run("sed -i '/PermitRootLogin/d' /etc/ssh/sshd_config", shell=True) + subprocess.run("sed -i '$a\%s' /etc/ssh/sshd_config" % PasswordAuthentication, shell=True) + subprocess.run("sed -i '$a\%s' /etc/ssh/sshd_config" % PermitRootLogin, shell=True) + subprocess.run("systemctl restart sshd", shell=True) diff --git a/repos/system_upgrade/el7toel8/actors/checkmemory/libraries/checkmemory.py b/repos/system_upgrade/el7toel8/actors/checkmemory/libraries/checkmemory.py index e1ac56740b9a94999e7d604b1d41cfe97bd0edcc..bf6fbee9a19a4d0509e0aee0bf5e81af94933b43 100644 --- a/repos/system_upgrade/el7toel8/actors/checkmemory/libraries/checkmemory.py +++ b/repos/system_upgrade/el7toel8/actors/checkmemory/libraries/checkmemory.py @@ -5,10 +5,10 @@ from leapp.libraries.stdlib import api from leapp.models import MemoryInfo min_req_memory = { - architecture.ARCH_X86_64: 1536, # 1.5G - architecture.ARCH_ARM64: 2048, # 2Gb - architecture.ARCH_PPC64LE: 2048, # 2Gb - architecture.ARCH_S390X: 1024 # 1Gb + architecture.ARCH_X86_64: 1572864, # 1.5G + architecture.ARCH_ARM64: 2097152, # 2Gb + architecture.ARCH_PPC64LE: 2097152, # 2Gb + architecture.ARCH_S390X: 1048576 # 1Gb } @@ -33,8 +33,8 @@ def process(): if minimum_req_error: title = 'Minimum memory requirements for Anolis 8 are not met' - summary = 'Memory detected: {} KiB, required: {} KiB'.format(minimum_req_error['detected'], - minimum_req_error['minimal_req']) + summary = 'Memory detected: {} MiB, required: {} MiB'.format(int(minimum_req_error['detected'] / 1024), + int(minimum_req_error['minimal_req'] / 1024)) reporting.create_report([ reporting.Title(title), reporting.Summary(summary), diff --git a/repos/system_upgrade/el7toel8/actors/checkopenssl11libs/actor.py b/repos/system_upgrade/el7toel8/actors/checkopenssl11libs/actor.py deleted file mode 100644 index f5ca177596723f2ce8afd24c2d66753e695c54dd..0000000000000000000000000000000000000000 --- a/repos/system_upgrade/el7toel8/actors/checkopenssl11libs/actor.py +++ /dev/null @@ -1,30 +0,0 @@ -from leapp.actors import Actor -from leapp.libraries.common.rpms import has_package -from leapp.models import InstalledRPM -from leapp.reporting import Report, create_report -from leapp import reporting -from leapp.reporting import create_report -from leapp.tags import ChecksPhaseTag, IPUWorkflowTag - - -class Checkopenssl11libs(Actor): - """ - Check if openssl11-libs is installed. If yes, stop upgrade - """ - - name = 'check-openssl11-libs' - consumes = (InstalledRPM,) - produces = (Report,) - tags = (ChecksPhaseTag, IPUWorkflowTag) - - def process(self): - if has_package(InstalledRPM, 'openssl11-libs'): - create_report([ - reporting.Title('Openssl11-libs is installed, openssl11-libs cannot be processed during upgrade.'), - reporting.Summary( - 'Package openssl11-libs is conflicated with openssl-libs from Anolis OS 8 while upgrading.\n' - 'You should first backup your application files and data when your app requires openssl11-libs. Secondly, remove openssl11-libs from your OS and finally exec upgrade.'), - reporting.Severity(reporting.Severity.HIGH), - reporting.Remediation(hint='Please uninstall openssl11-libs, and then preupgrade again.'), - reporting.Flags([reporting.Flags.INHIBITOR]) - ]) diff --git a/repos/system_upgrade/el7toel8/actors/checkpkgforupgrade/actor.py b/repos/system_upgrade/el7toel8/actors/checkpkgforupgrade/actor.py index 9e420307e49afbed0f5fcad720e4925bc0bc2565..d52bdc779ed6f868979fc2333e62999d4a15ea2b 100644 --- a/repos/system_upgrade/el7toel8/actors/checkpkgforupgrade/actor.py +++ b/repos/system_upgrade/el7toel8/actors/checkpkgforupgrade/actor.py @@ -5,6 +5,9 @@ from leapp.reporting import Report, create_report from leapp import reporting from leapp.tags import ChecksPhaseTag, IPUWorkflowTag from leapp.libraries.stdlib import run +from leapp.dialogs import Dialog +from leapp.dialogs.components import BooleanComponent +import subprocess class CheckPackagesForUpgrade(Actor): @@ -17,6 +20,37 @@ class CheckPackagesForUpgrade(Actor): produces = (Report,) tags = (ChecksPhaseTag, IPUWorkflowTag) + dialogs = ( + Dialog( + scope='update_grub2-tools', + reason='Confirmation', + components=( + BooleanComponent( + key='confirm', + label='Update grub2-tools? ' + 'If no, the upgrade process will be interrupted.', + description='grub2 version is too low for system upgrade.', + reason='grub2 version must be upgrade to version >= 2.02-0.64, ' + 'otherwise system upgrade will get failed after reboot.' + ), + ) + ), + Dialog( + scope='update_python-devel', + reason='Confirmation', + components=( + BooleanComponent( + key='confirm', + label='Update python-devel ? ' + 'If not, the upgrade process will be interrupted.', + description='python-devel version is too low for system upgrade.', + reason='python-devel version must be upgrade to version >= 2.7.5-77, ' + 'otherwise system upgrade will get failed after reboot.' + ), + ) + ), + ) + def get_releasever_of_rpm(self, pkg_name): rel_ver = run(['rpm', '-q', pkg_name, '--qf', '%{RELEASE}'], split=False)['stdout'] return rel_ver @@ -50,16 +84,42 @@ class CheckPackagesForUpgrade(Actor): def process(self): if has_package(InstalledRedHatSignedRPM, 'grub2'): grub2_version = self.get_releasever_of_rpm('grub2') + if self.compare_version(grub2_version, '0.64') < 0: - commands = [['yum', '-y', 'update', 'grub2']] - create_report([ - reporting.Title('grub2 version is too low for system upgrade'), - reporting.Summary( - 'grub2 version must be upgrade to version >= 2.02-0.64, ' - 'otherwise system upgrade will get failed after reboot.' - ), - reporting.Severity(reporting.Severity.HIGH), - reporting.Flags([reporting.Flags.INHIBITOR]), - reporting.Remediation(commands=commands), - reporting.RelatedResource('package', 'grub2'), - ]) + answer = self.get_answers(self.dialogs[0]) + if answer.get('confirm') == True: + subprocess.call(['yum', 'update', '-y', 'grub2']) + else: + commands = [['yum', '-y', 'update', 'grub2']] + create_report([ + reporting.Title('grub2 version is too low for system upgrade'), + reporting.Summary( + 'grub2 version must be upgrade to version >= 2.02-0.64, ' + 'otherwise system upgrade will get failed after reboot.' + ), + reporting.Severity(reporting.Severity.HIGH), + reporting.Flags([reporting.Flags.INHIBITOR]), + reporting.Remediation(commands=commands), + reporting.RelatedResource('package', 'grub2'), + ]) + + if has_package(InstalledRedHatSignedRPM, 'python-devel'): + python_devel_version = self.get_releasever_of_rpm('python-devel') + + if self.compare_version(python_devel_version, '77.el7_6') <= 0: + answer = self.get_answers(self.dialogs[1]) + if answer.get('confirm') == True: + subprocess.call(['yum', 'update', '-y', 'python-devel']) + else: + commands = [['yum', '-y', 'update', 'python-devel']] + create_report([ + reporting.Title('python-devel version is too low for system upgrade'), + reporting.Summary( + 'python-devel version must be upgrade to version > 2.7.5-77, ' + 'otherwise system upgrade will get failed after reboot.' + ), + reporting.Severity(reporting.Severity.HIGH), + reporting.Flags([reporting.Flags.INHIBITOR]), + reporting.Remediation(commands=commands), + reporting.RelatedResource('package', 'python-devel'), + ]) diff --git a/repos/system_upgrade/el7toel8/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh b/repos/system_upgrade/el7toel8/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh index 8729a5db165a2bcf3addb0d411f8c50f925cf8ac..2ae9f7ebc8929fdc862a413df7c34b96c59649ce 100755 --- a/repos/system_upgrade/el7toel8/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh +++ b/repos/system_upgrade/el7toel8/actors/commonleappdracutmodules/files/dracut/85sys-upgrade-redhat/do-upgrade.sh @@ -70,6 +70,24 @@ do_upgrade() { ## install new product id certificates #chroot $NEWROOT /bin/sh -c 'mv -f /system-upgrade/*.pem /etc/pki/product/' + if [ -d "/sys/firmware/efi/efivars/" ]; then + cp $NEWROOT/lib64/libefi* /lib64/ + cp $NEWROOT/lib64/libfdisk* /lib64/ + if ! $NEWROOT/usr/sbin/efibootmgr | grep -i "Anolis OS"; then + efi_device=$($NEWROOT/usr/sbin/fdisk -l -o Device,Type | grep EFI\ System | sed 's/ .*//') + if [ "${efi_device}" ]; then + efi_part=${efi_device:8} + efi_device=${efi_device::8} + if [ "$(uname -m)" == "aarch64" ]; then + efi_arch="aa64" + elif [ "$(uname -m)" == "x86_64" ]; then + efi_arch="x64" + fi + $NEWROOT/usr/sbin/efibootmgr -c -d ${efi_device} -p ${efi_part} -l "/EFI/anolis/shim${efi_arch}.efi" -L "Anolis OS" + fi + fi + fi + # restore things twiddled by workarounds above. TODO: remove! if [ -f /sys/fs/selinux/enforce ]; then echo $enforce > /sys/fs/selinux/enforce diff --git a/repos/system_upgrade/el7toel8/actors/dnfpackagedownload/actor.py b/repos/system_upgrade/el7toel8/actors/dnfpackagedownload/actor.py index 8e29faaaf11af62ba1f09bc4d50bc8ba4da7513a..95c88652692b3be045819883549252b1004f94dd 100644 --- a/repos/system_upgrade/el7toel8/actors/dnfpackagedownload/actor.py +++ b/repos/system_upgrade/el7toel8/actors/dnfpackagedownload/actor.py @@ -10,6 +10,10 @@ from leapp.models import ( XFSPresence, ) from leapp.tags import DownloadPhaseTag, IPUWorkflowTag +from leapp.exceptions import RPMDownloadOrInstallError + +import sys +import traceback class DnfPackageDownload(Actor): @@ -43,7 +47,10 @@ class DnfPackageDownload(Actor): rhui_info = next(self.consume(RHUIInfo), None) on_aws = bool(rhui_info and rhui_info.provider == 'aws') - dnfplugin.perform_rpm_download( - tasks=tasks, used_repos=used_repos, target_userspace_info=target_userspace_info, - xfs_info=xfs_info, storage_info=storage_info, plugin_info=plugin_info, on_aws=on_aws - ) + try: + dnfplugin.perform_rpm_download( + tasks=tasks, used_repos=used_repos, target_userspace_info=target_userspace_info, + xfs_info=xfs_info, storage_info=storage_info, plugin_info=plugin_info, on_aws=on_aws + ) + except Exception as e: + raise RPMDownloadOrInstallError(message="fail to download rpm packages.", traceback=''.join(traceback.format_exception(*sys.exc_info()))) diff --git a/repos/system_upgrade/el7toel8/actors/dnfupgradetransaction/actor.py b/repos/system_upgrade/el7toel8/actors/dnfupgradetransaction/actor.py index 73e5a83c47a5510f3c8b11c10949cd580c5abf60..64bd3a37c9d546514f6c56455662693dafc99188 100644 --- a/repos/system_upgrade/el7toel8/actors/dnfupgradetransaction/actor.py +++ b/repos/system_upgrade/el7toel8/actors/dnfupgradetransaction/actor.py @@ -13,6 +13,8 @@ from leapp.models import ( UsedTargetRepositories, ) from leapp.tags import IPUWorkflowTag, RPMUpgradePhaseTag +import subprocess +import re class DnfUpgradeTransaction(Actor): @@ -35,6 +37,8 @@ class DnfUpgradeTransaction(Actor): produces = (TransactionCompleted,) tags = (RPMUpgradePhaseTag, IPUWorkflowTag) + grub2_migrear_prefix = 'title=MigReaR-' + def process(self): src_rhsm_info = next(self.consume(RHSMInfo), None) if src_rhsm_info: @@ -47,10 +51,35 @@ class DnfUpgradeTransaction(Actor): tasks = next(self.consume(FilteredRpmTransactionTasks), FilteredRpmTransactionTasks()) target_userspace_info = next(self.consume(TargetUserSpaceInfo), None) + output = subprocess.check_output("grubby --info=ALL", shell=True).strip() + grub_entries = output.split('index=') + + migrear_entries = [] + for entry in grub_entries: + if self.grub2_migrear_prefix in entry: + kernel = re.findall(r"kernel=(/.*)\n", entry) + nargs = re.findall(r"args=(.*)\n", entry) + initrd = re.findall(r"initrd=(.*)\n", entry) + title = re.findall(r"title=(.*)\n", entry) + if len(kernel) == 1 and len(initrd) == 1 and len(title) == 1: + migrear_entries += [{ + "kernel": kernel[0], + "args": nargs[0] if len(nargs) == 1 else "", + "initrd": initrd[0], + "title": title[0], + }] + dnfplugin.perform_transaction_install( tasks=tasks, used_repos=used_repos, storage_info=storage_info, target_userspace_info=target_userspace_info, plugin_info=plugin_info ) + + for entry in migrear_entries: + try: + subprocess.check_call("grubby --copy-default --add-kernel %s --initrd %s --args=%s --title=%s" % (entry['kernel'], entry['initrd'], entry['args'], entry['title']), shell=True) + except Exception as e: + self.log.info(" ".join(["Failed restore migrear entry", str(entry), "Exception:", str(e)]), exc_info=True) + self.produce(TransactionCompleted()) userspace = next(self.consume(TargetUserSpaceInfo), None) if userspace: diff --git a/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/actor.py b/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/actor.py index e1ce3038d8ea5dc526bbe5087cde61ca08a027db..e0feea3a5d8f939dbe2bf0ca511d410c24d61e64 100644 --- a/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/actor.py +++ b/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/actor.py @@ -4,7 +4,7 @@ from leapp.libraries.actor.checkkerneldrivers import ( get_present_drivers, get_removed_drivers, ) -from leapp.models import PCIDevices +from leapp.models import (PCIDevices, CustomTargetRepository) from leapp.reporting import Report, create_report from leapp import reporting from leapp.tags import ChecksPhaseTag, IPUWorkflowTag @@ -23,12 +23,22 @@ class CheckKernelDrivers(Actor): files/removed_drivers.txt file. """ name = 'check_kernel_drivers' - consumes = (PCIDevices,) + consumes = (PCIDevices, CustomTargetRepository) produces = (Report,) tags = (ChecksPhaseTag, IPUWorkflowTag) def process(self): - removed_file = 'files/removed_drivers.txt' + toANCK = False + removed_file = '' + for repo in self.consume(CustomTargetRepository): + if repo.repoid == 'anolis_plus': + toANCK = True + break + if toANCK == True: + removed_file = 'files/removed_drivers_anck.txt' + else: + removed_file = 'files/removed_drivers_rhck.txt' + conflicting = check_drivers(get_removed_drivers(removed_file), get_present_drivers()) if conflicting: diff --git a/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/files/removed_drivers_anck.txt b/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/files/removed_drivers_anck.txt new file mode 100644 index 0000000000000000000000000000000000000000..1ab9e3e8f0d4bb70f2ca4ee6ebae6c69a7a48fc2 --- /dev/null +++ b/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/files/removed_drivers_anck.txt @@ -0,0 +1,69 @@ +# Support for the following device drivers has been removed in Anolis 8. + +at91_ether +osdblk +ebt_ulog +ablk_helper +pcompress +salsa20-x86_64 +zlib +gve +hid-lenovo-tpkbd +hid-ps3remote +hmcdrv +iavf +idma64 +igc +ib_ipath +ipg +gpio-ir-recv +ir-lirc-codec +ir-rc5-sz-decoder +dell-led +rtsx_pci +rtsx_usb +nft_meta_bridge +nft_exthdr +nft_meta +nft_rbtree +pata_arasan_cf +pata_cs5536 +pch_dma +pch_gbe +pch_phub +ptp_pch +rtw88 +rtwpci +libsrp +scsi_tgt +snd-firewire-speakers +snd-scs1x +snd-tea575x-tuner +wacom +uio_pdrv_genirq +vringh +videobuf-dvb +btcx-risc +mt9v011 +output +stk1160 +poseidon +tvp5150 +w83697hf_wdt +w83697ug_wdt +xen-acpi-processor +dvb-usb-friio +dvb-usb-it913x +ipt_ULOG +xgmac +sctp_probe +nf_conntrack_ipv4 +nf_conntrack_ipv6 +nfnetlink_cthelper +libore +objlayoutdriver +snd-soc-sst-baytrail-pcm +stm_p_basic +stm_p_sys-t +i7300_idle +it913x-fe diff --git a/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/files/removed_drivers.txt b/repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/files/removed_drivers_rhck.txt similarity index 100% rename from repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/files/removed_drivers.txt rename to repos/system_upgrade/el7toel8/actors/kernel/checkkerneldrivers/files/removed_drivers_rhck.txt diff --git a/repos/system_upgrade/el7toel8/actors/scancustomrepofile/libraries/scancustomrepofile.py b/repos/system_upgrade/el7toel8/actors/scancustomrepofile/libraries/scancustomrepofile.py index c294193dca4e398cfd6f87828cef0e6a2bb7a998..a5a30bd2be556440cad7c3b8cb951932462c9909 100644 --- a/repos/system_upgrade/el7toel8/actors/scancustomrepofile/libraries/scancustomrepofile.py +++ b/repos/system_upgrade/el7toel8/actors/scancustomrepofile/libraries/scancustomrepofile.py @@ -3,7 +3,7 @@ import os from leapp.libraries.common import repofileutils from leapp.libraries.stdlib import api from leapp.models import CustomTargetRepository, CustomTargetRepositoryFile - +from leapp.libraries.common import config CUSTOM_REPO_PATH = "/etc/leapp/files/leapp_upgrade_repositories.repo" @@ -26,10 +26,14 @@ def process(): if not repofile.data: return api.produce(CustomTargetRepositoryFile(file=CUSTOM_REPO_PATH)) + disablelist=[] + if config.get_env('LEAPP_DISABLE_REPOS'): + disablelist = [repoid for repoid in config.get_env('LEAPP_DISABLE_REPOS').split(',')] for repo in repofile.data: - api.produce(CustomTargetRepository( - repoid=repo.repoid, - name=repo.name, - baseurl=repo.baseurl, - enabled=repo.enabled, - )) + if repo.enabled and repo.repoid not in disablelist: + api.produce(CustomTargetRepository( + repoid=repo.repoid, + name=repo.name, + baseurl=repo.baseurl, + enabled=repo.enabled, + )) diff --git a/repos/system_upgrade/el7toel8/actors/serviceconfigurationcollector/actor.py b/repos/system_upgrade/el7toel8/actors/serviceconfigurationcollector/actor.py new file mode 100644 index 0000000000000000000000000000000000000000..fbee73223930a8be7e2f2db92731343d1ee1ed5a --- /dev/null +++ b/repos/system_upgrade/el7toel8/actors/serviceconfigurationcollector/actor.py @@ -0,0 +1,27 @@ +import subprocess +import json + +from leapp.actors import Actor +from leapp.tags import ConfigurationCollectionPhaseTag, IPUWorkflowTag +from leapp.models import ConfigurationSynchronization + + +class ServiceConfigurationCollector(Actor): + """ + No documentation has been provided for the service_configuration_collector actor. + """ + + name = 'service_configuration_collector' + consumes = () + produces = (ConfigurationSynchronization, ) + tags = (ConfigurationCollectionPhaseTag, IPUWorkflowTag, ) + + def process(self): + self.log.info("Starting to backup service configurations.") + services_config_raw = subprocess.check_output("systemctl list-unit-files | egrep 'enabled|disabled'", shell=True).decode("utf-8").strip() + services_config = { + line.strip().split()[0]: line.strip().split()[1][:-1] + for line in services_config_raw.split('\n') + } + self.produce(ConfigurationSynchronization(services_configuration=json.dumps(services_config))) + diff --git a/repos/system_upgrade/el7toel8/actors/serviceconfigurationsynchronizer/actor.py b/repos/system_upgrade/el7toel8/actors/serviceconfigurationsynchronizer/actor.py new file mode 100644 index 0000000000000000000000000000000000000000..5f57b4b88ffb74e36399efdca5545cb18b5219a6 --- /dev/null +++ b/repos/system_upgrade/el7toel8/actors/serviceconfigurationsynchronizer/actor.py @@ -0,0 +1,105 @@ +import json +import subprocess + +from leapp.actors import Actor +from leapp.tags import ConfigurationSynchronizationPhaseTag, IPUWorkflowTag +from leapp.models import ConfigurationSynchronization + + +class ServiceConfigurationSynchronizer(Actor): + """ + No documentation has been provided for the service_configuration_synchronizer actor. + """ + + name = 'service_configuration_synchronizer' + consumes = (ConfigurationSynchronization, ) + produces = () + tags = (IPUWorkflowTag, ConfigurationSynchronizationPhaseTag, ) + + def service_configuration_backup(self): + try: + self.log.info("backing up service configurations after migration.") + services_config_raw = str(subprocess.check_output("systemctl list-unit-files | egrep 'enabled |disabled ' | awk '{print $1,$2}'", shell=True)).strip() + services_config = { + line.strip().split()[0]: line.strip().split()[1][:-1] + for line in services_config_raw.split('\n') + } + + return services_config + except Exception as e: + self.log.warning(" fail to backup service, ignore it. " + str(e)) + + return {} + + def do_config_services(self, config): + config_report = [] + for service, status in config.items(): + self.log.info("".join((service, " -> ", status))) + report = { + "service": service, + "old status": status, + "current status": status, + } + + try: + print("systemctl %s %s" % (status, service)) + output = str(subprocess.check_call("systemctl %s %s" % (status, service), shell=True)).strip() + report.update({ + "information": output, + "result": "succeed" + }) + + except Exception as e: + self.log.warning("fail to %s %s" % (status, service)) + + report.update({ + "information": str(e), + "result": "fail", + }) + + config_report += [report] + + return config_report + + def config_services(self, config, backup): + _config_report = self.do_config_services(config) + + config_report = [] + for line in _config_report: + if line["result"] == "fail": + line["current status"] = backup.get(line["service"] , "does not exist") + + config_report += [line] + + return config_report + + def service_configuration_restore(self, backup_configuration): + try: + self.log.info("Starting to roll back services configurations.") + self.do_config_services(backup_configuration) + + except Exception as e: + self.log.warning("fail to roll back services configurations: " + str(e)) + self.log.warning("default service configuration : " + str(backup_configuration)) + with open("/var/log/leapp/service-default.log", "w") as f: + json.dump(str(backup_configuration), f, indent=4) + + def process(self): + backup_configuratuon = self.service_configuration_backup() + + try: + self.log.info("Starting to synchronize services configurations.") + for configuration in self.consume(ConfigurationSynchronization): + if configuration.services_configuration is None: + continue + + services_configuration = json.loads(configuration.services_configuration) + config_report = self.config_services(services_configuration, backup_configuratuon) + + with open("/var/log/leapp/service-configuration-report.json", "w") as f: + json.dump(config_report, f, indent=4) + print("Service configuration output: /var/log/leapp/service-configuration-report.json") + + except Exception as e: + self.log.warning("fail to synchronize services configurations, rolling back. " + str(e)) + diff --git a/repos/system_upgrade/el7toel8/actors/systemrequirementschecker/actor.py b/repos/system_upgrade/el7toel8/actors/systemrequirementschecker/actor.py new file mode 100644 index 0000000000000000000000000000000000000000..242a6ff7b7a60ab12cc4b5913f485ff4eea9dae5 --- /dev/null +++ b/repos/system_upgrade/el7toel8/actors/systemrequirementschecker/actor.py @@ -0,0 +1,31 @@ +from leapp.actors import Actor +from leapp import tags +from leapp.libraries.actor import systemchecker + +from leapp.exceptions import SystemEnvironmentCheckError, FailureInSystemEnvironmentCheckError +import sys +import traceback + + +class SystemRequirementsChecker(Actor): + """ + No documentation has been provided for the system_requirements_checker actor. + """ + + name = 'system_requirements_checker' + consumes = () + produces = () + tags = (tags.FactsPhaseTag, tags.IPUWorkflowTag, ) + + def process(self): + sc = systemchecker.SystemChecker() + vm_info = sc.virtual_memory() + partition = sc.partition_size_from_directory("/var/lib/leapp/") + + try: + assert partition['free'] >= 4 * 1024 * 1024 * 1024 and vm_info['free'] >= 600 * 1024 * 1024, "To ensure the migration, this machine must have 4G free space on disk and 600M RAM available." + assert sc.initd_is_symlink(), "It is crucial that /etc/init.d be a symlink to rc.d/init.d by default." + except AssertionError as e: + raise SystemEnvironmentCheckError(message=e.message, traceback=''.join(traceback.format_exception(*sys.exc_info()))) + except Exception as e: + raise FailureInSystemEnvironmentCheckError(message="Exception raised in system requirements check.", traceback=''.join(traceback.format_exception(*sys.exc_info()))) diff --git a/repos/system_upgrade/el7toel8/actors/systemrequirementschecker/libraries/systemchecker.py b/repos/system_upgrade/el7toel8/actors/systemrequirementschecker/libraries/systemchecker.py new file mode 100644 index 0000000000000000000000000000000000000000..f77dde8e4845618bbb77189b53d3b2c10807040b --- /dev/null +++ b/repos/system_upgrade/el7toel8/actors/systemrequirementschecker/libraries/systemchecker.py @@ -0,0 +1,33 @@ +import subprocess +import os +import sys +import psutil + + +class SystemChecker(object): + def partition_size_from_directory(self, directory): + statvfs = os.statvfs(directory) + return { + "free": statvfs.f_frsize * statvfs.f_bfree, + "total": statvfs.f_frsize * statvfs.f_blocks, + "blocks": statvfs.f_blocks, + "freeblocks": statvfs.f_bfree, + "blocksize": statvfs.f_frsize, + } + + def virtual_memory(self): + mem_info = psutil.virtual_memory() + return { + "free": mem_info.available, + "total": mem_info.total, + } + + def is_symlink(self, directory): + return os.path.islink(directory) + + def initd_is_symlink(self, initd_directory="/etc/init.d"): + is_symlink = self.is_symlink(initd_directory) + if not is_symlink: + return False + link_path = os.readlink(initd_directory) + return link_path == "rc.d/init.d" or link_path == "/etc/rc.d/init.d" diff --git a/repos/system_upgrade/el7toel8/actors/verifycheckresults/libraries/verifycheckresults.py b/repos/system_upgrade/el7toel8/actors/verifycheckresults/libraries/verifycheckresults.py index 63e65e81da83e58d3466cfeacc1195ff6678a801..a127b333acab31c430df82d3db471e7883db8d19 100644 --- a/repos/system_upgrade/el7toel8/actors/verifycheckresults/libraries/verifycheckresults.py +++ b/repos/system_upgrade/el7toel8/actors/verifycheckresults/libraries/verifycheckresults.py @@ -1,8 +1,19 @@ from leapp.exceptions import RequestStopAfterPhase from leapp.libraries.stdlib import api from leapp.reporting import Report +from leapp.libraries.common import smc_interface +inhibitor_list = [] +inhibitor_flag = 0 def check(): - if [msg for msg in api.consume(Report) if 'inhibitor' in msg.report.get('flags', [])]: + for msg in api.consume(Report): + if 'inhibitor' in msg.report.get('flags', []): + global inhibitor_flag + inhibitor_flag = 1 + inhibitor_list.append(str(msg.report.get('title', []))) + + if inhibitor_flag == 1: + # The err_msg length is currently limited to 512, which can be adjusted + smc_interface.update_progress_infomation(err_no=199, err_msg="|".join(inhibitor_list)[:512]) raise RequestStopAfterPhase() diff --git a/repos/system_upgrade/el7toel8/models/configurationsynchronization.py b/repos/system_upgrade/el7toel8/models/configurationsynchronization.py new file mode 100644 index 0000000000000000000000000000000000000000..1133674f27ea4d2d39ee3f74dc0a59dcea022f6d --- /dev/null +++ b/repos/system_upgrade/el7toel8/models/configurationsynchronization.py @@ -0,0 +1,8 @@ +from leapp.models import Model, fields +from leapp.topics import ConfigurationSynchronizationTopic + +class ConfigurationSynchronization(Model): + topic = ConfigurationSynchronizationTopic + services_configuration = fields.Nullable(fields.String()) + sshd_auth_configuration = fields.Nullable(fields.String()) + diff --git a/repos/system_upgrade/el7toel8/tags/configurationcollectionphase.py b/repos/system_upgrade/el7toel8/tags/configurationcollectionphase.py new file mode 100644 index 0000000000000000000000000000000000000000..a24ec82b976766bef005cb539bae42340d7705ea --- /dev/null +++ b/repos/system_upgrade/el7toel8/tags/configurationcollectionphase.py @@ -0,0 +1,5 @@ +from leapp.tags import Tag + + +class ConfigurationCollectionPhaseTag(Tag): + name = 'configuration_collection_phase' diff --git a/repos/system_upgrade/el7toel8/tags/configurationsynchronizationphase.py b/repos/system_upgrade/el7toel8/tags/configurationsynchronizationphase.py new file mode 100644 index 0000000000000000000000000000000000000000..81610a892bc2e0fc754d1f42dfc0086146885d71 --- /dev/null +++ b/repos/system_upgrade/el7toel8/tags/configurationsynchronizationphase.py @@ -0,0 +1,5 @@ +from leapp.tags import Tag + + +class ConfigurationSynchronizationPhaseTag(Tag): + name = 'configuration_synchronization_phase' diff --git a/repos/system_upgrade/el7toel8/topics/configurationsynchronization.py b/repos/system_upgrade/el7toel8/topics/configurationsynchronization.py new file mode 100644 index 0000000000000000000000000000000000000000..8d01b38563e22129d8f76a7e883fbe9adace5077 --- /dev/null +++ b/repos/system_upgrade/el7toel8/topics/configurationsynchronization.py @@ -0,0 +1,5 @@ +from leapp.topics import Topic + + +class ConfigurationSynchronizationTopic(Topic): + name = 'configuration_synchronization' diff --git a/repos/system_upgrade/el7toel8/workflows/inplace_upgrade.py b/repos/system_upgrade/el7toel8/workflows/inplace_upgrade.py index 8e48d8c938d82a110e4e729391a6ae4a15845b30..c0dd27ec2303e9e9e165c8bbf95e1f0ab57375fd 100644 --- a/repos/system_upgrade/el7toel8/workflows/inplace_upgrade.py +++ b/repos/system_upgrade/el7toel8/workflows/inplace_upgrade.py @@ -16,6 +16,19 @@ class IPUWorkflow(Workflow): configuration = IPUConfig description = """The IPU workflow takes care of an in-place upgrade (IPU) of RHEL 7 to Anolis 8.""" + class ConfigurationCollectionPhase(Phase): + """ + This phase and ConfigurationSynchronizationPhase must appear in pairs to ensure the configuration + before and after migration remains as similar as possible. + + This part is configuration collection phase. + """ + name = "ConfigurationCollection" + filter = TagFilter(tags.ConfigurationCollectionPhaseTag) + policies = Policies(Policies.Errors.FailPhase, + Policies.Retry.Phase) + flags = Flags() + class FactsCollectionPhase(Phase): """ Get information (facts) about the system (e.g. installed packages, configuration, ...). @@ -210,6 +223,19 @@ class IPUWorkflow(Workflow): Policies.Retry.Phase) flags = Flags(restart_after_phase=True) + class ConfigurationSynchronizationPhase(Phase): + """ + This phase and ConfigurationCollectionPhase must appear in pairs to ensure the configuration + before and after migration remains as similar as possible. + + This part is configuration Synchronization phase. + """ + name = "ConfigurationSynchronization" + filter = TagFilter(tags.ConfigurationSynchronizationPhaseTag) + policies = Policies(Policies.Errors.FailPhase, + Policies.Retry.Phase) + flags = Flags() + class FirstBootPhase(Phase): """Actions to be done right after booting into the upgraded system."""