snapcraft kernel plugin needs to check compression method of the initrd before trying to unpack it

Bug #1569337 reported by Oliver Grawert
16
This bug affects 3 people
Affects Status Importance Assigned to Milestone
Snapcraft
Fix Released
High
Sergio Schvezov

Bug Description

when building a kernel snap, snapcraft pulls the initrd out of an os snap package. with the dropping of the ubuntu-core-generic-initrd package this means the initrd.img is now using teh same compression method like the rest of the world ... which is lzma

the snapcraft kernel plugin should run something like "file usr/lib/ubuntu-core-generic-initrd/initrd.img-core" and select the right decompressor based on the output.

Revision history for this message
Mark W Wenning (mwenning) wrote :

I am also seeing this.

Revision history for this message
Gunther Laure (gunther-laure-e) wrote :

I tried this to solve this issue:

    def _unpack_generic_initrd(self):
        initrd_path = os.path.join(
            'usr', 'lib', 'ubuntu-core-generic-initrd', 'initrd.img-core')
        initrd_unpacked_path = os.path.join(self.builddir, 'initrd-staging')
        if os.path.exists(initrd_unpacked_path):
            shutil.rmtree(initrd_unpacked_path)
        os.makedirs(initrd_unpacked_path)

        with tempfile.TemporaryDirectory() as temp_dir:
            subprocess.check_call([
                'unsquashfs', self.os_snap, os.path.dirname(initrd_path)],
                cwd=temp_dir)

            result = subprocess.check_call(
                'file {} --mime-type'.format(
                    os.path.join(temp_dir, 'squashfs-root', initrd_path)),
                cwd=initrd_unpacked_path)
            mime_type = result.split()[-1]
            decompressor = 'gzip'
            if "gzip" in mime_type:
                decompressor = 'gzip'
            elif "x-xz" in mime_type:
                decompressor = 'xz'

            subprocess.check_call(
                'cat {0} | {1} -dc | cpio -i'.format(
                    os.path.join(temp_dir, 'squashfs-root', initrd_path), decompressor),
                shell=True, cwd=initrd_unpacked_path)

        return initrd_unpacked_path

Revision history for this message
Gunther Laure (gunther-laure-e) wrote :

Better variant (and this time working)

    def _unpack_generic_initrd(self):
        initrd_path = os.path.join(
            'usr', 'lib', 'ubuntu-core-generic-initrd', 'initrd.img-core')
        initrd_unpacked_path = os.path.join(self.builddir, 'initrd-staging')
        if os.path.exists(initrd_unpacked_path):
            shutil.rmtree(initrd_unpacked_path)
        os.makedirs(initrd_unpacked_path)

        with tempfile.TemporaryDirectory() as temp_dir:
            subprocess.check_call([
                'unsquashfs', self.os_snap, os.path.dirname(initrd_path)],
                cwd=temp_dir)

            tmp_initrd_path = os.path.join(temp_dir, 'squashfs-root', initrd_path)
            cmd = shlex.split('file -L --mime-type {}'.format(tmp_initrd_path))
            result = subprocess.check_output(cmd)
            mime_type = str(result.split()[-1])
            logger.info('initrd mime_type: {} {}'.format(tmp_initrd_path, mime_type))
            decompressor = 'gzip'
            if "gzip" in mime_type:
                decompressor = 'gzip'
            elif "x-xz" in mime_type:
                decompressor = 'xz'
            elif "x-lzma" in mime_type:
                decompressor = 'xz'

            subprocess.check_call(
                'cat {0} | {1} -dc | cpio -i'.format(tmp_initrd_path, decompressor),
                shell=True, cwd=initrd_unpacked_path)

        return initrd_unpacked_path

Revision history for this message
Paolo Pisati (p-pisati) wrote :

Ok, with Gunther's patch (plus a minor fix) and another patch, i can build again kernel using snapcraft in a xenial chroot.

Revision history for this message
Paolo Pisati (p-pisati) wrote :
Revision history for this message
Paolo Pisati (p-pisati) wrote :

I'm a bit skeptical about this one, so feel free to reject it with the "you should really have /sbin in $PATH" argument

Revision history for this message
Oliver Grawert (ogra) wrote :

- 'cat {} | gzip -dc | cpio -i'.format(
- os.path.join(temp_dir, 'squashfs-root', initrd_path)),
+ 'cat {0} | {1} -dc | cpio -i'.format(tmp_initrd_path, decompressor),

can we please turn that from:

"cat ...| gzip .. | cpio ..."

to something like:

"zcat .. | cpio ..."
(or xzcat ro lzcat)

unless there is a good reason to pipe it through three commands instead of two ...

Revision history for this message
Sergio Schvezov (sergiusens) wrote :
Changed in snapcraft:
milestone: none → 2.8.1
assignee: nobody → Sergio Schvezov (sergiusens)
importance: Undecided → High
status: New → In Progress
Changed in snapcraft:
status: In Progress → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.