Merge "Add support for ephemeral disk to ironic"
diff --git a/README.md b/README.md
index 89e3855..f9a996e 100644
--- a/README.md
+++ b/README.md
@@ -124,7 +124,7 @@
 `APACHE_ENABLED_SERVICES` in your ``localrc`` section.  Remember to
 enable these services at first as above.
 
-    APACHE_ENABLED_SERVICES+=keystone,swift
+    APACHE_ENABLED_SERVICES+=key,swift
 
 # Swift
 
diff --git a/clean.sh b/clean.sh
index 3707d84..7851da3 100755
--- a/clean.sh
+++ b/clean.sh
@@ -102,7 +102,7 @@
 fi
 
 # Clean out /etc
-sudo rm -rf /etc/keystone /etc/glance /etc/nova /etc/cinder /etc/swift
+sudo rm -rf /etc/keystone /etc/glance /etc/nova /etc/cinder /etc/swift /etc/heat /etc/neutron
 
 # Clean out tgt
 sudo rm -f /etc/tgt/conf.d/*
diff --git a/files/apts/ironic b/files/apts/ironic
index a749ad7..b77a6b1 100644
--- a/files/apts/ironic
+++ b/files/apts/ironic
@@ -1,3 +1,4 @@
+iptables
 libguestfs0
 libvirt-bin
 openssh-client
diff --git a/files/rpms/ironic b/files/rpms/ironic
index 54b9829..6534095 100644
--- a/files/rpms/ironic
+++ b/files/rpms/ironic
@@ -1,6 +1,8 @@
+iptables
 libguestfs
 libvirt
 libvirt-python
+net-tools
 openssh-clients
 openvswitch
 python-libguestfs
diff --git a/lib/ceilometer b/lib/ceilometer
index 5476773..59f572c 100644
--- a/lib/ceilometer
+++ b/lib/ceilometer
@@ -237,7 +237,7 @@
 # start_ceilometer() - Start running processes, including screen
 function start_ceilometer {
     if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then
-        screen_it ceilometer-acompute "cd ; sg $LIBVIRT_GROUP \"ceilometer-agent-compute --config-file $CEILOMETER_CONF\""
+        screen_it ceilometer-acompute "cd ; sg $LIBVIRT_GROUP 'ceilometer-agent-compute --config-file $CEILOMETER_CONF'"
     fi
     if [[ "$VIRT_DRIVER" = 'vsphere' ]]; then
         screen_it ceilometer-acompute "cd ; ceilometer-agent-compute --config-file $CEILOMETER_CONF"
diff --git a/lib/databases/mysql b/lib/databases/mysql
index 0a96cf8..ea22d14 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -47,6 +47,7 @@
 }
 
 function configure_database_mysql {
+    local slow_log
     echo_summary "Configuring and starting MySQL"
 
     if is_ubuntu; then
@@ -92,7 +93,11 @@
 
     if [[ "$DATABASE_QUERY_LOGGING" == "True" ]]; then
         echo_summary "Enabling MySQL query logging"
-
+        if is_fedora && ! [[ $DISTRO =~ (rhel6) ]]; then
+            slow_log=/var/log/mariadb/mariadb-slow.log
+        else
+            slow_log=/var/log/mysql/mysql-slow.log
+        fi
         sudo sed -e '/log.slow.queries/d' \
             -e '/long.query.time/d' \
             -e '/log.queries.not.using.indexes/d' \
@@ -102,7 +107,7 @@
         # 0 seconds) and log all non-indexed queries
         sudo bash -c "source $TOP_DIR/functions && \
             iniset $MY_CONF mysqld slow-query-log 1 && \
-            iniset $MY_CONF mysqld slow-query-log-file /var/log/mysql/mysql-slow.log && \
+            iniset $MY_CONF mysqld slow-query-log-file $slow_log && \
             iniset $MY_CONF mysqld long-query-time 0 && \
             iniset $MY_CONF mysqld log-queries-not-using-indexes 1"
 
diff --git a/lib/horizon b/lib/horizon
index 90a2bc5..9ce4853 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -45,7 +45,10 @@
     local option=$3
     local value=$4
 
-    if grep -q "^$section" $file; then
+    if [ -z "$section" ]; then
+        sed -e "/^$option/d" -i $local_settings
+        echo -e "\n$option=$value" >> $file
+    elif grep -q "^$section" $file; then
         line=$(sed -ne "/^$section/,/^}/ { /^ *'$option':/ p; }" $file)
         if [ -n "$line" ]; then
             sed -i -e "/^$section/,/^}/ s/^\( *'$option'\) *:.*$/\1: $value,/" $file
@@ -103,6 +106,13 @@
         _horizon_config_set $local_settings OPENSTACK_NEUTRON_NETWORK enable_vpn True
     fi
 
+    _horizon_config_set $local_settings "" OPENSTACK_HOST \"${KEYSTONE_SERVICE_HOST}\"
+    _horizon_config_set $local_settings "" OPENSTACK_KEYSTONE_URL "\"${KEYSTONE_SERVICE_PROTOCOL}://%s:${KEYSTONE_SERVICE_PORT}/v2.0\" % OPENSTACK_HOST"
+
+    if [ -f $SSL_BUNDLE_FILE ]; then
+        _horizon_config_set $local_settings "" OPENSTACK_SSL_CACERT \"${SSL_BUNDLE_FILE}\"
+    fi
+
     # Create an empty directory that apache uses as docroot
     sudo mkdir -p $HORIZON_DIR/.blackhole
 
diff --git a/lib/ironic b/lib/ironic
index 90d9b93..389040c 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -53,11 +53,12 @@
 IRONIC_VM_SSH_ADDRESS=${IRONIC_VM_SSH_ADDRESS:-$HOST_IP}
 IRONIC_VM_COUNT=${IRONIC_VM_COUNT:-1}
 IRONIC_VM_SPECS_CPU=${IRONIC_VM_SPECS_CPU:-1}
-# NOTE(agordeev): both ubuntu and fedora deploy images won't work with 256MB of RAM.
-#                 System halts and throws kernel panic during initramfs unpacking.
-#                 Ubuntu needs at least 384MB, but fedora requires 448.
-#                 So placing 512 here to satisfy both.
-IRONIC_VM_SPECS_RAM=${IRONIC_VM_SPECS_RAM:-512}
+# NOTE(adam_g): Kernels 3.12 and newer user tmpfs by default for initramfs.
+#               DIB produced ramdisks tend to be ~250MB but tmpfs will only allow
+#               use of 50% of available memory before ENOSPC.  Set minimum 1GB
+#               for nodes to avoid (LP: #1311987) and ensure consistency across
+#               older and newer kernels.
+IRONIC_VM_SPECS_RAM=${IRONIC_VM_SPECS_RAM:-1024}
 IRONIC_VM_SPECS_DISK=${IRONIC_VM_SPECS_DISK:-10}
 IRONIC_VM_EPHEMERAL_DISK=${IRONIC_VM_EPHEMERAL_DISK:-0}
 IRONIC_VM_EMULATOR=${IRONIC_VM_EMULATOR:-/usr/bin/qemu-system-x86_64}
@@ -66,6 +67,10 @@
 IRONIC_VM_MACS_CSV_FILE=${IRONIC_VM_MACS_CSV_FILE:-$IRONIC_DATA_DIR/ironic_macs.csv}
 IRONIC_AUTHORIZED_KEYS_FILE=${IRONIC_AUTHORIZED_KEYS_FILE:-$HOME/.ssh/authorized_keys}
 
+# By default, baremetal VMs will console output to file.
+IRONIC_VM_LOG_CONSOLE=${IRONIC_VM_LOG_CONSOLE:-True}
+IRONIC_VM_LOG_DIR=${IRONIC_VM_LOG_DIR:-$IRONIC_DATA_DIR/logs/}
+
 DIB_DIR=${DIB_DIR:-$DEST/diskimage-builder}
 
 # Use DIB to create deploy ramdisk and kernel.
@@ -187,6 +192,9 @@
     iniset $IRONIC_CONF_FILE pxe tftp_server $HOST_IP
     iniset $IRONIC_CONF_FILE pxe tftp_root $IRONIC_TFTPBOOT_DIR
     iniset $IRONIC_CONF_FILE pxe tftp_master_path $IRONIC_TFTPBOOT_DIR/master_images
+    if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
+        iniset $IRONIC_CONF_FILE pxe pxe_append_params "nofb nomodeset vga=normal console=ttyS0"
+    fi
 }
 
 # create_ironic_cache_dir() - Part of the init_ironic() process
@@ -316,9 +324,15 @@
 function create_bridge_and_vms {
     # Call libvirt setup scripts in a new shell to ensure any new group membership
     sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/setup-network"
+    if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
+        LOG_ARG="$IRONIC_VM_LOG_DIR"
+    else
+        LOG_ARG=""
+    fi
     sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/create-nodes \
         $IRONIC_VM_SPECS_CPU $IRONIC_VM_SPECS_RAM $IRONIC_VM_SPECS_DISK \
-        amd64 $IRONIC_VM_COUNT $IRONIC_VM_NETWORK_BRIDGE $IRONIC_VM_EMULATOR" >> $IRONIC_VM_MACS_CSV_FILE
+        amd64 $IRONIC_VM_COUNT $IRONIC_VM_NETWORK_BRIDGE $IRONIC_VM_EMULATOR \
+        $LOG_ARG" >> $IRONIC_VM_MACS_CSV_FILE
 }
 
 function enroll_vms {
@@ -381,11 +395,16 @@
     neutron port-delete $PORT_ID
 }
 
-function configure_tftpd {
-    # enable tftp natting for allowing connections to SERVICE_HOST's tftp server
+function configure_iptables {
+    # enable tftp natting for allowing connections to HOST_IP's tftp server
     sudo modprobe nf_conntrack_tftp
     sudo modprobe nf_nat_tftp
+    # nodes boot from TFTP and callback to the API server listening on $HOST_IP
+    sudo iptables -I INPUT -d $HOST_IP -p udp --dport 69 -j ACCEPT || true
+    sudo iptables -I INPUT -d $HOST_IP -p tcp --dport 6385 -j ACCEPT || true
+}
 
+function configure_tftpd {
     if is_ubuntu; then
         PXEBIN=/usr/lib/syslinux/pxelinux.0
     elif is_fedora; then
@@ -508,6 +527,7 @@
     create_bridge_and_vms
     enroll_vms
     configure_tftpd
+    configure_iptables
 
     # restart nova-compute to ensure its resource tracking is up to
     # date with newly enrolled nodes
@@ -527,6 +547,10 @@
     sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/cleanup-nodes $IRONIC_VM_COUNT $IRONIC_VM_NETWORK_BRIDGE"
     sudo rm -rf /etc/xinetd.d/tftp /etc/init/tftpd-hpa.override
     restart_service xinetd
+    sudo iptables -D INPUT -d $HOST_IP -p udp --dport 69 -j ACCEPT || true
+    sudo iptables -D INPUT -d $HOST_IP -p tcp --dport 6385 -j ACCEPT || true
+    sudo rmmod nf_conntrack_tftp || true
+    sudo rmmod nf_nat_tftp || true
 }
 
 # Restore xtrace + pipefail
diff --git a/lib/neutron b/lib/neutron
index 9e1e787..15cfa8e 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -316,7 +316,7 @@
     # set NOVA_VIF_DRIVER and optionally set options in nova_conf
     neutron_plugin_create_nova_conf
 
-    iniset $NOVA_CONF DEFAULT libvirt_vif_driver "$NOVA_VIF_DRIVER"
+    iniset $NOVA_CONF libvirt vif_driver "$NOVA_VIF_DRIVER"
     iniset $NOVA_CONF DEFAULT linuxnet_interface_driver "$LINUXNET_VIF_DRIVER"
     if is_service_enabled q-meta; then
         iniset $NOVA_CONF DEFAULT service_neutron_metadata_proxy "True"
diff --git a/lib/neutron_plugins/openvswitch_agent b/lib/neutron_plugins/openvswitch_agent
index 33ca17a..3604a50 100644
--- a/lib/neutron_plugins/openvswitch_agent
+++ b/lib/neutron_plugins/openvswitch_agent
@@ -10,8 +10,8 @@
 function neutron_plugin_create_nova_conf {
     _neutron_ovs_base_configure_nova_vif_driver
     if [ "$VIRT_DRIVER" = 'xenserver' ]; then
-        iniset $NOVA_CONF DEFAULT xenapi_vif_driver nova.virt.xenapi.vif.XenAPIOpenVswitchDriver
-        iniset $NOVA_CONF DEFAULT xenapi_ovs_integration_bridge $XEN_INTEGRATION_BRIDGE
+        iniset $NOVA_CONF xenserver vif_driver nova.virt.xenapi.vif.XenAPIOpenVswitchDriver
+        iniset $NOVA_CONF xenserver ovs_integration_bridge $XEN_INTEGRATION_BRIDGE
         # Disable nova's firewall so that it does not conflict with neutron
         iniset $NOVA_CONF DEFAULT firewall_driver nova.virt.firewall.NoopFirewallDriver
     fi
diff --git a/lib/nova_plugins/hypervisor-baremetal b/lib/nova_plugins/hypervisor-baremetal
index 2da1097..1d4d414 100644
--- a/lib/nova_plugins/hypervisor-baremetal
+++ b/lib/nova_plugins/hypervisor-baremetal
@@ -49,7 +49,7 @@
     iniset $NOVA_CONF DEFAULT scheduler_host_manager nova.scheduler.baremetal_host_manager.BaremetalHostManager
     iniset $NOVA_CONF DEFAULT ram_allocation_ratio 1.0
     iniset $NOVA_CONF DEFAULT reserved_host_memory_mb 0
-    iniset $NOVA_CONF baremetal instance_type_extra_specs cpu_arch:$BM_CPU_ARCH
+    iniset $NOVA_CONF baremetal flavor_extra_specs cpu_arch:$BM_CPU_ARCH
     iniset $NOVA_CONF baremetal driver $BM_DRIVER
     iniset $NOVA_CONF baremetal power_manager $BM_POWER_MANAGER
     iniset $NOVA_CONF baremetal tftp_root /tftpboot
diff --git a/lib/nova_plugins/hypervisor-libvirt b/lib/nova_plugins/hypervisor-libvirt
index a868330..259bf15 100644
--- a/lib/nova_plugins/hypervisor-libvirt
+++ b/lib/nova_plugins/hypervisor-libvirt
@@ -41,7 +41,7 @@
     configure_libvirt
     iniset $NOVA_CONF libvirt virt_type "$LIBVIRT_TYPE"
     iniset $NOVA_CONF libvirt cpu_mode "none"
-    iniset $NOVA_CONF DEFAULT use_usb_tablet "False"
+    iniset $NOVA_CONF libvirt use_usb_tablet "False"
     iniset $NOVA_CONF DEFAULT default_ephemeral_format "ext4"
     iniset $NOVA_CONF DEFAULT compute_driver "libvirt.LibvirtDriver"
     LIBVIRT_FIREWALL_DRIVER=${LIBVIRT_FIREWALL_DRIVER:-"nova.virt.libvirt.firewall.IptablesFirewallDriver"}
diff --git a/lib/tempest b/lib/tempest
index 81eeba3..2125f88 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -76,7 +76,6 @@
     local num_images
     local image_uuid
     local image_uuid_alt
-    local errexit
     local password
     local line
     local flavors
@@ -92,11 +91,6 @@
     # TODO(afazekas):
     # sudo python setup.py deploy
 
-    # This function exits on an error so that errors don't compound and you see
-    # only the first error that occurred.
-    errexit=$(set +o | grep errexit)
-    set -o errexit
-
     # Save IFS
     ifs=$IFS
 
@@ -383,8 +377,6 @@
 
     # Restore IFS
     IFS=$ifs
-    #Restore errexit
-    $errexit
 }
 
 # create_tempest_accounts() - Set up common required tempest accounts
diff --git a/stack.sh b/stack.sh
index dff6bd3..4a8cb90 100755
--- a/stack.sh
+++ b/stack.sh
@@ -150,7 +150,7 @@
 fi
 
 # Look for obsolete stuff
-if [[ ,${ENABLED_SERVICES} =~ ,"swift" ]]; then
+if [[ ,${ENABLED_SERVICES}, =~ ,"swift", ]]; then
     echo "FATAL: 'swift' is not supported as a service name"
     echo "FATAL: Use the actual swift service names to enable tham as required:"
     echo "FATAL: s-proxy s-object s-container s-account"
@@ -494,14 +494,18 @@
     done
 }
 
+function kill_spinner {
+    if [ ! -z "$LAST_SPINNER_PID" ]; then
+        kill >/dev/null 2>&1 $LAST_SPINNER_PID
+        printf "\b\b\bdone\n" >&3
+    fi
+}
+
 # Echo text to the log file, summary log file and stdout
 # echo_summary "something to say"
 function echo_summary {
     if [[ -t 3 && "$VERBOSE" != "True" ]]; then
-        kill >/dev/null 2>&1 $LAST_SPINNER_PID
-        if [ ! -z "$LAST_SPINNER_PID" ]; then
-            printf "\b\b\bdone\n" >&3
-        fi
+        kill_spinner
         echo -n -e $@ >&6
         spinner &
         LAST_SPINNER_PID=$!
@@ -612,6 +616,10 @@
         echo "exit_trap: cleaning up child processes"
         kill 2>&1 $jobs
     fi
+
+    # Kill the last spinner process
+    kill_spinner
+
     exit $r
 }
 
diff --git a/tools/ironic/scripts/configure-vm b/tools/ironic/scripts/configure-vm
index 9936b76..4c42c49 100755
--- a/tools/ironic/scripts/configure-vm
+++ b/tools/ironic/scripts/configure-vm
@@ -9,6 +9,25 @@
                            'templates')
 
 
+CONSOLE_LOG = """
+    <serial type='file'>
+      <source path='%(console_log)s'/>
+      <target port='0'/>
+      <alias name='serial0'/>
+    </serial>
+    <serial type='pty'>
+      <source path='/dev/pts/49'/>
+      <target port='1'/>
+      <alias name='serial1'/>
+    </serial>
+    <console type='file'>
+      <source path='%(console_log)s'/>
+      <target type='serial' port='0'/>
+      <alias name='serial0'/>
+    </console>
+"""
+
+
 def main():
     parser = argparse.ArgumentParser(
         description="Configure a kvm virtual machine for the seed image.")
@@ -30,6 +49,8 @@
                         help='The libvirt network name to use')
     parser.add_argument('--libvirt-nic-driver', default='e1000',
                         help='The libvirt network driver to use')
+    parser.add_argument('--console-log',
+                        help='File to log console')
     parser.add_argument('--emulator', default=None,
                         help='Path to emulator bin for vm template')
     args = parser.parse_args()
@@ -44,6 +65,7 @@
         'cpus': args.cpus,
         'bootdev': args.bootdev,
         'network': args.network,
+        'nicdriver': args.libvirt_nic_driver,
         'emulator': args.emulator,
     }
 
@@ -55,22 +77,13 @@
         elif os.path.exists("/usr/bin/qemu-kvm"):  # Redhat
             params['emulator'] = "/usr/bin/qemu-kvm"
 
-    nicparams = {
-        'nicdriver': args.libvirt_nic_driver,
-        'network': args.network,
-    }
-
-    params['bm_network'] = """
-<!-- neutron friendly 'bare metal' network -->
-<interface type='network'>
-  <source network='%(network)s'/>
-  <virtualport type='openvswitch'/>
-  <model type='%(nicdriver)s'/>
-  <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
-</interface>""" % nicparams
-
+    if args.console_log:
+        params['console_log'] = CONSOLE_LOG % {'console_log': args.console_log}
+    else:
+        params['console_log'] = ''
     libvirt_template = source_template % params
     conn = libvirt.open("qemu:///system")
+
     a = conn.defineXML(libvirt_template)
     print ("Created machine %s with UUID %s" % (args.name, a.UUIDString()))
 
diff --git a/tools/ironic/scripts/create-nodes b/tools/ironic/scripts/create-nodes
index d81113a..140bffe 100755
--- a/tools/ironic/scripts/create-nodes
+++ b/tools/ironic/scripts/create-nodes
@@ -4,7 +4,7 @@
 
 # Creates baremetal poseur nodes for ironic testing purposes
 
-set -exu
+set -ex
 
 # Keep track of the devstack directory
 TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
@@ -24,6 +24,7 @@
 TOTAL=$(($5 - 1))
 BRIDGE=$6
 EMULATOR=$7
+LOGDIR=$8
 
 LIBVIRT_NIC_DRIVER=${LIBVIRT_NIC_DRIVER:-"e1000"}
 LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
@@ -43,6 +44,10 @@
   virsh pool-start $LIBVIRT_STORAGE_POOL >&2
 fi
 
+if [ -n "$LOGDIR" ] ; then
+  mkdir -p "$LOGDIR"
+fi
+
 PREALLOC=
 if [ -f /etc/debian_version ]; then
     PREALLOC="--prealloc-metadata"
@@ -51,6 +56,11 @@
 DOMS=""
 for idx in $(seq 0 $TOTAL) ; do
     NAME="baremetal${BRIDGE}_${idx}"
+    if [ -n "$LOGDIR" ] ; then
+      VM_LOGGING="--console-log $LOGDIR/${NAME}_console.log"
+    else
+      VM_LOGGING=""
+    fi
     DOMS="$DOMS $NAME"
     VOL_NAME="baremetal${BRIDGE}-${idx}.qcow2"
     (virsh list --all | grep -q $NAME) && continue
@@ -62,7 +72,10 @@
     # Pre-touch the VM to set +C, as it can only be set on empty files.
     sudo touch "$volume_path"
     sudo chattr +C "$volume_path" || true
-    $TOP_DIR/scripts/configure-vm --bootdev network --name $NAME --image "$volume_path" --arch $ARCH --cpus $CPU --memory $MEM --libvirt-nic-driver $LIBVIRT_NIC_DRIVER --emulator $EMULATOR --network $BRIDGE >&2
+    $TOP_DIR/scripts/configure-vm \
+      --bootdev network --name $NAME --image "$volume_path" \
+      --arch $ARCH --cpus $CPU --memory $MEM --libvirt-nic-driver $LIBVIRT_NIC_DRIVER \
+      --emulator $EMULATOR --network $BRIDGE $VM_LOGGING >&2
 done
 
 for dom in $DOMS ; do
diff --git a/tools/ironic/templates/vm.xml b/tools/ironic/templates/vm.xml
index b18dec0..4f40334 100644
--- a/tools/ironic/templates/vm.xml
+++ b/tools/ironic/templates/vm.xml
@@ -27,14 +27,19 @@
     <controller type='ide' index='0'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
     </controller>
-    %(network)s
-    %(bm_network)s
+    <interface type='network'>
+      <source network='%(network)s'/>
+      <virtualport type='openvswitch'/>
+      <model type='%(nicdriver)s'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+    </interface>
     <input type='mouse' bus='ps2'/>
     <graphics type='vnc' port='-1' autoport='yes'/>
     <video>
       <model type='cirrus' vram='9216' heads='1'/>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
     </video>
+    %(console_log)s
     <memballoon model='virtio'>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
     </memballoon>