Bug 866608 - virt-install --initrd-inject does not work for RHEL 4.x guests (ext2 initrd)
virt-install --initrd-inject does not work for RHEL 4.x guests (ext2 initrd)
Product: Virtualization Tools
Classification: Community
Component: virt-manager (Show other bugs)
All Linux
unspecified Severity high
: ---
: ---
Assigned To: Cole Robinson
Depends On:
Blocks: 924526
  Show dependency treegraph
Reported: 2012-10-15 13:47 EDT by Patrick J. LoPresti
Modified: 2014-07-06 15:31 EDT (History)
9 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
: 924526 (view as bug list)
Last Closed: 2013-09-02 16:11:54 EDT
Type: Bug
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

  None (edit)
Description Patrick J. LoPresti 2012-10-15 13:47:42 EDT
Description of problem:
"virt-install --initrd-inject=..." inject does not work.  No diagnostic is printed, but the files simply do not appear on the installer's initrd.

The problem is that earlier versions of Linux used a compressed ext2 image for the initrd.  initrd-inject only works if the initrd is a compressed cpio image.  (Indeed, the script happily appends compressed cpio blocks to the ext2 image which are then ignored by the kernel.)

Version-Release number of selected component (if applicable):
(also current git)

How reproducible:

Steps to Reproduce:
1. "virt-install --initrd-inject=foo <any RHEL 4.x version>"
Actual results:
File "foo" does not appear on the initrd during installation

Expected results:
File "foo" should appear on the initrd during installation

Additional info:
I am working on a patch for this, but I am not an experienced Python programmer.  Yet.
Comment 2 Patrick J. LoPresti 2012-10-18 12:19:15 EDT
I decided I do not have time to learn Python right now...  So I worked around this issue in my shell script wrapper.  I am including my approach here in case it can help someone else or provide a basis for a real patch.

The below fragment of shell script code assumes that $location is what you plan to pass to "virt-install --location=...".  The code locates the pxeboot/initrd.img file within $location and determines whether it is an ext2 compressed image.  If so, it creates a temporary directory, copies the vmlinuz and initrd.img files into it, and adds "file1", "file2", and "file3" to the initrd.img.  Then it modifies $location to point to the temporary directory.  (It also arranges to remove the temporary directory when the containing shell script exits.)

So, once this fragment finishes, your script just does "virt-install --location=$location ..." to get the installation going.  You can even include "--initrd-inject=..." lines, although they will of course have no effect when the initrd is actually ext2.  In this way you can wind up with a generic install script.

I hope this basic approach can be adapted to DistroInstaller.py by someone better versed in Python.  It does assume that e2fstools is installed (for debugfs), and it will fail if the ext2 initrd does not already have enough free space on it to hold the injected files.  This is good enough for my application and would probably be a reasonable assumption for an initial patch.

Shell script fragment follows.


# At this point, "$location" refers to the OS distro
pxeboot_dir=$(find "$location"/. -name example -prune -o -type d -name pxeboot -print)

[ -f "$initrd" ] \
    && file_initrd=$(file -z "$initrd")

if [ -f "$initrd" ] && [ "$file_initrd" != "${file_initrd#* ext2 }" ] ; then
    # This is awful.  "virt-install --initrd-inject=..." does not
    # handle compressed ext2 images (RHEL 4 and below).  So hack
    # around it.  (If
    # https://bugzilla.redhat.com/show_bug.cgi?id=866608 is ever
    # fixed, all of this can be removed.)

    echo "$0: Looks like $initrd ext2...  Engaging hack"

    # Create temporary directory and arrange to remove it on script exit.
    temp_dir=$(mktemp -d)
    trap "rm -rf $temp_dir" EXIT

    mkdir -p $temp_dir/images/pxeboot
    cp -a "$pxeboot_dir"/vmlinuz $temp_dir/images/pxeboot/.

    # "-f" just in case initrd is not compressed
    zcat -f "$initrd" > $temp_initrd

    # Inject files into temp initrd.
    for file in file1 file2 file3 ; do
        /sbin/debugfs -w -R "write $file ${file##*/}" $temp_initrd

# Now we can run virt-install --location=$location ...
Comment 4 Cole Robinson 2013-09-02 16:11:54 EDT
This is fixed upstream now:

commit 018fcbbb4abb15974463cf2b3f76eecdabb02e5e
Author: Cole Robinson <crobinso@redhat.com>
Date:   Mon Sep 2 16:10:28 2013 -0400

    distroinstaller: Support --initrd-inject for RHEL4 (bz 866608)
    RHEL4 kernels are gzip'd ext2 images, so unzip it, use debugfs to inject
    files, and zip it back up. Based on shell code from Patrick J. LoPresti.

Note You need to log in before you can comment on or make changes to this bug.