* Launches a cirros builder instance
* Mounts a disk to the builder instance
* Creates a bootable volume from builder
* Launches the volume-backed instance
* Update glance syntax
* Don't require instance-to-web communication (that only works with
fully configured floating ips)
* Add footer/header
Change-Id: Ia6dcf399ee49154aaf4e597b060164c2f41cf3d2
| 1 | 1 |
new file mode 100755 |
| ... | ... |
@@ -0,0 +1,253 @@ |
| 0 |
+#!/usr/bin/env bash |
|
| 1 |
+ |
|
| 2 |
+# **boot_from_volume.sh** |
|
| 3 |
+ |
|
| 4 |
+# This script demonstrates how to boot from a volume. It does the following: |
|
| 5 |
+# * Create a 'builder' instance |
|
| 6 |
+# * Attach a volume to the instance |
|
| 7 |
+# * Format and install an os onto the volume |
|
| 8 |
+# * Detach volume from builder, and then boot volume-backed instance |
|
| 9 |
+ |
|
| 10 |
+echo "**************************************************" |
|
| 11 |
+echo "Begin DevStack Exercise: $0" |
|
| 12 |
+echo "**************************************************" |
|
| 13 |
+ |
|
| 14 |
+# This script exits on an error so that errors don't compound and you see |
|
| 15 |
+# only the first error that occured. |
|
| 16 |
+set -o errexit |
|
| 17 |
+ |
|
| 18 |
+# Print the commands being run so that we can see the command that triggers |
|
| 19 |
+# an error. It is also useful for following allowing as the install occurs. |
|
| 20 |
+set -o xtrace |
|
| 21 |
+ |
|
| 22 |
+ |
|
| 23 |
+# Settings |
|
| 24 |
+# ======== |
|
| 25 |
+ |
|
| 26 |
+# Keep track of the current directory |
|
| 27 |
+EXERCISE_DIR=$(cd $(dirname "$0") && pwd) |
|
| 28 |
+TOP_DIR=$(cd $EXERCISE_DIR/..; pwd) |
|
| 29 |
+ |
|
| 30 |
+# Import common functions |
|
| 31 |
+source $TOP_DIR/functions |
|
| 32 |
+ |
|
| 33 |
+# Import configuration |
|
| 34 |
+source $TOP_DIR/openrc |
|
| 35 |
+ |
|
| 36 |
+# Import exercise configuration |
|
| 37 |
+source $TOP_DIR/exerciserc |
|
| 38 |
+ |
|
| 39 |
+# Boot this image, use first AMI image if unset |
|
| 40 |
+DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-ami}
|
|
| 41 |
+ |
|
| 42 |
+# Instance type |
|
| 43 |
+DEFAULT_INSTANCE_TYPE=${DEFAULT_INSTANCE_TYPE:-m1.tiny}
|
|
| 44 |
+ |
|
| 45 |
+# Default floating IP pool name |
|
| 46 |
+DEFAULT_FLOATING_POOL=${DEFAULT_FLOATING_POOL:-nova}
|
|
| 47 |
+ |
|
| 48 |
+# Grab the id of the image to launch |
|
| 49 |
+IMAGE=`glance -f index | egrep $DEFAULT_IMAGE_NAME | head -1 | cut -d" " -f1` |
|
| 50 |
+ |
|
| 51 |
+die_if_not_set IMAGE "Failure getting image" |
|
| 52 |
+ |
|
| 53 |
+# Instance and volume names |
|
| 54 |
+INSTANCE_NAME=${INSTANCE_NAME:-test_instance}
|
|
| 55 |
+VOL_INSTANCE_NAME=${VOL_INSTANCE_NAME:-test_vol_instance}
|
|
| 56 |
+VOL_NAME=${VOL_NAME:-test_volume}
|
|
| 57 |
+ |
|
| 58 |
+# Clean-up from previous runs |
|
| 59 |
+nova delete $VOL_INSTANCE_NAME || true |
|
| 60 |
+nova delete $INSTANCE_NAME || true |
|
| 61 |
+ |
|
| 62 |
+# Wait till server is gone |
|
| 63 |
+if ! timeout $ACTIVE_TIMEOUT sh -c "while nova show $INSTANCE_NAME; do sleep 1; done"; then |
|
| 64 |
+ echo "server didn't terminate!" |
|
| 65 |
+ exit 1 |
|
| 66 |
+fi |
|
| 67 |
+ |
|
| 68 |
+# Configure Security Groups |
|
| 69 |
+SECGROUP=${SECGROUP:-test_secgroup}
|
|
| 70 |
+nova secgroup-delete $SECGROUP || true |
|
| 71 |
+nova secgroup-create $SECGROUP "$SECGROUP description" |
|
| 72 |
+nova secgroup-add-rule $SECGROUP icmp -1 -1 0.0.0.0/0 |
|
| 73 |
+nova secgroup-add-rule $SECGROUP tcp 22 22 0.0.0.0/0 |
|
| 74 |
+ |
|
| 75 |
+# Determinine instance type |
|
| 76 |
+INSTANCE_TYPE=`nova flavor-list | grep $DEFAULT_INSTANCE_TYPE | cut -d"|" -f2` |
|
| 77 |
+if [[ -z "$INSTANCE_TYPE" ]]; then |
|
| 78 |
+ # grab the first flavor in the list to launch if default doesn't exist |
|
| 79 |
+ INSTANCE_TYPE=`nova flavor-list | head -n 4 | tail -n 1 | cut -d"|" -f2` |
|
| 80 |
+fi |
|
| 81 |
+ |
|
| 82 |
+# Setup Keypair |
|
| 83 |
+KEY_NAME=test_key |
|
| 84 |
+KEY_FILE=key.pem |
|
| 85 |
+nova keypair-delete $KEY_NAME || true |
|
| 86 |
+nova keypair-add $KEY_NAME > $KEY_FILE |
|
| 87 |
+chmod 600 $KEY_FILE |
|
| 88 |
+ |
|
| 89 |
+# Boot our instance |
|
| 90 |
+VM_UUID=`nova boot --flavor $INSTANCE_TYPE --image $IMAGE --security_groups=$SECGROUP --key_name $KEY_NAME $INSTANCE_NAME | grep ' id ' | cut -d"|" -f3 | sed 's/ //g'` |
|
| 91 |
+ |
|
| 92 |
+# check that the status is active within ACTIVE_TIMEOUT seconds |
|
| 93 |
+if ! timeout $ACTIVE_TIMEOUT sh -c "while ! nova show $VM_UUID | grep status | grep -q ACTIVE; do sleep 1; done"; then |
|
| 94 |
+ echo "server didn't become active!" |
|
| 95 |
+ exit 1 |
|
| 96 |
+fi |
|
| 97 |
+ |
|
| 98 |
+# Delete the old volume |
|
| 99 |
+nova volume-delete $VOL_NAME || true |
|
| 100 |
+ |
|
| 101 |
+# Free every floating ips - setting FREE_ALL_FLOATING_IPS=True in localrc will make life easier for testers |
|
| 102 |
+if [ "$FREE_ALL_FLOATING_IPS" = "True" ]; then |
|
| 103 |
+ nova floating-ip-list | grep nova | cut -d "|" -f2 | tr -d " " | xargs -n1 nova floating-ip-delete || true |
|
| 104 |
+fi |
|
| 105 |
+ |
|
| 106 |
+# Allocate floating ip |
|
| 107 |
+FLOATING_IP=`nova floating-ip-create | grep $DEFAULT_FLOATING_POOL | cut -d '|' -f2 | tr -d ' '` |
|
| 108 |
+ |
|
| 109 |
+# Make sure the ip gets allocated |
|
| 110 |
+if ! timeout $ASSOCIATE_TIMEOUT sh -c "while ! nova floating-ip-list | grep -q $FLOATING_IP; do sleep 1; done"; then |
|
| 111 |
+ echo "Floating IP not allocated" |
|
| 112 |
+ exit 1 |
|
| 113 |
+fi |
|
| 114 |
+ |
|
| 115 |
+# Add floating ip to our server |
|
| 116 |
+nova add-floating-ip $VM_UUID $FLOATING_IP |
|
| 117 |
+ |
|
| 118 |
+# Test we can ping our floating ip within ASSOCIATE_TIMEOUT seconds |
|
| 119 |
+if ! timeout $ASSOCIATE_TIMEOUT sh -c "while ! ping -c1 -w1 $FLOATING_IP; do sleep 1; done"; then |
|
| 120 |
+ echo "Couldn't ping server with floating ip" |
|
| 121 |
+ exit 1 |
|
| 122 |
+fi |
|
| 123 |
+ |
|
| 124 |
+# Create our volume |
|
| 125 |
+nova volume-create --display_name=$VOL_NAME 1 |
|
| 126 |
+ |
|
| 127 |
+# Wait for volume to activate |
|
| 128 |
+if ! timeout $ACTIVE_TIMEOUT sh -c "while ! nova volume-list | grep $VOL_NAME | grep available; do sleep 1; done"; then |
|
| 129 |
+ echo "Volume $VOL_NAME not created" |
|
| 130 |
+ exit 1 |
|
| 131 |
+fi |
|
| 132 |
+ |
|
| 133 |
+# FIXME (anthony) - python-novaclient should accept a volume_name for the attachment param? |
|
| 134 |
+DEVICE=/dev/vdb |
|
| 135 |
+VOLUME_ID=`nova volume-list | grep $VOL_NAME | cut -d '|' -f 2 | tr -d ' '` |
|
| 136 |
+nova volume-attach $INSTANCE_NAME $VOLUME_ID $DEVICE |
|
| 137 |
+ |
|
| 138 |
+# Wait till volume is attached |
|
| 139 |
+if ! timeout $ACTIVE_TIMEOUT sh -c "while ! nova volume-list | grep $VOL_NAME | grep in-use; do sleep 1; done"; then |
|
| 140 |
+ echo "Volume $VOL_NAME not created" |
|
| 141 |
+ exit 1 |
|
| 142 |
+fi |
|
| 143 |
+ |
|
| 144 |
+# The following script builds our bootable volume. |
|
| 145 |
+# To do this, ssh to the builder instance, mount volume, and build a volume-backed image. |
|
| 146 |
+STAGING_DIR=/tmp/stage |
|
| 147 |
+CIRROS_DIR=/tmp/cirros |
|
| 148 |
+ssh -o StrictHostKeyChecking=no -i $KEY_FILE cirros@$FLOATING_IP << EOF |
|
| 149 |
+set -o errexit |
|
| 150 |
+set -o xtrace |
|
| 151 |
+sudo mkdir -p $STAGING_DIR |
|
| 152 |
+sudo mkfs.ext3 -b 1024 $DEVICE 1048576 |
|
| 153 |
+sudo mount $DEVICE $STAGING_DIR |
|
| 154 |
+# The following lines create a writable empty file so that we can scp |
|
| 155 |
+# the actual file |
|
| 156 |
+sudo touch $STAGING_DIR/cirros-0.3.0-x86_64-rootfs.img.gz |
|
| 157 |
+sudo chown cirros $STAGING_DIR/cirros-0.3.0-x86_64-rootfs.img.gz |
|
| 158 |
+EOF |
|
| 159 |
+ |
|
| 160 |
+# Download cirros |
|
| 161 |
+if [ ! -e cirros-0.3.0-x86_64-rootfs.img.gz ]; then |
|
| 162 |
+ wget http://images.ansolabs.com/cirros-0.3.0-x86_64-rootfs.img.gz |
|
| 163 |
+fi |
|
| 164 |
+ |
|
| 165 |
+# Copy cirros onto the volume |
|
| 166 |
+scp -o StrictHostKeyChecking=no -i $KEY_FILE cirros-0.3.0-x86_64-rootfs.img.gz cirros@$FLOATING_IP:$STAGING_DIR |
|
| 167 |
+ |
|
| 168 |
+# Unpack cirros into volume |
|
| 169 |
+ssh -o StrictHostKeyChecking=no -i $KEY_FILE cirros@$FLOATING_IP << EOF |
|
| 170 |
+set -o errexit |
|
| 171 |
+set -o xtrace |
|
| 172 |
+cd $STAGING_DIR |
|
| 173 |
+sudo mkdir -p $CIRROS_DIR |
|
| 174 |
+sudo gunzip cirros-0.3.0-x86_64-rootfs.img.gz |
|
| 175 |
+sudo mount cirros-0.3.0-x86_64-rootfs.img $CIRROS_DIR |
|
| 176 |
+ |
|
| 177 |
+# Copy cirros into our volume |
|
| 178 |
+sudo cp -pr $CIRROS_DIR/* $STAGING_DIR/ |
|
| 179 |
+ |
|
| 180 |
+cd |
|
| 181 |
+sync |
|
| 182 |
+sudo umount $CIRROS_DIR |
|
| 183 |
+# The following typically fails. Don't know why. |
|
| 184 |
+sudo umount $STAGING_DIR || true |
|
| 185 |
+EOF |
|
| 186 |
+ |
|
| 187 |
+# Detach the volume from the builder instance |
|
| 188 |
+nova volume-detach $INSTANCE_NAME $VOLUME_ID |
|
| 189 |
+ |
|
| 190 |
+# Boot instance from volume! This is done with the --block_device_mapping param. |
|
| 191 |
+# The format of mapping is: |
|
| 192 |
+# <dev_name>=<id>:<type>:<size(GB)>:<delete_on_terminate> |
|
| 193 |
+# Leaving the middle two fields blank appears to do-the-right-thing |
|
| 194 |
+VOL_VM_UUID=`nova boot --flavor $INSTANCE_TYPE --image $IMAGE --block_device_mapping vda=$VOLUME_ID:::0 --security_groups=$SECGROUP --key_name $KEY_NAME $VOL_INSTANCE_NAME | grep ' id ' | cut -d"|" -f3 | sed 's/ //g'` |
|
| 195 |
+ |
|
| 196 |
+# Check that the status is active within ACTIVE_TIMEOUT seconds |
|
| 197 |
+if ! timeout $ACTIVE_TIMEOUT sh -c "while ! nova show $VOL_VM_UUID | grep status | grep -q ACTIVE; do sleep 1; done"; then |
|
| 198 |
+ echo "server didn't become active!" |
|
| 199 |
+ exit 1 |
|
| 200 |
+fi |
|
| 201 |
+ |
|
| 202 |
+# Add floating ip to our server |
|
| 203 |
+nova remove-floating-ip $VM_UUID $FLOATING_IP |
|
| 204 |
+ |
|
| 205 |
+# Gratuitous sleep, probably hiding a race condition :/ |
|
| 206 |
+sleep 1 |
|
| 207 |
+ |
|
| 208 |
+# Add floating ip to our server |
|
| 209 |
+nova add-floating-ip $VOL_VM_UUID $FLOATING_IP |
|
| 210 |
+ |
|
| 211 |
+# Test we can ping our floating ip within ASSOCIATE_TIMEOUT seconds |
|
| 212 |
+if ! timeout $ASSOCIATE_TIMEOUT sh -c "while ! ping -c1 -w1 $FLOATING_IP; do sleep 1; done"; then |
|
| 213 |
+ echo "Couldn't ping volume-backed server with floating ip" |
|
| 214 |
+ exit 1 |
|
| 215 |
+fi |
|
| 216 |
+ |
|
| 217 |
+# Make sure our volume-backed instance launched |
|
| 218 |
+ssh -o StrictHostKeyChecking=no -i $KEY_FILE cirros@$FLOATING_IP << EOF |
|
| 219 |
+echo "success!" |
|
| 220 |
+EOF |
|
| 221 |
+ |
|
| 222 |
+# Delete volume backed instance |
|
| 223 |
+nova delete $VOL_INSTANCE_NAME |
|
| 224 |
+ |
|
| 225 |
+# Wait till our volume is no longer in-use |
|
| 226 |
+if ! timeout $ACTIVE_TIMEOUT sh -c "while ! nova volume-list | grep $VOL_NAME | grep available; do sleep 1; done"; then |
|
| 227 |
+ echo "Volume $VOL_NAME not created" |
|
| 228 |
+ exit 1 |
|
| 229 |
+fi |
|
| 230 |
+ |
|
| 231 |
+# Delete the volume |
|
| 232 |
+nova volume-delete $VOL_NAME |
|
| 233 |
+ |
|
| 234 |
+# Delete instance |
|
| 235 |
+nova delete $INSTANCE_NAME |
|
| 236 |
+ |
|
| 237 |
+# Wait for termination |
|
| 238 |
+if ! timeout $ACTIVE_TIMEOUT sh -c "while nova show $INSTANCE_NAME; do sleep 1; done"; then |
|
| 239 |
+ echo "server didn't terminate!" |
|
| 240 |
+ exit 1 |
|
| 241 |
+fi |
|
| 242 |
+ |
|
| 243 |
+# De-allocate the floating ip |
|
| 244 |
+nova floating-ip-delete $FLOATING_IP |
|
| 245 |
+ |
|
| 246 |
+# Delete secgroup |
|
| 247 |
+nova secgroup-delete $SECGROUP |
|
| 248 |
+ |
|
| 249 |
+set +o xtrace |
|
| 250 |
+echo "**************************************************" |
|
| 251 |
+echo "End DevStack Exercise: $0" |
|
| 252 |
+echo "**************************************************" |