blob: 4ca1f1a6a16ecb6885680ef850ee91b55c1bf806 [file] [log] [blame]
Anthony Young1b7a42e2011-10-19 02:34:06 -07001#!/usr/bin/env bash
2
Jesse Andrews4b8ab922011-10-24 12:42:43 -07003# exit on error to stop unexpected errors
4set -o errexit
5
Anthony Young3ee09ec2011-10-19 20:35:04 -07006# Make sure that we have the proper version of ubuntu
Anthony Youngfa4b5eb2011-10-19 11:27:02 -07007UBUNTU_VERSION=`cat /etc/lsb-release | grep CODENAME | sed 's/.*=//g'`
8if [ ! "oneiric" = "$UBUNTU_VERSION" ]; then
Anthony Young3ee09ec2011-10-19 20:35:04 -07009 if [ ! "natty" = "$UBUNTU_VERSION" ]; then
10 echo "This script only works with oneiric and natty"
11 exit 1
12 fi
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070013fi
14
Anthony Young1b7a42e2011-10-19 02:34:06 -070015# Echo commands
16set -o xtrace
17
18# Keep track of the current directory
19TOOLS_DIR=$(cd $(dirname "$0") && pwd)
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070020TOP_DIR=$TOOLS_DIR/..
Anthony Young1b7a42e2011-10-19 02:34:06 -070021
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070022# Configure the root password of the vm
Jesse Andrewsb169b632011-10-24 12:46:01 -070023ROOT_PASSWORD=${ROOT_PASSWORD:-password}
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070024
25# Where to store files and instances
26KVMSTACK_DIR=${KVMSTACK_DIR:-/opt/kvmstack}
27
28# Where to store images
29IMAGES_DIR=$KVMSTACK_DIR/images
30
31# Create images dir
32mkdir -p $IMAGES_DIR
Anthony Young1b7a42e2011-10-19 02:34:06 -070033
34# Move to top devstack dir
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070035cd $TOP_DIR
Anthony Young1b7a42e2011-10-19 02:34:06 -070036
37# Abort if localrc is not set
38if [ ! -e ./localrc ]; then
39 echo "You must have a localrc with ALL necessary passwords defined before proceeding."
40 echo "See stack.sh for required passwords."
41 exit 1
42fi
43
44# Source params
45source ./stackrc
46
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070047# Base image (natty by default)
48DIST_NAME=${DIST_NAME:-natty}
49IMAGE_FNAME=$DIST_NAME.raw
Anthony Young1b7a42e2011-10-19 02:34:06 -070050
Dean Troyere4f030f2011-10-21 14:28:03 -050051# Name of our instance, used by libvirt
Jesse Andrews82040df2011-10-22 20:56:23 -070052GUEST_NAME=${GUEST_NAME:-kvmstack}
Dean Troyere4f030f2011-10-21 14:28:03 -050053
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070054# Original version of built image
Dean Troyerad57a3a2011-10-21 14:29:30 -050055BASE_IMAGE=$KVMSTACK_DIR/images/$DIST_NAME.raw
Anthony Young1b7a42e2011-10-19 02:34:06 -070056
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070057# Copy of base image, which we pre-install with tasty treats
Jesse Andrews82040df2011-10-22 20:56:23 -070058VM_IMAGE=$IMAGES_DIR/$DIST_NAME.$GUEST_NAME.raw
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070059
60# Mop up after previous runs
Jesse Andrews61e0a2e2011-10-24 12:47:13 -070061virsh destroy $GUEST_NAME || true
Anthony Young1b7a42e2011-10-19 02:34:06 -070062
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070063# Where this vm is stored
Jesse Andrews82040df2011-10-22 20:56:23 -070064VM_DIR=$KVMSTACK_DIR/instances/$GUEST_NAME
Anthony Young1b7a42e2011-10-19 02:34:06 -070065
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070066# Create vm dir
Anthony Young1b7a42e2011-10-19 02:34:06 -070067mkdir -p $VM_DIR
68
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070069# Mount point into copied base image
Anthony Young1b7a42e2011-10-19 02:34:06 -070070COPY_DIR=$VM_DIR/copy
71mkdir -p $COPY_DIR
72
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070073# Create the base image if it does not yet exist
Anthony Young1b7a42e2011-10-19 02:34:06 -070074if [ ! -e $IMAGES_DIR/$IMAGE_FNAME ]; then
75 cd $TOOLS_DIR
Dean Troyerad57a3a2011-10-21 14:29:30 -050076 ./make_image.sh -m -r 5000 $DIST_NAME raw
77 mv $DIST_NAME.raw $BASE_IMAGE
Anthony Young1b7a42e2011-10-19 02:34:06 -070078 cd $TOP_DIR
79fi
80
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070081# Create a copy of the base image
Dean Troyerd0332912011-10-21 14:58:44 -050082if [ ! -e $VM_IMAGE ]; then
83 cp -p $BASE_IMAGE $VM_IMAGE
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070084fi
85
86# Unmount the copied base image
Anthony Young1b7a42e2011-10-19 02:34:06 -070087function unmount_images() {
88 # unmount the filesystem
89 while df | grep -q $COPY_DIR; do
90 umount $COPY_DIR || echo 'ok'
91 sleep 1
92 done
93}
94
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070095# Unmount from failed runs
Anthony Young1b7a42e2011-10-19 02:34:06 -070096unmount_images
97
Anthony Youngfa4b5eb2011-10-19 11:27:02 -070098# Ctrl-c catcher
99function kill_unmount() {
Anthony Young1b7a42e2011-10-19 02:34:06 -0700100 unmount_images
101 exit 1
102}
103
Jesse Andrews87a73e82011-10-24 17:06:58 -0700104# Install deps if needed
105dpkg -l kvm libvirt-bin kpartx || apt-get install -y --force-yes kvm libvirt-bin kpartx
Anthony Young1b7a42e2011-10-19 02:34:06 -0700106
107# Let Ctrl-c kill tail and exit
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700108trap kill_unmount SIGINT
Anthony Young1b7a42e2011-10-19 02:34:06 -0700109
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700110# Where Openstack code will live in image
Anthony Young1b7a42e2011-10-19 02:34:06 -0700111DEST=${DEST:-/opt/stack}
112
113# Mount the file system
Dean Troyerd0332912011-10-21 14:58:44 -0500114mount -o loop,offset=32256 $VM_IMAGE $COPY_DIR
Anthony Young1b7a42e2011-10-19 02:34:06 -0700115
116# git clone only if directory doesn't exist already. Since ``DEST`` might not
117# be owned by the installation user, we create the directory and change the
118# ownership to the proper user.
119function git_clone {
120 if [ ! -d $2 ]; then
121 sudo mkdir $2
122 sudo chown `whoami` $2
123 git clone $1 $2
124 cd $2
125 # This checkout syntax works for both branches and tags
126 git checkout $3
127 fi
128}
129
130# Make sure that base requirements are installed
131cp /etc/resolv.conf $COPY_DIR/etc/resolv.conf
132chroot $COPY_DIR apt-get update
133chroot $COPY_DIR apt-get install -y --force-yes `cat files/apts/* | cut -d\# -f1 | egrep -v "(rabbitmq|libvirt-bin|mysql-server)"`
134chroot $COPY_DIR apt-get install -y --download-only rabbitmq-server libvirt-bin mysql-server
135chroot $COPY_DIR pip install `cat files/pips/*`
136
137# Clean out code repos if directed to do so
138if [ "$CLEAN" = "1" ]; then
139 rm -rf $COPY_DIR/$DEST
140fi
141
142# Cache openstack code
143mkdir -p $COPY_DIR/$DEST
144git_clone $NOVA_REPO $COPY_DIR/$DEST/nova $NOVA_BRANCH
145git_clone $GLANCE_REPO $COPY_DIR/$DEST/glance $GLANCE_BRANCH
146git_clone $KEYSTONE_REPO $COPY_DIR/$DESTkeystone $KEYSTONE_BRANCH
147git_clone $NOVNC_REPO $COPY_DIR/$DEST/noVNC $NOVNC_BRANCH
148git_clone $DASH_REPO $COPY_DIR/$DEST/dash $DASH_BRANCH $DASH_TAG
149git_clone $NOVACLIENT_REPO $COPY_DIR/$DEST/python-novaclient $NOVACLIENT_BRANCH
150git_clone $OPENSTACKX_REPO $COPY_DIR/$DEST/openstackx $OPENSTACKX_BRANCH
151git_clone $KEYSTONE_REPO $COPY_DIR/$DEST/keystone $KEYSTONE_BRANCH
152git_clone $NOVNC_REPO $COPY_DIR/$DEST/noVNC $NOVNC_BRANCH
153
Anthony Youngbabb2e02011-10-20 12:32:58 -0700154# Back to devstack
155cd $TOP_DIR
Anthony Young1b7a42e2011-10-19 02:34:06 -0700156
Jesse Andrews1369c052011-10-24 12:38:13 -0700157# Unmount the filesystems
158unmount_images
159
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700160# Network configuration variables
Anthony Young1b7a42e2011-10-19 02:34:06 -0700161BRIDGE=${BRIDGE:-br0}
Jesse Andrews82040df2011-10-22 20:56:23 -0700162GUEST_IP=${GUEST_IP:-192.168.1.50}
163GUEST_CIDR=${GUEST_CIDR:-$GUEST_IP/24}
164GUEST_NETMASK=${GUEST_NETMASK:-255.255.255.0}
165GUEST_GATEWAY=${GUEST_GATEWAY:-192.168.1.1}
166GUEST_MAC=${GUEST_MAC:-"02:16:3e:07:69:`printf '%02X' $(echo $GUEST_IP | sed "s/.*\.//")`"}
167GUEST_RAM=${GUEST_RAM:-1524288}
168GUEST_CORES=${GUEST_CORES:-1}
Anthony Young1b7a42e2011-10-19 02:34:06 -0700169
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700170# libvirt.xml configuration
Jesse Andrewsec1d0312011-10-21 19:22:55 -0700171LIBVIRT_XML=$VM_DIR/libvirt.xml
Anthony Young1b7a42e2011-10-19 02:34:06 -0700172cat > $LIBVIRT_XML <<EOF
173<domain type='kvm'>
Jesse Andrews82040df2011-10-22 20:56:23 -0700174 <name>$GUEST_NAME</name>
175 <memory>$GUEST_RAM</memory>
Anthony Young1b7a42e2011-10-19 02:34:06 -0700176 <os>
Anthony Youngd51812d2011-10-19 20:09:43 -0700177 <type>hvm</type>
178 <bootmenu enable='yes'/>
Anthony Young1b7a42e2011-10-19 02:34:06 -0700179 </os>
180 <features>
181 <acpi/>
182 </features>
Jesse Andrews82040df2011-10-22 20:56:23 -0700183 <vcpu>$GUEST_CORES</vcpu>
Anthony Young1b7a42e2011-10-19 02:34:06 -0700184 <devices>
185 <disk type='file'>
186 <driver type='qcow2'/>
187 <source file='$VM_DIR/disk'/>
188 <target dev='vda' bus='virtio'/>
189 </disk>
190
191 <interface type='bridge'>
192 <source bridge='$BRIDGE'/>
Jesse Andrews82040df2011-10-22 20:56:23 -0700193 <mac address='$GUEST_MAC'/>
Anthony Young1b7a42e2011-10-19 02:34:06 -0700194 </interface>
195
196 <!-- The order is significant here. File must be defined first -->
197 <serial type="file">
198 <source path='$VM_DIR/console.log'/>
199 <target port='1'/>
200 </serial>
201
202 <console type='pty' tty='/dev/pts/2'>
203 <source path='/dev/pts/2'/>
204 <target port='0'/>
205 </console>
206
207 <serial type='pty'>
208 <source path='/dev/pts/2'/>
209 <target port='0'/>
210 </serial>
211
212 <graphics type='vnc' port='-1' autoport='yes' keymap='en-us' listen='0.0.0.0'/>
213 </devices>
214</domain>
215EOF
216
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700217# Mount point for instance fs
Anthony Young1b7a42e2011-10-19 02:34:06 -0700218ROOTFS=$VM_DIR/root
219mkdir -p $ROOTFS
220
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700221# Make sure we have nbd-ness
Anthony Young1b7a42e2011-10-19 02:34:06 -0700222modprobe nbd max_part=63
223
Anthony Young9c0fdd72011-10-19 20:22:32 -0700224# Which NBD device to use?
225NBD=${NBD:-/dev/nbd5}
226
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700227# Clean up from previous runs
Anthony Young1b7a42e2011-10-19 02:34:06 -0700228umount $ROOTFS || echo 'ok'
Anthony Young9c0fdd72011-10-19 20:22:32 -0700229qemu-nbd -d $NBD || echo 'ok'
Anthony Young1b7a42e2011-10-19 02:34:06 -0700230
Anthony Youngbabb2e02011-10-20 12:32:58 -0700231# Clean up old runs
232cd $VM_DIR
233rm -f $VM_DIR/disk
234
235# Create our instance fs
Dean Troyerd0332912011-10-21 14:58:44 -0500236qemu-img create -f qcow2 -b $VM_IMAGE disk
Anthony Youngbabb2e02011-10-20 12:32:58 -0700237
Anthony Young68565362011-10-24 23:20:12 -0700238# Connect our nbd and wait till it is mountable
Anthony Young9c0fdd72011-10-19 20:22:32 -0700239qemu-nbd -c $NBD disk
Anthony Young68565362011-10-24 23:20:12 -0700240NBD_DEV=`basename $NBD`
241if ! timeout 60 sh -c "while ! [ -e /sys/block/$NBD_DEV/pid ]; do sleep 1; done"; then
242 echo "Couldn't connect $NBD"
243 exit 1
244fi
Anthony Young69937462011-10-20 12:55:46 -0700245
246# Mount the instance
Anthony Young9c0fdd72011-10-19 20:22:32 -0700247mount $NBD $ROOTFS -o offset=32256 -t ext4
Anthony Young1b7a42e2011-10-19 02:34:06 -0700248
249# Configure instance network
250INTERFACES=$ROOTFS/etc/network/interfaces
251cat > $INTERFACES <<EOF
252auto lo
253iface lo inet loopback
254
255auto eth0
256iface eth0 inet static
Jesse Andrews82040df2011-10-22 20:56:23 -0700257 address $GUEST_IP
258 netmask $GUEST_NETMASK
259 gateway $GUEST_GATEWAY
Anthony Young1b7a42e2011-10-19 02:34:06 -0700260EOF
261
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700262# User configuration for the instance
Anthony Young1b7a42e2011-10-19 02:34:06 -0700263chroot $ROOTFS groupadd libvirtd
264chroot $ROOTFS useradd stack -s /bin/bash -d $DEST -G libvirtd
265cp -pr $TOOLS_DIR/.. $ROOTFS/$DEST/devstack
266echo "root:$ROOT_PASSWORD" | chroot $ROOTFS chpasswd
Anthony Young1b7a42e2011-10-19 02:34:06 -0700267echo "stack:pass" | chroot $ROOTFS chpasswd
Anthony Young1b7a42e2011-10-19 02:34:06 -0700268echo "stack ALL=(ALL) NOPASSWD: ALL" >> $ROOTFS/etc/sudoers
269
270# Gracefully cp only if source file/dir exists
271function cp_it {
272 if [ -e $1 ] || [ -d $1 ]; then
273 cp -pRL $1 $2
274 fi
275}
276
277# Copy over your ssh keys and env if desired
278COPYENV=${COPYENV:-1}
279if [ "$COPYENV" = "1" ]; then
280 cp_it ~/.ssh $ROOTFS/$DEST/.ssh
281 cp_it ~/.ssh/id_rsa.pub $ROOTFS/$DEST/.ssh/authorized_keys
282 cp_it ~/.gitconfig $ROOTFS/$DEST/.gitconfig
283 cp_it ~/.vimrc $ROOTFS/$DEST/.vimrc
284 cp_it ~/.bashrc $ROOTFS/$DEST/.bashrc
285fi
286
Jesse Andrews60657722011-10-25 23:41:59 -0700287# pre-cache uec images
288for image_url in ${IMAGE_URLS//,/ }; do
289 IMAGE_FNAME=`basename "$image_url"`
290 if [ ! -f $IMAGES_DIR/$IMAGE_FNAME ]; then
291 wget -c $image_url -O $IMAGES_DIR/$IMAGE_FNAME
292 fi
293 cp $IMAGES_DIR/$IMAGE_FNAME $ROOTFS/$DEST/devstack/files/images
Jesse Andrews9173d062011-10-25 23:43:03 -0700294done
Jesse Andrews60657722011-10-25 23:41:59 -0700295
Anthony Young1b7a42e2011-10-19 02:34:06 -0700296# Configure the runner
297RUN_SH=$ROOTFS/$DEST/run.sh
298cat > $RUN_SH <<EOF
299#!/usr/bin/env bash
Anthony Young1b7a42e2011-10-19 02:34:06 -0700300
301# Kill any existing screens
302killall screen
303
304# Install and run stack.sh
305sudo apt-get update
306sudo apt-get -y --force-yes install git-core vim-nox sudo
307if [ ! -d "$DEST/devstack" ]; then
308 git clone git://github.com/cloudbuilders/devstack.git $DEST/devstack
309fi
310cd $DEST/devstack && $STACKSH_PARAMS FORCE=yes ./stack.sh > /$DEST/run.sh.log
311echo >> /$DEST/run.sh.log
312echo >> /$DEST/run.sh.log
313echo "All done! Time to start clicking." >> /$DEST/run.sh.log
Anthony Youngd51812d2011-10-19 20:09:43 -0700314cat $DEST/run.sh.log
Anthony Young1b7a42e2011-10-19 02:34:06 -0700315EOF
Anthony Young1b7a42e2011-10-19 02:34:06 -0700316chmod 755 $RUN_SH
317
318# Make runner launch on boot
319RC_LOCAL=$ROOTFS/etc/init.d/local
320cat > $RC_LOCAL <<EOF
321#!/bin/sh -e
Dean Troyerad57a3a2011-10-21 14:29:30 -0500322# Reboot if this is our first run to enable console log on $DIST_NAME :(
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700323if [ ! -e /root/firstlaunch ]; then
324 touch /root/firstlaunch
Anthony Youngd51812d2011-10-19 20:09:43 -0700325 reboot -f
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700326 exit 0
327fi
Anthony Young1b7a42e2011-10-19 02:34:06 -0700328su -c "$DEST/run.sh" stack
329EOF
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700330chmod +x $RC_LOCAL
331chroot $ROOTFS sudo update-rc.d local defaults 80
Anthony Young1b7a42e2011-10-19 02:34:06 -0700332
333# Make our ip address hostnames look nice at the command prompt
334echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/$DEST/.bashrc
335echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/etc/profile
336
337# Give stack ownership over $DEST so it may do the work needed
338chroot $ROOTFS chown -R stack $DEST
339
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700340# Change boot params so that we get a console log
Anthony Youngf6f52272011-10-19 02:58:18 -0700341sudo sed -e "s/quiet splash/splash console=ttyS0 console=ttyS1,19200n8/g" -i $ROOTFS/boot/grub/menu.lst
Anthony Youngd51812d2011-10-19 20:09:43 -0700342sudo sed -e "s/^hiddenmenu//g" -i $ROOTFS/boot/grub/menu.lst
343#chroot $ROOTFS grub-install /dev/vda
Anthony Youngf6f52272011-10-19 02:58:18 -0700344
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700345# Unmount
346umount $ROOTFS || echo 'ok'
Anthony Young9c0fdd72011-10-19 20:22:32 -0700347qemu-nbd -d $NBD
Anthony Young1b7a42e2011-10-19 02:34:06 -0700348
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700349# Create the instance
350cd $VM_DIR && virsh create libvirt.xml
351
352# Tail the console log till we are done
Anthony Youngd51812d2011-10-19 20:09:43 -0700353WAIT_TILL_LAUNCH=${WAIT_TILL_LAUNCH:-1}
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700354if [ "$WAIT_TILL_LAUNCH" = "1" ]; then
355 # Done creating the container, let's tail the log
356 echo
357 echo "============================================================="
358 echo " -- YAY! --"
359 echo "============================================================="
360 echo
361 echo "We're done launching the vm, about to start tailing the"
362 echo "stack.sh log. It will take a second or two to start."
363 echo
364 echo "Just CTRL-C at any time to stop tailing."
365
366 while [ ! -e "$VM_DIR/console.log" ]; do
367 sleep 1
368 done
369
370 tail -F $VM_DIR/console.log &
371
372 TAIL_PID=$!
373
374 function kill_tail() {
375 kill $TAIL_PID
376 exit 1
377 }
Vishvananda Ishaya9b353672011-10-20 10:07:10 -0700378
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700379 # Let Ctrl-c kill tail and exit
380 trap kill_tail SIGINT
381
382 echo "Waiting stack.sh to finish..."
Anthony Youngd51812d2011-10-19 20:09:43 -0700383 while ! cat $VM_DIR/console.log | grep -q 'All done' ; do
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700384 sleep 5
385 done
386
387 kill $TAIL_PID
Jesse Andrews381591a2011-10-24 22:25:16 -0700388
389 if grep -q "stack.sh failed" $VM_DIR/console.log; then
390 exit 1
391 fi
Anthony Youngfa4b5eb2011-10-19 11:27:02 -0700392 echo ""
393 echo "Finished - Zip-a-dee Doo-dah!"
394fi