#
|
# SPDX-License-Identifier: GPL-2.0-only
|
#
|
|
from oe.rootfs import Rootfs
|
from oe.manifest import Manifest
|
from oe.utils import execute_pre_post_process
|
from oe.package_manager.rpm.manifest import PkgManifest
|
from oe.package_manager.rpm import RpmPM
|
|
class PkgRootfs(Rootfs):
|
def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
|
super(PkgRootfs, self).__init__(d, progress_reporter, logcatcher)
|
self.log_check_regex = r'(unpacking of archive failed|Cannot find package'\
|
r'|exit 1|ERROR: |Error: |Error |ERROR '\
|
r'|Failed |Failed: |Failed$|Failed\(\d+\):)'
|
|
self.manifest = PkgManifest(d, manifest_dir)
|
|
self.pm = RpmPM(d,
|
d.getVar('IMAGE_ROOTFS'),
|
self.d.getVar('TARGET_VENDOR')
|
)
|
|
self.inc_rpm_image_gen = self.d.getVar('INC_RPM_IMAGE_GEN')
|
if self.inc_rpm_image_gen != "1":
|
bb.utils.remove(self.image_rootfs, True)
|
else:
|
self.pm.recovery_packaging_data()
|
bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
|
|
self.pm.create_configs()
|
|
'''
|
While rpm incremental image generation is enabled, it will remove the
|
unneeded pkgs by comparing the new install solution manifest and the
|
old installed manifest.
|
'''
|
def _create_incremental(self, pkgs_initial_install):
|
if self.inc_rpm_image_gen == "1":
|
|
pkgs_to_install = list()
|
for pkg_type in pkgs_initial_install:
|
pkgs_to_install += pkgs_initial_install[pkg_type]
|
|
installed_manifest = self.pm.load_old_install_solution()
|
solution_manifest = self.pm.dump_install_solution(pkgs_to_install)
|
|
pkg_to_remove = list()
|
for pkg in installed_manifest:
|
if pkg not in solution_manifest:
|
pkg_to_remove.append(pkg)
|
|
self.pm.update()
|
|
bb.note('incremental update -- upgrade packages in place ')
|
self.pm.upgrade()
|
if pkg_to_remove != []:
|
bb.note('incremental removed: %s' % ' '.join(pkg_to_remove))
|
self.pm.remove(pkg_to_remove)
|
|
self.pm.autoremove()
|
|
def _create(self):
|
pkgs_to_install = self.manifest.parse_initial_manifest()
|
rpm_pre_process_cmds = self.d.getVar('RPM_PREPROCESS_COMMANDS')
|
rpm_post_process_cmds = self.d.getVar('RPM_POSTPROCESS_COMMANDS')
|
|
# update PM index files
|
self.pm.write_index()
|
|
execute_pre_post_process(self.d, rpm_pre_process_cmds)
|
|
if self.progress_reporter:
|
self.progress_reporter.next_stage()
|
|
if self.inc_rpm_image_gen == "1":
|
self._create_incremental(pkgs_to_install)
|
|
if self.progress_reporter:
|
self.progress_reporter.next_stage()
|
|
self.pm.update()
|
|
pkgs = []
|
pkgs_attempt = []
|
for pkg_type in pkgs_to_install:
|
if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY:
|
pkgs_attempt += pkgs_to_install[pkg_type]
|
else:
|
pkgs += pkgs_to_install[pkg_type]
|
|
if self.progress_reporter:
|
self.progress_reporter.next_stage()
|
|
self.pm.install(pkgs)
|
|
if self.progress_reporter:
|
self.progress_reporter.next_stage()
|
|
self.pm.install(pkgs_attempt, True)
|
|
if self.progress_reporter:
|
self.progress_reporter.next_stage()
|
|
self.pm.install_complementary()
|
|
if self.progress_reporter:
|
self.progress_reporter.next_stage()
|
|
self._setup_dbg_rootfs(['/etc', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
|
|
execute_pre_post_process(self.d, rpm_post_process_cmds)
|
|
if self.inc_rpm_image_gen == "1":
|
self.pm.backup_packaging_data()
|
|
if self.progress_reporter:
|
self.progress_reporter.next_stage()
|
|
|
@staticmethod
|
def _depends_list():
|
return ['DEPLOY_DIR_RPM', 'INC_RPM_IMAGE_GEN', 'RPM_PREPROCESS_COMMANDS',
|
'RPM_POSTPROCESS_COMMANDS', 'RPM_PREFER_ELF_ARCH']
|
|
def _get_delayed_postinsts(self):
|
postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/rpm-postinsts")
|
if os.path.isdir(postinst_dir):
|
files = os.listdir(postinst_dir)
|
for f in files:
|
bb.note('Delayed package scriptlet: %s' % f)
|
return files
|
|
return None
|
|
def _save_postinsts(self):
|
# this is just a stub. For RPM, the failed postinstalls are
|
# already saved in /etc/rpm-postinsts
|
pass
|
|
def _log_check(self):
|
self._log_check_warn()
|
self._log_check_error()
|
|
def _cleanup(self):
|
if bb.utils.contains("IMAGE_FEATURES", "package-management", True, False, self.d):
|
self.pm._invoke_dnf(["clean", "all"])
|