Browse code

convert build_kvm to build_libvirt - using libvirt net

Jesse Andrews authored on 2011/10/31 10:37:49
Showing 1 changed files
1 1
new file mode 100755
... ...
@@ -0,0 +1,414 @@
0
+#!/usr/bin/env bash
1
+
2
+# exit on error to stop unexpected errors
3
+set -o errexit
4
+
5
+# Make sure that we have the proper version of ubuntu
6
+UBUNTU_VERSION=`cat /etc/lsb-release | grep CODENAME | sed 's/.*=//g'`
7
+if [ ! "oneiric" = "$UBUNTU_VERSION" ]; then
8
+    if [ ! "natty" = "$UBUNTU_VERSION" ]; then
9
+        echo "This script only works with oneiric and natty"
10
+        exit 1
11
+    fi
12
+fi
13
+
14
+# Echo commands
15
+set -o xtrace
16
+
17
+# Keep track of the current directory
18
+TOOLS_DIR=$(cd $(dirname "$0") && pwd)
19
+TOP_DIR=$TOOLS_DIR/..
20
+
21
+# Where to store files and instances
22
+WORK_DIR=${WORK_DIR:-$TOP_DIR/work}
23
+
24
+# Where to store images
25
+IMAGES_DIR=$WORK_DIR/images
26
+
27
+# Create images dir
28
+mkdir -p $IMAGES_DIR
29
+
30
+# Abort if localrc is not set
31
+if [ ! -e $TOP_DIR/localrc ]; then
32
+    echo "You must have a localrc with ALL necessary passwords defined before proceeding."
33
+    echo "See stack.sh for required passwords."
34
+    exit 1
35
+fi
36
+
37
+# Source params
38
+source ./stackrc
39
+
40
+# Configure the root password of the vm to be the same as ``ADMIN_PASSWORD``
41
+ROOT_PASSWORD=${ADMIN_PASSWORD:-password}
42
+
43
+
44
+# Base image (natty by default)
45
+DIST_NAME=${DIST_NAME:-natty}
46
+IMAGE_FNAME=$DIST_NAME.raw
47
+
48
+# Name of our instance, used by libvirt
49
+GUEST_NAME=${GUEST_NAME:-devstack}
50
+
51
+# Original version of built image
52
+BASE_IMAGE=$WORK_DIR/images/$DIST_NAME.raw
53
+
54
+# Copy of base image, which we pre-install with tasty treats
55
+VM_IMAGE=$IMAGES_DIR/$DIST_NAME.$GUEST_NAME.raw
56
+
57
+# Mop up after previous runs
58
+virsh destroy $GUEST_NAME || true
59
+
60
+# Where this vm is stored
61
+VM_DIR=$WORK_DIR/instances/$GUEST_NAME
62
+
63
+# Create vm dir
64
+mkdir -p $VM_DIR
65
+
66
+# Mount point into copied base image
67
+COPY_DIR=$VM_DIR/copy
68
+mkdir -p $COPY_DIR
69
+
70
+# Create the base image if it does not yet exist
71
+if [ ! -e $IMAGES_DIR/$IMAGE_FNAME ]; then
72
+    cd $TOOLS_DIR
73
+    ./make_image.sh -m -r 5000  $DIST_NAME raw
74
+    mv $DIST_NAME.raw $BASE_IMAGE
75
+    cd $TOP_DIR
76
+fi
77
+
78
+# Create a copy of the base image
79
+if [ ! -e $VM_IMAGE ]; then
80
+    cp -p $BASE_IMAGE $VM_IMAGE
81
+fi
82
+
83
+# Unmount the copied base image
84
+function unmount_images() {
85
+    # unmount the filesystem
86
+    while df | grep -q $COPY_DIR; do
87
+        umount $COPY_DIR || echo 'ok'
88
+        sleep 1
89
+    done
90
+}
91
+
92
+# Unmount from failed runs
93
+unmount_images
94
+
95
+# Ctrl-c catcher
96
+function kill_unmount() {
97
+    unmount_images
98
+    exit 1
99
+}
100
+
101
+# Install deps if needed
102
+dpkg -l kvm libvirt-bin kpartx || apt-get install -y --force-yes kvm libvirt-bin kpartx
103
+
104
+# Let Ctrl-c kill tail and exit
105
+trap kill_unmount SIGINT
106
+
107
+# Where Openstack code will live in image
108
+DEST=${DEST:-/opt/stack}
109
+
110
+# Mount the file system
111
+mount -o loop,offset=32256 $VM_IMAGE  $COPY_DIR
112
+
113
+# git clone only if directory doesn't exist already.  Since ``DEST`` might not
114
+# be owned by the installation user, we create the directory and change the
115
+# ownership to the proper user.
116
+function git_clone {
117
+    if [ ! -d $2 ]; then
118
+        sudo mkdir $2
119
+        sudo chown `whoami` $2
120
+        git clone $1 $2
121
+        cd $2
122
+        # This checkout syntax works for both branches and tags
123
+        git checkout $3
124
+    fi
125
+}
126
+
127
+# Make sure that base requirements are installed
128
+cp /etc/resolv.conf $COPY_DIR/etc/resolv.conf
129
+chroot $COPY_DIR apt-get update
130
+chroot $COPY_DIR apt-get install -y --force-yes `cat files/apts/* | cut -d\# -f1 | egrep -v "(rabbitmq|libvirt-bin|mysql-server)"`
131
+chroot $COPY_DIR apt-get install -y --download-only rabbitmq-server libvirt-bin mysql-server
132
+chroot $COPY_DIR pip install `cat files/pips/*`
133
+
134
+# Clean out code repos if directed to do so
135
+if [ "$CLEAN" = "1" ]; then
136
+    rm -rf $COPY_DIR/$DEST
137
+fi
138
+
139
+# Cache openstack code
140
+mkdir -p $COPY_DIR/$DEST
141
+git_clone $NOVA_REPO $COPY_DIR/$DEST/nova $NOVA_BRANCH
142
+git_clone $GLANCE_REPO $COPY_DIR/$DEST/glance $GLANCE_BRANCH
143
+git_clone $KEYSTONE_REPO $COPY_DIR/$DESTkeystone $KEYSTONE_BRANCH
144
+git_clone $NOVNC_REPO $COPY_DIR/$DEST/noVNC $NOVNC_BRANCH
145
+git_clone $HORIZON_REPO $COPY_DIR/$DEST/horizon $HORIZON_BRANCH $HORIZON_TAG
146
+git_clone $NOVACLIENT_REPO $COPY_DIR/$DEST/python-novaclient $NOVACLIENT_BRANCH
147
+git_clone $OPENSTACKX_REPO $COPY_DIR/$DEST/openstackx $OPENSTACKX_BRANCH
148
+git_clone $KEYSTONE_REPO $COPY_DIR/$DEST/keystone $KEYSTONE_BRANCH
149
+git_clone $NOVNC_REPO $COPY_DIR/$DEST/noVNC $NOVNC_BRANCH
150
+
151
+# Back to devstack
152
+cd $TOP_DIR
153
+
154
+# Unmount the filesystems
155
+unmount_images
156
+
157
+# Network configuration variables
158
+BRIDGE=${BRIDGE:-br0}
159
+GUEST_NETWORK=${GUEST_NETWORK:-1}
160
+
161
+GUEST_IP=${GUEST_IP:-192.168.$GUEST_NETWORK.50}
162
+GUEST_CIDR=${GUEST_CIDR:-$GUEST_IP/24}
163
+GUEST_NETMASK=${GUEST_NETMASK:-255.255.255.0}
164
+GUEST_GATEWAY=${GUEST_GATEWAY:-192.168.$GUEST_NETWORK.1}
165
+GUEST_MAC=${GUEST_MAC:-"02:16:3e:07:69:`printf '%02X' $GUEST_NETWORK`"}
166
+GUEST_RAM=${GUEST_RAM:-1524288}
167
+GUEST_CORES=${GUEST_CORES:-1}
168
+
169
+# libvirt.xml configuration
170
+NET_XML=$VM_DIR/net.xml
171
+cat > $NET_XML <<EOF
172
+<network>
173
+  <name>devstack-$GUEST_NETWORK</name>
174
+  <bridge name="stackbr%d" />
175
+  <forward/>
176
+  <ip address="$GUEST_GATEWAY" netmask="$GUEST_NETMASK" />
177
+</network>
178
+EOF
179
+
180
+virsh net-destroy devstack-$GUEST_NETWORK || true
181
+virsh net-create $VM_DIR/net.xml
182
+
183
+# libvirt.xml configuration
184
+LIBVIRT_XML=$VM_DIR/libvirt.xml
185
+cat > $LIBVIRT_XML <<EOF
186
+<domain type='kvm'>
187
+    <name>$GUEST_NAME</name>
188
+    <memory>$GUEST_RAM</memory>
189
+    <os>
190
+        <type>hvm</type>
191
+        <bootmenu enable='yes'/>
192
+    </os>
193
+    <features>
194
+        <acpi/>
195
+    </features>
196
+    <vcpu>$GUEST_CORES</vcpu>
197
+    <devices>
198
+        <disk type='file'>
199
+            <driver type='qcow2'/>
200
+            <source file='$VM_DIR/disk'/>
201
+            <target dev='vda' bus='virtio'/>
202
+        </disk>
203
+
204
+        <interface type='network'>
205
+           <source network='devstack-$GUEST_NETWORK'/>
206
+        </interface>
207
+        
208
+        <!-- The order is significant here.  File must be defined first -->
209
+        <serial type="file">
210
+            <source path='$VM_DIR/console.log'/>
211
+            <target port='1'/>
212
+        </serial>
213
+
214
+        <console type='pty' tty='/dev/pts/2'>
215
+            <source path='/dev/pts/2'/>
216
+            <target port='0'/>
217
+        </console>
218
+
219
+        <serial type='pty'>
220
+            <source path='/dev/pts/2'/>
221
+            <target port='0'/>
222
+        </serial>
223
+
224
+        <graphics type='vnc' port='-1' autoport='yes' keymap='en-us' listen='0.0.0.0'/>
225
+    </devices>
226
+</domain>
227
+EOF
228
+
229
+# Mount point for instance fs
230
+ROOTFS=$VM_DIR/root
231
+mkdir -p $ROOTFS
232
+
233
+# Make sure we have nbd-ness
234
+modprobe nbd max_part=63
235
+
236
+# Which NBD device to use?
237
+NBD=${NBD:-/dev/nbd5}
238
+
239
+# Clean up from previous runs
240
+umount $ROOTFS || echo 'ok'
241
+qemu-nbd -d $NBD || echo 'ok'
242
+
243
+# Clean up old runs
244
+cd $VM_DIR
245
+rm -f $VM_DIR/disk
246
+
247
+# Create our instance fs
248
+qemu-img create -f qcow2 -b $VM_IMAGE disk
249
+
250
+# Connect our nbd and wait till it is mountable
251
+qemu-nbd -c $NBD disk
252
+NBD_DEV=`basename $NBD`
253
+if ! timeout 60 sh -c "while ! [ -e /sys/block/$NBD_DEV/pid ]; do sleep 1; done"; then
254
+    echo "Couldn't connect $NBD"
255
+    exit 1
256
+fi
257
+
258
+# Mount the instance
259
+mount $NBD $ROOTFS -o offset=32256 -t ext4
260
+
261
+# Configure instance network
262
+INTERFACES=$ROOTFS/etc/network/interfaces
263
+cat > $INTERFACES <<EOF
264
+auto lo
265
+iface lo inet loopback
266
+
267
+auto eth0
268
+iface eth0 inet static
269
+        address $GUEST_IP
270
+        netmask $GUEST_NETMASK
271
+        gateway $GUEST_GATEWAY
272
+EOF
273
+
274
+# User configuration for the instance
275
+chroot $ROOTFS groupadd libvirtd || true
276
+chroot $ROOTFS useradd stack -s /bin/bash -d $DEST -G libvirtd
277
+cp -pr $TOOLS_DIR/.. $ROOTFS/$DEST/devstack
278
+echo "root:$ROOT_PASSWORD" | chroot $ROOTFS chpasswd
279
+echo "stack:pass" | chroot $ROOTFS chpasswd
280
+echo "stack ALL=(ALL) NOPASSWD: ALL" >> $ROOTFS/etc/sudoers
281
+
282
+# Gracefully cp only if source file/dir exists
283
+function cp_it {
284
+    if [ -e $1 ] || [ -d $1 ]; then
285
+        cp -pRL $1 $2
286
+    fi
287
+}
288
+
289
+# Copy over your ssh keys and env if desired
290
+COPYENV=${COPYENV:-1}
291
+if [ "$COPYENV" = "1" ]; then
292
+    cp_it ~/.ssh $ROOTFS/$DEST/.ssh
293
+    cp_it ~/.ssh/id_rsa.pub $ROOTFS/$DEST/.ssh/authorized_keys
294
+    cp_it ~/.gitconfig $ROOTFS/$DEST/.gitconfig
295
+    cp_it ~/.vimrc $ROOTFS/$DEST/.vimrc
296
+    cp_it ~/.bashrc $ROOTFS/$DEST/.bashrc
297
+fi
298
+
299
+# pre-cache uec images
300
+for image_url in ${IMAGE_URLS//,/ }; do
301
+    IMAGE_FNAME=`basename "$image_url"`
302
+    if [ ! -f $IMAGES_DIR/$IMAGE_FNAME ]; then
303
+        wget -c $image_url -O $IMAGES_DIR/$IMAGE_FNAME
304
+    fi
305
+    cp $IMAGES_DIR/$IMAGE_FNAME $ROOTFS/$DEST/devstack/files
306
+done
307
+
308
+# Configure the runner
309
+RUN_SH=$ROOTFS/$DEST/run.sh
310
+cat > $RUN_SH <<EOF
311
+#!/usr/bin/env bash
312
+
313
+# Kill any existing screens
314
+killall screen
315
+
316
+# Install and run stack.sh
317
+sudo apt-get update
318
+sudo apt-get -y --force-yes install git-core vim-nox sudo
319
+if [ ! -d "$DEST/devstack" ]; then
320
+    git clone git://github.com/cloudbuilders/devstack.git $DEST/devstack
321
+fi
322
+cd $DEST/devstack && $STACKSH_PARAMS FORCE=yes ./stack.sh > /$DEST/run.sh.log
323
+echo >> /$DEST/run.sh.log
324
+echo >> /$DEST/run.sh.log
325
+echo "All done! Time to start clicking." >> /$DEST/run.sh.log
326
+cat $DEST/run.sh.log
327
+EOF
328
+chmod 755 $RUN_SH
329
+
330
+# Make runner launch on boot
331
+RC_LOCAL=$ROOTFS/etc/init.d/local
332
+cat > $RC_LOCAL <<EOF
333
+#!/bin/sh -e
334
+# Reboot if this is our first run to enable console log on $DIST_NAME :(
335
+if [ ! -e /root/firstlaunch ]; then
336
+    touch /root/firstlaunch
337
+    reboot -f
338
+    exit 0
339
+fi
340
+su -c "$DEST/run.sh" stack
341
+EOF
342
+chmod +x $RC_LOCAL
343
+chroot $ROOTFS sudo update-rc.d local defaults 80
344
+
345
+# Make our ip address hostnames look nice at the command prompt
346
+echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/$DEST/.bashrc
347
+echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $ROOTFS/etc/profile
348
+
349
+# Give stack ownership over $DEST so it may do the work needed
350
+chroot $ROOTFS chown -R stack $DEST
351
+
352
+# Change boot params so that we get a console log
353
+sudo sed -e "s/quiet splash/splash console=ttyS0 console=ttyS1,19200n8/g" -i $ROOTFS/boot/grub/menu.lst
354
+sudo sed -e "s/^hiddenmenu//g" -i $ROOTFS/boot/grub/menu.lst
355
+
356
+# Set the hostname
357
+echo $GUEST_NAME > $ROOTFS/etc/hostname
358
+
359
+# We need the hostname to resolve for rabbit to launch
360
+if ! grep -q $GUEST_NAME $ROOTFS/etc/hosts; then
361
+    echo "$GUEST_IP $GUEST_NAME" >> $ROOTFS/etc/hosts
362
+fi
363
+
364
+# Unmount
365
+umount $ROOTFS || echo 'ok'
366
+qemu-nbd -d $NBD
367
+
368
+# Create the instance
369
+cd $VM_DIR && virsh create libvirt.xml
370
+
371
+# Tail the console log till we are done
372
+WAIT_TILL_LAUNCH=${WAIT_TILL_LAUNCH:-1}
373
+if [ "$WAIT_TILL_LAUNCH" = "1" ]; then
374
+    # Done creating the container, let's tail the log
375
+    echo
376
+    echo "============================================================="
377
+    echo "                          -- YAY! --"
378
+    echo "============================================================="
379
+    echo
380
+    echo "We're done launching the vm, about to start tailing the"
381
+    echo "stack.sh log. It will take a second or two to start."
382
+    echo
383
+    echo "Just CTRL-C at any time to stop tailing."
384
+
385
+    while [ ! -e "$VM_DIR/console.log" ]; do
386
+      sleep 1
387
+    done
388
+
389
+    tail -F $VM_DIR/console.log &
390
+
391
+    TAIL_PID=$!
392
+
393
+    function kill_tail() {
394
+        kill $TAIL_PID
395
+        exit 1
396
+    }
397
+
398
+    # Let Ctrl-c kill tail and exit
399
+    trap kill_tail SIGINT
400
+
401
+    echo "Waiting stack.sh to finish..."
402
+    while ! cat $VM_DIR/console.log | grep -q 'All done' ; do
403
+        sleep 5
404
+    done
405
+
406
+    kill $TAIL_PID
407
+
408
+    if grep -q "stack.sh failed" $VM_DIR/console.log; then
409
+        exit 1
410
+    fi
411
+    echo ""
412
+    echo "Finished - Zip-a-dee Doo-dah!"
413
+fi