All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] [RFC] Libvirt test v2
@ 2011-10-11 21:07 Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 02/11] virt: Introducing virt_test.virt_test class Lucas Meneghel Rodrigues
                   ` (9 more replies)
  0 siblings, 10 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm, Lucas Meneghel Rodrigues

Hi guys, this is an updated version of the Libvirt test.
Cleber has made some great work and fixed a bunch of
problems involving using libvirt Xen backend, and now
it is possible to run most of the autotest tests using
libvirt on both KVM and Xen backends.

This patchset was also sent as a pull request on github,
so you can comment in there, if you wish so.

https://github.com/autotest/autotest/pull/31

Cleber Rosa (3):
  Virt: builtin HTTP server for unattended installs
  Virt: support XEN via libvirt and auto url installer
  Virt: add support for XEN via libvirt installs and auto url

Lucas Meneghel Rodrigues (8):
  virt: Move data dirs from KVM test to client.virt
  virt: Introducing virt_test.virt_test class
  Moving unattended_install test from kvm test to common virt location
  Moving get_started code to client.virt.virt_utils
  virt: Introducing libvirt VM class
  virt: Introducing libvirt monitor
  virt.virt_env_process: Add libvirt vm handling
  client.tests: Introducing libvirt test

 client/tests/kvm/autoit/notepad1.au3               |   44 -
 client/tests/kvm/autotest_control/bonnie.control   |   21 -
 .../tests/kvm/autotest_control/cpu_hotplug.control |   10 -
 client/tests/kvm/autotest_control/ctcs.control     |   19 -
 client/tests/kvm/autotest_control/dbench.control   |   20 -
 client/tests/kvm/autotest_control/disktest.control |   15 -
 client/tests/kvm/autotest_control/ebizzy.control   |   11 -
 client/tests/kvm/autotest_control/flail.control    |   17 -
 .../tests/kvm/autotest_control/hackbench.control   |   13 -
 client/tests/kvm/autotest_control/hwclock.control  |   12 -
 client/tests/kvm/autotest_control/iozone.control   |   18 -
 .../tests/kvm/autotest_control/kernbench.control   |   12 -
 .../kvm/autotest_control/monotonic_time.control    |   37 -
 client/tests/kvm/autotest_control/npb.control      |   28 -
 client/tests/kvm/autotest_control/rtc.control      |   15 -
 client/tests/kvm/autotest_control/scrashme.control |   14 -
 .../tests/kvm/autotest_control/sleeptest.control   |   15 -
 client/tests/kvm/autotest_control/stress.control   |   14 -
 .../tests/kvm/autotest_control/systemtap.control   |   14 -
 client/tests/kvm/autotest_control/tsc.control      |   13 -
 client/tests/kvm/deps/Makefile                     |    8 -
 client/tests/kvm/deps/finish.cpp                   |  144 -
 client/tests/kvm/deps/finish.exe                   |  Bin 31007 -> 0 bytes
 client/tests/kvm/deps/heartbeat_slu.py             |  205 --
 client/tests/kvm/deps/rss.cpp                      | 1011 -------
 client/tests/kvm/deps/rss.exe                      |  Bin 94518 -> 0 bytes
 client/tests/kvm/deps/rss.reg                      |   15 -
 client/tests/kvm/deps/setuprss.bat                 |   21 -
 client/tests/kvm/deps/test_clock_getres/Makefile   |   11 -
 .../kvm/deps/test_clock_getres/test_clock_getres.c |   58 -
 client/tests/kvm/deps/whql_delete_machine_15.cs    |   82 -
 client/tests/kvm/deps/whql_delete_machine_15.exe   |  Bin 5632 -> 0 bytes
 client/tests/kvm/deps/whql_submission_15.cs        |  373 ---
 client/tests/kvm/deps/whql_submission_15.exe       |  Bin 12288 -> 0 bytes
 client/tests/kvm/get_started.py                    |  162 +-
 client/tests/kvm/kvm.py                            |  123 +-
 client/tests/kvm/scripts/ksm_overcommit_guest.py   |  237 --
 client/tests/kvm/scripts/multicast_guest.py        |   37 -
 client/tests/kvm/scripts/virtio_console_guest.py   |  929 -------
 client/tests/kvm/steps/Belenix-0.7.1.steps         |  198 --
 client/tests/kvm/steps/CentOS5-64.steps            |  316 ---
 client/tests/kvm/steps/DSL-4.2.5.steps             |  482 ----
 client/tests/kvm/steps/Fedora-11-64.steps          |  300 --
 client/tests/kvm/steps/Fedora-8-64.steps           |  281 --
 client/tests/kvm/steps/Fedora-8-i386.steps         |  317 ---
 client/tests/kvm/steps/Fedora-9-64.steps           |  274 --
 client/tests/kvm/steps/Fedora-9-i386.steps         |  268 --
 client/tests/kvm/steps/FreeSBIE-2.0.1.steps        |  198 --
 client/tests/kvm/steps/Mandriva-One-2007-32.steps  |  480 ----
 client/tests/kvm/steps/NetBSD-1.6.2.steps          |  241 --
 client/tests/kvm/steps/OpenBSD-4.1-32.steps        |  348 ---
 client/tests/kvm/steps/RHEL-3.9-i386.steps         |  316 ---
 client/tests/kvm/steps/RHEL-3.9-x86_64.steps       |  311 ---
 client/tests/kvm/steps/RHEL-4.7-i386.steps         |  297 --
 client/tests/kvm/steps/RHEL-4.7-x86_64.steps       |  323 ---
 client/tests/kvm/steps/RHEL-5.3-i386.steps         |  306 --
 client/tests/kvm/steps/RHEL-5.3-x86_64.steps       |  298 --
 client/tests/kvm/steps/Slax-6.0.7.steps            |  311 ---
 client/tests/kvm/steps/Ubuntu-6.10-32.steps        |  127 -
 .../tests/kvm/steps/Ubuntu-8.04-32-setupssh.steps  |  184 --
 client/tests/kvm/steps/Ubuntu-8.04-32.steps        |  246 --
 client/tests/kvm/steps/Ubuntu-8.04-server-32.steps |  210 --
 client/tests/kvm/steps/Ubuntu-8.10-64.steps        |  165 --
 .../kvm/steps/Ubuntu-8.10-server-32-gcc.steps      |  148 -
 client/tests/kvm/steps/Ubuntu-8.10-server-32.steps |  258 --
 client/tests/kvm/steps/Win-Vista-32.steps          |  152 -
 client/tests/kvm/steps/Win-Vista-64.steps          |  153 -
 client/tests/kvm/steps/Win2000-32-rss.steps        |   52 -
 client/tests/kvm/steps/Win2000-32-setupssh.steps   |  106 -
 client/tests/kvm/steps/Win2000-32.steps            |  119 -
 client/tests/kvm/steps/Win2003-32-rss.steps        |   49 -
 client/tests/kvm/steps/Win2003-32-setupssh.steps   |  109 -
 client/tests/kvm/steps/Win2003-32.steps            |  231 --
 client/tests/kvm/steps/Win2003-64-rss.steps        |   47 -
 client/tests/kvm/steps/Win2003-64.steps            |  154 -
 client/tests/kvm/steps/Win2008-32-rss.steps        |   49 -
 client/tests/kvm/steps/Win2008-32-setupssh.steps   |   83 -
 .../tests/kvm/steps/Win2008-32-setuptelnet.steps   |   86 -
 client/tests/kvm/steps/Win2008-32.steps            |  139 -
 client/tests/kvm/steps/Win2008-64-rss.steps        |   52 -
 client/tests/kvm/steps/Win2008-64.steps            |  105 -
 client/tests/kvm/steps/Win7-64-rss.steps           |  121 -
 client/tests/kvm/steps/Win7-64.steps               |  187 --
 client/tests/kvm/steps/WinVista-32-rss.steps       |   53 -
 client/tests/kvm/steps/WinVista-64-rss.steps       |   53 -
 client/tests/kvm/steps/WinXP-32-rss.steps          |   31 -
 client/tests/kvm/steps/WinXP-32-setupssh.steps     |   98 -
 client/tests/kvm/steps/WinXP-32.steps              |  175 --
 client/tests/kvm/steps/WinXP-64-rss.steps          |   34 -
 client/tests/kvm/steps/WinXP-64.steps              |  111 -
 client/tests/kvm/steps/memtest86+.steps            |    9 -
 client/tests/kvm/steps/openSUSE-11.0-32.steps      |  203 --
 .../tests/kvm/steps/openSUSE-11.1-32-and-64.steps  |  321 ---
 client/tests/kvm/tests/cpu_hotplug.py              |    2 +-
 client/tests/kvm/tests/stepmaker.py                |    2 +-
 client/tests/kvm/tests/steps.py                    |    2 +-
 client/tests/kvm/tests/unattended_install.py       |  632 -----
 client/tests/kvm/unattended/Fedora-10.ks           |   39 -
 client/tests/kvm/unattended/Fedora-11.ks           |   39 -
 client/tests/kvm/unattended/Fedora-12.ks           |   39 -
 client/tests/kvm/unattended/Fedora-13.ks           |   39 -
 client/tests/kvm/unattended/Fedora-14.ks           |   40 -
 client/tests/kvm/unattended/Fedora-15.ks           |   40 -
 client/tests/kvm/unattended/Fedora-8.ks            |   37 -
 client/tests/kvm/unattended/Fedora-9.ks            |   38 -
 client/tests/kvm/unattended/OpenSUSE-11.xml        |  243 --
 client/tests/kvm/unattended/RHEL-3-series.ks       |   36 -
 client/tests/kvm/unattended/RHEL-4-series.ks       |   37 -
 client/tests/kvm/unattended/RHEL-5-series.ks       |   39 -
 client/tests/kvm/unattended/RHEL-6-series.ks       |   42 -
 client/tests/kvm/unattended/SLES-11.xml            |  891 ------
 client/tests/kvm/unattended/win2000-32.sif         |   76 -
 client/tests/kvm/unattended/win2003-32.sif         |   66 -
 client/tests/kvm/unattended/win2003-64.sif         |   66 -
 .../kvm/unattended/win2008-32-autounattend.xml     |  194 --
 .../kvm/unattended/win2008-64-autounattend.xml     |  200 --
 .../kvm/unattended/win2008-r2-autounattend.xml     |  200 --
 .../tests/kvm/unattended/win7-32-autounattend.xml  |  179 --
 .../tests/kvm/unattended/win7-64-autounattend.xml  |  179 --
 client/tests/kvm/unattended/winnt.bat              |   12 -
 .../kvm/unattended/winvista-32-autounattend.xml    |  175 --
 .../kvm/unattended/winvista-64-autounattend.xml    |  188 --
 client/tests/kvm/unattended/winxp32.sif            |   76 -
 client/tests/kvm/unattended/winxp64.sif            |   76 -
 client/tests/libvirt/README                        |   11 +
 client/tests/libvirt/cdkeys.cfg.sample             |   18 +
 client/tests/libvirt/common.py                     |    8 +
 client/tests/libvirt/control                       |   64 +
 client/tests/libvirt/get_started.py                |   22 +
 client/tests/libvirt/libvirt.py                    |    9 +
 client/tests/libvirt/tests.cfg.sample              |   88 +
 client/tests/libvirt/tests_base.cfg.sample         | 2925 ++++++++++++++++++++
 client/tests/libvirt/virtio-win.cfg.sample         |  235 ++
 client/virt/autoit/notepad1.au3                    |   44 +
 client/virt/autotest_control/bonnie.control        |   21 +
 client/virt/autotest_control/cpu_hotplug.control   |   10 +
 client/virt/autotest_control/ctcs.control          |   19 +
 client/virt/autotest_control/dbench.control        |   20 +
 client/virt/autotest_control/disktest.control      |   15 +
 client/virt/autotest_control/ebizzy.control        |   11 +
 client/virt/autotest_control/flail.control         |   17 +
 client/virt/autotest_control/hackbench.control     |   13 +
 client/virt/autotest_control/hwclock.control       |   12 +
 client/virt/autotest_control/iozone.control        |   18 +
 client/virt/autotest_control/kernbench.control     |   12 +
 .../virt/autotest_control/monotonic_time.control   |   37 +
 client/virt/autotest_control/npb.control           |   28 +
 client/virt/autotest_control/rtc.control           |   15 +
 client/virt/autotest_control/scrashme.control      |   14 +
 client/virt/autotest_control/sleeptest.control     |   15 +
 client/virt/autotest_control/stress.control        |   14 +
 client/virt/autotest_control/systemtap.control     |   14 +
 client/virt/autotest_control/tsc.control           |   13 +
 client/virt/deps/Makefile                          |    8 +
 client/virt/deps/finish.cpp                        |  144 +
 client/virt/deps/finish.exe                        |  Bin 0 -> 31007 bytes
 client/virt/deps/heartbeat_slu.py                  |  205 ++
 client/virt/deps/rss.cpp                           | 1011 +++++++
 client/virt/deps/rss.exe                           |  Bin 0 -> 94518 bytes
 client/virt/deps/rss.reg                           |   15 +
 client/virt/deps/setuprss.bat                      |   21 +
 client/virt/deps/test_clock_getres/Makefile        |   11 +
 .../deps/test_clock_getres/test_clock_getres.c     |   58 +
 client/virt/deps/whql_delete_machine_15.cs         |   82 +
 client/virt/deps/whql_delete_machine_15.exe        |  Bin 0 -> 5632 bytes
 client/virt/deps/whql_submission_15.cs             |  373 +++
 client/virt/deps/whql_submission_15.exe            |  Bin 0 -> 12288 bytes
 client/virt/libvirt_monitor.py                     |  322 +++
 client/virt/libvirt_vm.py                          | 1246 +++++++++
 client/virt/scripts/ksm_overcommit_guest.py        |  237 ++
 client/virt/scripts/multicast_guest.py             |   37 +
 client/virt/scripts/virtio_console_guest.py        |  929 +++++++
 client/virt/steps/Belenix-0.7.1.steps              |  198 ++
 client/virt/steps/CentOS5-64.steps                 |  316 +++
 client/virt/steps/DSL-4.2.5.steps                  |  482 ++++
 client/virt/steps/Fedora-11-64.steps               |  300 ++
 client/virt/steps/Fedora-8-64.steps                |  281 ++
 client/virt/steps/Fedora-8-i386.steps              |  317 +++
 client/virt/steps/Fedora-9-64.steps                |  274 ++
 client/virt/steps/Fedora-9-i386.steps              |  268 ++
 client/virt/steps/FreeSBIE-2.0.1.steps             |  198 ++
 client/virt/steps/Mandriva-One-2007-32.steps       |  480 ++++
 client/virt/steps/NetBSD-1.6.2.steps               |  241 ++
 client/virt/steps/OpenBSD-4.1-32.steps             |  348 +++
 client/virt/steps/RHEL-3.9-i386.steps              |  316 +++
 client/virt/steps/RHEL-3.9-x86_64.steps            |  311 +++
 client/virt/steps/RHEL-4.7-i386.steps              |  297 ++
 client/virt/steps/RHEL-4.7-x86_64.steps            |  323 +++
 client/virt/steps/RHEL-5.3-i386.steps              |  306 ++
 client/virt/steps/RHEL-5.3-x86_64.steps            |  298 ++
 client/virt/steps/Slax-6.0.7.steps                 |  311 +++
 client/virt/steps/Ubuntu-6.10-32.steps             |  127 +
 client/virt/steps/Ubuntu-8.04-32-setupssh.steps    |  184 ++
 client/virt/steps/Ubuntu-8.04-32.steps             |  246 ++
 client/virt/steps/Ubuntu-8.04-server-32.steps      |  210 ++
 client/virt/steps/Ubuntu-8.10-64.steps             |  165 ++
 client/virt/steps/Ubuntu-8.10-server-32-gcc.steps  |  148 +
 client/virt/steps/Ubuntu-8.10-server-32.steps      |  258 ++
 client/virt/steps/Win-Vista-32.steps               |  152 +
 client/virt/steps/Win-Vista-64.steps               |  153 +
 client/virt/steps/Win2000-32-rss.steps             |   52 +
 client/virt/steps/Win2000-32-setupssh.steps        |  106 +
 client/virt/steps/Win2000-32.steps                 |  119 +
 client/virt/steps/Win2003-32-rss.steps             |   49 +
 client/virt/steps/Win2003-32-setupssh.steps        |  109 +
 client/virt/steps/Win2003-32.steps                 |  231 ++
 client/virt/steps/Win2003-64-rss.steps             |   47 +
 client/virt/steps/Win2003-64.steps                 |  154 +
 client/virt/steps/Win2008-32-rss.steps             |   49 +
 client/virt/steps/Win2008-32-setupssh.steps        |   83 +
 client/virt/steps/Win2008-32-setuptelnet.steps     |   86 +
 client/virt/steps/Win2008-32.steps                 |  139 +
 client/virt/steps/Win2008-64-rss.steps             |   52 +
 client/virt/steps/Win2008-64.steps                 |  105 +
 client/virt/steps/Win7-64-rss.steps                |  121 +
 client/virt/steps/Win7-64.steps                    |  187 ++
 client/virt/steps/WinVista-32-rss.steps            |   53 +
 client/virt/steps/WinVista-64-rss.steps            |   53 +
 client/virt/steps/WinXP-32-rss.steps               |   31 +
 client/virt/steps/WinXP-32-setupssh.steps          |   98 +
 client/virt/steps/WinXP-32.steps                   |  175 ++
 client/virt/steps/WinXP-64-rss.steps               |   34 +
 client/virt/steps/WinXP-64.steps                   |  111 +
 client/virt/steps/memtest86+.steps                 |    9 +
 client/virt/steps/openSUSE-11.0-32.steps           |  203 ++
 client/virt/steps/openSUSE-11.1-32-and-64.steps    |  321 +++
 client/virt/tests/autotest.py                      |    2 +-
 client/virt/tests/clock_getres.py                  |    2 +-
 client/virt/tests/guest_test.py                    |    2 +-
 client/virt/tests/unattended_install.py            |  797 ++++++
 client/virt/tests/whql_submission.py               |    4 +-
 client/virt/unattended/Fedora-10.ks                |   39 +
 client/virt/unattended/Fedora-11.ks                |   39 +
 client/virt/unattended/Fedora-12.ks                |   39 +
 client/virt/unattended/Fedora-13.ks                |   39 +
 client/virt/unattended/Fedora-14.ks                |   40 +
 client/virt/unattended/Fedora-15.ks                |   40 +
 client/virt/unattended/Fedora-8.ks                 |   37 +
 client/virt/unattended/Fedora-9.ks                 |   38 +
 client/virt/unattended/OpenSUSE-11.xml             |  243 ++
 client/virt/unattended/RHEL-3-series.ks            |   36 +
 client/virt/unattended/RHEL-4-series.ks            |   37 +
 client/virt/unattended/RHEL-5-series.ks            |   39 +
 client/virt/unattended/RHEL-6-series.ks            |   42 +
 client/virt/unattended/SLES-11.xml                 |  891 ++++++
 client/virt/unattended/win2000-32.sif              |   76 +
 client/virt/unattended/win2003-32.sif              |   66 +
 client/virt/unattended/win2003-64.sif              |   66 +
 client/virt/unattended/win2008-32-autounattend.xml |  194 ++
 client/virt/unattended/win2008-64-autounattend.xml |  200 ++
 client/virt/unattended/win2008-r2-autounattend.xml |  200 ++
 client/virt/unattended/win7-32-autounattend.xml    |  179 ++
 client/virt/unattended/win7-64-autounattend.xml    |  179 ++
 client/virt/unattended/winnt.bat                   |   12 +
 .../virt/unattended/winvista-32-autounattend.xml   |  175 ++
 .../virt/unattended/winvista-64-autounattend.xml   |  188 ++
 client/virt/unattended/winxp32.sif                 |   76 +
 client/virt/unattended/winxp64.sif                 |   76 +
 client/virt/virt_env_process.py                    |   51 +-
 client/virt/virt_http_server.py                    |  124 +
 client/virt/virt_test.py                           |  131 +
 client/virt/virt_utils.py                          |  171 ++-
 262 files changed, 23295 insertions(+), 17988 deletions(-)
 delete mode 100644 client/tests/kvm/autoit/notepad1.au3
 delete mode 100644 client/tests/kvm/autotest_control/bonnie.control
 delete mode 100644 client/tests/kvm/autotest_control/cpu_hotplug.control
 delete mode 100644 client/tests/kvm/autotest_control/ctcs.control
 delete mode 100644 client/tests/kvm/autotest_control/dbench.control
 delete mode 100644 client/tests/kvm/autotest_control/disktest.control
 delete mode 100644 client/tests/kvm/autotest_control/ebizzy.control
 delete mode 100644 client/tests/kvm/autotest_control/flail.control
 delete mode 100644 client/tests/kvm/autotest_control/hackbench.control
 delete mode 100644 client/tests/kvm/autotest_control/hwclock.control
 delete mode 100644 client/tests/kvm/autotest_control/iozone.control
 delete mode 100644 client/tests/kvm/autotest_control/kernbench.control
 delete mode 100644 client/tests/kvm/autotest_control/monotonic_time.control
 delete mode 100644 client/tests/kvm/autotest_control/npb.control
 delete mode 100644 client/tests/kvm/autotest_control/rtc.control
 delete mode 100644 client/tests/kvm/autotest_control/scrashme.control
 delete mode 100644 client/tests/kvm/autotest_control/sleeptest.control
 delete mode 100644 client/tests/kvm/autotest_control/stress.control
 delete mode 100644 client/tests/kvm/autotest_control/systemtap.control
 delete mode 100644 client/tests/kvm/autotest_control/tsc.control
 delete mode 100644 client/tests/kvm/deps/Makefile
 delete mode 100644 client/tests/kvm/deps/finish.cpp
 delete mode 100644 client/tests/kvm/deps/finish.exe
 delete mode 100755 client/tests/kvm/deps/heartbeat_slu.py
 delete mode 100644 client/tests/kvm/deps/rss.cpp
 delete mode 100644 client/tests/kvm/deps/rss.exe
 delete mode 100644 client/tests/kvm/deps/rss.reg
 delete mode 100644 client/tests/kvm/deps/setuprss.bat
 delete mode 100644 client/tests/kvm/deps/test_clock_getres/Makefile
 delete mode 100644 client/tests/kvm/deps/test_clock_getres/test_clock_getres.c
 delete mode 100644 client/tests/kvm/deps/whql_delete_machine_15.cs
 delete mode 100644 client/tests/kvm/deps/whql_delete_machine_15.exe
 delete mode 100644 client/tests/kvm/deps/whql_submission_15.cs
 delete mode 100644 client/tests/kvm/deps/whql_submission_15.exe
 delete mode 100755 client/tests/kvm/scripts/ksm_overcommit_guest.py
 delete mode 100755 client/tests/kvm/scripts/multicast_guest.py
 delete mode 100755 client/tests/kvm/scripts/virtio_console_guest.py
 delete mode 100644 client/tests/kvm/steps/Belenix-0.7.1.steps
 delete mode 100644 client/tests/kvm/steps/CentOS5-64.steps
 delete mode 100644 client/tests/kvm/steps/DSL-4.2.5.steps
 delete mode 100644 client/tests/kvm/steps/Fedora-11-64.steps
 delete mode 100644 client/tests/kvm/steps/Fedora-8-64.steps
 delete mode 100644 client/tests/kvm/steps/Fedora-8-i386.steps
 delete mode 100644 client/tests/kvm/steps/Fedora-9-64.steps
 delete mode 100644 client/tests/kvm/steps/Fedora-9-i386.steps
 delete mode 100644 client/tests/kvm/steps/FreeSBIE-2.0.1.steps
 delete mode 100644 client/tests/kvm/steps/Mandriva-One-2007-32.steps
 delete mode 100644 client/tests/kvm/steps/NetBSD-1.6.2.steps
 delete mode 100644 client/tests/kvm/steps/OpenBSD-4.1-32.steps
 delete mode 100644 client/tests/kvm/steps/RHEL-3.9-i386.steps
 delete mode 100644 client/tests/kvm/steps/RHEL-3.9-x86_64.steps
 delete mode 100644 client/tests/kvm/steps/RHEL-4.7-i386.steps
 delete mode 100644 client/tests/kvm/steps/RHEL-4.7-x86_64.steps
 delete mode 100644 client/tests/kvm/steps/RHEL-5.3-i386.steps
 delete mode 100644 client/tests/kvm/steps/RHEL-5.3-x86_64.steps
 delete mode 100644 client/tests/kvm/steps/Slax-6.0.7.steps
 delete mode 100644 client/tests/kvm/steps/Ubuntu-6.10-32.steps
 delete mode 100644 client/tests/kvm/steps/Ubuntu-8.04-32-setupssh.steps
 delete mode 100644 client/tests/kvm/steps/Ubuntu-8.04-32.steps
 delete mode 100644 client/tests/kvm/steps/Ubuntu-8.04-server-32.steps
 delete mode 100644 client/tests/kvm/steps/Ubuntu-8.10-64.steps
 delete mode 100644 client/tests/kvm/steps/Ubuntu-8.10-server-32-gcc.steps
 delete mode 100644 client/tests/kvm/steps/Ubuntu-8.10-server-32.steps
 delete mode 100644 client/tests/kvm/steps/Win-Vista-32.steps
 delete mode 100644 client/tests/kvm/steps/Win-Vista-64.steps
 delete mode 100644 client/tests/kvm/steps/Win2000-32-rss.steps
 delete mode 100644 client/tests/kvm/steps/Win2000-32-setupssh.steps
 delete mode 100644 client/tests/kvm/steps/Win2000-32.steps
 delete mode 100644 client/tests/kvm/steps/Win2003-32-rss.steps
 delete mode 100644 client/tests/kvm/steps/Win2003-32-setupssh.steps
 delete mode 100644 client/tests/kvm/steps/Win2003-32.steps
 delete mode 100644 client/tests/kvm/steps/Win2003-64-rss.steps
 delete mode 100644 client/tests/kvm/steps/Win2003-64.steps
 delete mode 100644 client/tests/kvm/steps/Win2008-32-rss.steps
 delete mode 100644 client/tests/kvm/steps/Win2008-32-setupssh.steps
 delete mode 100644 client/tests/kvm/steps/Win2008-32-setuptelnet.steps
 delete mode 100644 client/tests/kvm/steps/Win2008-32.steps
 delete mode 100644 client/tests/kvm/steps/Win2008-64-rss.steps
 delete mode 100644 client/tests/kvm/steps/Win2008-64.steps
 delete mode 100644 client/tests/kvm/steps/Win7-64-rss.steps
 delete mode 100644 client/tests/kvm/steps/Win7-64.steps
 delete mode 100644 client/tests/kvm/steps/WinVista-32-rss.steps
 delete mode 100644 client/tests/kvm/steps/WinVista-64-rss.steps
 delete mode 100644 client/tests/kvm/steps/WinXP-32-rss.steps
 delete mode 100644 client/tests/kvm/steps/WinXP-32-setupssh.steps
 delete mode 100644 client/tests/kvm/steps/WinXP-32.steps
 delete mode 100644 client/tests/kvm/steps/WinXP-64-rss.steps
 delete mode 100644 client/tests/kvm/steps/WinXP-64.steps
 delete mode 100644 client/tests/kvm/steps/memtest86+.steps
 delete mode 100644 client/tests/kvm/steps/openSUSE-11.0-32.steps
 delete mode 100644 client/tests/kvm/steps/openSUSE-11.1-32-and-64.steps
 delete mode 100644 client/tests/kvm/tests/unattended_install.py
 delete mode 100644 client/tests/kvm/unattended/Fedora-10.ks
 delete mode 100644 client/tests/kvm/unattended/Fedora-11.ks
 delete mode 100644 client/tests/kvm/unattended/Fedora-12.ks
 delete mode 100644 client/tests/kvm/unattended/Fedora-13.ks
 delete mode 100644 client/tests/kvm/unattended/Fedora-14.ks
 delete mode 100644 client/tests/kvm/unattended/Fedora-15.ks
 delete mode 100644 client/tests/kvm/unattended/Fedora-8.ks
 delete mode 100644 client/tests/kvm/unattended/Fedora-9.ks
 delete mode 100644 client/tests/kvm/unattended/OpenSUSE-11.xml
 delete mode 100644 client/tests/kvm/unattended/RHEL-3-series.ks
 delete mode 100644 client/tests/kvm/unattended/RHEL-4-series.ks
 delete mode 100644 client/tests/kvm/unattended/RHEL-5-series.ks
 delete mode 100644 client/tests/kvm/unattended/RHEL-6-series.ks
 delete mode 100644 client/tests/kvm/unattended/SLES-11.xml
 delete mode 100644 client/tests/kvm/unattended/win2000-32.sif
 delete mode 100644 client/tests/kvm/unattended/win2003-32.sif
 delete mode 100644 client/tests/kvm/unattended/win2003-64.sif
 delete mode 100644 client/tests/kvm/unattended/win2008-32-autounattend.xml
 delete mode 100644 client/tests/kvm/unattended/win2008-64-autounattend.xml
 delete mode 100644 client/tests/kvm/unattended/win2008-r2-autounattend.xml
 delete mode 100644 client/tests/kvm/unattended/win7-32-autounattend.xml
 delete mode 100644 client/tests/kvm/unattended/win7-64-autounattend.xml
 delete mode 100644 client/tests/kvm/unattended/winnt.bat
 delete mode 100644 client/tests/kvm/unattended/winvista-32-autounattend.xml
 delete mode 100644 client/tests/kvm/unattended/winvista-64-autounattend.xml
 delete mode 100644 client/tests/kvm/unattended/winxp32.sif
 delete mode 100644 client/tests/kvm/unattended/winxp64.sif
 create mode 100644 client/tests/libvirt/README
 create mode 100644 client/tests/libvirt/cdkeys.cfg.sample
 create mode 100644 client/tests/libvirt/common.py
 create mode 100644 client/tests/libvirt/control
 create mode 100755 client/tests/libvirt/get_started.py
 create mode 100644 client/tests/libvirt/libvirt.py
 create mode 100644 client/tests/libvirt/tests.cfg.sample
 create mode 100644 client/tests/libvirt/tests_base.cfg.sample
 create mode 100644 client/tests/libvirt/virtio-win.cfg.sample
 create mode 100644 client/virt/autoit/notepad1.au3
 create mode 100644 client/virt/autotest_control/bonnie.control
 create mode 100644 client/virt/autotest_control/cpu_hotplug.control
 create mode 100644 client/virt/autotest_control/ctcs.control
 create mode 100644 client/virt/autotest_control/dbench.control
 create mode 100644 client/virt/autotest_control/disktest.control
 create mode 100644 client/virt/autotest_control/ebizzy.control
 create mode 100644 client/virt/autotest_control/flail.control
 create mode 100644 client/virt/autotest_control/hackbench.control
 create mode 100644 client/virt/autotest_control/hwclock.control
 create mode 100644 client/virt/autotest_control/iozone.control
 create mode 100644 client/virt/autotest_control/kernbench.control
 create mode 100644 client/virt/autotest_control/monotonic_time.control
 create mode 100644 client/virt/autotest_control/npb.control
 create mode 100644 client/virt/autotest_control/rtc.control
 create mode 100644 client/virt/autotest_control/scrashme.control
 create mode 100644 client/virt/autotest_control/sleeptest.control
 create mode 100644 client/virt/autotest_control/stress.control
 create mode 100644 client/virt/autotest_control/systemtap.control
 create mode 100644 client/virt/autotest_control/tsc.control
 create mode 100644 client/virt/deps/Makefile
 create mode 100644 client/virt/deps/finish.cpp
 create mode 100644 client/virt/deps/finish.exe
 create mode 100755 client/virt/deps/heartbeat_slu.py
 create mode 100644 client/virt/deps/rss.cpp
 create mode 100644 client/virt/deps/rss.exe
 create mode 100644 client/virt/deps/rss.reg
 create mode 100644 client/virt/deps/setuprss.bat
 create mode 100644 client/virt/deps/test_clock_getres/Makefile
 create mode 100644 client/virt/deps/test_clock_getres/test_clock_getres.c
 create mode 100644 client/virt/deps/whql_delete_machine_15.cs
 create mode 100644 client/virt/deps/whql_delete_machine_15.exe
 create mode 100644 client/virt/deps/whql_submission_15.cs
 create mode 100644 client/virt/deps/whql_submission_15.exe
 create mode 100644 client/virt/libvirt_monitor.py
 create mode 100644 client/virt/libvirt_vm.py
 create mode 100755 client/virt/scripts/ksm_overcommit_guest.py
 create mode 100755 client/virt/scripts/multicast_guest.py
 create mode 100755 client/virt/scripts/virtio_console_guest.py
 create mode 100644 client/virt/steps/Belenix-0.7.1.steps
 create mode 100644 client/virt/steps/CentOS5-64.steps
 create mode 100644 client/virt/steps/DSL-4.2.5.steps
 create mode 100644 client/virt/steps/Fedora-11-64.steps
 create mode 100644 client/virt/steps/Fedora-8-64.steps
 create mode 100644 client/virt/steps/Fedora-8-i386.steps
 create mode 100644 client/virt/steps/Fedora-9-64.steps
 create mode 100644 client/virt/steps/Fedora-9-i386.steps
 create mode 100644 client/virt/steps/FreeSBIE-2.0.1.steps
 create mode 100644 client/virt/steps/Mandriva-One-2007-32.steps
 create mode 100644 client/virt/steps/NetBSD-1.6.2.steps
 create mode 100644 client/virt/steps/OpenBSD-4.1-32.steps
 create mode 100644 client/virt/steps/RHEL-3.9-i386.steps
 create mode 100644 client/virt/steps/RHEL-3.9-x86_64.steps
 create mode 100644 client/virt/steps/RHEL-4.7-i386.steps
 create mode 100644 client/virt/steps/RHEL-4.7-x86_64.steps
 create mode 100644 client/virt/steps/RHEL-5.3-i386.steps
 create mode 100644 client/virt/steps/RHEL-5.3-x86_64.steps
 create mode 100644 client/virt/steps/Slax-6.0.7.steps
 create mode 100644 client/virt/steps/Ubuntu-6.10-32.steps
 create mode 100644 client/virt/steps/Ubuntu-8.04-32-setupssh.steps
 create mode 100644 client/virt/steps/Ubuntu-8.04-32.steps
 create mode 100644 client/virt/steps/Ubuntu-8.04-server-32.steps
 create mode 100644 client/virt/steps/Ubuntu-8.10-64.steps
 create mode 100644 client/virt/steps/Ubuntu-8.10-server-32-gcc.steps
 create mode 100644 client/virt/steps/Ubuntu-8.10-server-32.steps
 create mode 100644 client/virt/steps/Win-Vista-32.steps
 create mode 100644 client/virt/steps/Win-Vista-64.steps
 create mode 100644 client/virt/steps/Win2000-32-rss.steps
 create mode 100644 client/virt/steps/Win2000-32-setupssh.steps
 create mode 100644 client/virt/steps/Win2000-32.steps
 create mode 100644 client/virt/steps/Win2003-32-rss.steps
 create mode 100644 client/virt/steps/Win2003-32-setupssh.steps
 create mode 100644 client/virt/steps/Win2003-32.steps
 create mode 100644 client/virt/steps/Win2003-64-rss.steps
 create mode 100644 client/virt/steps/Win2003-64.steps
 create mode 100644 client/virt/steps/Win2008-32-rss.steps
 create mode 100644 client/virt/steps/Win2008-32-setupssh.steps
 create mode 100644 client/virt/steps/Win2008-32-setuptelnet.steps
 create mode 100644 client/virt/steps/Win2008-32.steps
 create mode 100644 client/virt/steps/Win2008-64-rss.steps
 create mode 100644 client/virt/steps/Win2008-64.steps
 create mode 100644 client/virt/steps/Win7-64-rss.steps
 create mode 100644 client/virt/steps/Win7-64.steps
 create mode 100644 client/virt/steps/WinVista-32-rss.steps
 create mode 100644 client/virt/steps/WinVista-64-rss.steps
 create mode 100644 client/virt/steps/WinXP-32-rss.steps
 create mode 100644 client/virt/steps/WinXP-32-setupssh.steps
 create mode 100644 client/virt/steps/WinXP-32.steps
 create mode 100644 client/virt/steps/WinXP-64-rss.steps
 create mode 100644 client/virt/steps/WinXP-64.steps
 create mode 100644 client/virt/steps/memtest86+.steps
 create mode 100644 client/virt/steps/openSUSE-11.0-32.steps
 create mode 100644 client/virt/steps/openSUSE-11.1-32-and-64.steps
 create mode 100644 client/virt/tests/unattended_install.py
 create mode 100644 client/virt/unattended/Fedora-10.ks
 create mode 100644 client/virt/unattended/Fedora-11.ks
 create mode 100644 client/virt/unattended/Fedora-12.ks
 create mode 100644 client/virt/unattended/Fedora-13.ks
 create mode 100644 client/virt/unattended/Fedora-14.ks
 create mode 100644 client/virt/unattended/Fedora-15.ks
 create mode 100644 client/virt/unattended/Fedora-8.ks
 create mode 100644 client/virt/unattended/Fedora-9.ks
 create mode 100644 client/virt/unattended/OpenSUSE-11.xml
 create mode 100644 client/virt/unattended/RHEL-3-series.ks
 create mode 100644 client/virt/unattended/RHEL-4-series.ks
 create mode 100644 client/virt/unattended/RHEL-5-series.ks
 create mode 100644 client/virt/unattended/RHEL-6-series.ks
 create mode 100644 client/virt/unattended/SLES-11.xml
 create mode 100644 client/virt/unattended/win2000-32.sif
 create mode 100644 client/virt/unattended/win2003-32.sif
 create mode 100644 client/virt/unattended/win2003-64.sif
 create mode 100644 client/virt/unattended/win2008-32-autounattend.xml
 create mode 100644 client/virt/unattended/win2008-64-autounattend.xml
 create mode 100644 client/virt/unattended/win2008-r2-autounattend.xml
 create mode 100644 client/virt/unattended/win7-32-autounattend.xml
 create mode 100644 client/virt/unattended/win7-64-autounattend.xml
 create mode 100644 client/virt/unattended/winnt.bat
 create mode 100644 client/virt/unattended/winvista-32-autounattend.xml
 create mode 100644 client/virt/unattended/winvista-64-autounattend.xml
 create mode 100644 client/virt/unattended/winxp32.sif
 create mode 100644 client/virt/unattended/winxp64.sif
 create mode 100644 client/virt/virt_http_server.py
 create mode 100644 client/virt/virt_test.py

-- 
1.7.6.4


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 02/11] virt: Introducing virt_test.virt_test class
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 03/11] Moving unattended_install test from kvm test to common virt location Lucas Meneghel Rodrigues
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

During the process of implementing the libvirt test,
we've noticed that the whole mechanism implemented
by the KVM test (subtest loader, use of env file, params)
could be turned into common infrastructure. So move
all implementation to a class called virt_test.

We believe most virt test classes don't even need to be
implemented with this common infrastructure in place.

Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
 client/tests/kvm/kvm.py  |  126 +-------------------------------------------
 client/virt/virt_test.py |  131 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 134 insertions(+), 123 deletions(-)
 create mode 100644 client/virt/virt_test.py

diff --git a/client/tests/kvm/kvm.py b/client/tests/kvm/kvm.py
index 3d5eef2..8388391 100644
--- a/client/tests/kvm/kvm.py
+++ b/client/tests/kvm/kvm.py
@@ -1,10 +1,7 @@
-import os, logging, imp, sys
-from autotest_lib.client.bin import test
-from autotest_lib.client.common_lib import error
-from autotest_lib.client.virt import virt_utils, virt_env_process
+from autotest_lib.client.virt import virt_test
 
 
-class kvm(test.test):
+class kvm(virt_test.virt_test):
     """
     Suite of KVM virtualization functional tests.
     Contains tests for testing both KVM kernel code and userspace code.
@@ -20,121 +17,4 @@ class kvm(test.test):
     @see: http://www.linux-kvm.org/page/KVM-Autotest/Client_Install
             (Online doc - Getting started with KVM testing)
     """
-    version = 1
-    env_version = 1
-
-
-    def initialize(self, params):
-        # Change the value of the preserve_srcdir attribute according to
-        # the value present on the configuration file (defaults to yes)
-        if params.get("preserve_srcdir", "yes") == "yes":
-            self.preserve_srcdir = True
-        dirname = os.path.dirname(sys.modules[__name__].__file__)
-        clientdir = os.path.abspath(os.path.join(dirname, "..", ".."))
-        self.virtdir = os.path.join(clientdir, "virt")
-
-
-    def run_once(self, params):
-        # Convert params to a Params object
-        params = virt_utils.Params(params)
-
-        # If a dependency test prior to this test has failed, let's fail
-        # it right away as TestNA.
-        if params.get("dependency_failed") == 'yes':
-            raise error.TestNAError("Test dependency failed")
-
-        # Report the parameters we've received and write them as keyvals
-        logging.debug("Test parameters:")
-        keys = params.keys()
-        keys.sort()
-        for key in keys:
-            logging.debug("    %s = %s", key, params[key])
-            self.write_test_keyval({key: params[key]})
-
-        # Set the log file dir for the logging mechanism used by kvm_subprocess
-        # (this must be done before unpickling env)
-        virt_utils.set_log_file_dir(self.debugdir)
-
-        # Open the environment file
-        env_filename = os.path.join(self.bindir, params.get("env", "env"))
-        env = virt_utils.Env(env_filename, self.env_version)
-
-        test_passed = False
-
-        try:
-            try:
-                try:
-                    # Get the test routine corresponding to the specified
-                    # test type
-                    t_type = params.get("type")
-                    # Verify if we have the correspondent source file for it
-                    virt_dir = os.path.dirname(virt_utils.__file__)
-                    subtest_dir_virt = os.path.join(virt_dir, "tests")
-                    subtest_dir_kvm = os.path.join(self.bindir, "tests")
-                    subtest_dir = None
-                    for d in [subtest_dir_kvm, subtest_dir_virt]:
-                        module_path = os.path.join(d, "%s.py" % t_type)
-                        if os.path.isfile(module_path):
-                            subtest_dir = d
-                            break
-                    if subtest_dir is None:
-                        raise error.TestError("Could not find test file %s.py "
-                                              "on either %s or %s directory" %
-                                              (t_type, subtest_dir_kvm,
-                                              subtest_dir_virt))
-                    # Load the test module
-                    f, p, d = imp.find_module(t_type, [subtest_dir])
-                    test_module = imp.load_module(t_type, f, p, d)
-                    f.close()
-
-                    # Preprocess
-                    try:
-                        virt_env_process.preprocess(self, params, env)
-                    finally:
-                        env.save()
-                    # Run the test function
-                    run_func = getattr(test_module, "run_%s" % t_type)
-                    try:
-                        run_func(self, params, env)
-                    finally:
-                        env.save()
-                    test_passed = True
-
-                except Exception, e:
-                    logging.error("Test failed: %s: %s",
-                                  e.__class__.__name__, e)
-                    try:
-                        virt_env_process.postprocess_on_error(
-                            self, params, env)
-                    finally:
-                        env.save()
-                    raise
-
-            finally:
-                # Postprocess
-                try:
-                    try:
-                        virt_env_process.postprocess(self, params, env)
-                    except Exception, e:
-                        if test_passed:
-                            raise
-                        logging.error("Exception raised during "
-                                      "postprocessing: %s", e)
-                finally:
-                    env.save()
-
-        except Exception, e:
-            if params.get("abort_on_error") != "yes":
-                raise
-            # Abort on error
-            logging.info("Aborting job (%s)", e)
-            for vm in env.get_all_vms():
-                if vm.is_dead():
-                    continue
-                logging.info("VM '%s' is alive.", vm.name)
-                for m in vm.monitors:
-                    logging.info("'%s' has a %s monitor unix socket at: %s",
-                                 vm.name, m.protocol, m.filename)
-                logging.info("The command line used to start '%s' was:\n%s",
-                             vm.name, vm.make_qemu_command())
-            raise error.JobError("Abort requested (%s)" % e)
+    pass
diff --git a/client/virt/virt_test.py b/client/virt/virt_test.py
new file mode 100644
index 0000000..e18081b
--- /dev/null
+++ b/client/virt/virt_test.py
@@ -0,0 +1,131 @@
+import os, sys, logging, imp
+
+from autotest_lib.client.bin import test
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.virt import virt_utils, virt_env_process
+
+
+class virt_test(test.test):
+    """
+    Shared test class infrastructure for tests such as the KVM test.
+
+    It comprises a subtest load system, use of parameters, and an env
+    file, all code that can be reused among those virt tests.
+    """
+    version = 1
+    env_version = 1
+
+
+    def initialize(self, params):
+        # Change the value of the preserve_srcdir attribute according to
+        # the value present on the configuration file (defaults to yes)
+        if params.get("preserve_srcdir", "yes") == "yes":
+            self.preserve_srcdir = True
+        self.virtdir = os.path.dirname(sys.modules[__name__].__file__)
+
+
+    def run_once(self, params):
+        # Convert params to a Params object
+        params = virt_utils.Params(params)
+
+        # If a dependency test prior to this test has failed, let's fail
+        # it right away as TestNA.
+        if params.get("dependency_failed") == 'yes':
+            raise error.TestNAError("Test dependency failed")
+
+        # Report the parameters we've received and write them as keyvals
+        logging.debug("Test parameters:")
+        keys = params.keys()
+        keys.sort()
+        for key in keys:
+            logging.debug("    %s = %s", key, params[key])
+            self.write_test_keyval({key: params[key]})
+
+        # Set the log file dir for the logging mechanism used by kvm_subprocess
+        # (this must be done before unpickling env)
+        virt_utils.set_log_file_dir(self.debugdir)
+
+        # Open the environment file
+        env_filename = os.path.join(self.bindir, params.get("env", "env"))
+        env = virt_utils.Env(env_filename, self.env_version)
+
+        test_passed = False
+
+        try:
+            try:
+                try:
+                    # Get the test routine corresponding to the specified
+                    # test type
+                    t_type = params.get("type")
+                    # Verify if we have the correspondent source file for it
+                    virt_dir = os.path.dirname(virt_utils.__file__)
+                    subtest_dir_common = os.path.join(virt_dir, "tests")
+                    subtest_dir_test = os.path.join(self.bindir, "tests")
+                    subtest_dir = None
+                    for d in [subtest_dir_test, subtest_dir_common]:
+                        module_path = os.path.join(d, "%s.py" % t_type)
+                        if os.path.isfile(module_path):
+                            subtest_dir = d
+                            break
+                    if subtest_dir is None:
+                        raise error.TestError("Could not find test file %s.py "
+                                              "on either %s or %s directory" %
+                                              (t_type, subtest_dir_test,
+                                              subtest_dir_common))
+                    # Load the test module
+                    f, p, d = imp.find_module(t_type, [subtest_dir])
+                    test_module = imp.load_module(t_type, f, p, d)
+                    f.close()
+
+                    # Preprocess
+                    try:
+                        virt_env_process.preprocess(self, params, env)
+                    finally:
+                        env.save()
+                    # Run the test function
+                    run_func = getattr(test_module, "run_%s" % t_type)
+                    try:
+                        run_func(self, params, env)
+                    finally:
+                        env.save()
+                    test_passed = True
+
+                except Exception, e:
+                    logging.error("Test failed: %s: %s",
+                                  e.__class__.__name__, e)
+                    try:
+                        virt_env_process.postprocess_on_error(
+                            self, params, env)
+                    finally:
+                        env.save()
+                    raise
+
+            finally:
+                # Postprocess
+                try:
+                    try:
+                        virt_env_process.postprocess(self, params, env)
+                    except Exception, e:
+                        if test_passed:
+                            raise
+                        logging.error("Exception raised during "
+                                      "postprocessing: %s", e)
+                finally:
+                    env.save()
+
+        except Exception, e:
+            if params.get("abort_on_error") != "yes":
+                raise
+            # Abort on error
+            logging.info("Aborting job (%s)", e)
+            if params.get("vm_type") == "kvm":
+                for vm in env.get_all_vms():
+                    if vm.is_dead():
+                        continue
+                    logging.info("VM '%s' is alive.", vm.name)
+                    for m in vm.monitors:
+                        logging.info("'%s' has a %s monitor unix socket at: %s",
+                                     vm.name, m.protocol, m.filename)
+                    logging.info("The command line used to start '%s' was:\n%s",
+                                 vm.name, vm.make_qemu_command())
+                raise error.JobError("Abort requested (%s)" % e)
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 03/11] Moving unattended_install test from kvm test to common virt location
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 02/11] virt: Introducing virt_test.virt_test class Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 04/11] Moving get_started code to client.virt.virt_utils Lucas Meneghel Rodrigues
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
 client/tests/kvm/tests/unattended_install.py |  632 --------------------------
 client/virt/tests/unattended_install.py      |  632 ++++++++++++++++++++++++++
 2 files changed, 632 insertions(+), 632 deletions(-)
 delete mode 100644 client/tests/kvm/tests/unattended_install.py
 create mode 100644 client/virt/tests/unattended_install.py

diff --git a/client/tests/kvm/tests/unattended_install.py b/client/tests/kvm/tests/unattended_install.py
deleted file mode 100644
index 41a5e60..0000000
--- a/client/tests/kvm/tests/unattended_install.py
+++ /dev/null
@@ -1,632 +0,0 @@
-import logging, time, socket, re, os, shutil, tempfile, glob, ConfigParser
-import xml.dom.minidom
-from autotest_lib.client.common_lib import error
-from autotest_lib.client.bin import utils
-from autotest_lib.client.virt import virt_vm, virt_utils
-
-
-@error.context_aware
-def cleanup(dir):
-    """
-    If dir is a mountpoint, do what is possible to unmount it. Afterwards,
-    try to remove it.
-
-    @param dir: Directory to be cleaned up.
-    """
-    error.context("cleaning up unattended install directory %s" % dir)
-    if os.path.ismount(dir):
-        utils.run('fuser -k %s' % dir, ignore_status=True)
-        utils.run('umount %s' % dir)
-    if os.path.isdir(dir):
-        shutil.rmtree(dir)
-
-
-@error.context_aware
-def clean_old_image(image):
-    """
-    Clean a leftover image file from previous processes. If it contains a
-    mounted file system, do the proper cleanup procedures.
-
-    @param image: Path to image to be cleaned up.
-    """
-    error.context("cleaning up old leftover image %s" % image)
-    if os.path.exists(image):
-        mtab = open('/etc/mtab', 'r')
-        mtab_contents = mtab.read()
-        mtab.close()
-        if image in mtab_contents:
-            utils.run('fuser -k %s' % image, ignore_status=True)
-            utils.run('umount %s' % image)
-        os.remove(image)
-
-
-class Disk(object):
-    """
-    Abstract class for Disk objects, with the common methods implemented.
-    """
-    def __init__(self):
-        self.path = None
-
-
-    def get_answer_file_path(self, filename):
-        return os.path.join(self.mount, filename)
-
-
-    def copy_to(self, src):
-        logging.debug("Copying %s to disk image mount", src)
-        dst = os.path.join(self.mount, os.path.basename(src))
-        if os.path.isdir(src):
-            shutil.copytree(src, dst)
-        elif os.path.isfile(src):
-            shutil.copyfile(src, dst)
-
-
-    def close(self):
-        os.chmod(self.path, 0755)
-        cleanup(self.mount)
-        logging.debug("Disk %s successfuly set", self.path)
-
-
-class FloppyDisk(Disk):
-    """
-    Represents a 1.44 MB floppy disk. We can copy files to it, and setup it in
-    convenient ways.
-    """
-    @error.context_aware
-    def __init__(self, path, qemu_img_binary, tmpdir):
-        error.context("Creating unattended install floppy image %s" % path)
-        self.tmpdir = tmpdir
-        self.mount = tempfile.mkdtemp(prefix='floppy_', dir=self.tmpdir)
-        self.virtio_mount = None
-        self.path = path
-        clean_old_image(path)
-        if not os.path.isdir(os.path.dirname(path)):
-            os.makedirs(os.path.dirname(path))
-
-        try:
-            c_cmd = '%s create -f raw %s 1440k' % (qemu_img_binary, path)
-            utils.run(c_cmd)
-            f_cmd = 'mkfs.msdos -s 1 %s' % path
-            utils.run(f_cmd)
-            m_cmd = 'mount -o loop,rw %s %s' % (path, self.mount)
-            utils.run(m_cmd)
-        except error.CmdError, e:
-            logging.error("Error during floppy initialization: %s" % e)
-            cleanup(self.mount)
-            raise
-
-
-    def _copy_virtio_drivers(self, virtio_floppy):
-        """
-        Copy the virtio drivers on the virtio floppy to the install floppy.
-
-        1) Mount the floppy containing the viostor drivers
-        2) Copy its contents to the root of the install floppy
-        """
-        virtio_mount = tempfile.mkdtemp(prefix='virtio_floppy_',
-                                        dir=self.tmpdir)
-
-        pwd = os.getcwd()
-        try:
-            m_cmd = 'mount -o loop,ro %s %s' % (virtio_floppy, virtio_mount)
-            utils.run(m_cmd)
-            os.chdir(virtio_mount)
-            path_list = glob.glob('*')
-            for path in path_list:
-                self.copy_to(path)
-        finally:
-            os.chdir(pwd)
-            cleanup(virtio_mount)
-
-
-    def setup_virtio_win2003(self, virtio_floppy, virtio_oemsetup_id):
-        """
-        Setup the install floppy with the virtio storage drivers, win2003 style.
-
-        Win2003 and WinXP depend on the file txtsetup.oem file to install
-        the virtio drivers from the floppy, which is a .ini file.
-        Process:
-
-        1) Copy the virtio drivers on the virtio floppy to the install floppy
-        2) Parse the ini file with config parser
-        3) Modify the identifier of the default session that is going to be
-           executed on the config parser object
-        4) Re-write the config file to the disk
-        """
-        self._copy_virtio_drivers(virtio_floppy)
-        txtsetup_oem = os.path.join(self.mount, 'txtsetup.oem')
-        if not os.path.isfile(txtsetup_oem):
-            raise IOError('File txtsetup.oem not found on the install '
-                          'floppy. Please verify if your floppy virtio '
-                          'driver image has this file')
-        parser = ConfigParser.ConfigParser()
-        parser.read(txtsetup_oem)
-        if not parser.has_section('Defaults'):
-            raise ValueError('File txtsetup.oem does not have the session '
-                             '"Defaults". Please check txtsetup.oem')
-        default_driver = parser.get('Defaults', 'SCSI')
-        if default_driver != virtio_oemsetup_id:
-            parser.set('Defaults', 'SCSI', virtio_oemsetup_id)
-            fp = open(txtsetup_oem, 'w')
-            parser.write(fp)
-            fp.close()
-
-
-    def setup_virtio_win2008(self, virtio_floppy):
-        """
-        Setup the install floppy with the virtio storage drivers, win2008 style.
-
-        Win2008, Vista and 7 require people to point out the path to the drivers
-        on the unattended file, so we just need to copy the drivers to the
-        driver floppy disk. Important to note that it's possible to specify
-        drivers from a CDROM, so the floppy driver copy is optional.
-        Process:
-
-        1) Copy the virtio drivers on the virtio floppy to the install floppy,
-           if there is one available
-        """
-        if os.path.isfile(virtio_floppy):
-            self._copy_virtio_drivers(virtio_floppy)
-        else:
-            logging.debug("No virtio floppy present, not needed for this OS anyway")
-
-
-class CdromDisk(Disk):
-    """
-    Represents a CDROM disk that we can master according to our needs.
-    """
-    def __init__(self, path, tmpdir):
-        self.mount = tempfile.mkdtemp(prefix='cdrom_unattended_', dir=tmpdir)
-        self.path = path
-        clean_old_image(path)
-        if not os.path.isdir(os.path.dirname(path)):
-            os.makedirs(os.path.dirname(path))
-
-
-    @error.context_aware
-    def close(self):
-        error.context("Creating unattended install CD image %s" % self.path)
-        g_cmd = ('mkisofs -o %s -max-iso9660-filenames '
-                 '-relaxed-filenames -D --input-charset iso8859-1 '
-                 '%s' % (self.path, self.mount))
-        utils.run(g_cmd)
-
-        os.chmod(self.path, 0755)
-        cleanup(self.mount)
-        logging.debug("unattended install CD image %s successfuly created",
-                      self.path)
-
-
-class UnattendedInstallConfig(object):
-    """
-    Creates a floppy disk image that will contain a config file for unattended
-    OS install. The parameters to the script are retrieved from environment
-    variables.
-    """
-    def __init__(self, test, params):
-        """
-        Sets class atributes from test parameters.
-
-        @param test: KVM test object.
-        @param params: Dictionary with test parameters.
-        """
-        root_dir = test.bindir
-        self.deps_dir = os.path.join(test.virtdir, 'deps')
-        self.unattended_dir = os.path.join(test.virtdir, 'unattended')
-
-        attributes = ['kernel_args', 'finish_program', 'cdrom_cd1',
-                      'unattended_file', 'medium', 'url', 'kernel', 'initrd',
-                      'nfs_server', 'nfs_dir', 'install_virtio', 'floppy',
-                      'cdrom_unattended', 'boot_path', 'extra_params',
-                      'qemu_img_binary', 'cdkey', 'finish_program']
-
-        for a in attributes:
-            setattr(self, a, params.get(a, ''))
-
-        if self.install_virtio == 'yes':
-            v_attributes = ['virtio_floppy', 'virtio_storage_path',
-                            'virtio_network_path', 'virtio_oemsetup_id',
-                            'virtio_network_installer']
-            for va in v_attributes:
-                setattr(self, va, params.get(va, ''))
-
-        self.tmpdir = test.tmpdir
-
-        if getattr(self, 'unattended_file'):
-            self.unattended_file = os.path.join(test.virtdir, self.unattended_file)
-
-        if getattr(self, 'finish_program'):
-            self.finish_program = os.path.join(test.virtdir, self.finish_program)
-
-        if getattr(self, 'qemu_img_binary'):
-            if not os.path.isfile(getattr(self, 'qemu_img_binary')):
-                self.qemu_img_binary = os.path.join(root_dir,
-                                                    self.qemu_img_binary)
-
-        if getattr(self, 'cdrom_cd1'):
-            self.cdrom_cd1 = os.path.join(root_dir, self.cdrom_cd1)
-        self.cdrom_cd1_mount = tempfile.mkdtemp(prefix='cdrom_cd1_',
-                                                dir=self.tmpdir)
-        if self.medium == 'nfs':
-            self.nfs_mount = tempfile.mkdtemp(prefix='nfs_',
-                                              dir=self.tmpdir)
-
-        if getattr(self, 'floppy'):
-            self.floppy = os.path.join(root_dir, self.floppy)
-            if not os.path.isdir(os.path.dirname(self.floppy)):
-                os.makedirs(os.path.dirname(self.floppy))
-
-        self.image_path = os.path.dirname(self.kernel)
-
-
-    def answer_kickstart(self, answer_path):
-        """
-        Replace KVM_TEST_CDKEY (in the unattended file) with the cdkey
-        provided for this test and replace the KVM_TEST_MEDIUM with
-        the tree url or nfs address provided for this test.
-
-        @return: Answer file contents
-        """
-        contents = open(self.unattended_file).read()
-
-        dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b'
-        if re.search(dummy_cdkey_re, contents):
-            if self.cdkey:
-                contents = re.sub(dummy_cdkey_re, self.cdkey, contents)
-
-        dummy_medium_re = r'\bKVM_TEST_MEDIUM\b'
-        if self.medium == "cdrom":
-            content = "cdrom"
-        elif self.medium == "url":
-            content = "url --url %s" % self.url
-        elif self.medium == "nfs":
-            content = "nfs --server=%s --dir=%s" % (self.nfs_server,
-                                                    self.nfs_dir)
-        else:
-            raise ValueError("Unexpected installation medium %s" % self.url)
-
-        contents = re.sub(dummy_medium_re, content, contents)
-
-        logging.debug("Unattended install contents:")
-        for line in contents.splitlines():
-            logging.debug(line)
-
-        utils.open_write_close(answer_path, contents)
-
-
-    def answer_windows_ini(self, answer_path):
-        parser = ConfigParser.ConfigParser()
-        parser.read(self.unattended_file)
-        # First, replacing the CDKEY
-        if self.cdkey:
-            parser.set('UserData', 'ProductKey', self.cdkey)
-        else:
-            logging.error("Param 'cdkey' required but not specified for "
-                          "this unattended installation")
-
-        # Now, replacing the virtio network driver path, under double quotes
-        if self.install_virtio == 'yes':
-            parser.set('Unattended', 'OemPnPDriversPath',
-                       '"%s"' % self.virtio_nework_path)
-        else:
-            parser.remove_option('Unattended', 'OemPnPDriversPath')
-
-        # Last, replace the virtio installer command
-        if self.install_virtio == 'yes':
-            driver = self.virtio_network_installer_path
-        else:
-            driver = 'dir'
-
-        dummy_re = 'KVM_TEST_VIRTIO_NETWORK_INSTALLER'
-        installer = parser.get('GuiRunOnce', 'Command0')
-        if dummy_re in installer:
-            installer = re.sub(dummy_re, driver, installer)
-        parser.set('GuiRunOnce', 'Command0', installer)
-
-        # Now, writing the in memory config state to the unattended file
-        fp = open(answer_path, 'w')
-        parser.write(fp)
-
-        # Let's read it so we can debug print the contents
-        fp = open(answer_path, 'r')
-        contents = fp.read()
-        logging.debug("Unattended install contents:")
-        for line in contents.splitlines():
-            logging.debug(line)
-        fp.close()
-
-
-    def answer_windows_xml(self, answer_path):
-        doc = xml.dom.minidom.parse(self.unattended_file)
-
-        if self.cdkey:
-            # First, replacing the CDKEY
-            product_key = doc.getElementsByTagName('ProductKey')[0]
-            key = product_key.getElementsByTagName('Key')[0]
-            key_text = key.childNodes[0]
-            assert key_text.nodeType == doc.TEXT_NODE
-            key_text.data = self.cdkey
-        else:
-            logging.error("Param 'cdkey' required but not specified for "
-                          "this unattended installation")
-
-        # Now, replacing the virtio driver paths or removing the entire
-        # component PnpCustomizationsWinPE Element Node
-        if self.install_virtio == 'yes':
-            paths = doc.getElementsByTagName("Path")
-            values = [self.virtio_storage_path, self.virtio_network_path]
-            for path, value in zip(paths, values):
-                path_text = path.childNodes[0]
-                assert key_text.nodeType == doc.TEXT_NODE
-                path_text.data = value
-        else:
-            settings = doc.getElementsByTagName("settings")
-            for s in settings:
-                for c in s.getElementsByTagName("component"):
-                    if (c.getAttribute('name') ==
-                        "Microsoft-Windows-PnpCustomizationsWinPE"):
-                        s.removeChild(c)
-
-        # Last but not least important, replacing the virtio installer command
-        command_lines = doc.getElementsByTagName("CommandLine")
-        for command_line in command_lines:
-            command_line_text = command_line.childNodes[0]
-            assert command_line_text.nodeType == doc.TEXT_NODE
-            dummy_re = 'KVM_TEST_VIRTIO_NETWORK_INSTALLER'
-            if (self.install_virtio == 'yes' and
-                hasattr(self, 'virtio_network_installer_path')):
-                driver = self.virtio_network_installer_path
-            else:
-                driver = 'dir'
-            if driver.endswith("msi"):
-                driver = 'msiexec /passive /package ' + driver
-            if dummy_re in command_line_text.data:
-                t = command_line_text.data
-                t = re.sub(dummy_re, driver, t)
-                command_line_text.data = t
-
-        contents = doc.toxml()
-        logging.debug("Unattended install contents:")
-        for line in contents.splitlines():
-            logging.debug(line)
-
-        fp = open(answer_path, 'w')
-        doc.writexml(fp)
-
-
-    def answer_suse_xml(self, answer_path):
-        # There's nothing to replace on SUSE files to date. Yay!
-        doc = xml.dom.minidom.parse(self.unattended_file)
-
-        contents = doc.toxml()
-        logging.debug("Unattended install contents:")
-        for line in contents.splitlines():
-            logging.debug(line)
-
-        fp = open(answer_path, 'w')
-        doc.writexml(fp)
-
-
-    def setup_boot_disk(self):
-        if self.unattended_file.endswith('.sif'):
-            dest_fname = 'winnt.sif'
-            setup_file = 'winnt.bat'
-            boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
-                                   self.tmpdir)
-            answer_path = boot_disk.get_answer_file_path(dest_fname)
-            self.answer_windows_ini(answer_path)
-            setup_file_path = os.path.join(self.unattended_dir, setup_file)
-            boot_disk.copy_to(setup_file_path)
-            if self.install_virtio == "yes":
-                boot_disk.setup_virtio_win2003(self.virtio_floppy,
-                                               self.virtio_oemsetup_id)
-            boot_disk.copy_to(self.finish_program)
-
-        elif self.unattended_file.endswith('.ks'):
-            # Red Hat kickstart install
-            dest_fname = 'ks.cfg'
-            if self.cdrom_unattended:
-                boot_disk = CdromDisk(self.cdrom_unattended, self.tmpdir)
-            elif self.floppy:
-                boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
-                                       self.tmpdir)
-            else:
-                raise ValueError("Neither cdrom_unattended nor floppy set "
-                                 "on the config file, please verify")
-            answer_path = boot_disk.get_answer_file_path(dest_fname)
-            self.answer_kickstart(answer_path)
-
-        elif self.unattended_file.endswith('.xml'):
-            if "autoyast" in self.extra_params:
-                # SUSE autoyast install
-                dest_fname = "autoinst.xml"
-                if self.cdrom_unattended:
-                    boot_disk = CdromDisk(self.cdrom_unattended, self.tmpdir)
-                elif self.floppy:
-                    boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
-                                           self.tmpdir)
-                else:
-                    raise ValueError("Neither cdrom_unattended nor floppy set "
-                                     "on the config file, please verify")
-                answer_path = boot_disk.get_answer_file_path(dest_fname)
-                self.answer_suse_xml(answer_path)
-
-            else:
-                # Windows unattended install
-                dest_fname = "autounattend.xml"
-                boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
-                                       self.tmpdir)
-                answer_path = boot_disk.get_answer_file_path(dest_fname)
-                self.answer_windows_xml(answer_path)
-
-                if self.install_virtio == "yes":
-                    boot_disk.setup_virtio_win2008(self.virtio_floppy)
-                boot_disk.copy_to(self.finish_program)
-
-        else:
-            raise ValueError('Unknown answer file type: %s' %
-                             self.unattended_file)
-
-        boot_disk.close()
-
-
-    @error.context_aware
-    def setup_cdrom(self):
-        """
-        Mount cdrom and copy vmlinuz and initrd.img.
-        """
-        error.context("Copying vmlinuz and initrd.img from install cdrom %s" %
-                      self.cdrom_cd1)
-        m_cmd = ('mount -t iso9660 -v -o loop,ro %s %s' %
-                 (self.cdrom_cd1, self.cdrom_cd1_mount))
-        utils.run(m_cmd)
-
-        try:
-            if not os.path.isdir(self.image_path):
-                os.makedirs(self.image_path)
-            kernel_fetch_cmd = ("cp %s/%s/%s %s" %
-                                (self.cdrom_cd1_mount, self.boot_path,
-                                 os.path.basename(self.kernel), self.kernel))
-            utils.run(kernel_fetch_cmd)
-            initrd_fetch_cmd = ("cp %s/%s/%s %s" %
-                                (self.cdrom_cd1_mount, self.boot_path,
-                                 os.path.basename(self.initrd), self.initrd))
-            utils.run(initrd_fetch_cmd)
-        finally:
-            cleanup(self.cdrom_cd1_mount)
-
-
-    @error.context_aware
-    def setup_url(self):
-        """
-        Download the vmlinuz and initrd.img from URL.
-        """
-        error.context("downloading vmlinuz and initrd.img from %s" % self.url)
-        os.chdir(self.image_path)
-        kernel_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path,
-                                                 os.path.basename(self.kernel))
-        initrd_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path,
-                                                 os.path.basename(self.initrd))
-
-        if os.path.exists(self.kernel):
-            os.remove(self.kernel)
-        if os.path.exists(self.initrd):
-            os.remove(self.initrd)
-
-        utils.run(kernel_fetch_cmd)
-        utils.run(initrd_fetch_cmd)
-
-
-    def setup_nfs(self):
-        """
-        Copy the vmlinuz and initrd.img from nfs.
-        """
-        error.context("copying the vmlinuz and initrd.img from NFS share")
-
-        m_cmd = ("mount %s:%s %s -o ro" %
-                 (self.nfs_server, self.nfs_dir, self.nfs_mount))
-        utils.run(m_cmd)
-
-        try:
-            kernel_fetch_cmd = ("cp %s/%s/%s %s" %
-                                (self.nfs_mount, self.boot_path,
-                                os.path.basename(self.kernel), self.image_path))
-            utils.run(kernel_fetch_cmd)
-            initrd_fetch_cmd = ("cp %s/%s/%s %s" %
-                                (self.nfs_mount, self.boot_path,
-                                os.path.basename(self.initrd), self.image_path))
-            utils.run(initrd_fetch_cmd)
-        finally:
-            cleanup(self.nfs_mount)
-
-
-    def setup(self):
-        """
-        Configure the environment for unattended install.
-
-        Uses an appropriate strategy according to each install model.
-        """
-        logging.info("Starting unattended install setup")
-        virt_utils.display_attributes(self)
-
-        if self.unattended_file and (self.floppy or self.cdrom_unattended):
-            self.setup_boot_disk()
-        if self.medium == "cdrom":
-            if self.kernel and self.initrd:
-                self.setup_cdrom()
-        elif self.medium == "url":
-            self.setup_url()
-        elif self.medium == "nfs":
-            self.setup_nfs()
-        else:
-            raise ValueError("Unexpected installation method %s" %
-                             self.medium)
-
-
-@error.context_aware
-def run_unattended_install(test, params, env):
-    """
-    Unattended install test:
-    1) Starts a VM with an appropriated setup to start an unattended OS install.
-    2) Wait until the install reports to the install watcher its end.
-
-    @param test: KVM test object.
-    @param params: Dictionary with the test parameters.
-    @param env: Dictionary with test environment.
-    """
-    unattended_install_config = UnattendedInstallConfig(test, params)
-    unattended_install_config.setup()
-    vm = env.get_vm(params["main_vm"])
-    vm.create()
-
-    install_timeout = int(params.get("timeout", 3000))
-    port = vm.get_port(int(params.get("guest_port_unattended_install")))
-
-    migrate_background = params.get("migrate_background") == "yes"
-    if migrate_background:
-        mig_timeout = float(params.get("mig_timeout", "3600"))
-        mig_protocol = params.get("migration_protocol", "tcp")
-
-    logging.info("Waiting for installation to finish. Timeout set to %d s "
-                 "(%d min)", install_timeout, install_timeout/60)
-    error.context("waiting for installation to finish")
-
-    start_time = time.time()
-    while (time.time() - start_time) < install_timeout:
-        try:
-            vm.verify_alive()
-        except virt_vm.VMDeadError, e:
-            if params.get("wait_no_ack", "no") == "yes":
-                break
-            else:
-                raise e
-        vm.verify_kernel_crash()
-        if params.get("wait_no_ack", "no") == "no":
-            client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-            try:
-                client.connect((vm.get_address(), port))
-                if client.recv(1024) == "done":
-                    break
-            except (socket.error, virt_vm.VMAddressError):
-                pass
-
-        if migrate_background:
-            vm.migrate(timeout=mig_timeout, protocol=mig_protocol)
-        else:
-            time.sleep(1)
-        if params.get("wait_no_ack", "no") == "no":
-            client.close()
-    else:
-        raise error.TestFail("Timeout elapsed while waiting for install to "
-                             "finish")
-
-    time_elapsed = time.time() - start_time
-    logging.info("Guest reported successful installation after %d s (%d min)",
-                 time_elapsed, time_elapsed/60)
-
-    if params.get("shutdown_cleanly", "yes") == "yes":
-        shutdown_cleanly_timeout = int(params.get("shutdown_cleanly_timeout",
-                                                  120))
-        logging.info("Wait for guest to shutdown cleanly")
-        if virt_utils.wait_for(vm.is_dead, shutdown_cleanly_timeout, 1, 1):
-            logging.info("Guest managed to shutdown cleanly")
diff --git a/client/virt/tests/unattended_install.py b/client/virt/tests/unattended_install.py
new file mode 100644
index 0000000..efa3c10
--- /dev/null
+++ b/client/virt/tests/unattended_install.py
@@ -0,0 +1,632 @@
+import logging, time, socket, re, os, shutil, tempfile, glob, ConfigParser
+import xml.dom.minidom
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+from autotest_lib.client.virt import virt_vm, virt_utils
+
+
+@error.context_aware
+def cleanup(dir):
+    """
+    If dir is a mountpoint, do what is possible to unmount it. Afterwards,
+    try to remove it.
+
+    @param dir: Directory to be cleaned up.
+    """
+    error.context("cleaning up unattended install directory %s" % dir)
+    if os.path.ismount(dir):
+        utils.run('fuser -k %s' % dir, ignore_status=True)
+        utils.run('umount %s' % dir)
+    if os.path.isdir(dir):
+        shutil.rmtree(dir)
+
+
+@error.context_aware
+def clean_old_image(image):
+    """
+    Clean a leftover image file from previous processes. If it contains a
+    mounted file system, do the proper cleanup procedures.
+
+    @param image: Path to image to be cleaned up.
+    """
+    error.context("cleaning up old leftover image %s" % image)
+    if os.path.exists(image):
+        mtab = open('/etc/mtab', 'r')
+        mtab_contents = mtab.read()
+        mtab.close()
+        if image in mtab_contents:
+            utils.run('fuser -k %s' % image, ignore_status=True)
+            utils.run('umount %s' % image)
+        os.remove(image)
+
+
+class Disk(object):
+    """
+    Abstract class for Disk objects, with the common methods implemented.
+    """
+    def __init__(self):
+        self.path = None
+
+
+    def get_answer_file_path(self, filename):
+        return os.path.join(self.mount, filename)
+
+
+    def copy_to(self, src):
+        logging.debug("Copying %s to disk image mount", src)
+        dst = os.path.join(self.mount, os.path.basename(src))
+        if os.path.isdir(src):
+            shutil.copytree(src, dst)
+        elif os.path.isfile(src):
+            shutil.copyfile(src, dst)
+
+
+    def close(self):
+        os.chmod(self.path, 0755)
+        cleanup(self.mount)
+        logging.debug("Disk %s successfuly set", self.path)
+
+
+class FloppyDisk(Disk):
+    """
+    Represents a 1.44 MB floppy disk. We can copy files to it, and setup it in
+    convenient ways.
+    """
+    @error.context_aware
+    def __init__(self, path, qemu_img_binary, tmpdir):
+        error.context("Creating unattended install floppy image %s" % path)
+        self.tmpdir = tmpdir
+        self.mount = tempfile.mkdtemp(prefix='floppy_', dir=self.tmpdir)
+        self.virtio_mount = None
+        self.path = path
+        clean_old_image(path)
+        if not os.path.isdir(os.path.dirname(path)):
+            os.makedirs(os.path.dirname(path))
+
+        try:
+            c_cmd = '%s create -f raw %s 1440k' % (qemu_img_binary, path)
+            utils.run(c_cmd)
+            f_cmd = 'mkfs.msdos -s 1 %s' % path
+            utils.run(f_cmd)
+            m_cmd = 'mount -o loop,rw %s %s' % (path, self.mount)
+            utils.run(m_cmd)
+        except error.CmdError, e:
+            logging.error("Error during floppy initialization: %s" % e)
+            cleanup(self.mount)
+            raise
+
+
+    def _copy_virtio_drivers(self, virtio_floppy):
+        """
+        Copy the virtio drivers on the virtio floppy to the install floppy.
+
+        1) Mount the floppy containing the viostor drivers
+        2) Copy its contents to the root of the install floppy
+        """
+        virtio_mount = tempfile.mkdtemp(prefix='virtio_floppy_',
+                                        dir=self.tmpdir)
+
+        pwd = os.getcwd()
+        try:
+            m_cmd = 'mount -o loop,ro %s %s' % (virtio_floppy, virtio_mount)
+            utils.run(m_cmd)
+            os.chdir(virtio_mount)
+            path_list = glob.glob('*')
+            for path in path_list:
+                self.copy_to(path)
+        finally:
+            os.chdir(pwd)
+            cleanup(virtio_mount)
+
+
+    def setup_virtio_win2003(self, virtio_floppy, virtio_oemsetup_id):
+        """
+        Setup the install floppy with the virtio storage drivers, win2003 style.
+
+        Win2003 and WinXP depend on the file txtsetup.oem file to install
+        the virtio drivers from the floppy, which is a .ini file.
+        Process:
+
+        1) Copy the virtio drivers on the virtio floppy to the install floppy
+        2) Parse the ini file with config parser
+        3) Modify the identifier of the default session that is going to be
+           executed on the config parser object
+        4) Re-write the config file to the disk
+        """
+        self._copy_virtio_drivers(virtio_floppy)
+        txtsetup_oem = os.path.join(self.mount, 'txtsetup.oem')
+        if not os.path.isfile(txtsetup_oem):
+            raise IOError('File txtsetup.oem not found on the install '
+                          'floppy. Please verify if your floppy virtio '
+                          'driver image has this file')
+        parser = ConfigParser.ConfigParser()
+        parser.read(txtsetup_oem)
+        if not parser.has_section('Defaults'):
+            raise ValueError('File txtsetup.oem does not have the session '
+                             '"Defaults". Please check txtsetup.oem')
+        default_driver = parser.get('Defaults', 'SCSI')
+        if default_driver != virtio_oemsetup_id:
+            parser.set('Defaults', 'SCSI', virtio_oemsetup_id)
+            fp = open(txtsetup_oem, 'w')
+            parser.write(fp)
+            fp.close()
+
+
+    def setup_virtio_win2008(self, virtio_floppy):
+        """
+        Setup the install floppy with the virtio storage drivers, win2008 style.
+
+        Win2008, Vista and 7 require people to point out the path to the drivers
+        on the unattended file, so we just need to copy the drivers to the
+        driver floppy disk. Important to note that it's possible to specify
+        drivers from a CDROM, so the floppy driver copy is optional.
+        Process:
+
+        1) Copy the virtio drivers on the virtio floppy to the install floppy,
+           if there is one available
+        """
+        if os.path.isfile(virtio_floppy):
+            self._copy_virtio_drivers(virtio_floppy)
+        else:
+            logging.debug("No virtio floppy present, not needed for this OS anyway")
+
+
+class CdromDisk(Disk):
+    """
+    Represents a CDROM disk that we can master according to our needs.
+    """
+    def __init__(self, path, tmpdir):
+        self.mount = tempfile.mkdtemp(prefix='cdrom_unattended_', dir=tmpdir)
+        self.path = path
+        clean_old_image(path)
+        if not os.path.isdir(os.path.dirname(path)):
+            os.makedirs(os.path.dirname(path))
+
+
+    @error.context_aware
+    def close(self):
+        error.context("Creating unattended install CD image %s" % self.path)
+        g_cmd = ('mkisofs -o %s -max-iso9660-filenames '
+                 '-relaxed-filenames -D --input-charset iso8859-1 '
+                 '%s' % (self.path, self.mount))
+        utils.run(g_cmd)
+
+        os.chmod(self.path, 0755)
+        cleanup(self.mount)
+        logging.debug("unattended install CD image %s successfuly created",
+                      self.path)
+
+
+class UnattendedInstallConfig(object):
+    """
+    Creates a floppy disk image that will contain a config file for unattended
+    OS install. The parameters to the script are retrieved from environment
+    variables.
+    """
+    def __init__(self, test, params):
+        """
+        Sets class atributes from test parameters.
+
+        @param test: KVM test object.
+        @param params: Dictionary with test parameters.
+        """
+        root_dir = test.bindir
+        self.deps_dir = os.path.join(test.virtdir, 'deps')
+        self.unattended_dir = os.path.join(test.virtdir, 'unattended')
+
+        attributes = ['kernel_args', 'finish_program', 'cdrom_cd1',
+                      'unattended_file', 'medium', 'url', 'kernel', 'initrd',
+                      'nfs_server', 'nfs_dir', 'install_virtio', 'floppy',
+                      'cdrom_unattended', 'boot_path', 'extra_params',
+                      'qemu_img_binary', 'cdkey', 'finish_program']
+
+        for a in attributes:
+            setattr(self, a, params.get(a, ''))
+
+        if self.install_virtio == 'yes':
+            v_attributes = ['virtio_floppy', 'virtio_storage_path',
+                            'virtio_network_path', 'virtio_oemsetup_id',
+                            'virtio_network_installer']
+            for va in v_attributes:
+                setattr(self, va, params.get(va, ''))
+
+        self.tmpdir = test.tmpdir
+
+        if getattr(self, 'unattended_file'):
+            self.unattended_file = os.path.join(test.virtdir, self.unattended_file)
+
+        if getattr(self, 'finish_program'):
+            self.finish_program = os.path.join(test.virtdir, self.finish_program)
+
+        if getattr(self, 'qemu_img_binary'):
+            if not os.path.isfile(getattr(self, 'qemu_img_binary')):
+                self.qemu_img_binary = os.path.join(root_dir,
+                                                    self.qemu_img_binary)
+
+        if getattr(self, 'cdrom_cd1'):
+            self.cdrom_cd1 = os.path.join(root_dir, self.cdrom_cd1)
+        self.cdrom_cd1_mount = tempfile.mkdtemp(prefix='cdrom_cd1_',
+                                                dir=self.tmpdir)
+        if self.medium == 'nfs':
+            self.nfs_mount = tempfile.mkdtemp(prefix='nfs_',
+                                              dir=self.tmpdir)
+
+        if getattr(self, 'floppy'):
+            self.floppy = os.path.join(root_dir, self.floppy)
+            if not os.path.isdir(os.path.dirname(self.floppy)):
+                os.makedirs(os.path.dirname(self.floppy))
+
+        self.image_path = os.path.dirname(self.kernel)
+
+
+    def answer_kickstart(self, answer_path):
+        """
+        Replace KVM_TEST_CDKEY (in the unattended file) with the cdkey
+        provided for this test and replace the KVM_TEST_MEDIUM with
+        the tree url or nfs address provided for this test.
+
+        @return: Answer file contents
+        """
+        contents = open(self.unattended_file).read()
+
+        dummy_cdkey_re = r'\bKVM_TEST_CDKEY\b'
+        if re.search(dummy_cdkey_re, contents):
+            if self.cdkey:
+                contents = re.sub(dummy_cdkey_re, self.cdkey, contents)
+
+        dummy_medium_re = r'\bKVM_TEST_MEDIUM\b'
+        if self.medium in ["cdrom", "kernel_initrd"]:
+            content = "cdrom"
+        elif self.medium == "url":
+            content = "url --url %s" % self.url
+        elif self.medium == "nfs":
+            content = "nfs --server=%s --dir=%s" % (self.nfs_server,
+                                                    self.nfs_dir)
+        else:
+            raise ValueError("Unexpected installation medium %s" % self.url)
+
+        contents = re.sub(dummy_medium_re, content, contents)
+
+        logging.debug("Unattended install contents:")
+        for line in contents.splitlines():
+            logging.debug(line)
+
+        utils.open_write_close(answer_path, contents)
+
+
+    def answer_windows_ini(self, answer_path):
+        parser = ConfigParser.ConfigParser()
+        parser.read(self.unattended_file)
+        # First, replacing the CDKEY
+        if self.cdkey:
+            parser.set('UserData', 'ProductKey', self.cdkey)
+        else:
+            logging.error("Param 'cdkey' required but not specified for "
+                          "this unattended installation")
+
+        # Now, replacing the virtio network driver path, under double quotes
+        if self.install_virtio == 'yes':
+            parser.set('Unattended', 'OemPnPDriversPath',
+                       '"%s"' % self.virtio_nework_path)
+        else:
+            parser.remove_option('Unattended', 'OemPnPDriversPath')
+
+        # Last, replace the virtio installer command
+        if self.install_virtio == 'yes':
+            driver = self.virtio_network_installer_path
+        else:
+            driver = 'dir'
+
+        dummy_re = 'KVM_TEST_VIRTIO_NETWORK_INSTALLER'
+        installer = parser.get('GuiRunOnce', 'Command0')
+        if dummy_re in installer:
+            installer = re.sub(dummy_re, driver, installer)
+        parser.set('GuiRunOnce', 'Command0', installer)
+
+        # Now, writing the in memory config state to the unattended file
+        fp = open(answer_path, 'w')
+        parser.write(fp)
+
+        # Let's read it so we can debug print the contents
+        fp = open(answer_path, 'r')
+        contents = fp.read()
+        logging.debug("Unattended install contents:")
+        for line in contents.splitlines():
+            logging.debug(line)
+        fp.close()
+
+
+    def answer_windows_xml(self, answer_path):
+        doc = xml.dom.minidom.parse(self.unattended_file)
+
+        if self.cdkey:
+            # First, replacing the CDKEY
+            product_key = doc.getElementsByTagName('ProductKey')[0]
+            key = product_key.getElementsByTagName('Key')[0]
+            key_text = key.childNodes[0]
+            assert key_text.nodeType == doc.TEXT_NODE
+            key_text.data = self.cdkey
+        else:
+            logging.error("Param 'cdkey' required but not specified for "
+                          "this unattended installation")
+
+        # Now, replacing the virtio driver paths or removing the entire
+        # component PnpCustomizationsWinPE Element Node
+        if self.install_virtio == 'yes':
+            paths = doc.getElementsByTagName("Path")
+            values = [self.virtio_storage_path, self.virtio_network_path]
+            for path, value in zip(paths, values):
+                path_text = path.childNodes[0]
+                assert key_text.nodeType == doc.TEXT_NODE
+                path_text.data = value
+        else:
+            settings = doc.getElementsByTagName("settings")
+            for s in settings:
+                for c in s.getElementsByTagName("component"):
+                    if (c.getAttribute('name') ==
+                        "Microsoft-Windows-PnpCustomizationsWinPE"):
+                        s.removeChild(c)
+
+        # Last but not least important, replacing the virtio installer command
+        command_lines = doc.getElementsByTagName("CommandLine")
+        for command_line in command_lines:
+            command_line_text = command_line.childNodes[0]
+            assert command_line_text.nodeType == doc.TEXT_NODE
+            dummy_re = 'KVM_TEST_VIRTIO_NETWORK_INSTALLER'
+            if (self.install_virtio == 'yes' and
+                hasattr(self, 'virtio_network_installer_path')):
+                driver = self.virtio_network_installer_path
+            else:
+                driver = 'dir'
+            if driver.endswith("msi"):
+                driver = 'msiexec /passive /package ' + driver
+            if dummy_re in command_line_text.data:
+                t = command_line_text.data
+                t = re.sub(dummy_re, driver, t)
+                command_line_text.data = t
+
+        contents = doc.toxml()
+        logging.debug("Unattended install contents:")
+        for line in contents.splitlines():
+            logging.debug(line)
+
+        fp = open(answer_path, 'w')
+        doc.writexml(fp)
+
+
+    def answer_suse_xml(self, answer_path):
+        # There's nothing to replace on SUSE files to date. Yay!
+        doc = xml.dom.minidom.parse(self.unattended_file)
+
+        contents = doc.toxml()
+        logging.debug("Unattended install contents:")
+        for line in contents.splitlines():
+            logging.debug(line)
+
+        fp = open(answer_path, 'w')
+        doc.writexml(fp)
+
+
+    def setup_boot_disk(self):
+        if self.unattended_file.endswith('.sif'):
+            dest_fname = 'winnt.sif'
+            setup_file = 'winnt.bat'
+            boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
+                                   self.tmpdir)
+            answer_path = boot_disk.get_answer_file_path(dest_fname)
+            self.answer_windows_ini(answer_path)
+            setup_file_path = os.path.join(self.unattended_dir, setup_file)
+            boot_disk.copy_to(setup_file_path)
+            if self.install_virtio == "yes":
+                boot_disk.setup_virtio_win2003(self.virtio_floppy,
+                                               self.virtio_oemsetup_id)
+            boot_disk.copy_to(self.finish_program)
+
+        elif self.unattended_file.endswith('.ks'):
+            # Red Hat kickstart install
+            dest_fname = 'ks.cfg'
+            if self.cdrom_unattended:
+                boot_disk = CdromDisk(self.cdrom_unattended, self.tmpdir)
+            elif self.floppy:
+                boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
+                                       self.tmpdir)
+            else:
+                raise ValueError("Neither cdrom_unattended nor floppy set "
+                                 "on the config file, please verify")
+            answer_path = boot_disk.get_answer_file_path(dest_fname)
+            self.answer_kickstart(answer_path)
+
+        elif self.unattended_file.endswith('.xml'):
+            if "autoyast" in self.extra_params:
+                # SUSE autoyast install
+                dest_fname = "autoinst.xml"
+                if self.cdrom_unattended:
+                    boot_disk = CdromDisk(self.cdrom_unattended, self.tmpdir)
+                elif self.floppy:
+                    boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
+                                           self.tmpdir)
+                else:
+                    raise ValueError("Neither cdrom_unattended nor floppy set "
+                                     "on the config file, please verify")
+                answer_path = boot_disk.get_answer_file_path(dest_fname)
+                self.answer_suse_xml(answer_path)
+
+            else:
+                # Windows unattended install
+                dest_fname = "autounattend.xml"
+                boot_disk = FloppyDisk(self.floppy, self.qemu_img_binary,
+                                       self.tmpdir)
+                answer_path = boot_disk.get_answer_file_path(dest_fname)
+                self.answer_windows_xml(answer_path)
+
+                if self.install_virtio == "yes":
+                    boot_disk.setup_virtio_win2008(self.virtio_floppy)
+                boot_disk.copy_to(self.finish_program)
+
+        else:
+            raise ValueError('Unknown answer file type: %s' %
+                             self.unattended_file)
+
+        boot_disk.close()
+
+
+    @error.context_aware
+    def setup_cdrom(self):
+        """
+        Mount cdrom and copy vmlinuz and initrd.img.
+        """
+        error.context("Copying vmlinuz and initrd.img from install cdrom %s" %
+                      self.cdrom_cd1)
+        m_cmd = ('mount -t iso9660 -v -o loop,ro %s %s' %
+                 (self.cdrom_cd1, self.cdrom_cd1_mount))
+        utils.run(m_cmd)
+
+        try:
+            if not os.path.isdir(self.image_path):
+                os.makedirs(self.image_path)
+            kernel_fetch_cmd = ("cp %s/%s/%s %s" %
+                                (self.cdrom_cd1_mount, self.boot_path,
+                                 os.path.basename(self.kernel), self.kernel))
+            utils.run(kernel_fetch_cmd)
+            initrd_fetch_cmd = ("cp %s/%s/%s %s" %
+                                (self.cdrom_cd1_mount, self.boot_path,
+                                 os.path.basename(self.initrd), self.initrd))
+            utils.run(initrd_fetch_cmd)
+        finally:
+            cleanup(self.cdrom_cd1_mount)
+
+
+    @error.context_aware
+    def setup_url(self):
+        """
+        Download the vmlinuz and initrd.img from URL.
+        """
+        error.context("downloading vmlinuz and initrd.img from %s" % self.url)
+        os.chdir(self.image_path)
+        kernel_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path,
+                                                 os.path.basename(self.kernel))
+        initrd_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path,
+                                                 os.path.basename(self.initrd))
+
+        if os.path.exists(self.kernel):
+            os.remove(self.kernel)
+        if os.path.exists(self.initrd):
+            os.remove(self.initrd)
+
+        utils.run(kernel_fetch_cmd)
+        utils.run(initrd_fetch_cmd)
+
+
+    def setup_nfs(self):
+        """
+        Copy the vmlinuz and initrd.img from nfs.
+        """
+        error.context("copying the vmlinuz and initrd.img from NFS share")
+
+        m_cmd = ("mount %s:%s %s -o ro" %
+                 (self.nfs_server, self.nfs_dir, self.nfs_mount))
+        utils.run(m_cmd)
+
+        try:
+            kernel_fetch_cmd = ("cp %s/%s/%s %s" %
+                                (self.nfs_mount, self.boot_path,
+                                os.path.basename(self.kernel), self.image_path))
+            utils.run(kernel_fetch_cmd)
+            initrd_fetch_cmd = ("cp %s/%s/%s %s" %
+                                (self.nfs_mount, self.boot_path,
+                                os.path.basename(self.initrd), self.image_path))
+            utils.run(initrd_fetch_cmd)
+        finally:
+            cleanup(self.nfs_mount)
+
+
+    def setup(self):
+        """
+        Configure the environment for unattended install.
+
+        Uses an appropriate strategy according to each install model.
+        """
+        logging.info("Starting unattended install setup")
+        virt_utils.display_attributes(self)
+
+        if self.unattended_file and (self.floppy or self.cdrom_unattended):
+            self.setup_boot_disk()
+        if self.medium in ["cdrom", "kernel_initrd"]:
+            if self.kernel and self.initrd:
+                self.setup_cdrom()
+        elif self.medium == "url":
+            self.setup_url()
+        elif self.medium == "nfs":
+            self.setup_nfs()
+        else:
+            raise ValueError("Unexpected installation method %s" %
+                             self.medium)
+
+
+@error.context_aware
+def run_unattended_install(test, params, env):
+    """
+    Unattended install test:
+    1) Starts a VM with an appropriated setup to start an unattended OS install.
+    2) Wait until the install reports to the install watcher its end.
+
+    @param test: KVM test object.
+    @param params: Dictionary with the test parameters.
+    @param env: Dictionary with test environment.
+    """
+    unattended_install_config = UnattendedInstallConfig(test, params)
+    unattended_install_config.setup()
+    vm = env.get_vm(params["main_vm"])
+    vm.create()
+
+    install_timeout = int(params.get("timeout", 3000))
+    port = vm.get_port(int(params.get("guest_port_unattended_install")))
+
+    migrate_background = params.get("migrate_background") == "yes"
+    if migrate_background:
+        mig_timeout = float(params.get("mig_timeout", "3600"))
+        mig_protocol = params.get("migration_protocol", "tcp")
+
+    logging.info("Waiting for installation to finish. Timeout set to %d s "
+                 "(%d min)", install_timeout, install_timeout/60)
+    error.context("waiting for installation to finish")
+
+    start_time = time.time()
+    while (time.time() - start_time) < install_timeout:
+        try:
+            vm.verify_alive()
+        except virt_vm.VMDeadError, e:
+            if params.get("wait_no_ack", "no") == "yes":
+                break
+            else:
+                raise e
+        vm.verify_kernel_crash()
+        if params.get("wait_no_ack", "no") == "no":
+            client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            try:
+                client.connect((vm.get_address(), port))
+                if client.recv(1024) == "done":
+                    break
+            except (socket.error, virt_vm.VMAddressError):
+                pass
+
+        if migrate_background:
+            vm.migrate(timeout=mig_timeout, protocol=mig_protocol)
+        else:
+            time.sleep(1)
+        if params.get("wait_no_ack", "no") == "no":
+            client.close()
+    else:
+        raise error.TestFail("Timeout elapsed while waiting for install to "
+                             "finish")
+
+    time_elapsed = time.time() - start_time
+    logging.info("Guest reported successful installation after %d s (%d min)",
+                 time_elapsed, time_elapsed/60)
+
+    if params.get("shutdown_cleanly", "yes") == "yes":
+        shutdown_cleanly_timeout = int(params.get("shutdown_cleanly_timeout",
+                                                  120))
+        logging.info("Wait for guest to shutdown cleanly")
+        if virt_utils.wait_for(vm.is_dead, shutdown_cleanly_timeout, 1, 1):
+            logging.info("Guest managed to shutdown cleanly")
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 04/11] Moving get_started code to client.virt.virt_utils
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 02/11] virt: Introducing virt_test.virt_test class Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 03/11] Moving unattended_install test from kvm test to common virt location Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 05/11] virt: Introducing libvirt VM class Lucas Meneghel Rodrigues
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

As most of the get_started.py code could be very well
shared among virt tests, moved the bulk of the code
to virt_utils.py. Now we have the function
virt_test_assistant(), that is generic enough so other
tests can implement their variation of the assistant
script.

Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
 client/tests/kvm/get_started.py |  162 +++----------------------------------
 client/virt/virt_utils.py       |  171 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 181 insertions(+), 152 deletions(-)

diff --git a/client/tests/kvm/get_started.py b/client/tests/kvm/get_started.py
index 4a40925..830c2a9 100755
--- a/client/tests/kvm/get_started.py
+++ b/client/tests/kvm/get_started.py
@@ -4,159 +4,19 @@ Program to help setup kvm test environment
 
 @copyright: Red Hat 2010
 """
-
-import os, sys, logging, shutil, glob
+import os, sys
 import common
-from autotest_lib.client.common_lib import logging_manager
-from autotest_lib.client.bin import utils
 from autotest_lib.client.virt import virt_utils
 
-
-def check_iso(url, destination, hash):
-    """
-    Verifies if ISO that can be find on url is on destination with right hash.
-
-    This function will verify the SHA1 hash of the ISO image. If the file
-    turns out to be missing or corrupted, let the user know we can download it.
-
-    @param url: URL where the ISO file can be found.
-    @param destination: Directory in local disk where we'd like the iso to be.
-    @param hash: SHA1 hash for the ISO image.
-    """
-    file_ok = False
-    if not destination:
-        os.makedirs(destination)
-    iso_path = os.path.join(destination, os.path.basename(url))
-    if not os.path.isfile(iso_path):
-        logging.warning("File %s not found", iso_path)
-        logging.warning("Expected SHA1 sum: %s", hash)
-        answer = utils.ask("Would you like to download it from %s?" % url)
-        if answer == 'y':
-            try:
-                utils.unmap_url_cache(destination, url, hash, method="sha1")
-                file_ok = True
-            except EnvironmentError, e:
-                logging.error(e)
-        else:
-            logging.warning("Missing file %s", iso_path)
-            logging.warning("Please download it or put an exsiting copy on the "
-                            "appropriate location")
-            return
-    else:
-        logging.info("Found %s", iso_path)
-        logging.info("Expected SHA1 sum: %s", hash)
-        answer = utils.ask("Would you like to check %s? It might take a while" %
-                           iso_path)
-        if answer == 'y':
-            try:
-                utils.unmap_url_cache(destination, url, hash, method="sha1")
-                file_ok = True
-            except EnvironmentError, e:
-                logging.error(e)
-        else:
-            logging.info("File %s present, but chose to not verify it",
-                         iso_path)
-            return
-
-    if file_ok:
-        logging.info("%s present, with proper checksum", iso_path)
-
+test_name = "kvm"
+test_dir = os.path.dirname(sys.modules[__name__].__file__)
+test_dir = os.path.abspath(test_dir)
+base_dir = "/tmp/kvm_autotest_root"
+default_userspace_paths = ["/usr/bin/qemu-kvm", "/usr/bin/qemu-img"]
+check_modules = ["kvm", "kvm-%s" % virt_utils.get_cpu_vendor(verbose=False)]
+online_docs_url = "https://github.com/autotest/autotest/wiki/KVMAutotest-GetStartedClient"
 
 if __name__ == "__main__":
-    logging_manager.configure_logging(virt_utils.VirtLoggingConfig(),
-                                      verbose=True)
-    logging.info("KVM test config helper")
-
-    logging.info("")
-    logging.info("1 - Verifying directories (check if the directory structure "
-                 "expected by the default test config is there)")
-    base_dir = "/tmp/kvm_autotest_root"
-    sub_dir_list = ["images", "isos", "steps_data"]
-    for sub_dir in sub_dir_list:
-        sub_dir_path = os.path.join(base_dir, sub_dir)
-        if not os.path.isdir(sub_dir_path):
-            logging.debug("Creating %s", sub_dir_path)
-            os.makedirs(sub_dir_path)
-        else:
-            logging.debug("Dir %s exists, not creating" %
-                          sub_dir_path)
-    logging.info("")
-    logging.info("2 - Creating config files from samples (copy the default "
-                 "config samples to actual config files)")
-    kvm_test_dir = os.path.dirname(sys.modules[__name__].__file__)
-    kvm_test_dir = os.path.abspath(kvm_test_dir)
-    config_file_list = glob.glob(os.path.join(kvm_test_dir, "*.cfg.sample"))
-    for config_file in config_file_list:
-        src_file = config_file
-        dst_file = config_file.rstrip(".sample")
-        if not os.path.isfile(dst_file):
-            logging.debug("Creating config file %s from sample", dst_file)
-            shutil.copyfile(src_file, dst_file)
-        else:
-            logging.debug("Config file %s exists, not touching" % dst_file)
-
-    logging.info("")
-    logging.info("3 - Verifying iso (make sure we have the OS ISO needed for "
-                 "the default test set)")
-
-    iso_name = "Fedora-15-x86_64-DVD.iso"
-    fedora_dir = "pub/fedora/linux/releases/15/Fedora/x86_64/iso"
-    url = os.path.join("http://download.fedoraproject.org/", fedora_dir,
-                       iso_name)
-    hash = "61b3407f62bac22d3a3b2e919c7fc960116012d7"
-    destination = os.path.join(base_dir, 'isos', 'linux')
-    path = os.path.join(destination, iso_name)
-    check_iso(url, destination, hash)
-
-    logging.info("")
-    logging.info("4 - Verifying winutils.iso (make sure we have the utility "
-                 "ISO needed for Windows testing)")
-
-    logging.info("In order to run the KVM autotests in Windows guests, we "
-                 "provide you an ISO that this script can download")
-
-    url = "http://people.redhat.com/mrodrigu/kvm/winutils.iso"
-    hash = "02930224756510e383c44c49bffb760e35d6f892"
-    destination = os.path.join(base_dir, 'isos', 'windows')
-    path = os.path.join(destination, iso_name)
-    check_iso(url, destination, hash)
-
-    logging.info("")
-    logging.info("5 - Checking if qemu is installed (certify qemu and qemu-kvm "
-                 "are in the place the default config expects)")
-    qemu_default_paths = ['/usr/bin/qemu-kvm', '/usr/bin/qemu-img']
-    for qemu_path in qemu_default_paths:
-        if not os.path.isfile(qemu_path):
-            logging.warning("No %s found. You might need to install qemu-kvm.",
-                            qemu_path)
-        else:
-            logging.debug("%s present", qemu_path)
-    logging.info("If you wish to change qemu-kvm to qemu or other binary path, "
-                 "you will have to modify tests.cfg")
-
-    logging.info("")
-    logging.info("6 - Checking for the KVM module (make sure kvm is loaded "
-                 "to accelerate qemu-kvm)")
-    if not utils.module_is_loaded("kvm"):
-        logging.warning("KVM module is not loaded. You might want to load it")
-    else:
-        logging.debug("KVM module loaded")
-
-    logging.info("")
-    logging.info("7 - Verify needed packages to get started")
-    logging.info("Please take a look at the online documentation "
-                 "http://www.linux-kvm.org/page/KVM-Autotest/Client_Install "
-                 "(session 'Install Prerequisite packages')")
-
-    client_dir = os.path.abspath(os.path.join(kvm_test_dir, "..", ".."))
-    autotest_bin = os.path.join(client_dir, 'bin', 'autotest')
-    control_file = os.path.join(kvm_test_dir, 'control')
-
-    logging.info("")
-    logging.info("When you are done fixing eventual warnings found, "
-                 "you can run the kvm test using the command line AS ROOT:")
-    logging.info("%s %s", autotest_bin, control_file)
-    logging.info("Autotest prints the results dir, so you can look at DEBUG "
-                 "logs if something went wrong")
-    logging.info("You can also edit the test config files (see output of "
-                 "step 2 for a list)")
+    virt_utils.virt_test_assistant(test_name, test_dir, base_dir,
+                                   default_userspace_paths, check_modules,
+                                   online_docs_url)
diff --git a/client/virt/virt_utils.py b/client/virt/virt_utils.py
index 962e2c3..b76e087 100644
--- a/client/virt/virt_utils.py
+++ b/client/virt/virt_utils.py
@@ -6,9 +6,10 @@ KVM test utility functions.
 
 import time, string, random, socket, os, signal, re, logging, commands, cPickle
 import fcntl, shelve, ConfigParser, threading, sys, UserDict, inspect, tarfile
-import struct, shutil
+import struct, shutil, glob
 from autotest_lib.client.bin import utils, os_dep
 from autotest_lib.client.common_lib import error, logging_config
+from autotest_lib.client.common_lib import logging_manager
 import rss_client, aexpect
 try:
     import koji
@@ -3287,3 +3288,171 @@ def if_set_macaddress(ifname, mac):
         logging.info(e)
         raise HwAddrSetError(ifname, mac)
     ctrl_sock.close()
+
+
+def check_iso(url, destination, hash):
+    """
+    Verifies if ISO that can be find on url is on destination with right hash.
+
+    This function will verify the SHA1 hash of the ISO image. If the file
+    turns out to be missing or corrupted, let the user know we can download it.
+
+    @param url: URL where the ISO file can be found.
+    @param destination: Directory in local disk where we'd like the iso to be.
+    @param hash: SHA1 hash for the ISO image.
+    """
+    file_ok = False
+    if not destination:
+        os.makedirs(destination)
+    iso_path = os.path.join(destination, os.path.basename(url))
+    if not os.path.isfile(iso_path):
+        logging.warning("File %s not found", iso_path)
+        logging.warning("Expected SHA1 sum: %s", hash)
+        answer = utils.ask("Would you like to download it from %s?" % url)
+        if answer == 'y':
+            try:
+                utils.unmap_url_cache(destination, url, hash, method="sha1")
+                file_ok = True
+            except EnvironmentError, e:
+                logging.error(e)
+        else:
+            logging.warning("Missing file %s", iso_path)
+            logging.warning("Please download it or put an exsiting copy on the "
+                            "appropriate location")
+            return
+    else:
+        logging.info("Found %s", iso_path)
+        logging.info("Expected SHA1 sum: %s", hash)
+        answer = utils.ask("Would you like to check %s? It might take a while" %
+                           iso_path)
+        if answer == 'y':
+            try:
+                utils.unmap_url_cache(destination, url, hash, method="sha1")
+                file_ok = True
+            except EnvironmentError, e:
+                logging.error(e)
+        else:
+            logging.info("File %s present, but chose to not verify it",
+                         iso_path)
+            return
+
+    if file_ok:
+        logging.info("%s present, with proper checksum", iso_path)
+
+
+def virt_test_assistant(test_name, test_dir, base_dir, default_userspace_paths,
+                        check_modules, online_docs_url):
+    """
+    Common virt test assistant module.
+
+    @param test_name: Test name, such as "kvm".
+    @param test_dir: Path with the test directory.
+    @param base_dir: Base directory used to hold images and isos.
+    @param default_userspace_paths: Important programs for a successful test
+            execution.
+    @param check_modules: Whether we want to verify if a given list of modules
+            is loaded in the system.
+    @param online_docs_url: URL to an online documentation system, such as an
+            wiki page.
+    """
+    logging_manager.configure_logging(VirtLoggingConfig(), verbose=True)
+    logging.info("%s test config helper", test_name)
+    step = 0
+
+    logging.info("")
+    step += 1
+    logging.info("%d - Verifying directories (check if the directory structure "
+                 "expected by the default test config is there)", step)
+    sub_dir_list = ["images", "isos", "steps_data"]
+    for sub_dir in sub_dir_list:
+        sub_dir_path = os.path.join(base_dir, sub_dir)
+        if not os.path.isdir(sub_dir_path):
+            logging.debug("Creating %s", sub_dir_path)
+            os.makedirs(sub_dir_path)
+        else:
+            logging.debug("Dir %s exists, not creating" %
+                          sub_dir_path)
+    logging.info("")
+    step += 1
+    logging.info("%d - Creating config files from samples (copy the default "
+                 "config samples to actual config files)", step)
+    config_file_list = glob.glob(os.path.join(test_dir, "*.cfg.sample"))
+    for config_file in config_file_list:
+        src_file = config_file
+        dst_file = config_file.rstrip(".sample")
+        if not os.path.isfile(dst_file):
+            logging.debug("Creating config file %s from sample", dst_file)
+            shutil.copyfile(src_file, dst_file)
+        else:
+            logging.debug("Config file %s exists, not touching" % dst_file)
+
+    logging.info("")
+    step += 1
+    logging.info("%s - Verifying iso (make sure we have the OS ISO needed for "
+                 "the default test set)", step)
+
+    iso_name = "Fedora-15-x86_64-DVD.iso"
+    fedora_dir = "pub/fedora/linux/releases/15/Fedora/x86_64/iso"
+    url = os.path.join("http://download.fedoraproject.org/", fedora_dir,
+                       iso_name)
+    hash = "61b3407f62bac22d3a3b2e919c7fc960116012d7"
+    destination = os.path.join(base_dir, 'isos', 'linux')
+    check_iso(url, destination, hash)
+
+    logging.info("")
+    step += 1
+    logging.info("%d - Verifying winutils.iso (make sure we have the utility "
+                 "ISO needed for Windows testing)", step)
+
+    logging.info("In order to run the KVM autotests in Windows guests, we "
+                 "provide you an ISO that this script can download")
+
+    url = "http://people.redhat.com/mrodrigu/kvm/winutils.iso"
+    hash = "02930224756510e383c44c49bffb760e35d6f892"
+    destination = os.path.join(base_dir, 'isos', 'windows')
+    path = os.path.join(destination, iso_name)
+    check_iso(url, destination, hash)
+
+    logging.info("")
+    step += 1
+    logging.info("%d - Checking if the appropriate userspace programs are "
+                 "installed", step)
+    for path in default_userspace_paths:
+        if not os.path.isfile(path):
+            logging.warning("No %s found. You might need to install %s.",
+                            path, os.path.basename(path))
+        else:
+            logging.debug("%s present", path)
+    logging.info("If you wish to change any userspace program path, "
+                 "you will have to modify tests.cfg")
+
+    if check_modules:
+        logging.info("")
+        step += 1
+        logging.info("%d - Checking for modules %s", step,
+                     ",".join(check_modules))
+        for module in check_modules:
+            if not utils.module_is_loaded(module):
+                logging.warning("Module %s is not loaded. You might want to "
+                                "load it", module)
+            else:
+                logging.debug("Module %s loaded", module)
+
+    if online_docs_url:
+        logging.info("")
+        step += 1
+        logging.info("%d - Verify needed packages to get started", step)
+        logging.info("Please take a look at the online documentation: %s",
+                     online_docs_url)
+
+    client_dir = os.path.abspath(os.path.join(test_dir, "..", ".."))
+    autotest_bin = os.path.join(client_dir, 'bin', 'autotest')
+    control_file = os.path.join(test_dir, 'control')
+
+    logging.info("")
+    logging.info("When you are done fixing eventual warnings found, "
+                 "you can run the test using this command line AS ROOT:")
+    logging.info("%s %s", autotest_bin, control_file)
+    logging.info("Autotest prints the results dir, so you can look at DEBUG "
+                 "logs if something went wrong")
+    logging.info("You can also edit the test config files")
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 05/11] virt: Introducing libvirt VM class
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
                   ` (2 preceding siblings ...)
  2011-10-11 21:07 ` [PATCH 04/11] Moving get_started code to client.virt.virt_utils Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-12  6:51   ` [Autotest] " Amos Kong
  2011-10-12  8:14   ` Daniel P. Berrange
  2011-10-11 21:07 ` [PATCH 06/11] virt: Introducing libvirt monitor Lucas Meneghel Rodrigues
                   ` (5 subsequent siblings)
  9 siblings, 2 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

This is a first attempt at providing a libvirt VM class,
in order to implement the needed methods for virt testing.
With this class, we will be able to implement a libvirt
test, that behaves similarly to the KVM test.

As of implementation details, libvirt_vm uses virsh
(a userspace program written on top of libvirt) to
do domain start, stop, verification of status and
other common operations. The reason why virsh was
used is to get more coverage of the userspace stack
that libvirt offers, and also to catch issues that
virsh users would catch.

Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
 client/virt/libvirt_vm.py | 1232 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1232 insertions(+), 0 deletions(-)
 create mode 100644 client/virt/libvirt_vm.py

diff --git a/client/virt/libvirt_vm.py b/client/virt/libvirt_vm.py
new file mode 100644
index 0000000..bed512f
--- /dev/null
+++ b/client/virt/libvirt_vm.py
@@ -0,0 +1,1232 @@
+"""
+Utility classes and functions to handle Virtual Machine creation using qemu.
+
+@copyright: 2008-2009 Red Hat Inc.
+"""
+
+import time, os, logging, fcntl, re, commands
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils, os_dep
+from xml.dom import minidom
+import virt_utils, virt_vm, aexpect
+
+DEBUG = False
+try:
+    VIRSH_EXEC = os_dep.command("virsh")
+except ValueError:
+    VIRSH_EXEC = None
+
+
+def libvirtd_restart():
+    """
+    Restart libvirt daemon.
+    """
+    try:
+        utils.run("service libvirtd restart")
+        logging.debug("Restarted libvirtd successfuly")
+        return True
+    except error.CmdError, detail:
+        logging.error("Failed to restart libvirtd: %s" % detail)
+        return False
+
+
+def virsh_cmd(cmd):
+    if VIRSH_EXEC is None:
+        raise ValueError('Missing command: virsh')
+    cmd_result = utils.run("%s %s" % (VIRSH_EXEC, cmd), ignore_status=True,
+                           verbose=DEBUG)
+    if DEBUG:
+        if cmd_result.stdout.strip():
+            logging.debug("stdout: %s", cmd_result.stdout.strip())
+        if cmd_result.stderr.strip():
+            logging.debug("stderr: %s", cmd_result.stderr.strip())
+    return cmd_result.stdout.strip()
+
+
+def virsh_uri():
+    """
+    Return the hypervisor canonical URI.
+    """
+    return virsh_cmd("uri")
+
+
+def virsh_hostname():
+    """
+    Return the hypervisor hostname.
+    """
+    return virsh_cmd("hostname")
+
+
+def virsh_domstate(name):
+    """
+    Return the state about a running domain.
+
+    @param name: VM name
+    """
+    return virsh_cmd("domstate %s" % name)
+
+
+def virsh_uuid(name):
+    """
+    Return the Converted domain name or id to the domain UUID.
+
+    @param name: VM name
+    """
+    return virsh_cmd("domuuid %s" % name)
+
+
+def virsh_screenshot(name, filename):
+    virsh_cmd("screenshot %s %s" % (name, filename))
+    return filename
+
+
+def virsh_dumpxml(name):
+    """
+    Return the domain information as an XML dump.
+
+    @param name: VM name
+    """
+    return virsh_cmd("dumpxml %s" % name)
+
+
+def virsh_is_alive(name):
+    """
+    Return True if the domain is started/alive.
+
+    @param name: VM name
+    """
+    return not virsh_is_dead(name)
+
+
+def virsh_is_dead(name):
+    """
+    Return True if the domain is not started/dead.
+
+    @param name: VM name
+    """
+    if (virsh_domstate(name) == 'running' or
+        virsh_domstate(name) == 'idle'):
+        return False
+    else:
+        return True
+
+
+def virsh_suspend(name):
+    """
+    Return True on successful domain suspention of VM.
+
+    Suspend  a domain. It is kept in memory but will not be scheduled.
+
+    @param name: VM name
+    """
+    try:
+        utils.run("virsh suspend %s" % (name))
+        if virsh_domstate(name) == 'paused':
+            logging.debug("Suspended VM %s", name)
+            return True
+        else:
+            return False
+    except error.CmdError:
+        logging.error("Suspending VM %s failed", name)
+        return False
+
+
+def virsh_resume(name):
+    """
+    Return True on successful domain resumption of VM.
+
+    Move a domain out of the suspended state.
+
+    @param name: VM name
+    """
+    try:
+        utils.run("virsh resume %s" % (name))
+        if virsh_is_alive(name):
+            logging.debug("Resumed VM %s", name)
+            return True
+        else:
+            return False
+    except error.CmdError:
+        logging.error("Resume VM %s failed", name)
+        return False
+
+
+def virsh_start(name, vm):
+    """
+    Return True on successful domain start.
+
+    Start a (previously defined) inactive domain.
+
+    @param name: VM name
+    """
+    if virsh_is_alive(name):
+        return
+    try:
+        utils.run("virsh start %s" % (name))
+        return True
+    except error.CmdError:
+        logging.error("Start VM %s failed", name)
+        return False
+
+
+def virsh_shutdown(name):
+    """
+    Return True on successful domain shutdown.
+
+    Gracefully shuts down a domain.
+
+    @param name: VM name
+    """
+    if virsh_domstate(name) == 'shut off':
+        return True
+    try:
+        utils.run("virsh shutdown %s" % (name))
+        return True
+    except error.CmdError:
+        logging.error("Shutdown VM %s failed", name)
+        return False
+
+
+def virsh_destroy(name):
+    """
+    Return True on successful domain destroy.
+
+    Immediately terminate the domain domain-id. The equivalent of ripping
+    the power cord out on a physical machine.
+
+    @param name: VM name
+    """
+    if virsh_domstate(name) == 'shut off':
+        return True
+    try:
+        utils.run("virsh destroy %s" % (name))
+        return True
+    except error.CmdError:
+        logging.error("Destroy VM %s failed", name)
+        return False
+
+
+def virsh_undefine(name):
+    """
+    Return True on successful domain undefine.
+
+    Undefine the configuration for an inactive domain. The domain should
+    be shutdown or destroyed before calling this method.
+
+    @param name: VM name
+    """
+    try:
+        utils.run("virsh undefine %s" % (name))
+        logging.debug("undefined VM %s", name)
+        return True
+    except error.CmdError:
+        logging.error("undefine VM %s failed", name)
+        return False
+
+
+def virsh_remove_domain(name):
+    """
+    Return True after forcefully removing a domain if it exists.
+
+    @param name: VM name
+    """
+    if virsh_domain_exists(name):
+        if virsh_is_alive(name):
+            virsh_destroy(name)
+        virsh_undefine(name)
+    return True
+
+
+def virsh_domain_exists(name):
+    """
+    Return True if a domain exits.
+
+    @param name: VM name
+    """
+    try:
+        utils.run("virsh domstate %s" % name)
+        return True
+    except error.CmdError:
+        logging.warning("VM %s does not exist", name)
+        return False
+
+
+class VM(virt_vm.BaseVM):
+    """
+    This class handles all basic VM operations for libvirt.
+    """
+    def __init__(self, name, params, root_dir, address_cache, state=None):
+        """
+        Initialize the object and set a few attributes.
+
+        @param name: The name of the object
+        @param params: A dict containing VM params
+                (see method make_qemu_command for a full description)
+        @param root_dir: Base directory for relative filenames
+        @param address_cache: A dict that maps MAC addresses to IP addresses
+        @param state: If provided, use this as self.__dict__
+        """
+        virt_vm.BaseVM.__init__(self, name, params)
+
+        if state:
+            self.__dict__ = state
+        else:
+            self.process = None
+            self.serial_console = None
+            self.redirs = {}
+            self.vnc_port = 5900
+            self.pci_assignable = None
+            self.netdev_id = []
+            self.device_id = []
+            self.pci_devices = []
+            self.uuid = None
+
+        self.spice_port = 8000
+        self.name = name
+        self.params = params
+        self.root_dir = root_dir
+        self.address_cache = address_cache
+        # For now, libvirt does not have a monitor property.
+        self.monitor = None
+
+
+    def verify_alive(self):
+        """
+        Make sure the VM is alive.
+
+        @raise VMDeadError: If the VM is dead
+        """
+        if not self.is_alive():
+            raise virt_vm.VMDeadError("Domain %s is inactive" % self.name,
+                                      virsh_domstate(self.name))
+
+
+    def is_alive(self):
+        """
+        Return True if VM is alive.
+        """
+        return virsh_is_alive(self.name)
+
+
+    def is_dead(self):
+        """
+        Return True if VM is dead.
+        """
+        return virsh_is_dead(self.name)
+
+
+    def clone(self, name=None, params=None, root_dir=None, address_cache=None,
+              copy_state=False):
+        """
+        Return a clone of the VM object with optionally modified parameters.
+        The clone is initially not alive and needs to be started using create().
+        Any parameters not passed to this function are copied from the source
+        VM.
+
+        @param name: Optional new VM name
+        @param params: Optional new VM creation parameters
+        @param root_dir: Optional new base directory for relative filenames
+        @param address_cache: A dict that maps MAC addresses to IP addresses
+        @param copy_state: If True, copy the original VM's state to the clone.
+                Mainly useful for make_qemu_command().
+        """
+        if name is None:
+            name = self.name
+        if params is None:
+            params = self.params.copy()
+        if root_dir is None:
+            root_dir = self.root_dir
+        if address_cache is None:
+            address_cache = self.address_cache
+        if copy_state:
+            state = self.__dict__.copy()
+        else:
+            state = None
+        return VM(name, params, root_dir, address_cache, state)
+
+
+    def __make_libvirt_command(self, name=None, params=None, root_dir=None):
+        """
+        Generate a libvirt command line. All parameters are optional. If a
+        parameter is not supplied, the corresponding value stored in the
+        class attributes is used.
+
+        @param name: The name of the object
+        @param params: A dict containing VM params
+        @param root_dir: Base directory for relative filenames
+
+        @note: The params dict should contain:
+               mem -- memory size in MBs
+               cdrom -- ISO filename to use with the qemu -cdrom parameter
+               extra_params -- a string to append to the qemu command
+               shell_port -- port of the remote shell daemon on the guest
+               (SSH, Telnet or the home-made Remote Shell Server)
+               shell_client -- client program to use for connecting to the
+               remote shell daemon on the guest (ssh, telnet or nc)
+               x11_display -- if specified, the DISPLAY environment variable
+               will be be set to this value for the qemu process (useful for
+               SDL rendering)
+               images -- a list of image object names, separated by spaces
+               nics -- a list of NIC object names, separated by spaces
+
+               For each image in images:
+               drive_format -- string to pass as 'if' parameter for this
+               image (e.g. ide, scsi)
+               image_snapshot -- if yes, pass 'snapshot=on' to qemu for
+               this image
+               image_boot -- if yes, pass 'boot=on' to qemu for this image
+               In addition, all parameters required by get_image_filename.
+
+               For each NIC in nics:
+               nic_model -- string to pass as 'model' parameter for this
+               NIC (e.g. e1000)
+        """
+        # helper function for command line option wrappers
+        def has_option(help, option):
+            return bool(re.search(r"--%s" % option, help, re.MULTILINE))
+
+        # Wrappers for all supported libvirt command line parameters.
+        # This is meant to allow support for multiple libvirt versions.
+        # Each of these functions receives the output of 'libvirt --help' as a
+        # parameter, and should add the requested command line option
+        # accordingly.
+
+        def add_name(help, name):
+            return " --name '%s'" % name
+
+        def add_hvm_or_pv(help, hvm_or_pv):
+            return " --%s" % hvm_or_pv
+
+        def add_mem(help, mem):
+            return " --ram=%s" % mem
+
+        def add_check_cpu(help):
+            if has_option(help, "check-cpu"):
+                return " --check-cpu"
+            else:
+                return ""
+
+        def add_smp(help, smp):
+            return " --vcpu=%s" % smp
+
+        def add_location(help, location):
+            #return " --location %s" % location
+            if has_option(help, "location"):
+                return " --location %s" % location
+            else:
+                return ""
+
+        def add_cdrom(help, filename, index=None):
+            if has_option(help, "cdrom"):
+                return " --cdrom %s" % filename
+            else:
+                return ""
+
+        def add_pxe(help):
+            if has_option(help, "pxe"):
+                return " --pxe"
+            else:
+                return ""
+
+        def add_drive(help, filename, pool=None, vol=None, device=None,
+                      bus=None, perms=None, size=None, sparse=False,
+                      cache=None, format=None):
+            cmd = " --disk"
+            if filename:
+                cmd += " path=%s" % filename
+            elif pool:
+                if vol:
+                    cmd += " vol=%s/%s" % (pool, vol)
+                else:
+                    cmd += " pool=%s" % pool
+            if device:
+                cmd += ",device=%s" % device
+            if bus:
+                cmd += ",bus=%s" % bus
+            if perms:
+                cmd += ",%s" % perms
+            if size:
+                cmd += ",size=%s" % size.rstrip("Gg")
+            if sparse:
+                cmd += ",sparse=false"
+            if format:
+                cmd += ",format=%s" % format
+            return cmd
+
+        def add_floppy(help, filename):
+            return " --disk path=%s,device=floppy,ro" % filename
+
+        def add_vnc(help, vnc_port):
+            return " --vnc --vncport=%d" % (vnc_port)
+
+        def add_sdl(help):
+            if has_option(help, "sdl"):
+                return " --sdl"
+            else:
+                return ""
+
+        def add_nographic(help):
+            return " --nographics"
+
+        def add_video(help, video_device):
+            if has_option(help, "video"):
+                return " --video=%s" % (video_device)
+            else:
+                return ""
+
+        def add_uuid(help, uuid):
+            if has_option(help, "uuid"):
+                return " --uuid %s" % uuid
+            else:
+                return ""
+
+        def add_os_type(help, os_type):
+            if has_option(help, "os-type"):
+                return " --os-type %s" % os_type
+            else:
+                return ""
+
+        def add_os_variant(help, os_variant):
+            if has_option(help, "os-variant"):
+                return " --os-variant %s" % os_variant
+            else:
+                return ""
+
+        def add_pcidevice(help, pci_device):
+            if has_option(help, "host-device"):
+                return " --host-device %s" % pci_device
+            else:
+                return ""
+
+        def add_soundhw(help, sound_device):
+            if has_option(help, "soundhw"):
+                return " --soundhw %s" % sound_device
+            else:
+                return ""
+
+        def add_serial(help, filename):
+            if has_option(help, "serial"):
+                return "  --serial file,path=%s --serial pty" % filename
+            else:
+                return ""
+
+        def add_kernel_cmdline(help, cmdline):
+            return " -append %s" % cmdline
+
+        # End of command line option wrappers
+
+        if name is None:
+            name = self.name
+        if params is None:
+            params = self.params
+        if root_dir is None:
+            root_dir = self.root_dir
+
+        # Clone this VM using the new params
+        vm = self.clone(name, params, root_dir, copy_state=True)
+
+        virt_install_binary = virt_utils.get_path(root_dir,
+                                    params.get("virt_install_binary",
+                                    "virt-install"))
+
+        help = utils.system_output("%s --help" % virt_install_binary)
+
+        # Start constructing the qemu command
+        virt_install_cmd = ""
+        # Set the X11 display parameter if requested
+        if params.get("x11_display"):
+            virt_install_cmd += "DISPLAY=%s " % params.get("x11_display")
+        # Add the qemu binary
+        virt_install_cmd += virt_install_binary
+
+        # hvm or pv specificed by libvirt switch (pv used  by Xen only)
+        hvm_or_pv = params.get("hvm_or_pv")
+        if hvm_or_pv:
+            virt_install_cmd += add_hvm_or_pv(help, hvm_or_pv)
+
+        # Add the VM's name
+        virt_install_cmd += add_name(help, name)
+
+        mem = params.get("mem")
+        if mem:
+            virt_install_cmd += add_mem(help, mem)
+
+        # TODO: should we do the check before we call ? negative case ?
+        check_cpu = params.get("use_check_cpu")
+        if check_cpu:
+            virt_install_cmd += add_check_cpu(help)
+
+        smp = params.get("smp")
+        if smp:
+            virt_install_cmd += add_smp(help, smp)
+
+        # TODO: directory location for vmlinuz/kernel for cdrom install ?
+        location = None
+        if params.get("medium") == 'url':
+            location = params.get("url")
+        elif params.get("medium") == 'kernel_initrd':
+            # directory location of kernel/initrd pair (directory layout must
+            # be in format libvirt will recognize)
+            location = params.get("image_dir")
+        elif params.get("medium") == 'nfs':
+            location = "nfs:%s:%s" % (params.get("nfs_server"),
+                                      params.get("nfs_dir"))
+        elif params.get("medium") == 'cdrom':
+            if params.get("use_libvirt_cdrom_switch") == 'yes':
+                virt_install_cmd += add_cdrom(help, params.get("cdrom_cd1"))
+            else:
+                location = params.get("image_dir")
+
+        if location:
+            virt_install_cmd += add_location(help, location)
+
+        if params.get("display") == "vnc":
+            if params.get("vnc_port"):
+                vm.vnc_port = int(params.get("vnc_port"))
+            virt_install_cmd += add_vnc(help, vm.vnc_port)
+        elif params.get("display") == "sdl":
+            virt_install_cmd += add_sdl(help)
+        elif params.get("display") == "nographic":
+            virt_install_cmd += add_nographic(help)
+
+        video_device = params.get("video_device")
+        if video_device:
+            virt_install_cmd += add_video(help, video_device)
+
+        sound_device = params.get("sound_device")
+        if sound_device:
+            virt_install_cmd += add_soundhw(help, sound_device)
+
+        # if none is given a random UUID will be generated by libvirt
+        if params.get("uuid"):
+            virt_install_cmd += add_uuid(help, params.get("uuid"))
+
+        # selectable OS type
+        if params.get("use_os_type") == "yes":
+            virt_install_cmd += add_os_type(help, params.get("os_type"))
+
+        # selectable OS variant
+        if params.get("use_os_variant") == "yes":
+            virt_install_cmd += add_os_variant(help, params.get("os_variant"))
+
+        # If the PCI assignment step went OK, add each one of the PCI assigned
+        # devices to the command line.
+        if self.pci_devices:
+            for pci_id in self.pci_devices:
+                virt_install_cmd += add_pcidevice(help, pci_id)
+
+        for image_name in params.objects("images"):
+            image_params = params.object_params(image_name)
+            filename = virt_vm.get_image_filename(image_params, root_dir)
+            if image_params.get("use_storage_pool") == "yes":
+                filename = None
+            if image_params.get("boot_drive") == "no":
+                continue
+            virt_install_cmd += add_drive(help,
+                             filename,
+                                  image_params.get("image_pool"),
+                                  image_params.get("image_vol"),
+                                  image_params.get("image_device"),
+                                  image_params.get("image_bus"),
+                                  image_params.get("image_perms"),
+                                  image_params.get("image_size"),
+                                  image_params.get("drive_sparse"),
+                                  image_params.get("drive_cache"),
+                                  image_params.get("image_format"))
+
+        for cdrom in params.objects("cdroms"):
+            cdrom_params = params.object_params(cdrom)
+            iso = cdrom_params.get("cdrom")
+            if params.get("use_libvirt_cdrom_switch") == 'yes':
+                # we don't want to skip the winutils iso
+                if not cdrom == 'winutils':
+                    logging.debug("Using --cdrom instead of --disk for install")
+                    logging.debug("Skipping CDROM:%s:%s", cdrom, iso)
+                    continue
+            if params.get("medium") == 'cdrom_no_kernel_initrd':
+                if iso == params.get("cdrom_cd1"):
+                    logging.debug("Using cdrom or url for install")
+                    logging.debug("Skipping CDROM: %s", iso)
+                    continue
+
+            if iso:
+                virt_install_cmd += add_drive(help,
+                             virt_utils.get_path(root_dir, iso),
+                                  image_params.get("iso_image_pool"),
+                                  image_params.get("iso_image_vol"),
+                                  'cdrom',
+                                  None,
+                                  None,
+                                  None,
+                                  None,
+                                  None,
+                                  None)
+
+        # We may want to add {floppy_otps} parameter for -fda
+        # {fat:floppy:}/path/. However vvfat is not usually recommended.
+        floppy = params.get("floppy")
+        if floppy:
+            floppy = virt_utils.get_path(root_dir, floppy)
+            virt_install_cmd += add_drive(help, floppy,
+                              None,
+                              None,
+                              'floppy',
+                              None,
+                              None,
+                              None,
+                              None,
+                              None,
+                              None)
+
+        # FIXME: for now in the pilot always add mac address to virt-install
+        vlan = 0
+        mac = vm.get_mac_address(vlan)
+        if mac:
+            virt_install_cmd += " --mac %s" % mac
+            self.nic_mac = mac
+
+        virt_install_cmd += (" --network %s,model=%s" %
+                             (params.get("virsh_network"),
+                              params.get("nic_model")))
+
+        if params.get("use_no_reboot") == "yes":
+            virt_install_cmd += " --noreboot"
+
+        if params.get("use_autostart") == "yes":
+            virt_install_cmd += " --autostart"
+
+        if params.get("virt_install_debug") == "yes":
+            virt_install_cmd += " --debug"
+
+        # bz still open, not fully functional yet
+        if params.get("use_virt_install_wait") == "yes":
+            virt_install_cmd += (" --wait %s" %
+                                 params.get("virt_install_wait_time"))
+
+        extra_params = params.get("extra_params")
+        if extra_params:
+            virt_install_cmd += " --extra-args '%s'" % extra_params
+
+        virt_install_cmd += " --noautoconsole"
+
+        return virt_install_cmd
+
+
+    @error.context_aware
+    def create(self, name=None, params=None, root_dir=None, timeout=5.0,
+               migration_mode=None, mac_source=None):
+        """
+        Start the VM by running a qemu command.
+        All parameters are optional. If name, params or root_dir are not
+        supplied, the respective values stored as class attributes are used.
+
+        @param name: The name of the object
+        @param params: A dict containing VM params
+        @param root_dir: Base directory for relative filenames
+        @param migration_mode: If supplied, start VM for incoming migration
+                using this protocol (either 'tcp', 'unix' or 'exec')
+        @param migration_exec_cmd: Command to embed in '-incoming "exec: ..."'
+                (e.g. 'gzip -c -d filename') if migration_mode is 'exec'
+        @param mac_source: A VM object from which to copy MAC addresses. If not
+                specified, new addresses will be generated.
+
+        @raise VMCreateError: If qemu terminates unexpectedly
+        @raise VMKVMInitError: If KVM initialization fails
+        @raise VMHugePageError: If hugepage initialization fails
+        @raise VMImageMissingError: If a CD image is missing
+        @raise VMHashMismatchError: If a CD image hash has doesn't match the
+                expected hash
+        @raise VMBadPATypeError: If an unsupported PCI assignment type is
+                requested
+        @raise VMPAError: If no PCI assignable devices could be assigned
+        """
+        error.context("creating '%s'" % self.name)
+        self.destroy(free_mac_addresses=False)
+
+        if name is not None:
+            self.name = name
+        if params is not None:
+            self.params = params
+        if root_dir is not None:
+            self.root_dir = root_dir
+        name = self.name
+        params = self.params
+        root_dir = self.root_dir
+
+        # Verify the md5sum of the ISO images
+        for cdrom in params.objects("cdroms"):
+            cdrom_params = params.object_params(cdrom)
+            iso = cdrom_params.get("cdrom")
+            if iso:
+                iso = virt_utils.get_path(root_dir, iso)
+                if not os.path.exists(iso):
+                    raise virt_vm.VMImageMissingError(iso)
+                compare = False
+                if cdrom_params.get("md5sum_1m"):
+                    logging.debug("Comparing expected MD5 sum with MD5 sum of "
+                                  "first MB of ISO file...")
+                    actual_hash = utils.hash_file(iso, 1048576, method="md5")
+                    expected_hash = cdrom_params.get("md5sum_1m")
+                    compare = True
+                elif cdrom_params.get("md5sum"):
+                    logging.debug("Comparing expected MD5 sum with MD5 sum of "
+                                  "ISO file...")
+                    actual_hash = utils.hash_file(iso, method="md5")
+                    expected_hash = cdrom_params.get("md5sum")
+                    compare = True
+                elif cdrom_params.get("sha1sum"):
+                    logging.debug("Comparing expected SHA1 sum with SHA1 sum "
+                                  "of ISO file...")
+                    actual_hash = utils.hash_file(iso, method="sha1")
+                    expected_hash = cdrom_params.get("sha1sum")
+                    compare = True
+                if compare:
+                    if actual_hash == expected_hash:
+                        logging.debug("Hashes match")
+                    else:
+                        raise virt_vm.VMHashMismatchError(actual_hash,
+                                                          expected_hash)
+
+        # Make sure the following code is not executed by more than one thread
+        # at the same time
+        lockfile = open("/tmp/libvirt-autotest-vm-create.lock", "w+")
+        fcntl.lockf(lockfile, fcntl.LOCK_EX)
+
+        try:
+            # Handle port redirections
+            redir_names = params.objects("redirs")
+            host_ports = virt_utils.find_free_ports(5000, 6000, len(redir_names))
+            self.redirs = {}
+            for i in range(len(redir_names)):
+                redir_params = params.object_params(redir_names[i])
+                guest_port = int(redir_params.get("guest_port"))
+                self.redirs[guest_port] = host_ports[i]
+
+            # Generate netdev/device IDs for all NICs
+            self.netdev_id = []
+            self.device_id = []
+            for nic in params.objects("nics"):
+                self.netdev_id.append(virt_utils.generate_random_id())
+                self.device_id.append(virt_utils.generate_random_id())
+
+            # Find available PCI devices
+            self.pci_devices = []
+            for device in params.objects("pci_devices"):
+                self.pci_devices.append(device)
+
+            # Find available VNC port, if needed
+            if params.get("display") == "vnc":
+                self.vnc_port = virt_utils.find_free_port(5900, 6100)
+
+            # Find available spice port, if needed
+            if params.get("spice"):
+                self.spice_port = virt_utils.find_free_port(8000, 8100)
+
+            # Find random UUID if specified 'uuid = random' in config file
+            if params.get("uuid") == "random":
+                f = open("/proc/sys/kernel/random/uuid")
+                self.uuid = f.read().strip()
+                f.close()
+
+            # Generate or copy MAC addresses for all NICs
+            num_nics = len(params.objects("nics"))
+            for vlan in range(num_nics):
+                nic_name = params.objects("nics")[vlan]
+                nic_params = params.object_params(nic_name)
+                mac = (nic_params.get("nic_mac") or
+                       mac_source and mac_source.get_mac_address(vlan))
+                if mac:
+                    virt_utils.set_mac_address(self.instance, vlan, mac)
+                else:
+                    virt_utils.generate_mac_address(self.instance, vlan)
+
+            # Make qemu command
+            install_command = self.__make_libvirt_command()
+
+            logging.info("Running libvirt command:\n%s", install_command)
+            utils.run(install_command, verbose=False)
+            # Wait for the domain to be created
+            virt_utils.wait_for(func=self.is_alive, timeout=60,
+                                text=("waiting for domain %s to start" %
+                                      self.name))
+
+            # Establish a session with the serial console -- requires a version
+            # of netcat that supports -U
+            self.serial_console = aexpect.ShellSession(
+                "nc -U %s" % self.get_serial_console_filename(),
+                auto_close=False,
+                output_func=virt_utils.log_line,
+                output_params=("serial-%s.log" % name,))
+
+        finally:
+            fcntl.lockf(lockfile, fcntl.LOCK_UN)
+            lockfile.close()
+
+
+    def destroy(self, gracefully=True, free_mac_addresses=True):
+        """
+        Destroy the VM.
+
+        If gracefully is True, first attempt to shutdown the VM with a shell
+        command. If that fails, send SIGKILL to the qemu process.
+
+        @param gracefully: If True, an attempt will be made to end the VM
+                using a shell command before trying to end the qemu process
+                with a 'quit' or a kill signal.
+        @param free_mac_addresses: If True, the MAC addresses used by the VM
+                will be freed.
+        """
+        try:
+            # Is it already dead?
+            if self.is_dead():
+                return
+
+            logging.debug("Destroying VM")
+            if gracefully and self.params.get("shutdown_command"):
+                # Try to destroy with shell command
+                logging.debug("Trying to shutdown VM with shell command")
+                try:
+                    session = self.login()
+                except (virt_utils.LoginError, virt_vm.VMError), e:
+                    logging.debug(e)
+                else:
+                    try:
+                        # Send the shutdown command
+                        session.sendline(self.params.get("shutdown_command"))
+                        logging.debug("Shutdown command sent; waiting for VM "
+                                      "to go down...")
+                        if virt_utils.wait_for(self.is_dead, 60, 1, 1):
+                            logging.debug("VM is down")
+                            return
+                    finally:
+                        session.close()
+
+            virsh_destroy(self.name)
+
+        finally:
+            if self.serial_console:
+                self.serial_console.close()
+            for f in ([self.get_testlog_filename(),
+                       self.get_serial_console_filename()]):
+                try:
+                    os.unlink(f)
+                except OSError:
+                    pass
+            if hasattr(self, "migration_file"):
+                try:
+                    os.unlink(self.migration_file)
+                except OSError:
+                    pass
+            if free_mac_addresses:
+                num_nics = len(self.params.objects("nics"))
+                for vlan in range(num_nics):
+                    self.free_mac_address(vlan)
+
+
+    def get_address(self, index=0):
+        """
+        Return the address of a NIC of the guest, in host space.
+
+        If port redirection is used, return 'localhost' (the NIC has no IP
+        address of its own).  Otherwise return the NIC's IP address.
+
+        @param index: Index of the NIC whose address is requested.
+        @raise VMMACAddressMissingError: If no MAC address is defined for the
+                requested NIC
+        @raise VMIPAddressMissingError: If no IP address is found for the the
+                NIC's MAC address
+        @raise VMAddressVerificationError: If the MAC-IP address mapping cannot
+                be verified (using arping)
+        """
+        nics = self.params.objects("nics")
+        nic_name = nics[index]
+        nic_params = self.params.object_params(nic_name)
+        if nic_params.get("nic_mode") == "tap":
+            mac = self.get_mac_address(index).lower()
+            # Get the IP address from the cache
+            ip = self.address_cache.get(mac)
+            if not ip:
+                raise virt_vm.VMIPAddressMissingError(mac)
+            # Make sure the IP address is assigned to this guest
+            macs = [self.get_mac_address(i) for i in range(len(nics))]
+            if not virt_utils.verify_ip_address_ownership(ip, macs):
+                raise virt_vm.VMAddressVerificationError(mac, ip)
+            return ip
+        else:
+            return "localhost"
+
+
+    def get_port(self, port, nic_index=0):
+        """
+        Return the port in host space corresponding to port in guest space.
+
+        @param port: Port number in host space.
+        @param nic_index: Index of the NIC.
+        @return: If port redirection is used, return the host port redirected
+                to guest port port. Otherwise return port.
+        @raise VMPortNotRedirectedError: If an unredirected port is requested
+                in user mode
+        """
+        nic_name = self.params.objects("nics")[nic_index]
+        nic_params = self.params.object_params(nic_name)
+        if nic_params.get("nic_mode") == "tap":
+            return port
+        else:
+            try:
+                return self.redirs[port]
+            except KeyError:
+                raise virt_vm.VMPortNotRedirectedError(port)
+
+
+    def get_ifname(self, nic_index=0):
+        """
+        Return the ifname of a tap device associated with a NIC.
+
+        @param nic_index: Index of the NIC
+        """
+        nics = self.params.objects("nics")
+        nic_name = nics[nic_index]
+        nic_params = self.params.object_params(nic_name)
+        if nic_params.get("nic_ifname"):
+            return nic_params.get("nic_ifname")
+        else:
+            return "t%d-%s" % (nic_index, self.instance[-11:])
+
+
+    def get_virsh_mac_address(self, nic_index):
+        thexml = virsh_dumpxml(self.name)
+        dom = minidom.parseString(thexml)
+        count = 0
+        for node in dom.getElementsByTagName('interface'):
+            source = node.childNodes[1]
+            x = source.attributes["address"]
+            if nic_index == count:
+                return x.value
+            count += 1
+
+
+    def get_mac_address(self, nic_index=0):
+        """
+        Return the MAC address of a NIC.
+
+        @param nic_index: Index of the NIC
+        @raise VMMACAddressMissingError: If no MAC address is defined for the
+                requested NIC
+        """
+        nic_name = self.params.objects("nics")[nic_index]
+        nic_params = self.params.object_params(nic_name)
+        if nic_params.get("vm_type") == 'libvirt':
+            if self.params.objects("type")[0] == 'unattended_install':
+                mac = virt_utils.get_mac_address(self.instance, nic_index)
+            else:
+                mac = self.get_virsh_mac_address(nic_index)
+        else:
+            mac = (nic_params.get("nic_mac") or
+                virt_utils.get_mac_address(self.instance, nic_index))
+        if not mac:
+            raise virt_vm.VMMACAddressMissingError(nic_index)
+        return mac
+
+
+    def free_mac_address(self, nic_index=0):
+        """
+        Free a NIC's MAC address.
+
+        @param nic_index: Index of the NIC
+        """
+        virt_utils.free_mac_address(self.instance, nic_index)
+
+
+    def get_pid(self):
+        """
+        Return the VM's PID.  If the VM is dead return None.
+
+        @note: This works under the assumption that self.process.get_pid()
+        returns the PID of the parent shell process.
+        """
+        try:
+            filename = "/var/run/libvirt/qemu/%s.pid" % self.name
+            if not self.params.get("type") == "unattended_install":
+                if os.path.exists(filename):
+                    self.process = int(open(filename).read())
+            children = commands.getoutput("ps --ppid=%d -o pid=" %
+                                          self.process.get_pid()).split()
+            return int(children[0])
+        except (TypeError, IndexError, ValueError):
+            return None
+
+
+    def get_shell_pid(self):
+        """
+        Return the PID of the parent shell process.
+
+        @note: This works under the assumption that self.process.get_pid()
+        returns the PID of the parent shell process.
+        """
+        return self.process.get_pid()
+
+
+    def get_shared_meminfo(self):
+        """
+        Returns the VM's shared memory information.
+
+        @return: Shared memory used by VM (MB)
+        """
+        if self.is_dead():
+            logging.error("Could not get shared memory info from dead VM.")
+            return None
+
+        filename = "/proc/%d/statm" % self.get_pid()
+        shm = int(open(filename).read().split()[2])
+        # statm stores informations in pages, translate it to MB
+        return shm * 4.0 / 1024
+
+
+    @error.context_aware
+    def reboot(self, session=None, method="shell", nic_index=0, timeout=240):
+        """
+        Reboot the VM and wait for it to come back up by trying to log in until
+        timeout expires.
+
+        @param session: A shell session object or None.
+        @param method: Reboot method.  Can be "shell" (send a shell reboot
+                command).
+        @param nic_index: Index of NIC to access in the VM, when logging in
+                after rebooting.
+        @param timeout: Time to wait for login to succeed (after rebooting).
+        @return: A new shell session object.
+        """
+        error.base_context("rebooting '%s'" % self.name, logging.info)
+        error.context("before reboot")
+        session = session or self.login()
+        error.context()
+
+        if method == "shell":
+            session.sendline(self.params.get("reboot_command"))
+        else:
+            raise virt_vm.VMRebootError("Unknown reboot method: %s" % method)
+
+        error.context("waiting for guest to go down", logging.info)
+        if not virt_utils.wait_for(lambda:
+                                  not session.is_responsive(timeout=30),
+                                  120, 0, 1):
+            raise virt_vm.VMRebootError("Guest refuses to go down")
+        session.close()
+
+        error.context("logging in after reboot", logging.info)
+        return self.wait_for_login(nic_index, timeout=timeout)
+
+
+    def needs_restart(self, name, params, basedir):
+        """
+        Verifies whether the current qemu commandline matches the requested
+        one, based on the test parameters.
+        """
+        return (self.__make_libvirt_command() !=
+                self.__make_libvirt_command(name, params, basedir))
+
+
+    def screendump(self, filename, debug=False):
+        if debug:
+            logging.debug("Requesting screenshot %s" % filename)
+        return virsh_screenshot(self.name, filename)
+
+
+    def wait_for_start(self, count=60):
+        """
+        Return True on successful domain start.
+
+        Wait for a domain to start, libvirt does not block on domain
+        start so we need to watch for successful completion.
+
+        @param name: VM name
+        @param name: Optional timeout value
+        """
+        timeout = count
+        while count > 0:
+            # check every 5 seconds
+            if count % 5 == 0:
+                if virsh_is_alive(self.name):
+                    session = self.wait_for_login(timeout=60)
+                    session.close()
+                    logging.debug("Start took %d seconds", timeout - count)
+                    return True
+            count -= 1
+            time.sleep(1)
+            logging.debug("Waiting for guest to start %d", count)
+        return False
+
+
+    def start(self):
+        """
+        Starts this VM.
+        """
+        if virsh_start(self.name):
+            if self.wait_for_start():
+                logging.debug("Started VM %s", self.name)
+                return True
+            else:
+                logging.error("VM %s failed to start", self.name)
+                return False
+        else:
+            logging.error("VM %s failed to start", self.name)
+            return False
+
+
+    def wait_for_shutdown(self, count=60):
+        """
+        Return True on successful domain shutdown.
+
+        Wait for a domain to shutdown, libvirt does not block on domain
+        shutdown so we need to watch for successful completion.
+
+        @param name: VM name
+        @param name: Optional timeout value
+        """
+        timeout = count
+        while count > 0:
+            # check every 5 seconds
+            if count % 5 == 0:
+                if virsh_is_dead(self.name):
+                    logging.debug("Shutdown took %d seconds", timeout - count)
+                    return True
+            count -= 1
+            time.sleep(1)
+            logging.debug("Waiting for guest to shutdown %d", count)
+        return False
+
+
+    def shutdown(self):
+        """
+        Shuts down this VM.
+        """
+        if virsh_shutdown(self.name):
+            if self.wait_for_shutdown():
+                logging.debug("VM %s shut down", self.name)
+                return True
+            else:
+                logging.error("VM %s failed to shut down", self.name)
+                return False
+        else:
+            logging.error("VM %s failed to shut down", self.name)
+            return False
+
+
+    def send_key(self):
+        pass
+
+
+    def migrate(self):
+        pass
+
+
+    def pause(self):
+        pass
+
+
+    def resume(self):
+        pass
+
+
+    def save_to_file(self):
+        pass
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 06/11] virt: Introducing libvirt monitor
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
                   ` (3 preceding siblings ...)
  2011-10-11 21:07 ` [PATCH 05/11] virt: Introducing libvirt VM class Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-12  7:48   ` [Autotest] " Amos Kong
  2011-10-11 21:07 ` [PATCH 07/11] virt.virt_env_process: Add libvirt vm handling Lucas Meneghel Rodrigues
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

This is an initial implementation for a libvirt monitor.
With it, we plan on making the libvirt test use all the
monitor features, making most of the tests available for
kvm available for libvirt.

As of implementation details, it uses aexpect to get a
virsh shell, and then the monitor methods are implemented
by executing commands on that virsh shell.

As of now, the libvirt vm class is still not using the
monitor code, but we plan on making the move soon enough.

Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
 client/virt/libvirt_monitor.py |  322 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 322 insertions(+), 0 deletions(-)
 create mode 100644 client/virt/libvirt_monitor.py

diff --git a/client/virt/libvirt_monitor.py b/client/virt/libvirt_monitor.py
new file mode 100644
index 0000000..05b838c
--- /dev/null
+++ b/client/virt/libvirt_monitor.py
@@ -0,0 +1,322 @@
+import re, tempfile, xml.dom.minidom, logging
+import virt_utils, aexpect
+from autotest_lib.client.bin import utils
+
+
+class VirshMonitor:
+    """
+    Wraps "Virsh monitor" commands.
+    """
+
+    def __init__(self, virsh_exec='virsh', name, vmname, password=None,
+                 prompt=None, hostname='localhost', driver=None, username=None,
+                 linesep="\\n"):
+        """
+        Connect to the hypervisor and get virsh prompt.
+
+        @param virsh_exec: Virsh executable
+        @param name: Monitor identifier (a string)
+        @param vmname: VM name
+        @param password: Hypervisor user password
+        @param prompt: Virsh prompt
+        @param hostname: Hypervisor IP
+        @param driver: Hypervisor driver type
+        @param username: Hypervisor  username
+        @param linesep: The line separator to use when sending lines
+                (e.g. '\\n' or '\\r\\n')
+        """
+        self.virsh_exec = virsh_exec
+        self.name = name
+        self.vmname = vmname
+        self.password = password
+        self.prompt = prompt
+        self.hostname = hostname
+        self.driver = driver
+        self.username = username
+        self.session = self.login()
+        self.virsh_cmd = {"help":"help", "quit":"destroy " + self.vmname,
+                           "stop":"suspend", "cont":"resume"}
+        self.drive_map = {}
+        self.network_info = []
+        self.disk_info = []
+        self._parse_domxml()
+
+
+    def __del__(self):
+        self.session.sendline("quit")
+
+
+    def __getstate__(self):
+        pass
+
+
+    def __setstate__(self, state):
+        pass
+
+
+    def __getinitargs__(self):
+        # Save some information when pickling -- will be passed to the
+        # constructor upon unpickling
+        return (self.name, self.vmname, self.password, self.prompt,
+                self.hostname, self.driver, self.username)
+
+
+    def login(self, timeout=10):
+        """
+        Log into the hypervisor using required URIs .
+
+        @timeout: Time in seconds that we will wait before giving up on logging
+                into the host.
+        @return: A ShellSession object.
+        """
+        if self.driver is None:
+            uri = utils.system_output('%s uri' % self.virsh_exec)
+        else:
+            uri = "%s+ssh://%s@%s/system" % (self.driver, self.username,
+                                             self.host)
+
+        command = "%s --connect  %s" % (self.virsh_exec, uri)
+
+        session = aexpect.ShellSession(command, linesep=self.linesep,
+                                       prompt=self.prompt)
+
+        if self.username is not None:
+            try:
+                virt_utils._remote_login(session, self.username, self.password,
+                                         self.prompt, self.timeout)
+            except aexpect.ShellError:
+                session.close()
+                session = None
+
+        return session
+
+
+    def _parse_domxml(self):
+        self.session.cmd_output("\n")
+        domxml = self.session.cmd_output("dumpxml %s \n" % self.vmname)
+        self._parse_dev(domxml)
+
+
+    def _parse_dev(self, domxml):
+        dom = xml.dom.minidom.parseString(domxml)
+        self.network_info = []
+        for elems in dom.getElementsByTagName('interface'):
+            self.network_info.append(elems.toxml())
+
+        self.disk_info = []
+        for elems in dom.getElementsByTagName('disk'):
+            self.disk_info.append(elems.toxml())
+
+
+    def verify_responsive(self):
+        """
+        Make sure the monitor is responsive by sending a command.
+        """
+        self.cmd("help")
+
+
+    def cmd(self, command):
+        """
+        Send command to the monitor.
+
+        @param command: Command to send to the monitor
+        @return: Output received from the monitor
+        """
+        def dev_add(command):
+            """
+            Create the xml file for the device to be attached
+            """
+            parm_dic = dict(re.findall("(id|driver|mac|drive)=([^,\s]+)",
+                                         command))
+            self.session.cmd_output("\n")
+            if parm_dic.has_key("drive"):
+                self.drive_map[parm_dic["drive"]]["driver"] = parm_dic\
+                                                              ["driver"]
+                self.drive_map[parm_dic["drive"]]["device_id"] = parm_dic["id"]
+                self.drive_map[parm_dic["drive"]]["dev"] = "vd" + str(len(
+                                                              self.drive_map))
+                doc = xml.dom.minidom.Document()
+                topelem = doc.createElement("disk")
+                topelem.setAttribute('device', 'disk')
+                topelem.setAttribute('type', 'file')
+                doc.appendChild(topelem)
+                chld_elem = doc.createElement("driver")
+                chld_elem.setAttribute('name', "qemu")
+                topelem.appendChild(chld_elem)
+                chld_elem = doc.createElement("source")
+                chld_elem.setAttribute('file', self.drive_map[parm_dic["drive"]
+                                                             ]["file"])
+                topelem.appendChild(chld_elem)
+                chld_elem = doc.createElement("target")
+                if "virtio-blk-pci" in command:
+                    self.drive_map[parm_dic["drive"]]["driver"] = "virtio"
+                chld_elem.setAttribute('bus', self.drive_map[parm_dic["drive"]
+                                                            ]["driver"])
+                chld_elem.setAttribute('dev', self.drive_map[parm_dic["drive"]
+                                                            ]["dev"])
+                topelem.appendChild(chld_elem)
+            else:
+                netpool_lst = self.session.cmd_output("net-list"
+                                                               ).split('\n')
+                netpool = []
+                for r in range(2, len(netpool_lst) - 2):
+                    netpool.append(netpool_lst[r].split()[0])
+
+                doc = xml.dom.minidom.Document()
+                topelem = doc.createElement("interface")
+                doc.appendChild(topelem)
+
+                chld_elem = doc.createElement("source")
+                chld_elem.setAttribute('network', netpool[-1])
+                topelem.appendChild(chld_elem)
+                if parm_dic.has_key("mac"):
+                    mac = parm_dic.get("mac")
+                    chld_elem = doc.createElement("mac")
+                    chld_elem.setAttribute('address', mac)
+                    topelem.appendChild(chld_elem)
+                if not parm_dic.has_key("driver"):
+                    model = re.findall("device_add ([^,\s]+)", command)[0]
+                else:
+                    model = parm_dic.get("driver")
+                if model == "virtio-net-pci":
+                    model = "virtio"
+                chld_elem = doc.createElement("model")
+                chld_elem.setAttribute('type', model)
+                topelem.appendChild(chld_elem)
+                if parm_dic.has_key("id"):
+                    id = parm_dic.get("id")
+                    chld_elem = doc.createElement("target")
+                    chld_elem.setAttribute('dev', id)
+                    topelem.appendChild(chld_elem)
+
+            tmp_xml = doc.toxml()
+            devfl = tempfile.mktemp(prefix='dev')
+            devfd = open(devfl, 'w')
+            devfd.write(tmp_xml)
+            devfd.close()
+            return devfl
+
+        def net_del(command):
+            """
+            Create the xml file for the device to be detached
+            """
+            xml_str = ""
+            id = re.findall("device_del ([^,\s]+)", command)[0]
+            for i in range(len(self.network_info)):
+                if id in str(self.network_info[i]):
+                    xml_str = str(self.network_info[i])
+            for i in self.drive_map:
+                if id in str(self.drive_map[i]):
+                    map_key = self.drive_map[i]["dev"]
+                    for i in range(len(self.disk_info)):
+                        if map_key in str(self.disk_info[i]):
+                            xml_str = str(self.disk_info[i])
+            devfl = tempfile.mktemp(prefix='dev')
+            devfd = open(devfl, 'w')
+            devfd.write(xml_str)
+            devfd.close()
+            return devfl
+
+        if "device_add ?" in command:
+            return "virtio-net-pci virtio-blk-pci e1000 rtl8139"
+
+        if "?" in command:
+            output = "\nhelp|? [cmd]\ndevice_add\ndevice_del\ndrive_add"\
+                                                "\n__com.redhat_drive_add"
+            return output
+
+        if "redhat_drive" in command:
+            drive_dic = dict(re.findall("(file|id)=([^,\s]+)", command))
+            self.drive_map[drive_dic["id"]] = drive_dic
+            return
+
+        if "netdev_add" in command:
+            id = re.findall("id=(.*?),", command)[0]
+            net_str = " peer=%s" % id
+            self.network_info[id] = net_str
+            return
+
+        if "device_add"  in command:
+            devfile = dev_add(command)
+            xml_handle = open(devfile)
+            xml_pars = xml.dom.minidom.parse(xml_handle)
+            self.session.cmd_output("attach-device %s %s" %
+                                    (self.vmname, devfile))
+            domxml = self.session.cmd_output("dumpxml %s \n" % self.vmname)
+            self._parse_dev(domxml)
+            return
+
+        if "device_del" in command:
+            devfile = net_del(command)
+            xml_handle = open(devfile)
+            xml_pars = xml.dom.minidom.parse(xml_handle)
+            self.session.cmd_output("detach-device %s %s" %
+                                    (self.vmname, devfile))
+            domxml = self.session.cmd_output("dumpxml %s \n" % self.vmname)
+            self._parse_dev(domxml)
+            return
+
+        if "balloon" in command:
+            new_mem = re.findall("balloon\s+(\d+)", command)[0]
+            new_mem = str(int(new_mem) * 1024)
+            output = self.session.cmd_output("setmem  %s %s" %
+                                                      (self.vmname, new_mem))
+            return
+
+        if "system_reset" in command:
+            self.session.cmd_output("destroy %s" % self.vmname)
+            self.session.cmd_output("start %s" % self.vmname)
+            return
+
+        data = self.session.cmd_output(" %s \n" % self.virsh_cmd.get(
+                                                            command, command))
+        return data
+
+
+    def is_responsive(self):
+        """
+        Return True if the monitor is responsive.
+        """
+        return True
+
+
+    def quit(self):
+        """
+        Send "quit" without waiting for output.
+        """
+        self.cmd("quit")
+
+
+    def screendump(self, filename, debug=True):
+        """
+        Request a screendump.
+
+        @param filename: Location for the screendump
+        @return: The command's output
+        """
+        if debug:
+            logging.debug("Requesting screendump %s" % filename)
+        self.cmd("screenshot %s" % filename)
+
+
+    def info(self, what):
+        """
+        Request info about something and return the output.
+        """
+        if "network" in what:
+            return self.network_info
+
+        if "pci" in what:
+            domxml = self.session.cmd_output("dumpxml %s \n" %
+                                                       self.vmname)
+            self._parse_dev(domxml)
+            return str(self.network_info) + str(self.drive_map)
+
+        if "balloon" in what:
+            self.session.cmd_output("\n")
+            netpool_lst = self.session.cmd_output("dominfo %s" %
+                                                            self.vmname)
+            return str(int(re.findall("Used memory:\s+(\d+)", netpool_lst)
+                                       [0]) / 1024)
+
+        return self.cmd("info %s" % what)
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 07/11] virt.virt_env_process: Add libvirt vm handling
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
                   ` (4 preceding siblings ...)
  2011-10-11 21:07 ` [PATCH 06/11] virt: Introducing libvirt monitor Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 08/11] client.tests: Introducing libvirt test Lucas Meneghel Rodrigues
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

With this patch, we make libvirt vm handling integrating
to pre/postprocessing code, making it possible the
execution of a libvirt test. The idea was to try
to abstract some concepts and intrude the least
possible in the pre/postprocessing code.

Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
 client/virt/virt_env_process.py |   51 +++++++++++++++++++++++++++++---------
 1 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/client/virt/virt_env_process.py b/client/virt/virt_env_process.py
index 51c7e8a..6235c4e 100644
--- a/client/virt/virt_env_process.py
+++ b/client/virt/virt_env_process.py
@@ -2,7 +2,7 @@ import os, time, commands, re, logging, glob, threading, shutil
 from autotest_lib.client.bin import utils
 from autotest_lib.client.common_lib import error
 import aexpect, virt_utils, kvm_monitor, ppm_utils, virt_test_setup
-import virt_vm, kvm_vm
+import virt_vm, kvm_vm, libvirt_vm
 try:
     import PIL.Image
 except ImportError:
@@ -51,13 +51,23 @@ def preprocess_vm(test, params, env, name):
     """
     logging.debug("Preprocessing VM '%s'", name)
     vm = env.get_vm(name)
+    vm_type = params.get('vm_type')
     if not vm:
         logging.debug("VM object for '%s' does not exist, creating it", name)
-        vm_type = params.get('vm_type')
         if vm_type == 'kvm':
             vm = kvm_vm.VM(name, params, test.bindir, env.get("address_cache"))
+        if vm_type == 'libvirt':
+            vm = libvirt_vm.VM(name, params, test.bindir, env.get("address_cache"))
         env.register_vm(name, vm)
 
+    remove_vm = False
+    if params.get("force_remove_vm") == "yes":
+        logging.debug("'force_remove_vm' specified; removing VM...")
+        remove_vm = True
+
+    if remove_vm and not libvirt_vm.virsh_remove_domain(name):
+        raise error.TestError("Could not remove VM")
+
     start_vm = False
 
     if params.get("restart_vm") == "yes":
@@ -68,18 +78,31 @@ def preprocess_vm(test, params, env, name):
                       "incoming migration mode")
         start_vm = True
     elif params.get("start_vm") == "yes":
-        if not vm.is_alive():
-            logging.debug("VM is not alive, starting it")
-            start_vm = True
-        if vm.needs_restart(name=name, params=params, basedir=test.bindir):
-            logging.debug("Current VM specs differ from requested one; "
-                          "restarting it")
-            start_vm = True
+        # need to deal with libvirt VM differently than qemu
+        if vm_type == 'libvirt':
+            if not libvirt_vm.virsh_is_alive(name):
+                logging.debug("VM is not alive; starting it...")
+                start_vm = True
+        else:
+            if not vm.is_alive():
+                logging.debug("VM is not alive, starting it")
+                start_vm = True
+            if vm.needs_restart(name=name, params=params, basedir=test.bindir):
+                logging.debug("Current VM specs differ from requested one; "
+                              "restarting it")
+                start_vm = True
 
     if start_vm:
-        # Start the VM (or restart it if it's already up)
-        vm.create(name, params, test.bindir,
-                  migration_mode=params.get("migration_mode"))
+        if vm_type == 'libvirt' and params.get("type") != "unattended_install":
+            libvirt_vm.virsh_start(name, vm)
+            # Wait for the domain to be created
+            virt_utils.wait_for(func=vm.is_alive, timeout=60,
+                                text=("waiting for domain %s to start" %
+                                      vm.name))
+        else:
+            # Start the VM (or restart it if it's already up)
+            vm.create(name, params, test.bindir,
+                      migration_mode=params.get("migration_mode"))
     else:
         # Don't start the VM, just update its params
         vm.params = params
@@ -277,6 +300,8 @@ def preprocess(test, params, env):
     if params.get("setup_hugepages") == "yes":
         h = virt_test_setup.HugePageConfig(params)
         h.setup()
+        if params.get("vm_type") == "libvirt":
+            libvirt_vm.libvirtd_restart()
 
     # Execute any pre_commands
     if params.get("pre_command"):
@@ -377,6 +402,8 @@ def postprocess(test, params, env):
     if params.get("setup_hugepages") == "yes":
         h = virt_test_setup.HugePageConfig(params)
         h.cleanup()
+        if params.get("vm_type") == "libvirt":
+            libvirt_vm.libvirtd_restart()
 
     # Execute any post_commands
     if params.get("post_command"):
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 08/11] client.tests: Introducing libvirt test
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
                   ` (5 preceding siblings ...)
  2011-10-11 21:07 ` [PATCH 07/11] virt.virt_env_process: Add libvirt vm handling Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 09/11] Virt: builtin HTTP server for unattended installs Lucas Meneghel Rodrigues
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

Introduce libvirt test. The small amount of actual code
on this test is made possible by code reuse, made possible
by the kvm refactor patchset + the previous patches on
this set.

The obvious difference is that some new parameters had
to be introduced to accomplish libvirt testing. A more
complete description of such parameters will be present
on our online documentation (wiki).

Signed-off-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
---
 client/tests/libvirt/README                |   11 +
 client/tests/libvirt/cdkeys.cfg.sample     |   18 +
 client/tests/libvirt/common.py             |    8 +
 client/tests/libvirt/control               |   64 +
 client/tests/libvirt/get_started.py        |   22 +
 client/tests/libvirt/libvirt.py            |    9 +
 client/tests/libvirt/tests.cfg.sample      |   73 +
 client/tests/libvirt/tests_base.cfg.sample | 2918 ++++++++++++++++++++++++++++
 client/tests/libvirt/virtio-win.cfg.sample |  235 +++
 9 files changed, 3358 insertions(+), 0 deletions(-)
 create mode 100644 client/tests/libvirt/README
 create mode 100644 client/tests/libvirt/cdkeys.cfg.sample
 create mode 100644 client/tests/libvirt/common.py
 create mode 100644 client/tests/libvirt/control
 create mode 100755 client/tests/libvirt/get_started.py
 create mode 100644 client/tests/libvirt/libvirt.py
 create mode 100644 client/tests/libvirt/tests.cfg.sample
 create mode 100644 client/tests/libvirt/tests_base.cfg.sample
 create mode 100644 client/tests/libvirt/virtio-win.cfg.sample

diff --git a/client/tests/libvirt/README b/client/tests/libvirt/README
new file mode 100644
index 0000000..7b19979
--- /dev/null
+++ b/client/tests/libvirt/README
@@ -0,0 +1,11 @@
+For the impatient:
+
+Execute the get_started.py script located on this directory,
+that will guide you through setting up the default libvirt test
+scenario:
+
+ * Guest install with Fedora 15
+ * Boot, reboot and shutdown test
+
+The script will help you to create all the directories, and
+even get the OS iso in case you don't have it yet.
diff --git a/client/tests/libvirt/cdkeys.cfg.sample b/client/tests/libvirt/cdkeys.cfg.sample
new file mode 100644
index 0000000..2d1d05d
--- /dev/null
+++ b/client/tests/libvirt/cdkeys.cfg.sample
@@ -0,0 +1,18 @@
+# Copy this file to cdkeys.cfg and edit it.
+#
+# Replace the 'CDKEY' strings with real cdkeys where necessary.
+# Feel free to add additional guests as required.
+
+RHEL.5.3.i386: cdkey = CDKEY
+RHEL.5.3.x86_64: cdkey = CDKEY
+Win2000: cdkey = CDKEY
+WinXP.32: cdkey = CDKEY
+WinXP.64: cdkey = CDKEY
+Win2003.32: cdkey = CDKEY
+Win2003.64: cdkey = CDKEY
+WinVista.32: cdkey = CDKEY
+WinVista.64: cdkey = CDKEY
+Win2008.32: cdkey = CDKEY
+Win2008.64: cdkey = CDKEY
+Win7.32: cdkey = CDKEY
+Win7.64: cdkey = CDKEY
diff --git a/client/tests/libvirt/common.py b/client/tests/libvirt/common.py
new file mode 100644
index 0000000..ce78b85
--- /dev/null
+++ b/client/tests/libvirt/common.py
@@ -0,0 +1,8 @@
+import os, sys
+dirname = os.path.dirname(sys.modules[__name__].__file__)
+client_dir = os.path.abspath(os.path.join(dirname, "..", ".."))
+sys.path.insert(0, client_dir)
+import setup_modules
+sys.path.pop(0)
+setup_modules.setup(base_path=client_dir,
+                    root_module_name="autotest_lib.client")
diff --git a/client/tests/libvirt/control b/client/tests/libvirt/control
new file mode 100644
index 0000000..c73d59b
--- /dev/null
+++ b/client/tests/libvirt/control
@@ -0,0 +1,64 @@
+AUTHOR = """
+Red Hat Inc. Quality Assurance
+uril@redhat.com (Uri Lublin)
+drusso@redhat.com (Dror Russo)
+mgoldish@redhat.com (Michael Goldish)
+dhuff@redhat.com (David Huff)
+aeromenk@redhat.com (Alexey Eromenko)
+mburns@redhat.com (Mike Burns)
+"""
+TIME = 'MEDIUM'
+NAME = 'LIBVIRT test'
+TEST_TYPE = 'client'
+TEST_CLASS = 'Virtualization'
+TEST_CATEGORY = 'Functional'
+
+DOC = """
+Executes the LIBVIRT test framework on a given host. This module is separated in
+minor functions, that execute different tests for doing Quality Assurance on
+LIBVIRT (both kernelspace and userspace) code.
+
+For online docs, please refer to http://www.linux-kvm.org/page/KVM-Autotest
+"""
+
+import sys, os, logging
+from autotest_lib.client.common_lib import cartesian_config
+from autotest_lib.client.virt import virt_utils
+
+# set English environment (command output might be localized, need to be safe)
+os.environ['LANG'] = 'en_US.UTF-8'
+
+str = """
+# This string will be parsed after build.cfg.  Make any desired changes to the
+# build configuration here.  For example:
+#release_tag = 84
+"""
+
+libvirt_test_dir = os.path.join(os.environ['AUTODIR'],'tests/libvirt')
+
+str = """
+# This string will be parsed after tests.cfg.  Make any desired changes to the
+# test configuration here.  For example:
+#display = sdl
+#install, setup: timeout_multiplier = 3
+"""
+
+parser = cartesian_config.Parser()
+parser.parse_file(os.path.join(libvirt_test_dir, "tests.cfg"))
+
+if args:
+    # We get test parameters from command line
+    for arg in args:
+        try:
+            (key, value) = re.findall("^(\w+)=(.*)", arg)[0]
+            if key == "only":
+                str += "only %s\n" % value
+            elif key == "no":
+                str += "no %s\n" % value
+            else:
+                str += "%s = %s\n" % (key, value)
+        except IndexError:
+            pass
+parser.parse_string(str)
+
+virt_utils.run_tests(parser, job)
diff --git a/client/tests/libvirt/get_started.py b/client/tests/libvirt/get_started.py
new file mode 100755
index 0000000..8ea88ce
--- /dev/null
+++ b/client/tests/libvirt/get_started.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+"""
+Program to help setup libvirt test environment
+
+@copyright: Red Hat 2011
+"""
+import os, sys
+import common
+from autotest_lib.client.virt import virt_utils
+
+test_name = "libvirt"
+test_dir = os.path.dirname(sys.modules[__name__].__file__)
+test_dir = os.path.abspath(test_dir)
+base_dir = "/tmp/libvirt_autotest_root"
+default_userspace_paths = ["/usr/bin/virt-install"]
+check_modules = None
+online_docs_url = None
+
+if __name__ == "__main__":
+    virt_utils.virt_test_assistant(test_name, test_dir, base_dir,
+                                   default_userspace_paths, check_modules,
+                                   online_docs_url)
\ No newline at end of file
diff --git a/client/tests/libvirt/libvirt.py b/client/tests/libvirt/libvirt.py
new file mode 100644
index 0000000..ac9f919
--- /dev/null
+++ b/client/tests/libvirt/libvirt.py
@@ -0,0 +1,9 @@
+from autotest_lib.client.virt import virt_test
+
+class libvirt(virt_test.virt_test):
+    """
+    Suite of libvirt virtualization functional tests.
+
+    @copyright: Red Hat 2011
+    """
+    pass
diff --git a/client/tests/libvirt/tests.cfg.sample b/client/tests/libvirt/tests.cfg.sample
new file mode 100644
index 0000000..a068587
--- /dev/null
+++ b/client/tests/libvirt/tests.cfg.sample
@@ -0,0 +1,73 @@
+# Copy this file to tests.cfg and edit it.
+#
+# This file contains the test set definitions. Define your test sets here.
+include tests_base.cfg
+include cdkeys.cfg
+include virtio-win.cfg
+
+# Modify/comment the following lines if you wish to modify the paths of the
+# image files, ISO files or qemu binaries.
+#
+# As for the defaults:
+# * qemu and qemu-img are expected to be found under /usr/bin/qemu-kvm and
+#   /usr/bin/qemu-img respectively.
+# * All image files are expected under /tmp/libvirt_autotest_root/images/
+# * All install iso files are expected under /tmp/libvirt_autotest_root/isos/
+# * The parameters cdrom_unattended, floppy, kernel and initrd are generated
+#   by LIBVIRT autotest, so remember to put them under a writable location
+#   (for example, the cdrom share can be read only)
+image_name(_.*)? ?<= /tmp/libvirt_autotest_root/images/
+cdrom(_.*)? ?<= /tmp/libvirt_autotest_root/
+floppy ?<= /tmp/libvirt_autotest_root/
+image_dir = /tmp/libvirt_autotest_root/
+Linux..unattended_install:
+    kernel ?<= /tmp/libvirt_autotest_root/
+    initrd ?<= /tmp/libvirt_autotest_root/
+
+variants:
+    # Runs virt-install, f15 64 bit guest OS, install, boot, shutdown
+    - @libvirt_f15_quick:
+        virt_install_binary = /usr/bin/virt-install
+        qemu_img_binary = /usr/bin/qemu-img
+        only raw
+        only virtio_net
+        only ide
+        only smp2
+        only no_pci_assignable
+        only smallpages
+        only Fedora.15.64
+        only unattended_install.cdrom, boot, reboot, shutdown
+
+    # Runs virt-install, RHEL 6.0 64 bit guest OS, install, boot, shutdown
+    - @libvirt_rhel60_quick:
+        virt_install_binary = /usr/bin/virt-install
+        qemu_img_binary = /usr/bin/qemu-img
+        only raw
+        only virtio_net
+        only virtio_blk
+        only smp2
+        only no_pci_assignable
+        only smallpages
+        only RHEL.6.0.x86_64
+        only unattended_install.cdrom, boot, reboot, shutdown
+
+    - @libvirt_windows:
+        virt_install_binary = /usr/bin/virt-install
+        qemu_img_binary = /usr/bin/qemu-img
+        use_virt_install = yes
+        image_format = raw
+        virt_install_debug = yes
+        hvm_or_pv = --hvm --accelerate
+        mem = 4196
+        install_virtio = no
+        only raw
+        only rtl8139
+        only ide
+        only smp2
+        only no_pci_assignable
+        only smallpages
+        only Windows.Win7.64
+        only unattended_install.cdrom, boot, reboot, shutdown
+
+# Choose your test list from the testsets defined
+only libvirt_f15_quick
diff --git a/client/tests/libvirt/tests_base.cfg.sample b/client/tests/libvirt/tests_base.cfg.sample
new file mode 100644
index 0000000..f2a4e35
--- /dev/null
+++ b/client/tests/libvirt/tests_base.cfg.sample
@@ -0,0 +1,2918 @@
+# Copy this file to tests_base.cfg and edit it.
+#
+# Define the objects we'll be using
+vms = vm1
+vm_type = libvirt
+images = image1
+cdroms = cd1
+nics = nic1
+monitors = 
+
+# Choose the main VM and monitor
+main_vm = vm1
+#main_monitor = humanmonitor1
+
+# Some preprocessor/postprocessor params
+start_vm = yes
+kill_vm = no
+kill_vm_gracefully = yes
+kill_unresponsive_vms = no
+
+# Screendump specific stuff
+convert_ppm_files_to_png_on_error = yes
+#keep_ppm_files = yes
+#keep_ppm_files_on_error = yes
+take_regular_screendumps = yes
+keep_screendumps_on_error = yes
+screendump_delay = 5
+screendump_quality = 30
+screendump_temp_dir = /dev/shm
+screendump_verbose = no
+
+# Some default VM params
+qemu_binary = qemu
+qemu_img_binary = qemu-img
+smp = 1
+mem = 1024
+image_size = 10G
+drive_index_image1 = 0
+drive_cache = none
+shell_port = 22
+display = vnc
+drive_index_cd1 = 1
+
+qxl = on
+qxl_dev_nr = 1
+spice = disable-ticketing
+
+# Monitor params
+monitor_type = human
+
+# Default scheduler params
+used_cpus = 1
+used_mem = 512
+
+# Port redirections
+redirs = remote_shell
+guest_port_remote_shell = 22
+
+# NIC parameters
+#nic_mode = user
+nic_mode = tap
+
+# DO NOT set to 'private when using libvirt client
+bridge = none
+
+# You can set bridge to
+# be a specific bridge
+# name, such as 'virbr0'
+#bridge = virbr0
+# If you need more ports to be available for comm between host and guest,
+# please add them here
+priv_bridge_ports = 53 67
+run_tcpdump = yes
+
+# Misc
+profilers = kvm_stat
+login_timeout = 360
+image_raw_device = no
+
+# NFS directory of guests' images
+images_good = 0.0.0.0:/autotest/images_good
+
+# libvirt (virt-install optional arguments)
+use_connect_uri = yes
+use_autostart = no
+use_check_cpu = yes
+use_debug = yes
+use_no_reboot = no
+use_os_variant = no
+use_os_type = yes
+# libvirt network to use examples network=default or bridge=br0
+virsh_network = network=default
+# wait in minutes for virt-install to finish (bz still open)
+use_virt_install_wait = no
+virt_install_wait_time = 300  
+
+# Tests
+variants:
+    - install:
+        type = steps
+        fail_if_stuck_for = 300
+        stuck_detection_history = 2
+        keep_screendump_history = yes
+        force_create_image = yes
+        kill_vm = yes
+        kill_vm_timeout = 60
+        kill_vm_timeout_on_error = 0
+
+    - setup: install
+        type = steps
+        fail_if_stuck_for = 300
+        stuck_detection_history = 2
+        kill_vm_on_error = yes
+        keep_screendump_history = yes
+
+    - image_copy:
+        type = image_copy
+        vms = ''
+        parallel = no
+        profilers =
+
+    - unattended_install:
+        type = unattended_install
+        start_vm = no
+        kill_vm = yes
+        kill_vm_gracefully = yes
+        kill_vm_on_error = yes
+        shutdown_cleanly = yes
+        shutdown_cleanly_timeout = 120
+        force_create_image = yes
+        guest_port_unattended_install = 12323
+        kernel = vmlinuz
+        initrd = initrd.img
+        image_name_pxe = images/pxeboot
+        # force_remove_vm must be yes when using virt-install
+        force_remove_vm = yes
+        # uncomment the following line to test the migration in parallel
+        # migrate_background = yes
+
+        variants:
+            # Install guest from cdrom (virt-install --cdrom)
+            - cdrom:
+                medium = cdrom
+                redirs += " unattended_install"
+            # Install guest from http/ftp url (virt-install --location)
+            - url:
+                only Linux
+                medium = url
+                url = REPLACE_THIS_WITH_TREE_URL
+            # Install guest from nfs nfs_server:nfs_dir
+            - nfs:
+                only Linux
+                medium = nfs
+                nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+            # Install guest with a remote kickstart
+            - remote_ks:
+                only Linux
+                medium = url
+                extra_params = " ks=REPLACE_THIS_WITH_URL_OF_KS"
+                url = REPLACE_THIS_WITH_TREE_URL
+            # Install guest using pxe/tftp  (virt-install --pxe)
+            - pxe:
+                only Linux
+                medium = pxe
+            # Install guest using kernel/initrd pair from directory
+            - kernel_initrd:
+                only Linux
+                medium = kernel_initrd
+
+    - qemu_img:
+        type = qemu_img
+        vms = ''
+        profilers = ''
+        take_regular_screendumps = no
+        variants:
+            - check:
+                subcommand = check
+                image_name_dd = dd_created_image
+                force_create_image_dd = no
+                remove_image_dd = yes
+                create_image_cmd = "dd if=/dev/zero of=%s bs=1G count=1"
+                # Test the convertion from 'dd_image_name' to specified format
+                supported_image_formats = qcow2 raw
+            - create:
+                subcommand = create
+                images += " large"
+                force_create_image_large = yes
+                image_size_large = 1G
+                image_name_large = create_large_image
+                remove_image_large = yes
+            - convert:
+                subcommand = convert
+                variants:
+                    - to_qcow2:
+                        dest_image_format = qcow2
+                        compressed = no
+                        encrypted = no
+                    - to_raw:
+                        dest_image_format = raw
+            - snapshot:
+                subcommand = snapshot
+            - info:
+                subcommand = info
+            - rebase:
+                subcommand = rebase
+                rebase_mode = unsafe
+                image_name_snapshot1 = sn1
+                image_name_snapshot2 = sn2
+            # Commit is the only subtest that does need an installed guest
+            - commit:  install setup image_copy unattended_install.cdrom
+                subcommand = commit
+
+    - pxe:
+        type = pxe
+        images = pxe
+        image_name_pxe = pxe-test
+        image_size_pxe = 1G
+        force_create_image_pxe = yes
+        remove_image_pxe = yes
+        extra_params += ' -boot n'
+        kill_vm_on_error = yes
+        network = bridge
+        restart_vm = yes
+        pxe_timeout = 60
+
+    - module_probe:
+        type = module_probe
+        # You can specify your own module list, though it is not needed usually.
+        # mod_list = kvm
+        load_count = 100
+        vms = ''
+        profilers = ''
+        take_regular_screendumps = no
+
+# Tests that do need installed guests to run
+    - boot: install setup image_copy unattended_install.cdrom
+        type = boot
+        restart_vm = yes
+        kill_vm_on_error = yes
+        login_timeout = 240
+
+    - reboot: install setup image_copy unattended_install.cdrom
+        type = boot
+        reboot_method = shell
+        kill_vm_on_error = yes
+        login_timeout = 240
+
+    - migrate: install setup image_copy unattended_install.cdrom
+        type = migration
+        migration_test_command = help
+        migration_bg_command = "cd /tmp; nohup tcpdump -q -t ip host localhost"
+        migration_bg_check_command = pgrep tcpdump
+        migration_bg_kill_command = pkill tcpdump
+        kill_vm_on_error = yes
+        iterations = 2
+        used_mem = 1024
+        mig_timeout = 3600
+        # you can uncomment the following line to enable the state
+        # check
+        # vmstate_check = yes
+        variants:
+            - tcp:
+                migration_protocol = "tcp"
+            - unix:
+                migration_protocol = "unix"
+            - exec:
+                migration_protocol = "exec"
+            - mig_cancel:
+                migration_protocol = "tcp"
+                mig_cancel = yes
+        variants:
+            - @default:
+            - with_set_speed:
+                mig_speed = 1G
+                pre_migrate = "mig_set_speed"
+            - with_reboot:
+                iterations = 1
+                type = migration_with_reboot
+            - with_file_transfer:
+                iterations = 1
+                type = migration_with_file_transfer
+            - with_autotest:
+                only Linux
+                type = autotest
+                migrate_background = yes
+                test_timeout = 1800
+                variants:
+                    - dbench:
+                        test_control_file = dbench.control
+                    - stress:
+                        test_control_file = stress.control
+                    - monotonic_time:
+                        test_control_file = monotonic_time.control
+
+    - migrate_multi_host: install setup image_copy unattended_install.cdrom
+        type = migration_multi_host
+        migration_test_command = help
+        migration_bg_command = "cd /tmp; nohup tcpdump -q -t ip host localhost"
+        migration_bg_check_command = pgrep tcpdump
+        migration_bg_kill_command = pkill tcpdump
+        kill_vm_on_error = yes
+        iterations = 2
+        used_mem = 1024
+        mig_timeout = 3600
+        comm_port = 13234
+        regain_ip_cmd = dhclient
+
+    - boot_savevm: install setup image_copy unattended_install.cdrom
+        type = boot_savevm
+        savevm_delay = 0.3
+        savevm_login_delay = 120
+        savevm_timeout = 2000
+        kill_vm_on_error = yes
+        kill_vm_gracefully = yes
+        kill_vm = yes
+
+    - autotest: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = autotest
+        test_timeout = 1800
+        variants:
+            - sleeptest:
+                test_timeout = 120
+                test_control_file = sleeptest.control
+            - dbench:
+                test_control_file = dbench.control
+            - bonnie:
+                test_control_file = bonnie.control
+            - ebizzy:
+                test_control_file = ebizzy.control
+            - stress:
+                test_control_file = stress.control
+            - disktest:
+                test_control_file = disktest.control
+            - ctcs:
+                # If you think this is too lengthy, please change the cerberus
+                # control file and set this timeout appropriately.
+                test_timeout = 3900
+                test_control_file = ctcs.control
+            - npb:
+                test_control_file = npb.control
+            - hackbench:
+                test_control_file = hackbench.control
+            - cpu_hotplug:
+                test_control_file = cpu_hotplug.control
+            - monotonic_time:
+                test_control_file = monotonic_time.control
+            - tsc:
+                test_control_file = tsc.control
+            - scrashme:
+                test_control_file = scrashme.control
+            - hwclock:
+                test_control_file = hwclock.control
+            - rtc:
+                test_control_file = rtc.control
+            - iozone:
+                test_control_file = iozone.control
+            - flail:
+                test_control_file = flail.control
+            - systemtap:
+                test_control_file = systemtap.control
+
+    - stop_continue: install setup image_copy unattended_install.cdrom
+        type = stop_continue
+        kill_vm_on_error = yes
+
+    - linux_s3: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = linux_s3
+
+    - timedrift: install setup image_copy unattended_install.cdrom
+        variants:
+            - ntp:
+                variants:
+                    - with_load:
+                        type = timedrift
+                        # Pin the VM and host load to CPU #0
+                        cpu_mask = 0x1
+                        # Set the load and rest durations
+                        load_duration = 20
+                        rest_duration = 20
+                        # Fail if the drift after load is higher than 50%
+                        drift_threshold = 50
+                        # Fail if the drift after the rest period is higher than 10%
+                        drift_threshold_after_rest = 10
+                        # For now, make sure this test is executed alone
+                        used_cpus = 100
+                    - with_migration:
+                        type = timedrift_with_migration
+                        migration_iterations = 3
+                        drift_threshold = 10
+                        drift_threshold_single = 3
+                    - with_reboot:
+                        type = timedrift_with_reboot
+                        reboot_iterations = 1
+                        drift_threshold = 10
+                        drift_threshold_single = 3
+                    - with_stop:
+                        type = timedrift_with_stop
+                        stop_interations = 1
+                        drift_threshold = 10
+                        drift_threshold_single = 3
+            - date:
+                variants:
+                    - with_load:
+                        type = timedrift
+                        # Pin the VM and host load to CPU #0
+                        cpu_mask = 0x1
+                        # Set the load and rest durations
+                        load_duration = 20
+                        rest_duration = 20
+                        # Fail if the drift after load is higher than 50%
+                        drift_threshold = 50
+                        # Fail if the drift after the rest period is higher than 10%
+                        drift_threshold_after_rest = 10
+                        # For now, make sure this test is executed alone
+                        used_cpus = 100
+                    - with_migration:
+                        type = timedrift_with_migration
+                        migration_iterations = 3
+                        drift_threshold = 10
+                        drift_threshold_single = 3
+                    - with_reboot:
+                        type = timedrift_with_reboot
+                        reboot_iterations = 1
+                        drift_threshold = 10
+                        drift_threshold_single = 3
+                    - with_stop:
+                        type = timedrift_with_stop
+                        stop_interations = 1
+                        drift_threshold = 10
+                        drift_threshold_single = 3
+
+    - balloon_check: install setup image_copy unattended_install.cdrom
+        type = balloon_check
+        extra_params += " -balloon virtio"
+        iterations = 5
+
+    - watchdog: install setup image_copy unattended_install.cdrom
+        type = watchdog
+        extra_params += " -watchdog i6300esb -watchdog-action reset"
+        relogin_timeout = 240
+
+    - smbios_table: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = smbios_table
+        start_vm = no
+
+    - stress_boot: install setup image_copy unattended_install.cdrom
+        type = stress_boot
+        max_vms = 5    
+        alive_test_cmd = uname -a
+        login_timeout = 240
+        kill_vm = yes
+        kill_vm_vm1 = no
+        kill_vm_gracefully = no
+        extra_params += " -snapshot"
+        used_cpus = 5
+        used_mem = 2560
+
+    - guest_test: install setup image_copy unattended_install.cdrom
+        only Windows
+        type = guest_test
+        login_timeout = 360
+        test_timeout = 600
+        script_params =
+        reboot = yes
+        variants:
+            - autoit:
+                interpreter = "cmd /c D:\AutoIt3.exe"
+                variants:
+                    - notepad:
+                        guest_script = autoit/notepad1.au3
+                        dst_rsc_path = "C:\script.au3"
+                    - stub:
+                        download = yes
+                        download_cmd = "git clone"
+                        rsc_server = "git://the.resource.server/autoit"
+                        dst_rsc_dir = "C:\"
+                        dst_rsc_path = "C:\autoit\stub\stub.au3"
+            - powershell:
+                interpreter = "cmd /c powershell.exe -File"
+                variants:
+                    - stub:
+                        download = yes
+                        download_cmd = "git clone"
+                        rsc_server = "git://the.resource.server/powershell"
+                        dst_rsc_dir = "C:\"
+                        dst_rsc_path = "C:\powershell\stub\stub.ps1"
+
+    - iozone_windows: install setup image_copy unattended_install.cdrom
+        only Windows
+        type = iozone_windows
+        iozone_cmd = "D:\IOzone\iozone.exe -a"
+        iozone_timeout = 3600
+
+    - whql: install setup image_copy unattended_install.cdrom
+        only Windows
+        nic_mode = tap
+        # Replace this with the address of an installed DTM server
+        server_address = 10.20.30.40
+        # The server should run rss.exe like a regular Windows VM, preferably
+        # with administrator privileges (or at least with permission to write
+        # to the DTM studio directory)
+        server_shell_port = 10022
+        server_file_transfer_port = 10023
+        server_studio_path = %programfiles%\Microsoft Driver Test Manager\Studio
+        dsso_test_binary = deps/whql_submission_15.exe
+        dsso_delete_machine_binary = deps/whql_delete_machine_15.exe
+        wtt_services = wttsvc
+        variants:
+            - support_vm_install:
+                # The support VM is identical to the tested VM in every way
+                # except for the image name which ends with '-supportvm'.
+                type = unattended_install
+                extra_params += " -boot d"
+                force_create_image = yes
+                kill_vm = yes
+                nic_mode = user
+                redirs += " unattended_install"
+                guest_port_unattended_install = 12323
+                medium = cdrom
+                kernel =
+                initrd = 
+            - client_install:    support_vm_install
+                type = whql_client_install
+                # The username and password are required for accessing the DTM client
+                # installer binary shared by the server
+                server_username = administrator
+                server_password = 1q2w3eP
+                # This path refers to a shared directory on the server
+                # (the final cmd will be something like \\servername\DTMInstall\...)
+                install_cmd = \DTMInstall\Client\Setup.exe /passive
+                install_timeout = 3600
+                # The test will setup auto logon on the client machine using the
+                # following username and password:
+                client_username = DTMLLUAdminUser
+                client_password = Testpassword,1
+                # (These are created by the DTM client installer and should probably not
+                # be changed.)
+                variants:
+                    - @original:
+                    - support_vm:
+            - submission:    client_install support_vm_install
+                type = whql_submission
+                extra_params += " -snapshot"
+                restart_vm = yes
+                cdroms =
+                test_timeout = 3600
+                device_data = cat0 cat1 cat2 cat3 prog desc virt filter logoarch logoos whqlos whqlqual
+                descriptors = desc1 desc2 desc3
+                # DeviceData names
+                dd_name_cat0     = Category
+                dd_name_cat1     = Category
+                dd_name_cat2     = Category
+                dd_name_cat3     = Category
+                dd_name_logoarch = LogoProcessorArchitecture
+                dd_name_logoos   = LogoOperatingSystem
+                dd_name_whqlos   = WhqlOs
+                dd_name_whqlqual = WhqlQualification
+                dd_name_prog     = LogoProgramId
+                dd_name_desc     = LogoProgramDescription
+                dd_name_filter   = WDKFilterAttribute
+                dd_name_virt     = ParaVirtualizationDriver
+                # Common DeviceData data
+                dd_data_filter   = FilterIfNoInf
+                dd_data_virt     = True
+                # Exclude jobs that have '(Manual)' in their names
+                job_filter = ^((?!\(Manual\)).)*$
+                variants:
+                    - unclassified:
+                        dd_data_cat0 = Device Fundamentals
+                        dd_data_cat1 = System Fundamentals\Dynamic Partitioning
+                        dd_data_prog = Unclassified
+                        dd_data_desc = Unclassified
+                        dd_data_whqlqual = Unclassified Signature
+                        variants:
+                            - tablet:
+                                submission_name = tablet
+                                extra_params += " -usbdevice tablet"
+                                test_device = HID-compliant mouse
+                                test_timeout = 36000
+                    - device:
+                        variants:
+                            - keyboard:
+                                submission_name = keyboard
+                                # test_device is a regular expression that should match a device's
+                                # name as it appears in device manager.  The first device that matches
+                                # is used.
+                                test_device = keyboard
+                                # Set timeout to 10 hours
+                                test_timeout = 36000
+                                dd_data_cat0 = Input\Keyboard
+                                dd_data_cat1 = Device Fundamentals
+                                dd_data_cat2 = System Fundamentals\Dynamic Partitioning
+                                dd_data_prog = InputKbd
+                                dd_data_desc = Input > Keyboard
+                            - net:
+                                submission_name = net
+                                # Add a support machine and extra NICs
+                                vms += " supportvm"
+                                nics += " nic2 nic3"
+                                test_device = RTL8139.*NIC$
+                                test_timeout = 86400
+                                dd_data_cat0 = Network\LAN (Ethernet)
+                                dd_data_cat1 = Device Fundamentals
+                                dd_data_cat2 = System Fundamentals\Dynamic Partitioning
+                                dd_data_prog = NetLan
+                                dd_data_desc = Network > LAN (Ethernet)
+                                # Machine dimensions
+                                dimensions = testrole
+                                dim_name_testrole = NetDevice\TestRole
+                                dim_value_testrole_vm1 = NdistestLanClient
+                                dim_value_testrole_supportvm = NdistestLanServer
+                                # Device selection for the NDISTest client machine
+                                device_params_vm1 = testdev clientmsgdev clientsupportdev
+                                dp_name_testdev = NdistestLanClientTestDevice
+                                dp_regex_testdev = RTL8139.*NIC$
+                                dp_name_clientmsgdev = NdistestLanClientMessageDevice
+                                dp_regex_clientmsgdev = RTL8139.*NIC #2$
+                                dp_name_clientsupportdev = NdistestLanClientSupportDevice0
+                                dp_regex_clientsupportdev = RTL8139.*NIC #3$
+                                # Device selection for the NDISTest server machine
+                                device_params_supportvm = servermsgdev serversupportdev
+                                dp_name_servermsgdev = NdistestLanServerMessageDevice
+                                dp_regex_servermsgdev = RTL8139.*NIC$
+                                dp_name_serversupportdev = NdistestLanServerSupportDevice0
+                                dp_regex_serversupportdev = RTL8139.*NIC #2$
+                            - hdd:
+                                submission_name = hdd
+                                # Run the tests on a non-system drive
+                                # (match device names that contain 'QEMU HARDDISK' and do not contain '[C]')
+                                test_device = ^(?=.*?\bQEMU HARDDISK\b)((?!\[C\]).)*$
+                                device_data += " ex0 ex1 ex2 ex3"
+                                dd_data_cat0 = Storage\Device Class\Disk\Disk
+                                dd_data_cat1 = Storage\Device Class\Disk\Fixed
+                                dd_data_cat2 = Storage\Device Class\Disk\Bus\ATA
+                                dd_data_cat3 = Device Fundamentals
+                                dd_data_prog = StorHDD
+                                dd_data_desc = Storage > Hard Disk Drive (HDD)
+                                dd_name_ex0 = Storage_bus_type
+                                dd_data_ex0 = ATA/ATAPI
+                                dd_name_ex1 = Hybrid_HDD_Support
+                                dd_data_ex1 = 0
+                                dd_name_ex2 = Non_Rotating_Media
+                                dd_data_ex2 = 0
+                                dd_name_ex3 = Secure_Storage
+                                dd_data_ex3 = 0
+                                # Add a 2nd disk which will become D:
+                                images += " tmp"
+                                image_name_tmp = tmp
+                                image_size_tmp = 4G
+                                force_create_image_tmp = yes
+                                # Run diskpart to partition the 2nd disk
+                                whql_pre_command = "echo select disk=1 > dp.txt && "
+                                whql_pre_command += "echo create partition primary >> dp.txt && "
+                                whql_pre_command += "echo assign letter=d >> dp.txt && "
+                                whql_pre_command += "diskpart /s dp.txt & "
+                                whql_pre_command += "format d: /fs:ntfs /q /y"
+                                variants:
+                                    - full:
+                                        # Yes, 100 hours, this is not a mistake
+                                        test_timeout = 360000
+                                    - syscache_test:
+                                        job_filter = syscache test
+                                        test_timeout = 7200
+
+    - guest_s4: install setup image_copy unattended_install.cdrom
+        type = guest_s4
+        check_s4_support_cmd = grep -q disk /sys/power/state
+        test_s4_cmd = "cd /tmp; nohup tcpdump -q -t ip host localhost"
+        check_s4_cmd = pgrep tcpdump
+        set_s4_cmd = echo disk > /sys/power/state
+        kill_test_s4_cmd = pkill tcpdump
+        services_up_timeout = 30
+        relogin_timeout = 240
+
+    - nic_hotplug: install setup image_copy unattended_install.cdrom
+        pci_type = nic
+        reference_cmd = lspci
+        find_pci_cmd = 'lspci | tail -n1'
+        pci_test_cmd = 'nslookup www.redhat.com'
+        wait_secs_for_hook_up = 3
+        variants:
+            - nic_8139:
+                pci_model = rtl8139
+                match_string = "8139"
+            - nic_virtio:
+                pci_model = virtio
+                match_string = "Virtio network device"
+            - nic_e1000:
+                pci_model = e1000
+                match_string = "Gigabit Ethernet Controller"
+        variants:
+            - default:
+                type = pci_hotplug
+            - additional:
+                type = nic_hotplug
+
+
+    - block_hotplug: install setup image_copy unattended_install.cdrom
+        type = pci_hotplug
+        pci_type = block
+        reference_cmd = lspci
+        find_pci_cmd = 'lspci | tail -n1'
+        images += " stg"
+        boot_drive_stg = no
+        image_name_stg = storage
+        image_size_stg = 1G
+        remove_image_stg = yes
+        force_create_image_stg = yes
+        pci_test_cmd = "yes | mke2fs `fdisk -l 2>&1 | awk '/\/dev\/[sv]d[a-z] doesn/ {print $2}'`"
+        wait_secs_for_hook_up = 3
+        kill_vm_on_error = yes
+        variants:
+            - block_virtio:
+                pci_model = virtio
+                match_string = "Virtio block device"
+            - block_scsi:
+                pci_model = scsi
+                match_string = "LSI Logic"
+        variants:
+            - fmt_qcow2:
+                image_format_stg = qcow2
+            - fmt_raw:
+                image_format_stg = raw
+
+    - enospc: install setup image_copy unattended_install.cdrom
+        type = enospc
+        start_vm = no
+        images += " stg"
+        drive_werror = stop
+        drive_cache = none
+        image_name_stg = enospc
+        image_format_stg = qcow2
+        image_boot_stg = no
+        image_snapshot_stg = no
+        check_image_stg = no
+        vgtest_name = vg_kvm_test_enospc
+        lvtest_name = lv_kvm_test_enospc
+        background_cmd = "nohup dd if=/dev/zero of=%s bs=1024 &"
+        kill_vm = yes
+
+    - qmp_basic: install setup image_copy unattended_install.cdrom
+        type = qmp_basic
+
+    - qmp_basic_rhel6: install setup image_copy unattended_install.cdrom
+        type = qmp_basic_rhel6
+
+    - vlan: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = vlan
+        # subnet should not be used by host
+        subnet = "192.168"
+        vlan_num = 5
+        file_size = 10
+        maximal = 4094
+        listen_cmd = "nc -l %s > %s"
+        send_cmd = "nc %s %s < %s"
+        nic_mode = tap
+        vms += " vm2"
+        image_snapshot = yes
+        kill_vm_vm2 = yes
+        kill_vm_gracefully_vm2 = no
+
+    - ping: install setup image_copy unattended_install.cdrom
+        type = ping
+        counts = 100
+        flood_minutes = 10
+        nics += ' nic2'
+
+    - jumbo: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = jumbo
+
+    - file_transfer: install setup image_copy unattended_install.cdrom
+        type = file_transfer
+        filesize = 4000
+        transfer_timeout = 1000
+        variants:
+            - remote:
+                transfer_type = remote
+
+    - nicdriver_unload: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = nicdriver_unload
+        nic_mode = tap
+        filesize = 100
+        transfer_timeout = 100
+        transfer_type = remote
+        sessions_num = 10
+
+    - nic_promisc: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = nic_promisc
+        filesize = 400
+        transfer_timeout = 100
+        transfer_type = remote
+
+    - multicast: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = multicast
+        nic_mode = tap
+        mcast = 225.0.0.1
+        mgroup_count = 20
+        flood_minutes = 1
+
+    - mac_change: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = mac_change
+        kill_vm = yes
+
+    - netperf: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = netperf
+        nics += ' nic2 nic3 nic4'
+        nic_mode = tap
+        netperf_files = netperf-2.4.5.tar.bz2 wait_before_data.patch
+        packet_size = 1500
+        setup_cmd = "cd %s && tar xvfj netperf-2.4.5.tar.bz2 && cd netperf-2.4.5 && patch -p0 < ../wait_before_data.patch && ./configure && make"
+        netserver_cmd =  %s/netperf-2.4.5/src/netserver
+        variants:
+            - stream:
+                netperf_cmd = %s/netperf-2.4.5/src/netperf -t %s -H %s -l 60 -- -m %s
+                protocols = "TCP_STREAM TCP_MAERTS TCP_SENDFILE UDP_STREAM"
+            - rr:
+                netperf_cmd = %s/netperf-2.4.5/src/netperf -t %s -H %s -l 60 -- -r %s
+                protocols = "TCP_RR TCP_CRR UDP_RR"
+
+    - ethtool: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = ethtool
+        filesize = 512
+        nic_mode = tap
+
+    - nic_bonding: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = nic_bonding
+        nics += ' nic2 nic3 nic4'
+        image_snapshot = yes
+        serial_login = yes
+        test_timeout = 1000
+        filesize = 4000
+        transfer_timeout = 1000
+        transfer_type = remote
+        kill_vm = yes
+        # you can specify the parameters of bonding module here
+        # bonding_params = "mode=active-backup"
+
+    - set_link: install setup image_copy unattended_install.cdrom
+        type = set_link
+        test_timeout = 1000
+        filesize = 4000
+        transfer_timeout = 1000
+        transfer_type = remote
+        kill_vm =yes
+
+    - physical_resources_check: install setup image_copy unattended_install.cdrom
+        type = physical_resources_check
+        catch_uuid_cmd = dmidecode | awk -F: '/UUID/ {print $2}'
+
+    - ksm_overcommit: install setup image_copy unattended_install.cdrom
+        only Linux
+        # Don't preprocess any vms as we need to change its params
+        vms = ''
+        image_snapshot = yes
+        kill_vm_gracefully = no
+        type = ksm_overcommit
+        # Make host use swap (a value of 'no' will turn off host swap)
+        ksm_swap = yes
+        no hugepages
+        # Overcommit of host memmory
+        ksm_overcommit_ratio = 3
+        # Max paralel runs machine
+        ksm_parallel_ratio = 4
+        # Host memory reserve (default - best fit for used mem)
+        # ksm_host_reserve = 512
+        # ksm_guest_reserve = 1024
+        variants:
+            - ksm_serial:
+                ksm_mode = "serial"
+            - ksm_parallel:
+                ksm_mode = "parallel"
+
+    - iofuzz: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = iofuzz
+
+    - virtio_console: install setup image_copy unattended_install.cdrom
+        only Linux
+        vms = ''
+        type = virtio_console
+        # Default number of consoles
+        virtio_console_no_serialports = 0
+        virtio_console_no_consoles = 0
+
+        # smoke params - $console_type:data_string
+        # FIXME: test_smoke doesn't work with console yet (virtio_console bug)
+        # "serialport;console:Custom data"
+        smoke_test = yes
+        virtio_console_smoke = "serialport"
+        # loopback params - '$source_console_type@buffer_length:$destination_console_type1@buffer_length:...:$loopback_buffer_length;...'
+        loopback_test = yes
+        virtio_console_loopback = "serialport:serialport;serialport@1024:serialport@32:console@1024:console@8:16"
+        # perf params - $console_type@buffer_length:$test_duration
+        # FIXME: test_perf doesn't work with console yet (virtio_console bug)
+        # virtio_console_perf = "serialport;serialport@1000000:120;console@1024:60"
+        perf_test = yes
+        virtio_console_perf = "serialport;serialport@1000000:120"
+        # Enable destructive tests: "test_name  = yes"
+        # Disable test: change yes or delete key.
+        rmmod_test = yes
+        max_ports_test = yes
+        shutdown_test = yes
+
+        # Offline migration params - '$console_type:$no_migrations:$send-:$recv-$loopback-buffer_length'
+        migrate_offline_test = yes
+        virtio_console_migration_offline = "serialport:1:2048:2048:2048;serialport:5:4096:4096:4096"
+
+        # Online migration params - '$console_type:$no_migrations:$send-:$recv-$loopback-buffer_length'
+        migrate_online_test = yes
+        virtio_console_migration_online = "serialport:1:2048:2048:2048;serialport:5:4096:4096:4096"
+
+        hotplug_test = yes
+        hotplug_serial_test = yes
+        hotplug_console_test = no
+
+    # This unit test module is for older branches of KVM that use the
+    # kvmctl test harness (such as the code shipped with RHEL 5.x)
+    - unit_test_kvmctl:
+        type = unit_test
+        vms = ''
+        profilers = ''
+        variants:
+            - access:
+                case = access
+            - apic:
+                case = apic
+            - emulator:
+                case = emulator
+            - hypercall:
+                case = hypercall
+            - msr:
+                case = msr
+            - port80:
+                case = port80
+            - realmode:
+                case = realmode
+            - sieve:
+                case = sieve
+            - smptest:
+                case = smptest
+            - tsc:
+                case = tsc
+            - stringio:
+                case = stringio
+            - vmexit:
+                case = vmexit
+
+    - fillup_disk: install setup image_copy unattended_install.cdrom
+        only Linux
+        only qcow2
+        type = fillup_disk
+        fillup_timeout = 120
+        fillup_size = 200
+        fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1 oflag=direct"
+        kill_vm = yes
+
+    - lvm: install setup image_copy unattended_install.cdrom
+        only Linux
+        images += ' stg1 stg2'
+        image_name_stg1 = storage_4k
+        image_cluster_size_stg1 = 4096
+        image_size_stg1 = 1G
+        image_format_stg1 = qcow2
+        image_name_stg2 = storage_64k
+        image_cluster_size_stg2 = 65536
+        image_size_stg2 = 1G
+        image_format_stg2 = qcow2
+        guest_testdir = /mnt
+        disks = "/dev/sdb /dev/sdc"
+        kill_vm = no
+        post_command_noncritical = no
+        variants:
+            lvm_create:
+                type = lvm
+                force_create_image_stg1 = yes
+                force_create_image_stg2 = yes
+                clean = no
+            lvm_fill: lvm_create
+                type = fillup_disk
+                force_create_image_stg1 = no
+                force_create_image_stg2 = no
+                guest_testdir = /mnt/kvm_test_lvm
+                fillup_timeout = 120
+                fillup_size = 20
+                fillup_cmd = "dd if=/dev/zero of=%s/fillup.%d bs=%dM count=1 oflag=direct"
+            lvm_ioquit: lvm_create
+                type = ioquit
+                force_create_image_stg1 = no
+                force_create_image_stg2 = no
+                kill_vm = yes
+                background_cmd = "for i in 1 2 3 4; do (dd if=/dev/urandom of=/mnt/kvm_test_lvm/file bs=102400 count=10000000 &); done"
+                check_cmd = pgrep dd
+                clean = yes
+                remove_image_stg1 = yes
+                remove_image_stg2 = yes
+
+    - ioquit: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = ioquit
+        background_cmd = "for i in 1 2 3 4; do (dd if=/dev/urandom of=/tmp/file bs=102400 count=10000000 &); done"
+        check_cmd = ps -a |grep dd
+        login_timeout = 360
+
+    - multi_disk: install setup image_copy unattended_install.cdrom
+        type = multi_disk
+        force_create_image = yes
+        force_create_image_image1 = no
+        remove_image = yes
+        remove_image_image1 = no
+        cmd_timeout = 1000
+        block_list = C: D: vda vda1 vda2 hda hda1 hda2 sda sda1 sda2
+        variants:
+            - signal_repeat:
+                images += " stg"
+                image_format_stg = qcow2
+                image_name_stg = storage
+                image_size_stg = 1G
+                n_repeat = 10
+            - max_disk:
+                only virtio_blk
+                images += " stg stg2 stg3 stg4 stg5 stg6 stg7 stg8 stg9 stg10 stg11 stg12 stg13 stg14 stg15 stg16 stg17 stg18 stg19 stg20 stg21 stg22 stg23"
+                image_name_stg = storage
+                image_name_stg2 = storage2
+                image_name_stg3 = storage3
+                image_name_stg4 = storage4
+                image_name_stg5 = storage5
+                image_name_stg6 = storage6
+                image_name_stg7 = storage7
+                image_name_stg8 = storage8
+                image_name_stg9 = storage9
+                image_name_stg10 = storage10
+                image_name_stg11 = storage11
+                image_name_stg12 = storage12
+                image_name_stg13 = storage13
+                image_name_stg14 = storage14
+                image_name_stg15 = storage15
+                image_name_stg16 = storage16
+                image_name_stg17 = storage17
+                image_name_stg18 = storage18
+                image_name_stg19 = storage19
+                image_name_stg20 = storage20
+                image_name_stg21 = storage21
+                image_name_stg22 = storage22
+                image_name_stg23 = storage23
+
+    - clock_getres: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = clock_getres
+
+    - yum_update: install setup image_copy unattended_install.cdrom
+        only Fedora, RHEL
+        type = yum_update
+        shell_prompt = "Is this ok"
+
+    - kdump: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = kdump
+        # time waited for the completion of crash dump
+        # crash_timeout = 360
+        # command to add the crashkernel=X@Y to kernel cmd line
+        # kernel_param_cmd = "grubby --update-kernel=`grubby --default-kernel` --args=crashkernel=128M@64M"
+        # command to enable kdump service
+        # kdump_enable_cmd = chkconfig kdump on && service kdump start
+        # command to probe the crash kernel
+        # crash_kernel_prob_cmd = "grep -q 1 /sys/kernel/kexec_crash_loaded"
+
+    - vmstop: install setup image_copy unattended_install.cdrom
+        type = vmstop
+        # the path used to store the saved vm state
+        # save_path = /tmp
+        # clean the state file?
+        clean_save = yes
+
+    - trans_hugepage: install setup image_copy unattended_install.cdrom
+        thp_test_config = ""
+        kill_vm = yes
+        login_timeout = 360
+        variants:
+            - base:
+                type = trans_hugepage
+                dd_timeout = 900
+            - defrag:
+                type = trans_hugepage_defrag
+            - swapping:
+                type = trans_hugepage_swapping
+                dd_timeout = 900
+                check_cmd_timeout = 900
+
+    # system_powerdown, system_reset and shutdown *must* be the last ones
+    # defined (in this order), since the effect of such tests can leave
+    # the VM on a bad state.
+    - system_powerdown: install setup image_copy unattended_install.cdrom
+        type = shutdown
+        shutdown_method = system_powerdown
+        sleep_before_powerdown = 20
+        kill_vm = yes
+
+    - system_reset: install setup image_copy unattended_install.cdrom
+        type = boot
+        reboot_method = system_reset
+        sleep_before_reset = 20
+        kill_vm_on_error = yes
+
+    - system_reset_bootable: install setup image_copy unattended_install.cdrom
+        type = system_reset_bootable
+        interval = 1
+        reset_times = 20
+        wait_time_for_reset = 120
+        kill_vm_on_error = yes
+
+    - shutdown: install setup image_copy unattended_install.cdrom
+        type = shutdown
+        shutdown_method = shell
+        kill_vm = yes
+        kill_vm_gracefully = no
+    # Do not define test variants below shutdown
+
+
+# NICs
+variants:
+    - @rtl8139:
+        nic_model = rtl8139
+        no ethtool
+        jumbo:
+            mtu = 1500
+    - e1000:
+        nic_model = e1000
+        jumbo:
+            mtu = 16110
+        ethtool:
+                # gso gro lro is only supported by latest kernel
+                supported_features = "tx rx sg tso gso gro lro"
+    - virtio_net:
+        nic_model = virtio
+        # You can add advanced attributes on nic_extra_params such as mrg_rxbuf
+        #nic_extra_params =
+        # You can add advanced attributes through netdev_extra_params
+        # such as sndbuf, as an example, you can uncomment the
+        # following lines to enable the vhost support ( only available
+        # for tap )
+        #netdev_extra_params = "vhost=on"
+        jumbo:
+            mtu = 65520
+        ethtool:
+            supported_features = "tx sg tso gso"
+        whql.submission.device.net:
+            test_device = VirtIO Ethernet Adapter$
+            # Device selection for the NDISTest client machine
+            dp_regex_testdev = VirtIO Ethernet Adapter$
+            dp_regex_clientmsgdev = VirtIO Ethernet Adapter #2$
+            dp_regex_clientsupportdev = VirtIO Ethernet Adapter #3$
+            # Device selection for the NDISTest server machine
+            dp_regex_servermsgdev = VirtIO Ethernet Adapter$
+            dp_regex_serversupportdev = VirtIO Ethernet Adapter #2$
+
+# Guests
+variants:
+    # Linux section
+    - @Linux:
+        shutdown_command = shutdown -h now
+        reboot_command = shutdown -r now
+        status_test_command = echo $?
+        username = root
+        password = 123456
+        shell_client = ssh
+        shell_port = 22
+        file_transfer_client = scp
+        file_transfer_port = 22
+        mem_chk_cmd = dmidecode -t 17 | awk -F: '/Size/ {print $2}'
+        mem_chk_cur_cmd = grep MemTotal /proc/meminfo
+        cpu_chk_cmd = grep -c processor /proc/cpuinfo
+        unattended_install:
+            # If you want to use floppy to hold kickstarts,
+            # comment the 3 lines below
+            cdroms += " unattended"
+            drive_index_unattended = 1
+            drive_index_cd1 = 2
+        timedrift:
+            extra_params += " -no-kvm-pit-reinjection"
+            time_command = date +'TIME: %a %m/%d/%Y %H:%M:%S.%N'
+            time_filter_re = "(?:TIME: \w\w\w )(.{19})(?:\.\d\d)"
+            time_format = "%m/%d/%Y %H:%M:%S"
+            guest_load_command = "dd if=/dev/urandom of=/dev/null"
+            guest_load_instances = 2
+            guest_load_stop_command = "killall -9 dd"
+            host_load_command = "bzip2 -c --best /dev/urandom > /dev/null"
+            host_load_instances = 8
+            ntp:
+                time_command = "ntpdate -d -q ns1.nay.redhat.com"
+                time_filter_re = "originate timestamp:.*, (.\w+\s+\d+\s+\d+\s+\d+:\d+:\d+)\.(.\d+)"
+                time_format = "%b %d %Y %H:%M:%S"
+            date:
+                time_command = date +'TIME: %a %m/%d/%Y %H:%M:%S.%N'
+                time_filter_re = "(?:TIME: \w\w\w )(.{19})(?:\.\d\d)"
+                time_format = "%m/%d/%Y %H:%M:%S"
+        file_transfer:
+            tmp_dir = /tmp/
+            clean_cmd = rm -f
+        nicdriver_unload:
+            readlink_command = readlink -e
+            sys_path = "/sys/class/net/%s/device/driver"
+        multi_disk:
+            show_mount_cmd = mount|gawk '/mnt/{print $1}'
+            clean_cmd = "\rm -rf /mnt/*"
+            cmd_list = "copy_to_command copy_from_command"
+            file_system = "ext3 ext2"
+            mount_command = mkdir /mnt/%s && mount /dev/%s /mnt/%s
+            umount_command = umount /dev/%s && rmdir /mnt/%s
+            list_volume_command = cd /dev && \ls [vhs]d?
+            re_str = "[vhs]d[a-z]"
+            format_command = echo y | mkfs -t %s /dev/%s
+            copy_to_command = \cp -rf /bin/ls /mnt/%s
+            copy_from_command = \cp -rf /mnt/%s/ls /tmp/ls
+            compare_command = cd /bin && md5sum ls > /tmp/ls.md5 && cd /tmp && md5sum -c ls.md5
+            check_result_key_word = OK
+            max_disk:
+                 images += " stg24 stg25 stg26 stg27"
+                 image_name_stg24 = storage24
+                 image_name_stg25 = storage25
+                 image_name_stg26 = storage26
+                 image_name_stg27 = storage27
+                 list_volume_command = cd /dev && \ls vd*
+                 re_str = "[vhs]d[a-z][^0-9]"
+
+        variants:
+            - Fedora:
+                no setup
+                os_type = linux
+                shell_prompt = "^\[.*\][\#\$]\s*$"
+                unattended_install:
+                    boot_path = "images/pxeboot"
+                    # You have to use ks=floppy if you want to use floppies to
+                    # hold your kickstart file
+                    #extra_params += " ks=floppy nicdelay=60 console=ttyS0,115200 console=tty0"
+                    extra_params += " ks=cdrom nicdelay=60 console=ttyS0,115200 console=tty0"
+
+                variants:
+                    - 8.32:
+                        no setup
+                        image_name = fc8-32
+                        install:
+                            steps = Fedora-8-i386.steps
+                            cdrom_cd1 = isos/linux/Fedora-8-i386-DVD.iso
+                            md5sum_cd1 = dd6c79fddfff36d409d02242e7b10189
+                            md5sum_1m_cd1 = dabae451bb69fbbad0e505b25144b1f9
+                        unattended_install:
+                            unattended_file = unattended/Fedora-8.ks
+                            #floppy = images/f8-32/ks.vfd
+                            cdrom_unattended = images/f8-32/ks.iso
+                            kernel = images/f8-32/vmlinuz
+                            initrd = images/f8-32/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-8-i386-DVD.iso
+                            md5sum_cd1 = dd6c79fddfff36d409d02242e7b10189
+                            md5sum_1m_cd1 = dabae451bb69fbbad0e505b25144b1f9
+
+                    - 8.64:
+                        no setup
+                        image_name = f8-64
+                        install:
+                            steps = Fedora-8-64.steps
+                            cdrom_cd1 = isos/linux/Fedora-8-x86_64-DVD.iso
+                            md5sum_cd1 = 2cb231a86709dec413425fd2f8bf5295
+                            md5sum_1m_cd1 = 145f6414e19492649a56c89f0a45e719
+                        unattended_install:
+                            unattended_file = unattended/Fedora-8.ks
+                            #floppy = images/f8-64/ks.vfd
+                            cdrom_unattended = images/f8-64/ks.iso
+                            kernel = images/f8-64/vmlinuz
+                            initrd = images/f8-64/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-8-x86_64-DVD.iso
+                            md5sum_cd1 = 2cb231a86709dec413425fd2f8bf5295
+                            md5sum_1m_cd1 = 145f6414e19492649a56c89f0a45e719
+
+                    - 9.32:
+                        image_name = f9-32
+                        install:
+                            steps = Fedora-9-i386.steps
+                            cdrom_cd1 = isos/linux/Fedora-9-i386-DVD.iso
+                            md5sum_cd1 = 72601f685ea8c808c303353d8bf4d307
+                            md5sum_1m_cd1 = f24fa25689e5863f1b99984c6feb787f
+                        unattended_install:
+                            unattended_file = unattended/Fedora-9.ks
+                            #floppy = images/f9-32/ks.vfd
+                            cdrom_unattended = images/f9-32/ks.iso
+                            kernel = images/f9-32/vmlinuz
+                            initrd = images/f9-32/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-9-i386-DVD.iso
+                            md5sum_cd1 = 72601f685ea8c808c303353d8bf4d307
+                            md5sum_1m_cd1 = f24fa25689e5863f1b99984c6feb787f
+
+
+                    - 9.64:
+                        image_name = f9-64
+                        install:
+                            steps = Fedora-9-64.steps
+                            cdrom_cd1 = isos/linux/Fedora-9-x86_64-DVD.iso
+                            md5sum_cd1 = 05b2ebeed273ec54d6f9ed3d61ea4c96
+                            md5sum_1m_cd1 = 9822ab5097e37e8fe306ef2192727db4
+                        unattended_install:
+                            unattended_file = unattended/Fedora-9.ks
+                            #floppy = images/f9-64/ks.vfd
+                            cdrom_unattended = images/f9-64/ks.iso
+                            kernel = images/f9-64/vmlinuz
+                            initrd = images/f9-64/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-9-x86_64-DVD.iso
+                            md5sum_cd1 = 05b2ebeed273ec54d6f9ed3d61ea4c96
+                            md5sum_1m_cd1 = 9822ab5097e37e8fe306ef2192727db4
+
+
+                    - 10.32:
+                        image_name = f10-32
+                        unattended_install:
+                            unattended_file = unattended/Fedora-10.ks
+                            #floppy = images/f10-32/ks.vfd
+                            cdrom_unattended = images/f10-32/ks.iso
+                            kernel = images/f10-32/vmlinuz
+                            initrd = images/f10-32/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-10-i386-DVD.iso
+                            md5sum_cd1 = 27e581edb392728c4a07d00d3fc5ced0
+                            md5sum_1m_cd1 = bd67c68bdf595e4ba7131ec702159181
+
+                    - 10.64:
+                        image_name = f10-64
+                        unattended_install:
+                            unattended_file = unattended/Fedora-10.ks
+                            #floppy = images/f10-64/ks.vfd
+                            cdrom_unattended = images/f10-64/ks.iso
+                            kernel = images/f10-64/vmlinuz
+                            initrd = images/f10-64/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-10-x86_64-DVD.iso
+                            sha1sum_cd1 = f1e5ae7db6a1ba227de7294c4112385922388648
+                            md5sum_1m_cd1 = 732857cbf40c80c34683e874601d982c
+
+                    - 11.32:
+                        image_name = f11-32
+                        install:
+                            steps = Fedora-11-32.steps
+                        unattended_install:
+                            unattended_file = unattended/Fedora-11.ks
+                            #floppy = images/f11-32/ks.vfd
+                            cdrom_unattended = images/f11-32/ks.iso
+                            kernel = images/f11-32/vmlinuz
+                            initrd = images/f11-32/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-11-i386-DVD.iso
+                            md5sum_cd1 = e3b1e2d1ba42aa4705fa5f41771b3927
+                            md5sum_1m_cd1 = dc8ddf90648c247339c721395aa49714
+
+                    - 11.64:
+                        image_name = f11-64
+                        unattended_install:
+                            unattended_file = unattended/Fedora-11.ks
+                            #floppy = images/f11-64/ks.vfd
+                            cdrom_unattended = images/f11-64/ks.iso
+                            kernel = images/f11-64/vmlinuz
+                            initrd = images/f11-64/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-11-x86_64-DVD.iso
+                            md5sum_cd1 = 9d419844adeb93120215fe7505c9bce8
+                            md5sum_1m_cd1 = 405ee05e2387a2e4328b008d5bcbdd1e
+
+                    - 12.32:
+                        image_name = f12-32
+                        unattended_install:
+                            unattended_file = unattended/Fedora-12.ks
+                            #floppy = images/f12-32/ks.vfd
+                            cdrom_unattended = images/f12-32/ks.iso
+                            kernel = images/f12-32/vmlinuz
+                            initrd = images/f12-32/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-12-i386-DVD.iso
+                            md5sum_cd1 = 2c4c1c0d09f2fbcfd8ee6a0c5542eeb2
+                            md5sum_1m_cd1 = eee935d7f0cf2ef03f6ddce3a2a50050
+
+                    - 12.64:
+                        image_name = f12-64
+                        unattended_install:
+                            unattended_file = unattended/Fedora-12.ks
+                            #floppy = images/f12-64/ks.vfd
+                            cdrom_unattended = images/f12-64/ks.iso
+                            kernel = images/f12-64/vmlinuz
+                            initrd = images/f12-64/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-12-x86_64-DVD.iso
+                            md5sum_cd1 = 6dd31e292cc2eb1140544e9b1ba61c56
+                            md5sum_1m_cd1 = 514efbd7698b55ff6768c8605438bfc5
+
+                    - 13.32:
+                        image_name = f13-32
+                        unattended_install:
+                            unattended_file = unattended/Fedora-13.ks
+                            #floppy = images/f13-32/ks.vfd
+                            cdrom_unattended = images/f13-32/ks.iso
+                            kernel = images/f13-32/vmlinuz
+                            initrd = images/f13-32/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-13-i386-DVD.iso
+                            md5sum_cd1 = 212fec517c2629b4b5eaf3662ac13136
+                            md5sum_1m_cd1 = 4e1578a6ed5a6e7cd03b8fb074030746
+
+                    - 13.64:
+                        image_name = f13-64
+                        unattended_install:
+                            unattended_file = unattended/Fedora-13.ks
+                            #floppy = images/f13-64/ks.vfd
+                            cdrom_unattended = images/f13-64/ks.iso
+                            kernel = images/f13-64/vmlinuz
+                            initrd = images/f13-64/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-13-x86_64-DVD.iso
+                            md5sum_cd1 = 6fbae6379cf27f36e1f2c7827ba7dc35
+                            md5sum_1m_cd1 = 68821b9de4d3b5975d6634334e7f47a6
+
+                    - 14.32:
+                        image_name = f14-32
+                        unattended_install:
+                            unattended_file = unattended/Fedora-14.ks
+                            #floppy = images/f14-32/ks.vfd
+                            cdrom_unattended = images/f14-32/ks.iso
+                            #kernel = images/f14-32/vmlinuz
+                            #initrd = images/f14-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-14-i386-DVD.iso
+                            md5sum_cd1 = 1cc67641506d2f931d669b8d3528dded
+                            md5sum_1m_cd1 = d314ab126dabab686111e6a0d71d2e67
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+                    - 14.64:
+                        image_name = f14-64
+                        unattended_install:
+                            unattended_file = unattended/Fedora-14.ks
+                            #floppy = images/f14-64/ks.vfd
+                            cdrom_unattended = images/f14-64/ks.iso
+                            #kernel = images/f14-64/vmlinuz
+                            #initrd = images/f14-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-14-x86_64-DVD.iso
+                            md5sum_cd1 = f2ebf941dc45f99ee3e8a457c9544552
+                            md5sum_1m_cd1 = df029f9cffbc3517937a91124a1e0c3a
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+                    - 15.32:
+                        image_name = f15-32
+                        unattended_install:
+                            unattended_file = unattended/Fedora-15.ks
+                            #floppy = images/f15-32/ks.vfd
+                            cdrom_unattended = images/f15-32/ks.iso
+                            #kernel = images/f15-32/vmlinuz
+                            #initrd = images/f15-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-15-i386-DVD.iso
+                            md5sum_cd1 = 9a91492ac84dde9ceff0cb346a079487
+                            md5sum_1m_cd1 = 82a6005e8b7740628c6e53eef92f6bc1
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+                    - 15.64:
+                        image_name = f15-64
+                        unattended_install:
+                            unattended_file = unattended/Fedora-15.ks
+                            #floppy = images/f15-64/ks.vfd
+                            cdrom_unattended = images/f15-64/ks.iso
+                            #kernel = images/f15-64/vmlinuz
+                            #initrd = images/f15-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/Fedora-15-x86_64-DVD.iso
+                            md5sum_cd1 = c122a2a4f478da4a3d2d12396e84244e
+                            md5sum_1m_cd1 = c02f37e293bbc85be02a7c850a61273a
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+            - DSL-4.2.5:
+                no setup dbench bonnie linux_s3
+                image_name = dsl-4.2.5
+                install:
+                    steps = DSL-4.2.5.steps
+                    cdrom_cd1 = isos/linux/dsl-4.2.5.iso
+                    md5sum_cd1 = 61694888aede3e01229865b8e6acd4a1
+                    md5sum_1m_cd1 = 527f2481bd25310f2e3a6e5345ff3d12
+
+            - Mandriva-One-2007:
+                only install
+                image_name = mandriva-one-2007
+                steps = Mandriva-One-2007-32.steps
+                cdrom_cd1 = isos/linux/mandriva-one-2007-i386.iso
+                md5sum_cd1 = 7e9e183dc11b9d39f480238e4e12bb05
+                md5sum_1m_cd1 = dc7865a75db665efc86d59bca7c1fe07
+
+            - OpenSUSE:
+                no setup
+                shell_prompt = ".*:.*\s#"
+                unattended_install:
+                    # You have to use autoyast=floppy if you want to use floppies to
+                    # hold your autoyast file
+                    #extra_params += " 'autoyast=floppy console=ttyS0,115200 console=tty0'"
+                    extra_params += " 'autoyast=device://scd0/autoinst.xml console=ttyS0,115200 console=tty0'"
+                    wait_no_ack = yes
+
+                variants:
+                    - 11.0.32:
+                        image_name = openSUSE-11.0-32
+                        install:
+                            steps = openSUSE-11.0-32.steps
+                            cdrom_cd1 = isos/linux/openSUSE-11.0-DVD-i386.iso
+                            md5sum_cd1 = ed6a5b3feb668866df812b1c2aed9d7f
+                            md5sum_1m_cd1 = c720b30557af758e69de450409516369
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-0-32/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-0-32/autoyast.iso
+                            kernel = images/opensuse-11-0-32/linux
+                            initrd = images/opensuse-11-0-32/initrd
+                            boot_path = boot/i386/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.0-DVD-i386.iso
+                            md5sum_cd1 = ed6a5b3feb668866df812b1c2aed9d7f
+                            md5sum_1m_cd1 = c720b30557af758e69de450409516369
+
+
+                    - 11.0.64:
+                        image_name = openSUSE-11.0-64
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-0-64/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-0-64/autoyast.iso
+                            kernel = images/opensuse-11-0-64/linux
+                            initrd = images/opensuse-11-0-64/initrd
+                            boot_path = boot/x86_64/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.0-DVD-x86_64.iso
+                            md5sum_cd1 = 512c8346b0f8eb35f28c4eb96454d391
+                            md5sum_1m_cd1 = 661aa4cd031df2f25ea0102318a3f4d1
+
+                    - 11.1.32:
+                        image_name = openSUSE-11.1-32
+                        install:
+                            steps = openSUSE-11.1-32-and-64.steps
+                            cdrom_cd1 = isos/linux/openSUSE-11.1-DVD-i586.iso
+                            md5sum_cd1 = 8f51b278c0415be28c5699e465444bd3
+                            md5sum_1m_cd1 = b70217417468389083429f81ba7ce2bd
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-1-32/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-1-32/autoyast.iso
+                            kernel = images/opensuse-11-1-32/linux
+                            initrd = images/opensuse-11-1-32/initrd
+                            boot_path = boot/i386/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.1-DVD-i586.iso
+                            md5sum_cd1 = 8f51b278c0415be28c5699e465444bd3
+                            md5sum_1m_cd1 = b70217417468389083429f81ba7ce2bd
+
+                    - 11.1.64:
+                        image_name = openSUSE-11.1-64
+                        install:
+                            steps=openSUSE-11.1-32-and-64.steps
+                            cdrom_cd1 = isos/linux/openSUSE-11.1-DVD-x86_64.iso
+                            md5sum_cd1 = 2afee1b8a87175e6dee2b8dbbd1ad8e8
+                            md5sum_1m_cd1 = 768ca32503ef92c28f2d144f2a87e4d0
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-1-64/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-1-64/autoyast.iso
+                            kernel = images/opensuse-11-1-64/linux
+                            initrd = images/opensuse-11-1-64/initrd
+                            boot_path = boot/x86_64/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.1-DVD-x86_64.iso
+                            md5sum_cd1 = 2afee1b8a87175e6dee2b8dbbd1ad8e8
+                            md5sum_1m_cd1 = 768ca32503ef92c28f2d144f2a87e4d0
+
+
+                    - 11.2.32:
+                        image_name = openSUSE-11.2-32
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-2-32/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-2-32/autoyast.iso
+                            kernel = images/opensuse-11-2-32/linux
+                            initrd = images/opensuse-11-2-32/initrd
+                            boot_path = boot/i386/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.2-DVD-i586.iso
+                            md5sum_cd1 = 295d713314a30ad017948f0d542c6d92
+                            md5sum_1m_cd1 = 1f8767d00acb492be5a5627c834e543f
+
+
+                    - 11.2.64:
+                        image_name = openSUSE-11.2-64
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse11-2-64/autoyast.vfd
+                            cdrom_unattended = images/opensuse11-2-64/autoyast.iso
+                            kernel = images/opensuse-11-2-64/linux
+                            initrd = images/opensuse-11-2-64/initrd
+                            boot_path = boot/x86_64/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.2-DVD-x86_64.iso
+                            md5sum_cd1 = 6a09295e34dc030319d040f67f4742c6
+                            md5sum_1m_cd1 = 11fd11d39744450b898f04c371dde2e7
+
+                    - 11.3.32:
+                        image_name = openSUSE-11.3-32
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-3-32/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-3-32/autoyast.iso
+                            kernel = images/opensuse-11-3-32/linux
+                            initrd = images/opensuse-11-3-32/initrd
+                            boot_path = boot/i386/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.3-DVD-i586.iso
+                            md5sum_cd1 = 1a1da28c84e3cdad750d5cfa21c4fd17
+                            md5sum_1m_cd1 = 4dd26906ce6cb3946519cb0b0de4b0f8
+
+                    - 11.3.64:
+                        image_name = openSUSE-11.3-64
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-3-64/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-3-64/autoyast.iso
+                            kernel = images/opensuse-11-3-64/linux
+                            initrd = images/opensuse-11-3-64/initrd
+                            boot_path = boot/x86_64/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.3-DVD-x86_64.iso
+                            md5sum_cd1 = adf5d2a0a03c1e3aaf102fd6a4771b87
+                            md5sum_1m_cd1 = e0dd12dac30d296417256775e1234c6e
+
+                    - 11.4.32:
+                        image_name = openSUSE-11.4-32
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-4-32/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-4-32/autoyast.iso
+                            kernel = images/opensuse-11-4-32/linux
+                            initrd = images/opensuse-11-4-32/initrd
+                            boot_path = boot/x86_64/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.4-DVD-i586.iso
+                            md5sum_cd1 = 5f6d6d67c3e256b2513311f4ed650515
+
+                    - 11.4.64:
+                        image_name = openSUSE-11.4-64
+                        unattended_install:
+                            unattended_file = unattended/OpenSUSE-11.xml
+                            #floppy = images/opensuse-11-4-64/autoyast.vfd
+                            cdrom_unattended = images/opensuse-11-4-64/autoyast.iso
+                            kernel = images/opensuse-11-4-64/linux
+                            initrd = images/opensuse-11-4-64/initrd
+                            boot_path = boot/x86_64/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/openSUSE-11.4-DVD-x86_64.iso
+                            md5sum_cd1 = 082ebfac494b41cd56b38fb4218c545d
+                            md5sum_1m_cd1 = 2adcc5623e6c50b5d08acb7f84aa3fb1
+
+            - SLES:
+                shell_prompt = "^root@.*[\#\$]\s*$|#"
+                unattended_install:
+                    # You have to use autoyast=floppy if you want to use floppies to
+                    # hold your autoyast file
+                    #extra_params += " 'autoyast=floppy console=ttyS0,115200 console=tty0'"
+                    extra_params += " 'autoyast=device://scd0/autoinst.xml console=ttyS0,115200 console=tty0'"
+                    kernel = linux
+                    initrd = initrd
+                    wait_no_ack = yes
+
+                variants:
+                    - 11.0.32:
+                        image_name = sles11-32
+                        unattended_install:
+                            unattended_file = unattended/SLES-11.xml
+                            #floppy = images/sles-11-0-32/autoyast.vfd
+                            cdrom_unattended = images/sles-11-0-32/autoyast.iso
+                            kernel = images/sles-11-0-32/linux
+                            initrd = images/sles-11-0-32/initrd
+                            boot_path = boot/i386/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/SLES-11-DVD-i586-GM-DVD1.iso
+                            md5sum_cd1 = 4958d4dde2575666355c8a1c5858bab0
+                            md5sum_1m_cd1 = 1f19d4eff5bcead2a3e5b8b4212b6796
+
+
+                    - 11.0.64:
+                        image_name = sles11-64
+                        cdrom_cd1 = isos/linux/SLES-11-DVD-x86_64-GM-DVD1.iso
+                        md5sum_cd1 = 50a2bd45cd12c3808c3ee48208e2586b
+                        md5sum_1m_cd1 = 00000951cab7c32e332362fc424c1054
+                        unattended_install:
+                            unattended_file = unattended/SLES-11.xml
+                            #floppy = images/sles-11-0-64/autoyast.vfd
+                            cdrom_unattended = images/sles-11-0-64/autoyast.iso
+                            kernel = images/sles-11-0-64/linux
+                            initrd = images/sles-11-0-64/initrd
+                            boot_path = boot/x86_64/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/SLES-11-DVD-x86_64-GM-DVD1.iso
+                            md5sum_cd1 = 50a2bd45cd12c3808c3ee48208e2586b
+                            md5sum_1m_cd1 = 00000951cab7c32e332362fc424c1054
+
+
+                    - 11.1.32:
+                        image_name = sles11sp1-32
+                        unattended_install:
+                            unattended_file = unattended/SLES-11.xml
+                            #floppy = images/sles-11-1-32/autoyast.vfd
+                            cdrom_unattended = images/sles-11-1-32/autoyast.iso
+                            kernel = images/sles-11-1-32/linux
+                            initrd = images/sles-11-1-32/initrd
+                            boot_path = boot/i386/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/SLES-11-SP1-DVD-i586-GM-DVD1.iso
+                            md5sum_cd1 = 0dd6886858d93501c38854552b9b1b0d
+                            md5sum_1m_cd1 = a626a3d50813410e3ac42794e05773bb
+
+                    - 11.1.64:
+                        image_name = sles11sp1-64
+                        unattended_install:
+                            unattended_file = unattended/SLES-11.xml
+                            #floppy = images/sles-11-1-64/autoyast.vfd
+                            cdrom_unattended = images/sles-11-1-64/autoyast.iso
+                            kernel = images/sles-11-1-64/linux
+                            initrd = images/sles-11-1-64/initrd
+                            boot_path = boot/x86_64/loader
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/SLES-11-SP1-DVD-x86_64-GM-DVD1.iso
+                            md5sum_cd1 = d2e10420f3689faa49a004b60fb396b7
+                            md5sum_1m_cd1 = f7f67b5da46923a9f01da8a2b6909654
+
+
+            - @Ubuntu:
+                shell_prompt = "^root@.*[\#\$]\s*$"
+
+                variants:
+                    - Ubuntu-6.10-32:
+                        only install
+                        image_name = ubuntu-6.10-32
+                        steps = Ubuntu-6.10-32.steps
+                        cdrom_cd1 = isos/linux/ubuntu-6.10-desktop-i386.iso
+                        md5sum_cd1 = 17fb825641571ce5888a718329efd016
+                        md5sum_1m_cd1 = 7531d0a84e7451d17c5d976f1c3f8509
+
+                    - Ubuntu-8.04-32:
+                        skip = yes
+                        image_name = ubuntu-8.04-32
+                        install:
+                            steps = Ubuntu-8.04-32.steps
+                            cdrom_cd1 = isos/linux/ubuntu-8.04.1-desktop-i386.iso
+                        setup:
+                            steps = Ubuntu-8.04-32-setupssh.steps
+
+                    - Ubuntu-8.10-server-32:
+                        image_name = ubuntu-8.10-server-32
+                        install:
+                            steps = Ubuntu-8.10-server-32.steps
+                            cdrom_cd1 = isos/linux/ubuntu-8.10-server-i386.iso
+                            md5sum_cd1 = a2ec9975a91e1228c8292ed9799dc302
+                            md5sum_1m_cd1 = ea493eb8ef7722ead693492fd9f8a13f
+                        setup:
+                            steps = Ubuntu-8.10-server-32-gcc.steps
+
+            - RHEL:
+                no setup
+                os_type = linux
+                shell_prompt = "^\[.*\][\#\$]\s*$"
+                nic_hotplug:
+                    modprobe_module = acpiphp
+                block_hotplug:
+                    modprobe_module = acpiphp
+                    no block_scsi
+                unattended_install:
+                    boot_path = images/pxeboot
+                    # You have to use ks=floppy if you want to use floppies to
+                    # hold your kickstart file
+                    #extra_params += " ks=floppy nicdelay=60 console=ttyS0,115200 console=tty0"
+                    extra_params += " ks=cdrom nicdelay=60 console=ttyS0,115200 console=tty0"
+
+                variants:
+                    - 3.9.i386:
+                        no setup autotest linux_s3 guest_s4 shutdown multi_disk
+                        os_variant = rhel3
+                        image_name = rhel3-32
+                        mem_chk_cmd = dmidecode | awk -F: '/Maximum Capacity/ {print $2}'
+                        install:
+                            steps=RHEL-3.9-i386.steps
+                            cdrom_cd1 = isos/linux/RHEL-3.9-i386-DVD.iso
+                            md5sum_cd1 = ddd11a1cb104119039b0fa05df6d52b8
+                            md5sum_1m_cd1 = 5f10c9417c7b8372b3456c1b5f3f9ed0
+                        unattended_install:
+                            unattended_file = unattended/RHEL-3-series.ks
+                            #floppy = images/rhel39-32/ks.vfd
+                            cdrom_unattended = images/rhel39-32/ks.iso
+                            #kernel = images/rhel39-32/vmlinuz
+                            #initrd = images/rhel39-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                            # 3.X anaconda does not support 'poweroff' on ks
+                            shutdown_cleanly = no
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-3.9-i386-DVD.iso
+                            md5sum_cd1 = ddd11a1cb104119039b0fa05df6d52b8
+                            md5sum_1m_cd1 = 5f10c9417c7b8372b3456c1b5f3f9ed0
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+                    - 3.9.x86_64:
+                        no setup autotest linux_s3 guest_s4 shutdown multi_disk
+                        os_variant = rhel3
+                        image_name = rhel3-64
+                        mem_chk_cmd = dmidecode | awk -F: '/Maximum Capacity/ {print $2}'
+                        install:
+                            steps=RHEL-3.9-x86_64.steps
+                            cdrom_cd1 = isos/linux/RHEL-3.9-x86_64-DVD.iso
+                            md5sum_cd1 = bf4635e4a4bd3b43838e72bc8c329d55
+                            md5sum_1m_cd1 = 18ecd37b639109f1b2af05cfb57dfeaf
+                        unattended_install:
+                            unattended_file = unattended/RHEL-3-series.ks
+                            #floppy = images/rhel39-64/ks.vfd
+                            cdrom_unattended = images/rhel39-64/ks.iso
+                            #kernel = images/rhel39-64/vmlinuz
+                            #initrd = images/rhel39-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                            # 3.X anaconda does not support 'poweroff' on ks
+                            shutdown_cleanly = no
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-3.9-x86_64-DVD.iso
+                            md5sum_cd1 = bf4635e4a4bd3b43838e72bc8c329d55
+                            md5sum_1m_cd1 = 18ecd37b639109f1b2af05cfb57dfeaf
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 4.7.i386:
+                        no setup autotest
+                        os_variant = rhel4
+                        image_name = rhel4-32
+                        install:
+                            steps = RHEL-4.7-i386.steps
+                            cdrom_cd1 = isos/linux/RHEL-4.7-i386-DVD.iso
+                            md5sum_cd1 = ee5092653732a88ddbaf8eef2484c500
+                            md5sum_1m_cd1 = 127081cbed825d7232331a2083975528
+                        unattended_install:
+                            unattended_file = unattended/RHEL-4-series.ks
+                            #floppy = images/rhel47-32/ks.vfd
+                            cdrom_unattended = images/rhel47-32/ks.iso
+                            #kernel = images/rhel47-32/vmlinuz
+                            #initrd = images/rhel47-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-4.7-i386-DVD.iso
+                            md5sum_cd1 = ee5092653732a88ddbaf8eef2484c500
+                            md5sum_1m_cd1 = 127081cbed825d7232331a2083975528
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                        fillup_disk:
+                            fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1"
+                        lvm.lvm_fill:
+                            fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1"
+
+                    - 4.7.x86_64:
+                        no setup autotest
+                        os_variant = rhel4
+                        image_name = rhel4-64
+                        install:
+                            steps = RHEL-4.7-x86_64.steps
+                            cdrom_cd1 = isos/linux/RHEL-4.7-x86_64-DVD.iso
+                            md5sum_cd1 = ea9dae16dd86f7d94092d0e672333292
+                            md5sum_1m_cd1 = 58fa63eaee68e269f4cb1d2edf479792
+                        unattended_install:
+                            unattended_file = unattended/RHEL-4-series.ks
+                            #floppy = images/rhel47-64/ks.vfd
+                            cdrom_unattended = images/rhel47-64/ks.iso
+                            #kernel = images/rhel47-64/vmlinuz
+                            #initrd = images/rhel47-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-4.7-x86_64-DVD.iso
+                            md5sum_cd1 = ea9dae16dd86f7d94092d0e672333292
+                            md5sum_1m_cd1 = 58fa63eaee68e269f4cb1d2edf479792
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                        fillup_disk:
+                            fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1"
+                        lvm.lvm_fill:
+                            fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1"
+
+                    - 4.8.i386:
+                        no setup autotest
+                        os_variant = rhel4
+                        image_name = rhel4-32
+                        unattended_install:
+                            unattended_file = unattended/RHEL-4-series.ks
+                            #floppy = images/rhel48-32/ks.vfd
+                            cdrom_unattended = images/rhel48-32/ks.iso
+                            #kernel = images/rhel48-32/vmlinuz
+                            #initrd = images/rhel48-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-4.8-i386-DVD.iso
+                            md5sum_cd1 = b024f0af5079539d3ef51f71fed0b194
+                            md5sum_1m_cd1 = 969c197402b9058f28a278c1f807d15b
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                        nicdriver_unload:
+                            readlink_command = readlink -f
+                            sys_path = "/sys/class/net/%s/driver"
+                        fillup_disk:
+                            fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1"
+                        lvm.lvm_fill:
+                            fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1"
+
+
+                    - 4.8.x86_64:
+                        no setup autotest
+                        os_variant = rhel4
+                        image_name = rhel4-64
+                        unattended_install:
+                            unattended_file = unattended/RHEL-4-series.ks
+                            #floppy = images/rhel48-64/ks.vfd
+                            cdrom_unattended = images/rhel48-64/ks.iso
+                            #kernel = images/rhel48-64/vmlinuz
+                            #initrd = images/rhel48-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-4.8-x86_64-DVD.iso
+                            md5sum_cd1 = 696bc877b0200cc942626673fcc3fc09
+                            md5sum_1m_cd1 = b11ac0ef7fd345ad712966972db63886
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                        nicdriver_unload:
+                            readlink_command = readlink -f
+                            sys_path = "/sys/class/net/%s/driver"
+                        fillup_disk:
+                            fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1"
+                        lvm.lvm_fill:
+                            fillup_cmd = "dd if=/dev/zero of=/%s/fillup.%d bs=%dM count=1"
+
+
+                    - 5.3.i386:
+                        no setup
+                        os_variant = rhel5
+                        image_name = rhel5-32
+                        install:
+                            steps = RHEL-5.3-i386.steps
+                            cdrom_cd1 = isos/linux/RHEL-5.3-i386-DVD.iso
+                            md5sum_cd1 = 371c62851611fd32ead440df6f24a296
+                            md5sum_1m_cd1 = 242318dd44152210f6ff6cdda1bfbf51
+                        unattended_install:
+                            unattended_file = unattended/RHEL-5-series.ks
+                            #floppy = images/rhel53-32/ks.vfd
+                            cdrom_unattended = images/rhel53-32/ks.iso
+                            #kernel = images/rhel53-32/vmlinuz
+                            #initrd = images/rhel53-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.3-i386-DVD.iso
+                            md5sum_cd1 = 371c62851611fd32ead440df6f24a296
+                            md5sum_1m_cd1 = 242318dd44152210f6ff6cdda1bfbf51
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 5.3.x86_64:
+                        no setup
+                        os_variant = rhel5
+                        image_name = rhel5-64
+                        install:
+                            steps=RHEL-5.3-x86_64.steps
+                            cdrom_cd1 = isos/linux/RHEL-5.3-x86_64-DVD.iso
+                            md5sum_cd1 = c5ed6b284410f4d8212cafc78fd7a8c5
+                            md5sum_1m_cd1 = b999f437583098ea5bbd56fb1de1d011
+                        unattended_install:
+                            unattended_file = unattended/RHEL-5-series.ks
+                            #floppy = images/rhel53-64/ks.vfd
+                            cdrom_unattended = images/rhel53-64/ks.iso
+                            #kernel = images/rhel53-64/vmlinuz
+                            #initrd = images/rhel53-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.3-x86_64-DVD.iso
+                            md5sum_cd1 = c5ed6b284410f4d8212cafc78fd7a8c5
+                            md5sum_1m_cd1 = b999f437583098ea5bbd56fb1de1d011
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 5.4.i386:
+                        no setup
+                        os_variant = rhel5
+                        image_name = rhel5-32
+                        unattended_install:
+                            unattended_file = unattended/RHEL-5-series.ks
+                            #floppy = images/rhel54-32/ks.vfd
+                            cdrom_unattended = images/rhel54-32/ks.iso
+                            #kernel = images/rhel54-32/vmlinuz
+                            #initrd = images/rhel54-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.4-i386-DVD.iso
+                            md5sum_cd1 = 7a12ec6599527e4f3d1790b51eadbfed
+                            md5sum_1m_cd1 = 0dbeb8f58d213752d8c029e8601abfbb
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 5.4.x86_64:
+                        no setup
+                        os_variant = rhel5
+                        image_name = rhel5-64
+                        unattended_install:
+                            unattended_file = unattended/RHEL-5-series.ks
+                            #floppy = images/rhel54-64/ks.vfd
+                            cdrom_unattended = images/rhel54-64/ks.iso
+                            #kernel = images/rhel54-64/vmlinuz
+                            #initrd = images/rhel54-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.4-x86_64-DVD.iso
+                            md5sum_cd1 = 04fe3c10202402d7b389528d2bad0210
+                            md5sum_1m_cd1 = 3e74112003e88a966754849dbb8f5c3f
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 5.5.i386:
+                        no setup
+                        os_variant = rhel5
+                        image_name = rhel5-32
+                        unattended_install:
+                            unattended_file = unattended/RHEL-5-series.ks
+                            #floppy = images/rhel55-32/ks.vfd
+                            cdrom_unattended = images/rhel55-32/ks.iso
+                            #kernel = images/rhel55-32/vmlinuz
+                            #initrd = images/rhel55-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.5-i386-DVD.iso
+                            md5sum_cd1 = 148858b157f275d9153797efddfc83c3
+                            md5sum_1m_cd1 = 2502cc7ddb9d0684fe08c4a83d247902
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 5.5.x86_64:
+                        no setup
+                        os_variant = rhel5
+                        image_name = rhel5-64
+                        unattended_install:
+                            unattended_file = unattended/RHEL-5-series.ks
+                            #floppy = images/rhel55-64/ks.vfd
+                            cdrom_unattended = images/rhel55-64/ks.iso
+                            #kernel = images/rhel55-64/vmlinuz
+                            #initrd = images/rhel55-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.5-x86_64-DVD.iso
+                            md5sum_cd1 = f3119f883257ef9041234feda2f1cad0
+                            md5sum_1m_cd1 = a744084a03f6a08627f71527fc107a1e
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+                    - 5.6.i386:
+                        no setup
+                        os_variant = rhel5
+                        image_name = rhel5-32
+                        unattended_install:
+                            unattended_file = unattended/RHEL-5-series.ks
+                            #floppy = images/rhel56-32/ks.vfd
+                            cdrom_unattended = images/rhel56-32/ks.iso
+                            #kernel = images/rhel56-32/vmlinuz
+                            #initrd = images/rhel56-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.6-i386-DVD.iso
+                            md5sum_cd1 = c214653d91b81c9a7a7f7249753d0f5d
+                            md5sum_1m_cd1 = f299a881950bfec81fd5c74484e1b1d4
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 5.6.x86_64:
+                        no setup
+                        os_variant = rhel5
+                        image_name = rhel5-64
+                        unattended_install:
+                            unattended_file = unattended/RHEL-5-series.ks
+                            #floppy = images/rhel56-64/ks.vfd
+                            cdrom_unattended = images/rhel56-64/ks.iso
+                            #kernel = images/rhel56-64/vmlinuz
+                            #initrd = images/rhel56-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.6-x86_64-DVD.iso
+                            md5sum_cd1 = d77d3815afb381a50148ba55ad930679
+                            md5sum_1m_cd1 = 9dd97de110e391fcbed88b124a60f7a9
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 6.0.i386:
+                        no setup
+                        os_variant = rhel6
+                        nic_hotplug:
+                            modprobe_module =
+                        block_hotplug:
+                            modprobe_module =
+                        image_name = rhel6-32
+                        unattended_install:
+                            unattended_file = unattended/RHEL-6-series.ks
+                            #floppy = images/rhel60-32/ks.vfd
+                            cdrom_unattended = images/rhel60-32/ks.iso
+                            #kernel = images/rhel60-32/vmlinuz
+                            #initrd = images/rhel60-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-6.0-i386-DVD.iso
+                            md5sum_cd1 = 291d234c93442405972689b4b41c14bc
+                            md5sum_1m_cd1 = ee2cc3d3babe91a1d581a07099c4318b
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 6.0.x86_64:
+                        no setup
+                        os_variant = rhel6
+                        nic_hotplug:
+                            modprobe_module =
+                        block_hotplug:
+                            modprobe_module =
+                        image_name = rhel6-64
+                        unattended_install:
+                            unattended_file = unattended/RHEL-6-series.ks
+                            #floppy = images/rhel60-64/ks.vfd
+                            cdrom_unattended = images/rhel60-64/ks.iso
+                            #kernel = images/rhel60-64/vmlinuz
+                            #initrd = images/rhel60-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-6.0-x86_64-DVD.iso
+                            md5sum_cd1 = f7141396c6a19399d63e8c195354317d
+                            md5sum_1m_cd1 = b060eeef63e2c8700db54ae02056e80c
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 6.1.i386:
+                        no setup
+                        os_variant = rhel6
+                        nic_hotplug:
+                            modprobe_module =
+                        block_hotplug:
+                            modprobe_module =
+                        image_name = rhel6-32
+                        unattended_install:
+                            unattended_file = unattended/RHEL-6-series.ks
+                            #floppy = images/rhel61-32/ks.vfd
+                            cdrom_unattended = images/rhel61-32/ks.iso
+                            #kernel = images/rhel61-32/vmlinuz
+                            #initrd = images/rhel61-32/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-6.1-i386-DVD.iso
+                            md5sum_cd1 = f8c8a310e34d26339c99d462e3557324
+                            md5sum_1m_cd1 = 12f7692e6e20be0d42b9407d956f74c3
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+                    - 6.1.x86_64:
+                        no setup
+                        os_variant = rhel6
+                        nic_hotplug:
+                            modprobe_module =
+                        block_hotplug:
+                            modprobe_module =
+                        image_name = rhel6-64
+                        unattended_install:
+                            unattended_file = unattended/RHEL-6-series.ks
+                            #floppy = images/rhel61-64/ks.vfd
+                            cdrom_unattended = images/rhel61-64/ks.iso
+                            #kernel = images/rhel61-64/vmlinuz
+                            #initrd = images/rhel61-64/initrd.img
+                            kernel = images/pxeboot/vmlinuz
+                            initrd = images/pxeboot/initrd.img
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-6.1-x86_64-DVD.iso
+                            md5sum_cd1 = a051dbf28ef444a019dc6660efe3e3a4
+                            md5sum_1m_cd1 = cb3b9d140404a6797b0f423dfe620ab8
+                        unattended_install.url:
+                            url = REPLACE_THIS_WITH_TREE_URL
+                            nfs_server = REPLACE_THIS_WITH_NFS_SERVER
+                            nfs_dir = REPLACE_THIS_WITH_NFS_DIRECTORY
+
+
+
+    # Windows section
+    - @Windows:
+        os_type = windows
+        use_libvirt_cdrom_switch = yes
+        shutdown_command = shutdown /s /f /t 0
+        reboot_command = shutdown /r /f /t 0
+        status_test_command = echo %errorlevel%
+        shell_prompt = "^\w:\\.*>\s*$"
+        username = Administrator
+        password = 123456
+        shell_linesep = "\r\n"
+        shell_client = nc
+        shell_port = 10022
+        file_transfer_client = rss
+        file_transfer_port = 10023
+        redirs += " file_transfer"
+        guest_port_remote_shell = 10022
+        guest_port_file_transfer = 10023
+
+        # This ISO will be used for all tests except install:
+        cdrom_cd1 = isos/windows/winutils.iso
+
+        cpu_chk_cmd = echo %NUMBER_OF_PROCESSORS%
+        mem_chk_cmd = wmic memphysical
+        mem_chk_cur_cmd = wmic memphysical
+
+        unattended_install.cdrom, whql.support_vm_install:
+            timeout = 7200
+            finish_program = deps/finish.exe
+            cdroms += " winutils"
+            cdrom_winutils = isos/windows/winutils.iso
+            drive_index_winutils = 2
+            kernel =
+            initrd =
+        migrate:
+            migration_test_command = ver && vol
+            migration_bg_command = start ping -t localhost
+            migration_bg_check_command = tasklist | find /I "ping.exe"
+            migration_bg_kill_command = taskkill /IM ping.exe /F
+        migrate.with_file_transfer:
+            guest_path = C:\tmpfile
+        stress_boot:
+            alive_test_cmd = systeminfo
+        timedrift:
+            # Timedrift compensation on Windows with hpet does not happen
+            disable_hpet = yes
+            extra_params += " -rtc-td-hack"
+            time_command = "echo TIME: %date% %time%"
+            time_filter_re = "(?<=TIME: \w\w\w ).{19}(?=\.\d\d)"
+            time_format = "%m/%d/%Y %H:%M:%S"
+            # For this to work, the cdrom at d: should contain vlc (d:\vlc\vlc.exe) and a video (d:\ED_1024.avi)
+            guest_load_command = 'cmd /c "d:\vlc\vlc -f --loop --no-qt-privacy-ask --no-qt-system-tray d:\ED_1024.avi"'
+            # Alternative guest load:
+            #guest_load_command = "(dir /s && dir /s && dir /s && dir /s) > nul"
+            guest_load_stop_command = "taskkill /F /IM vlc.exe"
+            guest_load_instances = 2
+            host_load_command = "bzip2 -c --best /dev/urandom > /dev/null"
+            # Alternative host load:
+            #host_load_command = "dd if=/dev/urandom of=/dev/null"
+            host_load_instances = 8
+            ntp:
+                time_command = "w32tm /stripchart /samples:1 /computer:ns1.nay.redhat.com"
+                time_filter_re = "\d+/\d+/\d+\s\d+:\d+:\d+ [AP]M"
+                time_format = "%m/%d/%Y %H:%M:%S"
+            date:
+                time_command = "echo TIME: %date% %time%"
+                time_filter_re = "(?<=TIME: \w\w\w ).{19}(?=\.\d\d)"
+                time_format = "%m/%d/%Y %H:%M:%S"
+        guest_s4:
+            check_s4_support_cmd = powercfg /hibernate on
+            test_s4_cmd = start ping -t localhost
+            check_s4_cmd = tasklist | find /I "ping.exe"
+            set_s4_cmd = rundll32.exe PowrProf.dll, SetSuspendState
+            kill_test_s4_cmd = taskkill /IM ping.exe /F
+            services_up_timeout = 30
+        nic_hotplug:
+            reference_cmd = ipconfig /all
+            find_pci_cmd = ipconfig /all | find "Description"
+            wait_secs_for_hook_up = 10
+            nic_e1000:
+                match_string = "Intel(R) PRO/1000 MT Network Connection"
+            nic_virtio:
+                match_string = "VirtIO Ethernet"
+        block_hotplug:
+            wait_secs_for_hook_up = 10
+            reference_cmd = wmic diskdrive list brief
+            find_pci_cmd = wmic diskdrive list brief
+            pci_test_cmd = echo select disk 1 > dt && echo online >> dt && echo detail disk >> dt && echo exit >> dt && diskpart /s dt
+        physical_resources_check:
+            catch_uuid_cmd =
+        file_transfer:
+            tmp_dir = C:\
+            clean_cmd = del
+        vmstop:
+            guest_path = C:\
+        multi_disk:
+            block_list += " E:"
+            shell_port = 23
+            shell_client = telnet
+            post_cmd = del c:\cmd.exe
+            file_system = "ntfs fat32"
+            cmd_list = "copy_to_command copy_from_command"
+            list_volume_command = wmic volume get driveletter
+            re_str = "([A-Z]:)"
+            format_command = format /fs:%s %s /q /y
+            copy_to_command = copy C:\WINDOWS\system32\cmd.exe %s /y
+            copy_from_command = copy %s\cmd.exe c:\ /y
+            compare_command = fc /b c:\windows\system32\cmd.exe c:\cmd.exe
+            check_result_key_word = no difference
+            signal_repeat:
+                pre_cmd = del diskpart.script && (echo select disk 1 >> diskpart.script && echo create partition primary >> diskpart.script && echo assign >> diskpart.script) && echo select disk 0 >> diskpart.script && echo exit >> diskpart.script && diskpart /s diskpart.script
+            max_disk:
+                pre_cmd = del diskpart.script && (for /L %i in (1 1 23) do echo select disk %i >> diskpart.script && echo create partition primary >> diskpart.script && echo assign >> diskpart.script) && echo select disk 0 >> diskpart.script && echo exit >> diskpart.script && diskpart /s diskpart.script
+
+        variants:
+            - Win2000:
+                no reboot whql
+                os_variant = win2k
+                image_name = win2000-32
+                kill_vm_gracefully = no
+                install:
+                    steps = Win2000-32.steps
+                    cdrom_cd1 = isos/windows/Windows2000_sp4.iso
+                    md5sum_cd1 = dda6039f3a9173f0f6bfae40f5efdfea
+                    md5sum_1m_cd1 = dd28fba196d366d56fe774bd93df5527
+                    user = user
+                setup:
+                    steps = Win2000-32-rss.steps
+                unattended_install.cdrom:
+                    cdrom_cd1 = isos/windows/Windows2000_sp4.iso
+                    md5sum_cd1 = dda6039f3a9173f0f6bfae40f5efdfea
+                    md5sum_1m_cd1 = dd28fba196d366d56fe774bd93df5527
+                    unattended_file = unattended/win2000-32.sif
+                    floppy = images/win2000-32/answer.vfd
+
+            - WinXP:
+                image_name = winXP
+                os_variant = winxp
+                variants:
+                    - 32:
+                        image_name += -32
+                        install:
+                            cdrom_cd1 = isos/windows/WindowsXP-sp2-vlk.iso
+                            md5sum_cd1 = 743450644b1d9fe97b3cf379e22dceb0
+                            md5sum_1m_cd1 = b473bf75af2d1269fec8958cf0202bfd
+                            user = user
+                            steps = WinXP-32.steps
+                        setup:
+                            steps = WinXP-32-rss.steps
+                        unattended_install.cdrom, whql.support_vm_install:
+                            cdrom_cd1 = isos/windows/WindowsXP-sp2-vlk.iso
+                            md5sum_cd1 = 743450644b1d9fe97b3cf379e22dceb0
+                            md5sum_1m_cd1 = b473bf75af2d1269fec8958cf0202bfd
+                            unattended_file = unattended/winxp32.sif
+                            floppy = images/winXP-32/answer.vfd
+                        whql.submission:
+                            desc_path_desc1 = $\WDK\Logo Type\Device Logo\Windows XP
+                            desc_path_desc2 = $\WDK\Logo Type\Systems Logo\Windows XP
+                            dd_data_logoarch = X86
+                            dd_data_logoos = Windows XP
+                            dd_data_whqlos = Windows XP
+                            device:
+                                dd_data_whqlqual = Basic
+                            device.net:
+                                image_name_supportvm = winXP-32-supportvm
+                        multi_disk:
+                            list_volume_command = fsutil fsinfo drives
+
+
+                    - 64:
+                        image_name += -64
+                        install:
+                            cdrom_cd1 = isos/windows/WindowsXP-64.iso
+                            md5sum_cd1 = 8d3f007ec9c2060cec8a50ee7d7dc512
+                            md5sum_1m_cd1 = e812363ff427effc512b7801ee70e513
+                            user = user
+                            steps = WinXP-64.steps
+                        setup:
+                            steps = WinXP-64-rss.steps
+                        unattended_install.cdrom, whql.support_vm_install:
+                            cdrom_cd1 = isos/windows/WindowsXP-64.iso
+                            md5sum_cd1 = 8d3f007ec9c2060cec8a50ee7d7dc512
+                            md5sum_1m_cd1 = e812363ff427effc512b7801ee70e513
+                            unattended_file = unattended/winxp64.sif
+                            floppy = images/winXP-64/answer.vfd
+                        whql.submission:
+                            desc_path_desc1 = $\WDK\Logo Type\Device Logo\Windows XP
+                            desc_path_desc2 = $\WDK\Logo Type\Systems Logo\Windows XP
+                            dd_data_logoarch = AMD64
+                            dd_data_logoos = Windows XP 64-Bit Edition Version 2003
+                            dd_data_whqlos = Windows XP x64
+                            device:
+                                dd_data_whqlqual = Basic
+                            device.net:
+                                image_name_supportvm = winXP-64-supportvm
+                        multi_disk:
+                            list_volume_command = fsutil fsinfo drives
+
+
+            - Win2003:
+                os_variant = win2k3
+                image_name = win2003
+                image_size = 20G
+
+                variants:
+                    - 32:
+                        image_name += -32
+                        install:
+                            cdrom_cd1 = isos/windows/en_win_srv_2003_r2_enterprise_with_sp2_cd1_x13-05460.iso
+                            md5sum_cd1 = 7c3bc891d20c7e6a110c4f1ad82952ba
+                            md5sum_1m_cd1 = b1671ecf47a270e49e04982bf1474ff9
+                            sha1sum_cd1 = ee11cc735c695501874d2fa123f7d78449b3de7c
+                            sha1sum_1m_cd1 = e2d49dc3fbe17a6b2ba1812543f2cc08ef9565c4
+                            #cdrom_cd1 = isos/windows/Windows2003_r2_VLK.iso
+                            #md5sum_cd1 = 03e921e9b4214773c21a39f5c3f42ef7
+                            #md5sum_1m_cd1 = 37c2fdec15ac4ec16aa10fdfdb338aa3
+                            user = user
+                            steps = Win2003-32.steps
+                        setup:
+                            steps = Win2003-32-rss.steps
+                        unattended_install.cdrom, whql.support_vm_install:
+                            cdrom_cd1 = isos/windows/en_win_srv_2003_r2_enterprise_with_sp2_cd1_x13-05460.iso
+                            md5sum_cd1 = 7c3bc891d20c7e6a110c4f1ad82952ba
+                            md5sum_1m_cd1 = b1671ecf47a270e49e04982bf1474ff9
+                            sha1sum_cd1 = ee11cc735c695501874d2fa123f7d78449b3de7c
+                            sha1sum_1m_cd1 = e2d49dc3fbe17a6b2ba1812543f2cc08ef9565c4
+                            #cdrom_cd1 = isos/windows/Windows2003_r2_VLK.iso
+                            #md5sum_cd1 = 03e921e9b4214773c21a39f5c3f42ef7
+                            #md5sum_1m_cd1 = 37c2fdec15ac4ec16aa10fdfdb338aa3
+                            unattended_file = unattended/win2003-32.sif
+                            floppy = images/win2003-32/answer.vfd
+                        whql.submission:
+                            desc_path_desc1 = $\WDK\Logo Type\Device Logo\Windows Server 2003
+                            dd_data_logoarch = X86
+                            dd_data_logoos = Windows Server 2003
+                            dd_data_whqlos = Windows Server 2003
+                            device:
+                                dd_data_whqlqual = Basic
+                            device.net:
+                                image_name_supportvm = win2003-32-supportvm
+
+                    - 64:
+                        image_name += -64
+                        install:
+                            cdrom_cd1 = isos/windows/en_win_srv_2003_r2_enterprise_x64_with_sp2_cd1_x13-06188.iso
+                            md5sum_cd1 = 09f4cb31796e9802dcc477e397868c9a
+                            md5sum_1m_cd1 = c11ebcf6c128d94c83fe623566eb29d7
+                            sha1sum_cd1 = d04c8f304047397be486c38a6b769f16993d4b39
+                            sha1sum_1m_cd1 = 3daf6fafda8ba48779df65e4713a3cdbd6c9d136
+                            #cdrom_cd1 = isos/windows/Windows2003-x64.iso
+                            #md5sum_cd1 = 5703f87c9fd77d28c05ffadd3354dbbd
+                            #md5sum_1m_cd1 = 439393c384116aa09e08a0ad047dcea8
+                            user = user
+                            steps = Win2003-64.steps
+                        setup:
+                            steps = Win2003-64-rss.steps
+                        unattended_install.cdrom, whql.support_vm_install:
+                            cdrom_cd1 = isos/windows/en_win_srv_2003_r2_enterprise_x64_with_sp2_cd1_x13-06188.iso
+                            md5sum_cd1 = 09f4cb31796e9802dcc477e397868c9a
+                            md5sum_1m_cd1 = c11ebcf6c128d94c83fe623566eb29d7
+                            sha1sum_cd1 = d04c8f304047397be486c38a6b769f16993d4b39
+                            sha1sum_1m_cd1 = 3daf6fafda8ba48779df65e4713a3cdbd6c9d136
+                            #cdrom_cd1 = isos/windows/Windows2003-x64.iso
+                            #md5sum_cd1 = 5703f87c9fd77d28c05ffadd3354dbbd
+                            #md5sum_1m_cd1 = 439393c384116aa09e08a0ad047dcea8
+                            unattended_file = unattended/win2003-64.sif
+                            floppy = images/win2003-64/answer.vfd
+                        whql.submission:
+                            desc_path_desc1 = $\WDK\Logo Type\Device Logo\Windows Server 2003
+                            dd_data_logoarch = AMD64
+                            dd_data_logoos = Windows Server 2003
+                            dd_data_whqlos = Windows Server 2003 x64
+                            device:
+                                dd_data_whqlqual = Basic
+                            device.net:
+                                image_name_supportvm = win2003-64-supportvm
+
+            - WinVista:
+                os_variant = vista
+                image_name = winvista
+                image_size = 20G
+                whql.submission:
+                    desc_path_desc1 = $\WDK\Logo Type\Device Logo\Vista Client\Device Premium
+                    desc_path_desc2 = $\WDK\Logo Type\Device Logo\Vista Client\Device Standard
+                    desc_path_desc3 = $\WDK\Logo Type\Device Logo\Vista Client
+
+                variants:
+                    - 32:
+                        whql.submission:
+                            dd_data_logoarch = X86
+                            dd_data_logoos = Windows Vista
+                            dd_data_whqlos = Windows Vista Client
+                            device:
+                                dd_data_whqlqual = Premium
+                        variants:
+                            - sp1:
+                                image_name += -sp1-32
+                                install:
+                                    cdrom_cd1 = isos/windows/WindowsVista-32.iso
+                                    md5sum_cd1 = 1008f323d5170c8e614e52ccb85c0491
+                                    md5sum_1m_cd1 = c724e9695da483bc0fd59e426eaefc72
+                                    steps = Win-Vista-32.steps
+                                setup:
+                                    steps = WinVista-32-rss.steps
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/WindowsVista-32.iso
+                                    md5sum_cd1 = 1008f323d5170c8e614e52ccb85c0491
+                                    md5sum_1m_cd1 = c724e9695da483bc0fd59e426eaefc72
+                                    unattended_file = unattended/winvista-32-autounattend.xml
+                                    floppy = images/winvista-sp1-32/answer.vfd
+                                whql.submission.device.net:
+                                    image_name_supportvm = winvista-sp1-32-supportvm
+
+                            - sp2:
+                                image_name += -sp2-32
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/en_windows_vista_with_sp2_x86_dvd_342266.iso
+                                    md5sum_cd1 = 19ca90a425667812977bab6f4ce24175
+                                    md5sum_1m_cd1 = 89c15020e0e6125be19acf7a2e5dc614
+                                    sha1sum_cd1 = 25ad9a776503e6a583bec07879dbcc5dfd20cd6e
+                                    sha1sum_1m_cd1 = a2afa4cffdc1c362dbf9e62942337f4f875a22cf
+                                    unattended_file = unattended/winvista-32-autounattend.xml
+                                    floppy = images/winvista-sp2-32/answer.vfd
+                                whql.submission.device.net:
+                                    image_name_supportvm = winvista-sp2-32-supportvm
+
+                    - 64:
+                        whql.submission:
+                            dd_data_logoarch = AMD64
+                            dd_data_logoos = Windows Vista
+                            dd_data_whqlos = Windows Vista Client x64
+                            device:
+                                dd_data_whqlqual = Premium
+                        variants:
+                            - sp1:
+                                image_name += -sp1-64
+                                install:
+                                    cdrom_cd1 = isos/windows/WindowsVista-64.iso
+                                    md5sum_cd1 = 11e2010d857fffc47813295e6be6d58d
+                                    md5sum_1m_cd1 = 0947bcd5390546139e25f25217d6f165
+                                    steps = Win-Vista-64.steps
+                                setup:
+                                    steps = WinVista-64-rss.steps
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/WindowsVista-64.iso
+                                    md5sum_cd1 = 11e2010d857fffc47813295e6be6d58d
+                                    md5sum_1m_cd1 = 0947bcd5390546139e25f25217d6f165
+                                    unattended_file = unattended/winvista-64-autounattend.xml
+                                    floppy = images/winvista-sp1-64/answer.vfd
+                                whql.submission.device.net:
+                                    image_name_supportvm = winvista-sp1-64-supportvm
+
+                            - sp2:
+                                image_name += -sp2-64
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/en_windows_vista_sp2_x64_dvd_342267.iso
+                                    md5sum_cd1 = a1c024d7abaf34bac3368e88efbc2574
+                                    md5sum_1m_cd1 = 3d84911a80f3df71d1026f7adedc2181
+                                    sha1sum_cd1 = aaee3c04533899f9f8c4ae0c4250ef5fafbe29a3
+                                    sha1sum_1m_cd1 = 1fd21bd3ce2a4de8856c7b8fe6fdf80260f6d1c7
+                                    unattended_file = unattended/winvista-64-autounattend.xml
+                                    floppy = images/winvista-sp2-64/answer.vfd
+                                whql.submission.device.net:
+                                    image_name_supportvm = winvista-sp2-64-supportvm
+
+            - Win2008:
+                no whql
+                os_variant = win2k8
+                image_name = win2008
+                image_size = 20G
+
+                variants:
+                    - 32:
+                        variants:
+                            - sp1:
+                                image_name += -sp1-32
+                                install:
+                                    cdrom_cd1 = isos/windows/Windows2008-x86.iso
+                                    #en_windows_server_2008_datacenter_enterprise_standard_x86_dvd_X14-26710.iso
+                                    md5sum_cd1 = 0bfca49f0164de0a8eba236ced47007d
+                                    md5sum_1m_cd1 = 07d7f5006393f74dc76e6e2e943e2440
+                                    sha1sum_cd1 = 6ca018ff96f1e9b2b310a36546b6fded99a421e6
+                                    steps = Win2008-32.steps
+                                setup:
+                                    steps = Win2008-32-rss.steps
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/Windows2008-x86.iso
+                                    md5sum_cd1 = 0bfca49f0164de0a8eba236ced47007d
+                                    md5sum_1m_cd1 = 07d7f5006393f74dc76e6e2e943e2440
+                                    unattended_file = unattended/win2008-32-autounattend.xml
+                                    floppy = images/win2008-sp1-32/answer.vfd
+
+                            - sp2:
+                                image_name += -sp2-32
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/en_windows_server_2008_datacenter_enterprise_standard_sp2_x86_dvd_342333.iso
+                                    md5sum_cd1 = b9201aeb6eef04a3c573d036a8780bdf
+                                    md5sum_1m_cd1 = b7a9d42e55ea1e85105a3a6ad4da8e04
+                                    sha1sum_cd1 = 49d0d6917c1256fe81048d414fa473bbc76a8724
+                                    sha1sum_1m_cd1 = 9662ff7ed715faa00407e4befc484ea52a92a9fb
+                                    unattended_file = unattended/win2008-32-autounattend.xml
+                                    floppy = images/win2008-sp2-32/answer.vfd
+
+                    - 64:
+                        variants:
+                            -sp1:
+                                image_name += -sp1-64
+                                install:
+                                    steps = Win2008-64.steps
+                                    cdrom_cd1 = isos/windows/Windows2008-x64.iso
+                                    #en_windows_server_2008_datacenter_enterprise_standard_x64_dvd_X14-26714.iso
+                                    md5sum_cd1 = 27c58cdb3d620f28c36333a5552f271c
+                                    md5sum_1m_cd1 = efdcc11d485a1ef9afa739cb8e0ca766
+                                    sha1sum_cd1 = bd000374709f67e9358814db6ec8f0ddaaa16f70
+                                    passwd = 1q2w3eP
+                                setup:
+                                    steps = Win2008-64-rss.steps
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/Windows2008-x64.iso
+                                    md5sum_cd1 = 27c58cdb3d620f28c36333a5552f271c
+                                    md5sum_1m_cd1 = efdcc11d485a1ef9afa739cb8e0ca766
+                                    unattended_file = unattended/win2008-64-autounattend.xml
+                                    floppy = images/win2008-sp1-64/answer.vfd
+
+                            - sp2:
+                                image_name += -sp2-64
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/en_windows_server_2008_datacenter_enterprise_standard_sp2_x64_dvd_342336.iso
+                                    md5sum_cd1 = e94943ef484035b3288d8db69599a6b5
+                                    md5sum_1m_cd1 = ee55506823d0efffb5532ddd88a8e47b
+                                    sha1sum_cd1 = 34c7d726c57b0f8b19ba3b40d1b4044c15fc2029
+                                    sha1sum_1m_cd1 = 8fe08b03e3531906855a60a78020ac9577dff5ba
+                                    unattended_file = unattended/win2008-64-autounattend.xml
+                                    floppy = images/win2008-sp2-64/answer.vfd
+
+                            - r2:
+                                image_name += -r2-64
+                                unattended_install.cdrom, whql.support_vm_install:
+                                    cdrom_cd1 = isos/windows/en_windows_server_2008_r2_standard_enterprise_datacenter_and_web_x64_dvd_x15-59754.iso
+                                    md5sum_cd1 = 0207ef392c60efdda92071b0559ca0f9
+                                    md5sum_1m_cd1 = a5a22ce25008bd7109f6d830d627e3ed
+                                    sha1sum_cd1 = ad855ea913aaec3f1d0e1833c1aef7a0de326b0a
+                                    sha1sum_1m_cd1 = 9194a3aabae25b36e5f73cad001314b2c8d07d14
+                                    unattended_file = unattended/win2008-r2-autounattend.xml
+                                    floppy = images/win2008-r2-64/answer.vfd
+
+            - Win7:
+                os_variant = win7
+                image_name = win7
+                image_size = 20G
+                whql.submission:
+                    desc_path_desc1 = $\WDK\Logo Type\Device Logo\Windows 7 Client\Logo
+                    desc_path_desc2 = $\WDK\Logo Type\Device Logo\Windows 7 Client
+                    device_data += " adq"
+                    dd_name_adq = AdditionalQualificationGroup
+                    dd_data_adq = Windows 7
+
+                variants:
+                    - 32:
+                        image_name += -32
+                        unattended_install.cdrom, whql.support_vm_install:
+                            cdrom_cd1 = isos/windows/en_windows_7_ultimate_x86_dvd_x15-65921.iso
+                            md5sum_cd1 = d0b8b407e8a3d4b75ee9c10147266b89
+                            md5sum_1m_cd1 = 2b0c2c22b1ae95065db08686bf83af93
+                            sha1sum_cd1 = 5395dc4b38f7bdb1e005ff414deedfdb16dbf610
+                            sha1sum_1m_cd1 = 9f9c3780aebeb28a9bf22188eed6bc15475dc9c5
+                            unattended_file = unattended/win7-32-autounattend.xml
+                            floppy = images/win7-32/answer.vfd
+                        whql.submission:
+                            dd_data_logoarch = X86
+                            dd_data_logoos = Windows 7
+                            dd_data_whqlos = Windows 7 Client
+                            device:
+                                dd_data_whqlqual = Logo
+                            device.net:
+                                image_name_supportvm = win7-32-supportvm
+
+                    - 64:
+                        image_name += -64
+                        install:
+                            cdrom_cd1 = isos/windows/en_windows_7_ultimate_x64_dvd_x15-65922.iso
+                            md5sum_cd1 = f43d22e4fb07bf617d573acd8785c028
+                            md5sum_1m_cd1 = b44d8cf99dbed2a5cb02765db8dfd48f
+                            passwd = 1q2w3eP
+                            steps = Win7-64.steps
+                        setup:
+                            steps = Win7-64-rss.steps
+                        unattended_install.cdrom, whql.support_vm_install:
+                            cdrom_cd1 = isos/windows/en_windows_7_ultimate_x64_dvd_x15-65922.iso
+                            md5sum_cd1 = f43d22e4fb07bf617d573acd8785c028
+                            md5sum_1m_cd1 = b44d8cf99dbed2a5cb02765db8dfd48f
+                            sha1sum_cd1 = 326327cc2ff9f05379f5058c41be6bc5e004baa7
+                            sha1sum_1m_cd1 = 4a3903bd5157de54f0702e5263e0a683c5775515
+                            unattended_file = unattended/win7-64-autounattend.xml
+                            floppy = images/win7-64/answer.vfd
+                        whql.submission:
+                            dd_data_logoarch = AMD64
+                            dd_data_logoos = Windows 7
+                            dd_data_whqlos = Windows 7 Client x64
+                            device:
+                                dd_data_whqlqual = Logo
+                            device.net:
+                                image_name_supportvm = win7-64-supportvm
+
+
+    # Unix/BSD section
+    - @Unix:
+        only install
+        kill_vm = yes
+        kill_vm_gracefully = no
+        kill_vm_timeout = 0
+
+        variants:
+            - NetBSD-1.6.2:
+                image_name = NetBSD-1.6.2
+                image_size = 4G
+                steps = NetBSD-1.6.2.steps
+                cdrom_cd1 = isos/bsd/netbsd-1.6.2-i386.iso
+                md5sum_cd1 = 72eb680300f77d529bfbc880ba8208f3
+                md5sum_1m_cd1 = f1a9e1e825c90adfb1be35c6177bd9ac
+
+            - OpenBSD-4.1:
+                image_name = OpenBSD-4.1
+                steps = OpenBSD-4.1-32.steps
+                cdrom_cd1 = isos/unix/openbsd41-i386-07-05-06.iso
+                md5sum_cd1 = 984790db10ebdd6fc7a9cf97abc7c967
+                md5sum_1m_cd1 = 8fc234b4b0ecfe56843a32ac1d26ed55
+
+    # Live CD section
+    - @livecd:
+        only install
+        kill_vm = yes
+        kill_vm_gracefully = no
+        kill_vm_timeout = 0
+
+        variants:
+            - Belenix:
+                steps = Belenix-0.7.1.steps
+                cdrom_cd1 = isos/unix/belenix_0.7.1.iso
+                md5sum_cd1 = 29cea6160cf5250de138e2820e53e342
+                md5sum_1m_cd1 = 427bbef1b85d6d051799b825d686ae94
+
+            - Slax:
+                steps = Slax-6.0.7.steps
+                cdrom_cd1 = isos/linux/slax-6.0.7.iso
+                md5sum_cd1 = cde0ecba3c8289d786e12c44666ded6e
+                md5sum_1m_cd1 = ddf02bc7444f22d1160a6e5a8fc8723f
+
+            - FreeSBIE-2.0.1:
+                steps = FreeSBIE-2.0.1.steps
+                cdrom_cd1 = isos/unix/FreeSBIE-2.0.1-RELEASE.iso
+                md5sum_cd1 = b2f680d27c21bbfaf4fb90dce090a118
+                md5sum_1m_cd1 = 4d81ee7fe0101b0a14225963bfff60c1
+
+            - memtest:
+                mem = 128
+                steps = memtest86+.steps
+                cdrom_cd1 = isos/misc/memtest86+-2.01.iso
+                md5sum_cd1 = 9fae22f2666369968a76ef59e9a81ced
+
+
+whql.support_vm_install, whql.client_install.support_vm:
+    image_name += -supportvm
+
+
+variants:
+    - @up:
+        no autotest.npb autotest.tsc
+    - smp2:
+        smp = 2
+        used_cpus = 2
+        stress_boot: used_cpus = 10
+        timedrift.with_load: used_cpus = 100
+
+
+variants:
+    - @ide:
+        drive_format=ide
+    - scsi:
+        drive_format=scsi
+    - virtio_blk:
+        drive_format=virtio
+        # Some older qemu might need image_boot=yes for virtio images to work.
+        # Please uncomment the below if that is the case.
+        #image_boot=yes
+    - ahci:
+        drive_format=ahci
+        cd_format=ahci
+    - usb.stick:
+        drive_format=usb2
+    - usb.cdrom:
+        cd_format=usb2
+
+
+virtio_net, virtio_blk, e1000, balloon_check:
+    # Only excluding the OS that we *know* they won't have the drivers installed
+    # Some might require special setup though.
+    no Win2000, Fedora.8, Fedora.9, Fedora.10, RHEL.3, Unix, livecd
+
+kdump, watchdog:
+    only RHEL.5 RHEL.6
+
+variants:
+    - @qcow2:
+        image_format = qcow2
+        check_image = yes
+    - vmdk:
+        no ioquit
+        image_format = vmdk
+    - raw:
+        no ioquit
+        image_format = raw
+
+
+variants:
+    - @smallpages:
+    - hugepages:
+        setup_hugepages = yes
+        domain_xml_snippet = "<memoryBacking><hugepages/></memoryBacking>"
+
+
+variants:
+    - @no_pci_assignable:
+        pci_assignable = no
+    - pf_assignable:
+        pci_assignable = pf
+        device_names = eth1
+    - vf_assignable:
+        pci_assignable = vf
+        # Driver (kernel module) that supports SR-IOV hardware.
+        # As of today (30-11-2009), we have 2 drivers for this type of hardware:
+        # Intel® 82576 Gigabit Ethernet Controller - igb
+        # Neterion® X3100™ - vxge
+        driver = igb
+        # Driver option to specify the maximum number of virtual functions
+        # (on vxge the option is , for example, is max_config_dev)
+        # the default below is for the igb driver
+        driver_option = "max_vfs=7"
+        # Number of devices that are going to be requested.
+        devices_requested = 7
+
+
+steps ?<= steps/
diff --git a/client/tests/libvirt/virtio-win.cfg.sample b/client/tests/libvirt/virtio-win.cfg.sample
new file mode 100644
index 0000000..ce1bcf4
--- /dev/null
+++ b/client/tests/libvirt/virtio-win.cfg.sample
@@ -0,0 +1,235 @@
+# Copy this file to virtio-win.cfg and edit it.
+# This file intends to be a central point of configuration for folks wanting
+# to install windows virtio drivers on windows guests
+
+# A bit of context on windows virtio drivers install
+# --------------------------------------------------
+# This method of install so far covers the storage (viostor) and network
+# (NetKVM) drivers. KVM autotest uses a boot floppy with a Windows answer
+# file in order to perform unattended install of windows guests. For winXP
+# and win2003, the unattended files are simple .ini files, while for win2008
+# and later, the unattended files are XML files.
+#
+# In order to install the virtio drivers during guest install, KVM autotest
+# has to inform the windows install programs *where* to find the drivers. So,
+# we work from the following assumptions:
+#
+# * You already have an iso file that contains windows virtio drivers
+# (inf files) for both netkvm and viostor. If you are unsure how to generate
+# that iso, there's an example script under contrib, inside the kvm test
+# directory. If you take a look at the files inside this iso image, a small
+# part of them should look like:
+#
+# ./wxp/x86/viostor.cat
+# ./wxp/x86/viostor.inf
+# ./wxp/x86/viostor.pdb
+# ./wxp/x86/viostor.sys
+#
+# * If you are planning on installing WinXP or Win2003, you should also have
+# a pre-made floppy disk image with the virtio drivers *and* a configuration
+# file that the installer program will read to fetch the right drivers from it.
+# Unfortunately, I don't have much info on how to build that file, you probably
+# would have the image already assembled if you are willing to test those guest
+# OS.
+#
+# So you have to map the paths of your cd containing the drivers on the config
+# variables. More details below.
+
+Windows:
+    unattended_install.cdrom, whql.support_vm_install:
+        # In order to enable drivers install, turn the below to 'yes'
+        install_virtio = no
+
+        # In order to enable drivers install, uncomment the assignment lines
+        # below.
+
+        # This makes the vm to be started with the virtio iso file as an extra
+        # cdrom drive
+        #cdroms += " virtio"
+
+        # This assumes the virtio iso will be at (/tmp/kvm_autotest_root/isos)
+        #cdrom_virtio = isos/virtio-win.iso
+
+        # This ensures the iso will appear to the guest as F:
+        #drive_index_virtio = 3
+
+        # This assumes the virtio floppy will be at (/tmp/kvm_autotest_root/)
+        # This floppy is needed only if you desire to test virtio drivers
+        # install for WinXP and Win2003. If you don't, you can leave the line
+        # below uncommented
+        #virtio_floppy = virtio-drivers.vfd
+
+    WinXP:
+        32:
+            unattended_install.cdrom, whql.support_vm_install:
+                # This is a label used on the oemsetup.ini file, inside your
+                # virtio floppy. You might actually want to check what are
+                # the labels on yours
+                virtio_oemsetup_id = WXP32
+
+                # Look at your cd structure and see where the drivers are
+                # actually located
+                virtio_network_path = 'F:\xp\x86'
+
+                # Uncomment if you have a nw driver installer on the iso
+                #virtio_network_installer_path = 'F:\RHEV-Network32.msi'
+
+        64:
+            unattended_install.cdrom, whql.support_vm_install:
+                # This is a label used on the oemsetup.ini file, inside your
+                # virtio floppy. You might actually want to check what are
+                # the labels on yours
+                virtio_oemsetup_id = WNET64
+
+                # Look at your cd structure and see where the drivers are
+                # actually located
+                virtio_network_path = 'F:\xp\amd64'
+
+                # Uncomment if you have a nw driver installer on the iso
+                #virtio_network_installer_path = 'F:\RHEV-Network64.msi'
+
+    Win2003:
+        32:
+            unattended_install.cdrom, whql.support_vm_install:
+                # This is a label used on the oemsetup.ini file, inside your
+                # virtio floppy. You might actually want to check what are
+                # the labels on yours
+                virtio_oemsetup_id = WNET32
+
+                # Look at your cd structure and see where the drivers are
+                # actually located
+                virtio_network_path = 'F:\xp\x86'
+
+                # Uncomment if you have a nw driver installer on the iso
+                #virtio_network_installer_path = 'F:\RHEV-Network32.msi'
+
+        64:
+            unattended_install.cdrom, whql.support_vm_install:
+                # This is a label used on the oemsetup.ini file, inside your
+                # virtio floppy. You might actually want to check what are
+                # the labels on yours
+                virtio_oemsetup_id = WNET64
+
+                # Look at your cd structure and see where the drivers are
+                # actually located
+                virtio_network_path = 'F:\xp\amd64'
+
+                # Uncomment if you have a nw driver installer on the iso
+                #virtio_network_installer_path = 'F:\RHEV-Network64.msi'
+
+    WinVista:
+        32:
+            sp1:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\x86'
+                    virtio_network_path = 'F:\vista\x86'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network32.msi'
+
+            sp2:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\x86'
+                    virtio_network_path = 'F:\vista\x86'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network32.msi'
+
+        64:
+            sp1:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\amd64'
+                    virtio_network_path = 'F:\vista\amd64'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network64.msi'
+
+            sp2:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\amd64'
+                    virtio_network_path = 'F:\vista\amd64'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network64.msi'
+
+    Win2008:
+        32:
+            sp1:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\x86'
+                    virtio_network_path = 'F:\vista\x86'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network32.msi'
+
+            sp2:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\x86'
+                    virtio_network_path = 'F:\vista\x86'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network32.msi'
+
+        64:
+            sp1:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\amd64'
+                    virtio_network_path = 'F:\vista\amd64'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network64.msi'
+
+            sp2:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\amd64'
+                    virtio_network_path = 'F:\vista\amd64'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network64.msi'
+
+            r2:
+                unattended_install.cdrom, whql.support_vm_install:
+                    # Look at your cd structure and see where the drivers are
+                    # actually located (viostor and netkvm)
+                    virtio_storage_path = 'F:\win7\amd64'
+                    virtio_network_path = 'F:\vista\amd64'
+
+                    # Uncomment if you have a nw driver installer on the iso
+                    #virtio_network_installer_path = 'F:\RHEV-Network64.msi'
+
+    Win7:
+        32:
+            unattended_install.cdrom, whql.support_vm_install:
+                # Look at your cd structure and see where the drivers are
+                # actually located (viostor and netkvm)
+                virtio_storage_path = 'F:\win7\x86'
+                virtio_network_path = 'F:\vista\x86'
+
+                # Uncomment if you have a nw driver installer on the iso
+                #virtio_network_installer_path = 'F:\RHEV-Network32.msi'
+
+        64:
+            unattended_install.cdrom, whql.support_vm_install:
+                # Look at your cd structure and see where the drivers are
+                # actually located (viostor and netkvm)
+                virtio_storage_path = 'F:\win7\amd64'
+                virtio_network_path = 'F:\vista\amd64'
+
+                # Uncomment if you have a nw driver installer on the iso
+                #virtio_network_installer_path = 'F:\RHEV-Network64.msi'
-- 
1.7.6.4

_______________________________________________
Autotest mailing list
Autotest@test.kernel.org
http://test.kernel.org/cgi-bin/mailman/listinfo/autotest

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 09/11] Virt: builtin HTTP server for unattended installs
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
                   ` (6 preceding siblings ...)
  2011-10-11 21:07 ` [PATCH 08/11] client.tests: Introducing libvirt test Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 10/11] Virt: support XEN via libvirt and auto url installer Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 11/11] Virt: add support for XEN via libvirt installs and auto url Lucas Meneghel Rodrigues
  9 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

From: Cleber Rosa <crosa@redhat.com>

This adds a simple HTTP server that is good enought to support unattended
installs. Tested serving kickstart files and RHEL/Fedora content to
anaconda.

Signed-off-by: Cleber Rosa <crosa@redhat.com>
---
 client/virt/virt_http_server.py |  124 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 124 insertions(+), 0 deletions(-)
 create mode 100644 client/virt/virt_http_server.py

diff --git a/client/virt/virt_http_server.py b/client/virt/virt_http_server.py
new file mode 100644
index 0000000..286285a
--- /dev/null
+++ b/client/virt/virt_http_server.py
@@ -0,0 +1,124 @@
+import os, posixpath, urlparse, urllib, logging
+import BaseHTTPServer, SimpleHTTPServer
+
+
+class HTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+
+    def do_GET(self):
+        """
+        Serve a GET request.
+        """
+        range = self.parse_header_byte_range()
+        if range:
+            f = self.send_head_range(range[0], range[1])
+            if f:
+                self.copyfile_range(f, self.wfile, range[0], range[1])
+                f.close()
+        else:
+            f = self.send_head()
+            if f:
+                self.copyfile(f, self.wfile)
+                f.close()
+
+
+    def parse_header_byte_range(self):
+        range_param = 'Range'
+        range_discard = 'bytes='
+        if self.headers.has_key(range_param):
+            range = self.headers.get(range_param)
+            if range.startswith(range_discard):
+                range = range[len(range_discard):]
+                begin, end = range.split('-')
+                return (int(begin), int(end))
+        return None
+
+
+    def copyfile_range(self, source_file, output_file, range_begin, range_end):
+        """
+        Copies a range of a file to destination.
+        """
+        range_size = range_end - range_begin + 1
+        source_file.seek(range_begin)
+        buf = source_file.read(range_size)
+        output_file.write(buf)
+
+
+    def send_head_range(self, range_begin, range_end):
+        path = self.translate_path(self.path)
+        f = None
+        if os.path.isdir(path):
+            for index in "index.html", "index.htm":
+                index = os.path.join(path, index)
+                if os.path.exists(index):
+                    path = index
+                    break
+            else:
+                return self.list_directory(path)
+        ctype = self.guess_type(path)
+        try:
+            # Always read in binary mode. Opening files in text mode may cause
+            # newline translations, making the actual size of the content
+            # transmitted *less* than the content-length!
+            f = open(path, 'rb')
+        except IOError:
+            self.send_error(404, "File not found")
+            return None
+        self.send_response(206, "Partial Content")
+        file_size = str(os.fstat(f.fileno())[6])
+        range_size = str(range_end - range_begin + 1)
+        self.send_header("Accept-Ranges", "bytes")
+        self.send_header("Content-Length", range_size)
+        self.send_header("Content-Range", "bytes %s-%s/%s" % (range_begin,
+                                                              range_end,
+                                                              file_size))
+        self.send_header("Content-type", ctype)
+        self.end_headers()
+        return f
+
+
+    def translate_path(self, path):
+        """
+        Translate a /-separated PATH to the local filename syntax.
+
+        Components that mean special things to the local file system
+        (e.g. drive or directory names) are ignored.  (XXX They should
+        probably be diagnosed.)
+
+        """
+        # abandon query parameters
+        path = urlparse.urlparse(path)[2]
+        path = posixpath.normpath(urllib.unquote(path))
+        words = path.split('/')
+        words = filter(None, words)
+        path = self.server.cwd
+        for word in words:
+            drive, word = os.path.splitdrive(word)
+            head, word = os.path.split(word)
+            if word in (os.curdir, os.pardir): continue
+            path = os.path.join(path, word)
+        return path
+
+
+    def log_message(self, format, *args):
+        logging.debug("builtin http server handling request from %s: %s" %
+                      (self.address_string(), format%args))
+
+
+def http_server(port=8000, cwd=None, terminate_callable=None):
+    http = BaseHTTPServer.HTTPServer(('', port), HTTPRequestHandler)
+    if cwd is None:
+        cwd = os.getcwd()
+    http.cwd = cwd
+
+    while True:
+        if terminate_callable is not None:
+            terminate = terminate_callable()
+        else:
+            terminate = False
+
+        if not terminate:
+            http.handle_request()
+
+
+if __name__ == '__main__':
+    http_server()
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 10/11] Virt: support XEN via libvirt and auto url installer
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
                   ` (7 preceding siblings ...)
  2011-10-11 21:07 ` [PATCH 09/11] Virt: builtin HTTP server for unattended installs Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  2011-10-11 21:07 ` [PATCH 11/11] Virt: add support for XEN via libvirt installs and auto url Lucas Meneghel Rodrigues
  9 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

From: Cleber Rosa <crosa@redhat.com>

This patchs adds proper detection of active (alive) XEN domains via libvirt;
a quick way to determine whether the current connected hypervisor is XEN or
QEMU/KVM and also deals with virt-install options and syntax supported on
RHEL 5 libvirt+XEN.

Signed-off-by: Cleber Rosa <crosa@redhat.com>
---
 client/virt/libvirt_vm.py |   54 ++++++++++++++++++++++++++++----------------
 1 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/client/virt/libvirt_vm.py b/client/virt/libvirt_vm.py
index bed512f..e536b5b 100644
--- a/client/virt/libvirt_vm.py
+++ b/client/virt/libvirt_vm.py
@@ -104,8 +104,8 @@ def virsh_is_dead(name):
 
     @param name: VM name
     """
-    if (virsh_domstate(name) == 'running' or
-        virsh_domstate(name) == 'idle'):
+    state = virsh_domstate(name)
+    if state in ('running', 'idle', 'no state'):
         return False
     else:
         return True
@@ -250,6 +250,15 @@ def virsh_domain_exists(name):
         logging.warning("VM %s does not exist", name)
         return False
 
+VIRSH_DEFAULT_URI = virsh_uri()
+LIBVIRT_QEMU = False
+LIBVIRT_XEN = False
+
+if VIRSH_DEFAULT_URI == 'qemu:///system':
+    LIBVIRT_QEMU = True
+elif VIRSH_DEFAULT_URI == 'xen:///':
+    LIBVIRT_XEN = True
+
 
 class VM(virt_vm.BaseVM):
     """
@@ -410,7 +419,6 @@ class VM(virt_vm.BaseVM):
             return " --vcpu=%s" % smp
 
         def add_location(help, location):
-            #return " --location %s" % location
             if has_option(help, "location"):
                 return " --location %s" % location
             else:
@@ -563,7 +571,9 @@ class VM(virt_vm.BaseVM):
         # TODO: directory location for vmlinuz/kernel for cdrom install ?
         location = None
         if params.get("medium") == 'url':
-            location = params.get("url")
+            if params.get("url") == 'auto':
+                location = params.get('auto_content_url')
+
         elif params.get("medium") == 'kernel_initrd':
             # directory location of kernel/initrd pair (directory layout must
             # be in format libvirt will recognize)
@@ -634,19 +644,20 @@ class VM(virt_vm.BaseVM):
                                   image_params.get("drive_cache"),
                                   image_params.get("image_format"))
 
-        for cdrom in params.objects("cdroms"):
-            cdrom_params = params.object_params(cdrom)
-            iso = cdrom_params.get("cdrom")
-            if params.get("use_libvirt_cdrom_switch") == 'yes':
-                # we don't want to skip the winutils iso
-                if not cdrom == 'winutils':
-                    logging.debug("Using --cdrom instead of --disk for install")
-                    logging.debug("Skipping CDROM:%s:%s", cdrom, iso)
-                    continue
-            if params.get("medium") == 'cdrom_no_kernel_initrd':
-                if iso == params.get("cdrom_cd1"):
-                    logging.debug("Using cdrom or url for install")
-                    logging.debug("Skipping CDROM: %s", iso)
+        if LIBVIRT_QEMU:
+            for cdrom in params.objects("cdroms"):
+                cdrom_params = params.object_params(cdrom)
+                iso = cdrom_params.get("cdrom")
+                if params.get("use_libvirt_cdrom_switch") == 'yes':
+                    # we don't want to skip the winutils iso
+                    if not cdrom == 'winutils':
+                        logging.debug("Using --cdrom instead of --disk for install")
+                        logging.debug("Skipping CDROM:%s:%s", cdrom, iso)
+                        continue
+                if params.get("medium") == 'cdrom_no_kernel_initrd':
+                    if iso == params.get("cdrom_cd1"):
+                        logging.debug("Using cdrom or url for install")
+                        logging.debug("Skipping CDROM: %s", iso)
                     continue
 
             if iso:
@@ -685,9 +696,12 @@ class VM(virt_vm.BaseVM):
             virt_install_cmd += " --mac %s" % mac
             self.nic_mac = mac
 
-        virt_install_cmd += (" --network %s,model=%s" %
-                             (params.get("virsh_network"),
-                              params.get("nic_model")))
+        if LIBVIRT_XEN:
+            virt_install_cmd += (" --network=%s" % params.get("virsh_network"))
+        elif LIBVIRT_QEMU:
+            virt_install_cmd += (" --network=%s,model=%s" %
+                                 (params.get("virsh_network"),
+                                  params.get("nic_model")))
 
         if params.get("use_no_reboot") == "yes":
             virt_install_cmd += " --noreboot"
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 11/11] Virt: add support for XEN via libvirt installs and auto url
  2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
                   ` (8 preceding siblings ...)
  2011-10-11 21:07 ` [PATCH 10/11] Virt: support XEN via libvirt and auto url installer Lucas Meneghel Rodrigues
@ 2011-10-11 21:07 ` Lucas Meneghel Rodrigues
  9 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-11 21:07 UTC (permalink / raw)
  To: autotest; +Cc: kvm

From: Cleber Rosa <crosa@redhat.com>

This patch adds support to unattended installs via libvirt+XEN and
serving installation content via the auto url feature (using a
builtin http server).

A sample configuration is provided to run a Fedora 15 64 bits PV
based test (libvirt_xenpv_f15_quick).

Signed-off-by: Cleber Rosa <crosa@redhat.com>
---
 client/tests/libvirt/tests.cfg.sample      |   15 ++
 client/tests/libvirt/tests_base.cfg.sample |    7 +
 client/virt/tests/unattended_install.py    |  197 +++++++++++++++++++++++++---
 3 files changed, 203 insertions(+), 16 deletions(-)

diff --git a/client/tests/libvirt/tests.cfg.sample b/client/tests/libvirt/tests.cfg.sample
index a068587..8a1d318 100644
--- a/client/tests/libvirt/tests.cfg.sample
+++ b/client/tests/libvirt/tests.cfg.sample
@@ -38,6 +38,21 @@ variants:
         only Fedora.15.64
         only unattended_install.cdrom, boot, reboot, shutdown
 
+    # Runs virt-install, f15 64 as a 64 bit PV guest OS, install, boot, shutdown
+    - @libvirt_xenpv_f15_quick:
+        virt_install_binary = /usr/bin/virt-install
+        qemu_img_binary = /usr/bin/qemu-img
+        url = auto
+        cdrom_cd1 = isos/linux/Fedora-15-x86_64-DVD.iso
+        only raw
+        only xennet
+        only xenblk
+        only smp2
+        only no_pci_assignable
+        only smallpages
+        only Fedora.15.64
+        only unattended_install.url, boot, reboot, shutdown
+
     # Runs virt-install, RHEL 6.0 64 bit guest OS, install, boot, shutdown
     - @libvirt_rhel60_quick:
         virt_install_binary = /usr/bin/virt-install
diff --git a/client/tests/libvirt/tests_base.cfg.sample b/client/tests/libvirt/tests_base.cfg.sample
index f2a4e35..5fe8b01 100644
--- a/client/tests/libvirt/tests_base.cfg.sample
+++ b/client/tests/libvirt/tests_base.cfg.sample
@@ -90,6 +90,9 @@ use_os_variant = no
 use_os_type = yes
 # libvirt network to use examples network=default or bridge=br0
 virsh_network = network=default
+# if using 'url = auto' to install, url_auto_ip must match IP on
+# selected virsh network or bridge
+url_auto_ip = 192.168.122.1
 # wait in minutes for virt-install to finish (bz still open)
 use_virt_install_wait = no
 virt_install_wait_time = 300  
@@ -1165,6 +1168,8 @@ variants:
             # Device selection for the NDISTest server machine
             dp_regex_servermsgdev = VirtIO Ethernet Adapter$
             dp_regex_serversupportdev = VirtIO Ethernet Adapter #2$
+    -xennet:
+        # placeholder
 
 # Guests
 variants:
@@ -2865,6 +2870,8 @@ variants:
         drive_format=usb2
     - usb.cdrom:
         cd_format=usb2
+    - xenblk:
+        # placeholder
 
 
 virtio_net, virtio_blk, e1000, balloon_check:
diff --git a/client/virt/tests/unattended_install.py b/client/virt/tests/unattended_install.py
index efa3c10..ea3e9f4 100644
--- a/client/virt/tests/unattended_install.py
+++ b/client/virt/tests/unattended_install.py
@@ -1,8 +1,45 @@
 import logging, time, socket, re, os, shutil, tempfile, glob, ConfigParser
+import threading
 import xml.dom.minidom
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
-from autotest_lib.client.virt import virt_vm, virt_utils
+from autotest_lib.client.virt import virt_vm, virt_utils, virt_http_server
+
+
+_url_auto_content_server_thread = None
+_url_auto_content_server_thread_event = None
+
+_unattended_server_thread = None
+_unattended_server_thread_event = None
+
+
+def terminate_auto_content_server_thread():
+    global _url_auto_content_server_thread
+    global _url_auto_content_server_thread_event
+
+    if _url_auto_content_server_thread is None:
+        return False
+    if _url_auto_content_server_thread_event is None:
+        return False
+
+    if _url_auto_content_server_thread_event.isSet():
+        return True
+
+    return False
+
+
+def terminate_unattended_server_thread():
+    global _unattended_server_thread, _unattended_server_thread_event
+
+    if _unattended_server_thread is None:
+        return False
+    if _unattended_server_thread_event is None:
+        return False
+
+    if  _unattended_server_thread_event.isSet():
+        return True
+
+    return False
 
 
 @error.context_aware
@@ -213,12 +250,13 @@ class UnattendedInstallConfig(object):
         root_dir = test.bindir
         self.deps_dir = os.path.join(test.virtdir, 'deps')
         self.unattended_dir = os.path.join(test.virtdir, 'unattended')
+        self.params = params
 
         attributes = ['kernel_args', 'finish_program', 'cdrom_cd1',
                       'unattended_file', 'medium', 'url', 'kernel', 'initrd',
                       'nfs_server', 'nfs_dir', 'install_virtio', 'floppy',
                       'cdrom_unattended', 'boot_path', 'extra_params',
-                      'qemu_img_binary', 'cdkey', 'finish_program']
+                      'qemu_img_binary', 'cdkey', 'finish_program', 'vm_type']
 
         for a in attributes:
             setattr(self, a, params.get(a, ''))
@@ -258,6 +296,14 @@ class UnattendedInstallConfig(object):
 
         self.image_path = os.path.dirname(self.kernel)
 
+        # Content server params
+        self.url_auto_content_ip = params.get('url_auto_ip', '192.168.122.1')
+        self.url_auto_content_port = None
+
+        # Kickstart server params
+        # use the same IP as url_auto_content_ip, but a different port
+        self.unattended_server_port = None
+
 
     def answer_kickstart(self, answer_path):
         """
@@ -278,7 +324,13 @@ class UnattendedInstallConfig(object):
         if self.medium in ["cdrom", "kernel_initrd"]:
             content = "cdrom"
         elif self.medium == "url":
-            content = "url --url %s" % self.url
+            if self.url == 'auto':
+                url = "http://%s:%s" % (self.url_auto_content_ip,
+                                        self.url_auto_content_port)
+            else:
+                url = self.url
+            content = "url --url %s" % url
+
         elif self.medium == "nfs":
             content = "nfs --server=%s --dir=%s" % (self.nfs_server,
                                                     self.nfs_dir)
@@ -407,6 +459,51 @@ class UnattendedInstallConfig(object):
         doc.writexml(fp)
 
 
+    def setup_unattended_http_server(self):
+        '''
+        Setup a builtin http server for serving the kickstart file
+
+        Does nothing if unattended file is not a kickstart file
+        '''
+        global _unattended_server_thread, _unattended_server_thread_event
+
+        if self.unattended_file.endswith('.ks'):
+            # Red Hat kickstart install
+            dest_fname = 'ks.cfg'
+
+            answer_path = os.path.join(self.tmpdir, dest_fname)
+            self.answer_kickstart(answer_path)
+
+            if self.unattended_server_port is None:
+                self.unattended_server_port = virt_utils.find_free_port(
+                    8000,
+                    8100,
+                    self.url_auto_content_ip)
+
+            if _unattended_server_thread is None:
+                _unattended_server_thread_event = threading.Event()
+                _unattended_server_thread = threading.Thread(
+                    target=virt_http_server.http_server,
+                    args=(self.unattended_server_port, self.tmpdir,
+                          terminate_unattended_server_thread))
+                _unattended_server_thread.start()
+
+        # Point installation to this kickstart url
+        ks_param = 'ks=http://%s:%s/%s' % (self.url_auto_content_ip,
+                                           self.unattended_server_port,
+                                           dest_fname)
+        if 'ks=' in self.extra_params:
+            extra_params = re.sub('ks\=[\w\d\:\.\/]+',
+                                  ks_param,
+                                  self.extra_params)
+        else:
+            extra_params += ' %s ' % ks_param
+
+        # reflect change on params
+        self.extra_params = extra_params
+        self.params['extra_params'] = self.extra_params
+
+
     def setup_boot_disk(self):
         if self.unattended_file.endswith('.sif'):
             dest_fname = 'winnt.sif'
@@ -497,24 +594,70 @@ class UnattendedInstallConfig(object):
 
 
     @error.context_aware
+    def setup_url_auto(self):
+        """
+        Configures the builtin web server for serving content
+        """
+        global _url_auto_content_server_thread
+        global _url_auto_content_server_thread_event
+
+        logging.debug("starting unattended content web server")
+
+        if self.params.get('cdrom_cd1'):
+            # setup and mount cdrom contents to be served by http server
+            m_cmd = ('mount -t iso9660 -v -o loop,ro %s %s' %
+                     (self.cdrom_cd1, self.cdrom_cd1_mount))
+            utils.run(m_cmd)
+
+        self.url_auto_content_port = virt_utils.find_free_port(
+            8000,
+            8100,
+            self.url_auto_content_ip)
+
+        if _url_auto_content_server_thread is None:
+            _url_auto_content_server_thread_event = threading.Event()
+            _url_auto_content_server_thread = threading.Thread(
+                target=virt_http_server.http_server,
+                args=(self.url_auto_content_port, self.cdrom_cd1_mount,
+                      terminate_auto_content_server_thread))
+            _url_auto_content_server_thread.start()
+
+        auto_content_url = 'http://%s:%s' % (self.url_auto_content_ip,
+                                             self.url_auto_content_port)
+        self.params['auto_content_url'] = auto_content_url
+
+
+    @error.context_aware
     def setup_url(self):
         """
         Download the vmlinuz and initrd.img from URL.
         """
-        error.context("downloading vmlinuz and initrd.img from %s" % self.url)
-        os.chdir(self.image_path)
-        kernel_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path,
-                                                 os.path.basename(self.kernel))
-        initrd_fetch_cmd = "wget -q %s/%s/%s" % (self.url, self.boot_path,
-                                                 os.path.basename(self.initrd))
+        # it's only necessary to download kernel/initrd if running bare qemu
+        if self.vm_type == 'kvm':
+            error.context("downloading vmlinuz/initrd.img from %s" % self.url)
+            os.chdir(self.image_path)
+            kernel_cmd = "wget -q %s/%s/%s" % (self.url,
+                                               self.boot_path,
+                                               os.path.basename(self.kernel))
+            initrd_cmd = "wget -q %s/%s/%s" % (self.url,
+                                               self.boot_path,
+                                               os.path.basename(self.initrd))
+
+            if os.path.exists(self.kernel):
+                os.remove(self.kernel)
+            if os.path.exists(self.initrd):
+                os.remove(self.initrd)
 
-        if os.path.exists(self.kernel):
-            os.remove(self.kernel)
-        if os.path.exists(self.initrd):
-            os.remove(self.initrd)
+            utils.run(kernel_fetch_cmd)
+            utils.run(initrd_fetch_cmd)
+
+        elif self.vm_type == 'libvirt':
+            error.context("not downloading vmlinuz/initrd.img from %s, "
+                          "letting virt-install do it instead")
 
-        utils.run(kernel_fetch_cmd)
-        utils.run(initrd_fetch_cmd)
+        else:
+            error.context("no action defined/needed for the current virt "
+                          "type: '%s'" % self.vm_type)
 
 
     def setup_nfs(self):
@@ -556,6 +699,9 @@ class UnattendedInstallConfig(object):
                 self.setup_cdrom()
         elif self.medium == "url":
             self.setup_url()
+            if self.url == 'auto':
+                self.setup_url_auto()
+                self.setup_unattended_http_server()
         elif self.medium == "nfs":
             self.setup_nfs()
         else:
@@ -577,7 +723,10 @@ def run_unattended_install(test, params, env):
     unattended_install_config = UnattendedInstallConfig(test, params)
     unattended_install_config.setup()
     vm = env.get_vm(params["main_vm"])
-    vm.create()
+
+    # params passed explicitly, because they may have been updated by
+    # unattended install config code, such as when params['url'] == auto
+    vm.create(params=params)
 
     install_timeout = int(params.get("timeout", 3000))
     port = vm.get_port(int(params.get("guest_port_unattended_install")))
@@ -620,6 +769,22 @@ def run_unattended_install(test, params, env):
         raise error.TestFail("Timeout elapsed while waiting for install to "
                              "finish")
 
+    logging.debug('cleaning up threads and mounts that may be active')
+    global _url_auto_content_server_thread
+    global _url_auto_content_server_thread_event
+    if _url_auto_content_server_thread is not None:
+        _url_auto_content_server_thread_event.set()
+        _url_auto_content_server_thread.join(3)
+        _url_auto_content_server_thread = None
+        cleanup(unattended_install_config.cdrom_cd1_mount)
+
+    global _unattended_server_thread
+    global _unattended_server_thread_event
+    if _unattended_server_thread is not None:
+        _unattended_server_thread_event.set()
+        _unattended_server_thread.join(3)
+        _unattended_server_thread = None
+
     time_elapsed = time.time() - start_time
     logging.info("Guest reported successful installation after %d s (%d min)",
                  time_elapsed, time_elapsed/60)
-- 
1.7.6.4

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [Autotest] [PATCH 05/11] virt: Introducing libvirt VM class
  2011-10-11 21:07 ` [PATCH 05/11] virt: Introducing libvirt VM class Lucas Meneghel Rodrigues
@ 2011-10-12  6:51   ` Amos Kong
  2011-10-12  8:14   ` Daniel P. Berrange
  1 sibling, 0 replies; 16+ messages in thread
From: Amos Kong @ 2011-10-12  6:51 UTC (permalink / raw)
  To: Lucas Meneghel Rodrigues; +Cc: autotest, kvm

On 10/12/2011 05:07 AM, Lucas Meneghel Rodrigues wrote:
> This is a first attempt at providing a libvirt VM class,
> in order to implement the needed methods for virt testing.
> With this class, we will be able to implement a libvirt
> test, that behaves similarly to the KVM test.
>
> As of implementation details, libvirt_vm uses virsh
> (a userspace program written on top of libvirt) to
> do domain start, stop, verification of status and
> other common operations. The reason why virsh was
> used is to get more coverage of the userspace stack
> that libvirt offers, and also to catch issues that
> virsh users would catch.
>
> Signed-off-by: Lucas Meneghel Rodrigues<lmr@redhat.com>
> ---
>   client/virt/libvirt_vm.py | 1232 +++++++++++++++++++++++++++++++++++++++++++++
>   1 files changed, 1232 insertions(+), 0 deletions(-)
>   create mode 100644 client/virt/libvirt_vm.py
>
> diff --git a/client/virt/libvirt_vm.py b/client/virt/libvirt_vm.py
> new file mode 100644
> index 0000000..bed512f
> --- /dev/null
> +++ b/client/virt/libvirt_vm.py
> @@ -0,0 +1,1232 @@
> +"""
> +Utility classes and functions to handle Virtual Machine creation using qemu.
> +
> +@copyright: 2008-2009 Red Hat Inc.
> +"""
> +
> +import time, os, logging, fcntl, re, commands
> +from autotest_lib.client.common_lib import error
> +from autotest_lib.client.bin import utils, os_dep
> +from xml.dom import minidom
> +import virt_utils, virt_vm, aexpect
> +
> +DEBUG = False
> +try:
> +    VIRSH_EXEC = os_dep.command("virsh")
> +except ValueError:
> +    VIRSH_EXEC = None
> +
> +
> +def libvirtd_restart():
> +    """
> +    Restart libvirt daemon.
> +    """
> +    try:
> +        utils.run("service libvirtd restart")
> +        logging.debug("Restarted libvirtd successfuly")
> +        return True
> +    except error.CmdError, detail:
> +        logging.error("Failed to restart libvirtd: %s" % detail)
> +        return False
> +
> +
> +def virsh_cmd(cmd):
> +    if VIRSH_EXEC is None:
> +        raise ValueError('Missing command: virsh')
> +    cmd_result = utils.run("%s %s" % (VIRSH_EXEC, cmd), ignore_status=True,
> +                           verbose=DEBUG)
> +    if DEBUG:
> +        if cmd_result.stdout.strip():
> +            logging.debug("stdout: %s", cmd_result.stdout.strip())
> +        if cmd_result.stderr.strip():
> +            logging.debug("stderr: %s", cmd_result.stderr.strip())
> +    return cmd_result.stdout.strip()
> +
> +
> +def virsh_uri():
> +    """
> +    Return the hypervisor canonical URI.
> +    """
> +    return virsh_cmd("uri")
> +
> +
> +def virsh_hostname():
> +    """
> +    Return the hypervisor hostname.
> +    """
> +    return virsh_cmd("hostname")
> +
> +
> +def virsh_domstate(name):
> +    """
> +    Return the state about a running domain.
> +
> +    @param name: VM name
> +    """
> +    return virsh_cmd("domstate %s" % name)
> +
> +
> +def virsh_uuid(name):
> +    """
> +    Return the Converted domain name or id to the domain UUID.
> +
> +    @param name: VM name
> +    """
> +    return virsh_cmd("domuuid %s" % name)
> +
> +
> +def virsh_screenshot(name, filename):
> +    virsh_cmd("screenshot %s %s" % (name, filename))
> +    return filename
> +
> +
> +def virsh_dumpxml(name):
> +    """
> +    Return the domain information as an XML dump.
> +
> +    @param name: VM name
> +    """
> +    return virsh_cmd("dumpxml %s" % name)
> +
> +
> +def virsh_is_alive(name):
> +    """
> +    Return True if the domain is started/alive.
> +
> +    @param name: VM name
> +    """
> +    return not virsh_is_dead(name)
> +
> +
> +def virsh_is_dead(name):
> +    """
> +    Return True if the domain is not started/dead.
> +
> +    @param name: VM name
> +    """
> +    if (virsh_domstate(name) == 'running' or
> +        virsh_domstate(name) == 'idle'):
> +        return False
> +    else:
> +        return True
> +
> +
> +def virsh_suspend(name):
> +    """
> +    Return True on successful domain suspention of VM.
> +
> +    Suspend  a domain. It is kept in memory but will not be scheduled.
> +
> +    @param name: VM name
> +    """
> +    try:
> +        utils.run("virsh suspend %s" % (name))
> +        if virsh_domstate(name) == 'paused':
> +            logging.debug("Suspended VM %s", name)
> +            return True
> +        else:
> +            return False
> +    except error.CmdError:
> +        logging.error("Suspending VM %s failed", name)
> +        return False
> +
> +
> +def virsh_resume(name):
> +    """
> +    Return True on successful domain resumption of VM.
> +
> +    Move a domain out of the suspended state.
> +
> +    @param name: VM name
> +    """
> +    try:
> +        utils.run("virsh resume %s" % (name))
> +        if virsh_is_alive(name):
> +            logging.debug("Resumed VM %s", name)
> +            return True
> +        else:
> +            return False
> +    except error.CmdError:
> +        logging.error("Resume VM %s failed", name)
> +        return False
> +
> +
> +def virsh_start(name, vm):

    def virsh_start(name):

one or two augments here? this function is called with one augment in 
VM.start()

> +    """
> +    Return True on successful domain start.
> +
> +    Start a (previously defined) inactive domain.
> +
> +    @param name: VM name
> +    """
> +    if virsh_is_alive(name):
> +        return
> +    try:
> +        utils.run("virsh start %s" % (name))
> +        return True
> +    except error.CmdError:
> +        logging.error("Start VM %s failed", name)

If the virsh cmd fails, we would got two error message.
They are repeated, how about remove this one? or add a prefix(we would 
know it's an error of virsh cmd)

logging.error("Start VM %s failed", name)
logging.error("VM %s failed to start", self.name)

> +        return False
> +
> +

....
> +
> +class VM(virt_vm.BaseVM):
> +    """
> +    This class handles all basic VM operations for libvirt.
> +    """
> +    def __init__(self, name, params, root_dir, address_cache, state=None):
> +        """
> +        Initialize the object and set a few attributes.
> +
> +        @param name: The name of the object
> +        @param params: A dict containing VM params
> +                (see method make_qemu_command for a full description)

....
> +
> +    def start(self):
> +        """
> +        Starts this VM.
> +        """
> +        if virsh_start(self.name):

^^^^^^^^

> +            if self.wait_for_start():
> +                logging.debug("Started VM %s", self.name)
> +                return True
> +            else:
> +                logging.error("VM %s failed to start", self.name)
> +                return False
> +        else:
> +            logging.error("VM %s failed to start", self.name)

^^^^^^^^

> +            return False
> +
> +
> +    def wait_for_shutdown(self, count=60):
> +        """
> +        Return True on successful domain shutdown.
> +
> +        Wait for a domain to shutdown, libvirt does not block on domain
> +        shutdown so we need to watch for successful completion.
> +
> +        @param name: VM name
> +        @param name: Optional timeout value
> +        """
> +        timeout = count
> +        while count>  0:
> +            # check every 5 seconds
> +            if count % 5 == 0:
> +                if virsh_is_dead(self.name):
> +                    logging.debug("Shutdown took %d seconds", timeout - count)
> +                    return True
> +            count -= 1
> +            time.sleep(1)
> +            logging.debug("Waiting for guest to shutdown %d", count)
> +        return False
> +

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Autotest] [PATCH 06/11] virt: Introducing libvirt monitor
  2011-10-11 21:07 ` [PATCH 06/11] virt: Introducing libvirt monitor Lucas Meneghel Rodrigues
@ 2011-10-12  7:48   ` Amos Kong
  2011-10-13 17:12     ` Lucas Meneghel Rodrigues
  0 siblings, 1 reply; 16+ messages in thread
From: Amos Kong @ 2011-10-12  7:48 UTC (permalink / raw)
  To: Lucas Meneghel Rodrigues; +Cc: autotest, kvm

On 10/12/2011 05:07 AM, Lucas Meneghel Rodrigues wrote:
> This is an initial implementation for a libvirt monitor.
> With it, we plan on making the libvirt test use all the
> monitor features, making most of the tests available for
> kvm available for libvirt.
>
> As of implementation details, it uses aexpect to get a
> virsh shell, and then the monitor methods are implemented
> by executing commands on that virsh shell.
>
> As of now, the libvirt vm class is still not using the
> monitor code, but we plan on making the move soon enough.
>
> Signed-off-by: Lucas Meneghel Rodrigues<lmr@redhat.com>
> ---
>   client/virt/libvirt_monitor.py |  322 ++++++++++++++++++++++++++++++++++++++++
>   1 files changed, 322 insertions(+), 0 deletions(-)
>   create mode 100644 client/virt/libvirt_monitor.py
>
> diff --git a/client/virt/libvirt_monitor.py b/client/virt/libvirt_monitor.py
> new file mode 100644
> index 0000000..05b838c
> --- /dev/null
> +++ b/client/virt/libvirt_monitor.py
> @@ -0,0 +1,322 @@
> +import re, tempfile, xml.dom.minidom, logging
> +import virt_utils, aexpect
> +from autotest_lib.client.bin import utils
> +
> +
> +class VirshMonitor:
> +    """
> +    Wraps "Virsh monitor" commands.
> +    """
> +
> +    def __init__(self, virsh_exec='virsh', name, vmname, password=None,
> +                 prompt=None, hostname='localhost', driver=None, username=None,
> +                 linesep="\\n"):
> +        """
> +        Connect to the hypervisor and get virsh prompt.
> +
> +        @param virsh_exec: Virsh executable
> +        @param name: Monitor identifier (a string)
> +        @param vmname: VM name
> +        @param password: Hypervisor user password
> +        @param prompt: Virsh prompt
> +        @param hostname: Hypervisor IP
> +        @param driver: Hypervisor driver type
> +        @param username: Hypervisor  username
> +        @param linesep: The line separator to use when sending lines
> +                (e.g. '\\n' or '\\r\\n')
> +        """
> +        self.virsh_exec = virsh_exec
> +        self.name = name
> +        self.vmname = vmname
> +        self.password = password
> +        self.prompt = prompt
> +        self.hostname = hostname
> +        self.driver = driver
> +        self.username = username
> +        self.session = self.login()
> +        self.virsh_cmd = {"help":"help", "quit":"destroy " + self.vmname,
> +                           "stop":"suspend", "cont":"resume"}
> +        self.drive_map = {}
> +        self.network_info = []
> +        self.disk_info = []
> +        self._parse_domxml()
> +
> +
> +    def __del__(self):
> +        self.session.sendline("quit")
> +

....
> +        if "balloon" in command:
> +            new_mem = re.findall("balloon\s+(\d+)", command)[0]
> +            new_mem = str(int(new_mem) * 1024)
> +            output = self.session.cmd_output("setmem  %s %s" %
> +                                                      (self.vmname, new_mem))
> +            return
> +
> +        if "system_reset" in command:
> +            self.session.cmd_output("destroy %s" % self.vmname)
> +            self.session.cmd_output("start %s" % self.vmname)
> +            return

This would make qemu process exit, this is not same as qemu monitor 
cmd(system_reset). We may migrate guest which is repeatedly rebooting, 
then migration will be failed.

# grep system_reset virt/tests/*
virt/tests/boot.py:    2) Send a reboot command or a system_reset 
monitor command (optional)
virt/tests/boot.py:        if params["reboot_method"] == "system_reset":
Binary file virt/tests/boot.pyc matches
virt/tests/iofuzz.py:                        session = 
vm.reboot(method="system_reset")


'system_reset' of qemu monitor is only called for fakereboot in Libvirt.
but Libvirt developer told me they may add new API for it.


> +        data = self.session.cmd_output(" %s \n" % self.virsh_cmd.get(
> +                                                            command, command))
> +        return data
> +
> +
> +    def is_responsive(self):
> +        """
> +        Return True if the monitor is responsive.
> +        """
> +        return True
> +
> +
> +    def quit(self):
> +        """
> +        Send "quit" without waiting for output.
> +        """
> +        self.cmd("quit")
> +
> +
> +    def screendump(self, filename, debug=True):
> +        """
> +        Request a screendump.
> +
> +        @param filename: Location for the screendump
> +        @return: The command's output
                     ^^^^^^^^^^^^

> +        """
> +        if debug:
> +            logging.debug("Requesting screendump %s" % filename)
> +        self.cmd("screenshot %s" % filename)

            cmd output is not returned.


> +    def info(self, what):
> +        """
> +        Request info about something and return the output.
> +        """
> +        if "network" in what:
> +            return self.network_info
> +
> +        if "pci" in what:
> +            domxml = self.session.cmd_output("dumpxml %s \n" %
> +                                                       self.vmname)
> +            self._parse_dev(domxml)
> +            return str(self.network_info) + str(self.drive_map)
> +
> +        if "balloon" in what:
> +            self.session.cmd_output("\n")
> +            netpool_lst = self.session.cmd_output("dominfo %s" %
> +                                                            self.vmname)
> +            return str(int(re.findall("Used memory:\s+(\d+)", netpool_lst)
> +                                       [0]) / 1024)
> +
> +        return self.cmd("info %s" % what)


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 05/11] virt: Introducing libvirt VM class
  2011-10-11 21:07 ` [PATCH 05/11] virt: Introducing libvirt VM class Lucas Meneghel Rodrigues
  2011-10-12  6:51   ` [Autotest] " Amos Kong
@ 2011-10-12  8:14   ` Daniel P. Berrange
  2011-10-13 17:26     ` Lucas Meneghel Rodrigues
  1 sibling, 1 reply; 16+ messages in thread
From: Daniel P. Berrange @ 2011-10-12  8:14 UTC (permalink / raw)
  To: Lucas Meneghel Rodrigues; +Cc: autotest, kvm

On Tue, Oct 11, 2011 at 06:07:11PM -0300, Lucas Meneghel Rodrigues wrote:
> This is a first attempt at providing a libvirt VM class,
> in order to implement the needed methods for virt testing.
> With this class, we will be able to implement a libvirt
> test, that behaves similarly to the KVM test.
> 
> As of implementation details, libvirt_vm uses virsh
> (a userspace program written on top of libvirt) to
> do domain start, stop, verification of status and
> other common operations. The reason why virsh was
> used is to get more coverage of the userspace stack
> that libvirt offers, and also to catch issues that
> virsh users would catch.

Personally I would have recommended that you use the libvirt Python API.
virsh is a very thin layer over the libvirt API, which mostly avoidse
adding any logic of its own, so once it has been tested once, there's
not much value in doing more. By using the Python API directly, you will
be able todo more intelligent handling of errors, since you'll get the
full libvirt python exception object instead of a blob of stuff on stderr.
Not to mention that it is so much more efficient, and robust against
any future changes in virsh.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Autotest] [PATCH 06/11] virt: Introducing libvirt monitor
  2011-10-12  7:48   ` [Autotest] " Amos Kong
@ 2011-10-13 17:12     ` Lucas Meneghel Rodrigues
  0 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-13 17:12 UTC (permalink / raw)
  To: Amos Kong; +Cc: autotest, kvm

On Wed, Oct 12, 2011 at 4:48 AM, Amos Kong <akong@redhat.com> wrote:
> On 10/12/2011 05:07 AM, Lucas Meneghel Rodrigues wrote:
>> This is an initial implementation for a libvirt monitor.
>> With it, we plan on making the libvirt test use all the
>> monitor features, making most of the tests available for
>> kvm available for libvirt.
>>
>> As of implementation details, it uses aexpect to get a
>> virsh shell, and then the monitor methods are implemented
>> by executing commands on that virsh shell.
>>
>> As of now, the libvirt vm class is still not using the
>> monitor code, but we plan on making the move soon enough.
>>
>> Signed-off-by: Lucas Meneghel Rodrigues<lmr@redhat.com>
>> ---
>>   client/virt/libvirt_monitor.py |  322 ++++++++++++++++++++++++++++++++++++++++
>>   1 files changed, 322 insertions(+), 0 deletions(-)
>>   create mode 100644 client/virt/libvirt_monitor.py
>>
>> diff --git a/client/virt/libvirt_monitor.py b/client/virt/libvirt_monitor.py
>> new file mode 100644
>> index 0000000..05b838c
>> --- /dev/null
>> +++ b/client/virt/libvirt_monitor.py
>> @@ -0,0 +1,322 @@
>> +import re, tempfile, xml.dom.minidom, logging
>> +import virt_utils, aexpect
>> +from autotest_lib.client.bin import utils
>> +
>> +
>> +class VirshMonitor:
>> +    """
>> +    Wraps "Virsh monitor" commands.
>> +    """
>> +
>> +    def __init__(self, virsh_exec='virsh', name, vmname, password=None,
>> +                 prompt=None, hostname='localhost', driver=None, username=None,
>> +                 linesep="\\n"):
>> +        """
>> +        Connect to the hypervisor and get virsh prompt.
>> +
>> +        @param virsh_exec: Virsh executable
>> +        @param name: Monitor identifier (a string)
>> +        @param vmname: VM name
>> +        @param password: Hypervisor user password
>> +        @param prompt: Virsh prompt
>> +        @param hostname: Hypervisor IP
>> +        @param driver: Hypervisor driver type
>> +        @param username: Hypervisor  username
>> +        @param linesep: The line separator to use when sending lines
>> +                (e.g. '\\n' or '\\r\\n')
>> +        """
>> +        self.virsh_exec = virsh_exec
>> +        self.name = name
>> +        self.vmname = vmname
>> +        self.password = password
>> +        self.prompt = prompt
>> +        self.hostname = hostname
>> +        self.driver = driver
>> +        self.username = username
>> +        self.session = self.login()
>> +        self.virsh_cmd = {"help":"help", "quit":"destroy " + self.vmname,
>> +                           "stop":"suspend", "cont":"resume"}
>> +        self.drive_map = {}
>> +        self.network_info = []
>> +        self.disk_info = []
>> +        self._parse_domxml()
>> +
>> +
>> +    def __del__(self):
>> +        self.session.sendline("quit")
>> +
>
> ....
>> +        if "balloon" in command:
>> +            new_mem = re.findall("balloon\s+(\d+)", command)[0]
>> +            new_mem = str(int(new_mem) * 1024)
>> +            output = self.session.cmd_output("setmem  %s %s" %
>> +                                                      (self.vmname, new_mem))
>> +            return
>> +
>> +        if "system_reset" in command:
>> +            self.session.cmd_output("destroy %s" % self.vmname)
>> +            self.session.cmd_output("start %s" % self.vmname)
>> +            return
>
> This would make qemu process exit, this is not same as qemu monitor
> cmd(system_reset). We may migrate guest which is repeatedly rebooting,
> then migration will be failed.

Ok, noted, but since there's no such an API written for it yet, and
since we are still not supporting migration tests, I believe it's OK
to leave it like that for now.

> # grep system_reset virt/tests/*
> virt/tests/boot.py:    2) Send a reboot command or a system_reset
> monitor command (optional)
> virt/tests/boot.py:        if params["reboot_method"] == "system_reset":
> Binary file virt/tests/boot.pyc matches
> virt/tests/iofuzz.py:                        session =
> vm.reboot(method="system_reset")
>
>
> 'system_reset' of qemu monitor is only called for fakereboot in Libvirt.
> but Libvirt developer told me they may add new API for it.
>
>
>> +        data = self.session.cmd_output(" %s \n" % self.virsh_cmd.get(
>> +                                                            command, command))
>> +        return data
>> +
>> +
>> +    def is_responsive(self):
>> +        """
>> +        Return True if the monitor is responsive.
>> +        """
>> +        return True
>> +
>> +
>> +    def quit(self):
>> +        """
>> +        Send "quit" without waiting for output.
>> +        """
>> +        self.cmd("quit")
>> +
>> +
>> +    def screendump(self, filename, debug=True):
>> +        """
>> +        Request a screendump.
>> +
>> +        @param filename: Location for the screendump
>> +        @return: The command's output
>                     ^^^^^^^^^^^^
>
>> +        """
>> +        if debug:
>> +            logging.debug("Requesting screendump %s" % filename)
>> +        self.cmd("screenshot %s" % filename)
>
>            cmd output is not returned.

Ok, that was easy enough to fix, thanks! I've updated my branch with
all the fixes pointed out so far.

>
>> +    def info(self, what):
>> +        """
>> +        Request info about something and return the output.
>> +        """
>> +        if "network" in what:
>> +            return self.network_info
>> +
>> +        if "pci" in what:
>> +            domxml = self.session.cmd_output("dumpxml %s \n" %
>> +                                                       self.vmname)
>> +            self._parse_dev(domxml)
>> +            return str(self.network_info) + str(self.drive_map)
>> +
>> +        if "balloon" in what:
>> +            self.session.cmd_output("\n")
>> +            netpool_lst = self.session.cmd_output("dominfo %s" %
>> +                                                            self.vmname)
>> +            return str(int(re.findall("Used memory:\s+(\d+)", netpool_lst)
>> +                                       [0]) / 1024)
>> +
>> +        return self.cmd("info %s" % what)
>
> _______________________________________________
> Autotest mailing list
> Autotest@test.kernel.org
> http://test.kernel.org/cgi-bin/mailman/listinfo/autotest
>



-- 
Lucas

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 05/11] virt: Introducing libvirt VM class
  2011-10-12  8:14   ` Daniel P. Berrange
@ 2011-10-13 17:26     ` Lucas Meneghel Rodrigues
  0 siblings, 0 replies; 16+ messages in thread
From: Lucas Meneghel Rodrigues @ 2011-10-13 17:26 UTC (permalink / raw)
  To: Daniel P. Berrange; +Cc: autotest, kvm

On 10/12/2011 05:14 AM, Daniel P. Berrange wrote:
> On Tue, Oct 11, 2011 at 06:07:11PM -0300, Lucas Meneghel Rodrigues wrote:
>> This is a first attempt at providing a libvirt VM class,
>> in order to implement the needed methods for virt testing.
>> With this class, we will be able to implement a libvirt
>> test, that behaves similarly to the KVM test.
>>
>> As of implementation details, libvirt_vm uses virsh
>> (a userspace program written on top of libvirt) to
>> do domain start, stop, verification of status and
>> other common operations. The reason why virsh was
>> used is to get more coverage of the userspace stack
>> that libvirt offers, and also to catch issues that
>> virsh users would catch.
>
> Personally I would have recommended that you use the libvirt Python API.
> virsh is a very thin layer over the libvirt API, which mostly avoidse
> adding any logic of its own, so once it has been tested once, there's
> not much value in doing more. By using the Python API directly, you will
> be able todo more intelligent handling of errors, since you'll get the
> full libvirt python exception object instead of a blob of stuff on stderr.
> Not to mention that it is so much more efficient, and robust against
> any future changes in virsh.

Thanks Daniel. We've discussed about that quite a few times during the 
development of the code. The plan is to just add methods that will do 
the same as the API counterpart moving forward, so we can test both the 
think layer that is virsh and the py API. We just wanted to focusing in 
one implementation to get something functional first.

We'll keep you guys posted about progress on py bindings.

Cheers,

Lucas

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2011-10-13 17:26 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-11 21:07 [PATCH 00/11] [RFC] Libvirt test v2 Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 02/11] virt: Introducing virt_test.virt_test class Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 03/11] Moving unattended_install test from kvm test to common virt location Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 04/11] Moving get_started code to client.virt.virt_utils Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 05/11] virt: Introducing libvirt VM class Lucas Meneghel Rodrigues
2011-10-12  6:51   ` [Autotest] " Amos Kong
2011-10-12  8:14   ` Daniel P. Berrange
2011-10-13 17:26     ` Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 06/11] virt: Introducing libvirt monitor Lucas Meneghel Rodrigues
2011-10-12  7:48   ` [Autotest] " Amos Kong
2011-10-13 17:12     ` Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 07/11] virt.virt_env_process: Add libvirt vm handling Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 08/11] client.tests: Introducing libvirt test Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 09/11] Virt: builtin HTTP server for unattended installs Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 10/11] Virt: support XEN via libvirt and auto url installer Lucas Meneghel Rodrigues
2011-10-11 21:07 ` [PATCH 11/11] Virt: add support for XEN via libvirt installs and auto url Lucas Meneghel Rodrigues

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.