From 1be306d98d191bb5590d3cfa63c8fdd45edb6dc4 Mon Sep 17 00:00:00 2001 From: Markus Hilger Date: Mon, 2 Nov 2026 18:06:07 +0100 Subject: [PATCH] Require squashfs-tools and openssl for capture mksquashfs packs the image and the dracut module needs openssl. Without them capture failed silently and only the later rsync of private.key reported an error. Also stop when capturing a filesystem fails, unmount the capture tmpfs on the target, and have run_constrained print the exception it used to swallow. squashfs-tools is now required, so drop the optional prerequisite reporting. --- imgutil/imgutil | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/imgutil/imgutil b/imgutil/imgutil index 85db2992..e0f6c844 100644 --- a/imgutil/imgutil +++ b/imgutil/imgutil @@ -234,8 +234,6 @@ def capture_remote(args): for cmd in unmet: sys.stderr.write(cmd + '\n') sys.exit(1) - for cmd in finfo.get('optionalprereqs', []): - sys.stderr.write(cmd + '\n') oscat = finfo['oscategory'] subprocess.check_call(['ssh', '-o', 'LogLevel=QUIET', '-t', targ, 'python3', '/run/imgutil/capenv/imgutil', 'capturelocal']) utillib = __file__.replace('bin/imgutil', 'lib/imgutil') @@ -325,13 +323,17 @@ def capture_system(): added = install_selinux_module() mkdirp('/run/imgutil/capout') _mount('none', '/run/imgutil/capout', 'tmpfs') - run_constrained(capture_system_back, None) + failed = run_constrained(capture_system_back, None) if added: # the captured image keeps it try: subprocess.check_call(['semodule', '-r', 'confluent_diskless']) except (OSError, subprocess.CalledProcessError) as e: sys.stderr.write('Unable to remove SELinux module confluent_diskless again: {0}\n'.format(e)) + if failed: + sys.stderr.write('Capturing the system failed\n') + capture_local_cleanup() + sys.exit(1) def generalize_fstab(): with open('/etc/fstab') as tabfile: @@ -372,7 +374,8 @@ def capture_system_back(args): if fname[-1] == '_': fname = fname[:-1] fname = os.path.join('/run/imgutil/capout', fname) - run_constrained(capture_fs, (fs, fname)) + if run_constrained(capture_fs, (fs, fname)): + raise Exception('Capturing {0} failed'.format(fs['mount'])) isize = os.stat(fname + '.sfs').st_size todelete.append(fname + '.sfs') outimg.write(struct.pack('!H', len(fs['mount'].encode('utf8')))) @@ -529,7 +532,6 @@ class OsHandler(object): self.sourcepath = None self.osname = '{}-{}-{}'.format(name, version, arch) self.captureprereqs = [] - self.captureadvisories = [] try: pkglist = args.packagelist except AttributeError: @@ -575,8 +577,7 @@ class OsHandler(object): if not isinstance(odata[idx], str): odata[idx] = odata[idx].decode('utf8') info = {'oscategory': odata[0], - 'version': odata[1], 'arch': odata[2], 'name': odata[3], 'unmetprereqs': self.captureprereqs, - 'optionalprereqs': self.captureadvisories} + 'version': odata[1], 'arch': odata[2], 'name': odata[3], 'unmetprereqs': self.captureprereqs} return json.dumps(info) def prep_root_premount(self, args): @@ -800,21 +801,17 @@ class DebHandler(OsHandler): self.oscategory = name + version super().__init__(name, version, arch, args) needpkgs = [] - wantpkgs = [] if not os.path.exists(os.path.join(hostpath, 'usr/bin/tpm2_getcap')): needpkgs.append('tpm2-tools') lfuses = glob.glob(os.path.join(hostpath, '/lib/*/libfuse.so.2')) if not lfuses: needpkgs.append('libfuse2') - if not os.path.exists(os.path.join(hostpath, 'usr/bin/unsquashfs')): - wantpkgs.append('squashfs-tools') + # mksquashfs packs the image + if not os.path.exists(os.path.join(hostpath, 'usr/bin/mksquashfs')): + needpkgs.append('squashfs-tools') if needpkgs: needapt = 'Missing packages needed in target for capture, to add required packages: apt install ' + ' '.join(needpkgs) self.captureprereqs.append(needapt) - if wantpkgs: - wantapt = ('Missing optional packages in target, untethered boot will extract the image more slowly, ' - 'to add them: apt install ' + ' '.join(wantpkgs)) - self.captureadvisories.append(wantapt) def add_pkglists(self): self.includepkgs.extend(self.list_packages()) @@ -902,7 +899,6 @@ class ElHandler(OsHandler): self.yumargs = [] super().__init__(name, version, arch, args) needpkgs = [] - wantpkgs = [] if not hostpath: return if not os.path.exists(os.path.join(hostpath, 'usr/bin/tpm2_getcap')): @@ -921,17 +917,15 @@ class ElHandler(OsHandler): needpkgs.append('dhcp-client') if not os.path.exists(os.path.join(hostpath, 'usr/sbin/mount.nfs')): needpkgs.append('nfs-utils') - if (self.oscategory not in ('el7', 'el8') and - not os.path.exists(os.path.join(hostpath, 'usr/sbin/unsquashfs')) and - not os.path.exists(os.path.join(hostpath, 'usr/bin/unsquashfs'))): - wantpkgs.append('squashfs-tools') + # mksquashfs packs the image, the dracut module needs openssl + if (not os.path.exists(os.path.join(hostpath, 'usr/sbin/mksquashfs')) and + not os.path.exists(os.path.join(hostpath, 'usr/bin/mksquashfs'))): + needpkgs.append('squashfs-tools') + if not os.path.exists(os.path.join(hostpath, 'usr/bin/openssl')): + needpkgs.append('openssl') if needpkgs: needapt = 'Missing packages needed in target for capture, to add required packages: dnf install ' + ' '.join(needpkgs) self.captureprereqs.append(needapt) - if wantpkgs: - wantdnf = ('Missing optional packages in target, untethered boot will extract the image more slowly, ' - 'to add them: dnf install ' + ' '.join(wantpkgs)) - self.captureadvisories.append(wantdnf) def add_pkglists(self): self.yumargs.extend(self.list_packages()) @@ -1215,7 +1209,8 @@ def run_constrained(function, args): _mount('none', '/', flags=MS_REC|MS_PRIVATE) _mount('proc', '/proc', fstype='proc') function(args) - except Exception: + except Exception as e: + sys.stderr.write('{0}\n'.format(e)) exitcode = 1 finally: os._exit(exitcode)