From b9c0815e58cae4d744fb4540df389e06d35a03e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Sun, 31 Mar 2019 18:48:13 +0200 Subject: [PATCH] Fixed creation of image metadata files At the end of a build process the metadata information files .packages and .verified are created. On rpm based systems, rpm is invoked as chrooted operation inside the new root tree. For images that gets installed exclusively from the bootstrap phase there is no rpm inside of the image and the call fails. The result are empty metadata files. This patch prevents calling rpm inside of the image root tree if it's not installed and also uses the RpmDataBase interface instead of directly calling rpm. This Fixes #1037 --- kiwi/system/setup.py | 35 +++++----- test/unit/system_setup_test.py | 122 ++++++++++++++------------------- 2 files changed, 67 insertions(+), 90 deletions(-) diff --git a/kiwi/system/setup.py b/kiwi/system/setup.py index bb15abab..cd5fd898 100644 --- a/kiwi/system/setup.py +++ b/kiwi/system/setup.py @@ -38,6 +38,7 @@ from kiwi.path import Path from kiwi.archive.tar import ArchiveTar from kiwi.utils.compress import Compress from kiwi.utils.command_capabilities import CommandCapabilities +from kiwi.utils.rpm_database import RpmDataBase from kiwi.exceptions import ( KiwiImportDescriptionError, @@ -959,11 +960,9 @@ class SystemSetup(object): def _export_rpm_package_list(self, filename): log.info('Export rpm packages metadata') - dbpath = self._get_rpm_database_location() - if dbpath: - dbpath_option = ['--dbpath', dbpath] - else: - dbpath_option = [] + dbpath_option = [ + '--dbpath', self._get_rpm_database_location() + ] query_call = Command.run( [ 'rpm', '--root', self.root_dir, '-qa', '--qf', @@ -976,7 +975,9 @@ class SystemSetup(object): ] + dbpath_option ) with open(filename, 'w') as packages: - packages.write(os.linesep.join(sorted(query_call.output.splitlines()))) + packages.write( + os.linesep.join(sorted(query_call.output.splitlines())) + ) packages.write(os.linesep) def _export_deb_package_list(self, filename): @@ -994,16 +995,16 @@ class SystemSetup(object): ] ) with open(filename, 'w') as packages: - packages.write(os.linesep.join(sorted(query_call.output.splitlines()))) + packages.write( + os.linesep.join(sorted(query_call.output.splitlines())) + ) packages.write(os.linesep) def _export_rpm_package_verification(self, filename): log.info('Export rpm verification metadata') - dbpath = self._get_rpm_database_location() - if dbpath: - dbpath_option = ['--dbpath', dbpath] - else: - dbpath_option = [] + dbpath_option = [ + '--dbpath', self._get_rpm_database_location() + ] query_call = Command.run( command=['rpm', '--root', self.root_dir, '-Va'] + dbpath_option, raise_on_error=False @@ -1024,9 +1025,7 @@ class SystemSetup(object): verified.write(query_call.output) def _get_rpm_database_location(self): - try: - return Command.run( - ['chroot', self.root_dir, 'rpm', '-E', '%_dbpath'] - ).output.rstrip('\r\n') - except Exception: - return None + rpmdb = RpmDataBase(self.root_dir) + if rpmdb.has_rpm(): + return rpmdb.rpmdb_image.expand_query('%_dbpath') + return rpmdb.rpmdb_host.expand_query('%_dbpath') diff --git a/test/unit/system_setup_test.py b/test/unit/system_setup_test.py index d5b8e7e4..c0193d85 100644 --- a/test/unit/system_setup_test.py +++ b/test/unit/system_setup_test.py @@ -12,8 +12,7 @@ from kiwi.xml_description import XMLDescription from kiwi.xml_state import XMLState from kiwi.exceptions import ( KiwiScriptFailed, - KiwiImportDescriptionError, - KiwiCommandError + KiwiImportDescriptionError ) from kiwi.defaults import Defaults @@ -619,7 +618,8 @@ class TestSystemSetup(object): ) mock_command.assert_called_once_with([ 'bash', '-c', - 'cd root_dir && bash --norc /root_dir/image/edit_boot_config.sh ext4 1' + 'cd root_dir && bash --norc /root_dir/image/edit_boot_config.sh ' + 'ext4 1' ]) @patch('kiwi.command.Command.call') @@ -644,7 +644,8 @@ class TestSystemSetup(object): ) mock_command.assert_called_once_with([ 'bash', '-c', - 'cd root_dir && bash --norc /root_dir/image/edit_boot_install.sh my_image.raw /dev/mapper/loop0p1' + 'cd root_dir && bash --norc /root_dir/image/edit_boot_install.sh ' + 'my_image.raw /dev/mapper/loop0p1' ]) @raises(KiwiScriptFailed) @@ -822,26 +823,44 @@ class TestSystemSetup(object): ) @patch('kiwi.system.setup.Command.run') + @patch('kiwi.system.setup.RpmDataBase') @patch_open def test_export_package_list_rpm( - self, mock_open, mock_command + self, mock_open, mock_RpmDataBase, mock_command ): + rpmdb = mock.Mock() + rpmdb.rpmdb_image.expand_query.return_value = 'image_dbpath' + rpmdb.rpmdb_host.expand_query.return_value = 'host_dbpath' + rpmdb.has_rpm.return_value = True + mock_RpmDataBase.return_value = rpmdb command = mock.Mock() command.output = 'packages_data' mock_command.return_value = command result = self.setup.export_package_list('target_dir') assert result == 'target_dir/some-image.x86_64-1.2.3.packages' - mock_command.assert_has_calls([ - call(['chroot', 'root_dir', 'rpm', '-E', '%_dbpath']), - call([ + mock_command.assert_called_once_with( + [ 'rpm', '--root', 'root_dir', '-qa', '--qf', - '%{NAME}|%{EPOCH}|%{VERSION}|%{RELEASE}|%{ARCH}|%{DISTURL}|%{LICENSE}\\n', - '--dbpath', 'packages_data' - ]) - ]) + '%{NAME}|%{EPOCH}|%{VERSION}|%{RELEASE}|%{ARCH}|' + '%{DISTURL}|%{LICENSE}\\n', + '--dbpath', 'image_dbpath' + ] + ) mock_open.assert_called_once_with( 'target_dir/some-image.x86_64-1.2.3.packages', 'w' ) + rpmdb.has_rpm.return_value = False + mock_command.reset_mock() + result = self.setup.export_package_list('target_dir') + assert result == 'target_dir/some-image.x86_64-1.2.3.packages' + mock_command.assert_called_once_with( + [ + 'rpm', '--root', 'root_dir', '-qa', '--qf', + '%{NAME}|%{EPOCH}|%{VERSION}|%{RELEASE}|%{ARCH}|' + '%{DISTURL}|%{LICENSE}\\n', + '--dbpath', 'host_dbpath' + ] + ) @patch_open def test_setup_machine_id(self, mock_open): @@ -865,34 +884,6 @@ class TestSystemSetup(object): self.setup.setup_permissions() mock_log_warn.assert_called_once() - @patch('kiwi.system.setup.Command.run') - @patch_open - def test_export_package_list_rpm_no_dbpath( - self, mock_open, mock_command - ): - cmd = mock.Mock() - cmd.output = 'packages_data' - - def dbpath_check_fails(command): - if '%_dbpath' in command: - raise KiwiCommandError() - else: - return cmd - - mock_command.side_effect = dbpath_check_fails - result = self.setup.export_package_list('target_dir') - assert result == 'target_dir/some-image.x86_64-1.2.3.packages' - mock_command.assert_has_calls([ - call(['chroot', 'root_dir', 'rpm', '-E', '%_dbpath']), - call([ - 'rpm', '--root', 'root_dir', '-qa', '--qf', - '%{NAME}|%{EPOCH}|%{VERSION}|%{RELEASE}|%{ARCH}|%{DISTURL}|%{LICENSE}\\n' - ]) - ]) - mock_open.assert_called_once_with( - 'target_dir/some-image.x86_64-1.2.3.packages', 'w' - ) - @patch('kiwi.system.setup.Command.run') @patch_open def test_export_package_list_dpkg( @@ -915,52 +906,39 @@ class TestSystemSetup(object): ) @patch('kiwi.system.setup.Command.run') + @patch('kiwi.system.setup.RpmDataBase') @patch_open def test_export_package_verification( - self, mock_open, mock_command + self, mock_open, mock_RpmDataBase, mock_command ): + rpmdb = mock.Mock() + rpmdb.rpmdb_image.expand_query.return_value = 'image_dbpath' + rpmdb.rpmdb_host.expand_query.return_value = 'host_dbpath' + rpmdb.has_rpm.return_value = True + mock_RpmDataBase.return_value = rpmdb command = mock.Mock() command.output = 'verification_data' mock_command.return_value = command result = self.setup.export_package_verification('target_dir') assert result == 'target_dir/some-image.x86_64-1.2.3.verified' - mock_command.assert_has_calls([ - call(['chroot', 'root_dir', 'rpm', '-E', '%_dbpath']), - call(command=[ + mock_command.assert_called_once_with( + command=[ 'rpm', '--root', 'root_dir', '-Va', - '--dbpath', 'verification_data' - ], raise_on_error=False) - ]) + '--dbpath', 'image_dbpath' + ], raise_on_error=False + ) mock_open.assert_called_once_with( 'target_dir/some-image.x86_64-1.2.3.verified', 'w' ) - - @patch('kiwi.system.setup.Command.run') - @patch_open - def test_export_package_verification_no_dbpath( - self, mock_open, mock_command - ): - cmd = mock.Mock() - cmd.output = 'verification_data' - - def dbpath_check_fails(command, raise_on_error): - if '%_dbpath' in command: - raise KiwiCommandError() - else: - return cmd - - mock_command.side_effect = dbpath_check_fails + rpmdb.has_rpm.return_value = False + mock_command.reset_mock() result = self.setup.export_package_verification('target_dir') assert result == 'target_dir/some-image.x86_64-1.2.3.verified' - mock_command.assert_has_calls([ - call(['chroot', 'root_dir', 'rpm', '-E', '%_dbpath']), - call( - command=['rpm', '--root', 'root_dir', '-Va'], - raise_on_error=False - ) - ]) - mock_open.assert_called_once_with( - 'target_dir/some-image.x86_64-1.2.3.verified', 'w' + mock_command.assert_called_once_with( + command=[ + 'rpm', '--root', 'root_dir', '-Va', + '--dbpath', 'host_dbpath' + ], raise_on_error=False ) @patch('kiwi.system.setup.Command.run')