blob: 585f5afeebb60dd384b2a1fecc2d8ba6163f94bb [file] [log] [blame]
Jesse Andrewse97a2e72011-10-30 18:37:49 -07001#!/usr/bin/env bash
2
3# exit on error to stop unexpected errors
4set -o errexit
5
6# Make sure that we have the proper version of ubuntu
7UBUNTU_VERSION=`cat /etc/lsb-release | grep CODENAME | sed 's/.*=//g'`
8if [ ! "oneiric" = "$UBUNTU_VERSION" ]; then
9 if [ ! "natty" = "$UBUNTU_VERSION" ]; then
10 echo "This script only works with oneiric and natty"
11 exit 1
12 fi
13fi
14
Dean Troyer55c02732011-11-01 17:44:03 -050015# Clean up any resources that may be in use
16cleanup() {
17 set +o errexit
18 unmount_images
19
Dean Troyer8e998292011-11-07 16:41:47 -060020 if [ -n "$COPY_DIR" ]; then
21 umount $COPY_DIR/dev
22 umount $COPY_DIR
23 fi
24
Dean Troyer55c02732011-11-01 17:44:03 -050025 if [ -n "$ROOTFS" ]; then
26 umount $ROOTFS/dev
27 umount $ROOTFS
28 fi
29
30 # Release NBD devices
31 if [ -n "$NBD" ]; then
32 qemu-nbd -d $NBD
33 fi
34
35 # Kill ourselves to signal any calling process
36 trap 2; kill -2 $$
37}
38
Dean Troyer8e998292011-11-07 16:41:47 -060039trap cleanup SIGHUP SIGINT SIGTERM SIGQUIT EXIT
Dean Troyer55c02732011-11-01 17:44:03 -050040
Jesse Andrewse97a2e72011-10-30 18:37:49 -070041# Echo commands
42set -o xtrace
43
44# Keep track of the current directory
45TOOLS_DIR=$(cd $(dirname "$0") && pwd)
Jesse Andrews31989742011-10-30 18:56:05 -070046TOP_DIR=`cd $TOOLS_DIR/..; pwd`
Jesse Andrewse97a2e72011-10-30 18:37:49 -070047
48# Where to store files and instances
Jesse Andrewsb0559b22011-10-30 19:46:54 -070049WORK_DIR=${WORK_DIR:-/opt/kvmstack}
Jesse Andrewse97a2e72011-10-30 18:37:49 -070050
51# Where to store images
52IMAGES_DIR=$WORK_DIR/images
53
54# Create images dir
55mkdir -p $IMAGES_DIR
56
57# Abort if localrc is not set
58if [ ! -e $TOP_DIR/localrc ]; then
59 echo "You must have a localrc with ALL necessary passwords defined before proceeding."
60 echo "See stack.sh for required passwords."
61 exit 1
62fi
63
Jesse Andrews7fa56132011-10-30 18:43:54 -070064cd $TOP_DIR
65
Jesse Andrewse97a2e72011-10-30 18:37:49 -070066# Source params
67source ./stackrc
68
69# Configure the root password of the vm to be the same as ``ADMIN_PASSWORD``
70ROOT_PASSWORD=${ADMIN_PASSWORD:-password}
71
Jesse Andrewse97a2e72011-10-30 18:37:49 -070072# Base image (natty by default)
73DIST_NAME=${DIST_NAME:-natty}
74IMAGE_FNAME=$DIST_NAME.raw
75
76# Name of our instance, used by libvirt
77GUEST_NAME=${GUEST_NAME:-devstack}
78
79# Original version of built image
Jesse Andrews2b7d2212011-10-30 19:37:56 -070080BASE_IMAGE=$IMAGES_DIR/$DIST_NAME.raw
Jesse Andrewse97a2e72011-10-30 18:37:49 -070081
82# Copy of base image, which we pre-install with tasty treats
83VM_IMAGE=$IMAGES_DIR/$DIST_NAME.$GUEST_NAME.raw
84
85# Mop up after previous runs
86virsh destroy $GUEST_NAME || true
87
88# Where this vm is stored
89VM_DIR=$WORK_DIR/instances/$GUEST_NAME
90
91# Create vm dir
92mkdir -p $VM_DIR
93
94# Mount point into copied base image
95COPY_DIR=$VM_DIR/copy
96mkdir -p $COPY_DIR
97
Jesse Andrews2b7d2212011-10-30 19:37:56 -070098# Get the base image if it does not yet exist
99if [ ! -e $BASE_IMAGE ]; then
100 $TOOLS_DIR/get_uec_image.sh -f raw -r 5000 $DIST_NAME $BASE_IMAGE
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700101fi
102
103# Create a copy of the base image
104if [ ! -e $VM_IMAGE ]; then
105 cp -p $BASE_IMAGE $VM_IMAGE
106fi
107
108# Unmount the copied base image
109function unmount_images() {
110 # unmount the filesystem
111 while df | grep -q $COPY_DIR; do
112 umount $COPY_DIR || echo 'ok'
113 sleep 1
114 done
115}
116
117# Unmount from failed runs
118unmount_images
119
120# Ctrl-c catcher
121function kill_unmount() {
122 unmount_images
123 exit 1
124}
125
126# Install deps if needed
127dpkg -l kvm libvirt-bin kpartx || apt-get install -y --force-yes kvm libvirt-bin kpartx
128
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700129# Where Openstack code will live in image
130DEST=${DEST:-/opt/stack}
131
132# Mount the file system
Jesse Andrews2b7d2212011-10-30 19:37:56 -0700133# For some reason, UEC-based images want 255 heads * 63 sectors * 512 byte sectors = 8225280
134mount -t ext4 -o loop,offset=8225280 $VM_IMAGE $COPY_DIR
Dean Troyer8e998292011-11-07 16:41:47 -0600135mount -o bind /dev $COPY_DIR/dev
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700136
137# git clone only if directory doesn't exist already. Since ``DEST`` might not
138# be owned by the installation user, we create the directory and change the
139# ownership to the proper user.
140function git_clone {
141 if [ ! -d $2 ]; then
142 sudo mkdir $2
143 sudo chown `whoami` $2
144 git clone $1 $2
145 cd $2
146 # This checkout syntax works for both branches and tags
147 git checkout $3
148 fi
149}
150
151# Make sure that base requirements are installed
152cp /etc/resolv.conf $COPY_DIR/etc/resolv.conf
153chroot $COPY_DIR apt-get update
Anthony Youngca2c0472011-11-03 16:29:32 -0700154chroot $COPY_DIR apt-get install -y --download-only `cat files/apts/* | grep NOPRIME | cut -d\# -f1`
155chroot $COPY_DIR apt-get install -y --force-yes `cat files/apts/* | grep -v NOPRIME | cut -d\# -f1`
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700156chroot $COPY_DIR pip install `cat files/pips/*`
157
Dean Troyer8e998292011-11-07 16:41:47 -0600158umount $COPY_DIR/dev
159
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700160# Clean out code repos if directed to do so
161if [ "$CLEAN" = "1" ]; then
162 rm -rf $COPY_DIR/$DEST
163fi
164
165# Cache openstack code
166mkdir -p $COPY_DIR/$DEST
167git_clone $NOVA_REPO $COPY_DIR/$DEST/nova $NOVA_BRANCH
168git_clone $GLANCE_REPO $COPY_DIR/$DEST/glance $GLANCE_BRANCH
169git_clone $KEYSTONE_REPO $COPY_DIR/$DESTkeystone $KEYSTONE_BRANCH
170git_clone $NOVNC_REPO $COPY_DIR/$DEST/noVNC $NOVNC_BRANCH
171git_clone $HORIZON_REPO $COPY_DIR/$DEST/horizon $HORIZON_BRANCH $HORIZON_TAG
172git_clone $NOVACLIENT_REPO $COPY_DIR/$DEST/python-novaclient $NOVACLIENT_BRANCH
173git_clone $OPENSTACKX_REPO $COPY_DIR/$DEST/openstackx $OPENSTACKX_BRANCH
174git_clone $KEYSTONE_REPO $COPY_DIR/$DEST/keystone $KEYSTONE_BRANCH
175git_clone $NOVNC_REPO $COPY_DIR/$DEST/noVNC $NOVNC_BRANCH
Dean Troyer264aba52011-11-04 13:22:09 -0500176git_clone $CITEST_REPO $COPY_DIR/$DEST/openstack-integration-tests $CITEST_BRANCH
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700177
Dean Troyer8e998292011-11-07 16:41:47 -0600178if [ -z "$UPLOAD_LEGACY_TTY" =; then
179 # Pre-load an image for testing
180 UEC_NAME=$DIST_NAME-server-cloudimg-amd64
181 CIVMDIR=${COPY_DIR}${DEST}/openstack-integration-tests/include/sample_vm
182 if [ ! -e $CIVMDIR/$UEC_NAME.tar.gz ]; then
183 mkdir -p $CIVMDIR
184 (cd $CIVMDIR && wget -N http://uec-images.ubuntu.com/$DIST_NAME/current/$UEC_NAME.tar.gz;
185 tar xzf $UEC_NAME.tar.gz;)
186 fi
Dean Troyer89d1d022011-11-05 16:16:54 -0500187fi
188
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700189# Back to devstack
190cd $TOP_DIR
191
192# Unmount the filesystems
193unmount_images
194
195# Network configuration variables
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700196GUEST_NETWORK=${GUEST_NETWORK:-1}
Jesse Andrews1d1dda12011-11-01 19:46:17 -0700197GUEST_RECREATE_NET=${GUEST_RECREATE_NET:-yes}
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700198
199GUEST_IP=${GUEST_IP:-192.168.$GUEST_NETWORK.50}
200GUEST_CIDR=${GUEST_CIDR:-$GUEST_IP/24}
201GUEST_NETMASK=${GUEST_NETMASK:-255.255.255.0}
202GUEST_GATEWAY=${GUEST_GATEWAY:-192.168.$GUEST_NETWORK.1}
203GUEST_MAC=${GUEST_MAC:-"02:16:3e:07:69:`printf '%02X' $GUEST_NETWORK`"}
204GUEST_RAM=${GUEST_RAM:-1524288}
205GUEST_CORES=${GUEST_CORES:-1}
206
207# libvirt.xml configuration
208NET_XML=$VM_DIR/net.xml
209cat > $NET_XML <<EOF
210<network>
211 <name>devstack-$GUEST_NETWORK</name>
212 <bridge name="stackbr%d" />
213 <forward/>
214 <ip address="$GUEST_GATEWAY" netmask="$GUEST_NETMASK" />
215</network>
216EOF
217
Jesse Andrews1d1dda12011-11-01 19:46:17 -0700218if [[ "$GUEST_RECREATE_NET" == "yes" ]]; then
219 virsh net-destroy devstack-$GUEST_NETWORK || true
220 virsh net-create $VM_DIR/net.xml
221fi
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700222
223# libvirt.xml configuration
224LIBVIRT_XML=$VM_DIR/libvirt.xml
225cat > $LIBVIRT_XML <<EOF
226<domain type='kvm'>
227 <name>$GUEST_NAME</name>
228 <memory>$GUEST_RAM</memory>
229 <os>
230 <type>hvm</type>
231 <bootmenu enable='yes'/>
232 </os>
233 <features>
234 <acpi/>
235 </features>
236 <vcpu>$GUEST_CORES</vcpu>
237 <devices>
238 <disk type='file'>
239 <driver type='qcow2'/>
240 <source file='$VM_DIR/disk'/>
241 <target dev='vda' bus='virtio'/>
242 </disk>
243
244 <interface type='network'>
245 <source network='devstack-$GUEST_NETWORK'/>
246 </interface>
247
248 <!-- The order is significant here. File must be defined first -->
249 <serial type="file">
250 <source path='$VM_DIR/console.log'/>
251 <target port='1'/>
252 </serial>
253
254 <console type='pty' tty='/dev/pts/2'>
255 <source path='/dev/pts/2'/>
256 <target port='0'/>
257 </console>
258
259 <serial type='pty'>
260 <source path='/dev/pts/2'/>
261 <target port='0'/>
262 </serial>
263
264 <graphics type='vnc' port='-1' autoport='yes' keymap='en-us' listen='0.0.0.0'/>
265 </devices>
266</domain>
267EOF
268
269# Mount point for instance fs
270ROOTFS=$VM_DIR/root
271mkdir -p $ROOTFS
272
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700273# Clean up from previous runs
274umount $ROOTFS || echo 'ok'
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700275
276# Clean up old runs
277cd $VM_DIR
278rm -f $VM_DIR/disk
279
280# Create our instance fs
281qemu-img create -f qcow2 -b $VM_IMAGE disk
282
Dean Troyerdccd6b92011-11-01 15:46:14 -0500283# Finds the next available NBD device
284# Exits script if error connecting or none free
285# map_nbd image
286# returns full nbd device path
287function map_nbd {
288 for i in `seq 0 15`; do
289 if [ ! -e /sys/block/nbd$i/pid ]; then
290 NBD=/dev/nbd$i
291 # Connect to nbd and wait till it is ready
292 qemu-nbd -c $NBD $1
293 if ! timeout 60 sh -c "while ! [ -e ${NBD}p1 ]; do sleep 1; done"; then
294 echo "Couldn't connect $NBD"
295 exit 1
296 fi
297 break
298 fi
299 done
300 if [ -z "$NBD" ]; then
301 echo "No free NBD slots"
302 exit 1
303 fi
304 echo $NBD
305}
306
Dean Troyer7a569732011-10-31 17:34:29 -0500307# Make sure we have nbd-ness
308modprobe nbd max_part=63
309
310# Set up nbd
Dean Troyerdccd6b92011-11-01 15:46:14 -0500311NBD=`map_nbd disk`
Dean Troyer7a569732011-10-31 17:34:29 -0500312NBD_DEV=`basename $NBD`
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700313
314# Mount the instance
Jesse Andrews2b7d2212011-10-30 19:37:56 -0700315mount ${NBD}p1 $ROOTFS
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700316
317# Configure instance network
318INTERFACES=$ROOTFS/etc/network/interfaces
319cat > $INTERFACES <<EOF
320auto lo
321iface lo inet loopback
322
323auto eth0
324iface eth0 inet static
325 address $GUEST_IP
326 netmask $GUEST_NETMASK
327 gateway $GUEST_GATEWAY
328EOF
329
330# User configuration for the instance
331chroot $ROOTFS groupadd libvirtd || true
332chroot $ROOTFS useradd stack -s /bin/bash -d $DEST -G libvirtd
Jesse Andrews5f894cd2011-10-30 19:52:50 -0700333cp -pr $TOP_DIR $ROOTFS/$DEST/devstack
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700334echo "root:$ROOT_PASSWORD" | chroot $ROOTFS chpasswd
335echo "stack:pass" | chroot $ROOTFS chpasswd
336echo "stack ALL=(ALL) NOPASSWD: ALL" >> $ROOTFS/etc/sudoers
337
338# Gracefully cp only if source file/dir exists
339function cp_it {
340 if [ -e $1 ] || [ -d $1 ]; then
341 cp -pRL $1 $2
342 fi
343}
344
345# Copy over your ssh keys and env if desired
346COPYENV=${COPYENV:-1}
347if [ "$COPYENV" = "1" ]; then
348 cp_it ~/.ssh $ROOTFS/$DEST/.ssh
349 cp_it ~/.ssh/id_rsa.pub $ROOTFS/$DEST/.ssh/authorized_keys
350 cp_it ~/.gitconfig $ROOTFS/$DEST/.gitconfig
351 cp_it ~/.vimrc $ROOTFS/$DEST/.vimrc
352 cp_it ~/.bashrc $ROOTFS/$DEST/.bashrc
353fi
354
355# pre-cache uec images
356for image_url in ${IMAGE_URLS//,/ }; do
357 IMAGE_FNAME=`basename "$image_url"`
358 if [ ! -f $IMAGES_DIR/$IMAGE_FNAME ]; then
359 wget -c $image_url -O $IMAGES_DIR/$IMAGE_FNAME
360 fi
361 cp $IMAGES_DIR/$IMAGE_FNAME $ROOTFS/$DEST/devstack/files
362done
363
364# Configure the runner
365RUN_SH=$ROOTFS/$DEST/run.sh
366cat > $RUN_SH <<EOF
367#!/usr/bin/env bash
368
369# Kill any existing screens
370killall screen
371
372# Install and run stack.sh
373sudo apt-get update
374sudo apt-get -y --force-yes install git-core vim-nox sudo
375if [ ! -d "$DEST/devstack" ]; then
376 git clone git://github.com/cloudbuilders/devstack.git $DEST/devstack
377fi
378cd $DEST/devstack && $STACKSH_PARAMS FORCE=yes ./stack.sh > /$DEST/run.sh.log
379echo >> /$DEST/run.sh.log
380echo >> /$DEST/run.sh.log
381echo "All done! Time to start clicking." >> /$DEST/run.sh.log
382cat $DEST/run.sh.log
383EOF
384chmod 755 $RUN_SH
385
386# Make runner launch on boot
Jesse Andrews2b7d2212011-10-30 19:37:56 -0700387RC_LOCAL=$ROOTFS/etc/init.d/zlocal
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700388cat > $RC_LOCAL <<EOF
389#!/bin/sh -e
Jesse Andrewsddcc36d2011-10-30 22:41:23 -0700390# cloud-init overwrites the hostname with ubuntuhost
391echo $GUEST_NAME > /etc/hostname
392hostname $GUEST_NAME
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700393su -c "$DEST/run.sh" stack
394EOF
395chmod +x $RC_LOCAL
Jesse Andrews2b7d2212011-10-30 19:37:56 -0700396chroot $ROOTFS sudo update-rc.d zlocal defaults 99
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700397
398# Make our ip address hostnames look nice at the command prompt
399echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/$DEST/.bashrc
400echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/etc/profile
401
402# Give stack ownership over $DEST so it may do the work needed
403chroot $ROOTFS chown -R stack $DEST
404
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700405# Set the hostname
406echo $GUEST_NAME > $ROOTFS/etc/hostname
407
408# We need the hostname to resolve for rabbit to launch
409if ! grep -q $GUEST_NAME $ROOTFS/etc/hosts; then
410 echo "$GUEST_IP $GUEST_NAME" >> $ROOTFS/etc/hosts
411fi
412
Dean Troyer6fe687b2011-10-31 20:30:04 -0500413# GRUB 2 wants to see /dev
414mount -o bind /dev $ROOTFS/dev
415
Jesse Andrews2b7d2212011-10-30 19:37:56 -0700416# Change boot params so that we get a console log
417G_DEV_UUID=`blkid -t LABEL=cloudimg-rootfs -s UUID -o value | head -1`
418sed -e "s/GRUB_TIMEOUT=.*$/GRUB_TIMEOUT=3/" -i $ROOTFS/etc/default/grub
Jesse Andrews2c5201b2011-10-30 20:44:26 -0700419sed -e "s,GRUB_CMDLINE_LINUX_DEFAULT=.*$,GRUB_CMDLINE_LINUX_DEFAULT=\"console=ttyS0 console=tty0 ds=nocloud ubuntu-pass=pass\",g" -i $ROOTFS/etc/default/grub
Jesse Andrews2b7d2212011-10-30 19:37:56 -0700420sed -e 's/[#]*GRUB_TERMINAL=.*$/GRUB_TERMINAL="serial console"/' -i $ROOTFS/etc/default/grub
421echo 'GRUB_SERIAL_COMMAND="serial --unit=0"' >>$ROOTFS/etc/default/grub
422echo 'GRUB_DISABLE_OS_PROBER=true' >>$ROOTFS/etc/default/grub
423echo "GRUB_DEVICE_UUID=$G_DEV_UUID" >>$ROOTFS/etc/default/grub
424
425chroot $ROOTFS update-grub
Jesse Andrews2b7d2212011-10-30 19:37:56 -0700426
427# Pre-generate ssh host keys and allow password login
428chroot $ROOTFS dpkg-reconfigure openssh-server
429sed -e 's/^PasswordAuthentication.*$/PasswordAuthentication yes/' -i $ROOTFS/etc/ssh/sshd_config
430
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700431# Unmount
Dean Troyer8e998292011-11-07 16:41:47 -0600432umount $ROOTFS/dev
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700433umount $ROOTFS || echo 'ok'
Dean Troyer55c02732011-11-01 17:44:03 -0500434ROOTFS=""
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700435qemu-nbd -d $NBD
Dean Troyer55c02732011-11-01 17:44:03 -0500436NBD=""
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700437
Dean Troyer8e998292011-11-07 16:41:47 -0600438trap - SIGHUP SIGINT SIGTERM SIGQUIT EXIT
439
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700440# Create the instance
441cd $VM_DIR && virsh create libvirt.xml
442
443# Tail the console log till we are done
444WAIT_TILL_LAUNCH=${WAIT_TILL_LAUNCH:-1}
445if [ "$WAIT_TILL_LAUNCH" = "1" ]; then
446 # Done creating the container, let's tail the log
447 echo
448 echo "============================================================="
449 echo " -- YAY! --"
450 echo "============================================================="
451 echo
452 echo "We're done launching the vm, about to start tailing the"
453 echo "stack.sh log. It will take a second or two to start."
454 echo
455 echo "Just CTRL-C at any time to stop tailing."
456
457 while [ ! -e "$VM_DIR/console.log" ]; do
458 sleep 1
459 done
460
Jesse Andrews16341962011-10-31 00:21:56 -0700461 tail -F $VM_DIR/console.log &
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700462
463 TAIL_PID=$!
464
465 function kill_tail() {
466 kill $TAIL_PID
467 exit 1
468 }
469
470 # Let Ctrl-c kill tail and exit
471 trap kill_tail SIGINT
472
Jesse Andrews16341962011-10-31 00:21:56 -0700473 set +o xtrace
474
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700475 echo "Waiting stack.sh to finish..."
476 while ! cat $VM_DIR/console.log | grep -q 'All done' ; do
Jesse Andrews16341962011-10-31 00:21:56 -0700477 sleep 1
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700478 done
479
Jesse Andrews16341962011-10-31 00:21:56 -0700480 set -o xtrace
481
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700482 kill $TAIL_PID
483
Jesse Andrewsa06ac1c2011-10-31 22:29:23 -0700484 if ! grep -q "^stack.sh completed in" $VM_DIR/console.log; then
Jesse Andrewse97a2e72011-10-30 18:37:49 -0700485 exit 1
486 fi
487 echo ""
488 echo "Finished - Zip-a-dee Doo-dah!"
489fi