Browse code

Initial commit of xen devstack support

Anthony Young authored on 2011/10/27 14:29:08
Showing 15 changed files
... ...
@@ -1,5 +1,6 @@
1 1
 dnsmasq-base
2 2
 kpartx
3
+parted
3 4
 mysql-server
4 5
 python-mysqldb
5 6
 kvm
... ...
@@ -130,9 +130,10 @@ NOVNC_DIR=$DEST/noVNC
130 130
 # Specify which services to launch.  These generally correspond to screen tabs
131 131
 ENABLED_SERVICES=${ENABLED_SERVICES:-g-api,g-reg,key,n-api,n-cpu,n-net,n-sch,n-vnc,dash,mysql,rabbit}
132 132
 
133
-# Nova hypervisor configuration.  We default to **kvm** but will drop back to
134
-# **qemu** if we are unable to load the kvm module.  Stack.sh can also install
135
-# an **LXC** based system.
133
+# Nova hypervisor configuration.  We default to libvirt whth  **kvm** but will
134
+# drop back to **qemu** if we are unable to load the kvm module.  Stack.sh can
135
+# also install an **LXC** based system.
136
+VIRT_DRIVER=${VIRT_DRIVER:-libvirt}
136 137
 LIBVIRT_TYPE=${LIBVIRT_TYPE:-kvm}
137 138
 
138 139
 # nova supports pluggable schedulers.  ``SimpleScheduler`` should work in most
... ...
@@ -572,14 +573,30 @@ add_nova_flag "--ec2_dmz_host=$EC2_DMZ_HOST"
572 572
 add_nova_flag "--rabbit_host=$RABBIT_HOST"
573 573
 add_nova_flag "--rabbit_password=$RABBIT_PASSWORD"
574 574
 add_nova_flag "--glance_api_servers=$GLANCE_HOSTPORT"
575
-add_nova_flag "--flat_network_bridge=$FLAT_NETWORK_BRIDGE"
576
-if [ -n "$FLAT_INTERFACE" ]; then
577
-    add_nova_flag "--flat_interface=$FLAT_INTERFACE"
578
-fi
579 575
 if [ -n "$MULTI_HOST" ]; then
580 576
     add_nova_flag "--multi_host=$MULTI_HOST"
581 577
 fi
582 578
 
579
+# XenServer
580
+# ---------
581
+
582
+if [ "$VIRT_DRIVER" = 'xenserver' ]; then
583
+    read_password XENAPI_PASSWORD "ENTER A PASSWORD TO USE FOR XEN."
584
+    add_nova_flag "--connection_type=xenapi"
585
+    add_nova_flag "--xenapi_connection_url=http://169.254.0.1"
586
+    add_nova_flag "--xenapi_connection_username=root"
587
+    add_nova_flag "--xenapi_connection_password=$XENAPI_PASSWORD"
588
+    add_nova_flag "--flat_injected=False"
589
+    add_nova_flag "--flat_interface=eth1"
590
+    add_nova_flag "--flat_network_bridge=xapi1"
591
+    add_nova_flag "--public_interface=eth3"
592
+else
593
+    add_nova_flag "--flat_network_bridge=$FLAT_NETWORK_BRIDGE"
594
+    if [ -n "$FLAT_INTERFACE" ]; then
595
+        add_nova_flag "--flat_interface=$FLAT_INTERFACE"
596
+    fi
597
+fi
598
+
583 599
 # Nova Database
584 600
 # ~~~~~~~~~~~~~
585 601
 
... ...
@@ -712,6 +729,20 @@ if [[ "$ENABLED_SERVICES" =~ "g-reg" ]]; then
712 712
     # Create a directory for the downloaded image tarballs.
713 713
     mkdir -p $FILES/images
714 714
 
715
+    # Option to upload legacy ami-tty, which works with xenserver
716
+    if [ $UPLOAD_LEGACY_TTY ]; then
717
+        if [ ! -f $FILES/tty.tgz ]; then
718
+            wget -c http://images.ansolabs.com/tty.tgz -O $FILES/tty.tgz
719
+        fi
720
+
721
+        tar -zxf $FILES/tty.tgz -C $FILES/images
722
+        RVAL=`glance add -A $SERVICE_TOKEN name="tty-kernel" is_public=true container_format=aki disk_format=aki < $FILES/images/aki-tty/image`
723
+        KERNEL_ID=`echo $RVAL | cut -d":" -f2 | tr -d " "`
724
+        RVAL=`glance add -A $SERVICE_TOKEN name="tty-ramdisk" is_public=true container_format=ari disk_format=ari < $FILES/images/ari-tty/image`
725
+        RAMDISK_ID=`echo $RVAL | cut -d":" -f2 | tr -d " "`
726
+        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
727
+    fi
728
+
715 729
     for image_url in ${IMAGE_URLS//,/ }; do
716 730
         # Downloads the image (uec ami+aki style), then extracts it.
717 731
         IMAGE_FNAME=`echo "$image_url" | python -c "import sys; print sys.stdin.read().split('/')[-1]"`
718 732
new file mode 100644
... ...
@@ -0,0 +1,51 @@
0
+Getting Started With XenServer 5.6 and Devstack
1
+===============================================
2
+The purpose of the code in this directory it to help developers bootstrap
3
+a XenServer 5.6 + Openstack development environment.  This file gives
4
+some pointers on how to get started.
5
+
6
+Install Xenserver
7
+-----------------
8
+Install XenServer 5.6 on a clean box.
9
+Here are some sample Xenserver network settings for when you are just
10
+getting started (I used settings like this using a lappy + cheap wifi router):
11
+
12
+* XenServer Host IP: 192.168.1.10
13
+* XenServer Netmask: 255.255.255.0
14
+* XenServer Gateway: 192.168.1.1
15
+* XenServer DNS: 192.168.1.1
16
+
17
+Prepare DOM0
18
+------------
19
+At this point, your server is missing some critical software that you will
20
+need to run devstack (like git).  Do this to install required software:
21
+
22
+    ./prepare_dom0.sh 
23
+
24
+This script will also clone devstack in /root/devstack
25
+
26
+Configure your localrc
27
+----------------------
28
+Devstack uses a localrc for user-specific configuration.  Note that while
29
+the first 4 passwords are arbitrary, the XENAPI_PASSWORD must be your dom0
30
+root password.  And of course, use a real password if this machine is exposed.
31
+
32
+    cd /root/devstack
33
+    
34
+    cat > /root/devstack/localrc <<EOF
35
+    MYSQL_PASSWORD=my_super_secret
36
+    SERVICE_TOKEN=my_super_secret
37
+    ADMIN_PASSWORD=my_super_secret
38
+    RABBIT_PASSWORD=my_super_secret
39
+    # IMPORTANT: The following must be set to your dom0 root password!
40
+    XENAPI_PASSWORD=my_super_secret
41
+    EOF
42
+
43
+Run ./build_domU.sh
44
+------------------
45
+This script does a lot of stuff, it is probably best to read it in its entirety.
46
+But in a nutshell, it performs the following:
47
+
48
+* Configures bridges and vlans for public, private, and management nets
49
+* Creates XVAs for a HEAD and COMPUTE host
50
+* Launches those 2 instances into an HA FlatDHCP Configuration
0 51
new file mode 100755
... ...
@@ -0,0 +1,288 @@
0
+#!/bin/bash
1
+
2
+# Abort if localrc is not set
3
+if [ ! -e ../../localrc ]; then
4
+    echo "You must have a localrc with ALL necessary passwords defined before proceeding."
5
+    echo "See the xen README for required passwords."
6
+    exit 1
7
+fi
8
+
9
+# Echo commands
10
+set -o xtrace
11
+
12
+# Name of this guest
13
+GUEST_NAME=${GUEST_NAME:-ALLINONE}
14
+
15
+# dom0 ip
16
+HOST_IP=${HOST_IP:-`ifconfig xenbr0 | grep "inet addr" | cut -d ":" -f2 | sed "s/ .*//"`}
17
+
18
+# Our nova host's network info 
19
+MGT_IP=${MGT_IP:-172.16.100.1}
20
+PUB_IP=${PUB_IP:-192.168.1.55}
21
+
22
+# Public network
23
+PUB_BR=${PUB_BR:-xenbr0}
24
+PUB_NETMASK=${PUB_NETMASK:-255.255.255.0}
25
+
26
+# VM network params
27
+VM_NETMASK=${VM_NETMASK:-255.255.255.0}
28
+VM_BR=${VM_BR:-xapi1}
29
+VM_VLAN=${VM_VLAN:-100}
30
+
31
+# MGMT network params
32
+MGT_NETMASK=${MGT_NETMASK:-255.255.255.0}
33
+MGT_BR=${MGT_BR:-xapi2}
34
+MGT_VLAN=${MGT_VLAN:-101}
35
+
36
+# VM Password
37
+PASSWORD=${PASSWORD:-secrete}
38
+
39
+# Size of image
40
+VDI_MB=${VDI_MB:-2500}
41
+
42
+# This directory
43
+TOP_DIR=$(cd $(dirname "$0") && pwd)
44
+
45
+# Make sure we have git
46
+if ! which git; then
47
+    GITDIR=/tmp/git-1.7.7
48
+    cd /tmp
49
+    rm -rf $GITDIR*
50
+    wget http://git-core.googlecode.com/files/git-1.7.7.tar.gz
51
+    tar xfv git-1.7.7.tar.gz
52
+    cd $GITDIR
53
+    ./configure
54
+    make install
55
+    cd $TOP_DIR
56
+fi
57
+
58
+# Helper to create networks
59
+function create_network() {
60
+    if ! xe network-list | grep bridge | grep -q $1; then
61
+        echo "Creating bridge $1"
62
+        xe network-create name-label=$1
63
+    fi
64
+}
65
+
66
+# Create host, vm, mgmt, pub networks
67
+create_network xapi0
68
+create_network $VM_BR
69
+create_network $MGT_BR
70
+create_network $PUB_BR
71
+
72
+# Get the uuid for our physical (public) interface
73
+PIF=`xe pif-list --minimal device=eth0`
74
+
75
+# Create networks/bridges for vm and management
76
+VM_NET=`xe network-list --minimal bridge=$VM_BR`
77
+MGT_NET=`xe network-list --minimal bridge=$MGT_BR`
78
+
79
+# Helper to create vlans
80
+function create_vlan() {
81
+    pif=$1
82
+    vlan=$2
83
+    net=$3
84
+    if ! xe vlan-list | grep tag | grep -q $vlan; then
85
+        xe vlan-create pif-uuid=$pif vlan=$vlan network-uuid=$net
86
+    fi
87
+}
88
+
89
+# Create vlans for vm and management
90
+create_vlan $PIF $VM_VLAN $VM_NET
91
+create_vlan $PIF $MGT_VLAN $MGT_NET
92
+
93
+# Setup host-only nat rules
94
+HOST_NET=169.254.0.0/16
95
+if ! iptables -L -v -t nat | grep -q $HOST_NET; then
96
+    iptables -t nat -A POSTROUTING -s $HOST_NET -j SNAT --to-source $HOST_IP
97
+    iptables -I FORWARD 1 -s $HOST_NET -j ACCEPT
98
+    /etc/init.d/iptables save
99
+fi
100
+
101
+# Set up ip forwarding
102
+if ! grep -q "FORWARD_IPV4=YES" /etc/sysconfig/network; then
103
+    # FIXME: This doesn't work on reboot!
104
+    echo "FORWARD_IPV4=YES" >> /etc/sysconfig/network
105
+fi
106
+
107
+# Also, enable ip forwarding in rc.local, since the above trick isn't working
108
+if ! grep -q  "echo 1 >/proc/sys/net/ipv4/ip_forward" /etc/rc.local; then
109
+    echo "echo 1 >/proc/sys/net/ipv4/ip_forward" >> /etc/rc.local
110
+fi
111
+
112
+# Enable ip forwarding at runtime as well
113
+echo 1 > /proc/sys/net/ipv4/ip_forward
114
+
115
+# Directory where we stage the build
116
+STAGING_DIR=$TOP_DIR/stage
117
+
118
+# Option to clean out old stuff
119
+CLEAN=${CLEAN:-0}
120
+if [ "$CLEAN" = "1" ]; then
121
+    rm -rf $STAGING_DIR
122
+fi
123
+
124
+# Download our base image.  This image is made using prepare_guest.sh
125
+BASE_IMAGE_URL=${BASE_IMAGE_URL:-http://images.ansolabs.com/xen/stage.tgz}
126
+if [ ! -e $STAGING_DIR ]; then
127
+    if [ ! -e /tmp/stage.tgz ]; then
128
+        wget $BASE_IMAGE_URL -O /tmp/stage.tgz
129
+    fi
130
+    tar xfz /tmp/stage.tgz
131
+    cd $TOP_DIR
132
+fi
133
+
134
+# Free up precious disk space
135
+rm -f /tmp/stage.tgz
136
+
137
+# Make sure we have a stage
138
+if [ ! -d $STAGING_DIR/etc ]; then
139
+    echo "Stage is not properly set up!"
140
+    exit 1
141
+fi
142
+
143
+# Directory where our conf files are stored
144
+FILES_DIR=$TOP_DIR/files
145
+
146
+# Directory for supporting script files
147
+SCRIPT_DIR=$TOP_DIR/scripts
148
+
149
+# Version of ubuntu with which we are working
150
+UBUNTU_VERSION=`cat $STAGING_DIR/etc/lsb-release | grep "DISTRIB_CODENAME=" | sed "s/DISTRIB_CODENAME=//"`
151
+KERNEL_VERSION=`ls $STAGING_DIR/boot/vmlinuz* | head -1 | sed "s/.*vmlinuz-//"`
152
+
153
+# Setup fake grub
154
+rm -rf $STAGING_DIR/boot/grub/
155
+mkdir -p $STAGING_DIR/boot/grub/
156
+cp $FILES_DIR/menu.lst.in $STAGING_DIR/boot/grub/menu.lst
157
+sed -e "s,@KERNEL_VERSION@,$KERNEL_VERSION,g" -i $STAGING_DIR/boot/grub/menu.lst
158
+
159
+# Setup fstab, tty, and other system stuff
160
+cp $FILES_DIR/fstab $STAGING_DIR/etc/fstab
161
+cp $FILES_DIR/hvc0.conf $STAGING_DIR/etc/init/
162
+
163
+# Put the VPX into UTC.
164
+rm -f $STAGING_DIR/etc/localtime
165
+
166
+# Helper to set hostname
167
+function set_hostname() {
168
+    echo $1 > $STAGING_DIR/etc/hostname
169
+}
170
+
171
+# We need a resolvable host name for rabbit to launch
172
+if ! grep -q $GUEST_NAME $STAGING_DIR/etc/hosts; then
173
+    echo "$MGT_IP $GUEST_NAME" >> $STAGING_DIR/etc/hosts
174
+fi
175
+
176
+# Configre hosts file
177
+cat <<EOF >$STAGING_DIR/etc/hosts
178
+$MGT_IP $GUEST_NAME
179
+127.0.0.1 localhost localhost.localdomain
180
+EOF
181
+
182
+# Configure dns (use same dns as dom0)
183
+cp /etc/resolv.conf $STAGING_DIR/etc/resolv.conf
184
+
185
+# Copy over devstack
186
+rm -f /tmp/devstack.tar
187
+tar --exclude='stage' --exclude='xen/xvas' --exclude='xen/nova' -cvf /tmp/devstack.tar $TOP_DIR/../../../devstack
188
+cd $STAGING_DIR/opt/stack/
189
+tar xf /tmp/devstack.tar
190
+cd $TOP_DIR
191
+
192
+# Configure OVA
193
+VDI_SIZE=$(($VDI_MB*1024*1024))
194
+PRODUCT_BRAND=${PRODUCT_BRAND:-openstack}
195
+PRODUCT_VERSION=${PRODUCT_VERSION:-001}
196
+BUILD_NUMBER=${BUILD_NUMBER:-001}
197
+LABEL="$PRODUCT_BRAND $PRODUCT_VERSION-$BUILD_NUMBER"
198
+OVA=$STAGING_DIR/tmp/ova.xml
199
+cp templates/ova.xml.in  $OVA
200
+sed -e "s,@VDI_SIZE@,$VDI_SIZE,g" -i $OVA
201
+sed -e "s,@PRODUCT_BRAND@,$PRODUCT_BRAND,g" -i $OVA
202
+sed -e "s,@PRODUCT_VERSION@,$PRODUCT_VERSION,g" -i $OVA
203
+sed -e "s,@BUILD_NUMBER@,$BUILD_NUMBER,g" -i $OVA
204
+
205
+# Directory for xvas
206
+XVA_DIR=$TOP_DIR/xvas
207
+
208
+# Create xva dir
209
+mkdir -p $XVA_DIR
210
+
211
+# Clean nova if desired
212
+if [ "$CLEAN" = "1" ]; then
213
+    rm -rf $TOP_DIR/nova
214
+fi
215
+
216
+# Checkout nova
217
+if [ ! -d $TOP_DIR/nova ]; then
218
+    git clone git://github.com/cloudbuilders/nova.git
219
+    git checkout diablo
220
+fi 
221
+
222
+# Run devstack on launch
223
+cat <<EOF >$STAGING_DIR/etc/rc.local
224
+STAGING_DIR=/ DO_TGZ=0 bash /opt/stack/devstack/tools/xen/prepare_guest.sh
225
+STAGING_DIR=/ DO_TGZ=0 bash /opt/stack/devstack/tools/xen/prepare_guest.sh
226
+su -c "/opt/stack/run.sh > /opt/stack/run.sh.log" stack
227
+exit 0
228
+EOF
229
+
230
+# Install plugins
231
+cp -pr $TOP_DIR/nova/plugins/xenserver/xenapi/etc/xapi.d /etc/
232
+chmod a+x /etc/xapi.d/plugins/*
233
+yum --enablerepo=base install -y parted
234
+mkdir -p /boot/guest
235
+
236
+# Set local storage il8n
237
+SR_UUID=`xe sr-list --minimal name-label="Local storage"`
238
+xe sr-param-set uuid=$SR_UUID other-config:i18n-key=local-storage
239
+
240
+# Uninstall previous runs
241
+xe vm-list --minimal name-label="$LABEL" | xargs ./scripts/uninstall-os-vpx.sh
242
+
243
+# Destroy any instances that were launched
244
+for uuid in `xe vm-list | grep -1 instance | grep uuid | sed "s/.*\: //g"`; do
245
+    echo "Shutting down nova instance $uuid"
246
+    xe vm-shutdown uuid=$uuid
247
+    xe vm-destroy uuid=$uuid
248
+done
249
+
250
+# Path to head xva.  By default keep overwriting the same one to save space
251
+USE_SEPARATE_XVAS=${USE_SEPARATE_XVAS:-0}
252
+if [ "$USE_SEPARATE_XVAS" = "0" ]; then
253
+    XVA=$XVA_DIR/$UBUNTU_VERSION.xva 
254
+else
255
+    XVA=$XVA_DIR/$UBUNTU_VERSION.$GUEST_NAME.xva 
256
+fi
257
+
258
+# Clean old xva. In the future may not do this every time.
259
+rm -f $XVA
260
+
261
+# Configure the network
262
+set_hostname $GUEST_NAME
263
+INTERFACES=$STAGING_DIR/etc/network/interfaces
264
+cp templates/interfaces.in  $INTERFACES
265
+sed -e "s,@ETH1_NETMASK@,$VM_NETMASK,g" -i $INTERFACES
266
+sed -e "s,@ETH2_IP@,$MGT_IP,g" -i $INTERFACES
267
+sed -e "s,@ETH2_NETMASK@,$MGT_NETMASK,g" -i $INTERFACES
268
+sed -e "s,@ETH3_IP@,$PUB_IP,g" -i $INTERFACES
269
+sed -e "s,@ETH3_NETMASK@,$PUB_NETMASK,g" -i $INTERFACES
270
+
271
+# Configure run.sh
272
+cat <<EOF >$STAGING_DIR/opt/stack/run.sh
273
+#!/bin/bash
274
+cd /opt/stack/devstack
275
+killall screen
276
+UPLOAD_LEGACY_TTY=yes HOST_IP=$PUB_IP VIRT_DRIVER=xenserver FORCE=yes MULTI_HOST=1 $STACKSH_PARAMS ./stack.sh
277
+EOF
278
+chmod 755 $STAGING_DIR/opt/stack/run.sh
279
+
280
+# Create xva
281
+if [ ! -e $XVA ]; then
282
+    rm -rf /tmp/mkxva*
283
+    UID=0 $SCRIPT_DIR/mkxva -o $XVA -t xva -x $OVA $STAGING_DIR $VDI_MB /tmp/
284
+fi
285
+
286
+# Start guest
287
+$TOP_DIR/scripts/install-os-vpx.sh -f $XVA -v $VM_BR -m $MGT_BR -p $PUB_BR
0 288
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+LABEL=vpxroot           /                       ext3    defaults        1 1
1
+tmpfs                   /dev/shm                tmpfs   defaults        0 0
2
+devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3
+sysfs                   /sys                    sysfs   defaults        0 0
4
+proc                    /proc                   proc    defaults        0 0
0 5
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+# hvc0 - getty
1
+#
2
+# This service maintains a getty on hvc0 from the point the system is
3
+# started until it is shut down again.
4
+
5
+start on stopped rc RUNLEVEL=[2345]
6
+stop on runlevel [!2345]
7
+
8
+respawn
9
+exec /sbin/getty -8 9600 hvc0
0 10
new file mode 100755
... ...
@@ -0,0 +1,41 @@
0
+#!/bin/sh
1
+set -o xtrace
2
+set -o errexit
3
+
4
+# Install basics for vi and git
5
+yum -y  --enablerepo=base install gcc make vim-enhanced zlib-devel openssl-devel
6
+
7
+# Simple but usable vimrc
8
+if [ ! -e /root/.vimrc ]; then
9
+    cat > /root/.vimrc <<EOF
10
+syntax on
11
+se ts=4
12
+se expandtab
13
+se shiftwidth=4
14
+EOF
15
+fi
16
+
17
+# Use the pretty vim
18
+if [ -e /usr/bin/vim ]; then
19
+    rm /bin/vi
20
+    ln -s /usr/bin/vim /bin/vi
21
+fi
22
+
23
+# Install git 
24
+if ! which git; then
25
+    DEST=/tmp/
26
+    GITDIR=$DEST/git-1.7.7
27
+    cd $DEST
28
+    rm -rf $GITDIR*
29
+    wget http://git-core.googlecode.com/files/git-1.7.7.tar.gz
30
+    tar xfv git-1.7.7.tar.gz
31
+    cd $GITDIR
32
+    ./configure
33
+    make install
34
+fi
35
+
36
+# Clone devstack
37
+DEVSTACK=/root/devstack
38
+if [ ! -d $DEVSTACK ]; then
39
+    git clone git://github.com/cloudbuilders/devstack.git $DEVSTACK
40
+fi
0 41
new file mode 100644
... ...
@@ -0,0 +1,88 @@
0
+#!/bin/bash
1
+
2
+# Configurable nuggets
3
+PASSWORD=${PASSWORD:-secrete}
4
+STAGING_DIR=${STAGING_DIR:-stage}
5
+DO_TGZ=${DO_TGZ:-1}
6
+KERNEL_VERSION=3.0.0-12-virtual
7
+
8
+# Debootstrap base system
9
+if [ ! -d $STAGING_DIR ]; then
10
+    apt-get install debootstrap
11
+    debootstrap --arch amd64 oneiric $STAGING_DIR http://us.archive.ubuntu.com/ubuntu/
12
+fi
13
+
14
+# Sources.list
15
+cat <<EOF >$STAGING_DIR/etc/apt/sources.list
16
+deb http://us.archive.ubuntu.com/ubuntu/ oneiric main restricted
17
+deb-src http://us.archive.ubuntu.com/ubuntu/ oneiric main restricted
18
+deb http://us.archive.ubuntu.com/ubuntu/ oneiric-updates main restricted
19
+deb-src http://us.archive.ubuntu.com/ubuntu/ oneiric-updates main restricted
20
+deb http://us.archive.ubuntu.com/ubuntu/ oneiric universe
21
+deb http://us.archive.ubuntu.com/ubuntu/ oneiric-updates universe
22
+deb http://us.archive.ubuntu.com/ubuntu/ oneiric multiverse
23
+deb http://us.archive.ubuntu.com/ubuntu/ oneiric-updates multiverse
24
+EOF
25
+
26
+# Install basics
27
+chroot $STAGING_DIR apt-get update
28
+chroot $STAGING_DIR apt-get install -y linux-image-$KERNEL_VERSION
29
+chroot $STAGING_DIR apt-get install -y cracklib-runtime curl wget ssh openssh-server tcpdump ethtool
30
+chroot $STAGING_DIR apt-get install -y curl wget ssh openssh-server python-pip git vim-nox sudo
31
+chroot $STAGING_DIR pip install xenapi
32
+
33
+# Install guest utilities
34
+XEGUEST=xe-guest-utilities_5.6.100-651_amd64.deb
35
+wget http://images.ansolabs.com/xen/$XEGUEST -O $XEGUEST
36
+cp $XEGUEST $STAGING_DIR/root
37
+chroot $STAGING_DIR dpkg -i /root/$XEGUEST
38
+chroot $STAGING_DIR update-rc.d -f xe-linux-distribution remove
39
+chroot $STAGING_DIR update-rc.d xe-linux-distribution defaults
40
+
41
+# Make a small cracklib dictionary, so that passwd still works, but we don't
42
+# have the big dictionary.
43
+mkdir -p $STAGING_DIR/usr/share/cracklib
44
+echo a | chroot $STAGING_DIR cracklib-packer
45
+
46
+# Make /etc/shadow, and set the root password
47
+chroot $STAGING_DIR "pwconv"
48
+echo "root:$PASSWORD" | chroot $STAGING_DIR chpasswd
49
+
50
+# Put the VPX into UTC.
51
+rm -f $STAGING_DIR/etc/localtime
52
+
53
+# Add stack user
54
+chroot $STAGING_DIR groupadd libvirtd
55
+chroot $STAGING_DIR useradd stack -s /bin/bash -d /opt/stack -G libvirtd
56
+echo stack:$PASSWORD | chroot $STAGING_DIR chpasswd
57
+echo "stack ALL=(ALL) NOPASSWD: ALL" >> $STAGING_DIR/etc/sudoers
58
+
59
+# Give ownership of /opt/stack to stack user
60
+chroot $STAGING_DIR chown -R stack /opt/stack
61
+
62
+# Make our ip address hostnames look nice at the command prompt
63
+echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $STAGING_DIR/opt/stack/.bashrc
64
+echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $STAGING_DIR/root/.bashrc
65
+echo "export PS1='${debian_chroot:+($debian_chroot)}\\u@\\H:\\w\\$ '" >> $STAGING_DIR/etc/profile
66
+
67
+function setup_vimrc {
68
+    if [ ! -e $1 ]; then
69
+        # Simple but usable vimrc
70
+        cat > $1 <<EOF
71
+syntax on
72
+se ts=4
73
+se expandtab
74
+se shiftwidth=4
75
+EOF
76
+    fi
77
+}
78
+
79
+# Setup simple .vimrcs
80
+setup_vimrc $STAGING_DIR/root/.vimrc
81
+setup_vimrc $STAGING_DIR/opt/stack/.vimrc
82
+
83
+if [ "$DO_TGZ" = "1" ]; then
84
+    # Compress
85
+    rm -f stage.tgz
86
+    tar cfz stage.tgz stage
87
+fi
0 88
new file mode 100755
... ...
@@ -0,0 +1,508 @@
0
+#!/bin/bash
1
+#
2
+# Copyright (c) 2011 Citrix Systems, Inc.
3
+# Copyright 2011 OpenStack LLC.
4
+# Copyright (C) 2011 Nicira, Inc
5
+# All Rights Reserved.
6
+#
7
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
8
+#    not use this file except in compliance with the License. You may obtain
9
+#    a copy of the License at
10
+#
11
+#         http://www.apache.org/licenses/LICENSE-2.0
12
+#
13
+#    Unless required by applicable law or agreed to in writing, software
14
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+#    License for the specific language governing permissions and limitations
17
+#    under the License.
18
+#
19
+
20
+set -eux
21
+
22
+. /etc/xensource-inventory
23
+
24
+NAME="XenServer OpenStack VPX"
25
+DATA_VDI_SIZE="500MiB"
26
+BRIDGE_M=
27
+BRIDGE_P=
28
+KERNEL_PARAMS=
29
+VPX_FILE=os-vpx.xva
30
+AS_TEMPLATE=
31
+FROM_TEMPLATE=
32
+RAM=
33
+WAIT_FOR_NETWORK=
34
+BALLOONING=
35
+
36
+usage()
37
+{
38
+cat << EOF
39
+
40
+  Usage: $0 [-f FILE_PATH] [-d DISK_SIZE] [-v BRIDGE_NAME] [-m BRIDGE_NAME] [-p BRIDGE_NAME]
41
+            [-k PARAMS] [-r RAM] [-i|-c] [-w] [-b]
42
+
43
+  Installs XenServer OpenStack VPX.
44
+
45
+  OPTIONS:
46
+
47
+     -h           Shows this message.
48
+     -i           Install OpenStack VPX as template.
49
+     -c           Clone from existing template.
50
+     -w           Wait for the network settings to show up before exiting.
51
+     -b           Enable memory ballooning. When set min_RAM=RAM/2 max_RAM=RAM.
52
+     -f path      Specifies the path to the XVA.
53
+                  Default to ./os-vpx.xva.
54
+     -d disk-size Specifies the size in MiB for the data disk.
55
+                  Defaults to 500 MiB.
56
+     -m bridge    Specifies the bridge for the isolated management network.
57
+                  Defaults to xenbr0.
58
+     -v bridge    Specifies the bridge for the vm network
59
+     -p bridge    Specifies the bridge for the externally facing network.
60
+     -k params    Specifies kernel parameters.
61
+     -r MiB       Specifies RAM used by the VPX, in MiB.
62
+                  By default it will take the value from the XVA.
63
+
64
+  EXAMPLES:
65
+
66
+     Create a VPX that connects to the isolated management network using the
67
+     default bridge with a data disk of 1GiB:
68
+            install-os-vpx.sh -f /root/os-vpx-devel.xva -d 1024
69
+
70
+     Create a VPX that connects to the isolated management network using xenbr1
71
+     as bridge:
72
+            install-os-vpx.sh -m xenbr1
73
+
74
+     Create a VPX that connects to both the management and public networks
75
+     using xenbr1 and xapi4 as bridges:
76
+            install-os-vpx.sh -m xenbr1 -p xapi4
77
+
78
+     Create a VPX that connects to both the management and public networks
79
+     using the default for management traffic:
80
+            install-os-vpx.sh -m xapi4
81
+
82
+     Create a VPX that automatically becomes the master:
83
+            install-os-vpx.sh -k geppetto_master=true
84
+
85
+EOF
86
+}
87
+
88
+get_params()
89
+{
90
+  while getopts "hicwbf:d:v:m:p:k:r:" OPTION; 
91
+  do
92
+    case $OPTION in
93
+      h) usage
94
+         exit 1
95
+         ;;
96
+      i)
97
+         AS_TEMPLATE=1
98
+         ;;
99
+      c)
100
+         FROM_TEMPLATE=1
101
+         ;;
102
+      w)
103
+         WAIT_FOR_NETWORK=1
104
+         ;;
105
+      b)
106
+         BALLOONING=1
107
+         ;;
108
+      f)
109
+         VPX_FILE=$OPTARG
110
+         ;;
111
+      d)
112
+         DATA_VDI_SIZE="${OPTARG}MiB"
113
+         ;;
114
+      m)
115
+         BRIDGE_M=$OPTARG
116
+         ;;
117
+      p)
118
+         BRIDGE_P=$OPTARG
119
+         ;;
120
+      k)
121
+         KERNEL_PARAMS=$OPTARG
122
+         ;;
123
+      r)
124
+         RAM=$OPTARG
125
+         ;;
126
+      v)
127
+         BRIDGE_V=$OPTARG
128
+         ;;
129
+      ?)
130
+         usage
131
+         exit
132
+         ;;
133
+    esac
134
+  done
135
+  if [[ -z $BRIDGE_M ]]
136
+  then
137
+     BRIDGE_M=xenbr0
138
+  fi
139
+}
140
+
141
+
142
+xe_min()
143
+{
144
+  local cmd="$1"
145
+  shift
146
+  xe "$cmd" --minimal "$@"
147
+}
148
+
149
+
150
+get_dest_sr()
151
+{
152
+  IFS=,
153
+  sr_uuids=$(xe sr-list --minimal other-config:i18n-key=local-storage)
154
+  dest_sr=""
155
+  for sr_uuid in $sr_uuids
156
+  do
157
+    pbd=$(xe pbd-list --minimal sr-uuid=$sr_uuid host-uuid=$INSTALLATION_UUID)
158
+    if [ "$pbd" ]
159
+    then
160
+      echo "$sr_uuid"
161
+      unset IFS
162
+      return
163
+    fi
164
+  done
165
+  unset IFS
166
+
167
+  dest_sr=$(xe_min sr-list uuid=$(xe_min pool-list params=default-SR))
168
+  if [ "$dest_sr" = "" ]
169
+  then
170
+    echo "No local storage and no default storage; cannot import VPX." >&2
171
+    exit 1
172
+  else
173
+    echo "$dest_sr"
174
+  fi
175
+}
176
+
177
+
178
+find_network()
179
+{
180
+  result=$(xe_min network-list bridge="$1")
181
+  if [ "$result" = "" ]
182
+  then
183
+    result=$(xe_min network-list name-label="$1")
184
+  fi
185
+  echo "$result"
186
+}
187
+
188
+
189
+find_template()
190
+{
191
+  xe_min template-list other-config:os-vpx=true
192
+}
193
+
194
+
195
+renumber_system_disk()
196
+{
197
+  local v="$1"
198
+  local vdi_uuid=$(xe_min vbd-list vm-uuid="$v" type=Disk userdevice=xvda \
199
+                                   params=vdi-uuid)
200
+  if [ "$vdi_uuid" ]
201
+  then
202
+    local vbd_uuid=$(xe_min vbd-list vm-uuid="$v" vdi-uuid="$vdi_uuid")
203
+    xe vbd-destroy uuid="$vbd_uuid"
204
+    local new_vbd_uuid=$(xe vbd-create vm-uuid="$v" vdi-uuid="$vdi_uuid" \
205
+                         device=0 bootable=true type=Disk)
206
+    xe vbd-param-set other-config:owner uuid="$new_vbd_uuid"
207
+  fi
208
+}
209
+
210
+
211
+create_vif()
212
+{
213
+  xe vif-create vm-uuid="$1" network-uuid="$2" device="$3"
214
+}
215
+
216
+create_gi_vif()
217
+{
218
+  local v="$1"
219
+  # Note that we've made the outbound device eth1, so that it comes up after
220
+  # the guest installer VIF, which means that the outbound one wins in terms
221
+  # of gateway.
222
+  local gi_network_uuid=$(xe_min network-list \
223
+                                 other-config:is_guest_installer_network=true)
224
+  create_vif "$v" "$gi_network_uuid" "0" >/dev/null
225
+}
226
+
227
+create_vm_vif()
228
+{
229
+  local v="$1"
230
+  echo "Installing management interface on $BRIDGE_V."
231
+  local out_network_uuid=$(find_network "$BRIDGE_V")
232
+  create_vif "$v" "$out_network_uuid" "1" >/dev/null
233
+}
234
+
235
+create_management_vif()
236
+{
237
+  local v="$1"
238
+  echo "Installing management interface on $BRIDGE_M."
239
+  local out_network_uuid=$(find_network "$BRIDGE_M")
240
+  create_vif "$v" "$out_network_uuid" "2" >/dev/null
241
+}
242
+
243
+
244
+# This installs the interface for public traffic, only if a bridge is specified
245
+# The interface is not configured at this stage, but it will be, once the admin   
246
+# tasks are complete for the services of this VPX
247
+create_public_vif()
248
+{
249
+  local v="$1"
250
+  if [[ -z $BRIDGE_P ]]
251
+  then
252
+    echo "Skipping installation of interface for public traffic."
253
+  else
254
+    echo "Installing public interface on $BRIDGE_P."
255
+    pub_network_uuid=$(find_network "$BRIDGE_P")
256
+    create_vif "$v" "$pub_network_uuid" "3" >/dev/null
257
+  fi
258
+}
259
+
260
+
261
+label_system_disk()
262
+{
263
+  local v="$1"
264
+  local vdi_uuid=$(xe_min vbd-list vm-uuid="$v" type=Disk userdevice=0 \
265
+                                   params=vdi-uuid)
266
+  xe vdi-param-set \
267
+     name-label="$NAME system disk" \
268
+     other-config:os-vpx=true \
269
+     uuid=$vdi_uuid
270
+}
271
+
272
+
273
+create_data_disk()
274
+{
275
+  local v="$1"
276
+
277
+  local sys_vdi_uuid=$(xe_min vbd-list vm-uuid="$v" type=Disk params=vdi-uuid)
278
+  local data_vdi_uuid=$(xe_min vdi-list other-config:os-vpx-data=true)
279
+
280
+  if echo "$data_vdi_uuid" | grep -q ,
281
+  then
282
+    echo "Multiple data disks found -- assuming that you want a new one."
283
+    data_vdi_uuid=""
284
+  else
285
+    data_in_use=$(xe_min vbd-list vdi-uuid="$data_vdi_uuid")
286
+    if [ "$data_in_use" != "" ]
287
+    then
288
+      echo "Data disk already in use -- will create another one."
289
+      data_vdi_uuid=""
290
+    fi
291
+  fi
292
+
293
+  if [ "$data_vdi_uuid" = "" ]
294
+  then
295
+    echo -n "Creating new data disk ($DATA_VDI_SIZE)... "
296
+    sr_uuid=$(xe_min vdi-list params=sr-uuid uuid="$sys_vdi_uuid")
297
+    data_vdi_uuid=$(xe vdi-create name-label="$NAME data disk" \
298
+                                  sr-uuid="$sr_uuid" \
299
+                                  type=user \
300
+                                  virtual-size="$DATA_VDI_SIZE")
301
+    xe vdi-param-set \
302
+       other-config:os-vpx-data=true \
303
+       uuid="$data_vdi_uuid"
304
+    dom0_uuid=$(xe_min vm-list is-control-domain=true)
305
+    vbd_uuid=$(xe vbd-create device=autodetect type=Disk \
306
+                             vdi-uuid="$data_vdi_uuid" vm-uuid="$dom0_uuid")
307
+    xe vbd-plug uuid=$vbd_uuid
308
+    dev=$(xe_min vbd-list params=device uuid=$vbd_uuid)
309
+    mke2fs -q -j -m0 /dev/$dev
310
+    e2label /dev/$dev vpxstate
311
+    xe vbd-unplug uuid=$vbd_uuid
312
+    xe vbd-destroy uuid=$vbd_uuid
313
+  else
314
+    echo -n "Attaching old data disk... "
315
+  fi
316
+  vbd_uuid=$(xe vbd-create device=2 type=Disk \
317
+                           vdi-uuid="$data_vdi_uuid" vm-uuid="$v")
318
+  xe vbd-param-set other-config:os-vpx-data=true uuid=$vbd_uuid
319
+  echo "done."
320
+}
321
+
322
+
323
+set_kernel_params()
324
+{
325
+  local v="$1"
326
+  local args=$KERNEL_PARAMS
327
+  local cmdline=$(cat /proc/cmdline)
328
+  for word in $cmdline
329
+  do
330
+    if echo "$word" | grep -q "geppetto"
331
+    then
332
+      args="$word $args"
333
+    fi
334
+  done
335
+  if [ "$args" != "" ]
336
+  then
337
+    echo "Passing Geppetto args to VPX: $args."
338
+    xe vm-param-set PV-args="$args" uuid="$v"
339
+  fi
340
+}
341
+
342
+
343
+set_memory()
344
+{
345
+  local v="$1"
346
+  if [ "$RAM" != "" ]
347
+  then
348
+    echo "Setting RAM to $RAM MiB."
349
+    [ "$BALLOONING" == 1 ] && RAM_MIN=$(($RAM / 2)) || RAM_MIN=$RAM
350
+    xe vm-memory-limits-set static-min=16MiB static-max=${RAM}MiB \
351
+                            dynamic-min=${RAM_MIN}MiB dynamic-max=${RAM}MiB \
352
+                            uuid="$v"
353
+  fi
354
+}
355
+
356
+
357
+# Make the VM auto-start on server boot.
358
+set_auto_start()
359
+{
360
+  local v="$1"
361
+  xe vm-param-set uuid="$v" other-config:auto_poweron=true
362
+}
363
+
364
+
365
+set_all()
366
+{
367
+  local v="$1"
368
+  set_kernel_params "$v"
369
+  set_memory "$v"
370
+  set_auto_start "$v"
371
+  label_system_disk "$v"
372
+  create_gi_vif "$v"
373
+  create_vm_vif "$v"
374
+  create_management_vif "$v"
375
+  create_public_vif "$v"
376
+}
377
+
378
+
379
+log_vifs()
380
+{
381
+  local v="$1"
382
+
383
+  (IFS=,
384
+   for vif in $(xe_min vif-list vm-uuid="$v")
385
+   do
386
+    dev=$(xe_min vif-list uuid="$vif" params=device)
387
+    mac=$(xe_min vif-list uuid="$vif" params=MAC | sed -e 's/:/-/g')
388
+    echo "eth$dev has MAC $mac."
389
+   done
390
+   unset IFS) | sort
391
+}
392
+
393
+
394
+destroy_vifs()
395
+{
396
+  local v="$1"
397
+  IFS=,
398
+  for vif in $(xe_min vif-list vm-uuid="$v")
399
+  do
400
+    xe vif-destroy uuid="$vif"
401
+  done
402
+  unset IFS
403
+}
404
+
405
+
406
+get_params "$@"
407
+
408
+thisdir=$(dirname "$0")
409
+
410
+if [ "$FROM_TEMPLATE" ]
411
+then
412
+  template_uuid=$(find_template)
413
+  name=$(xe_min template-list params=name-label uuid="$template_uuid")
414
+  echo -n "Cloning $name... "
415
+  vm_uuid=$(xe vm-clone vm="$template_uuid" new-name-label="$name")
416
+  xe vm-param-set is-a-template=false uuid="$vm_uuid"
417
+  echo $vm_uuid.
418
+
419
+  destroy_vifs "$vm_uuid"
420
+  set_all "$vm_uuid"
421
+else
422
+  if [ ! -f "$VPX_FILE" ]
423
+  then
424
+      # Search $thisdir/$VPX_FILE too.  In particular, this is used when
425
+      # installing the VPX from the supp-pack, because we want to be able to
426
+      # invoke this script from the RPM and the firstboot script.
427
+      if [ -f "$thisdir/$VPX_FILE" ]
428
+      then
429
+          VPX_FILE="$thisdir/$VPX_FILE"
430
+      else
431
+          echo "$VPX_FILE does not exist." >&2
432
+          exit 1
433
+      fi
434
+  fi
435
+
436
+  echo "Found OS-VPX File: $VPX_FILE. "
437
+
438
+  dest_sr=$(get_dest_sr)
439
+
440
+  echo -n "Installing $NAME... "
441
+  vm_uuid=$(xe vm-import filename=$VPX_FILE sr-uuid="$dest_sr")
442
+  echo $vm_uuid.
443
+
444
+  renumber_system_disk "$vm_uuid"
445
+
446
+  nl=$(xe_min vm-list params=name-label uuid=$vm_uuid)
447
+  xe vm-param-set \
448
+    "name-label=${nl/ import/}" \
449
+    other-config:os-vpx=true \
450
+    uuid=$vm_uuid
451
+
452
+  set_all "$vm_uuid"
453
+  create_data_disk "$vm_uuid"
454
+
455
+  if [ "$AS_TEMPLATE" ]
456
+  then
457
+    xe vm-param-set uuid="$vm_uuid" is-a-template=true \
458
+                                    other-config:instant=true
459
+    echo -n "Installing VPX from template... "
460
+    vm_uuid=$(xe vm-clone vm="$vm_uuid" new-name-label="${nl/ import/}")
461
+    xe vm-param-set is-a-template=false uuid="$vm_uuid"
462
+    echo "$vm_uuid."
463
+  fi
464
+fi
465
+
466
+
467
+log_vifs "$vm_uuid"
468
+
469
+echo -n "Starting VM... "
470
+xe vm-start uuid=$vm_uuid
471
+echo "done."
472
+
473
+
474
+show_ip()
475
+{
476
+  ip_addr=$(echo "$1" | sed -n "s,^.*"$2"/ip: \([^;]*\).*$,\1,p")
477
+  echo -n "IP address for $3: "
478
+  if [ "$ip_addr" = "" ]
479
+  then
480
+    echo "did not appear."
481
+  else
482
+    echo "$ip_addr."
483
+  fi
484
+}
485
+
486
+
487
+if [ "$WAIT_FOR_NETWORK" ]
488
+then
489
+  echo "Waiting for network configuration... "
490
+  i=0
491
+  while [ $i -lt 600 ]
492
+  do
493
+    ip=$(xe_min vm-list params=networks uuid=$vm_uuid)
494
+    if [ "$ip" != "<not in database>" ]
495
+    then
496
+      show_ip "$ip" "1" "$BRIDGE_M"
497
+      if [[ $BRIDGE_P ]]
498
+      then
499
+        show_ip "$ip" "2" "$BRIDGE_P"
500
+      fi
501
+      echo "Installation complete."
502
+      exit 0
503
+    fi
504
+    sleep 10
505
+    let i=i+1
506
+  done
507
+fi
0 508
new file mode 100755
... ...
@@ -0,0 +1,366 @@
0
+#!/bin/bash
1
+#
2
+# Copyright (c) 2011 Citrix Systems, Inc.
3
+# Copyright 2011 OpenStack LLC.
4
+# Copyright (C) 2011 Nicira, Inc
5
+# All Rights Reserved.
6
+#
7
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
8
+#    not use this file except in compliance with the License. You may obtain
9
+#    a copy of the License at
10
+#
11
+#         http://www.apache.org/licenses/LICENSE-2.0
12
+#
13
+#    Unless required by applicable law or agreed to in writing, software
14
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+#    License for the specific language governing permissions and limitations
17
+#    under the License.
18
+#
19
+
20
+set -eu
21
+
22
+set -o xtrace
23
+
24
+VBOX_IMG=/output/packages/vbox-img
25
+
26
+usage() {
27
+    cat >&2 <<EOF
28
+$0 -o <output filenames> -t <types> -x <xml files> <fs-staging-dir> <fs-size-MiB> <tmpdir>
29
+  -o: Colon-separated list of output filenames (one for each type).
30
+  -p: Create a disk label and partition within the output image
31
+  -t: Colon-separated list of types of output file.  xva and ovf supported.
32
+  -x: XML filenames (one for each type)
33
+
34
+EOF
35
+    exit 1
36
+}
37
+
38
+# parse cmdline
39
+
40
+OPT_USE_PARTITION=
41
+OPT_TYPES=
42
+OPT_OUTPUT_FILES=
43
+OPT_XML_FILES=
44
+
45
+while getopts o:pt:x: o
46
+do case "$o" in
47
+    o)    OPT_OUTPUT_FILES=$(echo "$OPTARG" | sed -e 's/\s*:\s*/ /g')
48
+        ;;
49
+    p)    OPT_USE_PARTITION=1
50
+        ;;
51
+    t)    OPT_TYPES=$(echo "$OPTARG" | sed -e 's/\s*:\s*/ /g')
52
+        ;;
53
+    x)    OPT_XML_FILES=$(echo "$OPTARG" | sed -e 's/\s*:\s*/ /g')
54
+        ;;
55
+    [?])  usage
56
+        ;;
57
+    esac
58
+done
59
+shift $((OPTIND-1))
60
+
61
+[ $# -ne 3 ] && usage
62
+FS_STAGING="$1"
63
+FS_SIZE_MIB="$2"
64
+TMPDIR="$3"
65
+
66
+if [ "$UID" = "0" ]
67
+then
68
+  SUDO=
69
+else
70
+  SUDO=sudo
71
+fi
72
+
73
+if [ "$FS_SIZE_MIB" = "0" ]
74
+then
75
+    # Just create a dummy file.  This allows developers to bypass bits of
76
+    # the build by setting the size to 0.
77
+    touch $OPT_OUTPUT_FILES
78
+    exit 0
79
+fi
80
+
81
+# create temporary files and dirs
82
+FS_TMPFILE=$(mktemp "$TMPDIR/mkxva-fsimg-XXXXX")
83
+XVA_TARBALL_STAGING=$(mktemp -d "$TMPDIR/mkxva-tarball-staging-XXXXX")
84
+OVF_STAGING=$(mktemp -d "$TMPDIR/mkxva-ovf-staging-XXXXX")
85
+
86
+# Find udevsettle and udevtrigger on this installation
87
+if [ -x "/sbin/udevsettle" ] ; then
88
+    UDEVSETTLE="/sbin/udevsettle --timeout=30"
89
+elif [ -x "/sbin/udevadm" ] ; then
90
+    UDEVSETTLE='/sbin/udevadm settle'
91
+else
92
+    UDEVSETTLE='/bin/true'
93
+fi
94
+
95
+if [ -x "/sbin/udevtrigger" ] ; then
96
+    UDEVTRIGGER=/sbin/udevtrigger
97
+elif [ -x "/sbin/udevadm" ] ; then
98
+    UDEVTRIGGER='/sbin/udevadm trigger'
99
+else
100
+    UDEVTRIGGER=
101
+fi
102
+
103
+# CLEAN_ variables track devices and mounts that must be taken down
104
+# no matter how the script exits.  Loop devices are vulnerable to
105
+# exhaustion so we make every effort to remove them
106
+
107
+CLEAN_KPARTX=
108
+CLEAN_LOSETUP=
109
+CLEAN_MOUNTPOINT=
110
+
111
+cleanup_devices () {
112
+    if [ -n "$CLEAN_MOUNTPOINT" ] ; then
113
+        echo "Mountpoint $CLEAN_MOUNTPOINT removed on abnormal exit"
114
+        $SUDO umount "$CLEAN_MOUNTPOINT" || echo "umount failed"
115
+        rmdir "$CLEAN_MOUNTPOINT" || echo "rmdir failed"
116
+    fi
117
+    if [ -n "$CLEAN_KPARTX" ] ; then
118
+        echo "kpartx devices for $CLEAN_KPARTX removed on abnormal exit"
119
+        $SUDO kpartx -d "$CLEAN_KPARTX" || echo "kpartx -d failed"
120
+    fi
121
+    if [ -n "$CLEAN_LOSETUP" ] ; then
122
+        echo "Loop device $CLEAN_LOSETUP removed on abnormal exit"
123
+        $SUDO losetup -d "$CLEAN_LOSETUP" # Allow losetup errors to propagate
124
+    fi
125
+}
126
+
127
+trap "cleanup_devices" EXIT
128
+
129
+make_fs_inner () {
130
+    local staging="$1"
131
+    local output="$2"
132
+    local options="$3"
133
+    CLEAN_MOUNTPOINT=$(mktemp -d "$TMPDIR/mkfs-XXXXXX")
134
+
135
+    # copy staging dir contents to fs image
136
+    $SUDO mount $options "$output" "$CLEAN_MOUNTPOINT"
137
+    $SUDO tar -C "$staging" -c . | tar -C "$CLEAN_MOUNTPOINT" -x
138
+    $SUDO umount "$CLEAN_MOUNTPOINT"
139
+    rmdir "$CLEAN_MOUNTPOINT"
140
+    CLEAN_MOUNTPOINT=
141
+}
142
+
143
+# Turn a staging dir into an ext3 filesystem within a partition
144
+make_fs_in_partition () {
145
+    local staging="$1"
146
+    local output="$2"
147
+
148
+    # create new empty disk
149
+    dd if=/dev/zero of="$output" bs=1M count=$FS_SIZE_MIB
150
+    # Set up a loop device on the empty disk image
151
+    local loopdevice=$($SUDO losetup -f)
152
+    $SUDO losetup "$loopdevice" "$output"
153
+    CLEAN_LOSETUP="$loopdevice"
154
+    # Create a partition table and single partition.
155
+    # Start partition at sector 63 to allow space for grub
156
+    cat <<EOF
157
+Errors from sfdisk below are expected because the new disk is uninitialised
158
+  Expecting: sfdisk: ERROR: sector 0 does not have an msdos signature
159
+  Expecting: /dev/loop0: unrecognized partition table type
160
+EOF
161
+    $SUDO sfdisk -uS "$CLEAN_LOSETUP" <<EOF
162
+63 - - *
163
+EOF
164
+
165
+    # kpartx creates a device for the new partition
166
+    # in the form /dev/mapper/loop1p1
167
+    $SUDO kpartx -av "$CLEAN_LOSETUP"
168
+    CLEAN_KPARTX="$CLEAN_LOSETUP"
169
+    # Wait for the device to appear
170
+    $UDEVTRIGGER
171
+    $UDEVSETTLE  || echo "udev settle command return code non-zero"
172
+    # Infer the name of the partition device
173
+    local partition="${CLEAN_LOSETUP/dev/dev/mapper}p1"
174
+    # Set permissive privileges on the device
175
+    $SUDO chmod 0777 "$partition"
176
+    # Make an ext3 filesystem on the partition
177
+    /sbin/mkfs.ext3 -I 128 -m0 -F "$partition"
178
+    /sbin/e2label "$partition" vpxroot
179
+    make_fs_inner "$staging" "$partition" ""
180
+    
181
+    # Now run grub on the image we've created
182
+    CLEAN_MOUNTPOINT=$(mktemp -d "$TMPDIR/mkfs-XXXXXX")
183
+
184
+    # copy Set up[ grub files prior to installing grub within the image
185
+    $SUDO mount "$partition" "$CLEAN_MOUNTPOINT"
186
+    $SUDO cp $CLEAN_MOUNTPOINT/usr/share/grub/i386-redhat/* "$CLEAN_MOUNTPOINT/boot/grub"
187
+    kernel_version=$($SUDO chroot "$CLEAN_MOUNTPOINT" rpm -qv kernel | sed -e 's/kernel-//')
188
+    kernel_version_xen=$($SUDO chroot "$CLEAN_MOUNTPOINT" rpm -qv kernel-xen | sed -e 's/kernel-xen-//')
189
+    $SUDO cat > "$CLEAN_MOUNTPOINT/boot/grub/grub.conf" <<EOF
190
+default 0
191
+timeout 2
192
+
193
+title vmlinuz-$kernel_version (HVM)
194
+        root (hd0,0)
195
+        kernel /boot/vmlinuz-$kernel_version ro root=LABEL=vpxroot
196
+        initrd /boot/initrd-$kernel_version.img
197
+
198
+title vmlinuz-${kernel_version_xen}xen (PV)
199
+        root (hd0,0)
200
+        kernel /boot/vmlinuz-${kernel_version_xen}xen ro root=LABEL=vpxroot console=xvc0
201
+        initrd /boot/initrd-${kernel_version_xen}xen.img
202
+EOF
203
+
204
+    $SUDO umount "$CLEAN_MOUNTPOINT"
205
+    CLEAN_MOUNTPOINT=
206
+    
207
+    # Grub expects a disk with name /dev/xxxx with a first partition
208
+    # named /dev/xxxx1, so we give it what it wants using symlinks
209
+    # Note: /dev is linked to the real /dev of the build machine, so
210
+    # must be cleaned up
211
+    local disk_name="/dev/osxva$$bld"
212
+    local disk_part1_name="${disk_name}1"
213
+    rm -f "$disk_name"
214
+    rm -f "$disk_part1_name"
215
+    ln -s "$CLEAN_LOSETUP" "$disk_name"
216
+    ln -s "$partition" "$disk_part1_name"
217
+    
218
+    # Feed commands into the grub shell to setup the disk
219
+    grub --no-curses --device-map=/dev/null <<EOF
220
+device (hd0) $disk_name
221
+setup (hd0) (hd0,0)
222
+quit
223
+EOF
224
+    
225
+    # Cleanup
226
+    rm -f "$disk_name"
227
+    rm -f "$disk_part1_name"
228
+    $SUDO kpartx -dv "$CLEAN_KPARTX"
229
+    CLEAN_KPARTX=
230
+    $SUDO losetup -d "$CLEAN_LOSETUP"
231
+    CLEAN_LOSETUP=
232
+}
233
+
234
+# turn a staging dir into an ext3 filesystem image
235
+make_fs () {
236
+    local staging="$1"
237
+    local output="$2"
238
+
239
+    # create new empty fs
240
+    dd if=/dev/zero of="$output" bs=1M count=0 seek=$FS_SIZE_MIB
241
+    /sbin/mkfs.ext3 -m0 -F "$output"
242
+    /sbin/e2label "$output" vpxroot
243
+    make_fs_inner "$staging" "$output" "-oloop"
244
+}
245
+
246
+
247
+# split a virtual disk image into the format expected inside an xva file
248
+splitvdi () {
249
+    local diskimg="$1"
250
+    local outputdir="$2"
251
+    local rio="$3"
252
+
253
+    local n_bytes=$(stat --printf=%s "$diskimg")
254
+    local n_meg=$((($n_bytes+$((1024*1024 -1)))/$((1024*1024))))
255
+    local i=0
256
+    while [ $i -lt $n_meg ] ; do 
257
+	if [ $rio -eq 0 ] ; then
258
+		local file="$outputdir"/chunk-$(printf "%08d" $i)
259
+		dd if="$diskimg" of="$file" skip=$i bs=1M count=1 2>/dev/null
260
+		gzip "$file"
261
+	else
262
+		local file="$outputdir"/$(printf "%08d" $i)
263
+	        dd if="$diskimg" of="$file" skip=$i bs=1M count=1 2>/dev/null
264
+		local chksum=$(sha1sum -b "$file")
265
+		echo -n "${chksum/ */}" > "$file.checksum"
266
+	fi
267
+	i=$(($i + 1))
268
+    done
269
+}
270
+
271
+if [ -n "$OPT_USE_PARTITION" ] ; then
272
+    make_fs_in_partition "$FS_STAGING" "$FS_TMPFILE"
273
+else
274
+    make_fs "$FS_STAGING" "$FS_TMPFILE"
275
+fi
276
+
277
+VDI_SIZE=$(stat --format=%s "$FS_TMPFILE")
278
+
279
+make_xva () {
280
+    local output_file="$1"
281
+    local xml_file="$2"
282
+    local subdir
283
+    local rio
284
+
285
+    if [[ `cat $xml_file` =~ "<member>\s*<name>class</name>\s*<value>VDI</value>\s*</member>\s*<member>\s*<name>id</name>\s*<value>(Ref:[0-9]+)</value>" ]]
286
+    then
287
+        # it's a rio style xva
288
+        subdir="${BASH_REMATCH[1]}";
289
+        rio=1
290
+    else
291
+        # it's a geneva style xva
292
+        subdir="xvda"
293
+        rio=0
294
+    fi
295
+
296
+    cp "$xml_file" "$XVA_TARBALL_STAGING"/ova.xml
297
+    sed -i -e "s/@VDI_SIZE@/$VDI_SIZE/" "$XVA_TARBALL_STAGING"/ova.xml
298
+    mkdir "$XVA_TARBALL_STAGING/$subdir"
299
+    splitvdi "$FS_TMPFILE" "$XVA_TARBALL_STAGING/$subdir" "$rio"
300
+    TARFILE_MEMBERS=$(cd "$XVA_TARBALL_STAGING" && echo ova.xml $subdir/*)
301
+    tar -C "$XVA_TARBALL_STAGING" --format=v7 -c $TARFILE_MEMBERS -f "$output_file.tmp"
302
+    mv "$output_file.tmp" "$output_file"
303
+}
304
+
305
+make_ovf () {
306
+    local output_dir="$1"
307
+    local xml_file="$2"
308
+    local output_base=$(basename "$output_dir")
309
+    local disk="$output_dir/${output_base}.vmdk"
310
+    local manifest="$output_dir/${output_base}.mf"
311
+    local ovf="$output_dir/${output_base}.ovf"
312
+
313
+    mkdir -p "$output_dir"
314
+    rm -f "$disk"
315
+    $VBOX_IMG convert --srcfilename="$FS_TMPFILE" --dstfilename="$disk" \
316
+        --srcformat RAW --dstformat VMDK --variant Stream
317
+    chmod 0644 "$disk"
318
+
319
+    local n_bytes=$(stat --printf=%s "$disk")
320
+    cp "$xml_file" "$ovf"
321
+    sed -i -e "s/@MKXVA_DISK_FULLSIZE@/$VDI_SIZE/" "$ovf"
322
+    sed -i -e "s/@MKXVA_DISK_SIZE@/$n_bytes/" "$ovf"
323
+    sed -i -e "s/@MKXVA_DISK_MIB_SIZE@/$FS_SIZE_MIB/" "$ovf"
324
+    sed -i -e "s/@MKXVA_DISK_FILENAME@/${output_base}.vmdk/" "$ovf"
325
+
326
+    for to_sign in "$ovf" "$disk"
327
+    do
328
+	local sha1_sum=$(sha1sum "$to_sign" | cut -d' ' -f1)
329
+	echo "SHA1($(basename "$to_sign"))= $sha1_sum" >> $manifest
330
+    done
331
+}
332
+
333
+output_files="$OPT_OUTPUT_FILES"
334
+xml_files="$OPT_XML_FILES"
335
+# Iterate through the type list creating the relevant VMs
336
+for create_type in $OPT_TYPES
337
+do
338
+    # Shift one parameter from the front of the lists
339
+    create_output_file="${output_files%% *}"
340
+    output_files="${output_files#* }"
341
+    create_xml_file="${xml_files%% *}"
342
+    xml_files="${xml_files#* }"
343
+    echo "Creating $create_type appliance $create_output_file using metadata file $create_xml_file"
344
+
345
+    case "$create_type" in
346
+	xva)
347
+	    make_xva "$create_output_file" "$create_xml_file"
348
+	    ;;
349
+	ovf)
350
+	    make_ovf "$create_output_file" "$create_xml_file"
351
+	    ;;
352
+	*)
353
+	    echo "Unknown VM type '$create_type'"
354
+	    exit 1
355
+	    ;;
356
+    esac
357
+
358
+done
359
+
360
+
361
+# cleanup
362
+if [ -z "${DO_NOT_CLEANUP:-}" ] ; then 
363
+    rm -rf "$XVA_TARBALL_STAGING"
364
+    rm -f "$FS_TMPFILE"
365
+fi
0 366
new file mode 100755
... ...
@@ -0,0 +1,102 @@
0
+#!/bin/bash
1
+#
2
+# Copyright (c) 2011 Citrix Systems, Inc.
3
+# Copyright 2011 OpenStack LLC.
4
+# Copyright (C) 2011 Nicira, Inc
5
+# All Rights Reserved.
6
+#
7
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
8
+#    not use this file except in compliance with the License. You may obtain
9
+#    a copy of the License at
10
+#
11
+#         http://www.apache.org/licenses/LICENSE-2.0
12
+#
13
+#    Unless required by applicable law or agreed to in writing, software
14
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+#    License for the specific language governing permissions and limitations
17
+#    under the License.
18
+#
19
+
20
+remove_data=
21
+if [ "$1" = "--remove-data" ]
22
+then
23
+  remove_data=1
24
+fi
25
+
26
+set -eu
27
+
28
+xe_min()
29
+{
30
+  local cmd="$1"
31
+  shift
32
+  /opt/xensource/bin/xe "$cmd" --minimal "$@"
33
+}
34
+
35
+destroy_vdi()
36
+{
37
+  local vbd_uuid="$1"
38
+  local type=$(xe_min vbd-list uuid=$vbd_uuid params=type)
39
+  local dev=$(xe_min vbd-list uuid=$vbd_uuid params=userdevice)
40
+  local vdi_uuid=$(xe_min vbd-list uuid=$vbd_uuid params=vdi-uuid)
41
+
42
+  if [ "$type" = 'Disk' ] && [ "$dev" != 'xvda' ] && [ "$dev" != '0' ]
43
+  then
44
+    echo -n "Destroying data disk... "
45
+    xe vdi-destroy uuid=$vdi_uuid
46
+    echo "done."
47
+  fi
48
+}
49
+
50
+uninstall()
51
+{
52
+  local vm_uuid="$1"
53
+  local power_state=$(xe_min vm-list uuid=$vm_uuid params=power-state)
54
+
55
+  if [ "$power_state" != "halted" ]
56
+  then
57
+    echo -n "Shutting down VM... "
58
+    xe vm-shutdown vm=$vm_uuid force=true
59
+    echo "done."
60
+  fi
61
+
62
+  if [ "$remove_data" = "1" ]
63
+  then
64
+    for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g')
65
+    do
66
+      destroy_vdi "$v"
67
+    done
68
+  fi
69
+
70
+  echo -n "Deleting VM... "
71
+  xe vm-uninstall vm=$vm_uuid force=true >/dev/null
72
+  echo "done."
73
+}
74
+
75
+uninstall_template()
76
+{
77
+  local vm_uuid="$1"
78
+
79
+  if [ "$remove_data" = "1" ]
80
+  then
81
+    for v in $(xe_min vbd-list vm-uuid=$vm_uuid | sed -e 's/,/ /g')
82
+    do
83
+      destroy_vdi "$v"
84
+    done
85
+  fi
86
+
87
+  echo -n "Deleting template... "
88
+  xe template-uninstall template-uuid=$vm_uuid force=true >/dev/null
89
+  echo "done."
90
+}
91
+
92
+
93
+for u in $(xe_min vm-list other-config:os-vpx=true | sed -e 's/,/ /g')
94
+do
95
+  uninstall "$u"
96
+done
97
+
98
+for u in $(xe_min template-list other-config:os-vpx=true | sed -e 's/,/ /g')
99
+do
100
+  uninstall_template "$u"
101
+done
0 102
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+127.0.0.1   localhost
1
+127.0.0.1   %HOSTNAME%
2
+::1     localhost ip6-localhost ip6-loopback
3
+fe00::0     ip6-localnet
4
+ff00::0     ip6-mcastprefix
5
+ff02::1     ip6-allnodes
6
+ff02::2     ip6-allrouters
7
+
0 8
new file mode 100644
... ...
@@ -0,0 +1,21 @@
0
+auto lo
1
+iface lo inet loopback
2
+
3
+auto eth0
4
+iface eth0 inet dhcp
5
+
6
+auto eth1
7
+iface eth1 inet static
8
+        netmask @ETH1_NETMASK@
9
+post-up ethtool -K eth1 tx off
10
+post-up ifconfig eth1 up
11
+
12
+auto eth2
13
+iface eth2 inet static
14
+        address @ETH2_IP@
15
+        netmask @ETH2_NETMASK@
16
+
17
+auto eth3
18
+iface eth3 inet static
19
+        address @ETH3_IP@
20
+        netmask @ETH3_NETMASK@
0 21
new file mode 100644
... ...
@@ -0,0 +1,6 @@
0
+default 0
1
+
2
+title default
3
+        root (hd0,0)
4
+        kernel /boot/vmlinuz-@KERNEL_VERSION@ ro root=LABEL=vpxroot console=xvc0
5
+        initrd /boot/initrd.img-@KERNEL_VERSION@
0 6
new file mode 100644
... ...
@@ -0,0 +1,14 @@
0
+<?xml version="1.0" ?>
1
+<appliance version="0.1">
2
+        <vm name="vm">
3
+                <label>
4
+                        @PRODUCT_BRAND@ @PRODUCT_VERSION@-@BUILD_NUMBER@
5
+                </label>
6
+                <shortdesc></shortdesc>
7
+                <config mem_set="671088640" vcpus="1"/>
8
+                <hacks is_hvm="false"/>
9
+                <vbd device="xvda" function="root" mode="w" vdi="vdi_xvda"/>
10
+        </vm>
11
+        <vdi name="vdi_xvda" size="@VDI_SIZE@" source="file://xvda" type="dir-gzipped-chunks" variety="system"/>
12
+</appliance>
13
+