#!/bin/bash # # Builds a Fedora reference image. Requires the build server to # host a local yum repository in one of: # # /usr/share/mirrors/fedora # /var/www/html/mirrors/fedora # # Otherwise, tries using CoBlitz: # # http://coblitz.planet-lab.org/pub/fedora # # Mark Huang # Copyright (C) 2004-2006 The Trustees of Princeton University # # $Id$ # export PATH=/sbin:/bin:/usr/sbin:/usr/bin # Verbosity verbose=0 # Default yum repositories to try mirrors=( file:///data/fedora http://localhost/fedora ftp://smoke.cs.princeton.edu/pub/mirrors/fedora http://coblitz.codeen.org/coblitz.planet-lab.org/pub/fedora ftp://mirror.cs.princeton.edu/pub/mirrors/fedora http://coblitz.planet-lab.org/pub/fedora ftp://mirror.stanford.edu/pub/mirrors/fedora ftp://rpmfind.net/linux/fedora http://fedora.laptop.org/fedora-linux-releases ) # Release and architecture to install releasever=4 basearch=i386 # Yum groups to install groups=() # Packages to install packages=() # Packages to exclude exclude=() # Exclude kernel* (and related) packages from all repositories except bootstrap exclude_kernel= # PlanetLab development environment if [ -f /etc/planetlab/plc_config ] ; then . /etc/planetlab/plc_config if [ -n "$PLC_DEVEL_FEDORA_URL" ] ; then mirrors=($PLC_DEVEL_FEDORA_URL) fi fi usage() { echo "Usage: mkfedora [OPTION]... [basedir]" echo " -l url Fedora mirror location. Defaults to try:" for mirror in "${mirrors[@]}" ; do echo " $mirror" done echo " -r release Fedora release number (default: $releasever)" echo " -a arch Fedora architecture (default: $basearch)" echo " -g group1 -g group2 ..." echo " Yumgroups to install (default: none)" echo " -p package1 -p package2 ..." echo " Additional packages to install (default: none)" echo " -x package1 -x package2 ..." echo " Packages to exclude (default: none)" echo " -k Exclude kernel* packages from all repositories except bootstrap" echo " -v Be verbose" echo " -h This message" exit 1 } # Get options while getopts "l:r:a:g:p:x:kvh" opt ; do case $opt in l) if echo $OPTARG | grep -q -i '^\(file\|http[s]*\)://' ; then mirrors=($OPTARG) else mirrors=(file://$OPTARG) fi ;; r) releasever=$OPTARG ;; a) basearch=$OPTARG ;; g) groups[${#groups[*]}]="$OPTARG" ;; p) packages[${#packages[*]}]="$OPTARG" ;; x) exclude[${#exclude[*]}]="$OPTARG" ;; k) exclude_kernel="exclude=kernel* ulogd iptables" ;; v) verbose=1 set -x ;; h|*) usage ;; esac done shift $(($OPTIND - 1)) if [ ! -d "$1" ] ; then usage fi vroot=$(cd $1 && pwd -P) if [ $UID -ne 0 ] ; then echo "Error: You must run this script as root." exit 1 fi fetch () { curl --fail --silent --max-time 60 "$1" } # hard to find two mirrors with a similar layout # set list of attempted locations according to releasever if [ $releasever -ge 7 ] ; then attempts=" $releasever/Everything/$basearch/os core/$releasever/Everything/$basearch/os \ linux/core/$releasever/$basearch/os " else attempts=" linux/core/$releasever/$basearch/os core/$releasever/$basearch/os $releasever/$basearch/os " fi for mirror in "${mirrors[@]}" ; do for attempt in $attempts; do baseurl=$mirror/$attempt if fetch $baseurl/repodata/repomd.xml >/dev/null ; then break fi unset baseurl done if [ -n "$baseurl" ] ; then break fi unset baseurl done if [ -z "$baseurl" ] ; then echo "Error: $releasever/$basearch/os/repodata/repomd.xml" echo " could not be found in any of the following locations:" echo for mirror in ${mirrors[@]} ; do for attempt in $attempts ; do echo $mirror/$attempt done done echo usage fi exec 3>&1 exec 4>&2 if [ $verbose -eq 0 ] ; then exec 1>/dev/null exec 2>/dev/null fi # Do not tolerate errors set -e # Mount /dev/pts and /dev/shm in reference image mount -t devpts none $vroot/dev/pts mount -t tmpfs none $vroot/dev/shm # Mount /proc in reference image mkdir -p $vroot/proc mount -t proc none $vroot/proc cleanup () { umount -l $vroot/proc umount -l $vroot/dev/shm umount -l $vroot/dev/pts } # Clean up before exiting if anything goes wrong trap "cleanup" ERR INT # Create a /var/lib dirs for yum & rpm mkdir -p $vroot/var/lib/yum mkdir -p $vroot/var/lib/rpm mkdir -p $vroot/usr/share/info # Create a dummy /etc/fstab in reference image mkdir -p $vroot/etc cat >$vroot/etc/fstab <$vroot/etc/rpm/macros < $vroot/etc/sysconfig/network # Trick rpm and yum, who read the real root /etc/rpm/macros file # rather than the one installed in the reference image, despite what # you might expect the --root and --installroot options to mean. Both # programs always read $HOME/.rpmmacros. export HOME=$vroot/tmp mkdir -p $vroot/tmp cp $vroot/etc/rpm/macros $vroot/tmp/.rpmmacros # Initialize RPM database in reference image mkdir -p $vroot/var/lib/rpm rpm --root $vroot --initdb rpm --root $vroot --import $baseurl/RPM-GPG-KEY-fedora # Initialize yum in reference image mkdir -p $vroot/var/cache/yum $vroot/var/log if [ $releasever -lt 7 ] ; then corename="Core " else corename="" fi cat >$vroot/etc/yum.conf <>$vroot/etc/yum.conf <>$vroot/etc/yum.conf <&3 yum -c $vroot/etc/yum.conf --installroot=$vroot -y $excludes install glibc # Go, baby, go if [ ${#packages[*]} -gt 0 ] ; then echo "* Installing optional packages" "${packages[@]}" >&3 yum -c $vroot/etc/yum.conf --installroot=$vroot -y $excludes \ install "${packages[@]}" if ! rpm --root $vroot -q "${packages[@]}" >/dev/null ; then echo "* Warning: Missing packages" rpm --root $vroot -q "${packages[@]}" | grep "not installed" fi fi if [ ${#groups[*]} -gt 0 ] ; then ## call yum sequentially to get finer-grained info on dependencies for grp in "${groups[@]}" ; do echo "* Installing optional group $grp" >&3 yum -c $vroot/etc/yum.conf --installroot=$vroot -y $excludes \ groupinstall "$grp" done fi # FC2 dev %preinstall checks /proc/mounts to make sure that /dev is # not currently mounted as devfs. If it thinks it is, it will refuse # to install the package. On a modern system running udev that mounts # /dev as tmpfs, this check fails. Since we are installing into a # chroot, whether /dev is mounted on the host system or not doesn't # matter. If dev was explicitly mentioned in the packages list, force # its installation. if [ "$releasever" = "2" ] ; then for package in "${packages[@]}" ; do if [ "$package" = "dev" ] && ! rpm --root $vroot -q dev >/dev/null 2>&1 ; then rpm --root $vroot -Uvh --noscripts $baseurl/Fedora/RPMS/dev-3.3.13-1.i386.rpm break fi done fi # Clean yum cache echo "* Cleaning up" >&3 yum -c $vroot/etc/yum.conf --installroot=$vroot -y \ clean all # Clean RPM state rm -f $vroot/var/lib/rpm/__db* # Set time zone to UTC if [ -f $vroot/usr/share/zoneinfo/UTC -a -f $vroot/etc/localtime ] ; then rm -f $vroot/etc/localtime ln -s /usr/share/zoneinfo/UTC $vroot/etc/localtime fi # remove trap handler, as we are about to call it directly. trap - ERR INT # Clean up cleanup exit 0