Generalize xen network config

Allow dhcp for IP addresses.
dhclient3 bug workaround.
Refactor code to improve network creation logic.

Change-Id: Ia3e2e65bbe8b68cf4832595cb7c283c3dc84db19
diff --git a/tools/xen/build_domU.sh b/tools/xen/build_domU.sh
index cd28f15..5ea03da 100755
--- a/tools/xen/build_domU.sh
+++ b/tools/xen/build_domU.sh
@@ -37,51 +37,85 @@
 fi
 
 # Helper to create networks
+# Uses echo trickery to return network uuid
 function create_network() {
-    if ! xe network-list | grep bridge | grep -q $1; then
-        echo "Creating bridge $1"
-        xe network-create name-label=$1
+    br=$1
+    dev=$2
+    vlan=$3
+    netname=$4
+    if [ -z $br ]
+    then
+        pif=$(xe pif-list --minimal device=$dev VLAN=$vlan)
+        if [ -z $pif ]
+        then
+            net=$(xe network-create name-label=$netname)
+        else
+            net=$(xe network-list --minimal PIF-uuids=$pif)
+        fi
+        echo $net
+        return 0
+    fi
+    if [ ! $(xe network-list --minimal params=bridge | grep -w --only-matching $br) ]
+    then
+        echo "Specified bridge $br does not exist"
+        echo "If you wish to use defaults, please keep the bridge name empty"
+        exit 1
+    else
+        net=$(xe network-list --minimal bridge=$br)
+        echo $net
+    fi
+}
+
+function errorcheck() {
+    rc=$?
+    if [ $rc -ne 0 ]
+    then
+        exit $rc
     fi
 }
 
 # Create host, vm, mgmt, pub networks
-create_network xapi0
-create_network $VM_BR
-create_network $MGT_BR
-create_network $PUB_BR
-
-# Get the uuid for our physical (public) interface
-PIF=`xe pif-list --minimal device=eth0`
-
-# Create networks/bridges for vm and management
-VM_NET=`xe network-list --minimal bridge=$VM_BR`
-MGT_NET=`xe network-list --minimal bridge=$MGT_BR`
+VM_NET=$(create_network "$VM_BR" "$VM_DEV" "$VM_VLAN" "vmbr")
+errorcheck
+MGT_NET=$(create_network "$MGT_BR" "$MGT_DEV" "$MGT_VLAN" "mgtbr")
+errorcheck
+PUB_NET=$(create_network "$PUB_BR" "$PUB_DEV" "$PUB_VLAN" "pubbr")
+errorcheck
 
 # Helper to create vlans
 function create_vlan() {
-    pif=$1
+    dev=$1
     vlan=$2
     net=$3
-    if ! xe vlan-list | grep tag | grep -q $vlan; then
-        xe vlan-create pif-uuid=$pif vlan=$vlan network-uuid=$net
+    # VLAN -1 refers to no VLAN (physical network)
+    if [ $vlan -eq -1 ]
+    then
+        return
+    fi
+    if [ -z $(xe vlan-list --minimal tag=$vlan) ]
+    then
+        pif=$(xe pif-list --minimal network-uuid=$net)
+        # We created a brand new network this time
+        if [ -z $pif ]
+        then
+            pif=$(xe pif-list --minimal device=$dev VLAN=-1)
+            xe vlan-create pif-uuid=$pif vlan=$vlan network-uuid=$net
+        else
+            echo "VLAN does not exist but PIF attached to this network"
+            echo "How did we reach here?"
+            exit 1
+        fi
     fi
 }
 
 # Create vlans for vm and management
-create_vlan $PIF $VM_VLAN $VM_NET
-create_vlan $PIF $MGT_VLAN $MGT_NET
+create_vlan $PUB_DEV $PUB_VLAN $PUB_NET
+create_vlan $VM_DEV $VM_VLAN $VM_NET
+create_vlan $MGT_DEV $MGT_VLAN $MGT_NET
 
 # dom0 ip
 HOST_IP=${HOST_IP:-`ifconfig xenbr0 | grep "inet addr" | cut -d ":" -f2 | sed "s/ .*//"`}
 
-# Setup host-only nat rules
-HOST_NET=169.254.0.0/16
-if ! iptables -L -v -t nat | grep -q $HOST_NET; then
-    iptables -t nat -A POSTROUTING -s $HOST_NET -j SNAT --to-source $HOST_IP
-    iptables -I FORWARD 1 -s $HOST_NET -j ACCEPT
-    /etc/init.d/iptables save
-fi
-
 # Set up ip forwarding
 if ! grep -q "FORWARD_IPV4=YES" /etc/sysconfig/network; then
     # FIXME: This doesn't work on reboot!
@@ -139,6 +173,15 @@
 fi
 
 # Start guest
+if [ -z $VM_BR ]; then
+    VM_BR=$(xe network-list --minimal uuid=$VM_NET params=bridge)
+fi
+if [ -z $MGT_BR ]; then
+    MGT_BR=$(xe network-list --minimal uuid=$MGT_NET params=bridge)
+fi
+if [ -z $PUB_BR ]; then
+    PUB_BR=$(xe network-list --minimal uuid=$PUB_NET params=bridge)
+fi
 $TOP_DIR/scripts/install-os-vpx.sh -f $XVA -v $VM_BR -m $MGT_BR -p $PUB_BR
 
 # If we have copied our ssh credentials, use ssh to monitor while the installation runs
diff --git a/tools/xen/build_xva.sh b/tools/xen/build_xva.sh
index e4de2a1..c8721aa 100755
--- a/tools/xen/build_xva.sh
+++ b/tools/xen/build_xva.sh
@@ -62,7 +62,7 @@
 mkdir -p $XVA_DIR
 
 # Path to xva
-XVA=$XVA_DIR/$GUEST_NAME.xva 
+XVA=$XVA_DIR/$GUEST_NAME.xva
 
 # Setup fake grub
 rm -rf $STAGING_DIR/boot/grub/
@@ -102,6 +102,8 @@
 
 # Run devstack on launch
 cat <<EOF >$STAGING_DIR/etc/rc.local
+# network restart required for getting the right gateway
+/etc/init.d/networking restart
 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
@@ -122,12 +124,36 @@
 # 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
+if [ $VM_IP == "dhcp" ]; then
+    echo 'eth1 on dhcp'
+    sed -e "s,iface eth1 inet static,iface eth1 inet dhcp,g" -i $INTERFACES
+    sed -e '/@ETH1_/d' -i $INTERFACES
+else
+    sed -e "s,@ETH1_IP@,$VM_IP,g" -i $INTERFACES
+    sed -e "s,@ETH1_NETMASK@,$VM_NETMASK,g" -i $INTERFACES
+fi
+
+if [ $MGT_IP == "dhcp" ]; then
+    echo 'eth2 on dhcp'
+    sed -e "s,iface eth2 inet static,iface eth2 inet dhcp,g" -i $INTERFACES
+    sed -e '/@ETH2_/d' -i $INTERFACES
+else
+    sed -e "s,@ETH2_IP@,$MGT_IP,g" -i $INTERFACES
+    sed -e "s,@ETH2_NETMASK@,$MGT_NETMASK,g" -i $INTERFACES
+fi
+
+if [ $PUB_IP == "dhcp" ]; then
+    echo 'eth3 on dhcp'
+    sed -e "s,iface eth3 inet static,iface eth3 inet dhcp,g" -i $INTERFACES
+    sed -e '/@ETH3_/d' -i $INTERFACES
+else
+    sed -e "s,@ETH3_IP@,$PUB_IP,g" -i $INTERFACES
+    sed -e "s,@ETH3_NETMASK@,$PUB_NETMASK,g" -i $INTERFACES
+fi
+
+if [ -h $STAGING_DIR/sbin/dhclient3 ]; then
+    rm -f $STAGING_DIR/sbin/dhclient3
+fi
 
 # Gracefully cp only if source file/dir exists
 function cp_it {
@@ -151,7 +177,7 @@
 #!/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
+UPLOAD_LEGACY_TTY=yes HOST_IP=$PUB_IP VIRT_DRIVER=xenserver FORCE=yes MULTI_HOST=1 HOST_IP_IFACE=$HOST_IP_IFACE $STACKSH_PARAMS ./stack.sh
 EOF
 chmod 755 $STAGING_DIR/opt/stack/run.sh
 
diff --git a/tools/xen/templates/interfaces.in b/tools/xen/templates/interfaces.in
index 49c3d68..e315a8c 100644
--- a/tools/xen/templates/interfaces.in
+++ b/tools/xen/templates/interfaces.in
@@ -1,8 +1,15 @@
 auto lo
 iface lo inet loopback
 
-auto eth0
-iface eth0 inet dhcp
+# If eth3 is static, the order should not matter
+# and eth0 will have the default gateway. If not,
+# we probably want the default gateway to be
+# what is on the public interface. Hence changed
+# the order here.
+auto eth3
+iface eth3 inet static
+        address @ETH3_IP@
+        netmask @ETH3_NETMASK@
 
 auto eth1
 iface eth1 inet static
@@ -15,7 +22,5 @@
         address @ETH2_IP@
         netmask @ETH2_NETMASK@
 
-auto eth3
-iface eth3 inet static
-        address @ETH3_IP@
-        netmask @ETH3_NETMASK@
+auto eth0
+iface eth0 inet dhcp
diff --git a/tools/xen/xenrc b/tools/xen/xenrc
index 246ac16..73f9c02 100644
--- a/tools/xen/xenrc
+++ b/tools/xen/xenrc
@@ -9,24 +9,31 @@
 # VM Password
 GUEST_PASSWORD=${GUEST_PASSWORD:-secrete}
 
-# Our nova host's network info 
+# Host Interface, i.e. the public facing interface on the nova vm
+HOST_IP_IFACE=${HOST_IP_IFACE:-eth0}
+
+# Our nova host's network info
 VM_IP=${VM_IP:-10.255.255.255} # A host-only ip that let's the interface come up, otherwise unused
 MGT_IP=${MGT_IP:-172.16.100.55}
 PUB_IP=${PUB_IP:-192.168.1.55}
 
 # Public network
-PUB_BR=${PUB_BR:-xenbr0}
+PUB_BR=${PUB_BR:-"xenbr0"}
+PUB_DEV=${PUB_DEV:-eth0}
+PUB_VLAN=${PUB_VLAN:--1}
 PUB_NETMASK=${PUB_NETMASK:-255.255.255.0}
 
 # VM network params
 VM_NETMASK=${VM_NETMASK:-255.255.255.0}
-VM_BR=${VM_BR:-xapi1}
+VM_BR=${VM_BR:-""}
 VM_VLAN=${VM_VLAN:-100}
+VM_DEV=${VM_DEV:-eth0}
 
 # MGMT network params
 MGT_NETMASK=${MGT_NETMASK:-255.255.255.0}
-MGT_BR=${MGT_BR:-xapi2}
+MGT_BR=${MGT_BR:-""}
 MGT_VLAN=${MGT_VLAN:-101}
+MGT_DEV=${MGT_DEV:-eth0}
 
 # XVA Directory
 XVA_DIR=${XVA_DIR:-xvas}