blob: 352f63acce5292ad450878f5249e43114317521a [file] [log] [blame]
Anthony Youngb62b4ca2011-10-26 22:29:08 -07001#!/bin/bash
2
John Garbuttdaadf742012-04-27 18:28:28 +01003# This script is a level script
4# It must be run on a XenServer or XCP machine
5#
6# It creates a DomU VM that runs OpenStack services
7#
8# For more details see: README.md
9
Renuka Apte0af143b2012-04-02 15:46:53 -070010# Exit on errors
11set -o errexit
John Garbuttdaadf742012-04-27 18:28:28 +010012# Echo commands
13set -o xtrace
Renuka Apte0af143b2012-04-02 15:46:53 -070014
Anthony Youngb62b4ca2011-10-26 22:29:08 -070015# Abort if localrc is not set
16if [ ! -e ../../localrc ]; then
17 echo "You must have a localrc with ALL necessary passwords defined before proceeding."
18 echo "See the xen README for required passwords."
19 exit 1
20fi
21
Anthony Youngaf6ed6b2011-11-02 07:50:27 -050022# This directory
23TOP_DIR=$(cd $(dirname "$0") && pwd)
24
Anthony Youngb3e2f332012-03-16 17:01:49 -070025# Source lower level functions
26. $TOP_DIR/../../functions
27
John Garbuttdaadf742012-04-27 18:28:28 +010028# Include onexit commands
29. $TOP_DIR/scripts/on_exit.sh
30
31
32#
33# Get Settings
34#
35
Anthony Youngb3e2f332012-03-16 17:01:49 -070036# Source params - override xenrc params in your localrc to suit your taste
Anthony Young11889042012-01-12 17:11:56 -080037source xenrc
Anthony Youngaf6ed6b2011-11-02 07:50:27 -050038
Renuka Apte0af143b2012-04-02 15:46:53 -070039xe_min()
40{
41 local cmd="$1"
42 shift
43 xe "$cmd" --minimal "$@"
44}
Anthony Youngb62b4ca2011-10-26 22:29:08 -070045
John Garbuttdaadf742012-04-27 18:28:28 +010046
47#
48# Prepare Dom0
49# including installing XenAPI plugins
50#
51
Renuka Apte0af143b2012-04-02 15:46:53 -070052cd $TOP_DIR
53if [ -f ./master ]
54then
55 rm -rf ./master
56 rm -rf ./nova
Anthony Youngb62b4ca2011-10-26 22:29:08 -070057fi
John Garbuttdaadf742012-04-27 18:28:28 +010058
59# get nova
Renuka Apte0af143b2012-04-02 15:46:53 -070060wget https://github.com/openstack/nova/zipball/master --no-check-certificate
61unzip -o master -d ./nova
John Garbuttdaadf742012-04-27 18:28:28 +010062
63# install xapi plugins
64XAPI_PLUGIN_DIR=/etc/xapi.d/plugins/
65if [ ! -d $XAPI_PLUGIN_DIR ]; then
66 # the following is needed when using xcp-xapi
67 XAPI_PLUGIN_DIR=/usr/lib/xcp/plugins/
68fi
69cp -pr ./nova/*/plugins/xenserver/xenapi/etc/xapi.d/plugins/* $XAPI_PLUGIN_DIR
70chmod a+x ${XAPI_PLUGIN_DIR}*
Renuka Apte0af143b2012-04-02 15:46:53 -070071
72mkdir -p /boot/guest
73
John Garbuttdaadf742012-04-27 18:28:28 +010074
75#
76# Configure Networking
77#
Anthony Youngb62b4ca2011-10-26 22:29:08 -070078
79# Helper to create networks
rootb1153412012-01-19 13:28:21 -080080# Uses echo trickery to return network uuid
Anthony Youngb62b4ca2011-10-26 22:29:08 -070081function create_network() {
rootb1153412012-01-19 13:28:21 -080082 br=$1
83 dev=$2
84 vlan=$3
85 netname=$4
86 if [ -z $br ]
87 then
Renuka Apte0af143b2012-04-02 15:46:53 -070088 pif=$(xe_min pif-list device=$dev VLAN=$vlan)
rootb1153412012-01-19 13:28:21 -080089 if [ -z $pif ]
90 then
91 net=$(xe network-create name-label=$netname)
92 else
Renuka Apte0af143b2012-04-02 15:46:53 -070093 net=$(xe_min network-list PIF-uuids=$pif)
rootb1153412012-01-19 13:28:21 -080094 fi
95 echo $net
96 return 0
97 fi
Renuka Apte0af143b2012-04-02 15:46:53 -070098 if [ ! $(xe_min network-list params=bridge | grep -w --only-matching $br) ]
rootb1153412012-01-19 13:28:21 -080099 then
100 echo "Specified bridge $br does not exist"
101 echo "If you wish to use defaults, please keep the bridge name empty"
102 exit 1
103 else
Renuka Apte0af143b2012-04-02 15:46:53 -0700104 net=$(xe_min network-list bridge=$br)
rootb1153412012-01-19 13:28:21 -0800105 echo $net
106 fi
107}
108
109function errorcheck() {
110 rc=$?
111 if [ $rc -ne 0 ]
112 then
113 exit $rc
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700114 fi
115}
116
John Garbuttdaadf742012-04-27 18:28:28 +0100117# Create host, vm, mgmt, pub networks on XenServer
rootb1153412012-01-19 13:28:21 -0800118VM_NET=$(create_network "$VM_BR" "$VM_DEV" "$VM_VLAN" "vmbr")
119errorcheck
120MGT_NET=$(create_network "$MGT_BR" "$MGT_DEV" "$MGT_VLAN" "mgtbr")
121errorcheck
122PUB_NET=$(create_network "$PUB_BR" "$PUB_DEV" "$PUB_VLAN" "pubbr")
123errorcheck
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700124
125# Helper to create vlans
126function create_vlan() {
rootb1153412012-01-19 13:28:21 -0800127 dev=$1
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700128 vlan=$2
129 net=$3
rootb1153412012-01-19 13:28:21 -0800130 # VLAN -1 refers to no VLAN (physical network)
131 if [ $vlan -eq -1 ]
132 then
133 return
134 fi
Renuka Apte0af143b2012-04-02 15:46:53 -0700135 if [ -z $(xe_min vlan-list tag=$vlan) ]
rootb1153412012-01-19 13:28:21 -0800136 then
Renuka Apte0af143b2012-04-02 15:46:53 -0700137 pif=$(xe_min pif-list network-uuid=$net)
rootb1153412012-01-19 13:28:21 -0800138 # We created a brand new network this time
139 if [ -z $pif ]
140 then
Renuka Apte0af143b2012-04-02 15:46:53 -0700141 pif=$(xe_min pif-list device=$dev VLAN=-1)
rootb1153412012-01-19 13:28:21 -0800142 xe vlan-create pif-uuid=$pif vlan=$vlan network-uuid=$net
143 else
144 echo "VLAN does not exist but PIF attached to this network"
145 echo "How did we reach here?"
146 exit 1
147 fi
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700148 fi
149}
150
151# Create vlans for vm and management
rootb1153412012-01-19 13:28:21 -0800152create_vlan $PUB_DEV $PUB_VLAN $PUB_NET
153create_vlan $VM_DEV $VM_VLAN $VM_NET
154create_vlan $MGT_DEV $MGT_VLAN $MGT_NET
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700155
John Garbuttdaadf742012-04-27 18:28:28 +0100156# Get final bridge names
157if [ -z $VM_BR ]; then
158 VM_BR=$(xe_min network-list uuid=$VM_NET params=bridge)
159fi
160if [ -z $MGT_BR ]; then
161 MGT_BR=$(xe_min network-list uuid=$MGT_NET params=bridge)
162fi
163if [ -z $PUB_BR ]; then
164 PUB_BR=$(xe_min network-list uuid=$PUB_NET params=bridge)
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700165fi
166
John Garbuttdaadf742012-04-27 18:28:28 +0100167# dom0 ip, XenAPI is assumed to be listening
168HOST_IP=${HOST_IP:-`ifconfig xenbr0 | grep "inet addr" | cut -d ":" -f2 | sed "s/ .*//"`}
169
170# Set up ip forwarding, but skip on xcp-xapi
171if [ -a /etc/sysconfig/network]; then
172 if ! grep -q "FORWARD_IPV4=YES" /etc/sysconfig/network; then
173 # FIXME: This doesn't work on reboot!
174 echo "FORWARD_IPV4=YES" >> /etc/sysconfig/network
175 fi
176fi
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700177# Also, enable ip forwarding in rc.local, since the above trick isn't working
178if ! grep -q "echo 1 >/proc/sys/net/ipv4/ip_forward" /etc/rc.local; then
179 echo "echo 1 >/proc/sys/net/ipv4/ip_forward" >> /etc/rc.local
180fi
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700181# Enable ip forwarding at runtime as well
182echo 1 > /proc/sys/net/ipv4/ip_forward
183
John Garbuttdaadf742012-04-27 18:28:28 +0100184
185#
Anthony Young346e4912011-11-05 00:22:47 -0500186# Shutdown previous runs
John Garbuttdaadf742012-04-27 18:28:28 +0100187#
188
Anthony Young346e4912011-11-05 00:22:47 -0500189DO_SHUTDOWN=${DO_SHUTDOWN:-1}
John Garbuttdaadf742012-04-27 18:28:28 +0100190CLEAN_TEMPLATES=${CLEAN_TEMPLATES:-false}
Anthony Young346e4912011-11-05 00:22:47 -0500191if [ "$DO_SHUTDOWN" = "1" ]; then
Anthony Young40b57372011-11-05 00:30:07 -0500192 # Shutdown all domU's that created previously
John Garbuttdaadf742012-04-27 18:28:28 +0100193 clean_templates_arg=""
194 if $CLEAN_TEMPLATES; then
195 clean_templates_arg="--remove-templates"
196 fi
197 ./scripts/uninstall-os-vpx.sh $clean_templates_arg
Anthony Young346e4912011-11-05 00:22:47 -0500198
199 # Destroy any instances that were launched
200 for uuid in `xe vm-list | grep -1 instance | grep uuid | sed "s/.*\: //g"`; do
201 echo "Shutting down nova instance $uuid"
202 xe vm-unpause uuid=$uuid || true
Armando Migliaccio7a5f7f22012-04-20 22:58:00 +0100203 xe vm-shutdown uuid=$uuid || true
Anthony Young346e4912011-11-05 00:22:47 -0500204 xe vm-destroy uuid=$uuid
205 done
Anthony Youngfa4ecc62011-11-11 10:23:22 -0800206
207 # Destroy orphaned vdis
208 for uuid in `xe vdi-list | grep -1 Glance | grep uuid | sed "s/.*\: //g"`; do
209 xe vdi-destroy uuid=$uuid
210 done
Anthony Young346e4912011-11-05 00:22:47 -0500211fi
Anthony Youngb62b4ca2011-10-26 22:29:08 -0700212
Renuka Apte0af143b2012-04-02 15:46:53 -0700213
John Garbuttdaadf742012-04-27 18:28:28 +0100214#
215# Create Ubuntu VM template
216# and/or create VM from template
217#
Renuka Apte0af143b2012-04-02 15:46:53 -0700218
John Garbuttdaadf742012-04-27 18:28:28 +0100219GUEST_NAME=${GUEST_NAME:-"DevStackOSDomU"}
220TNAME="devstack_template_folsom_11.10"
221SNAME_PREPARED="template_prepared"
222SNAME_FIRST_BOOT="before_first_boot"
223
224function wait_for_VM_to_halt() {
Renuka Apte0af143b2012-04-02 15:46:53 -0700225 while true
226 do
227 state=$(xe_min vm-list name-label="$GUEST_NAME" power-state=halted)
228 if [ -n "$state" ]
229 then
230 break
231 else
232 echo "Waiting for "$GUEST_NAME" to finish installation..."
John Garbuttdaadf742012-04-27 18:28:28 +0100233 sleep 20
Renuka Apte0af143b2012-04-02 15:46:53 -0700234 fi
235 done
John Garbuttdaadf742012-04-27 18:28:28 +0100236}
Renuka Apte0af143b2012-04-02 15:46:53 -0700237
John Garbuttdaadf742012-04-27 18:28:28 +0100238templateuuid=$(xe template-list name-label="$TNAME")
239if [ -z "$templateuuid" ]; then
240 #
241 # Install Ubuntu over network
242 #
243
244 # try to find ubuntu template
245 ubuntu_template_name="Ubuntu 11.10 for DevStack (64-bit)"
246 ubuntu_template=$(xe_min template-list name-label="$ubuntu_template_name")
247
248 # remove template, if we are in CLEAN_TEMPLATE mode
249 if [ -n "$ubuntu_template" ]; then
250 if $CLEAN_TEMPLATES; then
251 xe template-param-clear param-name=other-config uuid=$ubuntu_template
252 xe template-uninstall template-uuid=$ubuntu_template force=true
253 ubuntu_template=""
254 fi
255 fi
256
257 # always update the preseed file, incase we have a newer one
258 PRESEED_URL=${PRESEED_URL:-""}
259 if [ -z "$PRESEED_URL" ]; then
260 PRESEED_URL="${HOST_IP}/devstackubuntupreseed.cfg"
261 HTTP_SERVER_LOCATION="/opt/xensource/www"
262 if [ ! -e $HTTP_SERVER_LOCATION ]; then
263 HTTP_SERVER_LOCATION="/var/www/html"
264 mkdir -p $HTTP_SERVER_LOCATION
265 fi
266 cp -f $TOP_DIR/devstackubuntupreseed.cfg $HTTP_SERVER_LOCATION
267 MIRROR=${MIRROR:-""}
268 if [ -n "$MIRROR" ]; then
269 sed -e "s,d-i mirror/http/hostname string .*,d-i mirror/http/hostname string $MIRROR," \
270 -i "${HTTP_SERVER_LOCATION}/devstackubuntupreseed.cfg"
271 fi
272 fi
273
274 if [ -z "$ubuntu_template" ]; then
275 $TOP_DIR/scripts/xenoneirictemplate.sh $PRESEED_URL
276 fi
277
278 # create a new VM with the given template
279 # creating the correct VIFs and metadata
280 $TOP_DIR/scripts/install-os-vpx.sh -t "$ubuntu_template_name" -v $VM_BR -m $MGT_BR -p $PUB_BR -l $GUEST_NAME -r $OSDOMU_MEM_MB -k "flat_network_bridge=${VM_BR}"
281
282 # wait for install to finish
283 wait_for_VM_to_halt
284
285 # set VM to restart after a reboot
Renuka Apte0af143b2012-04-02 15:46:53 -0700286 vm_uuid=$(xe_min vm-list name-label="$GUEST_NAME")
287 xe vm-param-set actions-after-reboot=Restart uuid="$vm_uuid"
288
John Garbuttdaadf742012-04-27 18:28:28 +0100289 #
290 # Prepare VM for DevStack
291 #
292
293 # Install XenServer tools, and other such things
294 $TOP_DIR/prepare_guest_template.sh "$GUEST_NAME"
295
296 # start the VM to run the prepare steps
297 xe vm-start vm="$GUEST_NAME"
298
299 # Wait for prep script to finish and shutdown system
300 wait_for_VM_to_halt
301
Renuka Apte0af143b2012-04-02 15:46:53 -0700302 # Make template from VM
John Garbuttdaadf742012-04-27 18:28:28 +0100303 snuuid=$(xe vm-snapshot vm="$GUEST_NAME" new-name-label="$SNAME_PREPARED")
304 xe snapshot-clone uuid=$snuuid new-name-label="$TNAME"
305else
306 #
307 # Template already installed, create VM from template
308 #
309 vm_uuid=$(xe vm-install template="$TNAME" new-name-label="$GUEST_NAME")
Renuka Apte0af143b2012-04-02 15:46:53 -0700310fi
311
John Garbuttdaadf742012-04-27 18:28:28 +0100312
313#
314# Inject DevStack inside VM disk
315#
Renuka Apte0af143b2012-04-02 15:46:53 -0700316$TOP_DIR/build_xva.sh "$GUEST_NAME"
317
John Garbuttdaadf742012-04-27 18:28:28 +0100318# create a snapshot before the first boot
319# to allow a quick re-run with the same settings
320xe vm-snapshot vm="$GUEST_NAME" new-name-label="$SNAME_FIRST_BOOT"
321
322
323#
324# Run DevStack VM
325#
Renuka Apte0af143b2012-04-02 15:46:53 -0700326xe vm-start vm="$GUEST_NAME"
Anthony Young3eb8f592011-10-26 23:11:52 -0700327
John Garbuttdaadf742012-04-27 18:28:28 +0100328
329#
330# Find IP and optionally wait for stack.sh to complete
331#
332
333function find_ip_by_name() {
334 local guest_name="$1"
335 local interface="$2"
336 local period=10
337 max_tries=10
338 i=0
339 while true
340 do
341 if [ $i -ge $max_tries ]; then
342 echo "Timed out waiting for devstack ip address"
343 exit 11
344 fi
345
346 devstackip=$(xe vm-list --minimal \
347 name-label=$guest_name \
348 params=networks | sed -ne "s,^.*${interface}/ip: \([0-9.]*\).*\$,\1,p")
349 if [ -z "$devstackip" ]
350 then
351 sleep $period
352 ((i++))
353 else
354 echo $devstackip
355 break
356 fi
357 done
358}
359
360function ssh_no_check() {
361 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$@"
362}
363
364# Note the XenServer needs to be on the chosen
365# network, so XenServer can access Glance API
366if [ $HOST_IP_IFACE == "eth2" ]; then
367 DOMU_IP=$MGT_IP
368 if [ $MGT_IP == "dhcp" ]; then
369 DOMU_IP=$(find_ip_by_name $GUEST_NAME 2)
370 fi
371else
372 DOMU_IP=$PUB_IP
373 if [ $PUB_IP == "dhcp" ]; then
374 DOMU_IP=$(find_ip_by_name $GUEST_NAME 3)
375 fi
Renuka Aptec56885a2012-02-29 16:09:26 -0800376fi
377
Anthony Young1de18c62011-11-01 14:19:18 -0500378# If we have copied our ssh credentials, use ssh to monitor while the installation runs
379WAIT_TILL_LAUNCH=${WAIT_TILL_LAUNCH:-1}
John Garbuttdaadf742012-04-27 18:28:28 +0100380COPYENV=${COPYENV:-1}
Anthony Young1de18c62011-11-01 14:19:18 -0500381if [ "$WAIT_TILL_LAUNCH" = "1" ] && [ -e ~/.ssh/id_rsa.pub ] && [ "$COPYENV" = "1" ]; then
Anthony Young1de18c62011-11-01 14:19:18 -0500382 echo "We're done launching the vm, about to start tailing the"
383 echo "stack.sh log. It will take a second or two to start."
384 echo
385 echo "Just CTRL-C at any time to stop tailing."
386
John Garbuttdaadf742012-04-27 18:28:28 +0100387 # wait for log to appear
388 while ! ssh_no_check -q stack@$DOMU_IP "[ -e run.sh.log ]"; do
389 sleep 10
Anthony Young1de18c62011-11-01 14:19:18 -0500390 done
391
John Garbuttdaadf742012-04-27 18:28:28 +0100392 # output the run.sh.log
393 ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no stack@$DOMU_IP 'tail -f run.sh.log' &
Anthony Young1de18c62011-11-01 14:19:18 -0500394 TAIL_PID=$!
395
396 function kill_tail() {
John Garbuttdaadf742012-04-27 18:28:28 +0100397 kill -9 $TAIL_PID
Anthony Young1de18c62011-11-01 14:19:18 -0500398 exit 1
399 }
Anthony Young1de18c62011-11-01 14:19:18 -0500400 # Let Ctrl-c kill tail and exit
401 trap kill_tail SIGINT
402
John Garbuttdaadf742012-04-27 18:28:28 +0100403 # ensure we kill off the tail if we exit the script early
404 # for other reasons
405 add_on_exit "kill -9 $TAIL_PID || true"
406
407 # wait silently until stack.sh has finished
408 set +o xtrace
409 while ! ssh_no_check -q stack@$DOMU_IP "tail run.sh.log | grep -q 'stack.sh completed in'"; do
410 sleep 10
Anthony Young1de18c62011-11-01 14:19:18 -0500411 done
John Garbuttdaadf742012-04-27 18:28:28 +0100412 set -o xtrace
Anthony Young1de18c62011-11-01 14:19:18 -0500413
John Garbuttdaadf742012-04-27 18:28:28 +0100414 # kill the tail process now stack.sh has finished
415 kill -9 $TAIL_PID
Anthony Young1de18c62011-11-01 14:19:18 -0500416
John Garbuttdaadf742012-04-27 18:28:28 +0100417 # check for a failure
418 if ssh_no_check -q stack@$DOMU_IP "grep -q 'stack.sh failed' run.sh.log"; then
Anthony Young1de18c62011-11-01 14:19:18 -0500419 exit 1
420 fi
John Garbuttdaadf742012-04-27 18:28:28 +0100421 echo "################################################################################"
Anthony Young1de18c62011-11-01 14:19:18 -0500422 echo ""
John Garbuttdaadf742012-04-27 18:28:28 +0100423 echo "All Finished!"
424 echo "You can visit the OpenStack Dashboard"
425 echo "at http://$DOMU_IP, and contact other services at the usual ports."
Anthony Young1de18c62011-11-01 14:19:18 -0500426else
427 echo "################################################################################"
428 echo ""
429 echo "All Finished!"
430 echo "Now, you can monitor the progress of the stack.sh installation by "
431 echo "tailing /opt/stack/run.sh.log from within your domU."
432 echo ""
John Garbuttdaadf742012-04-27 18:28:28 +0100433 echo "ssh into your domU now: 'ssh stack@$DOMU_IP' using your password"
Anthony Young1de18c62011-11-01 14:19:18 -0500434 echo "and then do: 'tail -f /opt/stack/run.sh.log'"
435 echo ""
436 echo "When the script completes, you can then visit the OpenStack Dashboard"
John Garbuttdaadf742012-04-27 18:28:28 +0100437 echo "at http://$DOMU_IP, and contact other services at the usual ports."
Anthony Young1de18c62011-11-01 14:19:18 -0500438fi