From 4defcdc578c00890c0510394ba09ac5381484bd7 Mon Sep 17 00:00:00 2001 From: Adam Hosek Date: Wed, 24 Jul 2024 15:33:44 +0200 Subject: [PATCH] [RHELC-1427] Fix rpm -Va parsing and improve speed Fix rpm -Va parsing to accept also ghosts files. Do not generate message about invalid output of lines related to ghosts files anymore. Those files aren't backed up as they are temporary. Extend rpm -Va command by --nodeps switch. This improves speed of the command and doesn't generate unimportant info about unsatisfied dependencies for packages. --- .../actions/pre_ponr_changes/backup_system.py | 7 +++- convert2rhel/systeminfo.py | 4 ++- .../pre_ponr_changes/backup_system_test.py | 35 +++++++++++++++++++ convert2rhel/unit_tests/systeminfo_test.py | 2 +- .../test_basic_sanity_checks.py | 2 +- 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/convert2rhel/actions/pre_ponr_changes/backup_system.py b/convert2rhel/actions/pre_ponr_changes/backup_system.py index 4ffbca9a70..5e1a1dfb05 100644 --- a/convert2rhel/actions/pre_ponr_changes/backup_system.py +++ b/convert2rhel/actions/pre_ponr_changes/backup_system.py @@ -38,7 +38,7 @@ # Match unix path: # [\/\\](?:(?!\.\s+)\S)+(\.)? RPM_VA_REGEX = re.compile( - r"^(missing|([S\.\?][M\.\?][5\.\?][D\.\?][L\.\?][U\.\?][G\.\?][T\.\?][P\.\?]))\s+[cdlr\s+]\s+[\/\\](?:(?!\.\s+)\S)+(\.)?$" + r"^(missing|([S\.\?][M\.\?][5\.\?][D\.\?][L\.\?][U\.\?][G\.\?][T\.\?][P\.\?]))\s+[cdlrg\s+]\s+[\/\\](?:(?!\.\s+)\S)+(\.)?$" ) @@ -153,6 +153,11 @@ def run(self): backed_up_paths = ["/etc/yum.repos.d", "/etc/yum/vars", "/etc/dnf/vars"] for file in package_files_changes: + # Ghost files can be skipped since those files are generated during the package run, usually temporary. + # We don't need to backup those type of files as was discussed under RHELC-1427 + if file["file_type"] == "g": + continue + if file["status"] == "missing": missing_file = MissingFile(file["path"]) backup.backup_control.push(missing_file) diff --git a/convert2rhel/systeminfo.py b/convert2rhel/systeminfo.py index d7cb7e46eb..7b96b9ae34 100644 --- a/convert2rhel/systeminfo.py +++ b/convert2rhel/systeminfo.py @@ -390,7 +390,9 @@ def generate_rpm_va(self, log_filename=PRE_RPM_VA_LOG_FILENAME): " minutes. It can be disabled by using the" " --no-rpm-va option." ) - rpm_va, _ = utils.run_subprocess(["rpm", "-Va"], print_output=False) + # Discussed under RHELC-1427, `--nodeps` will skip verification of package dependencies, + # avoiding unnecessary packages lookup. + rpm_va, _ = utils.run_subprocess(["rpm", "-Va", "--nodeps"], print_output=False) output_file = os.path.join(logger.LOG_DIR, log_filename) utils.store_content_to_file(output_file, rpm_va) self.logger.info("The 'rpm -Va' output has been stored in the %s file." % output_file) diff --git a/convert2rhel/unit_tests/actions/pre_ponr_changes/backup_system_test.py b/convert2rhel/unit_tests/actions/pre_ponr_changes/backup_system_test.py index bf1f51f781..aabaed301f 100644 --- a/convert2rhel/unit_tests/actions/pre_ponr_changes/backup_system_test.py +++ b/convert2rhel/unit_tests/actions/pre_ponr_changes/backup_system_test.py @@ -293,6 +293,14 @@ def test_backup_package_file_run( ], (True, True), ), + ( + [ + "S.5.?..T. c {path}/filename0", + "S.5.?..T. g {path}/filename1", + "S.5.?..T. c {path}/filename2", + ], + (True, False, True), + ), ), ) def test_backup_package_file_complete( @@ -391,6 +399,33 @@ def test_backup_package_file_complete( elif status == "missing": assert not os.path.isfile(original_file_path) + @pytest.mark.parametrize( + ("rpm_va_output"), + ( + ( + """S.5.?..T. g /path/filename_0, + missing g /path/filename_1""", + ) + ), + ) + def test_backup_package_file_ghost_files( + self, monkeypatch, rpm_va_output, backup_package_files_action, tmpdir, global_backup_control, caplog + ): + """Test if ghost files are skipped correctly.""" + rpm_va_logfile_path = os.path.join(str(tmpdir), PRE_RPM_VA_LOG_FILENAME) + with open(rpm_va_logfile_path, "w") as f: + f.write(rpm_va_output) + global_backup_control_push = mock.Mock() + + monkeypatch.setattr(files, "BACKUP_DIR", str(tmpdir)) + monkeypatch.setattr(backup_system, "LOG_DIR", str(tmpdir)) + monkeypatch.setattr(global_backup_control, "push", global_backup_control_push) + + backup_package_files_action.run() + + assert global_backup_control_push.call_count == 0 + assert "Skipping invalid output" not in caplog.text + class TestBackupRepository: def test_backup_repository_complete(self, monkeypatch, tmpdir, backup_repository_action, global_backup_control): diff --git a/convert2rhel/unit_tests/systeminfo_test.py b/convert2rhel/unit_tests/systeminfo_test.py index ed5eb897a6..3d15f79774 100644 --- a/convert2rhel/unit_tests/systeminfo_test.py +++ b/convert2rhel/unit_tests/systeminfo_test.py @@ -54,7 +54,7 @@ def test_generate_rpm_va(self, global_tool_opts, monkeypatch, tmpdir): # Check that rpm -Va is executed (default) assert utils.run_subprocess.called - assert utils.run_subprocess.call_args_list[0][0][0] == ["rpm", "-Va"] + assert utils.run_subprocess.call_args_list[0][0][0] == ["rpm", "-Va", "--nodeps"] # Check that the output was stored into the specific file. assert os.path.isfile(rpmva_output_file) diff --git a/tests/integration/tier0/non-destructive/basic-sanity-checks/test_basic_sanity_checks.py b/tests/integration/tier0/non-destructive/basic-sanity-checks/test_basic_sanity_checks.py index df2098200e..fe9028dd69 100644 --- a/tests/integration/tier0/non-destructive/basic-sanity-checks/test_basic_sanity_checks.py +++ b/tests/integration/tier0/non-destructive/basic-sanity-checks/test_basic_sanity_checks.py @@ -294,7 +294,7 @@ def test_analyze_no_rpm_va_option(convert2rhel): """ with convert2rhel("analyze -y --no-rpm-va --debug") as c2r: c2r.expect("We will proceed with ignoring the --no-rpm-va option") - c2r.expect_exact("Calling command 'rpm -Va'") + c2r.expect_exact("Calling command 'rpm -Va --nodeps'") c2r.sendcontrol("c") assert c2r.exitstatus == 1