Tip: Install RPMs in a guest

This script lets you install RPMs in a Fedora or RHEL guest (Update: offline guest in case that is not clear). It works by installing a “firstboot”-type script that actually does the install (avoiding various pitfalls of installing RPMs directly from libguestfs).

You use it like this:

# ./install-rpms.sh F14x64 xbill-2.1-2.fc11.x86_64.rpm
Uploading /etc/init.d/installrpms (firstboot script) ...
Uploading xbill-2.1-2.fc11.x86_64.rpm to /var/lib/installrpms/xbill-2.1-2.fc11.x86_64.rpm ...

Multiple RPMs can be given on the command line, and it can be used incrementally.

This is not quite a complete usable solution yet. What is really needed is a way to determine the dependencies between RPMs, and also determine what needs to be updated in a guest. These are jobs that can probably be done through the yum API.

#!/bin/bash -
#
# Install RPMs at next boot on a RHEL or Fedora VM.  This uploads the
# RPMs to the VM and creates a 'firstboot' script to install them when
# the VM boots next time.  You can use this script incrementally.
# Each time it runs, it adds further RPMs.  The RPM list is cleared
# when the VM boots.
#
# For more information, see
# https://rwmj.wordpress.com/   http://virt-tools.org/
#
# Usage:
#   install-rpms.sh GuestName *.rpm

# Parse command line.
if [ $# -lt 2 ]; then
    echo "install-rpms.sh GuestName *.rpm"
    exit 1
fi

set -e
guest="$1"; shift

# Create a temporary working directory.
tmpdir=$(mktemp -d)
trap "rm -rf '$tmpdir'" EXIT INT QUIT TERM

# Start up guestfish in remote control mode.
unset GUESTFISH_PID
eval `guestfish --listen -d "$guest" -i`
if [ -z "$GUESTFISH_PID" ]; then exit 1; fi
trap "guestfish --remote exit" EXIT INT QUIT TERM


# Check guest uses RPM for package management.
root=`guestfish --remote -- inspect-get-roots`
pkgfmt=`guestfish --remote -- inspect-get-package-format "$root"`
if [ "$pkgfmt" != "rpm" ]; then
    echo "$0: $guest: guest does not use RPM (package format = $pkgfmt)"
    exit 1
fi

# Upload/overwrite firstboot RPM installer script.
# This should run early (before network starts).
cat > $tmpdir/install.rc <<'EOF'
#!/bin/sh
#
# chkconfig: 345 15 85
# description: Install RPMs at next boot
#
### BEGIN INIT INFO
# Short-Description: Install RPMs at next boot
# Description: Install RPMs at next boot
### END INIT INFO

. /etc/rc.d/init.d/functions

[ -d /var/lib/installrpms ] || exit 0

start ()
{
    if [ `ls -1 /var/lib/installrpms/*.rpm 2>/dev/null | wc -l` -gt 0 ]; then
        echo -n $"Installing new packages: "
        yum -y install /var/lib/installrpms/*.rpm >> /var/log/installrpms.log
        if [ $? -eq 0 ]; then
            success;
            rm /var/lib/installrpms/*.rpm
        else
            failure
        fi
    fi
}

case "$1" in
  start)
        start
        ;;
  stop)
        # nothing
        ;;
  *)
        echo "Usage: $0 {start|stop}"
        exit 1
        ;;
esac
EOF
echo "Uploading /etc/init.d/installrpms (firstboot script) ..."
guestfish --remote -- upload $tmpdir/install.rc /etc/init.d/installrpms

# Set the script to run at boot.
guestfish --remote -- chmod 0755 /etc/init.d/installrpms
guestfish --remote -- ln-sf /etc/init.d/installrpms /etc/rc2.d/S15installrpms
guestfish --remote -- ln-sf /etc/init.d/installrpms /etc/rc3.d/S15installrpms
guestfish --remote -- ln-sf /etc/init.d/installrpms /etc/rc5.d/S15installrpms

# Make the RPMs directory.
guestfish --remote -- mkdir-p /var/lib/installrpms
guestfish --remote -- chmod 0755 /var/lib/installrpms

# Upload the RPMs.
for f in "$@"; do
    b="$(basename $f)"
    echo "Uploading $f to /var/lib/installrpms/$b ..."
    guestfish --remote -- upload "$f" /var/lib/installrpms/"$b"
done

2 Comments

Filed under Uncategorized

2 responses to “Tip: Install RPMs in a guest

  1. James Antill

    Note that using “rpm -U” to install things will make yum unhappy in RHEL-6+ …

    http://illiterat.livejournal.com/7834.html

    • rich

      Thanks … changed rpm -U to yum install.

      Edit: Note that “yum install” doesn’t fix the depsolving problem. You need to install the RPMs before bringing up networking (since a security bug may affect a network service), and so this script runs before networking is up. Thus the complete list of RPMs and dependencies must be available locally.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s