diff --git a/exercise.sh b/exercise.sh index d9d4c0a..dc8163f 100755 --- a/exercise.sh +++ b/exercise.sh @@ -52,10 +52,17 @@ export NOVA_VERSION=1.1 # FIXME - why does this need to be specified? export NOVA_REGION_NAME=RegionOne +# set log level to DEBUG (helps debug issues) +export NOVACLIENT_DEBUG=1 # Get a token for clients that don't support service catalog # ========================================================== -SERVICE_TOKEN=`curl -s -d "{\"auth\":{\"passwordCredentials\": {\"username\": \"$NOVA_PROJECT_ID\", \"password\": \"$NOVA_API_KEY\"}}}" -H "Content-type: application/json" http://$HOST:5000/v2.0/tokens | python -c "import sys; import json; tok = json.loads(sys.stdin.read()); print tok['access']['token']['id'];"` + +# manually create a token by querying keystone (sending JSON data). Keystone +# returns a token and catalog of endpoints. We use python to parse the token +# and save it. + +TOKEN=`curl -s -d "{\"auth\":{\"passwordCredentials\": {\"username\": \"$NOVA_USERNAME\", \"password\": \"$NOVA_API_KEY\"}}}" -H "Content-type: application/json" http://$HOST:5000/v2.0/tokens | python -c "import sys; import json; tok = json.loads(sys.stdin.read()); print tok['access']['token']['id'];"` # Launching a server # ================== @@ -63,9 +70,6 @@ SERVICE_TOKEN=`curl -s -d "{\"auth\":{\"passwordCredentials\": {\"username\": \ # List servers for tenant: nova list -# List of flavors: -nova flavor-list - # Images # ------ @@ -73,10 +77,46 @@ nova flavor-list nova image-list # But we recommend using glance directly -glance -A $SERVICE_TOKEN index +glance -A $TOKEN index + +# Let's grab the id of the first AMI image to launch +IMAGE=`glance -A $TOKEN index | egrep ami | cut -d" " -f1` + + +# Flavors +# ------- + +# List of flavors: +nova flavor-list + +# and grab the first flavor in the list to launch +FLAVOR=`nova flavor-list | head -n 4 | tail -n 1 | cut -d"|" -f2` + +NAME="firstpost" + +nova boot --flavor $FLAVOR --image $IMAGE $NAME + +# let's give it 10 seconds to launch +sleep 10 + +# check that the status is active +nova show $NAME | grep status | grep -q ACTIVE + +# get the IP of the server +IP=`nova show $NAME | grep "private network" | cut -d"|" -f3` + +# ping it once (timeout of a second) +ping -c1 -w1 $IP || true + +# sometimes the first ping fails (10 seconds isn't enough time for the VM's +# network to respond?), so let's wait 5 seconds and really test ping +sleep 5 + +ping -c1 -w1 $IP + +# shutdown the server +nova delete $NAME + +# FIXME: validate shutdown within 5 seconds +# (nova show $NAME returns 1 or status != ACTIVE)? -# show details of the active servers:: -# -# nova show 1234 -# -nova list | grep ACTIVE | cut -d \| -f2 | xargs -n1 nova show diff --git a/stack.sh b/stack.sh index 0b34790..a7eacbf 100755 --- a/stack.sh +++ b/stack.sh @@ -40,6 +40,9 @@ if [ ! -d $FILES ]; then exit 1 fi +# Keep track of the current devstack directory. +TOP_DIR=$(cd $(dirname "$0") && pwd) + # OpenStack is designed to be run as a regular user (Dashboard will fail to run # as root, since apache refused to startup serve content from root user). If # stack.sh is run as root, it automatically creates a stack user with @@ -86,14 +89,14 @@ fi # This script is customizable through setting environment variables. If you # want to override a setting you can either:: # -# export MYSQL_PASS=anothersecret +# export MYSQL_PASSWORD=anothersecret # ./stack.sh # -# You can also pass options on a single line ``MYSQL_PASS=simple ./stack.sh`` +# You can also pass options on a single line ``MYSQL_PASSWORD=simple ./stack.sh`` # # Additionally, you can put any local variables into a ``localrc`` file, like:: # -# MYSQL_PASS=anothersecret +# MYSQL_PASSWORD=anothersecret # MYSQL_USER=hellaroot # # We try to have sensible defaults, so you should be able to run ``./stack.sh`` @@ -106,7 +109,7 @@ fi # # If ``localrc`` exists, then ``stackrc`` will load those settings. This is # useful for changing a branch or repostiory to test other versions. Also you -# can store your other settings like **MYSQL_PASS** or **ADMIN_PASSWORD** instead +# can store your other settings like **MYSQL_PASSWORD** or **ADMIN_PASSWORD** instead # of letting devstack generate random ones for you. source ./stackrc @@ -139,6 +142,43 @@ if [ ! -n "$HOST_IP" ]; then HOST_IP=`LC_ALL=C /sbin/ifconfig | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'` fi +# Generic helper to configure passwords +function read_password { + set +o xtrace + var=$1; msg=$2 + pw=${!var} + + localrc=$TOP_DIR/localrc + + # If the password is not defined yet, proceed to prompt user for a password. + if [ ! $pw ]; then + # If there is no localrc file, create one + if [ ! -e $localrc ]; then + touch $localrc + fi + + # Presumably if we got this far it can only be that our localrc is missing + # the required password. Prompt user for a password and write to localrc. + echo '' + echo '################################################################################' + echo $msg + echo '################################################################################' + echo "This value will be written to your localrc file so you don't have to enter it again." + echo "It is probably best to avoid spaces and weird characters." + echo "If you leave this blank, a random default value will be used." + echo "Enter a password now:" + read $var + pw=${!var} + if [ ! $pw ]; then + pw=`openssl rand -hex 10` + fi + eval "$var=$pw" + echo "$var=$pw" >> $localrc + fi + set -o xtrace +} + + # Nova Network Configuration # -------------------------- @@ -187,31 +227,32 @@ FLAT_INTERFACE=${FLAT_INTERFACE:-eth0} # By default this script will install and configure MySQL. If you want to # use an existing server, you can pass in the user/password/host parameters. -# You will need to send the same ``MYSQL_PASS`` to every host if you are doing +# You will need to send the same ``MYSQL_PASSWORD`` to every host if you are doing # a multi-node devstack installation. MYSQL_USER=${MYSQL_USER:-root} -MYSQL_PASS=${MYSQL_PASS:-`openssl rand -hex 12`} +read_password MYSQL_PASSWORD "ENTER A PASSWORD TO USE FOR MYSQL." MYSQL_HOST=${MYSQL_HOST:-localhost} # don't specify /db in this string, so we can use it for multiple services -BASE_SQL_CONN=${BASE_SQL_CONN:-mysql://$MYSQL_USER:$MYSQL_PASS@$MYSQL_HOST} +BASE_SQL_CONN=${BASE_SQL_CONN:-mysql://$MYSQL_USER:$MYSQL_PASSWORD@$MYSQL_HOST} # Rabbit connection info RABBIT_HOST=${RABBIT_HOST:-localhost} RABBIT_PASSWORD=${RABBIT_PASSWORD:-`openssl rand -hex 12`} +read_password RABBIT_PASSWORD "ENTER A PASSWORD TO USE FOR RABBIT." # Glance connection info. Note the port must be specified. GLANCE_HOSTPORT=${GLANCE_HOSTPORT:-$HOST_IP:9292} + # Keystone # -------- # Service Token - Openstack components need to have an admin token # to validate user tokens. -SERVICE_TOKEN=${SERVICE_TOKEN:-`openssl rand -hex 12`} +read_password SERVICE_TOKEN "ENTER A SERVICE_TOKEN TO USE FOR THE SERVICE ADMIN TOKEN." # Dash currently truncates usernames and passwords at 20 characters -# so use 10 bytes -ADMIN_PASSWORD=${ADMIN_PASSWORD:-`openssl rand -hex 10`} +read_password ADMIN_PASSWORD "ENTER A PASSWORD TO USE FOR DASH AND KEYSTONE (20 CHARS OR LESS)." LOGFILE=${LOGFILE:-"$PWD/stack.sh.$$.log"} ( @@ -313,8 +354,8 @@ if [[ "$ENABLED_SERVICES" =~ "mysql" ]]; then # Seed configuration with mysql password so that apt-get install doesn't # prompt us for a password upon install. cat <$HOME/.my.cnf [client] user=$MYSQL_USER -password=$MYSQL_PASS +password=$MYSQL_PASSWORD host=$MYSQL_HOST EOF chmod 0600 $HOME/.my.cnf @@ -334,7 +375,7 @@ EOF # Install and start mysql-server sudo apt-get -y -q install mysql-server # Update the DB to give user ‘$MYSQL_USER’@’%’ full control of the all databases: - sudo mysql -uroot -p$MYSQL_PASS -e "GRANT ALL PRIVILEGES ON *.* TO '$MYSQL_USER'@'%' identified by '$MYSQL_PASS';" + sudo mysql -uroot -p$MYSQL_PASSWORD -e "GRANT ALL PRIVILEGES ON *.* TO '$MYSQL_USER'@'%' identified by '$MYSQL_PASSWORD';" # Edit /etc/mysql/my.cnf to change ‘bind-address’ from localhost (127.0.0.1) to any (0.0.0.0) and restart the mysql service: sudo sed -i 's/127.0.0.1/0.0.0.0/g' /etc/mysql/my.cnf @@ -385,8 +426,8 @@ if [[ "$ENABLED_SERVICES" =~ "g-reg" ]]; then mkdir -p $GLANCE_IMAGE_DIR # (re)create glance database - mysql -u$MYSQL_USER -p$MYSQL_PASS -e 'DROP DATABASE IF EXISTS glance;' - mysql -u$MYSQL_USER -p$MYSQL_PASS -e 'CREATE DATABASE glance;' + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS glance;' + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE glance;' # Copy over our glance-registry.conf GLANCE_CONF=$GLANCE_DIR/etc/glance-registry.conf cp $FILES/glance-registry.conf $GLANCE_CONF @@ -515,8 +556,8 @@ fi if [[ "$ENABLED_SERVICES" =~ "mysql" ]]; then # (re)create nova database - mysql -u$MYSQL_USER -p$MYSQL_PASS -e 'DROP DATABASE IF EXISTS nova;' - mysql -u$MYSQL_USER -p$MYSQL_PASS -e 'CREATE DATABASE nova;' + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS nova;' + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE nova;' # (re)create nova database $NOVA_DIR/bin/nova-manage db sync @@ -534,8 +575,8 @@ fi if [[ "$ENABLED_SERVICES" =~ "key" ]]; then # (re)create keystone database - mysql -u$MYSQL_USER -p$MYSQL_PASS -e 'DROP DATABASE IF EXISTS keystone;' - mysql -u$MYSQL_USER -p$MYSQL_PASS -e 'CREATE DATABASE keystone;' + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'DROP DATABASE IF EXISTS keystone;' + mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e 'CREATE DATABASE keystone;' # FIXME (anthony) keystone should use keystone.conf.example KEYSTONE_CONF=$KEYSTONE_DIR/etc/keystone.conf @@ -619,55 +660,41 @@ screen_it dash "cd $DASH_DIR && sudo /etc/init.d/apache2 restart; sudo tail -f / # Install Images # ============== -# Upload a couple images to glance. **TTY** is a simple small image that use the -# lets you login to it with username/password of user/password. TTY is useful -# for basic functionality. We all include an Ubuntu cloud build of **Natty**. -# Natty uses cloud-init, supporting login via keypair and sending scripts as -# userdata. +# Upload an image to glance. # -# Read more about cloud-init at https://help.ubuntu.com/community/CloudInit +# The default image is a small ***TTY*** testing image, which lets you login +# the username/password of root/password. +# +# TTY also uses cloud-init, supporting login via keypair and sending scripts as +# userdata. See https://help.ubuntu.com/community/CloudInit for more on cloud-init +# +# Override IMAGE_URLS if you would to launch a different image(s). +# Specify IMAGE_URLS as a comma-separated list of uec urls. Some other options include: +# natty: http://uec-images.ubuntu.com/natty/current/natty-server-cloudimg-amd64.tar.gz +# oneiric: http://uec-images.ubuntu.com/oneiric/current/oneiric-server-cloudimg-amd64.tar.gz if [[ "$ENABLED_SERVICES" =~ "g-reg" ]]; then - # create a directory for the downloadedthe images tarballs. + # Create a directory for the downloaded image tarballs. mkdir -p $FILES/images - # Debug Image (TTY) - # ----------------- + for image_url in ${IMAGE_URLS//,/ }; do + # Downloads the image (uec ami+aki style), then extracts it. + IMAGE_FNAME=`echo "$image_url" | python -c "import sys; print sys.stdin.read().split('/')[-1]"` + IMAGE_NAME=`echo "$IMAGE_FNAME" | python -c "import sys; print sys.stdin.read().split('.tar.gz')[0].split('.tgz')[0]"` + if [ ! -f $FILES/$IMAGE_FNAME ]; then + wget -c $image_url -O $FILES/$IMAGE_FNAME + fi - # Downloads the image (ami/aki/ari style), then extracts it. Upon extraction - # we upload to glance with the glance cli tool. TTY is a stripped down - # version of ubuntu. - if [ ! -f $FILES/tty.tgz ]; then - wget -c http://images.ansolabs.com/tty.tgz -O $FILES/tty.tgz - fi - - # extract ami-tty/image, aki-tty/image & ari-tty/image - tar -zxf $FILES/tty.tgz -C $FILES/images - - # Use glance client to add the kernel, ramdisk and finally the root - # filesystem. We parse the results of the uploads to get glance IDs of the - # ramdisk and kernel and use them for the root filesystem. - RVAL=`glance add -A $SERVICE_TOKEN name="tty-kernel" is_public=true container_format=aki disk_format=aki < $FILES/images/aki-tty/image` - KERNEL_ID=`echo $RVAL | cut -d":" -f2 | tr -d " "` - RVAL=`glance add -A $SERVICE_TOKEN name="tty-ramdisk" is_public=true container_format=ari disk_format=ari < $FILES/images/ari-tty/image` - RAMDISK_ID=`echo $RVAL | cut -d":" -f2 | tr -d " "` - glance add -A $SERVICE_TOKEN name="tty" is_public=true container_format=ami disk_format=ami kernel_id=$KERNEL_ID ramdisk_id=$RAMDISK_ID < $FILES/images/ami-tty/image - - # Ubuntu 11.04 aka Natty - # ---------------------- - - # Downloaded from ubuntu enterprise cloud images. This - # image doesn't use the ramdisk functionality - if [ ! -f $FILES/natty.tgz ]; then - wget -c http://uec-images.ubuntu.com/natty/current/natty-server-cloudimg-amd64.tar.gz -O $FILES/natty.tgz - fi - - tar -zxf $FILES/natty.tgz -C $FILES/images - - RVAL=`glance add -A $SERVICE_TOKEN name="uec-natty-kernel" is_public=true container_format=aki disk_format=aki < $FILES/images/natty-server-cloudimg-amd64-vmlinuz-virtual` - KERNEL_ID=`echo $RVAL | cut -d":" -f2 | tr -d " "` - glance add -A $SERVICE_TOKEN name="uec-natty" is_public=true container_format=ami disk_format=ami kernel_id=$KERNEL_ID < $FILES/images/natty-server-cloudimg-amd64.img + # Extract ami and aki files + tar -zxf $FILES/$IMAGE_FNAME -C $FILES/images + # Use glance client to add the kernel the root filesystem. + # We parse the results of the first upload to get the glance ID of the + # kernel for use when uploading the root filesystem. + RVAL=`glance add -A $SERVICE_TOKEN name="$IMAGE_NAME-kernel" is_public=true container_format=aki disk_format=aki < $FILES/images/$IMAGE_NAME-vmlinuz*` + KERNEL_ID=`echo $RVAL | cut -d":" -f2 | tr -d " "` + glance add -A $SERVICE_TOKEN name="$IMAGE_NAME" is_public=true container_format=ami disk_format=ami kernel_id=$KERNEL_ID < $FILES/images/$IMAGE_NAME.img + done fi # Fin diff --git a/stackrc b/stackrc index 15d73ce..e1b65c3 100644 --- a/stackrc +++ b/stackrc @@ -27,6 +27,9 @@ NOVACLIENT_BRANCH=master OPENSTACKX_REPO=https://github.com/cloudbuilders/openstackx.git OPENSTACKX_BRANCH=diablo +# Specify a comma-separated list of uec images to download and install into glance. +IMAGE_URLS=http://smoser.brickies.net/ubuntu/ttylinux-uec/ttylinux-uec-amd64-11.2_2.6.35-15_1.tar.gz + # allow local overrides of env variables if [ -f ./localrc ]; then source ./localrc diff --git a/build_lxc.sh b/tools/build_lxc.sh similarity index 75% rename from build_lxc.sh rename to tools/build_lxc.sh index 643da7e..42bd328 100755 --- a/build_lxc.sh +++ b/tools/build_lxc.sh @@ -6,9 +6,17 @@ if [ "$EUID" -ne "0" ]; then exit 1 fi -# Warn users who aren't on natty -if ! grep -q natty /etc/lsb-release; then - echo "WARNING: this script has only been tested on natty" +# Keep track of ubuntu version +UBUNTU_VERSION=`cat /etc/lsb-release | grep CODENAME | sed 's/.*=//g'` + +# Move to top devstack dir +cd .. + +# Abort if localrc is not set +if [ ! -e ./localrc ]; then + echo "You must have a localrc with ALL necessary passwords defined before proceeding." + echo "See stack.sh for required passwords." + exit 1 fi # Source params @@ -27,6 +35,7 @@ CONTAINER_GATEWAY=${CONTAINER_GATEWAY:-192.168.1.1} NAMESERVER=${NAMESERVER:-$CONTAINER_GATEWAY} COPYENV=${COPYENV:-1} DEST=${DEST:-/opt/stack} +WAIT_TILL_LAUNCH=${WAIT_TILL_LAUNCH:-1} # Param string to pass to stack.sh. Like "EC2_DMZ_HOST=192.168.1.1 MYSQL_USER=nova" STACKSH_PARAMS=${STACKSH_PARAMS:-} @@ -82,8 +91,21 @@ function git_clone { fi } +# Helper to create the container +function create_lxc { + if [ "natty" = "$UBUNTU_VERSION" ]; then + lxc-create -n $CONTAINER -t natty -f $LXC_CONF + else + lxc-create -n $CONTAINER -t ubuntu -f $LXC_CONF + fi +} + # Location of the base image directory -CACHEDIR=/var/cache/lxc/natty/rootfs-amd64 +if [ "natty" = "$UBUNTU_VERSION" ]; then + CACHEDIR=/var/cache/lxc/natty/rootfs-amd64 +else + CACHEDIR=/var/cache/lxc/oneiric/rootfs-amd64 +fi # Provide option to do totally clean install if [ "$CLEAR_LXC_CACHE" = "1" ]; then @@ -96,7 +118,7 @@ if [ ! -f $CACHEDIR/bootstrapped ]; then # lazy and doesn't do anything if a container already exists) lxc-destroy -n $CONTAINER # trigger the initial debootstrap - lxc-create -n $CONTAINER -t natty -f $LXC_CONF + create_lxc chroot $CACHEDIR apt-get update chroot $CACHEDIR apt-get install -y --force-yes `cat files/apts/* | cut -d\# -f1 | egrep -v "(rabbitmq|libvirt-bin|mysql-server)"` chroot $CACHEDIR pip install `cat files/pips/*` @@ -133,7 +155,7 @@ if [ "$TERMINATE" = "1" ]; then fi # Create the container -lxc-create -n $CONTAINER -t natty -f $LXC_CONF +create_lxc # Specify where our container rootfs lives ROOTFS=/var/lib/lxc/$CONTAINER/rootfs/ @@ -197,6 +219,10 @@ cat > $RUN_SH < /$DEST/run.sh.log +cd $DEST/devstack && $STACKSH_PARAMS FORCE=yes ./stack.sh > /$DEST/run.sh.log echo >> /$DEST/run.sh.log echo >> /$DEST/run.sh.log echo "All done! Time to start clicking." >> /$DEST/run.sh.log @@ -218,11 +244,13 @@ EOF chmod 755 $RUN_SH # Make runner launch on boot -RC_LOCAL=$ROOTFS/etc/rc.local +RC_LOCAL=$ROOTFS/etc/init.d/local cat > $RC_LOCAL <