X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=build.sh;h=bff2262edfcd0ac6103639486bcee1b67ad7b569;hb=38d28a2ffec0d8715e69c76d7e71e0736a0c3ce6;hp=1b52042ad7d98f2f88b53f7d0cf159609c880bf2;hpb=a7d57bb5c90ad28b11e838155023e807e7570864;p=bootcd.git diff --git a/build.sh b/build.sh index 1b52042..bff2262 100755 --- a/build.sh +++ b/build.sh @@ -1,348 +1,549 @@ #!/bin/bash - -set -e - -# where the boot cd build config files are stored (and certificats/keys) -CONFIGURATIONS_DIR=configurations/ - -# where built files are stored -BUILD_DIR=build/ - -BOOTCD_VERSION="3.0" -FULL_VERSION_STRING="PlanetLab BootCD" -OUTPUT_IMAGE_NAME='PlanetLab-BootCD' - -SYSLINUX_SRC=sources/syslinux-2.11.tar.bz2 - -BOOTCD_YUM_GROUP=BootCD - -CDRECORD_FLAGS="-v -dao" - -CONF_FILES_DIR=conf_files/ - -# size of the ram disk in MB -RAMDISK_SIZE=64 - -# the bytes per inode ratio (the -i value in mkfs.ext2) for the ramdisk -INITRD_BYTES_PER_INODE=1024 - - -# make sure the boot manager source is checked out in the same directory -# as the bootcd_v3 repository -BOOTMANAGER_DIR=../bootmanager/ - -if [ ! -d $BOOTMANAGER_DIR ]; then - echo "the bootmanager repository needs to be checked out at the same" - echo "level as this directory, for the merge_hw_tables.py script" - exit -fi - - -function usage() -{ - echo "Usage: build.sh []" - echo "Action: build burn clean" - echo - echo "If configuration is missing, 'default' is loaded" - exit -} - - -function build_cdroot() +# +# Builds custom BootCD ISO and USB images in the current +# directory. For backward compatibility, if an old-style static +# configuration is specified, that configuration file will be parsed +# instead of the current PLC configuration in +# /etc/planetlab/plc_config. +# +# Aaron Klingaman +# Mark Huang +# Copyright (C) 2004-2006 The Trustees of Princeton University +# +# $Id: build.sh,v 1.40 2006/07/25 23:51:39 mlhuang Exp $ +# + +PATH=/sbin:/bin:/usr/sbin:/usr/bin + +CONFIGURATION=default +NODE_CONFIGURATION_FILE= +ALL=0 + +usage() { - if [ -f $CD_ROOT/.built ]; then - echo "cd root already built, skipping" - return - fi - - clean - - mkdir -p $CD_ROOT/dev/pts - mkdir -p $CD_ROOT/proc - mkdir -p $CD_ROOT/etc - - echo "copy fstab and mtab" - cp -f $CONF_FILES_DIR/fstab $CD_ROOT/etc/ - cp -f $CONF_FILES_DIR/mtab $CD_ROOT/etc/ - - echo "setup rpm to install only en_US locale and no docs" - mkdir -p $CD_ROOT/etc/rpm - cp -f $CONF_FILES_DIR/macros $CD_ROOT/etc/rpm - - echo "initialize rpm db" - mkdir -p $CD_ROOT/var/lib/rpm - rpm --root $CD_ROOT --initdb - - echo "install boot cd base rpms" - yum -c yum.conf --installroot=$CD_ROOT -y groupinstall $BOOTCD_YUM_GROUP - - echo "checking to make sure rpms were installed" - packages=`cat yumgroups.xml | grep packagereq | sed 's#<[^<]*>##g'` - set +e - for package in $packages; do - echo "checking for package $package" - chroot $CD_ROOT /bin/rpm -qi $package > /dev/null - if [[ "$?" -ne 0 ]]; then - echo "package $package was not installed in the cd root." - echo "make sure it exists in the yum repository." - exit 1 - fi - done - set -e - - echo "removing unneccessary build files" - (cd $CD_ROOT/lib/modules && \ - find ./ -type d -name build -maxdepth 2 -exec rm -rf {} \;) - - echo "setting up non-ssh authentication" - mkdir -p $CD_ROOT/etc/samba - chroot $CD_ROOT /usr/sbin/authconfig --nostart --kickstart \ - --enablemd5 --enableshadow - - echo "setting root password" - sed -i "s#root::#root:$ROOT_PASSWORD:#g" $CD_ROOT/etc/shadow - - echo "relocate some large directories out of the root system" - # get /var/lib/rpm out, its 12mb. create in its place a - # symbolic link to /usr/relocated/var/lib/rpm - mkdir -p $CD_ROOT/usr/relocated/var/lib/ - mv $CD_ROOT/var/lib/rpm $CD_ROOT/usr/relocated/var/lib/ - (cd $CD_ROOT/var/lib && ln -s ../../usr/relocated/var/lib/rpm rpm) - - # get /lib/tls out - mkdir -p $CD_ROOT/usr/relocated/lib - mv $CD_ROOT/lib/tls $CD_ROOT/usr/relocated/lib/ - (cd $CD_ROOT/lib && ln -s ../usr/relocated/lib/tls tls) - - echo "extracting syslinux, copying isolinux files to cd" - mkdir -p $CD_ROOT/usr/isolinux/ - mkdir -p $BUILD_DIR/syslinux - tar -C $BUILD_DIR/syslinux -xjvf $SYSLINUX_SRC - find $BUILD_DIR/syslinux -name isolinux.bin \ - -exec cp -f {} $CD_ROOT/usr/isolinux/ \; - - echo "moving kernel to isolinux directory" - KERNEL=$CD_ROOT/boot/vmlinuz-* - mv -f $KERNEL $CD_ROOT/usr/isolinux/kernel - - echo "moving /usr/bin/find and /usr/bin/dirname to /bin" - mv $CD_ROOT/usr/bin/find $CD_ROOT/bin/ - mv $CD_ROOT/usr/bin/dirname $CD_ROOT/bin/ - - echo "creating version files" - echo "$FULL_VERSION_STRING" > $CD_ROOT/usr/isolinux/pl_version - echo "$FULL_VERSION_STRING" > $CD_ROOT/pl_version - - touch $CD_ROOT/.built + echo "Usage: build.sh [OPTION]..." + echo " -c name (Deprecated) Static configuration to use (default: $CONFIGURATION)" + echo " -f planet.cnf Node to customize CD for (default: none)" + echo " -a Build all images (default: only base images)" + echo " -h This message" + exit 1 } -function build_initrd() -{ - echo "building initrd" - rm -f $INITRD - rm -f $INITRD.gz - - echo "copy fstab and mtab" - cp -f $CONF_FILES_DIR/fstab $CD_ROOT/etc/ - cp -f $CONF_FILES_DIR/mtab $CD_ROOT/etc/ - - echo "installing generic modprobe.conf" - cp -f $CONF_FILES_DIR/modprobe.conf $CD_ROOT/etc/ - - echo "installing our own inittab and init scripts" - cp -f $CONF_FILES_DIR/inittab $CD_ROOT/etc - init_scripts="pl_sysinit pl_hwinit pl_netinit pl_validateconf pl_boot" - for script in $init_scripts; do - cp -f $CONF_FILES_DIR/$script $CD_ROOT/etc/init.d/ - chmod +x $CD_ROOT/etc/init.d/$script - done - - echo "setup basic networking files" - cp -f $CONF_FILES_DIR/hosts $CD_ROOT/etc/ - - echo "copying sysctl.conf (fix tcp window scaling and broken routers)" - cp -f $CONF_FILES_DIR/sysctl.conf $CD_ROOT/etc/ - - echo "setup default network conf file" - mkdir -p $CD_ROOT/usr/boot - cp -f $CONF_FILES_DIR/default-net.cnf $CD_ROOT/usr/boot/ - - echo "setup boot server configuration" - cp -f $CURRENT_CONFIG_DIR/$PRIMARY_SERVER_CERT $CD_ROOT/usr/boot/cacert.pem - cp -f $CURRENT_CONFIG_DIR/$PRIMARY_SERVER_GPG $CD_ROOT/usr/boot/pubring.gpg - echo "$PRIMARY_SERVER" > $CD_ROOT/usr/boot/boot_server - echo "$PRIMARY_SERVER_PORT" > $CD_ROOT/usr/boot/boot_server_port - echo "$PRIMARY_SERVER_PATH" > $CD_ROOT/usr/boot/boot_server_path - - echo "setup backup boot server configuration" - mkdir -p $CD_ROOT/usr/boot/backup - cp -f $CURRENT_CONFIG_DIR/$BACKUP_SERVER_CERT \ - $CD_ROOT/usr/boot/backup/cacert.pem - cp -f $CURRENT_CONFIG_DIR/$BACKUP_SERVER_GPG \ - $CD_ROOT/usr/boot/backup/pubring.gpg - echo "$BACKUP_SERVER" > $CD_ROOT/usr/boot/backup/boot_server - echo "$BACKUP_SERVER_PORT" > $CD_ROOT/usr/boot/backup/boot_server_port - echo "$BACKUP_SERVER_PATH" > $CD_ROOT/usr/boot/backup/boot_server_path - - echo "copying old boot cd directory bootme (TEMPORARY)" - cp -r bootme_old $CD_ROOT/usr/bootme - echo "$FULL_VERSION_STRING" > $CD_ROOT/usr/bootme/ID - echo "$PRIMARY_SERVER" > $CD_ROOT/usr/bootme/BOOTSERVER - echo "$PRIMARY_SERVER" > $CD_ROOT/usr/bootme/BOOTSERVER_IP - echo "$PRIMARY_SERVER_PORT" > $CD_ROOT/usr/bootme/BOOTPORT - - echo "copying cacert to old boot cd directory bootme (TEMPORARY)" - mkdir -p $CD_ROOT/usr/bootme/cacert/$PRIMARY_SERVER/ - cp -f $CURRENT_CONFIG_DIR/$PRIMARY_SERVER_CERT \ - $CD_ROOT/usr/bootme/cacert/$PRIMARY_SERVER/cacert.pem - - echo "forcing lvm to make lvm1 partitions (TEMPORARY)" - cp -f $CONF_FILES_DIR/lvm.conf $CD_ROOT/etc/lvm/ - - echo "copying isolinux configuration files" - cp -f $CONF_FILES_DIR/isolinux.cfg $CD_ROOT/usr/isolinux/ - echo "$FULL_VERSION_STRING" > $CD_ROOT/usr/isolinux/message.txt - - echo "writing /etc/issue" - echo "$FULL_VERSION_STRING" > $CD_ROOT/etc/issue - echo "Kernel \r on an \m" >> $CD_ROOT/etc/issue - echo "" >> $CD_ROOT/etc/issue - echo "" >> $CD_ROOT/etc/issue - - if [[ ! -z "$NODE_CONFIGURATION_FILE" ]]; then - echo "Copying node configuration file to cd" - cp -f $CURRENT_CONFIG_DIR/$NODE_CONFIGURATION_FILE \ - $CD_ROOT/usr/boot/plnode.txt - fi - - echo "making the isolinux initrd kernel command line match rd size" - let INITRD_SIZE_KB=$(($RAMDISK_SIZE * 1024)) - sed -i "s#ramdisk_size=0#ramdisk_size=$INITRD_SIZE_KB#g" \ - $CD_ROOT/usr/isolinux/isolinux.cfg - - echo "building pcitable for hardware detection" - pci_map_file=`find $CD_ROOT/lib/modules/ -name modules.pcimap | head -1` - module_dep_file=`find $CD_ROOT/lib/modules/ -name modules.dep | head -1` - pci_table=$CD_ROOT/usr/share/hwdata/pcitable - $BOOTMANAGER_DIR/source/merge_hw_tables.py \ - $module_dep_file $pci_map_file $pci_table $CD_ROOT/etc/pl_pcitable - - dd if=/dev/zero of=$INITRD bs=1M count=$RAMDISK_SIZE - mkfs.ext2 -F -m 0 -i $INITRD_BYTES_PER_INODE $INITRD - mkdir -p $INITRD_MOUNT - mount -o loop,rw $INITRD $INITRD_MOUNT - - echo "copy all files except usr to ramdisk" - pushd . - cd $CD_ROOT - find . -path ./usr -prune -o -print | cpio -p -d -u $INITRD_MOUNT - popd - - umount $INITRD_MOUNT - rmdir $INITRD_MOUNT - - echo "compressing ramdisk" - gzip $INITRD -} - -function build() -{ - # build base image via yum - build_cdroot - - # always build/rebuild initrd - build_initrd - - # build iso image - rm -f $ISO - mkisofs -o $ISO -R -allow-leading-dots -J -r -b isolinux/isolinux.bin \ - -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table \ - $CD_ROOT/usr - - # build usb image and make it bootable with syslinux (instead of isolinux) - USB_IMAGE=${ISO%*.iso}.usb - USB_KB=$(du -kc $ISO $CD_ROOT/usr/isolinux | awk '$2 == "total" { print $1 }') - mkfs.vfat -C $USB_IMAGE $USB_KB - mkdir -p $INITRD_MOUNT - mount -o loop,rw $USB_IMAGE $INITRD_MOUNT - cp -a $ISO $INITRD_MOUNT - cp -a $CD_ROOT/usr/isolinux/{initrd.gz,kernel,message.txt,pl_version} $INITRD_MOUNT - cp -a $CD_ROOT/usr/isolinux/isolinux.cfg $INITRD_MOUNT/syslinux.cfg - umount $INITRD_MOUNT - rmdir $INITRD_MOUNT - syslinux $USB_IMAGE -} - -function burn() -{ - cdrecord $CDRECORD_FLAGS -data $ISO -} +# Get options +while getopts "c:f:ah" opt ; do + case $opt in + c) + CONFIGURATION=$OPTARG + ;; + f) + NODE_CONFIGURATION_FILE=$OPTARG + ;; + a) + ALL=1 + ;; + h|*) + usage + ;; + esac +done + +# Do not tolerate errors +set -e -function clean() -{ - rm -rf $CD_ROOT - rm -rf $BUILD_DIR/syslinux - rm -rf $BUILD_DIR/$INITRD_MOUNT - rm -rf $BUILD_DIR - rm -f $ISO - rmdir --ignore-fail-on-non-empty build -} +# Change to our source directory +srcdir=$(cd $(dirname $0) && pwd -P) +pushd $srcdir -if [[ "$1" == "clean" || "$1" == "burn" || "$1" == "build" ]]; then - action=$1 - configuration=$2 +# Root of the isofs +isofs=$PWD/build/isofs - if [[ -z "$configuration" ]]; then - configuration=default - fi +# Build reference image if it does not exist. This should only need to +# be executed once at build time, never at run time. +if [ ! -f $isofs/bootcd.img ] ; then + ./prep.sh +fi - echo "Loading configuration $configuration" - CURRENT_CONFIG_DIR=$CONFIGURATIONS_DIR/$configuration - . $CURRENT_CONFIG_DIR/configuration +# build/version.txt written by prep.sh +BOOTCD_VERSION=$(cat build/version.txt) - # setup vars for this configuration +if [ -f /etc/planetlab/plc_config ] ; then + # Source PLC configuration + . /etc/planetlab/plc_config +fi - # version string for this build - if [[ ! -z "$EXTRA_VERSION" ]]; then - FULL_VERSION_STRING="$FULL_VERSION_STRING $EXTRA_VERSION" - fi - FULL_VERSION_STRING="$FULL_VERSION_STRING $BOOTCD_VERSION" +### This support for backwards compatibility can be taken out in the +### future. RC1 based MyPLCs set $PLC_BOOT_SSL_CRT in the plc_config +### file, but >=RC2 based bootcd assumes that $PLC_BOOT_CA_SSL_CRT is +### set. +if [ -z "$PLC_BOOT_CA_SSL_CRT" -a ! -z "$PLC_BOOT_SSL_CRT" ] ; then + PLC_BOOT_CA_SSL_CRT=$PLC_BOOT_SSL_CRT +fi - # destination image - if [[ ! -z "$EXTRA_VERSION" ]]; then - OUTPUT_IMAGE_NAME="$OUTPUT_IMAGE_NAME-$EXTRA_VERSION" +# If PLC configuration is not valid, try a static configuration +if [ -z "$PLC_BOOT_CA_SSL_CRT" -a -d configurations/$CONFIGURATION ] ; then + # (Deprecated) Source static configuration + . configurations/$CONFIGURATION/configuration + PLC_NAME="PlanetLab" + PLC_MAIL_SUPPORT_ADDRESS="support@planet-lab.org" + PLC_WWW_HOST="www.planet-lab.org" + PLC_WWW_PORT=80 + if [ -n "$EXTRA_VERSION" ] ; then + BOOTCD_VERSION="$BOOTCD_VERSION $EXTRA_VERSION" fi - OUTPUT_IMAGE_NAME="$OUTPUT_IMAGE_NAME-$BOOTCD_VERSION" - - # setup build directories - BUILD_DIR=build/$configuration - mkdir -p $BUILD_DIR - ISO=$BUILD_DIR/`echo $OUTPUT_IMAGE_NAME | sed -e "s/%version/$BOOTCD_VERSION/"`.iso - - CD_ROOT=`pwd`/$BUILD_DIR/cdroot - mkdir -p $CD_ROOT - - # location of the uncompressed ramdisk image - INITRD=$CD_ROOT/usr/isolinux/initrd - - # temporary mount point for rd - INITRD_MOUNT=`pwd`/$BUILD_DIR/rd + PLC_BOOT_HOST=$PRIMARY_SERVER + PLC_BOOT_SSL_PORT=$PRIMARY_SERVER_PORT + PLC_BOOT_CA_SSL_CRT=configurations/$CONFIGURATION/$PRIMARY_SERVER_CERT + PLC_ROOT_GPG_KEY_PUB=configurations/$CONFIGURATION/$PRIMARY_SERVER_GPG +fi +FULL_VERSION_STRING="$PLC_NAME BootCD $BOOTCD_VERSION" + +echo "* Building images for $FULL_VERSION_STRING" + +# From within a myplc chroot /tmp is too small to build +# all possible images, whereas /data is part of the host +# filesystem and usually has sufficient space. What we +# should do is check whether the expected amount of space +# is available. +[ -d /data ] && BUILDTMP=/data || BUILDTMP=/tmp + +# Root of the ISO and USB images +echo "* Populating root filesystem..." +overlay=$(mktemp -d ${BUILDTMP}/overlay.XXXXXX) +install -d -m 755 $overlay +trap "rm -rf $overlay" ERR INT + +# Create version files +echo "* Creating version files" + +# Boot Manager compares pl_version in both places to make sure that +# the right CD is mounted. We used to boot from an initrd and mount +# the CD on /usr. Now we just run everything out of the initrd. +for file in $overlay/pl_version $overlay/usr/isolinux/pl_version ; do + mkdir -p $(dirname $file) + echo "$FULL_VERSION_STRING" >$file +done + +# Install boot server configuration files +echo "* Installing boot server configuration files" + +# We always intended to bring up and support backup boot servers, +# but never got around to it. Just install the same parameters for +# both for now. +for dir in $overlay/usr/boot $overlay/usr/boot/backup ; do + install -D -m 644 $PLC_BOOT_CA_SSL_CRT $dir/cacert.pem + install -D -m 644 $PLC_ROOT_GPG_KEY_PUB $dir/pubring.gpg + echo "$PLC_BOOT_HOST" >$dir/boot_server + echo "$PLC_BOOT_SSL_PORT" >$dir/boot_server_port + echo "/boot/" >$dir/boot_server_path +done + +# (Deprecated) Install old-style boot server configuration files +install -D -m 644 $PLC_BOOT_CA_SSL_CRT $overlay/usr/bootme/cacert/$PLC_BOOT_HOST/cacert.pem +echo "$FULL_VERSION_STRING" >$overlay/usr/bootme/ID +echo "$PLC_BOOT_HOST" >$overlay/usr/bootme/BOOTSERVER +echo "$PLC_BOOT_HOST" >$overlay/usr/bootme/BOOTSERVER_IP +echo "$PLC_BOOT_SSL_PORT" >$overlay/usr/bootme/BOOTPORT + +# Generate /etc/issue +echo "* Generating /etc/issue" + +if [ "$PLC_WWW_PORT" = "443" ] ; then + PLC_WWW_URL="https://$PLC_WWW_HOST/" +elif [ "$PLC_WWW_PORT" != "80" ] ; then + PLC_WWW_URL="http://$PLC_WWW_HOST:$PLC_WWW_PORT/" +else + PLC_WWW_URL="http://$PLC_WWW_HOST/" +fi - case $action in - build ) - echo "Proceeding with building $DESCRIPTION" - build;; +mkdir -p $overlay/etc +cat >$overlay/etc/issue <$overlay/etc/passwd - burn ) - echo "Burning $DESCRIPTION" - burn;; - esac -else - usage +# Install node configuration file (e.g., if node has no floppy disk or USB slot) +if [ -f "$NODE_CONFIGURATION_FILE" ] ; then + echo "* Installing node configuration file" + install -D -m 644 $NODE_CONFIGURATION_FILE $overlay/usr/boot/plnode.txt fi +# Pack overlay files into a compressed archive +echo "* Compressing overlay image" +(cd $overlay && find . | cpio --quiet -c -o) | gzip -9 >$isofs/overlay.img + +rm -rf $overlay +trap - ERR INT + +# Calculate ramdisk size (total uncompressed size of both archives) +ramdisk_size=$(gzip -l $isofs/bootcd.img $isofs/overlay.img | tail -1 | awk '{ print $2; }') # bytes +ramdisk_size=$((($ramdisk_size + 1023) / 1024)) # kilobytes + +# Write isolinux configuration +echo "$FULL_VERSION_STRING" >$isofs/pl_version +cat >$isofs/isolinux.cfg <$isofs/isolinux.cfg <$tmp/syslinux.cfg <$tmp/syslinux.cfg <./etc/fstab < etc/rc.d/init.d/pl_rsysinit < /tmp/etc/mtab + +# copy over directory contents of all _o directories from /etc and /var +# /tmp/etc and /tmp/var +pushd /etc +for odir in \$(cd /etc && ls -d *_o); do dir=\$(echo \$odir | sed 's,\_o$,,'); (mkdir -p /tmp/etc/\$dir && cd \$odir && find . | cpio -p -d -u /tmp/etc/\$dir); done +popd +pushd /var +for odir in \$(cd /var && ls -d *_o); do dir=\$(echo \$odir | sed 's,\_o$,,'); (mkdir -p /tmp/var/\$dir && cd \$odir && find . | cpio -p -d -u /tmp/var/\$dir); done +popd + +echo "done" +# hand over to pl_sysinit +echo "pl_rsysinit: handing over to pl_sysinit" +/etc/init.d/pl_sysinit +EOF +chmod +x etc/rc.d/init.d/pl_rsysinit + +popd + +chown -R 0.0 $cramfs + +#create the cramfs image +echo "* Creating cramfs image" +mkfs.cramfs $tmp/ $cramfs +# Leave 1 MB of free space on the VFAT filesystem +cramfs_size=$(($(du -sk $cramfs | awk '{ print $1; }'))) +mv $cramfs ${BUILDTMP}/cramfs.img +rm -rf $tmp +trap - ERR INT + +# Create ISO CRAMFS image +echo "* Creating ISO CRAMFS-based image" +iso="$PLC_NAME-BootCD-$BOOTCD_VERSION-cramfs.iso" + +tmp=$(mktemp -d ${BUILDTMP}/bootcd.XXXXXX) +trap "$tmp; rm -rf $tmp" ERR INT +(cd $isofs && find . | grep -v "\.img$" | cpio -p -d -u $tmp/) +cat >$tmp/isolinux.cfg <$tmp/isolinux.cfg <$tmp/syslinux.cfg <$tmp/syslinux.cfg <