diff --git a/kiwi/schema/kiwi.rnc b/kiwi/schema/kiwi.rnc
index c6a9062b96f..e029c613ee9 100644
--- a/kiwi/schema/kiwi.rnc
+++ b/kiwi/schema/kiwi.rnc
@@ -3702,7 +3702,7 @@ div {
attribute type {
"bootstrap" | "delete" | "docker" | "image" |
"iso" | "oem" | "pxe" | "kis" | "oci" |
- "uninstall"
+ "uninstall" | "systemfiles"
}
k.packages.profiles.attribute = k.profiles.attribute
k.packages.patternType.attribute =
diff --git a/kiwi/schema/kiwi.rng b/kiwi/schema/kiwi.rng
index 4ea5fe26277..409d4dded60 100644
--- a/kiwi/schema/kiwi.rng
+++ b/kiwi/schema/kiwi.rng
@@ -5587,6 +5587,7 @@ packages are only installed if this build type is requested.
kis
oci
uninstall
+ systemfiles
diff --git a/kiwi/system/root_import/base.py b/kiwi/system/root_import/base.py
index 738a4996105..ccd4ac708f7 100644
--- a/kiwi/system/root_import/base.py
+++ b/kiwi/system/root_import/base.py
@@ -123,6 +123,9 @@ def overlay_finalize(self, xml_state: XMLState) -> None:
with open(systemfiles, 'a') as systemfiles_fd:
# copy on write makes this file to become part of the delta
systemfiles_fd.write(os.linesep)
+ with open(f'{systemfiles}.libs', 'a') as systemlibs_fd:
+ # copy on write makes this file to become part of the delta
+ systemlibs_fd.write(os.linesep)
# Umount and rename upper to be the new root
self.overlay.umount()
diff --git a/kiwi/system/setup.py b/kiwi/system/setup.py
index dc3fac541d5..5f36cfc5da3 100644
--- a/kiwi/system/setup.py
+++ b/kiwi/system/setup.py
@@ -625,7 +625,9 @@ def export_modprobe_setup(self, target_root_dir: str) -> None:
options=['-a']
)
- def export_package_file_list(self, target_dir: str, file_name: str) -> str:
+ def export_flake_pilot_system_file_list(
+ self, target_dir: str, file_name: str
+ ) -> str:
"""
Export image package file list to the target_dir
and filename
@@ -638,7 +640,7 @@ def export_package_file_list(self, target_dir: str, file_name: str) -> str:
)
result_file = os.path.normpath(f'{target_dir}/{file_name}')
if packager == 'rpm':
- self._export_rpm_file_list(result_file)
+ self._export_rpm_flake_pilot_system_file_list(result_file)
return result_file
return ''
@@ -829,10 +831,10 @@ def call_edit_boot_install_script(
def create_system_files(self) -> None:
"""
- Create file list of packages
+ Create file list of packages to be used by flake-pilot
"""
if self.xml_state.build_type.get_provide_system_files():
- self.export_package_file_list(
+ self.export_flake_pilot_system_file_list(
self.root_dir, Defaults.get_system_files_name()
)
@@ -1346,22 +1348,85 @@ def _text(self, section_content):
if section_content:
return section_content[0]
- def _export_rpm_file_list(self, filename):
- log.info('Export rpm packages file list')
+ def _export_rpm_flake_pilot_system_file_list(self, filename):
+ log.info('Export rpm packages system file list for flake-pilot')
dbpath_option = [
'--dbpath', self._get_rpm_database_location()
]
+ skip_list = self.xml_state.get_system_files_ignore_packages()
query_call = Command.run(
- [
- 'rpm', '--root', self.root_dir,
- '--noartifact', '--noghost', '-qal'
- ] + dbpath_option
+ ['rpm', '--root', self.root_dir, '-qa'] + dbpath_option
)
- with open(filename, 'w', encoding='utf-8') as packagefiles:
- packagefiles.write(
- os.linesep.join(sorted(query_call.output.splitlines()))
- )
- packagefiles.write(os.linesep)
+ libcheck = [
+ '/lib', '/usr/lib', '/lib64', '/usr/lib64'
+ ]
+ packmeta = {}
+ for package in query_call.output.splitlines():
+ skip = False
+ for skip_package in skip_list:
+ if package.startswith(skip_package):
+ skip = True
+ break
+ if not skip and package:
+ package = package.strip()
+ packmeta[package] = {}
+ query_call = Command.run(
+ [
+ 'rpm', '--root', self.root_dir, '-ql',
+ '--noghost', '--dump', package
+ ] + dbpath_option
+ )
+ for raw in query_call.output.splitlines():
+ meta = raw.lstrip().split(' ')
+ if len(meta) == 11:
+ islib = False
+ for libpath in libcheck:
+ if meta[0].startswith(libpath):
+ islib = True
+ break
+ packmeta[package][meta[0]] = {
+ 'islib': islib,
+ 'isdoc': True if meta[8] == '1' else False,
+ 'islink': True if meta[10] != 'X' else False,
+ 'linkname': meta[10]
+ }
+
+ with open(filename, 'w', encoding='utf-8') as systemfiles:
+ for package in packmeta.keys():
+ for file in packmeta[package].keys():
+ meta = packmeta[package][file]
+ if not meta['isdoc'] and not meta['islib']:
+ systemfiles.write(f'{file}{os.linesep}')
+
+ with open(f'{filename}.libs', 'w', encoding='utf-8') as systemlibs:
+ for package in packmeta.keys():
+ for file in packmeta[package].keys():
+ meta = packmeta[package][file]
+ if meta['islib']:
+ if meta['islink']:
+ systemlibs.write(f'{file}{os.linesep}')
+ elif not self._has_link_target(packmeta, file):
+ systemlibs.write(f'{file}{os.linesep}')
+
+ def _has_link_target(
+ self, packages: Dict[str, Dict[str, Dict[str, str]]], filename: str
+ ) -> bool:
+ if 'ld-linux' in filename:
+ # exceptional case. /lib.../ld-linux-* could be a
+ # symlink to /usr/bin/ld.so but only providing
+ # /usr/bin/ld.so is not enough to call programs.
+ # Thus in this case we indicate the file has no link
+ # target such that the later pilot sync takes it
+ # into account.
+ return False
+ for package in packages.keys():
+ for file in packages[package].keys():
+ meta = packages[package][file]
+ base_filename = os.path.basename(filename)
+ base_linkname = os.path.basename(meta['linkname'])
+ if meta['islink'] and base_filename == base_linkname:
+ return True
+ return False
def _export_rpm_package_list(self, filename):
log.info('Export rpm packages metadata')
diff --git a/kiwi/xml_state.py b/kiwi/xml_state.py
index 36454e11b0e..9dca9754ddf 100644
--- a/kiwi/xml_state.py
+++ b/kiwi/xml_state.py
@@ -732,6 +732,17 @@ def get_ignore_packages(self, section_type: str) -> List:
result.append(package.get_name().strip())
return sorted(result)
+ def get_system_files_ignore_packages(self) -> List[str]:
+ """
+ List of ignore package names from the type="systemfiles"
+ packages section(s)
+
+ :return: package names
+
+ :rtype: list
+ """
+ return self.get_ignore_packages('systemfiles')
+
def get_system_ignore_packages(self) -> List:
"""
List of ignore package names from the packages sections matching
diff --git a/test/data/example_config.xml b/test/data/example_config.xml
index 79b2a888b9f..3cc92053dbc 100644
--- a/test/data/example_config.xml
+++ b/test/data/example_config.xml
@@ -260,4 +260,9 @@
+
+
+
+
+
diff --git a/test/data/rpm_ql_dump_glibc b/test/data/rpm_ql_dump_glibc
new file mode 100644
index 00000000000..5c86eccd0cd
--- /dev/null
+++ b/test/data/rpm_ql_dump_glibc
@@ -0,0 +1,48 @@
+/etc/bindresvport.blacklist 415 1733214801 4b0166e286cb27b577940432c6e39614b143b0d2c207dd3533906a19956e2c04 0100644 root root 1 0 0 X
+/etc/gai.conf 0 1733214826 0000000000000000000000000000000000000000000000000000000000000000 0100644 root root 1 0 0 X
+/etc/ld.so.cache 0 1733214801 0000000000000000000000000000000000000000000000000000000000000000 0100644 root root 1 0 0 X
+/etc/ld.so.conf 206 1733214801 0ad7a03c5985fc18c3ee981325a60a7c3f8a169151b9cd653ddfe2e77f01fa26 0100644 root root 1 0 0 X
+/etc/nsswitch.conf 2190 1733214801 6e084899135cda5df149d95e3dc79f22d1b4367b7c3b2fd74582d02be3c785cf 0100644 root root 1 0 0 X
+/etc/rpc 1634 1733214698 3b24a975dcde688434258566813a83ce256a4c73efd7a8a9c3998327b0b4de68 0100644 root root 1 0 0 X
+/lib64/ld-linux-x86-64.so.2 243504 1733214804 c70459f7af50cbae25fe31df8344062ee83b2963675e32ee103fd10a8a7be5df 0100755 root root 0 0 0 X
+/lib64/ld-lsb-x86-64.so.3 20 1733214811 0000000000000000000000000000000000000000000000000000000000000000 0120777 root root 0 0 0 ld-linux-x86-64.so.2
+/lib64/libBrokenLocale.so.1 7560 1733214804 ba61bdf8b15c60bc81a2fa080f22fb39126ace4029d7f6e6d3a483ff91a41129 0100755 root root 0 0 0 X
+/lib64/libanl.so.1 7384 1733214804 d53507cacee2da3cdc82b9f4736f2acdd8b39d756f65a12bddc6fb8707d038b3 0100755 root root 0 0 0 X
+/lib64/libc.so.6 2449760 1733214804 d51f437bdf319de3d2c37443316c98541987603308a834a5511330c6bb1c91b8 0100755 root root 0 0 0 X
+/lib64/libc_malloc_debug.so.0 66640 1733214804 76901cfa755ad9fe4669982f311b1b417f720ce8984253a668e496d4b9400b49 0100755 root root 0 0 0 X
+/lib64/libdl.so.2 7552 1733214804 1f2534a7db24829fdc8b32b6a16938b5a52efde17f1e175ded9a8cab2bde1b2c 0100755 root root 0 0 0 X
+/lib64/libm.so.6 1037488 1733214804 f1e5e586ee981e8efec0eb149126118a3e4644502f939831ff1daaf474beb44c 0100755 root root 0 0 0 X
+/lib64/libmvec.so.1 1076328 1733214804 730556bf17e863368aab990007f8b505563712ea2323a866779302c9bb92745f 0100755 root root 0 0 0 X
+/lib64/libnss_compat.so.2 45672 1733214804 fe63514a1f16aef4587c81808310b2fc7d1a2c2180938839b3a5744e76276d4b 0100755 root root 0 0 0 X
+/lib64/libnss_db.so.2 40864 1733214804 8c848c3462df5ab90a8d3d6e5576449949e5ad55631423b546c9f3097e0030d2 0100755 root root 0 0 0 X
+/lib64/libnss_dns.so.2 7056 1733214804 6e1e6a5a863b549240168c3cf6542fd798d30a8c81c9e9fbb3baa7d82d809b4c 0100755 root root 0 0 0 X
+/lib64/libnss_files.so.2 7056 1733214804 e4c4621713e92c81673c80850b041828a1aa6b9b6dcd6b1ef8cf20d95e63a743 0100755 root root 0 0 0 X
+/lib64/libnss_hesiod.so.2 26680 1733214804 d8984863043b1a087d66bfd3f7a8f6a9d73b0df4144942b5cac4a0a4bbcd1af6 0100755 root root 0 0 0 X
+/lib64/libpthread.so.0 8408 1733214804 4f9d2dca66e07c9206190f9b6dde9ddc6eb3de5883865f5a0f365590d3cb528b 0100755 root root 0 0 0 X
+/lib64/libresolv.so.2 73640 1733214804 d9c7d53ab627c3f116e2520c6bd29fa4403295ba02af73d95430e38fb9ba1876 0100755 root root 0 0 0 X
+/lib64/librt.so.1 8176 1733214804 84bf7cec9a66333c1d33a93bd9d8f2d7211e25c8a4f328aa2739983c5b84da0b 0100755 root root 0 0 0 X
+/lib64/libthread_db.so.1 49216 1733214804 5a0a2cf166b6207d905fc6f3e4d5dad6774d9bc76be81a58e28a6ef6ad51971a 0100755 root root 0 0 0 X
+/lib64/libutil.so.1 7392 1733214804 ab7afc07bdc5be89ff703dc808b43c6dbc3c4885848b9463d5c5b7d243fac8a3 0100755 root root 0 0 0 X
+/sbin/ldconfig 1073856 1733214804 86143be7fb0e7619d9eb8153591491f2e3ab821a9cdb44483954eb6fdf443f23 0100755 root root 0 0 0 X
+/usr/bin/gencat 27120 1733214804 9754597fd4521fd9b2392fb91fbaea756d81a6bd9fe4d39929db38f9719c5aef 0100755 root root 0 0 0 X
+/usr/bin/getconf 22 1733214811 0000000000000000000000000000000000000000000000000000000000000000 0120777 root root 0 0 0 ../lib/getconf/getconf
+/usr/bin/getent 31616 1733214804 715f8eaf7d145853008a8169a4fb42ffa5a182288c609b827d9d2e9d5ca14872 0100755 root root 0 0 0 X
+/usr/bin/iconv 64432 1733214804 a645cdd3ce6fa2c10ee097db9866cc199d8f3d15095c312a8a170b7acd21c9ef 0100755 root root 0 0 0 X
+/usr/bin/ld.so 27 1733214811 0000000000000000000000000000000000000000000000000000000000000000 0120777 root root 0 0 0 /lib64/ld-linux-x86-64.so.2
+/usr/bin/ldd 5372 1733214700 d89312068d0940fc9ae75eac6f81ff60ca6750318567c4dd0caa646d966f6cd9 0100755 root root 0 0 0 X
+/usr/bin/locale 51112 1733214804 9e1cc2506dc7aaa94db572320331481f92be2c6dad78a7cfc46b7988e2c6d847 0100755 root root 0 0 0 X
+/usr/bin/localedef 336352 1733214804 fcee441a70cb59c6c709838582f6fc2ff015dfa4f4350d8a1f117847a9f8502e 0100755 root root 0 0 0 X
+/usr/lib/getconf 0 1733214804 0000000000000000000000000000000000000000000000000000000000000000 040755 root root 0 0 0 X
+/usr/lib/getconf/POSIX_V6_LP64_OFF64 31064 1733214804 347bece701b32a42b6cc545e9f63640765cfb493b9cc1c68507483a53c2db984 0100755 root root 0 0 0 X
+/usr/lib/getconf/POSIX_V7_LP64_OFF64 31064 1733214804 347bece701b32a42b6cc545e9f63640765cfb493b9cc1c68507483a53c2db984 0100755 root root 0 0 0 X
+/usr/lib/getconf/XBS5_LP64_OFF64 31064 1733214804 347bece701b32a42b6cc545e9f63640765cfb493b9cc1c68507483a53c2db984 0100755 root root 0 0 0 X
+/usr/lib/getconf/getconf 31064 1733214804 347bece701b32a42b6cc545e9f63640765cfb493b9cc1c68507483a53c2db984 0100755 root root 0 0 0 X
+/usr/sbin/iconvconfig 31376 1733214805 4cde0a5234ffd3caf7907f35a5e4b3de08eab17115bedd062cca4d19c17d2464 0100755 root root 0 0 0 X
+/usr/share/doc/packages/glibc 0 1733214826 0000000000000000000000000000000000000000000000000000000000000000 040755 root root 0 0 0 X
+/usr/share/doc/packages/glibc/gai.conf 2584 1690826056 76a5771adee7b9f36c7ae66eae78d72f325557500269107f2d98a7e3560a1808 0100644 root root 0 1 0 X
+/usr/share/licenses/glibc 0 1733214826 0000000000000000000000000000000000000000000000000000000000000000 040755 root root 0 0 0 X
+/usr/share/licenses/glibc/LICENSES 18943 1690826056 b33d0bd9f685b46853548814893a6135e74430d12f6d94ab3eba42fc591f83bc 0100644 root root 0 0 0 X
+/usr/share/man/man1/gencat.1.gz 2619 1733214801 2aa75ddeb08e1772018ed74fe8bc1f1c4467c49c0a939052a2fe6ce2211f07da 0100644 root root 0 1 0 X
+/usr/share/man/man1/getconf.1.gz 2346 1733214801 ec3d91ae40cbbf7aafb047a4799c25e00a04d340c0febe83d72f66ca2dfc7dc0 0100644 root root 0 1 0 X
+/usr/share/man/man5/locale.alias.5.gz 949 1733214801 397f8cd51dc51c12e1b387201c40191e72bc5b9a92ffa77a0864505e5bc0ec86 0100644 root root 0 1 0 X
+/var/cache/ldconfig 0 1733214801 0000000000000000000000000000000000000000000000000000000000000000 040700 root root 0 0 0 X
diff --git a/test/unit/system/root_import/base_test.py b/test/unit/system/root_import/base_test.py
index 6a51154a9e8..437474c8094 100644
--- a/test/unit/system/root_import/base_test.py
+++ b/test/unit/system/root_import/base_test.py
@@ -132,6 +132,7 @@ def test_overlay_finalize(
]
# create removed files metadata for later host provisioning
assert file_handle.write.call_args_list == [
+ call('\n'),
call('\n'),
call('/file_a'), call(os.linesep),
call('/file_b'), call(os.linesep)
diff --git a/test/unit/system/setup_test.py b/test/unit/system/setup_test.py
index e9db0949735..0b6a7f43da2 100644
--- a/test/unit/system/setup_test.py
+++ b/test/unit/system/setup_test.py
@@ -1286,10 +1286,10 @@ def test_export_package_list_unknown_packager(
assert self.setup.export_package_list('target_dir') == ''
@patch('kiwi.defaults.Defaults.get_default_packager_tool')
- def test_export_package_file_list_unknown_packager(
+ def test_export_flake_pilot_system_file_list_unknown_packager(
self, mock_get_default_packager_tool
):
- assert self.setup.export_package_file_list(
+ assert self.setup.export_flake_pilot_system_file_list(
'target_dir', 'system_files'
) == ''
@@ -1308,34 +1308,98 @@ def test_export_package_verification_unknown_packager(
@patch('kiwi.system.setup.Command.run')
@patch('kiwi.system.setup.RpmDataBase')
@patch('kiwi.system.setup.MountManager')
- def test_export_package_file_list(
- self, mock_MountManager, mock_RpmDataBase, mock_command
+ def test_export_flake_pilot_system_file_list(
+ self, mock_MountManager, mock_RpmDataBase, mock_command_run
):
rpmdb = 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()
- command.output = 'packages_file_data'
- mock_command.return_value = command
+ with open('../data/rpm_ql_dump_glibc', 'r') as glibc:
+ rpm_ql_dump_glibc = glibc.read()
+ self.xml_state.get_system_files_ignore_packages = Mock(
+ return_value=['rpm', 'yast', 'zypp']
+ )
- with patch('builtins.open') as m_open:
- result = self.setup.export_package_file_list(
+ def command_call(args):
+ if args[3] == '-qa':
+ return Mock(output='glibc\nzypper\n')
+ else:
+ return Mock(output=rpm_ql_dump_glibc)
+
+ mock_command_run.side_effect = command_call
+
+ with patch('builtins.open') as mock_open:
+ mock_open.return_value = MagicMock(spec=io.IOBase)
+ file_handle = mock_open.return_value.__enter__.return_value
+ result = self.setup.export_flake_pilot_system_file_list(
'target_dir', 'system_files'
)
- m_open.assert_called_once_with(
- 'target_dir/system_files', 'w', encoding='utf-8'
- )
-
- assert result == 'target_dir/system_files'
- mock_command.assert_called_once_with(
- [
- 'rpm', '--root', 'root_dir',
- '--noartifact', '--noghost', '-qal',
- '--dbpath', 'image_dbpath'
+ assert mock_open.call_args_list == [
+ call('target_dir/system_files', 'w', encoding='utf-8'),
+ call('target_dir/system_files.libs', 'w', encoding='utf-8')
]
- )
+ assert file_handle.write.call_args_list == [
+ call('/etc/bindresvport.blacklist\n'),
+ call('/etc/gai.conf\n'),
+ call('/etc/ld.so.cache\n'),
+ call('/etc/ld.so.conf\n'),
+ call('/etc/nsswitch.conf\n'),
+ call('/etc/rpc\n'),
+ call('/sbin/ldconfig\n'),
+ call('/usr/bin/gencat\n'),
+ call('/usr/bin/getconf\n'),
+ call('/usr/bin/getent\n'),
+ call('/usr/bin/iconv\n'),
+ call('/usr/bin/ld.so\n'),
+ call('/usr/bin/ldd\n'),
+ call('/usr/bin/locale\n'),
+ call('/usr/bin/localedef\n'),
+ call('/usr/sbin/iconvconfig\n'),
+ call('/usr/share/doc/packages/glibc\n'),
+ call('/usr/share/licenses/glibc\n'),
+ call('/usr/share/licenses/glibc/LICENSES\n'),
+ call('/var/cache/ldconfig\n'),
+ call('/lib64/ld-linux-x86-64.so.2\n'),
+ call('/lib64/ld-lsb-x86-64.so.3\n'),
+ call('/lib64/libBrokenLocale.so.1\n'),
+ call('/lib64/libanl.so.1\n'),
+ call('/lib64/libc.so.6\n'),
+ call('/lib64/libc_malloc_debug.so.0\n'),
+ call('/lib64/libdl.so.2\n'),
+ call('/lib64/libm.so.6\n'),
+ call('/lib64/libmvec.so.1\n'),
+ call('/lib64/libnss_compat.so.2\n'),
+ call('/lib64/libnss_db.so.2\n'),
+ call('/lib64/libnss_dns.so.2\n'),
+ call('/lib64/libnss_files.so.2\n'),
+ call('/lib64/libnss_hesiod.so.2\n'),
+ call('/lib64/libpthread.so.0\n'),
+ call('/lib64/libresolv.so.2\n'),
+ call('/lib64/librt.so.1\n'),
+ call('/lib64/libthread_db.so.1\n'),
+ call('/lib64/libutil.so.1\n'),
+ call('/usr/lib/getconf/POSIX_V6_LP64_OFF64\n'),
+ call('/usr/lib/getconf/POSIX_V7_LP64_OFF64\n'),
+ call('/usr/lib/getconf/XBS5_LP64_OFF64\n')
+ ]
+ assert result == 'target_dir/system_files'
+ assert mock_command_run.call_args_list == [
+ call(
+ [
+ 'rpm', '--root', 'root_dir',
+ '-qa', '--dbpath', 'image_dbpath'
+ ]
+ ),
+ call(
+ [
+ 'rpm', '--root', 'root_dir',
+ '-ql', '--noghost', '--dump', 'glibc',
+ '--dbpath', 'image_dbpath'
+ ]
+ )
+ ]
@patch('kiwi.system.setup.Command.run')
@patch('kiwi.system.setup.RpmDataBase')
@@ -1435,10 +1499,12 @@ def test_setup_permissions(
with self._caplog.at_level(logging.WARNING):
self.setup.setup_permissions()
- @patch.object(SystemSetup, 'export_package_file_list')
- def test_create_system_files(self, mock_export_package_file_list):
+ @patch.object(SystemSetup, 'export_flake_pilot_system_file_list')
+ def test_create_system_files(
+ self, mock_export_flake_pilot_system_file_list
+ ):
self.setup.create_system_files()
- mock_export_package_file_list.assert_called_once_with(
+ mock_export_flake_pilot_system_file_list.assert_called_once_with(
'root_dir', 'systemfiles'
)
diff --git a/test/unit/xml_state_test.py b/test/unit/xml_state_test.py
index e74fe27f3eb..8ef832a8c56 100644
--- a/test/unit/xml_state_test.py
+++ b/test/unit/xml_state_test.py
@@ -310,6 +310,11 @@ def test_get_to_become_deleted_packages(self):
'kernel-debug'
]
+ def test_get_system_files_ignore_packages(self):
+ assert self.state.get_system_files_ignore_packages() == [
+ 'rpm', 'yast', 'zypp'
+ ]
+
def test_get_build_type_vagrant_config_section(self):
vagrant_config = self.state.get_build_type_vagrant_config_section()
assert vagrant_config.get_provider() == 'libvirt'