[Ovirt-devel] [PATCH node-image] Added new autotests and refactored the autotest script.

Darryl L. Pierce dpierce at redhat.com
Mon Apr 27 20:12:54 UTC 2009


Completely reworked the tests so that it would be easier to add or
extend tests. Added commandline arguments to enable debugging of tests,
open virt-viewer on a test vm while it's running. specify different ISOs
to test, run just a single or small set of tests, and to make the script
itself more robust.

Signed-off-by: Darryl L. Pierce <dpierce at redhat.com>
---
 autotest.sh |  854 +++++++++++++++++++++++++++++++++++------------------------
 1 files changed, 507 insertions(+), 347 deletions(-)

diff --git a/autotest.sh b/autotest.sh
index 6cba9fa..e31dcff 100755
--- a/autotest.sh
+++ b/autotest.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 #
 # oVirt node image autotest script
 #
@@ -36,71 +36,237 @@
 # This will, for each module whose autobuild.sh is run, to have a matching
 # autotest.sh to run as well.
 #
-# To run the test locally, all that's needed is for an ISO file named ovirt-node-image.iso
-# be present in the local directory. This will then be put through its paces with test
-# results being send to stdout.
+# To run these tests locally, you will need to open port 69 TCP and UDP and have
+# an ISO file.
 
 ME=$(basename "$0")
 warn() { printf '%s: %s\n' "$ME" "$*" >&2; }
 die() {  warn "$*"; exit 1; }
+debug() { if $debugging; then log "[DEBUG] %s" "$*"; fi }
 
-# trap '__st=$?; stop_log; exit $__st' 0
-trap '__st=$?; log "Exiting normally."; cleanup; exit $__st' 0
-trap '__st=$?; log "Dying a horrible death."; cleanup; exit $__st' 1 2 13 15
+trap '__st=$?; cleanup_after_testing; exit $__st' 0
+trap '__st=$?; log "Dying a horrible death."; cleanup_after_testing; exit $__st' 1 2 13 15
 
-test -n "$1" && RESULTS=$1 || RESULTS=autotest.log
+set -e
+set -u
 
-echo "Running oVirt node image Autotest"
+log () {
+    date=$(date)
+    printf "${date} $*\n"
+}
 
-# BZ#495954 needs to be fixed to uncomment this
-# set -e
-# set -v
+usage () {
+    cat <<EOF
+Usage: $ME [-n test_name] [LOGFILE]
+  -i: set the ISO filename (defualt: ovirt-node-image.iso)
+  -n: the name of the specific autotest to run (default: run all autotests)
+  -d: enable more verbose output (default: disabled)
+  -v: enable tracing (default: disabled)
+  -w: launch virt-viewer for each VM (default: no window shown)
+  -h: display this help and exit
+EOF
+}
 
-OVIRT_NODE_IMAGE_ISO=$PWD/ovirt-node-image.iso
+# $1 - the test function to call
+execute_test () {
+    local testname=$1
 
-if [ ! -f $OVIRT_NODE_IMAGE_ISO ]; then
-    die "Missing ovirt-node-image.iso file!"
-fi
+    if [ -z $testname ]; then die "Missing test name"; fi
 
-log () {
-    local text="`date` $*"
-    printf "${text}\n"
-    # sudo bash -c "printf \"[$$] ${text}\n\" >> ${RESULTS}"
+    log "Executing test: $testname"
+
+    eval $testname
+
+    rc=$?
+    log "Completed test: $testname [result=$rc]"
+
+    return $rc
+}
+
+# setup a node for pxeboot
+# $1 - the working directory
+# $2 - kernel arguments; if present then they replace all default flags
+setup_pxeboot () {
+    local workdir=$1
+    local kernelargs=$2
+    local pxedefault=$workdir/tftpboot/pxelinux.cfg/default
+
+    debug "setup for pxeboot: isofile=${isofile} workdir=${workdir} kernelargs='${kernelargs}' pxedefault=${pxedefault}"
+    (cd $workdir && sudo livecd-iso-to-pxeboot $isofile) > /dev/null 2>&1
+    sudo chmod -R 777 $workdir
+
+    # set default kernel arguments if none were provided
+    # the defaults boot in standalone mode
+    if [ -z "$kernelargs" ]; then
+	kernelargs="ovirt_standalone"
+    fi
+
+    local definition="DEFAULT pxeboot"
+    definition="${definition}\nTIMEOUT 20"
+    definition="${definition}\nPROMPT 0"
+    definition="${definition}\nLABEL pxeboot"
+    definition="${definition}\n     KERNEL vmlinuz0"
+    definition="${definition}\n     IPAPPEND 2"
+    definition="${definition}\n     APPEND rootflags=loop initrd=initrd0.img root=/${isoname} rootfstype=auto console=tty0 check console=ttyS0,115200n8 $kernelargs"
+
+    debug "pxeboot definition=\n${definition}"
+    sudo bash -c "printf \"${definition}\" > $pxedefault"
 }
 
-cleanup () {
-    log "CLEANING UP"
+# Starts a simple instance of dnsmasq.
+# $1 - the iface on which dnsmasq works
+# $2 - the root for tftp files
+# $3 - the mac address for the node (ignored if blank)
+# $4 - the nodename
+start_dnsmasq () {
+    local iface=$1
+    local tftproot=$2
+    local macaddress=$3
+    local nodename=$4
+    local pidfile=$2/dnsmasq.pid
+
     stop_dnsmasq
-    destroy_test_iface
+    debug "Starting dnsmasq"
+    dns_startup="sudo /usr/sbin/dnsmasq --read-ethers
+                                        --dhcp-range=${NETWORK}.100,${NETWORK}.254,255.255.255.0,24h
+                                        --interface=${iface}
+                                        --bind-interfaces
+                                        --except-interface=lo
+                                        --dhcp-boot=tftpboot/pxelinux.0
+                                        --enable-tftp
+                                        --tftp-root=${tftproot}
+                                        --log-facility=/tmp/dnsmasq-${nodename}.log
+                                        --log-queries
+                                        --log-dhcp
+                                        --pid-file=${pidfile}"
+    if [ -n "$macaddress" ]; then
+	dns_startup="${dns_startup} --dhcp-host=${macaddress},${NODE_ADDRESS}"
+    fi
+    # start dnsmasq
+    eval $dns_startup
+    debug "pidfile=$pidfile"
+    DNSMASQ_PID=$(sudo cat $pidfile)
+    debug "DNSMASQ_PID=${DNSMASQ_PID}"
 }
 
-# Creates a HD disk file.
+# Kills the running instance of dnsmasq.
+stop_dnsmasq () {
+    if [ -n "${DNSMASQ_PID-}" -a "${DNSMASQ_PID-}" != "0" ]; then
+	local check=$(ps -ef | awk "/${DNSMASQ_PID}/"' { if ($2 ~ '"${DNSMASQ_PID}"') print $2 }')
+
+	if [[ "${check}" == "${DNSMASQ_PID}" ]]; then
+	    debug "Killing dnsmasq: DNSMASQ_PID=${DNSMASQ_PID}"
+	    sudo kill -9 $DNSMASQ_PID
+	    return
+	fi
+    fi
+    DNSMASQ_PID="0"
+}
+
+# Creates a virt network.
+# $1 - the node name
+# $2 - the network interface name
+# $3 - use DHCP (any value)
+# $4 - start dnsmsq (def. false)
+start_networking () {
+    local nodename=$1
+    local ifacename=$2
+    local use_dhcp=${3-false}
+    local start_dnsmasq=${4-false}
+    local workdir=$5
+    local definition=""
+    local network=$NETWORK
+    local xmlfile=$(mktemp)
+
+    debug "start_networking ()"
+    for var in nodename ifacename use_dhcp start_dnsmasq workdir network xmlfile; do
+	eval debug "::$var: \$$var"
+    done
+
+    definition="<network>\n<name>${ifacename}</name>\n<forward mode='nat' />\n<bridge name='${ifacename}' stp='on' forwardDelay='0' />"
+    definition="${definition}\n<ip address='${network}.1' netmask='255.255.255.0'>"
+    if $use_dhcp; then
+	definition="${definition}\n<dhcp>\n<range start='${network}.100' end='${network}.199' />\n</dhcp>"
+    fi
+    definition="${definition}\n</ip>\n</network>"
+
+    debug "Saving network definition file to: ${xmlfile}\n"
+    sudo printf "${definition}" > $xmlfile
+    sudo virsh net-define $xmlfile > /dev/null 2>&1
+    debug "Starting network."
+    sudo virsh net-start $ifacename > /dev/null 2>&1
+
+    if [ "${use_dhcp}" == "false" ]; then
+	if $start_dnsmasq; then
+	    start_dnsmasq $ifacename $workdir "" $nodename
+	fi
+    fi
+}
+
+# Destroys the test network interface
+# $1 - the network name
+# $2 - stop dnsmasq (def. false)
+stop_networking () {
+    local networkname=${1-}
+    local stop_dnsmasq=${2-true}
+
+    # if no network was supplied, then check for the global network
+    if [ -z "$networkname" ]; then
+	networkname=${NETWORK_NAME-}
+    fi
+
+    if [ -n "${networkname}" ]; then
+	debug "Destroying network interface: ${networkname}"
+	check=$(sudo virsh net-list --all)
+	if [[ "${check}" =~ "${networkname}" ]]; then
+	    if [[ "{$check}" =~ active ]]; then
+		sudo virsh net-destroy $networkname > /dev/null 2>&1
+	    fi
+	    sudo virsh net-undefine $networkname > /dev/null 2>&1
+	fi
+
+        # ensure the bridge interface was destroyed
+	check=$(sudo /sbin/ifconfig)
+	if [[ "${check}" =~ "${networkname}" ]]; then
+	    sudo /sbin/ifconfig $networkname down
+	fi
+    fi
+
+    if $stop_dnsmasq; then
+	stop_dnsmasq
+    fi
+}
+
+# creates a HD disk file
 # $1 - filename for disk file
-# $2 - size
+# $2 - size (##M or ##G)
 create_hard_disk () {
     local filename=$1
     local size=$2
 
-    sudo qemu-img create -f raw $filename $size
-    sudo chcon -t virt_image_t $filename
+    debug "Creating hard disk: filename=${filename} size=${size}"
+    sudo qemu-img create -f raw $filename "${size}M" > /dev/null 2>&1
+    sudo chcon -t virt_image_t $filename > /dev/null 2>&1
 }
 
 # Creates the XML for a virtual machine.
 # $1 - the file to write the xml
 # $2 - the node name
-# $3 - memory size (in bytes)
-# $4 - the local hard disk (if blank then no disk is used)
-# $5 - the cdrom disk (if blank then no cdrom is used)
-# $6 - the network bridge (if blank then 'default' is used)
-# $7 - optional arguments
+# $3 - memory size (in kb)
+# $4 - boot device
+# $5 - the local hard disk (if blank then no disk is used)
+# $6 - the cdrom disk (if blank then no cdrom is used)
+# $7 - the network bridge (if blank then 'default' is used)
+# $8 - optional arguments
 define_node () {
     local filename=$1
     local nodename=$2
     local memory=$3
-    local harddrive=$4
-    local cddrive=$5
-    local bridge=$6
-    local options=$7
+    local boot_device=$4
+    local harddrive=$5
+    local cddrive=$6
+    local bridge=${7-default}
+    local options=${8-}
     local result=""
 
     # flexible options
@@ -111,23 +277,28 @@ define_node () {
     local vncport="-1"
     local bootdev='hd'
 
-    # if a cdrom was defined, then assume it's the boot device
-    if [ -n "$cddrive" ]; then bootdev='cdrom'; fi
+    # first destroy the node
+    destroy_node $nodename
 
     if [ -n "$options" ]; then eval "$options"; fi
 
+    debug "define_node ()"
+    for var in filename nodename memory harddrive cddrive bridge options arch emulator serial vncport bootdev; do
+	eval debug "::$var: \$$var"
+    done
+
     result="<domain type='kvm'>\n<name>${nodename}</name>\n<memory>${memory}</memory>\n <vcpu>1</vcpu>"
 
     # begin the os section
     # inject the boot device
     result="${result}\n<os>\n<type arch='${arch}' machine='pc'>hvm</type>"
-    result="${result}\n<boot dev='${bootdev}' />"
+    result="${result}\n<boot dev='${boot_device}' />"
     result="${result}\n</os>"
 
     # virtual machine features
     result="${result}\n<features>"
     result="${result}\n<acpi />"
-    if [ -z "${noapic}" ]; then result="${result}\n<apic />"; fi
+    if [ -z "${noapic-}" ]; then result="${result}\n<apic />"; fi
     result="${result}\n<pae /></features>"
     result="${result}\n<clock offset='utc' />"
     result="${result}\n<on_poweroff>destroy</on_poweroff>"
@@ -139,6 +310,7 @@ define_node () {
     result="${result}\n<emulator>${emulator}</emulator>"
     # inject the hard disk if defined
     if [ -n "$harddrive" ]; then
+	debug "Adding a hard drive to the node"
 	result="${result}\n<disk type='file' device='disk'>"
 	result="${result}\n<source file='$harddrive' />"
 	result="${result}\n<target dev='vda' bus='virtio' />"
@@ -146,6 +318,7 @@ define_node () {
     fi
     # inject the cdrom drive if defined
     if [ -n "$cddrive" ]; then
+	debug "Adding a CDROM drive to the node"
 	result="${result}\n<disk type='file' device='cdrom'>"
 	result="${result}\n<source file='${cddrive}' />"
 	result="${result}\n<target dev='hdc' bus='ide' />"
@@ -169,398 +342,385 @@ define_node () {
 
     result="${result}\n</domain>"
 
-    log "Saving node definition to file: ${filename}"
+    debug "Node definition: ${filename}"
     sudo printf "$result" > $filename
 
     # now define the vm
-    sudo virsh define $filename
+    sudo virsh define $filename > /dev/null 2>&1
 
     if [ $? != 0 ]; then die "Unable to define virtual machine: $nodename"; fi
 }
 
-# Returns the mac address for the given node.
-# $1 - the node name
-# $2 - the variable name to set
-get_mac_address () {
-    local nodename=$1
-    local varname=$2
-
-    if [ -z "$nodename" ]; then die "Cannot get mac address for node with a name"; fi
-
-    address=$(sudo virsh dumpxml $nodename|awk '/<mac address/ {
-              match($0,"mac address='"'"'(.*)'"'"'",data); print data[1]}')
-
-    if [ -z "$varname" ]; then die "Cannot set unnamed varilable"; fi
-    eval $varname="$address"
-}
-
-# Starts the named node.
 # $1 - the node name
-start_node () {
+# $2 - the boot device (def. "hd")
+# $3 - the memory size in kb (def. 524288)
+# $4 - hard disk size (if blank then no hard disk)
+# $5 - the cd drive image file (if blank then no cd drive)
+# $6 - option arguments
+configure_node () {
     local nodename=$1
+    local boot_device=$2
+    local memory=$3
+    local hdsize=$4
+    local hdfile=""
+    local cdfile=$5
+    local args=$6
+    local nodefile=$(mktemp)
+
+    if [ -z "${boot_device}" ]; then boot_device="hd"; fi
+    if [ -z "${memory}" ]; then memory="524288"; fi
+
+    debug "configure_node ()"
+    for var in nodename boot_device memory hdsize hdfile cdfile args nodefile; do
+	eval debug "::$var: \$$var"
+    done
+
+    # create the hard disk file
+    if [ -n "${hdsize}" ]; then
+	hdfile=$(mktemp)
+	create_hard_disk $hdfile $hdsize
+    fi
 
-    if [ -z "$nodename" ]; then die "Cannot start node without a name"; fi
-
-    sudo virsh start $nodename
+    define_node $nodefile $nodename "${memory}" "${boot_device}" "${hdfile}" "${cdfile}" $IFACE_NAME "${args}"
 }
 
-# Destroys any existing instance of the given node.
 # $1 - the node name
+# $2 - undefine the node (def. true)
 destroy_node () {
     local nodename=$1
+    local undefine=${2-true}
+
+    for var in nodename undefine; do
+	eval debug "::$var: \$$var"
+    done
 
     if [ -n "${nodename}" ]; then
-	log "Destroying VM: ${nodename}"
 	check=$(sudo virsh list --all)
 	if [[ "${check}" =~ "${nodename}" ]]; then
 	    if [[ "${check}" =~ running ]]; then
-		sudo virsh destroy $nodename
+		debug "Destroying node: $nodename"
+		sudo virsh destroy $nodename > /dev/null 2>&1
+	    fi
+	    if $undefine; then
+		sudo virsh undefine $nodename > /dev/null 2>&1
 	    fi
-	    sudo virsh undefine $nodename
 	fi
     fi
 }
 
-# PXE boots a node.
-# $1 - the ISO file
-# $2 - the working directory
-# $3 - kernel arguments; if present then they replace all default flags
-setup_pxeboot () {
-    local isofile=$1
-    local workdir=$2
-    local kernelargs=$3
-    local pxedefault=$workdir/tftpboot/pxelinux.cfg/default
+# for each test created, add it to the follow array:
+tests=''; testcount=0;
 
-    (cd $workdir && sudo livecd-iso-to-pxeboot $isofile)
-    sudo chmod -R 777 $workdir
-
-    # set default kernel arguments if none were provided
-    # the defaults boot in standalone mode
-    if [ -z "$kernelargs" ]; then
-	kernelargs="ovirt_standalone"
-    fi
+# $1 - test name
+add_test () {
+    tests[$testcount]=$1
+    testcount=$testcount+1
+}
 
-    local definition="DEFAULT pxeboot\nTIMEOUT 20\nPROMPT 0\nLABEL pxeboot\n     KERNEL vmlinuz0\n     IPAPPEND 2\n     APPEND rootflags=loop BOOTIF=link|eth*|<MAC> initrd=initrd0.img root=/ovirt-node-image.iso rootfstype=auto console=ttyS0,115200n8 $kernelargs\n"
+# $1 - node name
+start_virt_viewer () {
+    local nodename=$1
 
-    sudo bash -c "printf \"${definition}\" > $pxedefault"
+    sudo virt-viewer $nodename > /dev/null 2>&1&
 }
 
-# Launches the node as a virtual machine.
-# $1 - the node name
-# $2 - the ISO filename
-# $3 - the hard disk file
-# $4 - the memory size (in MB)
-# $5 - the network bridge to use
-# $6 - kernel arguments
-# $7 - verification method
-pxeboot_node_vm () {
+# $1 - the node's name
+# $2 - kernel arguments
+# $3 - working directory
+boot_with_pxe () {
     local nodename=$1
-    local isofile=$2
-    local diskfile=$3
-    local memsize=$4
-    local bridge=$5
-    local kernel_args=$6
-    local verify_method=$7
-    local xmlfile=$(mktemp)
-    local tftproot=$(mktemp -d)
-    local node_mac_address=""
-    local return_code=0
+    local kernel_args=$2
+    local workdir=$3
 
-    destroy_node $nodename
+    log "boot_with_pxe ()"
+    debug "-      workdir: ${workdir}"
+    debug "-     nodename: ${nodename}"
+    debug "-  kernel_args: ${kernel_args}"
 
-    log "Beginning pxeboot for $nodename"
-    # setup the dnsmasq instance with the iso setup
-    setup_pxeboot "$isofile" "$tftproot" "$kernel_args"
-    create_test_iface $bridge
-    define_node $xmlfile $nodename $memsize "$diskfile" "" $bridge "local bootdev='network'; local noapic='yes'"
-    get_mac_address $nodename "node_mac_address"
-    start_dnsmasq $bridge $tftproot $node_mac_address $nodename
-    start_node $nodename
-    if [ -n "$verify_method" ]; then
-	eval $verify_method
-	return_code=$?
-    fi
-    destroy_node $nodename
-    stop_dnsmasq
-    destroy_test_iface $bridge
-    log "Finished pxeboot for $nodename (RC=${return_code})"
+    setup_pxeboot $workdir "${kernel_args}"
 
-    if [ $return_code != 0 ]; then
-	log "Test ended in failure"
+    sudo virsh start $nodename > /dev/null 2>&1
+    if $show_viewer; then
+	start_virt_viewer $nodename
     fi
-
-    test $return_code == 0 && return 0 || return 1
 }
 
-# Launches the node as a virtual machine with a CDROM.
-# $1 - the node name
-# $2 - the ISO filename
-# $3 - the disk file to use
-# $4 - the memory size (in MB)
-# $5 - the network bridge
-cdrom_boot_node_vm () {
+# $1 - the node's name
+boot_from_hd () {
     local nodename=$1
-    local isofile=$2
-    local diskfile=$3
-    local memsize=$4
-    local bridge=$5
-    local xmlfile=$(mktemp)
 
-    destroy_node $nodename
+    debug "boot_from_hd ()"
+    debug "::nodename: ${nodename}"
 
-    log "Beginning cdrom boot for $nodename"
-    create_test_iface $bridge "yes"
-    define_node $xmlfile $nodename $memsize "$diskfile" "$isofile" $bridge
-    start_node $nodename
-    # TODO make sure the node's booted
-    sleep 300
-    # TODO verify the node's running
-    destroy_node $nodename
-    destroy_test_iface $bridge
-    log "Finished cdrom booting for $nodename"
+    sudo virsh start $nodename > /dev/null 2>&1
+    if $show_viewer; then
+	start_virt_viewer $nodename
+    fi
 }
 
-# Creates a virt network.
-# $1 - the network interface name
-# $2 - use DHCP (any value)
-create_test_iface () {
-    local name=$1
-    local dhcp=$2
-    local definition=$(mktemp)
-    local network=$NETWORK
-    local definition=""
-    local xmlfile=$(mktemp)
+# $1 - the node name
+# $2 - the old boot device
+# $3 - the new boot device
+substitute_boot_device () {
+    local nodename=$1
+    local old_device=$2
+    local new_device=$3
+    local new_node_file=$(mktemp)
 
-    destroy_test_iface $name
-    NETWORK_NAME=$name
+    if [ -n "${nodename}" ]; then
+	local xml=$(sudo virsh dumpxml $nodename | sed "s/boot dev='"${old_device}"'/boot dev='"${new_device}"'/")
 
-    log "Creating network definition file: $definition"
-    definition="<network>\n<name>${name}</name>\n<forward mode='nat' />\n<bridge name='${name}' stp='on' forwardDelay='0' />"
-    definition="${definition}\n<ip address='${network}.1' netmask='255.255.255.0'>"
-    if [ -n "$dhcp" ]; then
-	definition="${definition}\n<dhcp>\n<range start='${network}.100' end='${network}.199' />\n</dhcp>"
-    fi
-    definition="${definition}\n</ip>\n</network>"
+	sudo printf "${xml}" > $new_node_file
 
-    printf "Saving network definition file to: ${xmlfile}\n"
-    sudo printf "${definition}" > $xmlfile
-    sudo virsh net-define $xmlfile
-    log "Starting network"
-    sudo virsh net-start $name
+	sudo virsh define $new_node_file
+    fi
 }
 
-# Destroys the test network interface
-# $1 - the network name
-destroy_test_iface () {
-    local networkname=$1
+add_test "test_stateless_pxe_with_nohd"
+test_stateless_pxe_with_nohd () {
+    local nodename="stateless-pxe-nohd"
+    local workdir=$(mktemp -d)
 
-    # if no network was supplied, then check for the global network
-    if [ -z "$networkname" ]; then
-	networkname=$NETWORK_NAME
-    fi
+    start_networking $nodename $IFACE_NAME false true $workdir
 
-    if [ -n "${networkname}" ]; then
-	log "Destroying network interface: ${networkname}"
-	check=$(sudo virsh net-list --all)
-	if [[ "${check}" =~ "${networkname}" ]]; then
-	    log "- found existing instance"
-	    if [[ "{$check}" =~ active ]]; then
-		log "- shutting down current instance"
-		sudo virsh net-destroy $networkname
-	    fi
-	    log "- undefining previous instance"
-	    sudo virsh net-undefine $networkname
-	fi
+    configure_node "${nodename}" "network" "" "" "" "local noapic=true"
+    boot_with_pxe "${nodename}" "ovirt_firstboot=yes" "${workdir}"
 
-        # ensure the bridge interface was destroyed
-	check=$(sudo /sbin/ifconfig)
-	if [[ "${check}" =~ "${networkname}" ]]; then
-	    sudo /sbin/ifconfig $networkname down
-	fi
-    fi
-}
+    expect -c '
+set timeout 120
+log_file -noappend stateless-pxe-nohd.log
 
-# Starts a simple instance of dnsmasq.
-# $1 - the iface on which dnsmasq works
-# $2 - the root for tftp files
-# $3 - the mac address for the node (ignored if blank)
-# $4 - the nodename
-start_dnsmasq () {
-    local iface=$1
-    local tftproot=$2
-    local macaddress=$3
-    local nodename=$4
-    local pidfile=$2/dnsmasq.pid
+spawn sudo virsh console stateless-pxe-nohd
 
-    stop_dnsmasq
-    log "Starting dnsmasq"
-    dns_startup="sudo /usr/sbin/dnsmasq --read-ethers
-                                        --dhcp-range=${NETWORK}.100,${NETWORK}.254,255.255.255.0,24h
-                                        --interface=${iface}
-                                        --bind-interfaces
-                                        --except-interface=lo
-                                        --dhcp-boot=tftpboot/pxelinux.0
-                                        --enable-tftp
-                                        --tftp-root=${tftproot}
-                                        --log-facility=/tmp/dnsmasq-${nodename}.log
-                                        --log-queries
-                                        --log-dhcp
-                                        --pid-file=${pidfile}"
-    if [ -n "$macaddress" ]; then
-	dns_startup="${dns_startup} --dhcp-host=${macaddress},${NODE_ADDRESS}"
-   fi
-    # start dnsmasq
-    eval $dns_startup
-    DNSMASQ_PID=$(sudo cat $pidfile)
-    log "dnsmasq start: PID=${DNSMASQ_PID}"
+expect {
+    -exact "Linux version"         { send_log "\n\nMarker 1\n\n"; exp_continue }
+    -exact "Starting ovirt-early:" { send_log "\n\nMarker 2\n\n"; exp_continue }
+    -exact "Starting ovirt:"       { send_log "\n\nMarker 3\n\n"; exp_continue }
+    -exact "Starting ovirt-post:"  { send_log "\n\nMarker 4\n\n"; exp_continue }
+    -exact "login:"      { send_log "\n\nMarker 5\n\n"; exit }
+    timeout {
+        send_log "\nMarker not found.\n\n"
+	exit 1
+    } eof {
+        send_log "Unexpected end of file."
+	exit 2
+    }
 }
 
-# Kills the running instance of dnsmasq.
-stop_dnsmasq () {
-    log "Killing dnsmasq: DNSMASQ_PID=${DNSMASQ_PID}"
-    if [ -n "$DNSMASQ_PID" -a "$DNSMASQ_PID" != "0" ]; then
-	local check=$(ps -ef | awk "/${DNSMASQ_PID}/"' { if ($2 ~ '"${DNSMASQ_PID}"') print $2 }')
+send_log \"\\n\\nUnexpected end of interaction.\\n\\n\"
+exit 3'
 
-	if [[ "${check}" == "${DNSMASQ_PID}" ]]; then
-	    log "Killing dnsmasq"
-	    sudo kill -9 $DNSMASQ_PID
-	    return
-	fi
-    fi
-    log "No running instance of dnsmasq found."
-    DNSMASQ_PID="0"
-}
+    result=$?
 
-# Boots a node via CDROM.
-# $1 - the node name
-# $2 - the network to use
-# $3 - the working directory
-# $4 - the ISO file to use as CDROM
-cdrom_boot () {
-    local nodename=$1
-    local network=$2
-    local workdir=$3
-    local isofile=$4
-    local diskfile=$workdir/ovirt-harddisk.img
+    destroy_node $nodename
+    stop_networking $IFACE_NAME true
 
-    create_hard_disk $diskfile "10G"
-    cdrom_boot_node_vm $nodename $isofile $diskfile "512" $network
+    return $result
 }
 
-# verify that a node has booted properly
-# $1 - the node's name
-# $2 - the logfile to use
-verify_pxeboot_stateless_standalone () {
-    local nodename=$1
-    local port=$(sudo virsh ttyconsole $nodename)
-    local logfile=$2
+add_test "test_stateless_pxe"
+test_stateless_pxe () {
+    local nodename="stateless-pxe"
+    local workdir=$(mktemp -d)
+
+    start_networking $nodename $IFACE_NAME false true $workdir
+
+    configure_node "${nodename}" "network" "" "" "" "local noapic=true"
+    boot_with_pxe "${nodename}" "ovirt_firstboot=yes" "${workdir}"
+
+    expect -c 'set timeout 120
+log_file -noappend stateless-pxe.log
+
+spawn sudo virsh console stateless-pxe
 
-    log "Verifying ${nodename} is booted correctly"
-    local script='
-log_file -noappend '"${logfile}"'
-set timeout 60
-expect {
-    "Linux version" {send_log "\n\n***\nGot first boot marker\n\n"}
-     timeout {send_log "\n\n***\nDid not receive in time\n\n"
-              exit 1}
-}
 expect {
-    -re "Kernel command line.*ovirt_standalone" {send_log "\n\n***\nGot kernel arguments marker\n\n"}
+    -exact "Linux version"         { send_log "\n\nMarker 1\n\n"; exp_continue }
+    -exact "Starting ovirt-early:" { send_log "\n\nMarker 2\n\n"; exp_continue }
+    -exact "Starting ovirt:"       { send_log "\n\nMarker 3\n\n"; exp_continue }
+    -exact "Starting ovirt-post:"  { send_log "\n\nMarker 4\n\n"; exp_continue }
+    -re    "localhost.*login:"     { send_log "\n\nMarker 5\n\n"; exit }
     timeout {
-       send_log "\n\n***\nDid not receive in time\n\n"
-       exit 2
+        send_log "\nMarker not found.\n\n"
+	exit 1
+    } eof {
+        send_log "Unexpected end of file."
+	exit 2
     }
 }
-expect {
-    "Starting ovirt-early:" {send_log "\n\n***\nGot ovirt-early marker\n\n"}
-    timeout {send_log "\n\n***\nDid not receive in time\n\n"
-             exit 3}
-}
-expect {
-    "Starting ovirt:" {send_log "\n\n***\nGot ovirt marker\n\n"}
-    timeout {send_log "\n\n***\nDid not receive in time\n\n"
-             exit 4}
+
+send_log "\n\nUnexpected end of interaction.\n\n"
+exit 3'
+    result=$?
+
+    destroy_node $nodename
+    stop_networking $IFACE_NAME true
+
+    return $result
 }
+
+# add_test "test_stateful_pxe"
+test_stateful_pxe () {
+    local nodename="stateful-pxe"
+    local workdir=$(mktemp -d)
+    local ipaddress=${NODE_ADDRESS}
+
+    for var in nodename workdir ipaddress; do
+	eval debug "::\$$var: $var"
+    done
+
+    start_networking $nodename $IFACE_NAME false true $workdir
+
+    configure_node "${nodename}" "network" "" "10000" "" "local noapic=true"
+    boot_with_pxe "${nodename}" "ovirt_standalone ovirt_init=/dev/vda ovirt_local_boot ip=${ipaddress}" ${workdir}
+
+    # verify the booting and installation
+    expect -c '
+set timeout 120
+log_file -noappend stateful-pxe.log
+
+spawn sudo virsh console stateful-pxe
+
 expect {
-    "Starting ovirt-post:"  {send_log "\n\n***\nGot ovirt-post marker\n\n"}
-    timeout {send_log "\n\n***\nDid not receive in time\n\n"
-             exit 5}
+    -exact "Linux version"                     { send_log "\n\nMarker 1\n\n"; exp_continue }
+    -exact "Starting ovirt-early:"             { send_log "\n\nMarker 2\n\n"; exp_continue }
+    -exact "Starting ovirt:"                   { send_log "\n\nMarker 3\n\n"; exp_continue }
+    -exact "Starting ovirt-post:"              { send_log "\n\nMarker 4\n\n"; exp_continue }
+    -exact "Starting ovirt-firstpost:"         { send_log "\n\nMarker 5\n\n"; exp_continue }
+    -exact "Starting partitioning of /dev/vda" { send_log "\n\nMarker 6\n\n"; exp_continue }
+    -exact "Restarting system"                 { send_log "\n\nMarker 7\n\n"; exit }
+    timeout {
+        send_log "\nMarker not found.\n\n"
+	exit 1
+    } eof {
+        send_log "Unexpected end of file."
+	exit 2
+    }
 }
-expect {
-    "Starting ovirt-firstboot:" {send_log "\n\n***\nGot ovirt-firstboot marker\n\n"}
-    timeout {send_log "\n\n***\nDid not receive in time\n\n"
-             exit 6}
-}'
 
-    sudo bash -c "/usr/bin/expect -c '${script}' < ${port}"
+send_log "\n\nUnexpected end of interaction.\n\n"
+exit 3'
     result=$?
-    printf "result=${result}\n"
-}
 
-# Verify that a stateful node has booted properly.
-# $1 - the node's name
-# $2 - the logfile for recording the transcript
-verify_pxeboot_stateful_standalone () {
-    local nodename=$1
-    local port=$(sudo virsh ttyconsole $nodename)
-    local logfile=$2
-
-    # leverage the existing stateless test
-    verify_pxeboot_stateless_standalone $nodename
-    log "Verifying ${nodename} is booted correctly"
-    local script='
-log_file -noappend '"${logfile}"'
-set timeout 180
+    # only continue if we're in a good state
+    if [ $result -eq 0 ]; then
+	destroy_node "stateful-pxe" false
+	substitute_boot_device "stateful-pxe" "network" "hd"
+	boot_from_hd  "stateful-pxe"
+
+	expect -c '
+set timeout 120
+log_file stateful-pxe.log
+
+send_log "Restarted node, booting from hard disk.\n"
+
+spawn sudo virsh console stateful-pxe
+
 expect {
-    -re "login:$" {send_log "\n\n***\nGot login prompt!\n\n"}
-    timeout {send_log "\n\n***\nDid not receive in time\n\n"
-             exit 7}
-}'
-    sudo bash -c "/usr/bin/expect -c '${script}' < ${port}"
+    -re "localhost.*login:" { send_log "\n\nLogin marker found\n\n"; exit }
+
+    timeout {
+        send_log "\nMarker not found.\n\n"
+        exit 1
+    } eof {
+        send_log "Unexpected end of file."
+        exit 2
+    }
 }
 
-# TEST: Performs a PXE boot of the node as a standalone, stateless instance.
-test_pxeboot_stateless_standalone () {
-    local nodename="pxe_stateless_standalone-$$"
-    local hdfile=$(mktemp)
+send_log "\n\nUnexpected end of interaction.\n\n"
 
-    log "TEST: Booting a stateless standalone node via PXE."
-    create_hard_disk $hdfile "10G"
-    pxeboot_node_vm $nodename $OVIRT_NODE_IMAGE_ISO "${hdfile}" "524288" \
-	            $IFACE_NAME "ovirt_standalone OVIRT_FIRSTBOOT=no" \
-                    "verify_pxeboot_stateless_standalone $nodename 'pxeboot_stateless_standalone.log'"
-}
+exit 3
+'
 
-# TEST: Performs a PXE boot of the node as a standalone instance. The node then performs a full install
-test_pxeboot_stateful_standalone () {
-    local nodename="pxe_stateful_standalone-$$"
-    local hdfile=$(mktemp)
+	expect -c '
+set timeout 3
+log_file stateful-pxe.log
 
-    log "TEST: Installing a stateful standalone node via PXE."
-    create_hard_disk $hdfile "10G"
-    pxeboot_node_vm $nodename $OVIRT_NODE_IMAGE_ISO "${hdfile}" "524288" \
-	            $IFACE_NAME "ovirt_standalone OVIRT_FIRSTBOOT=no ovirt_init=/dev/vda" \
-	            "verify_pxeboot_stateful_standalone $nodename 'pxeboot_stateful_standalone.log'"
+spawn ping -c 3 '"${ipaddress}"'
+
+expect {
+    -exact "64 bytes from '"${ipaddress}"'" { send_log "\n\nGot ping response!\n"; send_log "\n\nNetworking verified!\n"; exit }
+
+    timeout {
+        send_log "\nMarker not found.\n\n"
+        exit 1
+    } eof {
+        send_log "Unexpected end of file."
+        exit 2
+    }
 }
 
-# TEST: Performs a CDROM boot of the node as a standalone, stateless instance
-test_cdrom_stateless_standalone () {
-    local nodename="stateless_cdrom_standalone-$$"
+send_log "\n\nUnexpected end of interaction.\n\n"
+
+exit 3'
+
+	result=$?
+    fi
+
+    destroy_node $nodename
+    stop_networking $IFACE_NAME true
+
+    return $result
 
-    log "TEST: Booting a stateless node from CDROM."
-    cdrom_boot $nodename "$IFACE_NAME" "$TFTP_ROOT_DIR" "$OVIRT_NODE_IMAGE_ISO"
 }
 
-# automated testing entry points
-{
+# configures the environment for testing
+setup_for_testing () {
+    debug "isofile=${isofile}"
+    debug "isoname=${isoname}"
     IFACE_NAME=testbr$$
+    debug "IFACE_NAME=${IFACE_NAME}"
     NETWORK=192.168.$(echo "scale=0; print $$ % 255" | bc -l)
+    debug "NETWORK=${NETWORK}"
     NODE_ADDRESS=$NETWORK.100
+    debug "NODE_ADDRESS=${NODE_ADDRESS}"
     DNSMASQ_PID=0
+}
+
+# cleans up any loose ends
+cleanup_after_testing () {
+    stop_dnsmasq
+    stop_networking
+}
+
+# check commandline options
+test=''
+debugging=false
+isofile="${PWD}/ovirt-node-image.iso"
+show_viewer=false
+
+while getopts di:n:vwh c; do
+    case $c in
+	d) debugging=true;;
+	i) isofile=($OPTARG);;
+	n) tests=($OPTARG);;
+	v) set -v;;
+	w) show_viewer=true;;
+	h) usage; exit 0;;
+	'?') die "invalid option \`-$OPTARG'";;
+	:) die "missing argument to \`-$OPTARG' option";;
+	*) die "internal error";;
+    esac
+done
+
+isoname=$(basename $isofile)
+isofile="$(cd `dirname $isofile`; pwd)/${isoname}"
+
+shift $(($OPTIND - 1))
+
+set +u
+if [ $# -gt 0 -a -n "$1" ]; then RESULTS=$1; else RESULTS=autotest.log; fi
+set -u
+
+log "Logging results to file: ${RESULTS}"
+{
+    setup_for_testing
+
+    log "Begin Testing: RHEV-H"
 
-    log "Starting tests"
-    log "Using network: ${NETWORK}.0"
+    for test in ${tests[@]}; do
+	execute_test $test
+    done
 
-    test_pxeboot_stateless_standalone
-    test_pxeboot_stateful_standalone
+    log "End Testing: RHEV-H"
 } | sudo tee --append $RESULTS
-- 
1.6.0.6




More information about the ovirt-devel mailing list