Merge "Eradicate last of underscores in options"
diff --git a/clean.sh b/clean.sh
index 395941a..480a812 100755
--- a/clean.sh
+++ b/clean.sh
@@ -15,6 +15,8 @@
 # Import common functions
 source $TOP_DIR/functions
 
+FILES=$TOP_DIR/files
+
 # Load local configuration
 source $TOP_DIR/stackrc
 
@@ -84,6 +86,10 @@
 cleanup_neutron
 cleanup_swift
 
+if is_service_enabled ldap; then
+    cleanup_ldap
+fi
+
 # Do the hypervisor cleanup until this can be moved back into lib/nova
 if [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then
     cleanup_nova_hypervisor
diff --git a/extras.d/70-savanna.sh b/extras.d/70-savanna.sh
index f6881cc..6bbe113 100644
--- a/extras.d/70-savanna.sh
+++ b/extras.d/70-savanna.sh
@@ -14,6 +14,7 @@
     elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
         echo_summary "Configuring Savanna"
         configure_savanna
+        create_savanna_accounts
         if is_service_enabled horizon; then
             configure_savanna_dashboard
         fi
diff --git a/files/apts/general b/files/apts/general
index fcf0b5b..aff687f 100644
--- a/files/apts/general
+++ b/files/apts/general
@@ -20,3 +20,4 @@
 euca2ools # only for testing client
 tar
 python-cmd2 # dist:precise
+python2.7
diff --git a/files/apts/ldap b/files/apts/ldap
index 81a00f2..26f7aef 100644
--- a/files/apts/ldap
+++ b/files/apts/ldap
@@ -1,3 +1,3 @@
 ldap-utils
-slapd # NOPRIME
+slapd
 python-ldap
diff --git a/files/ldap/keystone.ldif.in b/files/ldap/keystone.ldif.in
new file mode 100644
index 0000000..cf51907
--- /dev/null
+++ b/files/ldap/keystone.ldif.in
@@ -0,0 +1,26 @@
+dn: ${BASE_DN}
+objectClass: dcObject
+objectClass: organizationalUnit
+dc: ${BASE_DC}
+ou: ${BASE_DC}
+
+dn: ou=UserGroups,${BASE_DN}
+objectClass: organizationalUnit
+ou: UserGroups
+
+dn: ou=Users,${BASE_DN}
+objectClass: organizationalUnit
+ou: Users
+
+dn: ou=Roles,${BASE_DN}
+objectClass: organizationalUnit
+ou: Roles
+
+dn: ou=Projects,${BASE_DN}
+objectClass: organizationalUnit
+ou: Projects
+
+dn: cn=9fe2ff9ee4384b1894a90878d3e92bab,ou=Roles,${BASE_DN}
+objectClass: organizationalRole
+ou: _member_
+cn: 9fe2ff9ee4384b1894a90878d3e92bab
diff --git a/files/ldap/manager.ldif.in b/files/ldap/manager.ldif.in
index e522150..de3b69d 100644
--- a/files/ldap/manager.ldif.in
+++ b/files/ldap/manager.ldif.in
@@ -1,10 +1,15 @@
 dn: olcDatabase={${LDAP_OLCDB_NUMBER}}hdb,cn=config
 changetype: modify
 replace: olcSuffix
-olcSuffix: dc=openstack,dc=org
+olcSuffix: ${BASE_DN}
 -
 replace: olcRootDN
-olcRootDN: dc=Manager,dc=openstack,dc=org
+olcRootDN: ${MANAGER_DN}
 -
 ${LDAP_ROOTPW_COMMAND}: olcRootPW
 olcRootPW: ${SLAPPASS}
+-
+replace: olcDbIndex
+olcDbIndex: objectClass eq
+olcDbIndex: default pres,eq
+olcDbIndex: cn,sn,givenName,co
diff --git a/files/ldap/openstack.ldif b/files/ldap/openstack.ldif
deleted file mode 100644
index 02caf3f..0000000
--- a/files/ldap/openstack.ldif
+++ /dev/null
@@ -1,26 +0,0 @@
-dn: dc=openstack,dc=org
-dc: openstack
-objectClass: dcObject
-objectClass: organizationalUnit
-ou: openstack
-
-dn: ou=UserGroups,dc=openstack,dc=org
-objectClass: organizationalUnit
-ou: UserGroups
-
-dn: ou=Users,dc=openstack,dc=org
-objectClass: organizationalUnit
-ou: Users
-
-dn: ou=Roles,dc=openstack,dc=org
-objectClass: organizationalUnit
-ou: Roles
-
-dn: ou=Projects,dc=openstack,dc=org
-objectClass: organizationalUnit
-ou: Projects
-
-dn: cn=9fe2ff9ee4384b1894a90878d3e92bab,ou=Roles,dc=openstack,dc=org
-objectClass: organizationalRole
-ou: _member_
-cn: 9fe2ff9ee4384b1894a90878d3e92bab
diff --git a/files/ldap/base-config.ldif b/files/ldap/suse-base-config.ldif.in
similarity index 77%
rename from files/ldap/base-config.ldif
rename to files/ldap/suse-base-config.ldif.in
index 026d8bc..00256ee 100644
--- a/files/ldap/base-config.ldif
+++ b/files/ldap/suse-base-config.ldif.in
@@ -12,8 +12,10 @@
 cn: schema
 
 include: file:///etc/openldap/schema/core.ldif
+include: file:///etc/openldap/schema/cosine.ldif
+include: file:///etc/openldap/schema/inetorgperson.ldif
 
 dn: olcDatabase={1}hdb,cn=config
 objectClass: olcHdbConfig
 olcDbDirectory: /var/lib/ldap
-olcSuffix: dc=openstack,dc=org
+olcSuffix: ${BASE_DN}
diff --git a/functions b/functions
index 5ff4a9b..0280b2b 100644
--- a/functions
+++ b/functions
@@ -729,6 +729,8 @@
     local option=$3
     local value=$4
 
+    [[ -z $section || -z $option ]] && return
+
     if ! grep -q "^\[$section\]" "$file" 2>/dev/null; then
         # Add section at the end
         echo -e "\n[$section]" >>"$file"
diff --git a/lib/cinder b/lib/cinder
index 9288685..ef3bd81 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -237,6 +237,11 @@
         iniset $CINDER_CONF lvmdriver-2 volume_group $VOLUME_GROUP2
         iniset $CINDER_CONF lvmdriver-2 volume_driver cinder.volume.drivers.lvm.LVMISCSIDriver
         iniset $CINDER_CONF lvmdriver-2 volume_backend_name LVM_iSCSI_2
+        # NOTE(mriedem): Work around Cinder "wishlist" bug 1255593
+        if [[ "$CINDER_SECURE_DELETE" == "False" ]]; then
+            iniset $CINDER_CONF lvmdriver-1 volume_clear none
+            iniset $CINDER_CONF lvmdriver-2 volume_clear none
+        fi
     else
         iniset $CINDER_CONF DEFAULT volume_group $VOLUME_GROUP
         iniset $CINDER_CONF DEFAULT volume_name_template ${VOLUME_NAME_PREFIX}%s
diff --git a/lib/config b/lib/config
index 91cefe4..c28072f 100644
--- a/lib/config
+++ b/lib/config
@@ -95,7 +95,7 @@
         /^ *\#/ {
             next
         }
-        /^.+/ {
+        /^[^ \t]+/ {
             split($0, d, " *= *")
             print "iniset " configfile " " section " " d[1] " \"" d[2] "\""
         }
diff --git a/lib/keystone b/lib/keystone
index 6d0c1cd..712a509 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -151,17 +151,17 @@
 
     if is_service_enabled ldap; then
         #Set all needed ldap values
-        iniset $KEYSTONE_CONF ldap password  $LDAP_PASSWORD
-        iniset $KEYSTONE_CONF ldap user "dc=Manager,dc=openstack,dc=org"
-        iniset $KEYSTONE_CONF ldap suffix "dc=openstack,dc=org"
+        iniset $KEYSTONE_CONF ldap password $LDAP_PASSWORD
+        iniset $KEYSTONE_CONF ldap user $LDAP_MANAGER_DN
+        iniset $KEYSTONE_CONF ldap suffix $LDAP_BASE_DN
         iniset $KEYSTONE_CONF ldap use_dumb_member "True"
         iniset $KEYSTONE_CONF ldap user_attribute_ignore "enabled,email,tenants,default_project_id"
         iniset $KEYSTONE_CONF ldap tenant_attribute_ignore "enabled"
         iniset $KEYSTONE_CONF ldap tenant_domain_id_attribute "businessCategory"
         iniset $KEYSTONE_CONF ldap tenant_desc_attribute "description"
-        iniset $KEYSTONE_CONF ldap tenant_tree_dn "ou=Projects,dc=openstack,dc=org"
+        iniset $KEYSTONE_CONF ldap tenant_tree_dn "ou=Projects,$LDAP_BASE_DN"
         iniset $KEYSTONE_CONF ldap user_domain_id_attribute "businessCategory"
-        iniset $KEYSTONE_CONF ldap user_tree_dn "ou=Users,dc=openstack,dc=org"
+        iniset $KEYSTONE_CONF ldap user_tree_dn "ou=Users,$LDAP_BASE_DN"
         iniset $KEYSTONE_CONF DEFAULT member_role_id "9fe2ff9ee4384b1894a90878d3e92bab"
         iniset $KEYSTONE_CONF DEFAULT member_role_name "_member_"
     fi
@@ -337,6 +337,10 @@
 
 # init_keystone() - Initialize databases, etc.
 function init_keystone() {
+    if is_service_enabled ldap; then
+        init_ldap
+    fi
+
     # (Re)create keystone database
     recreate_database keystone utf8
 
diff --git a/lib/ldap b/lib/ldap
index 80992a7..e4bd416 100644
--- a/lib/ldap
+++ b/lib/ldap
@@ -9,68 +9,137 @@
 XTRACE=$(set +o | grep xtrace)
 set +o xtrace
 
+
+LDAP_DOMAIN=${LDAP_DOMAIN:-openstack.org}
+# Make an array of domain components
+DC=(${LDAP_DOMAIN/./ })
+
+# Leftmost domain component used in top-level entry
+LDAP_BASE_DC=${DC[0]}
+
+# Build the base DN
+dn=""
+for dc in ${DC[*]}; do
+    dn="$dn,dc=$dc"
+done
+LDAP_BASE_DN=${dn#,}
+
+LDAP_MANAGER_DN="${LDAP_MANAGER_DN:-cn=Manager,${LDAP_BASE_DN}}"
+LDAP_URL=${LDAP_URL:-ldap://localhost}
+
 LDAP_SERVICE_NAME=slapd
 
+if is_ubuntu; then
+    LDAP_OLCDB_NUMBER=1
+    LDAP_ROOTPW_COMMAND=replace
+elif is_fedora; then
+    LDAP_OLCDB_NUMBER=2
+    LDAP_ROOTPW_COMMAND=add
+elif is_suse; then
+    # SUSE has slappasswd in /usr/sbin/
+    PATH=$PATH:/usr/sbin/
+    LDAP_OLCDB_NUMBER=1
+    LDAP_ROOTPW_COMMAND=add
+    LDAP_SERVICE_NAME=ldap
+fi
+
+
 # Functions
 # ---------
 
+# Perform common variable substitutions on the data files
+# _ldap_varsubst file
+function _ldap_varsubst() {
+    local infile=$1
+    sed -e "
+        s|\${LDAP_OLCDB_NUMBER}|$LDAP_OLCDB_NUMBER|
+        s|\${SLAPPASS}|$SLAPPASS|
+        s|\${LDAP_ROOTPW_COMMAND}|$LDAP_ROOTPW_COMMAND|
+        s|\${BASE_DC}|$LDAP_BASE_DC|
+        s|\${BASE_DN}|$LDAP_BASE_DN|
+        s|\${MANAGER_DN}|$LDAP_MANAGER_DN|
+    " $infile
+}
+
+# clean_ldap() - Remove ldap server
+function cleanup_ldap() {
+    uninstall_package $(get_packages ldap)
+    if is_ubuntu; then
+        uninstall_package slapd ldap-utils libslp1
+        sudo rm -rf /etc/ldap/ldap.conf /var/lib/ldap
+    elif is_fedora; then
+        sudo rm -rf /etc/openldap /var/lib/ldap
+    elif is_suse; then
+        sudo rm -rf /var/lib/ldap
+    fi
+}
+
+# init_ldap
+# init_ldap() - Initialize databases, etc.
+function init_ldap() {
+    local keystone_ldif
+
+    TMP_LDAP_DIR=$(mktemp -d -t ldap.$$.XXXXXXXXXX)
+
+    # Remove data but not schemas
+    clear_ldap_state
+
+    # Add our top level ldap nodes
+    if ldapsearch -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -b "$LDAP_BASE_DN" | grep -q "Success"; then
+        printf "LDAP already configured for $LDAP_BASE_DC\n"
+    else
+        printf "Configuring LDAP for $LDAP_BASE_DC\n"
+        # If BASE_DN is changed, the user may override the default file
+        if [[ -r $FILES/ldap/${LDAP_BASE_DC}.ldif.in ]]; then
+            keystone_ldif=${LDAP_BASE_DC}.ldif
+        else
+            keystone_ldif=keystone.ldif
+        fi
+        _ldap_varsubst $FILES/ldap/${keystone_ldif}.in >$TMP_LDAP_DIR/${keystone_ldif}
+        if [[ -r $TMP_LDAP_DIR/${keystone_ldif} ]]; then
+            ldapadd -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -c -f $TMP_LDAP_DIR/${keystone_ldif}
+        fi
+    fi
+
+    rm -rf TMP_LDAP_DIR
+}
+
 # install_ldap
 # install_ldap() - Collect source and prepare
 function install_ldap() {
     echo "Installing LDAP inside function"
-    echo "LDAP_PASSWORD is $LDAP_PASSWORD"
     echo "os_VENDOR is $os_VENDOR"
-    printf "installing"
+
+    TMP_LDAP_DIR=$(mktemp -d -t ldap.$$.XXXXXXXXXX)
+
+    printf "installing OpenLDAP"
     if is_ubuntu; then
-        LDAP_OLCDB_NUMBER=1
-        LDAP_ROOTPW_COMMAND=replace
-        sudo DEBIAN_FRONTEND=noninteractive apt-get install slapd ldap-utils
-        #automatically starts LDAP on ubuntu so no need to call start_ldap
+        # Ubuntu automatically starts LDAP so no need to call start_ldap()
+        :
     elif is_fedora; then
-        LDAP_OLCDB_NUMBER=2
-        LDAP_ROOTPW_COMMAND=add
         start_ldap
     elif is_suse; then
-        LDAP_OLCDB_NUMBER=1
-        LDAP_ROOTPW_COMMAND=add
-        LDAP_SERVICE_NAME=ldap
-        # SUSE has slappasswd in /usr/sbin/
-        PATH=$PATH:/usr/sbin/
-        sudo slapadd -F /etc/openldap/slapd.d/ -bcn=config -l $FILES/ldap/base-config.ldif
+        _ldap_varsubst $FILES/ldap/suse-base-config.ldif.in >$TMP_LDAP_DIR/suse-base-config.ldif
+        sudo slapadd -F /etc/openldap/slapd.d/ -bcn=config -l $TMP_LDAP_DIR/suse-base-config.ldif
         sudo sed -i '/^OPENLDAP_START_LDAPI=/s/"no"/"yes"/g' /etc/sysconfig/openldap
         start_ldap
     fi
 
-    printf "generate password file"
-    SLAPPASS=`slappasswd -s $LDAP_PASSWORD`
+    echo "LDAP_PASSWORD is $LDAP_PASSWORD"
+    SLAPPASS=$(slappasswd -s $LDAP_PASSWORD)
+    printf "LDAP secret is $SLAPPASS\n"
 
-    printf "secret is $SLAPPASS\n"
-    #create manager.ldif
-    TMP_MGR_DIFF_FILE=`mktemp -t manager_ldiff.$$.XXXXXXXXXX.ldif`
-    sed -e "s|\${LDAP_OLCDB_NUMBER}|$LDAP_OLCDB_NUMBER|" -e "s|\${SLAPPASS}|$SLAPPASS|" -e "s|\${LDAP_ROOTPW_COMMAND}|$LDAP_ROOTPW_COMMAND|" $FILES/ldap/manager.ldif.in >> $TMP_MGR_DIFF_FILE
-
-    #update ldap olcdb
-    sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f $TMP_MGR_DIFF_FILE
+    # Create manager.ldif and add to olcdb
+    _ldap_varsubst $FILES/ldap/manager.ldif.in >$TMP_LDAP_DIR/manager.ldif
+    sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f $TMP_LDAP_DIR/manager.ldif
 
     # On fedora we need to manually add cosine and inetorgperson schemas
-    if is_fedora || is_suse; then
+    if is_fedora; then
         sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
         sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
     fi
 
-    # add our top level ldap nodes
-    if ldapsearch -x -w $LDAP_PASSWORD -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -x -b dc=openstack,dc=org | grep -q "Success"; then
-        printf "LDAP already configured for OpenStack\n"
-        if [[ "$KEYSTONE_CLEAR_LDAP" == "yes" ]]; then
-            # clear LDAP state
-            clear_ldap_state
-            # reconfigure LDAP for OpenStack
-            ldapadd -c -x -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -w $LDAP_PASSWORD -f  $FILES/ldap/openstack.ldif
-        fi
-    else
-        printf "Configuring LDAP for OpenStack\n"
-        ldapadd -c -x -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -w $LDAP_PASSWORD -f  $FILES/ldap/openstack.ldif
-    fi
+    rm -rf TMP_LDAP_DIR
 }
 
 # start_ldap() - Start LDAP
@@ -78,7 +147,6 @@
     sudo service $LDAP_SERVICE_NAME restart
 }
 
-
 # stop_ldap() - Stop LDAP
 function stop_ldap() {
     sudo service $LDAP_SERVICE_NAME stop
@@ -86,7 +154,7 @@
 
 # clear_ldap_state() - Clear LDAP State
 function clear_ldap_state() {
-    ldapdelete -x -w $LDAP_PASSWORD -H ldap://localhost -D dc=Manager,dc=openstack,dc=org -x -r "dc=openstack,dc=org"
+    ldapdelete -x -w $LDAP_PASSWORD -D "$LDAP_MANAGER_DN" -H $LDAP_URL -r "$LDAP_BASE_DN"
 }
 
 # Restore xtrace
diff --git a/lib/neutron b/lib/neutron
index 7376772..b05b16d 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -115,6 +115,13 @@
 # nova vif driver that all plugins should use
 NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"}
 
+# The next two variables are configured by plugin
+# e.g.  _configure_neutron_l3_agent or lib/neutron_plugins/*
+#
+# The plugin supports L3.
+Q_L3_ENABLED=${Q_L3_ENABLED:-False}
+# L3 routers exist per tenant
+Q_L3_ROUTER_PER_TENANT=${Q_L3_ROUTER_PER_TENANT:-False}
 
 # List of config file names in addition to the main plugin config file
 # See _configure_neutron_common() for details about setting it up
diff --git a/lib/neutron_plugins/midonet b/lib/neutron_plugins/midonet
index e406146..f95fcb7 100644
--- a/lib/neutron_plugins/midonet
+++ b/lib/neutron_plugins/midonet
@@ -62,6 +62,9 @@
     if [[ "$MIDONET_PROVIDER_ROUTER_ID" != "" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE MIDONET provider_router_id $MIDONET_PROVIDER_ROUTER_ID
     fi
+
+    Q_L3_ENABLED=True
+    Q_L3_ROUTER_PER_TENANT=True
 }
 
 function neutron_plugin_setup_interface_driver() {
diff --git a/lib/neutron_thirdparty/nicira b/lib/neutron_thirdparty/nicira
index 3f2a5af..3efb5a9 100644
--- a/lib/neutron_thirdparty/nicira
+++ b/lib/neutron_thirdparty/nicira
@@ -33,7 +33,7 @@
         echo "Defaulting to "$NVP_GATEWAY_NETWORK_CIDR
     fi
     # Make sure the interface is up, but not configured
-    sudo ip link dev $NVP_GATEWAY_NETWORK_INTERFACE set up
+    sudo ip link set $NVP_GATEWAY_NETWORK_INTERFACE up
     # Save and then flush the IP addresses on the interface
     addresses=$(ip addr show dev $NVP_GATEWAY_NETWORK_INTERFACE | grep inet | awk {'print $2'})
     sudo ip addr flush $NVP_GATEWAY_NETWORK_INTERFACE
@@ -45,7 +45,7 @@
     sudo ovs-vsctl --no-wait -- --may-exist add-br $PUBLIC_BRIDGE
     sudo ovs-vsctl -- --may-exist add-port $PUBLIC_BRIDGE $NVP_GATEWAY_NETWORK_INTERFACE
     nvp_gw_net_if_mac=$(ip link show $NVP_GATEWAY_NETWORK_INTERFACE | awk '/ether/ {print $2}')
-    sudo ip link dev $PUBLIC_BRIDGE set address $nvp_gw_net_if_mac
+    sudo ip link set address $nvp_gw_net_if_mac dev $PUBLIC_BRIDGE
     for address in $addresses; do
         sudo ip addr add dev $PUBLIC_BRIDGE $address
     done
diff --git a/lib/nova b/lib/nova
index 5fd0beb..e754341 100644
--- a/lib/nova
+++ b/lib/nova
@@ -398,6 +398,7 @@
         # Add keystone authtoken configuration
 
         iniset $NOVA_CONF keystone_authtoken auth_host $KEYSTONE_AUTH_HOST
+        iniset $NOVA_CONF keystone_authtoken auth_port $KEYSTONE_AUTH_PORT
         iniset $NOVA_CONF keystone_authtoken auth_protocol $KEYSTONE_AUTH_PROTOCOL
         iniset $NOVA_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
         iniset $NOVA_CONF keystone_authtoken cafile $KEYSTONE_SSL_CA
@@ -652,7 +653,7 @@
         screen_it n-cpu "cd $NOVA_DIR && sg $LIBVIRT_GROUP '$NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf'"
     elif [[ "$VIRT_DRIVER" = 'fake' ]]; then
         for i in `seq 1 $NUMBER_FAKE_NOVA_COMPUTE`; do
-            screen_it n-cpu "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf"
+            screen_it n-cpu "cd $NOVA_DIR && $NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf --config-file <(echo -e '[DEFAULT]\nhost=${HOSTNAME}${i}')"
         done
     else
         if is_service_enabled n-cpu && [[ -r $NOVA_PLUGINS/hypervisor-$VIRT_DRIVER ]]; then
diff --git a/lib/savanna b/lib/savanna
index e9dbe72..6794e36 100644
--- a/lib/savanna
+++ b/lib/savanna
@@ -3,7 +3,6 @@
 # Dependencies:
 # ``functions`` file
 # ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
-# ``ADMIN_{TENANT_NAME|PASSWORD}`` must be defined
 
 # ``stack.sh`` calls the entry points in this order:
 #
@@ -28,11 +27,12 @@
 SAVANNA_DIR=$DEST/savanna
 SAVANNA_CONF_DIR=${SAVANNA_CONF_DIR:-/etc/savanna}
 SAVANNA_CONF_FILE=savanna.conf
-ADMIN_TENANT_NAME=${ADMIN_TENANT_NAME:-admin}
-ADMIN_NAME=${ADMIN_NAME:-admin}
-ADMIN_PASSWORD=${ADMIN_PASSWORD:-nova}
 SAVANNA_DEBUG=${SAVANNA_DEBUG:-True}
 
+SAVANNA_SERVICE_HOST=${SAVANNA_SERVICE_HOST:-$SERVICE_HOST}
+SAVANNA_SERVICE_PORT=${SAVANNA_SERVICE_PORT:-8386}
+SAVANNA_SERVICE_PROTOCOL=${SAVANNA_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
+
 # Support entry points installation of console scripts
 if [[ -d $SAVANNA_DIR/bin ]]; then
     SAVANNA_BIN_DIR=$SAVANNA_DIR/bin
@@ -43,6 +43,42 @@
 # Functions
 # ---------
 
+# create_savanna_accounts() - Set up common required savanna accounts
+#
+# Tenant      User       Roles
+# ------------------------------
+# service     savanna    admin
+function create_savanna_accounts() {
+
+    SERVICE_TENANT=$(keystone tenant-list | awk "/ $SERVICE_TENANT_NAME / { print \$2 }")
+    ADMIN_ROLE=$(keystone role-list | awk "/ admin / { print \$2 }")
+
+    SAVANNA_USER=$(keystone user-create \
+        --name=savanna \
+        --pass="$SERVICE_PASSWORD" \
+        --tenant_id $SERVICE_TENANT \
+        --email=savanna@example.com \
+        | grep " id " | get_field 2)
+    keystone user-role-add \
+        --tenant-id $SERVICE_TENANT \
+        --user-id $SAVANNA_USER \
+        --role-id $ADMIN_ROLE
+
+    if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
+        SAVANNA_SERVICE=$(keystone service-create \
+            --name=savanna \
+            --type=data_processing \
+            --description="Savanna Data Processing" \
+            | grep " id " | get_field 2)
+        keystone endpoint-create \
+            --region RegionOne \
+            --service_id $SAVANNA_SERVICE \
+            --publicurl "$SAVANNA_SERVICE_PROTOCOL://$SAVANNA_SERVICE_HOST:$SAVANNA_SERVICE_PORT/v1.1/\$(tenant_id)s" \
+            --adminurl "$SAVANNA_SERVICE_PROTOCOL://$SAVANNA_SERVICE_HOST:$SAVANNA_SERVICE_PORT/v1.1/\$(tenant_id)s" \
+            --internalurl "$SAVANNA_SERVICE_PROTOCOL://$SAVANNA_SERVICE_HOST:$SAVANNA_SERVICE_PORT/v1.1/\$(tenant_id)s"
+    fi
+}
+
 # configure_savanna() - Set config files, create data dirs, etc
 function configure_savanna() {
 
@@ -54,9 +90,9 @@
     # Copy over savanna configuration file and configure common parameters.
     cp $SAVANNA_DIR/etc/savanna/savanna.conf.sample $SAVANNA_CONF_DIR/$SAVANNA_CONF_FILE
 
-    iniset $SAVANNA_CONF_DIR/$SAVANNA_CONF_FILE DEFAULT os_admin_password $ADMIN_PASSWORD
-    iniset $SAVANNA_CONF_DIR/$SAVANNA_CONF_FILE DEFAULT os_admin_username $ADMIN_NAME
-    iniset $SAVANNA_CONF_DIR/$SAVANNA_CONF_FILE DEFAULT os_admin_tenant_name $ADMIN_TENANT_NAME
+    iniset $SAVANNA_CONF_DIR/$SAVANNA_CONF_FILE DEFAULT os_admin_password $SERVICE_PASSWORD
+    iniset $SAVANNA_CONF_DIR/$SAVANNA_CONF_FILE DEFAULT os_admin_username savanna
+    iniset $SAVANNA_CONF_DIR/$SAVANNA_CONF_FILE DEFAULT os_admin_tenant_name $SERVICE_TENANT_NAME
     iniset $SAVANNA_CONF_DIR/$SAVANNA_CONF_FILE DEFAULT debug $SAVANNA_DEBUG
 
     recreate_database savanna utf8
diff --git a/lib/swift b/lib/swift
index 5ff6055..3bf2b78 100644
--- a/lib/swift
+++ b/lib/swift
@@ -378,6 +378,9 @@
         iniuncomment ${swift_node_config} DEFAULT log_facility
         iniset ${swift_node_config} DEFAULT log_facility LOG_LOCAL${log_facility}
 
+        iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT workers
+        iniset ${SWIFT_CONFIG_PROXY_SERVER} DEFAULT workers 1
+
         iniuncomment ${swift_node_config} DEFAULT disable_fallocate
         iniset ${swift_node_config} DEFAULT disable_fallocate true
 
diff --git a/lib/tempest b/lib/tempest
index 5a2c78d..4400b31 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -15,6 +15,7 @@
 #   - ``PUBLIC_NETWORK_NAME``
 #   - ``Q_USE_NAMESPACE``
 #   - ``Q_ROUTER_NAME``
+#   - ``Q_L3_ENABLED``
 #   - ``VIRT_DRIVER``
 #   - ``LIBVIRT_TYPE``
 #   - ``KEYSTONE_SERVICE_PROTOCOL``, ``KEYSTONE_SERVICE_HOST`` from lib/keystone
@@ -146,12 +147,21 @@
     if  [[ -z "$DEFAULT_INSTANCE_TYPE" ]]; then
         available_flavors=$(nova flavor-list)
         if [[ ! ( $available_flavors =~ 'm1.nano' ) ]]; then
-            nova flavor-create m1.nano 42 64 0 1
+            if is_arch "ppc64"; then
+                # qemu needs at least 128MB of memory to boot on ppc64
+                nova flavor-create m1.nano 42 128 0 1
+            else
+                nova flavor-create m1.nano 42 64 0 1
+            fi
         fi
         flavor_ref=42
         boto_instance_type=m1.nano
         if [[ ! ( $available_flavors =~ 'm1.micro' ) ]]; then
-            nova flavor-create m1.micro 84 128 0 1
+            if is_arch "ppc64"; then
+                nova flavor-create m1.micro 84 256 0 1
+            else
+                nova flavor-create m1.micro 84 128 0 1
+            fi
         fi
         flavor_ref_alt=84
     else
@@ -202,7 +212,7 @@
 
     ssh_connect_method=${TEMPEST_SSH_CONNECT_METHOD:-$ssh_connect_method}
 
-    if is_service_enabled q-l3; then
+    if [ "$Q_L3_ENABLED" = "True" ]; then
         public_network_id=$(neutron net-list | grep $PUBLIC_NETWORK_NAME | \
             awk '{print $2}')
         if [ "$Q_USE_NAMESPACE" == "False" ]; then
diff --git a/lib/trove b/lib/trove
index 5ba4de5..6d5a56e 100644
--- a/lib/trove
+++ b/lib/trove
@@ -32,6 +32,17 @@
 TROVE_AUTH_CACHE_DIR=${TROVE_AUTH_CACHE_DIR:-/var/cache/trove}
 TROVE_BIN_DIR=/usr/local/bin
 
+# setup_trove_logging() - Adds logging configuration to conf files
+function setup_trove_logging() {
+    local CONF=$1
+    iniset $CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
+    iniset $CONF DEFAULT use_syslog $SYSLOG
+    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
+        # Add color to logging output
+        setup_colorized_logging $CONF DEFAULT tenant user
+    fi
+}
+
 # create_trove_accounts() - Set up common required trove accounts
 
 # Tenant               User       Roles
@@ -121,6 +132,9 @@
     iniset $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample DEFAULT control_exchange trove
     sed -i "s/localhost/$NETWORK_GATEWAY/g" $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample
 
+    setup_trove_logging $TROVE_CONF_DIR/trove.conf
+    setup_trove_logging $TROVE_LOCAL_CONF_DIR/trove-guestagent.conf.sample
+
     # (Re)create trove taskmanager conf file if needed
     if is_service_enabled tr-tmgr; then
         TROVE_AUTH_ENDPOINT=$KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT//v$IDENTITY_API_VERSION
@@ -132,6 +146,7 @@
         iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT nova_proxy_admin_tenant_name trove
         iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT nova_proxy_admin_pass $RADMIN_USER_PASS
         iniset $TROVE_CONF_DIR/trove-taskmanager.conf DEFAULT trove_auth_url $TROVE_AUTH_ENDPOINT
+        setup_trove_logging $TROVE_CONF_DIR/trove-taskmanager.conf
     fi
 
     # (Re)create trove conductor conf file if needed
@@ -143,6 +158,7 @@
         iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT nova_proxy_admin_pass $RADMIN_USER_PASS
         iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT trove_auth_url $TROVE_AUTH_ENDPOINT
         iniset $TROVE_CONF_DIR/trove-conductor.conf DEFAULT control_exchange trove
+        setup_trove_logging $TROVE_CONF_DIR/trove-conductor.conf
     fi
 }
 
diff --git a/tests/functions.sh b/tests/functions.sh
index 40376aa..95dafe1 100755
--- a/tests/functions.sh
+++ b/tests/functions.sh
@@ -38,195 +38,6 @@
 fi
 
 
-echo "Testing INI functions"
-
-cat >test.ini <<EOF
-[default]
-# comment an option
-#log_file=./log.conf
-log_file=/etc/log.conf
-handlers=do not disturb
-
-[aaa]
-# the commented option should not change
-#handlers=cc,dd
-handlers = aa, bb
-
-[bbb]
-handlers=ee,ff
-
-[ ccc ]
-spaces  =  yes
-
-[ddd]
-empty =
-
-[eee]
-multi = foo1
-multi = foo2
-EOF
-
-# Test with spaces
-
-VAL=$(iniget test.ini aaa handlers)
-if [[ "$VAL" == "aa, bb" ]]; then
-    echo "OK: $VAL"
-else
-    echo "iniget failed: $VAL"
-fi
-
-iniset test.ini aaa handlers "11, 22"
-
-VAL=$(iniget test.ini aaa handlers)
-if [[ "$VAL" == "11, 22" ]]; then
-    echo "OK: $VAL"
-else
-    echo "iniget failed: $VAL"
-fi
-
-# Test with spaces in section header
-
-VAL=$(iniget test.ini " ccc " spaces)
-if [[ "$VAL" == "yes" ]]; then
-    echo "OK: $VAL"
-else
-    echo "iniget failed: $VAL"
-fi
-
-iniset test.ini "b b" opt_ion 42
-
-VAL=$(iniget test.ini "b b" opt_ion)
-if [[ "$VAL" == "42" ]]; then
-    echo "OK: $VAL"
-else
-    echo "iniget failed: $VAL"
-fi
-
-# Test without spaces, end of file
-
-VAL=$(iniget test.ini bbb handlers)
-if [[ "$VAL" == "ee,ff" ]]; then
-    echo "OK: $VAL"
-else
-    echo "iniget failed: $VAL"
-fi
-
-iniset test.ini bbb handlers "33,44"
-
-VAL=$(iniget test.ini bbb handlers)
-if [[ "$VAL" == "33,44" ]]; then
-    echo "OK: $VAL"
-else
-    echo "iniget failed: $VAL"
-fi
-
-# test empty option
-if ini_has_option test.ini ddd empty; then
-    echo "OK: ddd.empty present"
-else
-    echo "ini_has_option failed: ddd.empty not found"
-fi
-
-# test non-empty option
-if ini_has_option test.ini bbb handlers; then
-    echo "OK: bbb.handlers present"
-else
-    echo "ini_has_option failed: bbb.handlers not found"
-fi
-
-# test changing empty option
-iniset test.ini ddd empty "42"
-
-VAL=$(iniget test.ini ddd empty)
-if [[ "$VAL" == "42" ]]; then
-    echo "OK: $VAL"
-else
-    echo "iniget failed: $VAL"
-fi
-
-# Test section not exist
-
-VAL=$(iniget test.ini zzz handlers)
-if [[ -z "$VAL" ]]; then
-    echo "OK: zzz not present"
-else
-    echo "iniget failed: $VAL"
-fi
-
-iniset test.ini zzz handlers "999"
-
-VAL=$(iniget test.ini zzz handlers)
-if [[ -n "$VAL" ]]; then
-    echo "OK: zzz not present"
-else
-    echo "iniget failed: $VAL"
-fi
-
-# Test option not exist
-
-VAL=$(iniget test.ini aaa debug)
-if [[ -z "$VAL" ]]; then
-    echo "OK aaa.debug not present"
-else
-    echo "iniget failed: $VAL"
-fi
-
-if ! ini_has_option test.ini aaa debug; then
-    echo "OK aaa.debug not present"
-else
-    echo "ini_has_option failed: aaa.debug"
-fi
-
-iniset test.ini aaa debug "999"
-
-VAL=$(iniget test.ini aaa debug)
-if [[ -n "$VAL" ]]; then
-    echo "OK aaa.debug present"
-else
-    echo "iniget failed: $VAL"
-fi
-
-# Test comments
-
-inicomment test.ini aaa handlers
-
-VAL=$(iniget test.ini aaa handlers)
-if [[ -z "$VAL" ]]; then
-    echo "OK"
-else
-    echo "inicomment failed: $VAL"
-fi
-
-# Test multiple line iniset/iniget
-iniset_multiline test.ini eee multi bar1 bar2
-
-VAL=$(iniget_multiline test.ini eee multi)
-if [[ "$VAL" == "bar1 bar2" ]]; then
-    echo "OK: iniset_multiline"
-else
-    echo "iniset_multiline failed: $VAL"
-fi
-
-# Test iniadd with exiting values
-iniadd test.ini eee multi bar3
-VAL=$(iniget_multiline test.ini eee multi)
-if [[ "$VAL" == "bar1 bar2 bar3" ]]; then
-    echo "OK: iniadd"
-else
-    echo "iniadd failed: $VAL"
-fi
-
-# Test iniadd with non-exiting values
-iniadd test.ini eee non-multi foobar1 foobar2
-VAL=$(iniget_multiline test.ini eee non-multi)
-if [[ "$VAL" == "foobar1 foobar2" ]]; then
-    echo "OK: iniadd with non-exiting value"
-else
-    echo "iniadd with non-exsting failed: $VAL"
-fi
-
-rm test.ini
-
 # Enabling/disabling services
 
 echo "Testing enable_service()"
diff --git a/tests/test_config.sh b/tests/test_config.sh
index fed2e7d..39603c9 100755
--- a/tests/test_config.sh
+++ b/tests/test_config.sh
@@ -70,6 +70,12 @@
 
 [[test1|test1c.conf]]
 $TEST_1C_ADD
+
+[[test3|test-space.conf]]
+[DEFAULT]
+attribute=value
+ 
+# the above line has a single space
 EOF
 
 
@@ -176,4 +182,14 @@
     echo "failed: $VAL != $EXPECT_VAL"
 fi
 
-rm -f test.conf test1c.conf test2a.conf
+echo -n "merge_config_file test-space: "
+rm -f test-space.conf
+merge_config_file test.conf test3 test-space.conf
+VAL=$(cat test-space.conf)
+# iniset adds a blank line if it creates the file...
+EXPECT_VAL="
+[DEFAULT]
+attribute = value"
+check_result "$VAL" "$EXPECT_VAL"
+
+rm -f test.conf test1c.conf test2a.conf test-space.conf
diff --git a/tests/test_ini.sh b/tests/test_ini.sh
new file mode 100755
index 0000000..b0dc6b1
--- /dev/null
+++ b/tests/test_ini.sh
@@ -0,0 +1,220 @@
+#!/usr/bin/env bash
+
+# Tests for DevStack INI functions
+
+TOP=$(cd $(dirname "$0")/.. && pwd)
+
+# Import common functions
+source $TOP/functions
+
+
+echo "Testing INI functions"
+
+cat >test.ini <<EOF
+[default]
+# comment an option
+#log_file=./log.conf
+log_file=/etc/log.conf
+handlers=do not disturb
+
+[aaa]
+# the commented option should not change
+#handlers=cc,dd
+handlers = aa, bb
+
+[bbb]
+handlers=ee,ff
+
+[ ccc ]
+spaces  =  yes
+
+[ddd]
+empty =
+
+[eee]
+multi = foo1
+multi = foo2
+EOF
+
+# Test with missing arguments
+
+BEFORE=$(cat test.ini)
+
+echo -n "iniset: test missing attribute argument: "
+iniset test.ini aaa
+NO_ATTRIBUTE=$(cat test.ini)
+if [[ "$BEFORE" == "$NO_ATTRIBUTE" ]]; then
+    echo "OK"
+else
+    echo "failed"
+fi
+
+echo -n "iniset: test missing section argument: "
+iniset test.ini
+NO_SECTION=$(cat test.ini)
+if [[ "$BEFORE" == "$NO_SECTION" ]]; then
+    echo "OK"
+else
+    echo "failed"
+fi
+
+# Test with spaces
+
+VAL=$(iniget test.ini aaa handlers)
+if [[ "$VAL" == "aa, bb" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
+
+iniset test.ini aaa handlers "11, 22"
+
+VAL=$(iniget test.ini aaa handlers)
+if [[ "$VAL" == "11, 22" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
+
+# Test with spaces in section header
+
+VAL=$(iniget test.ini " ccc " spaces)
+if [[ "$VAL" == "yes" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
+
+iniset test.ini "b b" opt_ion 42
+
+VAL=$(iniget test.ini "b b" opt_ion)
+if [[ "$VAL" == "42" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
+
+# Test without spaces, end of file
+
+VAL=$(iniget test.ini bbb handlers)
+if [[ "$VAL" == "ee,ff" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
+
+iniset test.ini bbb handlers "33,44"
+
+VAL=$(iniget test.ini bbb handlers)
+if [[ "$VAL" == "33,44" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
+
+# test empty option
+if ini_has_option test.ini ddd empty; then
+    echo "OK: ddd.empty present"
+else
+    echo "ini_has_option failed: ddd.empty not found"
+fi
+
+# test non-empty option
+if ini_has_option test.ini bbb handlers; then
+    echo "OK: bbb.handlers present"
+else
+    echo "ini_has_option failed: bbb.handlers not found"
+fi
+
+# test changing empty option
+iniset test.ini ddd empty "42"
+
+VAL=$(iniget test.ini ddd empty)
+if [[ "$VAL" == "42" ]]; then
+    echo "OK: $VAL"
+else
+    echo "iniget failed: $VAL"
+fi
+
+# Test section not exist
+
+VAL=$(iniget test.ini zzz handlers)
+if [[ -z "$VAL" ]]; then
+    echo "OK: zzz not present"
+else
+    echo "iniget failed: $VAL"
+fi
+
+iniset test.ini zzz handlers "999"
+
+VAL=$(iniget test.ini zzz handlers)
+if [[ -n "$VAL" ]]; then
+    echo "OK: zzz not present"
+else
+    echo "iniget failed: $VAL"
+fi
+
+# Test option not exist
+
+VAL=$(iniget test.ini aaa debug)
+if [[ -z "$VAL" ]]; then
+    echo "OK aaa.debug not present"
+else
+    echo "iniget failed: $VAL"
+fi
+
+if ! ini_has_option test.ini aaa debug; then
+    echo "OK aaa.debug not present"
+else
+    echo "ini_has_option failed: aaa.debug"
+fi
+
+iniset test.ini aaa debug "999"
+
+VAL=$(iniget test.ini aaa debug)
+if [[ -n "$VAL" ]]; then
+    echo "OK aaa.debug present"
+else
+    echo "iniget failed: $VAL"
+fi
+
+# Test comments
+
+inicomment test.ini aaa handlers
+
+VAL=$(iniget test.ini aaa handlers)
+if [[ -z "$VAL" ]]; then
+    echo "OK"
+else
+    echo "inicomment failed: $VAL"
+fi
+
+# Test multiple line iniset/iniget
+iniset_multiline test.ini eee multi bar1 bar2
+
+VAL=$(iniget_multiline test.ini eee multi)
+if [[ "$VAL" == "bar1 bar2" ]]; then
+    echo "OK: iniset_multiline"
+else
+    echo "iniset_multiline failed: $VAL"
+fi
+
+# Test iniadd with exiting values
+iniadd test.ini eee multi bar3
+VAL=$(iniget_multiline test.ini eee multi)
+if [[ "$VAL" == "bar1 bar2 bar3" ]]; then
+    echo "OK: iniadd"
+else
+    echo "iniadd failed: $VAL"
+fi
+
+# Test iniadd with non-exiting values
+iniadd test.ini eee non-multi foobar1 foobar2
+VAL=$(iniget_multiline test.ini eee non-multi)
+if [[ "$VAL" == "foobar1 foobar2" ]]; then
+    echo "OK: iniadd with non-exiting value"
+else
+    echo "iniadd with non-exsting failed: $VAL"
+fi
+
+rm test.ini
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index 6b9b25e..a65a77e 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -67,7 +67,7 @@
             curl -O $PIP_GET_PIP_URL; \
         )
     fi
-    sudo python $FILES/get-pip.py
+    sudo -E python $FILES/get-pip.py
 }
 
 function install_pip_tarball() {
@@ -75,7 +75,7 @@
         curl -O $PIP_TAR_URL; \
         tar xvfz pip-$INSTALL_PIP_VERSION.tar.gz 1>/dev/null; \
         cd pip-$INSTALL_PIP_VERSION; \
-        sudo python setup.py install 1>/dev/null; \
+        sudo -E python setup.py install 1>/dev/null; \
     )
 }
 
diff --git a/tools/xen/build_xva.sh b/tools/xen/build_xva.sh
index 7272fe2..958102b 100755
--- a/tools/xen/build_xva.sh
+++ b/tools/xen/build_xva.sh
@@ -119,6 +119,20 @@
     if su -c "/opt/stack/run.sh" $STACK_USER; then
         touch /var/run/devstack.succeeded
     fi
+
+    # Update /etc/issue
+    {
+        echo "OpenStack VM - Installed by DevStack"
+        IPADDR=\$(ip -4 address show eth0 | sed -n 's/.*inet \\([0-9\.]\\+\\).*/\1/p')
+        echo "  Management IP:   \$IPADDR"
+        echo -n "  Devstack run:    "
+        if [ -e /var/run/devstack.succeeded ]; then
+            echo "SUCCEEDED"
+        else
+            echo "FAILED"
+        fi
+        echo ""
+    } > /etc/issue
     initctl start hvc0 > /dev/null 2>&1
 end script
 EOF
diff --git a/tools/xen/xenrc b/tools/xen/xenrc
index bdcaf99..c0ea3bc 100644
--- a/tools/xen/xenrc
+++ b/tools/xen/xenrc
@@ -13,7 +13,13 @@
 
 # Size of image
 VDI_MB=${VDI_MB:-5000}
-OSDOMU_MEM_MB=3072
+
+# Devstack now contains many components.  3GB ram is not enough to prevent
+# swapping and memory fragmentation - the latter of which can cause failures
+# such as blkfront failing to plug a VBD and lead to random test fails.
+#
+# Set to 4GB so an 8GB XenServer VM can have a 1GB Dom0 and leave 3GB for VMs
+OSDOMU_MEM_MB=4096
 OSDOMU_VDI_GB=8
 
 # Network mapping. Specify bridge names or network names. Network names may