diff --git a/tools/build_libvirt.sh b/tools/build_libvirt.sh new file mode 100755 index 0000000..1bf99f9 --- /dev/null +++ b/tools/build_libvirt.sh @@ -0,0 +1,414 @@ +#!/usr/bin/env bash + +# exit on error to stop unexpected errors +set -o errexit + +# Make sure that we have the proper version of ubuntu +UBUNTU_VERSION=`cat /etc/lsb-release | grep CODENAME | sed 's/.*=//g'` +if [ ! "oneiric" = "$UBUNTU_VERSION" ]; then + if [ ! "natty" = "$UBUNTU_VERSION" ]; then + echo "This script only works with oneiric and natty" + exit 1 + fi +fi + +# Echo commands +set -o xtrace + +# Keep track of the current directory +TOOLS_DIR=$(cd $(dirname "$0") && pwd) +TOP_DIR=$TOOLS_DIR/.. + +# Where to store files and instances +WORK_DIR=${WORK_DIR:-$TOP_DIR/work} + +# Where to store images +IMAGES_DIR=$WORK_DIR/images + +# Create images dir +mkdir -p $IMAGES_DIR + +# Abort if localrc is not set +if [ ! -e $TOP_DIR/localrc ]; then + echo "You must have a localrc with ALL necessary passwords defined before proceeding." + echo "See stack.sh for required passwords." + exit 1 +fi + +# Source params +source ./stackrc + +# Configure the root password of the vm to be the same as ``ADMIN_PASSWORD`` +ROOT_PASSWORD=${ADMIN_PASSWORD:-password} + + +# Base image (natty by default) +DIST_NAME=${DIST_NAME:-natty} +IMAGE_FNAME=$DIST_NAME.raw + +# Name of our instance, used by libvirt +GUEST_NAME=${GUEST_NAME:-devstack} + +# Original version of built image +BASE_IMAGE=$WORK_DIR/images/$DIST_NAME.raw + +# Copy of base image, which we pre-install with tasty treats +VM_IMAGE=$IMAGES_DIR/$DIST_NAME.$GUEST_NAME.raw + +# Mop up after previous runs +virsh destroy $GUEST_NAME || true + +# Where this vm is stored +VM_DIR=$WORK_DIR/instances/$GUEST_NAME + +# Create vm dir +mkdir -p $VM_DIR + +# Mount point into copied base image +COPY_DIR=$VM_DIR/copy +mkdir -p $COPY_DIR + +# Create the base image if it does not yet exist +if [ ! -e $IMAGES_DIR/$IMAGE_FNAME ]; then + cd $TOOLS_DIR + ./make_image.sh -m -r 5000 $DIST_NAME raw + mv $DIST_NAME.raw $BASE_IMAGE + cd $TOP_DIR +fi + +# Create a copy of the base image +if [ ! -e $VM_IMAGE ]; then + cp -p $BASE_IMAGE $VM_IMAGE +fi + +# Unmount the copied base image +function unmount_images() { + # unmount the filesystem + while df | grep -q $COPY_DIR; do + umount $COPY_DIR || echo 'ok' + sleep 1 + done +} + +# Unmount from failed runs +unmount_images + +# Ctrl-c catcher +function kill_unmount() { + unmount_images + exit 1 +} + +# Install deps if needed +dpkg -l kvm libvirt-bin kpartx || apt-get install -y --force-yes kvm libvirt-bin kpartx + +# Let Ctrl-c kill tail and exit +trap kill_unmount SIGINT + +# Where Openstack code will live in image +DEST=${DEST:-/opt/stack} + +# Mount the file system +mount -o loop,offset=32256 $VM_IMAGE $COPY_DIR + +# git clone only if directory doesn't exist already. Since ``DEST`` might not +# be owned by the installation user, we create the directory and change the +# ownership to the proper user. +function git_clone { + if [ ! -d $2 ]; then + sudo mkdir $2 + sudo chown `whoami` $2 + git clone $1 $2 + cd $2 + # This checkout syntax works for both branches and tags + git checkout $3 + fi +} + +# Make sure that base requirements are installed +cp /etc/resolv.conf $COPY_DIR/etc/resolv.conf +chroot $COPY_DIR apt-get update +chroot $COPY_DIR apt-get install -y --force-yes `cat files/apts/* | cut -d\# -f1 | egrep -v "(rabbitmq|libvirt-bin|mysql-server)"` +chroot $COPY_DIR apt-get install -y --download-only rabbitmq-server libvirt-bin mysql-server +chroot $COPY_DIR pip install `cat files/pips/*` + +# Clean out code repos if directed to do so +if [ "$CLEAN" = "1" ]; then + rm -rf $COPY_DIR/$DEST +fi + +# Cache openstack code +mkdir -p $COPY_DIR/$DEST +git_clone $NOVA_REPO $COPY_DIR/$DEST/nova $NOVA_BRANCH +git_clone $GLANCE_REPO $COPY_DIR/$DEST/glance $GLANCE_BRANCH +git_clone $KEYSTONE_REPO $COPY_DIR/$DESTkeystone $KEYSTONE_BRANCH +git_clone $NOVNC_REPO $COPY_DIR/$DEST/noVNC $NOVNC_BRANCH +git_clone $HORIZON_REPO $COPY_DIR/$DEST/horizon $HORIZON_BRANCH $HORIZON_TAG +git_clone $NOVACLIENT_REPO $COPY_DIR/$DEST/python-novaclient $NOVACLIENT_BRANCH +git_clone $OPENSTACKX_REPO $COPY_DIR/$DEST/openstackx $OPENSTACKX_BRANCH +git_clone $KEYSTONE_REPO $COPY_DIR/$DEST/keystone $KEYSTONE_BRANCH +git_clone $NOVNC_REPO $COPY_DIR/$DEST/noVNC $NOVNC_BRANCH + +# Back to devstack +cd $TOP_DIR + +# Unmount the filesystems +unmount_images + +# Network configuration variables +BRIDGE=${BRIDGE:-br0} +GUEST_NETWORK=${GUEST_NETWORK:-1} + +GUEST_IP=${GUEST_IP:-192.168.$GUEST_NETWORK.50} +GUEST_CIDR=${GUEST_CIDR:-$GUEST_IP/24} +GUEST_NETMASK=${GUEST_NETMASK:-255.255.255.0} +GUEST_GATEWAY=${GUEST_GATEWAY:-192.168.$GUEST_NETWORK.1} +GUEST_MAC=${GUEST_MAC:-"02:16:3e:07:69:`printf '%02X' $GUEST_NETWORK`"} +GUEST_RAM=${GUEST_RAM:-1524288} +GUEST_CORES=${GUEST_CORES:-1} + +# libvirt.xml configuration +NET_XML=$VM_DIR/net.xml +cat > $NET_XML < + devstack-$GUEST_NETWORK + + + + +EOF + +virsh net-destroy devstack-$GUEST_NETWORK || true +virsh net-create $VM_DIR/net.xml + +# libvirt.xml configuration +LIBVIRT_XML=$VM_DIR/libvirt.xml +cat > $LIBVIRT_XML < + $GUEST_NAME + $GUEST_RAM + + hvm + + + + + + $GUEST_CORES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + +# Mount point for instance fs +ROOTFS=$VM_DIR/root +mkdir -p $ROOTFS + +# Make sure we have nbd-ness +modprobe nbd max_part=63 + +# Which NBD device to use? +NBD=${NBD:-/dev/nbd5} + +# Clean up from previous runs +umount $ROOTFS || echo 'ok' +qemu-nbd -d $NBD || echo 'ok' + +# Clean up old runs +cd $VM_DIR +rm -f $VM_DIR/disk + +# Create our instance fs +qemu-img create -f qcow2 -b $VM_IMAGE disk + +# Connect our nbd and wait till it is mountable +qemu-nbd -c $NBD disk +NBD_DEV=`basename $NBD` +if ! timeout 60 sh -c "while ! [ -e /sys/block/$NBD_DEV/pid ]; do sleep 1; done"; then + echo "Couldn't connect $NBD" + exit 1 +fi + +# Mount the instance +mount $NBD $ROOTFS -o offset=32256 -t ext4 + +# Configure instance network +INTERFACES=$ROOTFS/etc/network/interfaces +cat > $INTERFACES <> $ROOTFS/etc/sudoers + +# Gracefully cp only if source file/dir exists +function cp_it { + if [ -e $1 ] || [ -d $1 ]; then + cp -pRL $1 $2 + fi +} + +# Copy over your ssh keys and env if desired +COPYENV=${COPYENV:-1} +if [ "$COPYENV" = "1" ]; then + cp_it ~/.ssh $ROOTFS/$DEST/.ssh + cp_it ~/.ssh/id_rsa.pub $ROOTFS/$DEST/.ssh/authorized_keys + cp_it ~/.gitconfig $ROOTFS/$DEST/.gitconfig + cp_it ~/.vimrc $ROOTFS/$DEST/.vimrc + cp_it ~/.bashrc $ROOTFS/$DEST/.bashrc +fi + +# pre-cache uec images +for image_url in ${IMAGE_URLS//,/ }; do + IMAGE_FNAME=`basename "$image_url"` + if [ ! -f $IMAGES_DIR/$IMAGE_FNAME ]; then + wget -c $image_url -O $IMAGES_DIR/$IMAGE_FNAME + fi + cp $IMAGES_DIR/$IMAGE_FNAME $ROOTFS/$DEST/devstack/files +done + +# Configure the runner +RUN_SH=$ROOTFS/$DEST/run.sh +cat > $RUN_SH < /$DEST/run.sh.log +echo >> /$DEST/run.sh.log +echo >> /$DEST/run.sh.log +echo "All done! Time to start clicking." >> /$DEST/run.sh.log +cat $DEST/run.sh.log +EOF +chmod 755 $RUN_SH + +# Make runner launch on boot +RC_LOCAL=$ROOTFS/etc/init.d/local +cat > $RC_LOCAL <> $ROOTFS/$DEST/.bashrc +echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/etc/profile + +# Give stack ownership over $DEST so it may do the work needed +chroot $ROOTFS chown -R stack $DEST + +# Change boot params so that we get a console log +sudo sed -e "s/quiet splash/splash console=ttyS0 console=ttyS1,19200n8/g" -i $ROOTFS/boot/grub/menu.lst +sudo sed -e "s/^hiddenmenu//g" -i $ROOTFS/boot/grub/menu.lst + +# Set the hostname +echo $GUEST_NAME > $ROOTFS/etc/hostname + +# We need the hostname to resolve for rabbit to launch +if ! grep -q $GUEST_NAME $ROOTFS/etc/hosts; then + echo "$GUEST_IP $GUEST_NAME" >> $ROOTFS/etc/hosts +fi + +# Unmount +umount $ROOTFS || echo 'ok' +qemu-nbd -d $NBD + +# Create the instance +cd $VM_DIR && virsh create libvirt.xml + +# Tail the console log till we are done +WAIT_TILL_LAUNCH=${WAIT_TILL_LAUNCH:-1} +if [ "$WAIT_TILL_LAUNCH" = "1" ]; then + # Done creating the container, let's tail the log + echo + echo "=============================================================" + echo " -- YAY! --" + echo "=============================================================" + echo + echo "We're done launching the vm, about to start tailing the" + echo "stack.sh log. It will take a second or two to start." + echo + echo "Just CTRL-C at any time to stop tailing." + + while [ ! -e "$VM_DIR/console.log" ]; do + sleep 1 + done + + tail -F $VM_DIR/console.log & + + TAIL_PID=$! + + function kill_tail() { + kill $TAIL_PID + exit 1 + } + + # Let Ctrl-c kill tail and exit + trap kill_tail SIGINT + + echo "Waiting stack.sh to finish..." + while ! cat $VM_DIR/console.log | grep -q 'All done' ; do + sleep 5 + done + + kill $TAIL_PID + + if grep -q "stack.sh failed" $VM_DIR/console.log; then + exit 1 + fi + echo "" + echo "Finished - Zip-a-dee Doo-dah!" +fi