diff --git a/files/apts/nova b/files/apts/nova index 594f2da..8ae74a2 100644 --- a/files/apts/nova +++ b/files/apts/nova @@ -1,5 +1,6 @@ dnsmasq-base kpartx +parted mysql-server python-mysqldb kvm diff --git a/stack.sh b/stack.sh index f0bc377..80605de 100755 --- a/stack.sh +++ b/stack.sh @@ -81,6 +81,15 @@ DEST=${DEST:-/opt/stack} # Configure services to syslog instead of writing to individual log files SYSLOG=${SYSLOG:-False} +# apt-get wrapper to just get arguments set correctly +function apt_get() { + local sudo="sudo" + [ "$(id -u)" = "0" ] && sudo="env" + $sudo DEBIAN_FRONTEND=noninteractive apt-get \ + --option "Dpkg::Options::=--force-confold" --assume-yes "$@" +} + + # 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 @@ -125,9 +134,12 @@ else # Natty uec images sudoers does not have a '#includedir'. add one. sudo grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || echo "#includedir /etc/sudoers.d" | sudo tee -a /etc/sudoers - sudo cp $FILES/sudo/nova /etc/sudoers.d/stack_sh_nova - sudo sed -e "s,%USER%,$USER,g" -i /etc/sudoers.d/stack_sh_nova - sudo chmod 0440 /etc/sudoers.d/stack_sh_nova + TEMPFILE=`mktemp` + cat $FILES/sudo/nova > $TEMPFILE + sed -e "s,%USER%,$USER,g" -i $TEMPFILE + chmod 0440 $TEMPFILE + sudo chown root:root $TEMPFILE + sudo mv $TEMPFILE /etc/sudoers.d/stack_sh_nova fi # Set the destination directories for openstack projects @@ -142,9 +154,10 @@ NOVNC_DIR=$DEST/noVNC # Specify which services to launch. These generally correspond to screen tabs ENABLED_SERVICES=${ENABLED_SERVICES:-g-api,g-reg,key,n-api,n-cpu,n-net,n-sch,n-vnc,dash,mysql,rabbit} -# Nova hypervisor configuration. We default to **kvm** but will drop back to -# **qemu** if we are unable to load the kvm module. Stack.sh can also install -# an **LXC** based system. +# Nova hypervisor configuration. We default to libvirt whth **kvm** but will +# drop back to **qemu** if we are unable to load the kvm module. Stack.sh can +# also install an **LXC** based system. +VIRT_DRIVER=${VIRT_DRIVER:-libvirt} LIBVIRT_TYPE=${LIBVIRT_TYPE:-kvm} # nova supports pluggable schedulers. ``SimpleScheduler`` should work in most @@ -156,14 +169,6 @@ if [ ! -n "$HOST_IP" ]; then HOST_IP=`LC_ALL=C /sbin/ifconfig | grep -m 1 'inet addr:'| cut -d: -f2 | awk '{print $1}'` fi -# apt-get wrapper to just get arguments set correctly -function apt_get() { - local sudo="sudo" - [ "$(id -u)" = "0" ] && sudo="" - $sudo DEBIAN_FRONTEND=noninteractive apt-get \ - --option "Dpkg::Options::=--force-confold" --assume-yes "$@" -} - # Generic helper to configure passwords function read_password { set +o xtrace @@ -210,7 +215,7 @@ function read_password { PUBLIC_INTERFACE=${PUBLIC_INTERFACE:-eth0} FIXED_RANGE=${FIXED_RANGE:-10.0.0.0/24} FIXED_NETWORK_SIZE=${FIXED_NETWORK_SIZE:-256} -FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.1/28} +FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.224/28} NET_MAN=${NET_MAN:-FlatDHCPManager} EC2_DMZ_HOST=${EC2_DMZ_HOST:-$HOST_IP} FLAT_NETWORK_BRIDGE=${FLAT_NETWORK_BRIDGE:-br100} @@ -457,6 +462,7 @@ if [[ "$ENABLED_SERVICES" =~ "dash" ]]; then sudo cp $FILES/000-default.template /etc/apache2/sites-enabled/000-default sudo sed -e "s,%USER%,$USER,g" -i /etc/apache2/sites-enabled/000-default sudo sed -e "s,%DASH_DIR%,$DASH_DIR,g" -i /etc/apache2/sites-enabled/000-default + sudo service apache2 restart fi @@ -624,13 +630,8 @@ add_nova_flag "--ec2_dmz_host=$EC2_DMZ_HOST" add_nova_flag "--rabbit_host=$RABBIT_HOST" add_nova_flag "--rabbit_password=$RABBIT_PASSWORD" add_nova_flag "--glance_api_servers=$GLANCE_HOSTPORT" -add_nova_flag "--flat_network_bridge=$FLAT_NETWORK_BRIDGE" if [ -n "$INSTANCES_PATH" ]; then add_nova_flag "--instances_path=$INSTANCES_PATH" -fi -if [ -n "$FLAT_INTERFACE" ]; then - add_nova_flag "--flat_interface=$FLAT_INTERFACE" -fi if [ -n "$MULTI_HOST" ]; then add_nova_flag "--multi_host=$MULTI_HOST" add_nova_flag "--send_arp_for_ha=1" @@ -639,6 +640,26 @@ if [ "$SYSLOG" != "False" ]; then add_nova_flag "--use_syslog=1" fi +# XenServer +# --------- + +if [ "$VIRT_DRIVER" = 'xenserver' ]; then + read_password XENAPI_PASSWORD "ENTER A PASSWORD TO USE FOR XEN." + add_nova_flag "--connection_type=xenapi" + add_nova_flag "--xenapi_connection_url=http://169.254.0.1" + add_nova_flag "--xenapi_connection_username=root" + add_nova_flag "--xenapi_connection_password=$XENAPI_PASSWORD" + add_nova_flag "--flat_injected=False" + add_nova_flag "--flat_interface=eth1" + add_nova_flag "--flat_network_bridge=xenbr1" + add_nova_flag "--public_interface=eth3" +else + add_nova_flag "--flat_network_bridge=$FLAT_NETWORK_BRIDGE" + if [ -n "$FLAT_INTERFACE" ]; then + add_nova_flag "--flat_interface=$FLAT_INTERFACE" + fi +fi + # Nova Database # ~~~~~~~~~~~~~ @@ -750,7 +771,7 @@ screen_it n-vol "cd $NOVA_DIR && $NOVA_DIR/bin/nova-volume" screen_it n-net "cd $NOVA_DIR && $NOVA_DIR/bin/nova-network" screen_it n-sch "cd $NOVA_DIR && $NOVA_DIR/bin/nova-scheduler" screen_it n-vnc "cd $NOVNC_DIR && ./utils/nova-wsproxy.py 6080 --web . --flagfile=../nova/bin/nova.conf" -screen_it dash "cd $DASH_DIR && sudo /etc/init.d/apache2 restart; sudo tail -f /var/log/apache2/error.log" +screen_it dash "cd $DASH_DIR && sudo tail -f /var/log/apache2/error.log" # Install Images # ============== @@ -772,6 +793,20 @@ if [[ "$ENABLED_SERVICES" =~ "g-reg" ]]; then # Create a directory for the downloaded image tarballs. mkdir -p $FILES/images + # Option to upload legacy ami-tty, which works with xenserver + if [ $UPLOAD_LEGACY_TTY ]; then + if [ ! -f $FILES/tty.tgz ]; then + wget -c http://images.ansolabs.com/tty.tgz -O $FILES/tty.tgz + fi + + tar -zxf $FILES/tty.tgz -C $FILES/images + 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 + fi + for image_url in ${IMAGE_URLS//,/ }; do # Downloads the image (uec ami+aki style), then extracts it. IMAGE_FNAME=`basename "$image_url"` diff --git a/tools/build_kvm.sh b/tools/build_kvm.sh index 36457d5..e6cb3e3 100755 --- a/tools/build_kvm.sh +++ b/tools/build_kvm.sh @@ -341,7 +341,14 @@ chroot $ROOTFS chown -R stack $DEST # Change boot params so that we get a console log sudo sed -e "s/quiet splash/splash console=ttyS0 console=ttyS1,19200n8/g" -i $ROOTFS/boot/grub/menu.lst sudo sed -e "s/^hiddenmenu//g" -i $ROOTFS/boot/grub/menu.lst -#chroot $ROOTFS grub-install /dev/vda + +# Set the hostname +echo $GUEST_NAME > $ROOTFS/etc/hostname + +# We need the hostname to resolve for rabbit to launch +if ! grep -q $GUEST_NAME $ROOTFS/etc/hosts; then + echo "$GUEST_IP $GUEST_NAME" >> $ROOTFS/etc/hosts +fi # Unmount umount $ROOTFS || echo 'ok' diff --git a/tools/xen/README.md b/tools/xen/README.md new file mode 100644 index 0000000..3a4bedd --- /dev/null +++ b/tools/xen/README.md @@ -0,0 +1,64 @@ +Getting Started With XenServer 5.6 and Devstack +=============================================== +The purpose of the code in this directory it to help developers bootstrap +a XenServer 5.6 + Openstack development environment. This file gives +some pointers on how to get started. + +Step 1: Install Xenserver +------------------------ +Install XenServer 5.6 on a clean box. You can get XenServer by signing +up for an account on citrix.com, and then visiting: +https://www.citrix.com/English/ss/downloads/details.asp?downloadId=2311504&productId=683148 + +Here are some sample Xenserver network settings for when you are just +getting started (I use settings like this with a lappy + cheap wifi router): + +* XenServer Host IP: 192.168.1.10 +* XenServer Netmask: 255.255.255.0 +* XenServer Gateway: 192.168.1.1 +* XenServer DNS: 192.168.1.1 + +Step 2: Prepare DOM0 +------------------- +At this point, your server is missing some critical software that you will +need to run devstack (like git). Do this to install required software: + + wget --no-check-certificate https://github.com/cloudbuilders/devstack/raw/xen/tools/xen/prepare_dom0.sh + chmod 755 prepare_dom0.sh + ./prepare_dom0.sh + +This script will also clone devstack in /root/devstack + +Step 3: Configure your localrc +----------------------------- +Devstack uses a localrc for user-specific configuration. Note that +the XENAPI_PASSWORD must be your dom0 root password. +Of course, use real passwords if this machine is exposed. + + cat > /root/devstack/localrc <> /etc/sysconfig/network +fi + +# Also, enable ip forwarding in rc.local, since the above trick isn't working +if ! grep -q "echo 1 >/proc/sys/net/ipv4/ip_forward" /etc/rc.local; then + echo "echo 1 >/proc/sys/net/ipv4/ip_forward" >> /etc/rc.local +fi + +# Enable ip forwarding at runtime as well +echo 1 > /proc/sys/net/ipv4/ip_forward + +# Directory where we stage the build +STAGING_DIR=$TOP_DIR/stage + +# Option to clean out old stuff +CLEAN=${CLEAN:-0} +if [ "$CLEAN" = "1" ]; then + rm -rf $STAGING_DIR +fi + +# Download our base image. This image is made using prepare_guest.sh +BASE_IMAGE_URL=${BASE_IMAGE_URL:-http://images.ansolabs.com/xen/stage.tgz} +if [ ! -e $STAGING_DIR ]; then + if [ ! -e /tmp/stage.tgz ]; then + wget $BASE_IMAGE_URL -O /tmp/stage.tgz + fi + tar xfz /tmp/stage.tgz + cd $TOP_DIR +fi + +# Free up precious disk space +rm -f /tmp/stage.tgz + +# Make sure we have a stage +if [ ! -d $STAGING_DIR/etc ]; then + echo "Stage is not properly set up!" + exit 1 +fi + +# Directory where our conf files are stored +FILES_DIR=$TOP_DIR/files +TEMPLATES_DIR=$TOP_DIR/templates + +# Directory for supporting script files +SCRIPT_DIR=$TOP_DIR/scripts + +# Version of ubuntu with which we are working +UBUNTU_VERSION=`cat $STAGING_DIR/etc/lsb-release | grep "DISTRIB_CODENAME=" | sed "s/DISTRIB_CODENAME=//"` +KERNEL_VERSION=`ls $STAGING_DIR/boot/vmlinuz* | head -1 | sed "s/.*vmlinuz-//"` + +# Setup fake grub +rm -rf $STAGING_DIR/boot/grub/ +mkdir -p $STAGING_DIR/boot/grub/ +cp $TEMPLATES_DIR/menu.lst.in $STAGING_DIR/boot/grub/menu.lst +sed -e "s,@KERNEL_VERSION@,$KERNEL_VERSION,g" -i $STAGING_DIR/boot/grub/menu.lst + +# Setup fstab, tty, and other system stuff +cp $FILES_DIR/fstab $STAGING_DIR/etc/fstab +cp $FILES_DIR/hvc0.conf $STAGING_DIR/etc/init/ + +# Put the VPX into UTC. +rm -f $STAGING_DIR/etc/localtime + +# Configure dns (use same dns as dom0) +cp /etc/resolv.conf $STAGING_DIR/etc/resolv.conf + +# Copy over devstack +rm -f /tmp/devstack.tar +tar --exclude='stage' --exclude='xen/xvas' --exclude='xen/nova' -cvf /tmp/devstack.tar $TOP_DIR/../../../devstack +cd $STAGING_DIR/opt/stack/ +tar xf /tmp/devstack.tar +cd $TOP_DIR + +# Configure OVA +VDI_SIZE=$(($VDI_MB*1024*1024)) +PRODUCT_BRAND=${PRODUCT_BRAND:-openstack} +PRODUCT_VERSION=${PRODUCT_VERSION:-001} +BUILD_NUMBER=${BUILD_NUMBER:-001} +LABEL="$PRODUCT_BRAND $PRODUCT_VERSION-$BUILD_NUMBER" +OVA=$STAGING_DIR/tmp/ova.xml +cp $TEMPLATES_DIR/ova.xml.in $OVA +sed -e "s,@VDI_SIZE@,$VDI_SIZE,g" -i $OVA +sed -e "s,@PRODUCT_BRAND@,$PRODUCT_BRAND,g" -i $OVA +sed -e "s,@PRODUCT_VERSION@,$PRODUCT_VERSION,g" -i $OVA +sed -e "s,@BUILD_NUMBER@,$BUILD_NUMBER,g" -i $OVA + +# Directory for xvas +XVA_DIR=$TOP_DIR/xvas + +# Create xva dir +mkdir -p $XVA_DIR + +# Clean nova if desired +if [ "$CLEAN" = "1" ]; then + rm -rf $TOP_DIR/nova +fi + +# Checkout nova +if [ ! -d $TOP_DIR/nova ]; then + git clone git://github.com/cloudbuilders/nova.git + git checkout diablo +fi + +# Run devstack on launch +cat <$STAGING_DIR/etc/rc.local +GUEST_PASSWORD=$GUEST_PASSWORD STAGING_DIR=/ DO_TGZ=0 bash /opt/stack/devstack/tools/xen/prepare_guest.sh +su -c "/opt/stack/run.sh > /opt/stack/run.sh.log" stack +exit 0 +EOF + +# Install plugins +cp -pr $TOP_DIR/nova/plugins/xenserver/xenapi/etc/xapi.d /etc/ +chmod a+x /etc/xapi.d/plugins/* +yum --enablerepo=base install -y parted +mkdir -p /boot/guest + +# Set local storage il8n +SR_UUID=`xe sr-list --minimal name-label="Local storage"` +xe sr-param-set uuid=$SR_UUID other-config:i18n-key=local-storage + +# Uninstall previous runs +xe vm-list --minimal name-label="$LABEL" | xargs ./scripts/uninstall-os-vpx.sh + +# Destroy any instances that were launched +for uuid in `xe vm-list | grep -1 instance | grep uuid | sed "s/.*\: //g"`; do + echo "Shutting down nova instance $uuid" + xe vm-shutdown uuid=$uuid + xe vm-destroy uuid=$uuid +done + +# Path to head xva. By default keep overwriting the same one to save space +USE_SEPARATE_XVAS=${USE_SEPARATE_XVAS:-0} +if [ "$USE_SEPARATE_XVAS" = "0" ]; then + XVA=$XVA_DIR/$UBUNTU_VERSION.xva +else + XVA=$XVA_DIR/$UBUNTU_VERSION.$GUEST_NAME.xva +fi + +# Clean old xva. In the future may not do this every time. +rm -f $XVA + +# Configure the hostname +echo $GUEST_NAME > $STAGING_DIR/etc/hostname + +# Hostname must resolve for rabbit +cat <$STAGING_DIR/etc/hosts +$MGT_IP $GUEST_NAME +127.0.0.1 localhost localhost.localdomain +EOF + +# Configure the network +INTERFACES=$STAGING_DIR/etc/network/interfaces +cp $TEMPLATES_DIR/interfaces.in $INTERFACES +sed -e "s,@ETH1_IP@,$VM_IP,g" -i $INTERFACES +sed -e "s,@ETH1_NETMASK@,$VM_NETMASK,g" -i $INTERFACES +sed -e "s,@ETH2_IP@,$MGT_IP,g" -i $INTERFACES +sed -e "s,@ETH2_NETMASK@,$MGT_NETMASK,g" -i $INTERFACES +sed -e "s,@ETH3_IP@,$PUB_IP,g" -i $INTERFACES +sed -e "s,@ETH3_NETMASK@,$PUB_NETMASK,g" -i $INTERFACES + +# Configure run.sh +cat <$STAGING_DIR/opt/stack/run.sh +#!/bin/bash +cd /opt/stack/devstack +killall screen +UPLOAD_LEGACY_TTY=yes HOST_IP=$PUB_IP VIRT_DRIVER=xenserver FORCE=yes MULTI_HOST=1 $STACKSH_PARAMS ./stack.sh +EOF +chmod 755 $STAGING_DIR/opt/stack/run.sh + +# Create xva +if [ ! -e $XVA ]; then + rm -rf /tmp/mkxva* + UID=0 $SCRIPT_DIR/mkxva -o $XVA -t xva -x $OVA $STAGING_DIR $VDI_MB /tmp/ +fi + +# Start guest +$TOP_DIR/scripts/install-os-vpx.sh -f $XVA -v $VM_BR -m $MGT_BR -p $PUB_BR + +echo "################################################################################" +echo "" +echo "All Finished!" +echo "Now, you can monitor the progress of the stack.sh installation by " +echo "tailing /opt/stack/run.sh.log from within your domU." +echo "" +echo "ssh into your domU now: 'ssh stack@$PUB_IP' using your password" +echo "and then do: 'tail -f /opt/stack/run.sh.log'" +echo "" +echo "When the script completes, you can then visit the OpenStack Dashboard" +echo "at http://$PUB_IP, and contact other services at the usual ports." diff --git a/tools/xen/files/fstab b/tools/xen/files/fstab new file mode 100644 index 0000000..6c9b981 --- /dev/null +++ b/tools/xen/files/fstab @@ -0,0 +1,5 @@ +LABEL=vpxroot / ext3 defaults 1 1 +tmpfs /dev/shm tmpfs defaults 0 0 +devpts /dev/pts devpts gid=5,mode=620 0 0 +sysfs /sys sysfs defaults 0 0 +proc /proc proc defaults 0 0 diff --git a/tools/xen/files/hvc0.conf b/tools/xen/files/hvc0.conf new file mode 100644 index 0000000..4eedaf6 --- /dev/null +++ b/tools/xen/files/hvc0.conf @@ -0,0 +1,10 @@ +# hvc0 - getty +# +# This service maintains a getty on hvc0 from the point the system is +# started until it is shut down again. + +start on stopped rc RUNLEVEL=[2345] +stop on runlevel [!2345] + +respawn +exec /sbin/getty -8 9600 hvc0 diff --git a/tools/xen/prepare_dom0.sh b/tools/xen/prepare_dom0.sh new file mode 100755 index 0000000..ce16ada --- /dev/null +++ b/tools/xen/prepare_dom0.sh @@ -0,0 +1,41 @@ +#!/bin/sh +set -o xtrace +set -o errexit + +# Install basics for vi and git +yum -y --enablerepo=base install gcc make vim-enhanced zlib-devel openssl-devel + +# Simple but usable vimrc +if [ ! -e /root/.vimrc ]; then + cat > /root/.vimrc <$STAGING_DIR/etc/apt/sources.list +deb http://us.archive.ubuntu.com/ubuntu/ oneiric main restricted +deb-src http://us.archive.ubuntu.com/ubuntu/ oneiric main restricted +deb http://us.archive.ubuntu.com/ubuntu/ oneiric-updates main restricted +deb-src http://us.archive.ubuntu.com/ubuntu/ oneiric-updates main restricted +deb http://us.archive.ubuntu.com/ubuntu/ oneiric universe +deb http://us.archive.ubuntu.com/ubuntu/ oneiric-updates universe +deb http://us.archive.ubuntu.com/ubuntu/ oneiric multiverse +deb http://us.archive.ubuntu.com/ubuntu/ oneiric-updates multiverse +EOF + +# Install basics +chroot $STAGING_DIR apt-get update +chroot $STAGING_DIR apt-get install -y linux-image-$KERNEL_VERSION +chroot $STAGING_DIR apt-get install -y cracklib-runtime curl wget ssh openssh-server tcpdump ethtool +chroot $STAGING_DIR apt-get install -y curl wget ssh openssh-server python-pip git vim-nox sudo +chroot $STAGING_DIR pip install xenapi + +# Install guest utilities +XEGUEST=xe-guest-utilities_5.6.100-651_amd64.deb +wget http://images.ansolabs.com/xen/$XEGUEST -O $XEGUEST +cp $XEGUEST $STAGING_DIR/root +chroot $STAGING_DIR dpkg -i /root/$XEGUEST +chroot $STAGING_DIR update-rc.d -f xe-linux-distribution remove +chroot $STAGING_DIR update-rc.d xe-linux-distribution defaults + +# Make a small cracklib dictionary, so that passwd still works, but we don't +# have the big dictionary. +mkdir -p $STAGING_DIR/usr/share/cracklib +echo a | chroot $STAGING_DIR cracklib-packer + +# Make /etc/shadow, and set the root password +chroot $STAGING_DIR "pwconv" +echo "root:$GUEST_PASSWORD" | chroot $STAGING_DIR chpasswd + +# Put the VPX into UTC. +rm -f $STAGING_DIR/etc/localtime + +# Add stack user +chroot $STAGING_DIR groupadd libvirtd +chroot $STAGING_DIR useradd stack -s /bin/bash -d /opt/stack -G libvirtd +echo stack:$GUEST_PASSWORD | chroot $STAGING_DIR chpasswd +echo "stack ALL=(ALL) NOPASSWD: ALL" >> $STAGING_DIR/etc/sudoers + +# Give ownership of /opt/stack to stack user +chroot $STAGING_DIR chown -R stack /opt/stack + +# Make our ip address hostnames look nice at the command prompt +echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $STAGING_DIR/opt/stack/.bashrc +echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $STAGING_DIR/root/.bashrc +echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $STAGING_DIR/etc/profile + +function setup_vimrc { + if [ ! -e $1 ]; then + # Simple but usable vimrc + cat > $1 <&2 + exit 1 + else + echo "$dest_sr" + fi +} + + +find_network() +{ + result=$(xe_min network-list bridge="$1") + if [ "$result" = "" ] + then + result=$(xe_min network-list name-label="$1") + fi + echo "$result" +} + + +find_template() +{ + xe_min template-list other-config:os-vpx=true +} + + +renumber_system_disk() +{ + local v="$1" + local vdi_uuid=$(xe_min vbd-list vm-uuid="$v" type=Disk userdevice=xvda \ + params=vdi-uuid) + if [ "$vdi_uuid" ] + then + local vbd_uuid=$(xe_min vbd-list vm-uuid="$v" vdi-uuid="$vdi_uuid") + xe vbd-destroy uuid="$vbd_uuid" + local new_vbd_uuid=$(xe vbd-create vm-uuid="$v" vdi-uuid="$vdi_uuid" \ + device=0 bootable=true type=Disk) + xe vbd-param-set other-config:owner uuid="$new_vbd_uuid" + fi +} + + +create_vif() +{ + xe vif-create vm-uuid="$1" network-uuid="$2" device="$3" +} + +create_gi_vif() +{ + local v="$1" + # Note that we've made the outbound device eth1, so that it comes up after + # the guest installer VIF, which means that the outbound one wins in terms + # of gateway. + local gi_network_uuid=$(xe_min network-list \ + other-config:is_guest_installer_network=true) + create_vif "$v" "$gi_network_uuid" "0" >/dev/null +} + +create_vm_vif() +{ + local v="$1" + echo "Installing management interface on $BRIDGE_V." + local out_network_uuid=$(find_network "$BRIDGE_V") + create_vif "$v" "$out_network_uuid" "1" >/dev/null +} + +create_management_vif() +{ + local v="$1" + echo "Installing management interface on $BRIDGE_M." + local out_network_uuid=$(find_network "$BRIDGE_M") + create_vif "$v" "$out_network_uuid" "2" >/dev/null +} + + +# This installs the interface for public traffic, only if a bridge is specified +# The interface is not configured at this stage, but it will be, once the admin +# tasks are complete for the services of this VPX +create_public_vif() +{ + local v="$1" + if [[ -z $BRIDGE_P ]] + then + echo "Skipping installation of interface for public traffic." + else + echo "Installing public interface on $BRIDGE_P." + pub_network_uuid=$(find_network "$BRIDGE_P") + create_vif "$v" "$pub_network_uuid" "3" >/dev/null + fi +} + + +label_system_disk() +{ + local v="$1" + local vdi_uuid=$(xe_min vbd-list vm-uuid="$v" type=Disk userdevice=0 \ + params=vdi-uuid) + xe vdi-param-set \ + name-label="$NAME system disk" \ + other-config:os-vpx=true \ + uuid=$vdi_uuid +} + + +create_data_disk() +{ + local v="$1" + + local sys_vdi_uuid=$(xe_min vbd-list vm-uuid="$v" type=Disk params=vdi-uuid) + local data_vdi_uuid=$(xe_min vdi-list other-config:os-vpx-data=true) + + if echo "$data_vdi_uuid" | grep -q , + then + echo "Multiple data disks found -- assuming that you want a new one." + data_vdi_uuid="" + else + data_in_use=$(xe_min vbd-list vdi-uuid="$data_vdi_uuid") + if [ "$data_in_use" != "" ] + then + echo "Data disk already in use -- will create another one." + data_vdi_uuid="" + fi + fi + + if [ "$data_vdi_uuid" = "" ] + then + echo -n "Creating new data disk ($DATA_VDI_SIZE)... " + sr_uuid=$(xe_min vdi-list params=sr-uuid uuid="$sys_vdi_uuid") + data_vdi_uuid=$(xe vdi-create name-label="$NAME data disk" \ + sr-uuid="$sr_uuid" \ + type=user \ + virtual-size="$DATA_VDI_SIZE") + xe vdi-param-set \ + other-config:os-vpx-data=true \ + uuid="$data_vdi_uuid" + dom0_uuid=$(xe_min vm-list is-control-domain=true) + vbd_uuid=$(xe vbd-create device=autodetect type=Disk \ + vdi-uuid="$data_vdi_uuid" vm-uuid="$dom0_uuid") + xe vbd-plug uuid=$vbd_uuid + dev=$(xe_min vbd-list params=device uuid=$vbd_uuid) + mke2fs -q -j -m0 /dev/$dev + e2label /dev/$dev vpxstate + xe vbd-unplug uuid=$vbd_uuid + xe vbd-destroy uuid=$vbd_uuid + else + echo -n "Attaching old data disk... " + fi + vbd_uuid=$(xe vbd-create device=2 type=Disk \ + vdi-uuid="$data_vdi_uuid" vm-uuid="$v") + xe vbd-param-set other-config:os-vpx-data=true uuid=$vbd_uuid + echo "done." +} + + +set_kernel_params() +{ + local v="$1" + local args=$KERNEL_PARAMS + local cmdline=$(cat /proc/cmdline) + for word in $cmdline + do + if echo "$word" | grep -q "geppetto" + then + args="$word $args" + fi + done + if [ "$args" != "" ] + then + echo "Passing Geppetto args to VPX: $args." + xe vm-param-set PV-args="$args" uuid="$v" + fi +} + + +set_memory() +{ + local v="$1" + if [ "$RAM" != "" ] + then + echo "Setting RAM to $RAM MiB." + [ "$BALLOONING" == 1 ] && RAM_MIN=$(($RAM / 2)) || RAM_MIN=$RAM + xe vm-memory-limits-set static-min=16MiB static-max=${RAM}MiB \ + dynamic-min=${RAM_MIN}MiB dynamic-max=${RAM}MiB \ + uuid="$v" + fi +} + + +# Make the VM auto-start on server boot. +set_auto_start() +{ + local v="$1" + xe vm-param-set uuid="$v" other-config:auto_poweron=true +} + + +set_all() +{ + local v="$1" + set_kernel_params "$v" + set_memory "$v" + set_auto_start "$v" + label_system_disk "$v" + create_gi_vif "$v" + create_vm_vif "$v" + create_management_vif "$v" + create_public_vif "$v" +} + + +log_vifs() +{ + local v="$1" + + (IFS=, + for vif in $(xe_min vif-list vm-uuid="$v") + do + dev=$(xe_min vif-list uuid="$vif" params=device) + mac=$(xe_min vif-list uuid="$vif" params=MAC | sed -e 's/:/-/g') + echo "eth$dev has MAC $mac." + done + unset IFS) | sort +} + + +destroy_vifs() +{ + local v="$1" + IFS=, + for vif in $(xe_min vif-list vm-uuid="$v") + do + xe vif-destroy uuid="$vif" + done + unset IFS +} + + +get_params "$@" + +thisdir=$(dirname "$0") + +if [ "$FROM_TEMPLATE" ] +then + template_uuid=$(find_template) + name=$(xe_min template-list params=name-label uuid="$template_uuid") + echo -n "Cloning $name... " + vm_uuid=$(xe vm-clone vm="$template_uuid" new-name-label="$name") + xe vm-param-set is-a-template=false uuid="$vm_uuid" + echo $vm_uuid. + + destroy_vifs "$vm_uuid" + set_all "$vm_uuid" +else + if [ ! -f "$VPX_FILE" ] + then + # Search $thisdir/$VPX_FILE too. In particular, this is used when + # installing the VPX from the supp-pack, because we want to be able to + # invoke this script from the RPM and the firstboot script. + if [ -f "$thisdir/$VPX_FILE" ] + then + VPX_FILE="$thisdir/$VPX_FILE" + else + echo "$VPX_FILE does not exist." >&2 + exit 1 + fi + fi + + echo "Found OS-VPX File: $VPX_FILE. " + + dest_sr=$(get_dest_sr) + + echo -n "Installing $NAME... " + vm_uuid=$(xe vm-import filename=$VPX_FILE sr-uuid="$dest_sr") + echo $vm_uuid. + + renumber_system_disk "$vm_uuid" + + nl=$(xe_min vm-list params=name-label uuid=$vm_uuid) + xe vm-param-set \ + "name-label=${nl/ import/}" \ + other-config:os-vpx=true \ + uuid=$vm_uuid + + set_all "$vm_uuid" + create_data_disk "$vm_uuid" + + if [ "$AS_TEMPLATE" ] + then + xe vm-param-set uuid="$vm_uuid" is-a-template=true \ + other-config:instant=true + echo -n "Installing VPX from template... " + vm_uuid=$(xe vm-clone vm="$vm_uuid" new-name-label="${nl/ import/}") + xe vm-param-set is-a-template=false uuid="$vm_uuid" + echo "$vm_uuid." + fi +fi + + +log_vifs "$vm_uuid" + +echo -n "Starting VM... " +xe vm-start uuid=$vm_uuid +echo "done." + + +show_ip() +{ + ip_addr=$(echo "$1" | sed -n "s,^.*"$2"/ip: \([^;]*\).*$,\1,p") + echo -n "IP address for $3: " + if [ "$ip_addr" = "" ] + then + echo "did not appear." + else + echo "$ip_addr." + fi +} + + +if [ "$WAIT_FOR_NETWORK" ] +then + echo "Waiting for network configuration... " + i=0 + while [ $i -lt 600 ] + do + ip=$(xe_min vm-list params=networks uuid=$vm_uuid) + if [ "$ip" != "" ] + then + show_ip "$ip" "1" "$BRIDGE_M" + if [[ $BRIDGE_P ]] + then + show_ip "$ip" "2" "$BRIDGE_P" + fi + echo "Installation complete." + exit 0 + fi + sleep 10 + let i=i+1 + done +fi diff --git a/tools/xen/scripts/mkxva b/tools/xen/scripts/mkxva new file mode 100755 index 0000000..dcdee61 --- /dev/null +++ b/tools/xen/scripts/mkxva @@ -0,0 +1,365 @@ +#!/bin/bash +# +# Copyright (c) 2011 Citrix Systems, Inc. +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +set -eu + +set -o xtrace + +VBOX_IMG=/output/packages/vbox-img + +usage() { + cat >&2 < -t -x + -o: Colon-separated list of output filenames (one for each type). + -p: Create a disk label and partition within the output image + -t: Colon-separated list of types of output file. xva and ovf supported. + -x: XML filenames (one for each type) + +EOF + exit 1 +} + +# parse cmdline + +OPT_USE_PARTITION= +OPT_TYPES= +OPT_OUTPUT_FILES= +OPT_XML_FILES= + +while getopts o:pt:x: o +do case "$o" in + o) OPT_OUTPUT_FILES=$(echo "$OPTARG" | sed -e 's/\s*:\s*/ /g') + ;; + p) OPT_USE_PARTITION=1 + ;; + t) OPT_TYPES=$(echo "$OPTARG" | sed -e 's/\s*:\s*/ /g') + ;; + x) OPT_XML_FILES=$(echo "$OPTARG" | sed -e 's/\s*:\s*/ /g') + ;; + [?]) usage + ;; + esac +done +shift $((OPTIND-1)) + +[ $# -ne 3 ] && usage +FS_STAGING="$1" +FS_SIZE_MIB="$2" +TMPDIR="$3" + +if [ "$UID" = "0" ] +then + SUDO= +else + SUDO=sudo +fi + +if [ "$FS_SIZE_MIB" = "0" ] +then + # Just create a dummy file. This allows developers to bypass bits of + # the build by setting the size to 0. + touch $OPT_OUTPUT_FILES + exit 0 +fi + +# create temporary files and dirs +FS_TMPFILE=$(mktemp "$TMPDIR/mkxva-fsimg-XXXXX") +XVA_TARBALL_STAGING=$(mktemp -d "$TMPDIR/mkxva-tarball-staging-XXXXX") +OVF_STAGING=$(mktemp -d "$TMPDIR/mkxva-ovf-staging-XXXXX") + +# Find udevsettle and udevtrigger on this installation +if [ -x "/sbin/udevsettle" ] ; then + UDEVSETTLE="/sbin/udevsettle --timeout=30" +elif [ -x "/sbin/udevadm" ] ; then + UDEVSETTLE='/sbin/udevadm settle' +else + UDEVSETTLE='/bin/true' +fi + +if [ -x "/sbin/udevtrigger" ] ; then + UDEVTRIGGER=/sbin/udevtrigger +elif [ -x "/sbin/udevadm" ] ; then + UDEVTRIGGER='/sbin/udevadm trigger' +else + UDEVTRIGGER= +fi + +# CLEAN_ variables track devices and mounts that must be taken down +# no matter how the script exits. Loop devices are vulnerable to +# exhaustion so we make every effort to remove them + +CLEAN_KPARTX= +CLEAN_LOSETUP= +CLEAN_MOUNTPOINT= + +cleanup_devices () { + if [ -n "$CLEAN_MOUNTPOINT" ] ; then + echo "Mountpoint $CLEAN_MOUNTPOINT removed on abnormal exit" + $SUDO umount "$CLEAN_MOUNTPOINT" || echo "umount failed" + rmdir "$CLEAN_MOUNTPOINT" || echo "rmdir failed" + fi + if [ -n "$CLEAN_KPARTX" ] ; then + echo "kpartx devices for $CLEAN_KPARTX removed on abnormal exit" + $SUDO kpartx -d "$CLEAN_KPARTX" || echo "kpartx -d failed" + fi + if [ -n "$CLEAN_LOSETUP" ] ; then + echo "Loop device $CLEAN_LOSETUP removed on abnormal exit" + $SUDO losetup -d "$CLEAN_LOSETUP" # Allow losetup errors to propagate + fi +} + +trap "cleanup_devices" EXIT + +make_fs_inner () { + local staging="$1" + local output="$2" + local options="$3" + CLEAN_MOUNTPOINT=$(mktemp -d "$TMPDIR/mkfs-XXXXXX") + + # copy staging dir contents to fs image + $SUDO mount $options "$output" "$CLEAN_MOUNTPOINT" + $SUDO tar -C "$staging" -c . | tar -C "$CLEAN_MOUNTPOINT" -x + $SUDO umount "$CLEAN_MOUNTPOINT" + rmdir "$CLEAN_MOUNTPOINT" + CLEAN_MOUNTPOINT= +} + +# Turn a staging dir into an ext3 filesystem within a partition +make_fs_in_partition () { + local staging="$1" + local output="$2" + + # create new empty disk + dd if=/dev/zero of="$output" bs=1M count=$FS_SIZE_MIB + # Set up a loop device on the empty disk image + local loopdevice=$($SUDO losetup -f) + $SUDO losetup "$loopdevice" "$output" + CLEAN_LOSETUP="$loopdevice" + # Create a partition table and single partition. + # Start partition at sector 63 to allow space for grub + cat < "$CLEAN_MOUNTPOINT/boot/grub/grub.conf" </dev/null + gzip "$file" + else + local file="$outputdir"/$(printf "%08d" $i) + dd if="$diskimg" of="$file" skip=$i bs=1M count=1 2>/dev/null + local chksum=$(sha1sum -b "$file") + echo -n "${chksum/ */}" > "$file.checksum" + fi + i=$(($i + 1)) + done +} + +if [ -n "$OPT_USE_PARTITION" ] ; then + make_fs_in_partition "$FS_STAGING" "$FS_TMPFILE" +else + make_fs "$FS_STAGING" "$FS_TMPFILE" +fi + +VDI_SIZE=$(stat --format=%s "$FS_TMPFILE") + +make_xva () { + local output_file="$1" + local xml_file="$2" + local subdir + local rio + + if [[ `cat $xml_file` =~ "\s*class\s*VDI\s*\s*\s*id\s*(Ref:[0-9]+)" ]] + then + # it's a rio style xva + subdir="${BASH_REMATCH[1]}"; + rio=1 + else + # it's a geneva style xva + subdir="xvda" + rio=0 + fi + + cp "$xml_file" "$XVA_TARBALL_STAGING"/ova.xml + sed -i -e "s/@VDI_SIZE@/$VDI_SIZE/" "$XVA_TARBALL_STAGING"/ova.xml + mkdir "$XVA_TARBALL_STAGING/$subdir" + splitvdi "$FS_TMPFILE" "$XVA_TARBALL_STAGING/$subdir" "$rio" + TARFILE_MEMBERS=$(cd "$XVA_TARBALL_STAGING" && echo ova.xml $subdir/*) + tar -C "$XVA_TARBALL_STAGING" --format=v7 -c $TARFILE_MEMBERS -f "$output_file.tmp" + mv "$output_file.tmp" "$output_file" +} + +make_ovf () { + local output_dir="$1" + local xml_file="$2" + local output_base=$(basename "$output_dir") + local disk="$output_dir/${output_base}.vmdk" + local manifest="$output_dir/${output_base}.mf" + local ovf="$output_dir/${output_base}.ovf" + + mkdir -p "$output_dir" + rm -f "$disk" + $VBOX_IMG convert --srcfilename="$FS_TMPFILE" --dstfilename="$disk" \ + --srcformat RAW --dstformat VMDK --variant Stream + chmod 0644 "$disk" + + local n_bytes=$(stat --printf=%s "$disk") + cp "$xml_file" "$ovf" + sed -i -e "s/@MKXVA_DISK_FULLSIZE@/$VDI_SIZE/" "$ovf" + sed -i -e "s/@MKXVA_DISK_SIZE@/$n_bytes/" "$ovf" + sed -i -e "s/@MKXVA_DISK_MIB_SIZE@/$FS_SIZE_MIB/" "$ovf" + sed -i -e "s/@MKXVA_DISK_FILENAME@/${output_base}.vmdk/" "$ovf" + + for to_sign in "$ovf" "$disk" + do + local sha1_sum=$(sha1sum "$to_sign" | cut -d' ' -f1) + echo "SHA1($(basename "$to_sign"))= $sha1_sum" >> $manifest + done +} + +output_files="$OPT_OUTPUT_FILES" +xml_files="$OPT_XML_FILES" +# Iterate through the type list creating the relevant VMs +for create_type in $OPT_TYPES +do + # Shift one parameter from the front of the lists + create_output_file="${output_files%% *}" + output_files="${output_files#* }" + create_xml_file="${xml_files%% *}" + xml_files="${xml_files#* }" + echo "Creating $create_type appliance $create_output_file using metadata file $create_xml_file" + + case "$create_type" in + xva) + make_xva "$create_output_file" "$create_xml_file" + ;; + ovf) + make_ovf "$create_output_file" "$create_xml_file" + ;; + *) + echo "Unknown VM type '$create_type'" + exit 1 + ;; + esac + +done + + +# cleanup +if [ -z "${DO_NOT_CLEANUP:-}" ] ; then + rm -rf "$XVA_TARBALL_STAGING" + rm -f "$FS_TMPFILE" +fi diff --git a/tools/xen/scripts/uninstall-os-vpx.sh b/tools/xen/scripts/uninstall-os-vpx.sh new file mode 100755 index 0000000..a82f3a0 --- /dev/null +++ b/tools/xen/scripts/uninstall-os-vpx.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# +# Copyright (c) 2011 Citrix Systems, Inc. +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +remove_data= +if [ "$1" = "--remove-data" ] +then + remove_data=1 +fi + +set -eu + +xe_min() +{ + local cmd="$1" + shift + /opt/xensource/bin/xe "$cmd" --minimal "$@" +} + +destroy_vdi() +{ + local vbd_uuid="$1" + local type=$(xe_min vbd-list uuid=$vbd_uuid params=type) + local dev=$(xe_min vbd-list uuid=$vbd_uuid params=userdevice) + local vdi_uuid=$(xe_min vbd-list uuid=$vbd_uuid params=vdi-uuid) + + if [ "$type" = 'Disk' ] && [ "$dev" != 'xvda' ] && [ "$dev" != '0' ] + then + echo -n "Destroying data disk... " + xe vdi-destroy uuid=$vdi_uuid + echo "done." + fi +} + +uninstall() +{ + local vm_uuid="$1" + local power_state=$(xe_min vm-list uuid=$vm_uuid params=power-state) + + if [ "$power_state" != "halted" ] + then + echo -n "Shutting down VM... " + xe vm-shutdown vm=$vm_uuid force=true + echo "done." + fi + + if [ "$remove_data" = "1" ] + then + for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g') + do + destroy_vdi "$v" + done + fi + + echo -n "Deleting VM... " + xe vm-uninstall vm=$vm_uuid force=true >/dev/null + echo "done." +} + +uninstall_template() +{ + local vm_uuid="$1" + + if [ "$remove_data" = "1" ] + then + for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g') + do + destroy_vdi "$v" + done + fi + + echo -n "Deleting template... " + xe template-uninstall template-uuid=$vm_uuid force=true >/dev/null + echo "done." +} + + +for u in $(xe_min vm-list other-config:os-vpx=true | sed -e 's/,/ /g') +do + uninstall "$u" +done + +for u in $(xe_min template-list other-config:os-vpx=true | sed -e 's/,/ /g') +do + uninstall_template "$u" +done diff --git a/tools/xen/templates/hosts.in b/tools/xen/templates/hosts.in new file mode 100644 index 0000000..8ab4c3e --- /dev/null +++ b/tools/xen/templates/hosts.in @@ -0,0 +1,8 @@ +127.0.0.1 localhost +127.0.0.1 %HOSTNAME% +::1 localhost ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters + diff --git a/tools/xen/templates/interfaces.in b/tools/xen/templates/interfaces.in new file mode 100644 index 0000000..49c3d68 --- /dev/null +++ b/tools/xen/templates/interfaces.in @@ -0,0 +1,21 @@ +auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet dhcp + +auto eth1 +iface eth1 inet static + address @ETH1_IP@ + netmask @ETH1_NETMASK@ +post-up ethtool -K eth1 tx off + +auto eth2 +iface eth2 inet static + address @ETH2_IP@ + netmask @ETH2_NETMASK@ + +auto eth3 +iface eth3 inet static + address @ETH3_IP@ + netmask @ETH3_NETMASK@ diff --git a/tools/xen/templates/menu.lst.in b/tools/xen/templates/menu.lst.in new file mode 100644 index 0000000..8bc6426 --- /dev/null +++ b/tools/xen/templates/menu.lst.in @@ -0,0 +1,6 @@ +default 0 + +title default + root (hd0,0) + kernel /boot/vmlinuz-@KERNEL_VERSION@ ro root=LABEL=vpxroot console=xvc0 + initrd /boot/initrd.img-@KERNEL_VERSION@ diff --git a/tools/xen/templates/ova.xml.in b/tools/xen/templates/ova.xml.in new file mode 100644 index 0000000..8443dcb --- /dev/null +++ b/tools/xen/templates/ova.xml.in @@ -0,0 +1,14 @@ + + + + + + + + + + + +