diff --git a/repos/system_upgrade/el7toel8/actors/checkbaota/actor.py b/repos/system_upgrade/el7toel8/actors/checkbaota/actor.py index af256b2d07dce129a9981f2bc31aec33b7224582..0c6d81190decf0af59673bdabf1301f57f785161 100644 --- a/repos/system_upgrade/el7toel8/actors/checkbaota/actor.py +++ b/repos/system_upgrade/el7toel8/actors/checkbaota/actor.py @@ -29,7 +29,6 @@ class Checkbaota(Actor): 'You should first backup your application files and data when baota requires openssl-libs. Secondly, install new version for baota after migration and recover the data.'), reporting.Severity(reporting.Severity.HIGH), reporting.Remediation(hint='Please uninstall baota, and then preupgrade again.'), - reporting.Flags([reporting.Flags.INHIBITOR]) ]) except: pass diff --git a/repos/system_upgrade/el7toel8/actors/checkbtrfs/actor.py b/repos/system_upgrade/el7toel8/actors/checkbtrfs/actor.py index 74e431f03a298e63554f6d0d4bfef5e8fbf5d6b2..a9c530f7c8171e71699b77f8bbdc19050379bae8 100644 --- a/repos/system_upgrade/el7toel8/actors/checkbtrfs/actor.py +++ b/repos/system_upgrade/el7toel8/actors/checkbtrfs/actor.py @@ -1,8 +1,13 @@ +import subprocess + from leapp.actors import Actor from leapp.models import ActiveKernelModulesFacts from leapp.tags import ChecksPhaseTag, IPUWorkflowTag from leapp import reporting from leapp.reporting import Report, create_report +from leapp.libraries.stdlib import api +from leapp.dialogs import Dialog +from leapp.dialogs.components import BooleanComponent class CheckBtrfs(Actor): @@ -18,16 +23,44 @@ class CheckBtrfs(Actor): produces = (Report,) tags = (ChecksPhaseTag, IPUWorkflowTag) + dialogs = ( + Dialog( + scope='remove_btrfs_module', + reason='Confirmation', + components=( + BooleanComponent( + key='confirm', + label='Remove btrfs module? ' + 'If no, the upgrade process will be interrupted.', + description='Btrfs has been removed from Anolis 8.', + default=True, + reason='Btrfs filesystem was deprecated on versions 6.6 and 7.4 and will not be present in Anolis 8. ' + ), + ) + ), + ) + def process(self): for fact in self.consume(ActiveKernelModulesFacts): for active_module in fact.kernel_modules: if active_module.filename == 'btrfs': + command = "rmmod btrfs" + answer = self.get_answers(self.dialogs[0]) + if answer.get('confirm') == True: + try: + subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + api.current_logger().error('remove btrfs module failed: {}'.format(e)) + else: + api.current_logger().info('remove btrfs module succeeded: {}'.format(command)) + return + create_report([ - reporting.Title('Btrfs has been removed from Anolis8'), + reporting.Title('Btrfs has been removed from Anolis 8'), reporting.Summary( 'The Btrfs file system was introduced as Technology Preview with the ' 'initial release of Red Hat Enterprise Linux 6 and Red Hat Enterprise Linux 7. As of ' - 'versions 6.6 and 7.4 this technology has been deprecated and removed in Anolis8.' + 'versions 6.6 and 7.4 this technology has been deprecated and removed in Anolis 8.' ), reporting.Severity(reporting.Severity.HIGH), reporting.Flags([reporting.Flags.INHIBITOR]), diff --git a/repos/system_upgrade/el7toel8/actors/checkfstabxfsoptions/actor.py b/repos/system_upgrade/el7toel8/actors/checkfstabxfsoptions/actor.py index 06c5f3256868986846e8525c95604642e46769d4..1e4494308e626a4494c77e41de84492c15fb9b00 100644 --- a/repos/system_upgrade/el7toel8/actors/checkfstabxfsoptions/actor.py +++ b/repos/system_upgrade/el7toel8/actors/checkfstabxfsoptions/actor.py @@ -3,7 +3,8 @@ from leapp.libraries.actor import checkfstabxfsoptions from leapp.models import StorageInfo from leapp.reporting import Report from leapp.tags import ChecksPhaseTag, IPUWorkflowTag - +from leapp.dialogs import Dialog +from leapp.dialogs.components import BooleanComponent class CheckFstabXFSOptions(Actor): """ @@ -22,6 +23,27 @@ class CheckFstabXFSOptions(Actor): consumes = (StorageInfo,) produces = (Report,) tags = (ChecksPhaseTag, IPUWorkflowTag) + + dialogs = ( + Dialog( + scope='change_fstab_xfs_options', + reason='Confirmation', + components=( + BooleanComponent( + key='confirm', + label='Change fstab xfs options? ' + 'If no, the upgrade process will be interrupted.', + description='Deprecated XFS mount options present in fstab.', + default=True, + reason='Some XFS mount options are not supported.' + ), + ) + ), + ) + + def is_confirm(self): + answer = self.get_answers(self.dialogs[0]) + return answer.get('confirm') def process(self): - checkfstabxfsoptions.process() + checkfstabxfsoptions.process(self.is_confirm) diff --git a/repos/system_upgrade/el7toel8/actors/checkfstabxfsoptions/libraries/checkfstabxfsoptions.py b/repos/system_upgrade/el7toel8/actors/checkfstabxfsoptions/libraries/checkfstabxfsoptions.py index c74772fb2ae444a8560472f40ba00ad6a19538f7..8d84939e047944b2c2459b9ea7b3e79d637e00d7 100644 --- a/repos/system_upgrade/el7toel8/actors/checkfstabxfsoptions/libraries/checkfstabxfsoptions.py +++ b/repos/system_upgrade/el7toel8/actors/checkfstabxfsoptions/libraries/checkfstabxfsoptions.py @@ -1,3 +1,5 @@ +import subprocess + from leapp import reporting from leapp.exceptions import StopActorExecutionError from leapp.libraries.stdlib import api @@ -27,7 +29,7 @@ def _get_storage_data(): return storage -def process(): +def process(is_confirm): storage = _get_storage_data() used_removed_options = set() for entry in storage.fstab: @@ -40,6 +42,16 @@ def process(): if not used_removed_options: return + command = "sed -i 's/\(\S\+\s\+\S\+\s\+xfs\s\+\)\S\+/\\1defaults/' /etc/fstab" + if is_confirm() == True: + try: + subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + api.current_logger().error('comment out XFS mount failed: {}'.format(e)) + else: + api.current_logger().info('comment out XFS mount succeeded: {}'.format(command)) + return + list_separator_fmt = '\n - ' reporting.create_report([ reporting.Title('Deprecated XFS mount options present in FSTAB.'), diff --git a/repos/system_upgrade/el7toel8/actors/checknfs/actor.py b/repos/system_upgrade/el7toel8/actors/checknfs/actor.py index 47626f74ffc5e29a7a843cb420886205c5bba9b9..d322d8e3a5c2fc56b88ec8054aef33a49d6d343b 100644 --- a/repos/system_upgrade/el7toel8/actors/checknfs/actor.py +++ b/repos/system_upgrade/el7toel8/actors/checknfs/actor.py @@ -1,9 +1,13 @@ +import subprocess + from leapp.actors import Actor from leapp.models import StorageInfo from leapp.reporting import Report, create_report from leapp import reporting from leapp.tags import ChecksPhaseTag, IPUWorkflowTag - +from leapp.libraries.stdlib import api +from leapp.dialogs import Dialog +from leapp.dialogs.components import BooleanComponent class CheckNfs(Actor): """ @@ -16,6 +20,23 @@ class CheckNfs(Actor): consumes = (StorageInfo,) produces = (Report,) tags = (ChecksPhaseTag, IPUWorkflowTag,) + + dialogs = ( + Dialog( + scope='cancle_nfs_mount_in_fstab', + reason='Confirmation', + components=( + BooleanComponent( + key='confirm', + label='Cancle nfs mount in fstab? ' + 'If no, the upgrade process will be interrupted.', + description='Deprecated NFS mount present in /etc/fstab.', + default=True, + reason='NFS is currently not supported by the inplace upgrade.' + ), + ) + ), + ) def process(self): details = "NFS is currently not supported by the inplace upgrade.\n" \ @@ -44,18 +65,29 @@ class CheckNfs(Actor): # mountpoint is not available in the model systemd_nfs_mounts.append(" - {}\n".format(systemdmount.node)) - if any((fstab_nfs_mounts, nfs_mounts, systemd_nfs_mounts)): - if fstab_nfs_mounts: - details += "- NFS shares found in /etc/fstab:\n" - details += ''.join(fstab_nfs_mounts) + if nfs_mounts: + details += "- NFS shares currently mounted:\n" + details += ''.join(nfs_mounts) - if nfs_mounts: - details += "- NFS shares currently mounted:\n" - details += ''.join(nfs_mounts) + if systemd_nfs_mounts: + details += "- NFS mounts configured with systemd-mount:\n" + details += ''.join(systemd_nfs_mounts) - if systemd_nfs_mounts: - details += "- NFS mounts configured with systemd-mount:\n" - details += ''.join(systemd_nfs_mounts) + if fstab_nfs_mounts: + details += "- NFS shares found in /etc/fstab:\n" + details += ''.join(fstab_nfs_mounts) + api.current_logger().info(details) + + command = "sed -i '/nfs/ s/^/#/' /etc/fstab" + answer = self.get_answers(self.dialogs[0]) + if answer.get('confirm') == True: + try: + subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + api.current_logger().error('comment out NFS mount failed: {}'.format(e)) + else: + api.current_logger().info('comment out NFS mount succeeded: {}'.format(command)) + return fstab_related_resource = [reporting.RelatedResource('file', '/etc/fstab')] if fstab_nfs_mounts else [] @@ -64,8 +96,8 @@ class CheckNfs(Actor): reporting.Summary(details), reporting.Severity(reporting.Severity.HIGH), reporting.Tags([ - reporting.Tags.FILESYSTEM, - reporting.Tags.NETWORK + reporting.Tags.FILESYSTEM, + reporting.Tags.NETWORK ]), reporting.Remediation(hint='Disable NFS temporarily for the upgrade if possible.'), reporting.Flags([reporting.Flags.INHIBITOR]), diff --git a/repos/system_upgrade/el7toel8/actors/checkrootsymlinks/actor.py b/repos/system_upgrade/el7toel8/actors/checkrootsymlinks/actor.py index ab7c5ca098653b59a1984441f00f3e20660649e9..0666559e9d166a85a33d267550bdff48139a8af1 100644 --- a/repos/system_upgrade/el7toel8/actors/checkrootsymlinks/actor.py +++ b/repos/system_upgrade/el7toel8/actors/checkrootsymlinks/actor.py @@ -1,11 +1,14 @@ import os +import subprocess from leapp import reporting from leapp.actors import Actor from leapp.exceptions import StopActorExecutionError from leapp.models import Report, RootDirectory from leapp.tags import IPUWorkflowTag, ChecksPhaseTag - +from leapp.libraries.stdlib import api +from leapp.dialogs import Dialog +from leapp.dialogs.components import BooleanComponent class CheckRootSymlinks(Actor): """ @@ -18,6 +21,23 @@ class CheckRootSymlinks(Actor): consumes = (RootDirectory,) produces = (Report,) tags = (IPUWorkflowTag, ChecksPhaseTag) + + dialogs = ( + Dialog( + scope='change_root_symlinks', + reason='Confirmation', + components=( + BooleanComponent( + key='confirm', + label='Change symlinks in root directory? ' + 'If no, the upgrade process will be interrupted.', + description='Upgrade requires links in root directory to be relative.', + default=True, + reason='After rebooting, parts of the upgrade process can fail if symbolic links in / point to absolute paths. ' + ), + ) + ), + ) def process(self): rootdir = next(self.consume(RootDirectory), None) @@ -32,6 +52,16 @@ class CheckRootSymlinks(Actor): os.path.relpath(item.target, '/'), os.path.join('/', item.name)]) for item in absolute_links] remediation = [['sh', '-c', ' && '.join(commands)]] + answer = self.get_answers(self.dialogs[0]) + if answer.get('confirm') == True: + try: + subprocess.check_output(commands, shell=True, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + api.current_logger().error('change symlinks to relative paths failed: {}'.format(e)) + else: + api.current_logger().info('change symlinks to relative paths succeeded: {}'.format(commands)) + return + reporting.create_report([ reporting.Title('Upgrade requires links in root directory to be relative'), reporting.Summary( diff --git a/repos/system_upgrade/el7toel8/actors/efibootorderfix/actor.py b/repos/system_upgrade/el7toel8/actors/efibootorderfix/actor.py index 41cf69014ad776599aefdd300732e624aceb04b5..d30f33477ba6cda5085c36d95813dc4ac7aadc57 100644 --- a/repos/system_upgrade/el7toel8/actors/efibootorderfix/actor.py +++ b/repos/system_upgrade/el7toel8/actors/efibootorderfix/actor.py @@ -1,10 +1,13 @@ import os +import subprocess from leapp.actors import Actor from leapp import reporting from leapp.tags import ChecksPhaseTag, IPUWorkflowTag from leapp.models import FirmwareFacts - +from leapp.libraries.stdlib import api +from leapp.dialogs import Dialog +from leapp.dialogs.components import BooleanComponent class EfiCheckBoot(Actor): """ @@ -16,6 +19,23 @@ class EfiCheckBoot(Actor): produces = (reporting.Report,) tags = (ChecksPhaseTag, IPUWorkflowTag) + dialogs = ( + Dialog( + scope='install_efibootmgr', + reason='Confirmation', + components=( + BooleanComponent( + key='confirm', + label='Install efibootmgr? ' + 'If no, the upgrade process will be interrupted.', + description='efibootmgr package is required on EFI systems.', + default=True, + reason='efibootmgr is required so that we can set proper boot options in between restarts. ' + ), + ) + ), + ) + def process(self): is_system_efi = False has_efibootmgr = os.path.exists('/sbin/efibootmgr') @@ -25,12 +45,23 @@ class EfiCheckBoot(Actor): break if is_system_efi and not has_efibootmgr: + command = "yum install -y efibootmgr" + answer = self.get_answers(self.dialogs[0]) + if answer.get('confirm') == True: + try: + subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + api.current_logger().error('install efibootmgr failed: {}'.format(e)) + else: + api.current_logger().info('install efibootmgr succeeded: {}'.format(command)) + return + reporting.create_report([ reporting.Title('efibootmgr package is required on EFI systems'), reporting.Summary( 'efibootmgr is required so that we can can set proper boot options in between restarts' ), - reporting.Remediation(commands=[['yum', '-y', 'install', 'efibootmgr']]), + reporting.Remediation(commands=[[command]]), reporting.RelatedResource('package', 'efibootmgr'), reporting.Flags([reporting.Flags.INHIBITOR]), reporting.Severity(reporting.Severity.HIGH), diff --git a/repos/system_upgrade/el7toel8/actors/kernel/checkinstalledkernels/actor.py b/repos/system_upgrade/el7toel8/actors/kernel/checkinstalledkernels/actor.py index 1c78b529e2ded6358da356f156c4f6b012d2023f..78f1e5ade9994fe925dfef7152547b4996c0d17e 100644 --- a/repos/system_upgrade/el7toel8/actors/kernel/checkinstalledkernels/actor.py +++ b/repos/system_upgrade/el7toel8/actors/kernel/checkinstalledkernels/actor.py @@ -45,7 +45,7 @@ class CheckInstalledKernels(Actor): label='Remove extra kernel? ' 'If no, the upgrade process will be interrupted.', description='Newest installed kernel not in use.', - default=False, + default=True, reason='To ensure a stable upgrade, the machine needs to be ' 'booted into the latest installed kernel.' ), diff --git a/repos/system_upgrade/el7toel8/actors/kernel/checkinstalledkernels/libraries/checkinstalledkernels.py b/repos/system_upgrade/el7toel8/actors/kernel/checkinstalledkernels/libraries/checkinstalledkernels.py index 3c0ccfa871062e1656c3a43db9d4a5367104abbf..dee39db944996b9c622831af52a2c5522c949ce9 100644 --- a/repos/system_upgrade/el7toel8/actors/kernel/checkinstalledkernels/libraries/checkinstalledkernels.py +++ b/repos/system_upgrade/el7toel8/actors/kernel/checkinstalledkernels/libraries/checkinstalledkernels.py @@ -77,7 +77,7 @@ def get_newest_evr(pkgs): packages have same name. """ if not pkgs: - return None + return () rpms_evr = _get_pkgs_evr(pkgs) newest_evr = rpms_evr.pop() @@ -89,15 +89,14 @@ def get_newest_evr(pkgs): def get_newer_evr(pkgs, current_evr): if not pkgs: - return None + return () newer_evr = [] rpms_evr = _get_pkgs_evr(pkgs) for pkg in rpms_evr: if labelCompare(current_evr, pkg) < 0: newer_evr.append(pkg) - print(newer_evr) - return newer_evr + return tuple(newer_evr) def process(is_confirm): @@ -111,8 +110,28 @@ def process(is_confirm): # Hypothatical, user is not allowed to install any kernel that is not signed by RH # In case we would like to be cautious, we could check whether there are no other # kernels installed as well. - api.current_logger().error('Cannot find any installed kernel signed by Red Hat.') - raise StopActorExecutionError('Cannot find any installed kernel signed by Red Hat.') + command = "yum install -y kernel" + try: + subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + api.current_logger().error('install kernel failed: {}'.format(e)) + title = 'Cannot find any installed kernel signed by Red Hat' + summary = ('The upgrade process does not handle well the case when kernel that is not signed by Red Hat. ' + 'Please install the RPM package named kernel.') + reporting.create_report([ + reporting.Title(title), + reporting.Summary(summary), + reporting.Severity(reporting.Severity.HIGH), + reporting.Tags([reporting.Tags.KERNEL, reporting.Tags.BOOT]), + reporting.Flags([reporting.Flags.INHIBITOR]), + reporting.Remediation( + hint="Install kernel package", + commands=[[command]], + ), + reporting.RelatedResource('package', 'kernel') + ]) + else: + api.current_logger().info('install kernel succeeded: {}'.format(command)) if len(all_kernel_pkgs) > 1 and architecture.matches_architecture(architecture.ARCH_S390X): # It's temporary solution, so no need to try automatize everything.