Autotest upstream merge.

Merged from d9d64b855363d214996b187380532d4cc9991d29 to
7bad38846fe9c74e42018131ce85aec2b5e6c7a9

BUG=none
TEST=emerge autotest, run bvt, smoke.

Change-Id: Ibe6462198e84e0d41fa160af086283cd712da4a6
Reviewed-on: http://gerrit.chromium.org/gerrit/7440
Tested-by: Dale Curtis <dalecurtis@chromium.org>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
diff --git a/cli/acl.py b/cli/acl.py
index d6f5baa..0b20acf 100644
--- a/cli/acl.py
+++ b/cli/acl.py
@@ -79,23 +79,26 @@
         (options, leftover) = super(acl_list, self).parse([user_info,
                                                            host_info])
 
-        if ((self.users and (self.hosts or self.acls)) or
-            (self.hosts and self.acls)):
+        users = getattr(self, 'users')
+        hosts = getattr(self, 'hosts')
+        acls = getattr(self, 'acls')
+        if ((users and (hosts or acls)) or
+            (hosts and acls)):
             self.invalid_syntax('Only specify one of --user,'
                                 '--machine or ACL')
 
-        if len(self.users) > 1:
+        if len(users) > 1:
             self.invalid_syntax('Only specify one <user>')
-        if len(self.hosts) > 1:
+        if len(hosts) > 1:
             self.invalid_syntax('Only specify one <machine>')
 
         try:
-            self.users = self.users[0]
+            self.users = users[0]
         except IndexError:
             pass
 
         try:
-            self.hosts = self.hosts[0]
+            self.hosts = hosts[0]
         except IndexError:
             pass
         return (options, leftover)
diff --git a/cli/job.py b/cli/job.py
index df5d3b8..51ceb92 100644
--- a/cli/job.py
+++ b/cli/job.py
@@ -314,10 +314,11 @@
                 [host_info, job_info, oth_info, label_info] + parse_info,
                 req_items='jobname')
         self.data = {}
-        if len(self.jobname) > 1:
+        jobname = getattr(self, 'jobname')
+        if len(jobname) > 1:
             self.invalid_syntax('Too many arguments specified, only expected '
-                                'to receive job name: %s' % self.jobname)
-        self.jobname = self.jobname[0]
+                                'to receive job name: %s' % jobname)
+        self.jobname = jobname[0]
 
         if options.priority:
             self.data['priority'] = options.priority.capitalize()
diff --git a/cli/topic_common_unittest.py b/cli/topic_common_unittest.py
index d3bdacb..67592f5 100755
--- a/cli/topic_common_unittest.py
+++ b/cli/topic_common_unittest.py
@@ -607,7 +607,7 @@
         ulist.clean()
 
 
-    def test_parse_no_add_on(self):
+    def test_parse_no_add_on_2(self):
         flist = cli_mock.create_file('host1\nhost2\nleft2')
         ulist = cli_mock.create_file('user1\nuser2\nuser3\n')
         sys.argv = ['atest', '-U', ulist.name,
@@ -898,7 +898,7 @@
                                       'Host=h1|Platform=p1|Locked=False\n')
 
 
-    def test_print_table_parse_all_fields(self):
+    def test_print_table_parse_all_fields_2(self):
         self.atest.parse_delim = '?'
         self.__test_print_table_parse(['hostname', 'platform',
                                        'locked'],
diff --git a/client/bin/autotest b/client/bin/autotest
index 28c6015..7d36a05 100755
--- a/client/bin/autotest
+++ b/client/bin/autotest
@@ -21,7 +21,7 @@
 os.environ['AUTODIRBIN'] = autodirbin
 os.environ['PYTHONPATH'] = autodirbin
 
-parser = OptionParser()
+parser = OptionParser(usage='Usage: %prog [options] <control-file>')
 
 parser.add_option("-a", "--args", dest='args',
                         help="additional args to pass to control file")
@@ -55,6 +55,10 @@
                   help='Take this as the hostname of this machine '
                        '(given by autoserv)')
 
+parser.add_option('--output_dir', dest='output_dir',
+                  type='string', default="", action='store',
+                  help='Specify an alternate path to store test result logs')
+
 parser.add_option('--client_test_setup', dest='client_test_setup',
                   type='string', default=None, action='store',
                   help='a comma seperated list of client tests to prebuild on '
@@ -72,6 +76,7 @@
 
 # Check for a control file if not in prebuild mode.
 if len(args) != 1 and options.client_test_setup is None:
+    print "Missing control file!"
     usage()
 
 drop_caches = global_config.global_config.get_config_value('CLIENT',
diff --git a/client/bin/job.py b/client/bin/job.py
index 1abdbcd..11a4175 100644
--- a/client/bin/job.py
+++ b/client/bin/job.py
@@ -19,6 +19,7 @@
 from autotest_lib.client.common_lib import global_config
 from autotest_lib.client.tools import html_report
 
+GLOBAL_CONFIG = global_config.global_config
 
 LAST_BOOT_TAG = object()
 JOB_PREAMBLE = """
@@ -146,7 +147,17 @@
         always <autodir>/results/<tag>, where tag is passed in on the command
         line as an option.
         """
-        return os.path.join(self.autodir, 'results', options.tag)
+        output_dir_config = GLOBAL_CONFIG.get_config_value('CLIENT',
+                                                           'output_dir',
+                                                            default="")
+        if options.output_dir:
+            basedir = options.output_dir
+        elif output_dir_config:
+            basedir = output_dir_config
+        else:
+            basedir = self.autodir
+
+        return os.path.join(basedir, 'results', options.tag)
 
 
     def _get_status_logger(self):
@@ -270,9 +281,9 @@
         Perform the drop caches initialization.
         """
         self.drop_caches_between_iterations = (
-                       global_config.global_config.get_config_value('CLIENT',
-                                            'drop_caches_between_iterations',
-                                            type=bool, default=True))
+                                    GLOBAL_CONFIG.get_config_value('CLIENT',
+                                    'drop_caches_between_iterations',
+                                    type=bool, default=True))
         self.drop_caches = drop_caches
         if self.drop_caches:
             utils.drop_caches()
diff --git a/client/bin/job_unittest.py b/client/bin/job_unittest.py
index f3e1ae1..990d871 100755
--- a/client/bin/job_unittest.py
+++ b/client/bin/job_unittest.py
@@ -87,6 +87,7 @@
             user = None
             log = False
             args = ''
+            output_dir = ''
             tap_report = None
         self.god.stub_function_to_return(job.utils, 'drop_caches', None)
 
@@ -245,6 +246,7 @@
         options.hostname = 'localhost'
         options.user = 'my_user'
         options.args = ''
+        options.output_dir = ''
         options.tap_report = None
         self.job.__init__(self.control, options,
                           extra_copy_cmdline=['more-blah'])
@@ -286,6 +288,7 @@
         options.hostname = 'localhost'
         options.user = 'my_user'
         options.args = ''
+        options.output_dir = ''
         options.tap_report = None
         error = Exception('fail')
 
diff --git a/client/bin/net/net_utils.py b/client/bin/net/net_utils.py
index 7c96ba0..ce336a9 100644
--- a/client/bin/net/net_utils.py
+++ b/client/bin/net/net_utils.py
@@ -274,9 +274,11 @@
         # If bonded do not set loopback mode.
         # Try mac loopback first then phy loopback
         # If both fail, raise an error
-        if (bond().is_enabled() or
-            (self._set_loopback('phyint', 'enable') > 0 and
-             self._set_loopback('mac', 'enable') > 0)):
+        if bond().is_enabled():
+            raise error.TestError('Unable to enable loopback while '
+                                  'bonding is enabled.')
+        if (self._set_loopback('phyint', 'enable') > 0 and
+            self._set_loopback('mac', 'enable') > 0):
             raise error.TestError('Unable to enable loopback')
         # Add a 1 second wait for drivers which do not have
         # a synchronous loopback enable
@@ -287,12 +289,10 @@
 
 
     def disable_loopback(self):
-        # If bonded, to not disable loopback.
         # Try mac loopback first then phy loopback
         # If both fail, raise an error
-        if (bond().is_enabled() or
-            (self._set_loopback('phyint', 'disable') > 0 and
-             self._set_loopback('mac', 'disable') > 0)):
+        if (self._set_loopback('phyint', 'disable') > 0 and
+            self._set_loopback('mac', 'disable') > 0):
             raise error.TestError('Unable to disable loopback')
 
 
diff --git a/client/bin/net/net_utils_unittest.py b/client/bin/net/net_utils_unittest.py
index 1c7e1ef..11eb424 100755
--- a/client/bin/net/net_utils_unittest.py
+++ b/client/bin/net/net_utils_unittest.py
@@ -107,14 +107,10 @@
         mock_netif.loopback_enabled = True
         mock_netif.was_down = False
 
-        self.god.stub_function(net_utils.bonding, 'is_enabled')
-
         # restore using phyint
         cmd = 'ifconfig %s %s' % (mock_netif._name, mock_netif.orig_ipaddr)
         utils.system.expect_call(cmd)
 
-        net_utils.bonding.is_enabled.expect_call().and_return(False)
-
         cmd = '%s -L %s %s %s' % (mock_netif.ethtool, mock_netif._name,
                                   'phyint', 'disable')
         utils.system.expect_call(cmd, ignore_status=True).and_return(0)
@@ -126,8 +122,6 @@
         cmd = 'ifconfig %s %s' % (mock_netif._name, mock_netif.orig_ipaddr)
         utils.system.expect_call(cmd)
 
-        net_utils.bonding.is_enabled.expect_call().and_return(False)
-
         cmd = '%s -L %s %s %s' % (mock_netif.ethtool, mock_netif._name,
                                   'phyint', 'disable')
         utils.system.expect_call(cmd, ignore_status=True).and_return(1)
@@ -146,8 +140,6 @@
         cmd = 'ifconfig %s %s' % (mock_netif._name, mock_netif.orig_ipaddr)
         utils.system.expect_call(cmd)
 
-        net_utils.bonding.is_enabled.expect_call().and_return(False)
-
         cmd = '%s -L %s %s %s' % (mock_netif.ethtool, mock_netif._name,
                                   'phyint', 'disable')
         utils.system.expect_call(cmd, ignore_status=True).and_return(0)
@@ -620,10 +612,7 @@
         mock_netif.loopback_enabled = True
         mock_netif.was_down = False
 
-        self.god.stub_function(net_utils.bonding, 'is_enabled')
-
         # restore using phyint
-        net_utils.bonding.is_enabled.expect_call().and_return(False)
         cmd = '%s -L %s %s %s' % (mock_netif.ethtool, mock_netif._name,
                                   'phyint', 'disable')
         utils.system.expect_call(cmd, ignore_status=True).and_return(0)
@@ -631,7 +620,6 @@
         self.god.check_playback()
 
         # restore using mac
-        net_utils.bonding.is_enabled.expect_call().and_return(False)
         cmd = '%s -L %s %s %s' % (mock_netif.ethtool, mock_netif._name,
                                   'phyint', 'disable')
         utils.system.expect_call(cmd, ignore_status=True).and_return(1)
@@ -641,18 +629,7 @@
         mock_netif.disable_loopback()
         self.god.check_playback()
 
-        # catch exception on bonding enabled
-        net_utils.bonding.is_enabled.expect_call().and_return(True)
-        try:
-            mock_netif.disable_loopback()
-        except error.TestError:
-            pass
-        else:
-            self.assertEquals(0,1)
-        self.god.check_playback()
-
         # catch exception on phyint and mac failures
-        net_utils.bonding.is_enabled.expect_call().and_return(False)
         cmd = '%s -L %s %s %s' % (mock_netif.ethtool, mock_netif._name,
                                   'phyint', 'disable')
         utils.system.expect_call(cmd, ignore_status=True).and_return(1)
diff --git a/client/common_lib/base_job_unittest.py b/client/common_lib/base_job_unittest.py
index b98b01d..5fd4150 100755
--- a/client/common_lib/base_job_unittest.py
+++ b/client/common_lib/base_job_unittest.py
@@ -1361,7 +1361,8 @@
             @classmethod
             def _find_base_directories(cls):
                 return '/autodir', '/autodir/client', '/autodir/server'
-            def _find_resultdir(inner_self):
+            @classmethod
+            def _find_resultdir(cls):
                 return self.resultdir
 
         # stub out _job_directory for creation only
diff --git a/client/common_lib/error.py b/client/common_lib/error.py
index 0c5641c..1823143 100644
--- a/client/common_lib/error.py
+++ b/client/common_lib/error.py
@@ -311,6 +311,7 @@
     """This exception is raised when an autotest test exceeds the timeout
     parameter passed to run_timed_test and is killed.
     """
+    pass
 
 
 class HostRunErrorMixIn(Exception):
@@ -329,6 +330,14 @@
         return self.description + '\n' + repr(self.result_obj)
 
 
+class HostInstallTimeoutError(JobError):
+    """
+    Indicates the machine failed to be installed after the predetermined
+    timeout.
+    """
+    pass
+
+
 class AutotestHostRunError(HostRunErrorMixIn, AutotestError):
     pass
 
diff --git a/client/common_lib/mail.py b/client/common_lib/mail.py
index 0c641dd..88e633b 100644
--- a/client/common_lib/mail.py
+++ b/client/common_lib/mail.py
@@ -1,4 +1,4 @@
-import os, email.Message, smtplib
+import os, email, smtplib
 
 
 def send(from_address, to_addresses, cc_addresses, subject, message_body):
diff --git a/client/common_lib/mail_unittest.py b/client/common_lib/mail_unittest.py
index cac7ee6..e9ad115 100755
--- a/client/common_lib/mail_unittest.py
+++ b/client/common_lib/mail_unittest.py
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 
 import unittest
-import mail, email.Message
+import mail, email
 
 class test_data:
     mail_host = None
diff --git a/client/common_lib/test_utils/mock.py b/client/common_lib/test_utils/mock.py
index 918dc48..3952db7 100644
--- a/client/common_lib/test_utils/mock.py
+++ b/client/common_lib/test_utils/mock.py
@@ -266,7 +266,7 @@
         return '<mock_class: %s>' % self.__name
 
 
-class mock_god:
+class mock_god(object):
     NONEXISTENT_ATTRIBUTE = object()
 
     def __init__(self, debug=False, fail_fast=True, ut=None):
@@ -344,8 +344,6 @@
 
                 return obj
 
-
-
         return cls_sub
 
 
diff --git a/client/tests/cgroup/cgroup.py b/client/tests/cgroup/cgroup.py
new file mode 100644
index 0000000..171f43e
--- /dev/null
+++ b/client/tests/cgroup/cgroup.py
@@ -0,0 +1,421 @@
+import os, logging
+import time
+from tempfile import NamedTemporaryFile
+
+from autotest_lib.client.bin import test, utils
+from autotest_lib.client.common_lib import error
+from cgroup_common import Cgroup as CG
+from cgroup_common import CgroupModules
+
+class cgroup(test.test):
+    """
+    Tests the cgroup functionalities. It works by creating a process (which is
+    also a python application) that will try to use CPU and memory. We will
+    then verify whether the cgroups rules are obeyed.
+    """
+    version = 1
+    _client = ""
+    modules = CgroupModules()
+
+    def run_once(self):
+        """
+            Try to access different resources which are restricted by cgroup.
+        """
+        logging.info('Starting cgroup testing')
+
+        err = ""
+        # Run available tests
+        for i in ['memory', 'cpuset']:
+            logging.info("---< 'test_%s' START >---", i)
+            try:
+                if not self.modules.get_pwd(i):
+                    raise error.TestFail("module not available/mounted")
+                t_function = getattr(self, "test_%s" % i)
+                t_function()
+                logging.info("---< 'test_%s' PASSED >---", i)
+            except AttributeError:
+                err += "%s, " % i
+                logging.error("test_%s: Test doesn't exist", i)
+                logging.info("---< 'test_%s' FAILED >---", i)
+            except Exception, inst:
+                err += "%s, " % i
+                logging.error("test_%s: %s", i, inst)
+                logging.info("---< 'test_%s' FAILED >---", i)
+
+        if err:
+            logging.error('Some subtests failed (%s)' % err[:-2])
+            raise error.TestFail('Some subtests failed (%s)' % err[:-2])
+
+
+    def setup(self):
+        """
+        Setup
+        """
+        logging.debug('Setting up cgroups modules')
+
+        self._client = os.path.join(self.bindir, "cgroup_client.py")
+
+        _modules = ['cpuset', 'ns', 'cpu', 'cpuacct', 'memory', 'devices',
+                    'freezer', 'net_cls', 'blkio']
+        if (self.modules.init(_modules) <= 0):
+            raise error.TestFail('Can\'t mount any cgroup modules')
+
+
+    def cleanup(self):
+        """
+        Unmount all cgroups and remove directories
+        """
+        logging.info('Cleanup')
+        self.modules.cleanup()
+
+
+    #############################
+    # TESTS
+    #############################
+    def test_memory(self):
+        """
+        Memory test
+        """
+        def cleanup(supress=False):
+            # cleanup
+            logging.debug("test_memory: Cleanup")
+            err = ""
+            if item.rm_cgroup(pwd):
+                err += "\nCan't remove cgroup directory"
+
+            utils.system("swapon -a")
+
+            if err:
+                if supress:
+                    logging.warn("Some parts of cleanup failed%s" % err)
+                else:
+                    raise error.TestFail("Some parts of cleanup failed%s" % err)
+
+        # Preparation
+        item = CG('memory', self._client)
+        if item.initialize(self.modules):
+            raise error.TestFail("cgroup init failed")
+
+        if item.smoke_test():
+            raise error.TestFail("smoke_test failed")
+
+        pwd = item.mk_cgroup()
+        if pwd == None:
+            raise error.TestFail("Can't create cgroup")
+
+        logging.debug("test_memory: Memory filling test")
+
+        f = open('/proc/meminfo','r')
+        mem = f.readline()
+        while not mem.startswith("MemFree"):
+            mem = f.readline()
+        # Use only 1G or max of the free memory
+        mem = min(int(mem.split()[1])/1024, 1024)
+        mem = max(mem, 100) # at least 100M
+        memsw_limit_bytes = item.get_property("memory.memsw.limit_in_bytes",
+                                              supress=True)
+        if memsw_limit_bytes is not None:
+            memsw = True
+            # Clear swap
+            utils.system("swapoff -a")
+            utils.system("swapon -a")
+            f.seek(0)
+            swap = f.readline()
+            while not swap.startswith("SwapTotal"):
+                swap = f.readline()
+            swap = int(swap.split()[1])/1024
+            if swap < mem / 2:
+                logging.error("Not enough swap memory to test 'memsw'")
+                memsw = False
+        else:
+            # Doesn't support swap + memory limitation, disable swap
+            logging.info("System does not support 'memsw'")
+            utils.system("swapoff -a")
+            memsw = False
+        outf = NamedTemporaryFile('w+', prefix="cgroup_client-",
+                                  dir="/tmp")
+        logging.debug("test_memory: Initializition passed")
+
+        ################################################
+        # Fill the memory without cgroup limitation
+        # Should pass
+        ################################################
+        logging.debug("test_memory: Memfill WO cgroup")
+        ps = item.test("memfill %d %s" % (mem, outf.name))
+        ps.stdin.write('\n')
+        i = 0
+        while ps.poll() == None:
+            if i > 60:
+                break
+            i += 1
+            time.sleep(1)
+        if i > 60:
+            ps.terminate()
+            raise error.TestFail("Memory filling failed (WO cgroup)")
+        outf.seek(0)
+        outf.flush()
+        out = outf.readlines()
+        if (len(out) < 2) or (ps.poll() != 0):
+            raise error.TestFail("Process failed (WO cgroup); output:\n%s"
+                                 "\nReturn: %d" % (out, ps.poll()))
+        if not out[-1].startswith("PASS"):
+            raise error.TestFail("Unsuccessful memory filling "
+                                 "(WO cgroup)")
+        logging.debug("test_memory: Memfill WO cgroup passed")
+
+        ################################################
+        # Fill the memory with 1/2 memory limit
+        # memsw: should swap out part of the process and pass
+        # WO memsw: should fail (SIGKILL)
+        ################################################
+        logging.debug("test_memory: Memfill mem only limit")
+        ps = item.test("memfill %d %s" % (mem, outf.name))
+        if item.set_cgroup(ps.pid, pwd):
+            raise error.TestFail("Could not set cgroup")
+        if item.set_prop("memory.limit_in_bytes", ("%dM" % (mem/2)), pwd):
+            raise error.TestFail("Could not set mem limit (mem)")
+        ps.stdin.write('\n')
+        i = 0
+        while ps.poll() == None:
+            if i > 120:
+                break
+            i += 1
+            time.sleep(1)
+        if i > 120:
+            ps.terminate()
+            raise error.TestFail("Memory filling failed (mem)")
+        outf.seek(0)
+        outf.flush()
+        out = outf.readlines()
+        if (len(out) < 2):
+            raise error.TestFail("Process failed (mem); output:\n%s"
+                          "\nReturn: %d" % (out, ps.poll()))
+        if memsw:
+            if not out[-1].startswith("PASS"):
+                logging.error("test_memory: cgroup_client.py returned %d; "
+                              "output:\n%s", ps.poll(), out)
+                raise error.TestFail("Unsuccessful memory filling (mem)")
+        else:
+            if out[-1].startswith("PASS"):
+                raise error.TestFail("Unexpected memory filling (mem)")
+            else:
+                filled = int(out[-2].split()[1][:-1])
+                if mem/2 > 1.5 * filled:
+                    logging.error("test_memory: Limit = %dM, Filled = %dM (+ "
+                                  "python overhead upto 1/3 (mem))", mem/2,
+                                  filled)
+                else:
+                    logging.debug("test_memory: Limit = %dM, Filled = %dM (+ "
+                                  "python overhead upto 1/3 (mem))", mem/2,
+                                  filled)
+        logging.debug("test_memory: Memfill mem only cgroup passed")
+
+        ################################################
+        # Fill the memory with 1/2 memory+swap limit
+        # Should fail
+        # (memory.limit_in_bytes have to be set prior to this test)
+        ################################################
+        if memsw:
+            logging.debug("test_memory: Memfill mem + swap limit")
+            ps = item.test("memfill %d %s" % (mem, outf.name))
+            if item.set_cgroup(ps.pid, pwd):
+                raise error.TestFail("Could not set cgroup (memsw)")
+            if item.set_prop("memory.memsw.limit_in_bytes", "%dM"%(mem/2), pwd):
+                raise error.TestFail("Could not set mem limit (memsw)")
+            ps.stdin.write('\n')
+            i = 0
+            while ps.poll() == None:
+                if i > 120:
+                    break
+                i += 1
+                time.sleep(1)
+            if i > 120:
+                ps.terminate()
+                raise error.TestFail("Memory filling failed (mem)")
+            outf.seek(0)
+            outf.flush()
+            out = outf.readlines()
+            if (len(out) < 2):
+                raise error.TestFail("Process failed (memsw); output:\n%s"
+                                     "\nReturn: %d" % (out, ps.poll()))
+            if out[-1].startswith("PASS"):
+                raise error.TestFail("Unexpected memory filling (memsw)",
+                              mem)
+            else:
+                filled = int(out[-2].split()[1][:-1])
+                if mem / 2 > 1.5 * filled:
+                    logging.error("test_memory: Limit = %dM, Filled = %dM (+ "
+                                  "python overhead upto 1/3 (memsw))", mem/2,
+                                  filled)
+                else:
+                    logging.debug("test_memory: Limit = %dM, Filled = %dM (+ "
+                                  "python overhead upto 1/3 (memsw))", mem/2,
+                                  filled)
+            logging.debug("test_memory: Memfill mem + swap cgroup passed")
+
+        ################################################
+        # CLEANUP
+        ################################################
+        cleanup()
+
+
+
+    def test_cpuset(self):
+        """
+        Cpuset test
+        1) Initiate CPU load on CPU0, than spread into CPU* - CPU0
+        """
+        class per_cpu_load:
+            """
+            Handles the per_cpu_load stats
+            self.values [cpus, cpu0, cpu1, ...]
+            """
+            def __init__(self):
+                """
+                Init
+                """
+                self.values = []
+                self.f = open('/proc/stat', 'r')
+                line = self.f.readline()
+                while line:
+                    if line.startswith('cpu'):
+                        self.values.append(int(line.split()[1]))
+                    else:
+                        break
+                    line = self.f.readline()
+
+            def reload(self):
+                """
+                Reload current values
+                """
+                self.values = self.get()
+
+            def get(self):
+                """
+                Get the current values
+                @return vals: array of current values [cpus, cpu0, cpu1..]
+                """
+                self.f.seek(0)
+                self.f.flush()
+                vals = []
+                for i in range(len(self.values)):
+                    vals.append(int(self.f.readline().split()[1]))
+                return vals
+
+            def tick(self):
+                """
+                Reload values and returns the load between the last tick/reload
+                @return vals: array of load between ticks/reloads
+                              values [cpus, cpu0, cpu1..]
+                """
+                vals = self.get()
+                ret = []
+                for i in range(len(self.values)):
+                    ret.append(vals[i] - self.values[i])
+                self.values = vals
+                return ret
+
+        def cleanup(supress=False):
+            # cleanup
+            logging.debug("test_cpuset: Cleanup")
+            err = ""
+            try:
+                for task in tasks:
+                    for i in range(10):
+                        task.terminate()
+                        if task.poll() != None:
+                            break
+                        time.sleep(1)
+                    if i >= 9:
+                        logging.error("test_cpuset: Subprocess didn't finish")
+            except Exception, inst:
+                err += "\nCan't terminate tasks: %s" % inst
+            if item.rm_cgroup(pwd):
+                err += "\nCan't remove cgroup direcotry"
+            if err:
+                if supress:
+                    logging.warn("Some parts of cleanup failed%s" % err)
+                else:
+                    raise error.TestFail("Some parts of cleanup failed%s" % err)
+
+        # Preparation
+        item = CG('cpuset', self._client)
+        if item.initialize(self.modules):
+            raise error.TestFail("cgroup init failed")
+
+        # FIXME: new cpuset cgroup doesn't have any mems and cpus assigned
+        # thus smoke_test won't work
+        #if item.smoke_test():
+        #    raise error.TestFail("smoke_test failed")
+
+        try:
+            # Available cpus: cpuset.cpus = "0-$CPUS\n"
+            no_cpus = int(item.get_prop("cpuset.cpus").split('-')[1]) + 1
+        except:
+            raise error.TestFail("Failed to get no_cpus or no_cpus = 1")
+
+        pwd = item.mk_cgroup()
+        if pwd == None:
+            raise error.TestFail("Can't create cgroup")
+        # FIXME: new cpuset cgroup doesn't have any mems and cpus assigned
+        try:
+            tmp = item.get_prop("cpuset.cpus")
+            item.set_property("cpuset.cpus", tmp, pwd)
+            tmp = item.get_prop("cpuset.mems")
+            item.set_property("cpuset.mems", tmp, pwd)
+        except:
+            cleanup(True)
+            raise error.TestFail("Failed to set cpus and mems of"
+                                 "a new cgroup")
+
+        ################################################
+        # Cpu allocation test
+        # Use cpu0 and verify, than all cpu* - cpu0 and verify
+        ################################################
+        logging.debug("test_cpuset: Cpu allocation test")
+
+        tasks = []
+        # Run no_cpus + 1 jobs
+        for i in range(no_cpus + 1):
+            tasks.append(item.test("cpu"))
+            if item.set_cgroup(tasks[i].pid, pwd):
+                cleanup(True)
+                raise error.TestFail("Failed to set cgroup")
+            tasks[i].stdin.write('\n')
+        stats = per_cpu_load()
+        # Use only the first CPU
+        item.set_property("cpuset.cpus", 0, pwd)
+        stats.reload()
+        time.sleep(10)
+        # [0] = all cpus
+        s1 = stats.tick()[1:]
+        s2 = s1[1:]
+        s1 = s1[0]
+        for _s in s2:
+            if s1 < _s:
+                cleanup(True)
+                raise error.TestFail("Unused processor had higher utilization\n"
+                                     "used cpu: %s, remaining cpus: %s"
+                                     % (s1, s2))
+
+        if no_cpus == 2:
+            item.set_property("cpuset.cpus", "1", pwd)
+        else:
+            item.set_property("cpuset.cpus", "1-%d"%(no_cpus-1), pwd)
+        stats.reload()
+        time.sleep(10)
+        s1 = stats.tick()[1:]
+        s2 = s1[0]
+        s1 = s1[1:]
+        for _s in s1:
+            if s2 > _s:
+                cleanup(True)
+                raise error.TestFail("Unused processor had higher utilization\n"
+                                     "used cpus: %s, remaining cpu: %s"
+                                     % (s1, s2))
+        logging.debug("test_cpuset: Cpu allocation test passed")
+
+        ################################################
+        # CLEANUP
+        ################################################
+        cleanup()
diff --git a/client/tests/cgroup/cgroup_client.py b/client/tests/cgroup/cgroup_client.py
new file mode 100755
index 0000000..8b01722
--- /dev/null
+++ b/client/tests/cgroup/cgroup_client.py
@@ -0,0 +1,131 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Interactive python script for testing cgroups. It will try to use system
+resources such as cpu, memory and device IO. The other cgroups test
+instrumentation will inspect whether the linux box behaved as it should.
+
+@copyright: 2011 Red Hat Inc.
+@author: Lukas Doktor <ldoktor@redhat.com>
+"""
+import array, sys, time, math, os
+from tempfile import mktemp
+
+def test_smoke(args):
+    """
+    SIGSTOP the process and after SIGCONT exits.
+    """
+    print "TEST: smoke"
+    print "TEST: wait for input"
+    raw_input()
+    print "PASS: smoke"
+
+
+def test_memfill(args):
+    """
+    SIGSTOP and after SIGCONT fills the memory up to size size.
+    """
+    size = 1024
+    f = sys.stdout
+    if args:
+        size = int(args[0])
+        if len(args) > 1:
+            f = open(args[1], 'w', 0)
+    print "TEST: memfill (%dM)" % size
+    print "Redirecting to: %s" % f.name
+    f.write("TEST: memfill (%dM)\n" % size)
+    f.write("TEST: wait for input\n")
+    raw_input()
+    mem = array.array('B')
+    buf = ""
+    for i in range(1024 * 1024):
+        buf += '\x00'
+    for i in range(size):
+        mem.fromstring(buf)
+        f.write("TEST: %dM\n" % i)
+        try:
+            f.flush()
+            os.fsync(f)
+        except:
+            pass
+    f.write("PASS: memfill (%dM)\n" % size)
+
+
+def test_cpu(args):
+    """
+    Stress the CPU.
+    """
+    print "TEST: cpu"
+    print "TEST: wait for input"
+    raw_input()
+    while True:
+        for i in range (1000, 10000):
+            math.factorial(i)
+
+
+def test_devices(args):
+    if args:
+        if args[0] == "write":
+            test_devices_write()
+        else:
+            test_devices_read()
+    else:
+        test_devices_read()
+
+
+def test_devices_read():
+    """
+    Inf read from /dev/zero
+    """
+    print "TEST: devices read"
+    print "TEST: wait for input"
+    raw_input()
+
+    dev = open("/dev/zero", 'r')
+    while True:
+        print "TEST: tick"
+        dev.flush()
+        dev.read(1024*1024)
+        time.sleep(1)
+
+
+def test_devices_write():
+    """
+    Inf write into /dev/null device
+    """
+    print "TEST: devices write"
+    print "TEST: wait for input"
+    raw_input()
+
+    dev = open("/dev/null", 'w')
+    buf = ""
+    for _ in range(1024*1024):
+        buf += '\x00'
+    while True:
+        print "TEST: tick"
+        dev.write(buf)
+        dev.flush()
+        time.sleep(1)
+
+
+def main():
+    """
+    Main (infinite) loop.
+    """
+    if len(sys.argv) < 2:
+        print "FAIL: Incorrect usage (%s)" % sys.argv
+        return -1
+    args = sys.argv[2:]
+    if sys.argv[1] == "smoke":
+        test_smoke(args)
+    elif sys.argv[1] == "memfill":
+        test_memfill(args)
+    elif sys.argv[1] == "cpu":
+        test_cpu(args)
+    elif sys.argv[1] == "devices":
+        test_devices(args)
+    else:
+        print "FAIL: No test specified (%s)" % sys.argv
+
+if __name__ == "__main__":
+    main()
diff --git a/client/tests/cgroup/cgroup_common.py b/client/tests/cgroup/cgroup_common.py
new file mode 100755
index 0000000..51e93f7
--- /dev/null
+++ b/client/tests/cgroup/cgroup_common.py
@@ -0,0 +1,379 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Helpers for cgroup testing.
+
+@copyright: 2011 Red Hat Inc.
+@author: Lukas Doktor <ldoktor@redhat.com>
+"""
+import os, logging, subprocess, time, shutil
+from tempfile import mkdtemp
+from autotest_lib.client.bin import utils
+from autotest_lib.client.common_lib import error
+
+
+class Cgroup(object):
+    """
+    Cgroup handling class.
+    """
+    def __init__(self, module, _client):
+        """
+        Constructor
+        @param module: Name of the cgroup module
+        @param _client: Test script pwd + name
+        """
+        self.module = module
+        self._client = _client
+        self.root = None
+
+
+    def initialize(self, modules):
+        """
+        Initializes object for use.
+
+        @param modules: Array of all available cgroup modules.
+        @return: 0 when PASSED.
+        """
+        self.root = modules.get_pwd(self.module)
+        if self.root:
+            return 0
+        else:
+            logging.error("cg.initialize(): Module %s not found", self.module)
+            return -1
+        return 0
+
+
+    def mk_cgroup(self, root=None):
+        """
+        Creates new temporary cgroup
+        @param root: where to create this cgroup (default: self.root)
+        @return: 0 when PASSED
+        """
+        try:
+            if root:
+                pwd = mkdtemp(prefix='cgroup-', dir=root) + '/'
+            else:
+                pwd = mkdtemp(prefix='cgroup-', dir=self.root) + '/'
+        except Exception, inst:
+            logging.error("cg.mk_cgroup(): %s" , inst)
+            return None
+        return pwd
+
+
+    def rm_cgroup(self, pwd, supress=False):
+        """
+        Removes cgroup.
+
+        @param pwd: cgroup directory.
+        @param supress: supress output.
+        @return: 0 when PASSED
+        """
+        try:
+            os.rmdir(pwd)
+        except Exception, inst:
+            if not supress:
+                logging.error("cg.rm_cgroup(): %s" , inst)
+            return -1
+        return 0
+
+
+    def test(self, cmd):
+        """
+        Executes cgroup_client.py with cmd parameter.
+
+        @param cmd: command to be executed
+        @return: subprocess.Popen() process
+        """
+        logging.debug("cg.test(): executing paralel process '%s'", cmd)
+        cmd = self._client + ' ' + cmd
+        process = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE,
+                                   stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE, close_fds=True)
+        return process
+
+
+    def is_cgroup(self, pid, pwd):
+        """
+        Checks if the 'pid' process is in 'pwd' cgroup
+        @param pid: pid of the process
+        @param pwd: cgroup directory
+        @return: 0 when is 'pwd' member
+        """
+        if open(pwd + '/tasks').readlines().count("%d\n" % pid) > 0:
+            return 0
+        else:
+            return -1
+
+
+    def is_root_cgroup(self, pid):
+        """
+        Checks if the 'pid' process is in root cgroup (WO cgroup)
+        @param pid: pid of the process
+        @return: 0 when is 'root' member
+        """
+        return self.is_cgroup(pid, self.root)
+
+
+    def set_cgroup(self, pid, pwd):
+        """
+        Sets cgroup membership
+        @param pid: pid of the process
+        @param pwd: cgroup directory
+        @return: 0 when PASSED
+        """
+        try:
+            open(pwd+'/tasks', 'w').write(str(pid))
+        except Exception, inst:
+            logging.error("cg.set_cgroup(): %s" , inst)
+            return -1
+        if self.is_cgroup(pid, pwd):
+            logging.error("cg.set_cgroup(): Setting %d pid into %s cgroup "
+                          "failed", pid, pwd)
+            return -1
+        else:
+            return 0
+
+    def set_root_cgroup(self, pid):
+        """
+        Resets the cgroup membership (sets to root)
+        @param pid: pid of the process
+        @return: 0 when PASSED
+        """
+        return self.set_cgroup(pid, self.root)
+
+
+    def get_prop(self, prop, pwd=None, supress=False):
+        """
+        Gets one line of the property value
+        @param prop: property name (file)
+        @param pwd: cgroup directory
+        @param supress: supress the output
+        @return: String value or None when FAILED
+        """
+        tmp = self.get_property(prop, pwd, supress)
+        if tmp:
+            if tmp[0][-1] == '\n':
+                tmp[0] = tmp[0][:-1]
+            return tmp[0]
+        else:
+            return None
+
+
+    def get_property(self, prop, pwd=None, supress=False):
+        """
+        Gets the property value
+        @param prop: property name (file)
+        @param pwd: cgroup directory
+        @param supress: supress the output
+        @return: [] values or None when FAILED
+        """
+        if pwd == None:
+            pwd = self.root
+        try:
+            ret = open(pwd+prop, 'r').readlines()
+        except Exception, inst:
+            ret = None
+            if not supress:
+                logging.error("cg.get_property(): %s" , inst)
+        return ret
+
+
+    def set_prop(self, prop, value, pwd=None, check=True):
+        """
+        Sets the one-line property value concerning the K,M,G postfix
+        @param prop: property name (file)
+        @param value: desired value
+        @param pwd: cgroup directory
+        @param check: check the value after setup
+        @return: 0 when PASSED
+        """
+        _value = value
+        try:
+            value = str(value)
+            if value[-1] == '\n':
+                value = value[:-1]
+            if value[-1] == 'K':
+                value = int(value[:-1]) * 1024
+            elif value[-1] == 'M':
+                value = int(value[:-1]) * 1048576
+            elif value[-1] == 'G':
+                value = int(value[:-1]) * 1073741824
+        except:
+            logging.error("cg.set_prop() fallback into cg.set_property.")
+            value = _value
+        return self.set_property(prop, value, pwd, check)
+
+
+    def set_property(self, prop, value, pwd=None, check=True):
+        """
+        Sets the property value
+        @param prop: property name (file)
+        @param value: desired value
+        @param pwd: cgroup directory
+        @param check: check the value after setup
+        @return: 0 when PASSED
+        """
+        value = str(value)
+        if pwd == None:
+            pwd = self.root
+        try:
+            open(pwd+prop, 'w').write(value)
+        except Exception, inst:
+            logging.error("cg.set_property(): %s" , inst)
+            return -1
+        if check:
+            # Get the first line - '\n'
+            _value = self.get_property(prop, pwd)[0][:-1]
+            if value != _value:
+                logging.error("cg.set_property(): Setting failed: desired = %s,"
+                              " real value = %s", value, _value)
+                return -1
+        return 0
+
+
+    def smoke_test(self):
+        """
+        Smoke test
+        Module independent basic tests
+        """
+        part = 0
+        pwd = self.mk_cgroup()
+        if pwd == None:
+            logging.error("cg.smoke_test[%d]: Can't create cgroup", part)
+            return -1
+
+        part += 1
+        ps = self.test("smoke")
+        if ps == None:
+            logging.error("cg.smoke_test[%d]: Couldn't create process", part)
+            return -1
+
+        part += 1
+        if (ps.poll() != None):
+            logging.error("cg.smoke_test[%d]: Process died unexpectidly", part)
+            return -1
+
+        # New process should be a root member
+        part += 1
+        if self.is_root_cgroup(ps.pid):
+            logging.error("cg.smoke_test[%d]: Process is not a root member",
+                          part)
+            return -1
+
+        # Change the cgroup
+        part += 1
+        if self.set_cgroup(ps.pid, pwd):
+            logging.error("cg.smoke_test[%d]: Could not set cgroup", part)
+            return -1
+
+        # Try to remove used cgroup
+        part += 1
+        if self.rm_cgroup(pwd, supress=True) == 0:
+            logging.error("cg.smoke_test[%d]: Unexpected successful deletion of"
+                          " the used cgroup", part)
+            return -1
+
+        # Return the process into the root cgroup
+        part += 1
+        if self.set_root_cgroup(ps.pid):
+            logging.error("cg.smoke_test[%d]: Could not return the root cgroup "
+                          "membership", part)
+            return -1
+
+        # It should be safe to remove the cgroup now
+        part += 1
+        if self.rm_cgroup(pwd):
+            logging.error("cg.smoke_test[%d]: Can't remove cgroup directory",
+                          part)
+            return -1
+
+        # Finish the process
+        part += 1
+        ps.stdin.write('\n')
+        time.sleep(2)
+        if (ps.poll() == None):
+            logging.error("cg.smoke_test[%d]: Process is not finished", part)
+            return -1
+
+        return 0
+
+
+class CgroupModules(object):
+    """
+    Handles the list of different cgroup filesystems.
+    """
+    def __init__(self):
+        self.modules = []
+        self.modules.append([])
+        self.modules.append([])
+        self.modules.append([])
+        self.mountdir = mkdtemp(prefix='cgroup-') + '/'
+
+
+    def init(self, _modules):
+        """
+        Checks the mounted modules and if necessary mounts them into tmp
+            mountdir.
+        @param _modules: Desired modules.
+        @return: Number of initialized modules.
+        """
+        logging.debug("Desired cgroup modules: %s", _modules)
+        mounts = []
+        fp = open('/proc/mounts', 'r')
+        line = fp.readline().split()
+        while line:
+            if line[2] == 'cgroup':
+                mounts.append(line)
+            line = fp.readline().split()
+        fp.close()
+
+        for module in _modules:
+            # Is it already mounted?
+            i = False
+            for mount in mounts:
+                if mount[3].find(module) != -1:
+                    self.modules[0].append(module)
+                    self.modules[1].append(mount[1] + '/')
+                    self.modules[2].append(False)
+                    i = True
+                    break
+            if not i:
+                # Not yet mounted
+                os.mkdir(self.mountdir + module)
+                cmd = ('mount -t cgroup -o %s %s %s' %
+                       (module, module, self.mountdir + module))
+                try:
+                    utils.run(cmd)
+                    self.modules[0].append(module)
+                    self.modules[1].append(self.mountdir + module)
+                    self.modules[2].append(True)
+                except error.CmdError:
+                    logging.info("Cgroup module '%s' not available", module)
+
+        logging.debug("Initialized cgroup modules: %s", self.modules[0])
+        return len(self.modules[0])
+
+
+    def cleanup(self):
+        """
+        Unmount all cgroups and remove the mountdir.
+        """
+        for i in range(len(self.modules[0])):
+            if self.modules[2][i]:
+                utils.system('umount %s -l' % self.modules[1][i],
+                             ignore_status=True)
+        shutil.rmtree(self.mountdir)
+
+
+    def get_pwd(self, module):
+        """
+        Returns the mount directory of 'module'
+        @param module: desired module (memory, ...)
+        @return: mount directory of 'module' or None
+        """
+        try:
+            i = self.modules[0].index(module)
+        except Exception, inst:
+            logging.error("module %s not found: %s", module, inst)
+            return None
+        return self.modules[1][i]
diff --git a/client/tests/cgroup/control b/client/tests/cgroup/control
new file mode 100644
index 0000000..86aec06
--- /dev/null
+++ b/client/tests/cgroup/control
@@ -0,0 +1,12 @@
+AUTHOR = "Lukas Doktor <ldoktor@redhat.com>"
+NAME = "Cgroup"
+TIME = "SHORT"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "General"
+TEST_TYPE = "client"
+
+DOC = """
+This test checks basic functionality of cgroups
+"""
+
+job.run_test('cgroup')
diff --git a/client/tests/connectathon/connectathon.py b/client/tests/connectathon/connectathon.py
new file mode 100644
index 0000000..a0ef86f
--- /dev/null
+++ b/client/tests/connectathon/connectathon.py
@@ -0,0 +1,67 @@
+import os, shutil, glob, logging
+from autotest_lib.client.bin import test, utils
+from autotest_lib.client.common_lib import error
+
+
+class connectathon(test.test):
+    """
+    Connectathon test is an nfs testsuite which can run on
+    both BSD and System V based systems. The tests.init file
+    has to be modified based on the OS in which this test is run.
+
+    The tar file in this dir has an init file which works for Linux
+    platform.
+
+    @see www.connectathon.org
+    @author Poornima.Nayak (Poornima.Nayak@in.ibm.com)(original code)
+    """
+    version = 1
+    def initialize(self):
+        """
+        Sets the overall failure counter for the test.
+        """
+        self.nfail = 0
+
+
+    def setup(self, tarball='connectathon.tar.bz2'):
+        connectathon_tarball = utils.unmap_url(self.bindir, tarball,
+                                               self.tmpdir)
+        utils.extract_tarball_to_dir(connectathon_tarball, self.srcdir)
+
+        os.chdir(self.srcdir)
+        utils.system('make clean')
+        utils.system('make')
+
+
+    def run_once(self, testdir=None, args='', cthon_iterations=1):
+        """
+        Runs the test, with the appropriate control file.
+        """
+        os.chdir(self.srcdir)
+
+        if testdir is None:
+            testdir = self.tmpdir
+
+        self.results_path = os.path.join(self.resultsdir,
+                                         'raw_output_%s' % self.iteration)
+
+        try:
+            if not args:
+                # run basic test
+                args = "-b -t"
+
+            self.results = utils.system_output('./runtests -N %s %s %s' %
+                                              (cthon_iterations, args, testdir))
+            utils.open_write_close(self.results_path, self.results)
+
+        except error.CmdError, e:
+            self.nfail += 1
+            logging.error("Test failed: %s", e)
+
+
+    def postprocess(self):
+        """
+        Raises on failure.
+        """
+        if self.nfail != 0:
+            raise error.TestFail('Connectathon test suite failed.')
diff --git a/client/tests/connectathon/connectathon.tar.bz2 b/client/tests/connectathon/connectathon.tar.bz2
new file mode 100644
index 0000000..f67d8c2
--- /dev/null
+++ b/client/tests/connectathon/connectathon.tar.bz2
Binary files differ
diff --git a/client/tests/connectathon/control b/client/tests/connectathon/control
new file mode 100644
index 0000000..92fa518
--- /dev/null
+++ b/client/tests/connectathon/control
@@ -0,0 +1,31 @@
+AUTHOR = "Poornima Nayak <mpnayak@linux.vnet.ibm.com>"
+NAME = "connectathon"
+TEST_CATEGORY = "NFS FVT"
+TEST_CLASS = "General"
+TEST_TYPE = "client"
+TIME = 'MEDIUM'
+DOC = '''
+Test for testing nfs mounted paths.
+
+More information about connecthon can be found at
+http://www.connectathon.org/nfstests.html
+'''
+
+import datetime, os
+now = datetime.datetime.now()
+#iter_range = [10, 100, 1000, 10000]
+#tests = ['-b -t', '-g -t', '-g -f', '-s -t', '-s -f', '-l -f', '-l -t']
+iter_range = [1]
+tests = ['-s -t']
+tag_ver = 0
+for test in tests:
+    for j in iter_range:
+        # On this example, /mnt/test is an NFS mounted location previously set
+        dir = os.path.join('/mnt', 'test', now.strftime("%Y-%m-%d%H:%M"))
+        if not os.path.isdir(dir):
+            os.makedirs(dir)
+        job.run_test(url='connectathon', testdir=dir, args=test,
+                     cthon_iterations=j,
+                     tag=("itera-%s-test-%s" % (j, tag_ver)))
+        tag_ver = tag_ver + 1
+
diff --git a/client/tests/ffsb/README b/client/tests/ffsb/README
new file mode 100644
index 0000000..d2516ef
--- /dev/null
+++ b/client/tests/ffsb/README
@@ -0,0 +1,44 @@
+INTRODUCTION:
+=============
+This patch integrates the Flexible Filesystem Benchmark (FFSB) with
+the autotest. This integration enables the high-performace I/O load testing in the
+KVM Virtual machine environment.
+
+FFSB is a filesystem performance measurement tool.  It is a multi-threaded
+application (using pthreads), written entirely in C with cross-platform
+portability in mind.  It differs from other filesystem benchmarks in that
+the user may supply a profile to create custom workloads, while most other
+filesystem benchmarks use a fixed set of randomly generated workloads.
+
+More information about the FFSB can be got from reading the README in the
+FFSB source directory which can be accessed from this link:
+[http://sourceforge.net/projects/ffsb/]
+
+With this integration, it is now possible to test a variety of filesystems on
+the KVM guest for :
+
+(1) directed I/O with sequential/random read/write.
+(2) buffered I/O with sequential/random read/write.
+(3) use varying block alignment boundaries to measure filesystem behaviour.
+(4) use multithreaded workloads to stress the filesystem.
+(5) Exert weighted combination of I/O workloads to analyze the I/O performace
+    for a specific scenario.
+(6) Age filesystem according to a specified workload upto a specified limit.
+
+    Since the only interface used for the integration is a FFSB configuration file;
+Autotest will be able to run variety of I/O tests on guest as FFSB improves,
+with no or minimal code change in Autotest itself.
+
+USE:
+====
+To use the FFSB for Filesystem testing, two configuration files
+need to be modified -
+(1) Usual - tests.cfg file to activate the ffsb tests through KVM.
+(2) profile.cfg - where the workloads are specified.
+
+TODO:
+====
+* Add validations for max. number of threads according to number of
+  vcpus exported by QEMU-KVM
+* Test Autotest/ffsb
+* Test FFSB itself.
diff --git a/client/tests/ffsb/control b/client/tests/ffsb/control
new file mode 100644
index 0000000..c7e92eb
--- /dev/null
+++ b/client/tests/ffsb/control
@@ -0,0 +1,16 @@
+AUTHOR = "Onkar N Mahajan <onkar.n.mahajan@linux.vnet.ibm.com>"
+NAME = "Flexible Filesystem Benchmark (FFSB)"
+TEST_CATEGORY = "Filesystem Benchmark"
+TEST_CLASS = "General"
+TEST_TYPE = "client"
+TIME = 'MEDIUM'
+DOC = """
+The Flexible Filesystem Benchmark (FFSB) is a cross-platform
+filesystem performance measurement tool. It uses customizable
+profiles to measure of different workloads, and it supports
+multiple groups of threads across multiple filesystems.
+
+For more info, see http://sourceforge.net/projects/ffsb/
+"""
+
+job.run_test('ffsb')
diff --git a/client/tests/ffsb/ffsb-6.0-rc2.tar.bz2 b/client/tests/ffsb/ffsb-6.0-rc2.tar.bz2
new file mode 100644
index 0000000..96c2f18
--- /dev/null
+++ b/client/tests/ffsb/ffsb-6.0-rc2.tar.bz2
Binary files differ
diff --git a/client/tests/ffsb/ffsb.py b/client/tests/ffsb/ffsb.py
new file mode 100644
index 0000000..90e35ec
--- /dev/null
+++ b/client/tests/ffsb/ffsb.py
@@ -0,0 +1,197 @@
+import os, string, logging, re, random, shutil
+from autotest_lib.client.bin import test, os_dep, utils
+from autotest_lib.client.common_lib import error
+
+
+def find_mnt_pt(path):
+    """
+    Find on which mount point a given path is mounted.
+
+    @param path: Path we want to figure its mount point.
+    """
+    pth = os.path.abspath(path)
+    while not os.path.ismount(pth):
+        pth = os.path.dirname(pth)
+    return pth
+
+
+class ffsb(test.test):
+    """
+    This class wraps FFSB (Flexible File System Benchmark) execution
+    under autotest.
+
+    @author Onkar N Mahajan (onkar.n.mahajan@linux.vnet.ibm.com)
+    """
+    version = 1
+    params = {}
+    tempdirs = []
+    bytes = {'K':1024 , 'k':1024,
+             'M':1048576, 'm':1048576,
+             'G':1073741824, 'g':1073741824,
+             'T':1099511627776 , 't':1099511627776}
+
+
+    def initialize(self):
+        self.job.require_gcc()
+        self.results = []
+        self.nfail = 0
+
+
+    def set_ffsb_params(self, usrfl):
+        """
+        This function checks for the user supplied FFSB profile file
+        and validates it against the availble resources on the
+        guest - currently only disk space validation is supported
+        but adjusting the number of threads according to the vcpus
+        exported by the qemu-kvm also needs to be added.
+
+        @param usrfl: Path to the user profile file.
+        """
+        d = {}
+        fr = open(usrfl,'r')
+        for line in fr.read().split('\n'):
+            p = re.compile(r'\s*\t*\[{1}filesystem(\d+)\]{1}')
+            m = p.match(line)
+            if m:
+                fsno = int(line[m.start(1):m.end(1)])
+                d[fsno] = []
+            p = re.compile(r'(\s*\t*location)\=(.*)')
+            m = p.match(line)
+            if m:
+                path = line[m.start(2):m.end(2)]
+                mntpt = find_mnt_pt(path)
+                f = os.statvfs(mntpt)
+                avl_dsk_spc = f.f_bfree * f.f_bsize
+                avl_dsk_spc *= 0.95
+                d[fsno].append(mntpt)
+                d[fsno].append(int(avl_dsk_spc))
+            p = re.compile(r'(\s*\t*num_files)\=(\d+)')
+
+            m = p.match(line)
+            if m:
+                usrnumfl = int(line[m.start(2):m.end(2)])
+                d[fsno].append(usrnumfl)
+            p = re.compile(r'(\s*\t*max_filesize)\=(\d+[kKMmGgTt]?)')
+            m = p.match(line)
+            if m:
+                usrmaxflsz = line[m.start(2):m.end(2)]
+                usrmaxflsz = int(usrmaxflsz[0:-1]) * self.bytes[usrmaxflsz[-1]]
+                d[fsno].append(usrmaxflsz)
+        for k in d.keys():
+            while d[k][2]*d[k][3] >= d[k][1]:
+                d[k][2] -= 1
+            if d[k][2] == 0:
+                d[k][2] = 1
+                d[k][3] = d[k][1]
+            # If the ffsb mount point is on the same file system
+            # then use the available disk space after the previous
+            # tests
+            for k1 in d.keys():
+                if d[k1][0] == d[k][0]:
+                    d[k1][1] -= (d[k][2]*d[k][3])
+        fr.close()
+        return d
+
+
+    def dup_ffsb_profilefl(self):
+        """
+        Validates the path from the FFSB configuration file, the
+        disk space available for the test, warn the user and
+        change the file sizes and/or number of files to be used for
+        generating the workload according to the available disk space
+        on the guest.
+        """
+        self.usrfl = '%s/%s' % (os.path.split(self.srcdir)[0],'profile.cfg')
+        self.sysfl = '%s/%s' % (self.srcdir,'profile.cfg')
+
+        params = self.set_ffsb_params(self.usrfl)
+
+        fsno = 0
+        fr = open(self.usrfl,'r')
+        fw = open(self.sysfl,'w')
+        for line in fr.read().split('\n'):
+            p = re.compile(r'\s*\t*\[{1}filesystem(\d+)\]{1}')
+            m = p.match(line)
+            if m:
+                fsno = int(line[m.start(1):m.end(1)])
+            p = re.compile(r'(\s*\t*location)\=(.*)')
+            m = p.match(line)
+            if m:
+                while True:
+                    dirnm = ''.join(random.choice(string.letters) for i in xrange(9))
+                    if line[m.end(2) - 1] == '/':
+                        newline = '%s%s' % (line[0:m.end(2)], dirnm)
+                        ffsbdir = '%s%s' % (line[m.start(2):m.end(2)], dirnm)
+                    else:
+                        newline = '%s/%s' % (line[0:m.end(2)], dirnm)
+                        ffsbdir = '%s/%s' % (line[m.start(2):m.end(2)], dirnm)
+                    self.tempdirs.append(ffsbdir)
+                    if os.path.exists(ffsbdir):
+                        continue
+                    else:
+                        os.makedirs(ffsbdir)
+                        break
+                fw.write(newline+'\n')
+                continue
+            p = re.compile(r'(\s*\t*num_files)\=(.*)')
+            m = p.match(line)
+            if m:
+                newline = '%s=%s' % (line[0:m.end(1)], str(params[fsno][2]))
+                fw.write(newline+'\n')
+                continue
+            p = re.compile(r'(\s*\t*max_filesize)\=(\d+[kKMmGgTt]?)')
+            m = p.match(line)
+            if m:
+                newline = '%s%s' % (line[0:m.start(2)], str(params[fsno][3]))
+                fw.write(newline+'\n')
+                continue
+            fw.write(line+'\n')
+        fr.close()
+        fw.close()
+
+
+    def setup(self, tarball='ffsb-6.0-rc2.tar.bz2'):
+        """
+        Uncompress the FFSB tarball and compiles it.
+
+        @param tarball: FFSB tarball. Could be either a path relative to
+                self.srcdir or a URL.
+        """
+        tarball = utils.unmap_url(self.bindir, tarball, self.tmpdir)
+        utils.extract_tarball_to_dir(tarball, self.srcdir)
+        os.chdir(self.srcdir)
+        os_dep.command('gcc')
+        utils.configure()
+        utils.make()
+
+
+    def run_once(self):
+        """
+        Runs a single iteration of the FFSB.
+        """
+        self.dup_ffsb_profilefl()
+        # Run FFSB using abspath
+        cmd = '%s/ffsb %s/profile.cfg' % (self.srcdir, self.srcdir)
+        logging.info("FFSB command: %s", cmd)
+        self.results_path = os.path.join(self.resultsdir,
+                                         'raw_output_%s' % self.iteration)
+        try:
+            self.results = utils.system_output(cmd, retain_output=True)
+            logging.info(self.results)
+            utils.open_write_close(self.results_path, self.results)
+        except error.CmdError, e:
+            self.nfail += 1
+            logging.error('Failed to execute FFSB : %s', e)
+
+
+    def postprocess(self):
+        """
+        Do test postprocessing. Fail the test or clean up results.
+        """
+        if self.nfail != 0:
+            raise error.TestError('FFSB test failed.')
+        else:
+            logging.info('FFSB test passed')
+            logging.info('Cleaning up test data...')
+            for l in self.tempdirs:
+                shutil.rmtree(l)
diff --git a/client/tests/ffsb/profile.cfg.sample b/client/tests/ffsb/profile.cfg.sample
new file mode 100644
index 0000000..e68fead
--- /dev/null
+++ b/client/tests/ffsb/profile.cfg.sample
@@ -0,0 +1,25 @@
+# Large file random writes.
+# 1024 files, 100MB per file.
+
+time=300  # 5 min
+alignio=1
+
+[filesystem0]
+#   For KVM Autotest , this will by-default
+#   be / , unless and until the user is absolutely
+#   sure what is is upto.
+    location=/
+    num_files=2
+    min_filesize=1G
+    max_filesize=2G
+[end0]
+
+[threadgroup0]
+    num_threads=4
+
+    read_random=1
+    read_weight=1
+
+    read_size=5242880  # 5 MB
+    read_blocksize=4096
+[end0]
diff --git a/client/tests/kvm/base.cfg.sample b/client/tests/kvm/base.cfg.sample
new file mode 100644
index 0000000..0e6d222
--- /dev/null
+++ b/client/tests/kvm/base.cfg.sample
@@ -0,0 +1,185 @@
+# Copy this file to base.cfg and edit it.
+#
+# Define the objects we'll be using
+vms = vm1
+vm_type = kvm
+images = image1
+cdroms = cd1
+nics = nic1
+monitors = humanmonitor1
+main_monitor = humanmonitor1
+monitor_type_humanmonitor1 = human
+monitor_type = human
+main_vm = vm1
+
+# Location of the qemu programs. You can refer to absolute paths here.
+qemu_binary = qemu
+qemu_img_binary = qemu-img
+
+# Default VM params
+# Number of processors
+smp = 1
+
+# Memory
+mem = 1024
+
+# Hard disk
+image_size = 10G
+image_raw_device = no
+drive_index_image1 = 0
+drive_cache = none
+
+# Cdrom drive index
+drive_index_cd1 = 1
+
+# Display
+display = vnc
+
+# If display = spice, you can set specific spice stuff here
+qxl = on
+qxl_dev_nr = 1
+spice = disable-ticketing
+
+# NIC parameters
+nic_mode = tap
+# By default we use libvirt's bridge
+bridge = virbr0
+run_tcpdump = yes
+
+# Some preprocessor/postprocessor params
+start_vm = yes
+kill_vm = no
+kill_vm_gracefully = yes
+kill_unresponsive_vms = yes
+
+# Screendump thread params
+convert_ppm_files_to_png_on_error = yes
+keep_ppm_files = no
+keep_ppm_files_on_error = no
+take_regular_screendumps = yes
+keep_screendumps_on_error = yes
+screendump_delay = 5
+screendump_quality = 30
+screendump_temp_dir = /dev/shm
+screendump_verbose = no
+
+# Default remote shell port (SSH under linux)
+shell_port = 22
+
+# Default scheduler params
+used_cpus = 1
+used_mem = 512
+
+# Port redirections
+redirs = remote_shell
+guest_port_remote_shell = 22
+
+# Profilers
+profilers = kvm_stat
+
+# Timeouts
+login_timeout = 360
+
+# NFS directory of guest images
+images_good = fileserver.foo.com:/autotest/images_good
+
+# 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$
+
+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
+
+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
+        extra_params += " -mem-path /mnt/kvm_hugepage"
+
+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
diff --git a/client/tests/kvm/deps/heartbeat_slu.py b/client/tests/kvm/deps/heartbeat_slu.py
new file mode 100755
index 0000000..86660af
--- /dev/null
+++ b/client/tests/kvm/deps/heartbeat_slu.py
@@ -0,0 +1,205 @@
+#!/usr/bin/env python
+
+"""
+Heartbeat server/client to detect soft lockups
+"""
+
+import socket, os, sys, time, getopt
+
+def daemonize(output_file):
+    try:
+        pid = os.fork()
+    except OSError, e:
+        raise Exception, "error %d: %s" % (e.strerror, e.errno)
+
+    if pid:
+        os._exit(0)
+
+    os.umask(0)
+    os.setsid()
+    sys.stdout.flush()
+    sys.stderr.flush()
+
+    if file:
+        output_handle = file(output_file, 'a+', 0)
+        # autoflush stdout/stderr
+        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+        sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)
+    else:
+        output_handle = file('/dev/null', 'a+')
+
+    stdin_handle = open('/dev/null', 'r')
+    os.dup2(output_handle.fileno(), sys.stdout.fileno())
+    os.dup2(output_handle.fileno(), sys.stderr.fileno())
+    os.dup2(stdin_handle.fileno(), sys.stdin.fileno())
+
+def recv_all(sock):
+    total_data = []
+    while True:
+        data = sock.recv(1024)
+        if not data:
+            break
+        total_data.append(data)
+    return ''.join(total_data)
+
+def run_server(host, port, daemon, file, queue_size, threshold, drift):
+    if daemon:
+        daemonize(output_file=file)
+    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    sock.bind((host, port))
+    sock.listen(queue_size)
+    timeout_interval = threshold * 2
+    prev_check_timestamp = float(time.time())
+    while 1:
+        c_sock, c_addr = sock.accept()
+        heartbeat = recv_all(c_sock)
+        local_timestamp = float(time.time())
+        drift = check_heartbeat(heartbeat, local_timestamp, threshold, check_drift)
+        # NOTE: this doesn't work if the only client is the one that timed
+        # out, but anything more complete would require another thread and
+        # a lock for client_prev_timestamp.
+        if local_timestamp - prev_check_timestamp > threshold * 2.0:
+            check_for_timeouts(threshold, check_drift)
+            prev_check_timestamp = local_timestamp
+        if verbose:
+            if check_drift:
+                print "%.2f: %s (%s)" % (local_timestamp, heartbeat, drift)
+            else:
+                print "%.2f: %s" % (local_timestamp, heartbeat)
+
+def run_client(host, port, daemon, file, interval):
+    if daemon:
+        daemonize(output_file=file)
+    seq = 1
+    while 1:
+        try:
+            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            sock.connect((host, port))
+            heartbeat = get_heartbeat(seq)
+            sock.sendall(heartbeat)
+            sock.close()
+            if verbose:
+                print heartbeat
+        except socket.error, (value, message):
+            print "%.2f: ERROR, %d - %s" % (float(time.time()), value, message)
+
+        seq += 1
+        time.sleep(interval)
+
+def get_heartbeat(seq=1):
+    return "%s %06d %.2f" % (hostname, seq, float(time.time()))
+
+def check_heartbeat(heartbeat, local_timestamp, threshold, check_drift):
+    hostname, seq, timestamp = heartbeat.rsplit()
+    timestamp = float(timestamp)
+    if client_prev_timestamp.has_key(hostname):
+        delta = local_timestamp - client_prev_timestamp[hostname]
+        if delta > threshold:
+            print "%.2f: ALERT, SLU detected on host %s, delta %ds" \
+                % (float(time.time()), hostname, delta)
+
+    client_prev_timestamp[hostname] = local_timestamp
+
+    if check_drift:
+        if not client_clock_offset.has_key(hostname):
+            client_clock_offset[hostname] = timestamp - local_timestamp
+            client_prev_drift[hostname] = 0
+        drift = timestamp - local_timestamp - client_clock_offset[hostname]
+        drift_delta = drift - client_prev_drift[hostname]
+        client_prev_drift[hostname] = drift
+        return "drift %+4.2f (%+4.2f)" % (drift, drift_delta)
+
+def check_for_timeouts(threshold, check_drift):
+    local_timestamp = float(time.time())
+    hostname_list = list(client_prev_timestamp)
+    for hostname in hostname_list:
+        timestamp = client_prev_timestamp[hostname]
+        delta = local_timestamp - timestamp
+        if delta > threshold * 2:
+            print "%.2f: ALERT, SLU detected on host %s, no heartbeat for %ds" \
+                % (local_timestamp, hostname, delta)
+            del client_prev_timestamp[hostname]
+            if check_drift:
+                del client_clock_offset[hostname]
+                del client_prev_drift[hostname]
+
+def usage():
+    print """
+Usage:
+
+    heartbeat_slu.py --server --address <bind_address> --port <bind_port>
+                     [--file <output_file>] [--no-daemon] [--verbose]
+                     [--threshold <heartbeat threshold>]
+
+    heartbeat_slu.py --client --address <server_address> -p <server_port>
+                     [--file output_file] [--no-daemon] [--verbose]
+                     [--interval <heartbeat interval in seconds>]
+"""
+
+# host information and global data
+hostname = socket.gethostname()
+client_prev_timestamp = {}
+client_clock_offset = {}
+client_prev_drift = {}
+
+# default param values
+host_port = 9001
+host_address = ''
+interval = 1 # seconds between heartbeats
+threshold = 10 # seconds late till alert
+is_server = False
+is_daemon = True
+file_server = "/tmp/heartbeat_server.out"
+file_client = "/tmp/heartbeat_client.out"
+file_selected = None
+queue_size = 5
+verbose = False
+check_drift = False
+
+# process cmdline opts
+try:
+    opts, args = getopt.getopt(sys.argv[1:], "vhsfd:p:a:i:t:", [
+                    "server", "client", "no-daemon", "address=", "port=",
+                    "file=", "server", "interval=", "threshold=", "verbose",
+                    "check-drift", "help"])
+except getopt.GetoptError, e:
+    print "error: %s" % str(e)
+    usage()
+    exit(1)
+
+for param, value in opts:
+    if param in ["-p", "--port"]:
+        host_port = int(value)
+    elif param in ["-a", "--address"]:
+        host_address = value
+    elif param in ["-s", "--server"]:
+        is_server = True
+    elif param in ["-c", "--client"]:
+        is_server = False
+    elif param in ["--no-daemon"]:
+        is_daemon = False
+    elif param in ["-f", "--file"]:
+        file_selected = value
+    elif param in ["-i", "--interval"]:
+        interval = int(value)
+    elif param in ["-t", "--threshold"]:
+        threshold = int(value)
+    elif param in ["-d", "--check-drift"]:
+        check_drift = True
+    elif param in ["-v", "--verbose"]:
+        verbose = True
+    elif param in ["-h", "--help"]:
+        usage()
+        exit(0)
+    else:
+        print "error: unrecognized option: %s" % value
+        usage()
+        exit(1)
+
+# run until we're terminated
+if is_server:
+    file_server = file_selected or file_server
+    run_server(host_address, host_port, is_daemon, file_server, queue_size, threshold, check_drift)
+else:
+    file_client = file_selected or file_client
+    run_client(host_address, host_port, is_daemon, file_client, interval)
diff --git a/client/tests/kvm/get_started.py b/client/tests/kvm/get_started.py
index d97fd8a..4a40925 100755
--- a/client/tests/kvm/get_started.py
+++ b/client/tests/kvm/get_started.py
@@ -5,7 +5,7 @@
 @copyright: Red Hat 2010
 """
 
-import os, sys, logging, shutil
+import os, sys, logging, shutil, glob
 import common
 from autotest_lib.client.common_lib import logging_manager
 from autotest_lib.client.bin import utils
@@ -85,11 +85,10 @@
                  "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 = ["build.cfg", "cdkeys.cfg", "tests_base.cfg",
-                        "tests.cfg", "unittests.cfg", "virtio-win.cfg"]
+    config_file_list = glob.glob(os.path.join(kvm_test_dir, "*.cfg.sample"))
     for config_file in config_file_list:
-        src_file = os.path.join(kvm_test_dir, "%s.sample" % config_file)
-        dst_file = os.path.join(kvm_test_dir, config_file)
+        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)
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/guest-os.cfg.sample
similarity index 61%
rename from client/tests/kvm/tests_base.cfg.sample
rename to client/tests/kvm/guest-os.cfg.sample
index e970141..1384b71 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/guest-os.cfg.sample
@@ -1,1152 +1,5 @@
-# Copy this file to tests_base.cfg and edit it.
+# Copy this file to guest_os.cfg and edit it.
 #
-# Define the objects we'll be using
-vms = vm1
-vm_type = kvm
-images = image1
-cdroms = cd1
-nics = nic1
-monitors = humanmonitor1
-
-# 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 = yes
-
-# 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
-bridge = private
-# 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
-
-# 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
-        extra_params += " -boot d"
-        guest_port_unattended_install = 12323
-        kernel = vmlinuz
-        initrd = initrd.img
-        # uncomment the following line to test the migration in parallel
-        # migrate_background = yes
-
-        variants:
-            # Install guest from cdrom 
-            - cdrom:
-                medium = cdrom
-                redirs += " unattended_install"
-            # Install guest from http/ftp url
-            - 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 = " --append ks=REPLACE_THIS_WITH_URL_OF_KS"
-                url = REPLACE_THIS_WITH_TREE_URL
-
-    - 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
-
-    - cdrom_test: install setup image_copy unattended_install.cdrom
-        only Linux
-        start_vm = no
-        type = cdrom
-        cdrom_cd1 = orig.iso
-        max_times = 20
-
-
-# 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:
@@ -1214,8 +67,24 @@
                  image_name_stg27 = storage27
                  list_volume_command = cd /dev && \ls vd*
                  re_str = "[vhs]d[a-z][^0-9]"
+        floppy:
+            format_floppy_cmd = mkfs -t ext3 /dev/fd0
+            test_floppy_cmd = (dd if=/dev/urandom of=/mnt/test_floppy bs=1M count=1) && (rm -f /mnt/test_floppy)
+            format_floppy_cmd = mkfs -t ext3 /dev/fd0
+            source_file = /etc/passwd
+            dest_file = /mnt/passwd
+            clean_cmd = rm -f
+            mount_dir = /mnt/
+            diff_file_cmd = diff
+            copy_cmd = cp
 
         variants:
+            - CustomGuestLinux:
+                image_name = custom_image
+                image_size = 10G
+                #image_name = /dev/mapper/vg_some_label
+                #image_type_raw = yes
+
             - Fedora:
                 no setup
                 shell_prompt = "^\[.*\][\#\$]\s*$"
@@ -1225,13 +94,12 @@
                     # hold your kickstart file
                     #extra_params += " --append 'ks=floppy nicdelay=60 console=ttyS0,115200 console=tty0'"
                     extra_params += " --append 'ks=cdrom nicdelay=60 console=ttyS0,115200 console=tty0'"
-
                 variants:
                     - 8.32:
                         no setup
                         image_name = fc8-32
                         install:
-                            steps = Fedora-8-i386.steps
+                            steps = steps/Fedora-8-i386.steps
                             cdrom_cd1 = isos/linux/Fedora-8-i386-DVD.iso
                             md5sum_cd1 = dd6c79fddfff36d409d02242e7b10189
                             md5sum_1m_cd1 = dabae451bb69fbbad0e505b25144b1f9
@@ -1250,7 +118,7 @@
                         no setup
                         image_name = f8-64
                         install:
-                            steps = Fedora-8-64.steps
+                            steps = steps/Fedora-8-64.steps
                             cdrom_cd1 = isos/linux/Fedora-8-x86_64-DVD.iso
                             md5sum_cd1 = 2cb231a86709dec413425fd2f8bf5295
                             md5sum_1m_cd1 = 145f6414e19492649a56c89f0a45e719
@@ -1268,7 +136,7 @@
                     - 9.32:
                         image_name = f9-32
                         install:
-                            steps = Fedora-9-i386.steps
+                            steps = steps/Fedora-9-i386.steps
                             cdrom_cd1 = isos/linux/Fedora-9-i386-DVD.iso
                             md5sum_cd1 = 72601f685ea8c808c303353d8bf4d307
                             md5sum_1m_cd1 = f24fa25689e5863f1b99984c6feb787f
@@ -1283,11 +151,10 @@
                             md5sum_cd1 = 72601f685ea8c808c303353d8bf4d307
                             md5sum_1m_cd1 = f24fa25689e5863f1b99984c6feb787f
 
-
                     - 9.64:
                         image_name = f9-64
                         install:
-                            steps = Fedora-9-64.steps
+                            steps = steps/Fedora-9-64.steps
                             cdrom_cd1 = isos/linux/Fedora-9-x86_64-DVD.iso
                             md5sum_cd1 = 05b2ebeed273ec54d6f9ed3d61ea4c96
                             md5sum_1m_cd1 = 9822ab5097e37e8fe306ef2192727db4
@@ -1332,7 +199,7 @@
                     - 11.32:
                         image_name = f11-32
                         install:
-                            steps = Fedora-11-32.steps
+                            steps = steps/Fedora-11-32.steps
                         unattended_install:
                             unattended_file = unattended/Fedora-11.ks
                             #floppy = images/f11-32/ks.vfd
@@ -1461,23 +328,347 @@
                             md5sum_cd1 = c122a2a4f478da4a3d2d12396e84244e
                             md5sum_1m_cd1 = c02f37e293bbc85be02a7c850a61273a
 
+            - RHEL:
+                no setup
+                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 += " --append 'ks=floppy nicdelay=60 console=ttyS0,115200 console=tty0'"
+                    extra_params += " --append 'ks=cdrom nicdelay=60 console=ttyS0,115200 console=tty0'"
 
-            - 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
+                variants:
+                    - 3.9.i386:
+                        no setup autotest linux_s3 guest_s4 shutdown multi_disk
+                        image_name = rhel3.9-32
+                        mem_chk_cmd = dmidecode | awk -F: '/Maximum Capacity/ {print $2}'
+                        install:
+                            steps = 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
+                            # 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
 
-            - 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
+                    - 3.9.x86_64:
+                        no setup autotest linux_s3 guest_s4 shutdown multi_disk
+                        image_name = rhel3.9-64
+                        mem_chk_cmd = dmidecode | awk -F: '/Maximum Capacity/ {print $2}'
+                        install:
+                            steps = 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
+                            # 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
+
+                    - 4.7.i386:
+                        no setup autotest
+                        image_name = rhel4.7-32
+                        install:
+                            steps = 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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-4.7-i386-DVD.iso
+                            md5sum_cd1 = ee5092653732a88ddbaf8eef2484c500
+                            md5sum_1m_cd1 = 127081cbed825d7232331a2083975528
+                        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
+                        image_name = rhel4.7-64
+                        install:
+                            steps = 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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-4.7-x86_64-DVD.iso
+                            md5sum_cd1 = ea9dae16dd86f7d94092d0e672333292
+                            md5sum_1m_cd1 = 58fa63eaee68e269f4cb1d2edf479792
+                        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
+                        image_name = rhel4.8-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-4.8-i386-DVD.iso
+                            md5sum_cd1 = b024f0af5079539d3ef51f71fed0b194
+                            md5sum_1m_cd1 = 969c197402b9058f28a278c1f807d15b
+                        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
+                        image_name = rhel4.8-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-4.8-x86_64-DVD.iso
+                            md5sum_cd1 = 696bc877b0200cc942626673fcc3fc09
+                            md5sum_1m_cd1 = b11ac0ef7fd345ad712966972db63886
+                        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
+                        image_name = rhel5.3-32
+                        install:
+                            steps = 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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.3-i386-DVD.iso
+                            md5sum_cd1 = 371c62851611fd32ead440df6f24a296
+                            md5sum_1m_cd1 = 242318dd44152210f6ff6cdda1bfbf51
+
+                    - 5.3.x86_64:
+                        no setup
+                        image_name = rhel5.3-64
+                        install:
+                            steps = 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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.3-x86_64-DVD.iso
+                            md5sum_cd1 = c5ed6b284410f4d8212cafc78fd7a8c5
+                            md5sum_1m_cd1 = b999f437583098ea5bbd56fb1de1d011
+
+                    - 5.4.i386:
+                        no setup
+                        image_name = rhel5.4-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.4-i386-DVD.iso
+                            md5sum_cd1 = 7a12ec6599527e4f3d1790b51eadbfed
+                            md5sum_1m_cd1 = 0dbeb8f58d213752d8c029e8601abfbb
+
+                    - 5.4.x86_64:
+                        no setup
+                        image_name = rhel5.4-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.4-x86_64-DVD.iso
+                            md5sum_cd1 = 04fe3c10202402d7b389528d2bad0210
+                            md5sum_1m_cd1 = 3e74112003e88a966754849dbb8f5c3f
+
+                    - 5.5.i386:
+                        no setup
+                        image_name = rhel5.5-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.5-i386-DVD.iso
+                            md5sum_cd1 = 148858b157f275d9153797efddfc83c3
+                            md5sum_1m_cd1 = 2502cc7ddb9d0684fe08c4a83d247902
+
+                    - 5.5.x86_64:
+                        no setup
+                        image_name = rhel5.5-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.5-x86_64-DVD.iso
+                            md5sum_cd1 = f3119f883257ef9041234feda2f1cad0
+                            md5sum_1m_cd1 = a744084a03f6a08627f71527fc107a1e
+
+                    - 5.6.i386:
+                        no setup
+                        image_name = rhel5.6-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.6-i386-DVD.iso
+                            md5sum_cd1 = c214653d91b81c9a7a7f7249753d0f5d
+                            md5sum_1m_cd1 = f299a881950bfec81fd5c74484e1b1d4
+
+                    - 5.6.x86_64:
+                        no setup
+                        image_name = rhel5.6-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-5.6-x86_64-DVD.iso
+                            md5sum_cd1 = d77d3815afb381a50148ba55ad930679
+                            md5sum_1m_cd1 = 9dd97de110e391fcbed88b124a60f7a9
+
+                    - 6.0.i386:
+                        no setup
+                        nic_hotplug:
+                            modprobe_module =
+                        block_hotplug:
+                            modprobe_module =
+                        image_name = rhel6.0-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-6.0-i386-DVD.iso
+                            md5sum_cd1 = 291d234c93442405972689b4b41c14bc
+                            md5sum_1m_cd1 = ee2cc3d3babe91a1d581a07099c4318b
+
+                    - 6.0.x86_64:
+                        no setup
+                        nic_hotplug:
+                            modprobe_module =
+                        block_hotplug:
+                            modprobe_module =
+                        image_name = rhel6.0-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-6.0-x86_64-DVD.iso
+                            md5sum_cd1 = f7141396c6a19399d63e8c195354317d
+                            md5sum_1m_cd1 = b060eeef63e2c8700db54ae02056e80c
+
+                    - 6.1.i386:
+                        no setup
+                        nic_hotplug:
+                            modprobe_module =
+                        block_hotplug:
+                            modprobe_module =
+                        image_name = rhel6.1-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-6.1-i386-DVD.iso
+                            md5sum_cd1 = f8c8a310e34d26339c99d462e3557324
+                            md5sum_1m_cd1 = 12f7692e6e20be0d42b9407d956f74c3
+
+                    - 6.1.x86_64:
+                        no setup
+                        nic_hotplug:
+                            modprobe_module =
+                        block_hotplug:
+                            modprobe_module =
+                        image_name = rhel6.1-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
+                        unattended_install.cdrom:
+                            cdrom_cd1 = isos/linux/RHEL-6.1-x86_64-DVD.iso
+                            md5sum_cd1 = a051dbf28ef444a019dc6660efe3e3a4
+                            md5sum_1m_cd1 = cb3b9d140404a6797b0f423dfe620ab8
 
             - OpenSUSE:
                 no setup
@@ -1493,7 +684,7 @@
                     - 11.0.32:
                         image_name = openSUSE-11.0-32
                         install:
-                            steps = openSUSE-11.0-32.steps
+                            steps = steps/openSUSE-11.0-32.steps
                             cdrom_cd1 = isos/linux/openSUSE-11.0-DVD-i386.iso
                             md5sum_cd1 = ed6a5b3feb668866df812b1c2aed9d7f
                             md5sum_1m_cd1 = c720b30557af758e69de450409516369
@@ -1509,7 +700,6 @@
                             md5sum_cd1 = ed6a5b3feb668866df812b1c2aed9d7f
                             md5sum_1m_cd1 = c720b30557af758e69de450409516369
 
-
                     - 11.0.64:
                         image_name = openSUSE-11.0-64
                         unattended_install:
@@ -1527,7 +717,7 @@
                     - 11.1.32:
                         image_name = openSUSE-11.1-32
                         install:
-                            steps = openSUSE-11.1-32-and-64.steps
+                            steps = 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
@@ -1546,7 +736,7 @@
                     - 11.1.64:
                         image_name = openSUSE-11.1-64
                         install:
-                            steps=openSUSE-11.1-32-and-64.steps
+                            steps = 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
@@ -1562,7 +752,6 @@
                             md5sum_cd1 = 2afee1b8a87175e6dee2b8dbbd1ad8e8
                             md5sum_1m_cd1 = 768ca32503ef92c28f2d144f2a87e4d0
 
-
                     - 11.2.32:
                         image_name = openSUSE-11.2-32
                         unattended_install:
@@ -1577,7 +766,6 @@
                             md5sum_cd1 = 295d713314a30ad017948f0d542c6d92
                             md5sum_1m_cd1 = 1f8767d00acb492be5a5627c834e543f
 
-
                     - 11.2.64:
                         image_name = openSUSE-11.2-64
                         unattended_install:
@@ -1673,7 +861,6 @@
                             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
@@ -1691,7 +878,6 @@
                             md5sum_cd1 = 50a2bd45cd12c3808c3ee48208e2586b
                             md5sum_1m_cd1 = 00000951cab7c32e332362fc424c1054
 
-
                     - 11.1.32:
                         image_name = sles11sp1-32
                         unattended_install:
@@ -1720,7 +906,6 @@
                             md5sum_cd1 = d2e10420f3689faa49a004b60fb396b7
                             md5sum_1m_cd1 = f7f67b5da46923a9f01da8a2b6909654
 
-
             - @Ubuntu:
                 shell_prompt = "^root@.*[\#\$]\s*$"
 
@@ -1728,7 +913,7 @@
                     - Ubuntu-6.10-32:
                         only install
                         image_name = ubuntu-6.10-32
-                        steps = Ubuntu-6.10-32.steps
+                        steps = steps/Ubuntu-6.10-32.steps
                         cdrom_cd1 = isos/linux/ubuntu-6.10-desktop-i386.iso
                         md5sum_cd1 = 17fb825641571ce5888a718329efd016
                         md5sum_1m_cd1 = 7531d0a84e7451d17c5d976f1c3f8509
@@ -1737,376 +922,37 @@
                         skip = yes
                         image_name = ubuntu-8.04-32
                         install:
-                            steps = Ubuntu-8.04-32.steps
+                            steps = 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
+                            steps = 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
+                            steps = 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
+                            steps = steps/Ubuntu-8.10-server-32-gcc.steps
 
-            - RHEL:
-                no setup
-                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 += " --append 'ks=floppy nicdelay=60 console=ttyS0,115200 console=tty0'"
-                    extra_params += " --append 'ks=cdrom nicdelay=60 console=ttyS0,115200 console=tty0'"
+            - DSL-4.2.5:
+                no setup dbench bonnie linux_s3
+                image_name = dsl-4.2.5
+                install:
+                    steps = steps/DSL-4.2.5.steps
+                    cdrom_cd1 = isos/linux/dsl-4.2.5.iso
+                    md5sum_cd1 = 61694888aede3e01229865b8e6acd4a1
+                    md5sum_1m_cd1 = 527f2481bd25310f2e3a6e5345ff3d12
 
-                variants:
-                    - 3.9.i386:
-                        no setup autotest linux_s3 guest_s4 shutdown multi_disk
-                        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
-                            # 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
-
-                    - 3.9.x86_64:
-                        no setup autotest linux_s3 guest_s4 shutdown multi_disk
-                        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
-                            # 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
-
-
-                    - 4.7.i386:
-                        no setup autotest
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-4.7-i386-DVD.iso
-                            md5sum_cd1 = ee5092653732a88ddbaf8eef2484c500
-                            md5sum_1m_cd1 = 127081cbed825d7232331a2083975528
-                        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
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-4.7-x86_64-DVD.iso
-                            md5sum_cd1 = ea9dae16dd86f7d94092d0e672333292
-                            md5sum_1m_cd1 = 58fa63eaee68e269f4cb1d2edf479792
-                        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
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-4.8-i386-DVD.iso
-                            md5sum_cd1 = b024f0af5079539d3ef51f71fed0b194
-                            md5sum_1m_cd1 = 969c197402b9058f28a278c1f807d15b
-                        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
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-4.8-x86_64-DVD.iso
-                            md5sum_cd1 = 696bc877b0200cc942626673fcc3fc09
-                            md5sum_1m_cd1 = b11ac0ef7fd345ad712966972db63886
-                        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
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-5.3-i386-DVD.iso
-                            md5sum_cd1 = 371c62851611fd32ead440df6f24a296
-                            md5sum_1m_cd1 = 242318dd44152210f6ff6cdda1bfbf51
-
-
-                    - 5.3.x86_64:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-5.3-x86_64-DVD.iso
-                            md5sum_cd1 = c5ed6b284410f4d8212cafc78fd7a8c5
-                            md5sum_1m_cd1 = b999f437583098ea5bbd56fb1de1d011
-
-
-                    - 5.4.i386:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-5.4-i386-DVD.iso
-                            md5sum_cd1 = 7a12ec6599527e4f3d1790b51eadbfed
-                            md5sum_1m_cd1 = 0dbeb8f58d213752d8c029e8601abfbb
-
-
-                    - 5.4.x86_64:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-5.4-x86_64-DVD.iso
-                            md5sum_cd1 = 04fe3c10202402d7b389528d2bad0210
-                            md5sum_1m_cd1 = 3e74112003e88a966754849dbb8f5c3f
-
-
-                    - 5.5.i386:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-5.5-i386-DVD.iso
-                            md5sum_cd1 = 148858b157f275d9153797efddfc83c3
-                            md5sum_1m_cd1 = 2502cc7ddb9d0684fe08c4a83d247902
-
-
-                    - 5.5.x86_64:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-5.5-x86_64-DVD.iso
-                            md5sum_cd1 = f3119f883257ef9041234feda2f1cad0
-                            md5sum_1m_cd1 = a744084a03f6a08627f71527fc107a1e
-
-                    - 5.6.i386:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-5.6-i386-DVD.iso
-                            md5sum_cd1 = c214653d91b81c9a7a7f7249753d0f5d
-                            md5sum_1m_cd1 = f299a881950bfec81fd5c74484e1b1d4
-
-
-                    - 5.6.x86_64:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-5.6-x86_64-DVD.iso
-                            md5sum_cd1 = d77d3815afb381a50148ba55ad930679
-                            md5sum_1m_cd1 = 9dd97de110e391fcbed88b124a60f7a9
-
-
-                    - 6.0.i386:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-6.0-i386-DVD.iso
-                            md5sum_cd1 = 291d234c93442405972689b4b41c14bc
-                            md5sum_1m_cd1 = ee2cc3d3babe91a1d581a07099c4318b
-
-
-                    - 6.0.x86_64:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-6.0-x86_64-DVD.iso
-                            md5sum_cd1 = f7141396c6a19399d63e8c195354317d
-                            md5sum_1m_cd1 = b060eeef63e2c8700db54ae02056e80c
-
-
-                    - 6.1.i386:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-6.1-i386-DVD.iso
-                            md5sum_cd1 = f8c8a310e34d26339c99d462e3557324
-                            md5sum_1m_cd1 = 12f7692e6e20be0d42b9407d956f74c3
-
-
-                    - 6.1.x86_64:
-                        no setup
-                        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
-                        unattended_install.cdrom:
-                            cdrom_cd1 = isos/linux/RHEL-6.1-x86_64-DVD.iso
-                            md5sum_cd1 = a051dbf28ef444a019dc6660efe3e3a4
-                            md5sum_1m_cd1 = cb3b9d140404a6797b0f423dfe620ab8
-
+            - Mandriva-One-2007:
+                only install
+                image_name = mandriva-one-2007
+                steps = steps/Mandriva-One-2007-32.steps
+                cdrom_cd1 = isos/linux/mandriva-one-2007-i386.iso
+                md5sum_cd1 = 7e9e183dc11b9d39f480238e4e12bb05
+                md5sum_1m_cd1 = dc7865a75db665efc86d59bca7c1fe07
 
 
     # Windows section
@@ -2220,20 +1066,33 @@
                 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
+        floppy:
+            format_floppy_cmd = echo n|format A: /Q /V:test_floppy
+            source_file = C:\Windows\System32\cmd.exe
+            dest_file = A:\cmd.exe
+            clean_cmd = del
+            diff_file_cmd = fc
+            test_floppy_cmd = "chkdsk A:"
+            copy_cmd = copy
 
         variants:
+            - CustomGuestWindows:
+                image_name = custom_image
+                image_size = 20G
+                #image_name = /dev/mapper/vg_some_label
+                #image_type_raw = yes
             - Win2000:
                 no reboot whql
                 image_name = win2000-32
                 kill_vm_gracefully = no
                 install:
-                    steps = Win2000-32.steps
+                    steps = 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
+                    steps = steps/Win2000-32-rss.steps
                 unattended_install.cdrom:
                     cdrom_cd1 = isos/windows/Windows2000_sp4.iso
                     md5sum_cd1 = dda6039f3a9173f0f6bfae40f5efdfea
@@ -2251,9 +1110,9 @@
                             md5sum_cd1 = 743450644b1d9fe97b3cf379e22dceb0
                             md5sum_1m_cd1 = b473bf75af2d1269fec8958cf0202bfd
                             user = user
-                            steps = WinXP-32.steps
+                            steps = steps/WinXP-32.steps
                         setup:
-                            steps = WinXP-32-rss.steps
+                            steps = steps/WinXP-32-rss.steps
                         unattended_install.cdrom, whql.support_vm_install:
                             cdrom_cd1 = isos/windows/WindowsXP-sp2-vlk.iso
                             md5sum_cd1 = 743450644b1d9fe97b3cf379e22dceb0
@@ -2281,9 +1140,9 @@
                             md5sum_cd1 = 8d3f007ec9c2060cec8a50ee7d7dc512
                             md5sum_1m_cd1 = e812363ff427effc512b7801ee70e513
                             user = user
-                            steps = WinXP-64.steps
+                            steps = steps/WinXP-64.steps
                         setup:
-                            steps = WinXP-64-rss.steps
+                            steps = steps/WinXP-64-rss.steps
                         unattended_install.cdrom, whql.support_vm_install:
                             cdrom_cd1 = isos/windows/WindowsXP-64.iso
                             md5sum_cd1 = 8d3f007ec9c2060cec8a50ee7d7dc512
@@ -2321,9 +1180,9 @@
                             #md5sum_cd1 = 03e921e9b4214773c21a39f5c3f42ef7
                             #md5sum_1m_cd1 = 37c2fdec15ac4ec16aa10fdfdb338aa3
                             user = user
-                            steps = Win2003-32.steps
+                            steps = steps/Win2003-32.steps
                         setup:
-                            steps = Win2003-32-rss.steps
+                            steps = 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
@@ -2357,9 +1216,9 @@
                             #md5sum_cd1 = 5703f87c9fd77d28c05ffadd3354dbbd
                             #md5sum_1m_cd1 = 439393c384116aa09e08a0ad047dcea8
                             user = user
-                            steps = Win2003-64.steps
+                            steps = steps/Win2003-64.steps
                         setup:
-                            steps = Win2003-64-rss.steps
+                            steps = 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
@@ -2404,9 +1263,9 @@
                                     cdrom_cd1 = isos/windows/WindowsVista-32.iso
                                     md5sum_cd1 = 1008f323d5170c8e614e52ccb85c0491
                                     md5sum_1m_cd1 = c724e9695da483bc0fd59e426eaefc72
-                                    steps = Win-Vista-32.steps
+                                    steps = steps/Win-Vista-32.steps
                                 setup:
-                                    steps = WinVista-32-rss.steps
+                                    steps = steps/WinVista-32-rss.steps
                                 unattended_install.cdrom, whql.support_vm_install:
                                     cdrom_cd1 = isos/windows/WindowsVista-32.iso
                                     md5sum_cd1 = 1008f323d5170c8e614e52ccb85c0491
@@ -2443,9 +1302,9 @@
                                     cdrom_cd1 = isos/windows/WindowsVista-64.iso
                                     md5sum_cd1 = 11e2010d857fffc47813295e6be6d58d
                                     md5sum_1m_cd1 = 0947bcd5390546139e25f25217d6f165
-                                    steps = Win-Vista-64.steps
+                                    steps = steps/Win-Vista-64.steps
                                 setup:
-                                    steps = WinVista-64-rss.steps
+                                    steps = steps/WinVista-64-rss.steps
                                 unattended_install.cdrom, whql.support_vm_install:
                                     cdrom_cd1 = isos/windows/WindowsVista-64.iso
                                     md5sum_cd1 = 11e2010d857fffc47813295e6be6d58d
@@ -2484,9 +1343,9 @@
                                     md5sum_cd1 = 0bfca49f0164de0a8eba236ced47007d
                                     md5sum_1m_cd1 = 07d7f5006393f74dc76e6e2e943e2440
                                     sha1sum_cd1 = 6ca018ff96f1e9b2b310a36546b6fded99a421e6
-                                    steps = Win2008-32.steps
+                                    steps = steps/Win2008-32.steps
                                 setup:
-                                    steps = Win2008-32-rss.steps
+                                    steps = steps/Win2008-32-rss.steps
                                 unattended_install.cdrom, whql.support_vm_install:
                                     cdrom_cd1 = isos/windows/Windows2008-x86.iso
                                     md5sum_cd1 = 0bfca49f0164de0a8eba236ced47007d
@@ -2510,7 +1369,7 @@
                             -sp1:
                                 image_name += -sp1-64
                                 install:
-                                    steps = Win2008-64.steps
+                                    steps = 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
@@ -2518,7 +1377,7 @@
                                     sha1sum_cd1 = bd000374709f67e9358814db6ec8f0ddaaa16f70
                                     passwd = 1q2w3eP
                                 setup:
-                                    steps = Win2008-64-rss.steps
+                                    steps = steps/Win2008-64-rss.steps
                                 unattended_install.cdrom, whql.support_vm_install:
                                     cdrom_cd1 = isos/windows/Windows2008-x64.iso
                                     md5sum_cd1 = 27c58cdb3d620f28c36333a5552f271c
@@ -2585,9 +1444,9 @@
                             md5sum_cd1 = f43d22e4fb07bf617d573acd8785c028
                             md5sum_1m_cd1 = b44d8cf99dbed2a5cb02765db8dfd48f
                             passwd = 1q2w3eP
-                            steps = Win7-64.steps
+                            steps = steps/Win7-64.steps
                         setup:
-                            steps = Win7-64-rss.steps
+                            steps = 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
@@ -2617,14 +1476,14 @@
             - NetBSD-1.6.2:
                 image_name = NetBSD-1.6.2
                 image_size = 4G
-                steps = NetBSD-1.6.2.steps
+                steps = 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
+                steps = steps/OpenBSD-4.1-32.steps
                 cdrom_cd1 = isos/unix/openbsd41-i386-07-05-06.iso
                 md5sum_cd1 = 984790db10ebdd6fc7a9cf97abc7c967
                 md5sum_1m_cd1 = 8fc234b4b0ecfe56843a32ac1d26ed55
@@ -2638,109 +1497,25 @@
 
         variants:
             - Belenix:
-                steps = Belenix-0.7.1.steps
+                steps = 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
+                steps = 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
+                steps = 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
+                steps = 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, RHEL.4, 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
-        extra_params += " -mem-path /mnt/kvm_hugepage"
-
-
-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/kvm/subtests.cfg.sample b/client/tests/kvm/subtests.cfg.sample
new file mode 100644
index 0000000..9d9dbba
--- /dev/null
+++ b/client/tests/kvm/subtests.cfg.sample
@@ -0,0 +1,1122 @@
+# Copy this file to subtests.cfg and edit it.
+#
+# Subtests
+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
+        extra_params += " -boot d"
+        guest_port_unattended_install = 12323
+        kernel = vmlinuz
+        initrd = initrd.img
+        # Set migrate_background to yes to run migration in parallel
+        migrate_background = no
+
+        variants:
+            # Install guest from cdrom 
+            - cdrom:
+                medium = cdrom
+                redirs += " unattended_install"
+            # Install guest from http/ftp url
+            - 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 = " --append ks=REPLACE_THIS_WITH_URL_OF_KS"
+                url = REPLACE_THIS_WITH_TREE_URL
+
+    - 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
+
+    - 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
+            - ffsb:
+                test_control_file = ffsb.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
+
+    - qemu_img_commit:  install setup image_copy unattended_install.cdrom
+        type = qemu_img
+        subcommand = commit
+
+    - 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
+        no Win2000, Fedora.8, Fedora.9, Fedora.10, RHEL.3, RHEL.4, Unix, livecd
+        type = balloon_check
+        extra_params += " -balloon virtio"
+        iterations = 5
+
+    - watchdog: install setup image_copy unattended_install.cdrom
+        only RHEL.5, RHEL.6
+        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
+
+    - softlockup: install setup unattended_install.cdrom
+        only Linux
+        type = softlockup
+        softlockup_files = stress-1.0.4.tar.gz
+        stress_setup_cmd = "cd %s && tar xvf stress-1.0.4.tar.gz && cd stress-1.0.4 && ./configure && make && cd src"
+        server_setup_cmd = "%s/heartbeat_slu.py --server --threshold %s --file %s --port %s --verbose --check-drift"
+        client_setup_cmd = "%s/heartbeat_slu.py --client --address %s --file %s --port %s --interval 1"
+        stress_cmd  = "cd %s && cd stress-1.0.4 && cd src && nohup ./stress -c %s > /dev/null 2>&1&"
+        kill_monitor_cmd = "ps aux | grep heart | grep -v grep | awk '{print$2}' | xargs kill -9 > /dev/null 2>&1"
+        kill_stress_cmd = "pkill -f stress > /dev/null 2>&1"
+        drift_cmd = "tail -1 %s | awk '{print $7}'"
+        monitor_log_file_server = /tmp/heartbeat_server.log
+        monitor_log_file_client = /tmp/heartbeat_client.log
+        monitor_port = 13330
+        stress_threshold = 10
+        # time_to_run (hours) = 12, 18, 24, 48 hours
+        test_length = 0.10
+
+    - 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
+                image_name += -supportvm
+                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:
+                        image_name += -supportvm
+            - 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
+
+    - netstress_kill_guest: install setup unattended_install.cdrom
+        only Linux
+        type = netstress_kill_guest
+        image_snapshot = yes
+        nic_mode = tap
+        # There should be enough vms for build topology.
+        variants:
+            -driver:
+                mode = driver
+            -load:
+                mode = load
+                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"
+                clean_cmd = " while killall -9 netserver; do True test; done;"
+                netserver_cmd =  %s/netperf-2.4.5/src/netserver
+                netperf_cmd = %s/netperf-2.4.5/src/netperf -t %s -H %s -l 60 -- -m %s
+
+    - 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 RHEL.5, RHEL.6
+        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
+
+    - cdrom_test: install setup image_copy unattended_install.cdrom
+        only Linux
+        start_vm = no
+        type = cdrom
+        cdrom_cd1 = orig.iso
+        max_times = 20
+
+    - nmi_watchdog: install setup image_copy unattended_install.cdrom
+        type = nmi_watchdog
+        get_nmi_cmd = grep NMI /proc/interrupts
+        nmi_watchdog_type = 1
+        image_snapshot = yes
+        only Linux
+
+    - floppy: install setup image_copy unattended_install.cdrom
+        type = floppy
+        start_vm = no
+        floppy = images/test_floppy.img
+
+    - 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
+
+    - cpu_hotplug_test:
+        type = cpu_hotplug
+        cpu_hotplug_timeout = 600
+        n_cpus_add = 1
+        kill_vm = yes
+        iterations = 5
+        onoff_iterations = 100
+
+    - usb: install setup image_copy unattended_install.cdrom
+        only Linux
+        type = usb
+        kill_vm = yes
+        format_timeout = 400
+        images += " stg"
+        image_name_stg = "usbdevice"
+        image_format_stg = "qcow2"
+        image_boot_stg = no
+        drive_format_stg = "usb2"
+        drive_index_stg = 1
+        create_image_stg = yes
+        image_size_stg = 10M
+        fdisk_string = "10 MB, 10485760 bytes"
+
+    - hdparm:
+        only Linux
+        type = hdparm
+        get_disk_cmd = \ls /dev/[vhs]da
+        low_status_cmd = hdparm -a64 -d0 -u0 %s
+        device_cache_read_cmd = hdparm -tT %s
+        high_status_cmd = hdparm -a256 -d1 -u1 %s
+        cmd_timeout = 540
+        virtio_blk:
+            get_disk_cmd = \ls /dev/vda
+            low_status_cmd = hdparm -a32 -r0 %s
+            high_status_cmd = hdparm -a256 -r1 %s
+
+    # 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
diff --git a/client/tests/kvm/tests.cfg.sample b/client/tests/kvm/tests.cfg.sample
index 8e9fb1a..e260166 100644
--- a/client/tests/kvm/tests.cfg.sample
+++ b/client/tests/kvm/tests.cfg.sample
@@ -1,10 +1,35 @@
 # 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 the base config files.
+include base.cfg
+include subtests.cfg
+include guest-os.cfg
 include cdkeys.cfg
 include virtio-win.cfg
 
+# Here you can override the image name for our custom linux and windows guests
+#
+CustomGuestLinux:
+    # Here you can override the default login credentials for your custom guest
+    username = root
+    password = 123456
+    image_name = custom_image_linux
+    image_size = 10G
+    # If you want to use a block device as the vm disk, uncomment the 2 lines
+    # below, pointing the image name for the device you want
+    #image_name = /dev/mapper/vg_linux_guest
+    #image_raw_device = yes
+
+CustomGuestWindows:
+    image_name = custom_image_windows
+    image_size = 10G
+    # If you want to use a block device as the vm disk, uncomment the 2 lines
+    # below, pointing the image name for the device you want
+    #image_name = /dev/mapper/vg_windows_guest
+    #image_raw_device = yes
+
 # Modify/comment the following lines if you wish to modify the paths of the
 # image files, ISO files or qemu binaries.
 #
@@ -83,6 +108,23 @@
         only Fedora.15.64
         only unattended_install.cdrom, boot, shutdown
 
+    # Runs your own guest image (qcow2, can be adjusted), all migration tests
+    # (on a core2 duo laptop with HD and 4GB RAM, F15 host took 3 hours to run)
+    # Be warned, disk stress + migration can corrupt your image, so make sure
+    # you have proper backups
+    - @qemu_kvm_custom_migrate:
+        # We want qemu-kvm for this run
+        qemu_binary = /usr/bin/qemu-kvm
+        qemu_img_binary = /usr/bin/qemu-img
+        only qcow2
+        only rtl8139
+        only ide
+        only smp2
+        only no_pci_assignable
+        only smallpages
+        only CustomGuestLinux
+        only migrate
+
 # You may provide information about the DTM server for WHQL tests here:
 #whql:
 #    server_address = 10.20.30.40
diff --git a/client/tests/kvm/tests/cpu_hotplug.py b/client/tests/kvm/tests/cpu_hotplug.py
new file mode 100644
index 0000000..e4d79f8
--- /dev/null
+++ b/client/tests/kvm/tests/cpu_hotplug.py
@@ -0,0 +1,111 @@
+import os, logging, re
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.virt import virt_test_utils
+
+
+@error.context_aware
+def run_cpu_hotplug(test, params, env):
+    """
+    Runs CPU hotplug test:
+
+    1) Pick up a living guest
+    2) Send the monitor command cpu_set [cpu id] for each cpu we wish to have
+    3) Verify if guest has the additional CPUs showing up under
+        /sys/devices/system/cpu
+    4) Try to bring them online by writing 1 to the 'online' file inside that dir
+    5) Run the CPU Hotplug test suite shipped with autotest inside guest
+
+    @param test: KVM test object.
+    @param params: Dictionary with test parameters.
+    @param env: Dictionary with the test environment.
+    """
+    vm = env.get_vm(params["main_vm"])
+    vm.verify_alive()
+    timeout = int(params.get("login_timeout", 360))
+    session = vm.wait_for_login(timeout=timeout)
+
+    n_cpus_add = int(params.get("n_cpus_add", 1))
+    current_cpus = int(params.get("smp", 1))
+    onoff_iterations = int(params.get("onoff_iterations", 20))
+    total_cpus = current_cpus + n_cpus_add
+
+    error.context("getting guest dmesg before addition")
+    dmesg_before = session.cmd("dmesg -c")
+
+    error.context("Adding %d CPUs to guest" % n_cpus_add)
+    for i in range(total_cpus):
+        vm.monitor.cmd("cpu_set %s online" % i)
+
+    output = vm.monitor.cmd("info cpus")
+    logging.debug("Output of info cpus:\n%s", output)
+
+    cpu_regexp = re.compile("CPU #(\d+)")
+    total_cpus_monitor = len(cpu_regexp.findall(output))
+    if total_cpus_monitor != total_cpus:
+        raise error.TestFail("Monitor reports %s CPUs, when VM should have %s" %
+                             (total_cpus_monitor, total_cpus))
+
+    dmesg_after = session.cmd("dmesg -c")
+    logging.debug("Guest dmesg output after CPU add:\n%s" % dmesg_after)
+
+    # Verify whether the new cpus are showing up on /sys
+    error.context("verifying if new CPUs are showing on guest's /sys dir")
+    n_cmd = 'find /sys/devices/system/cpu/cpu[0-99] -maxdepth 0 -type d | wc -l'
+    output = session.cmd(n_cmd)
+    logging.debug("List of cpus on /sys:\n%s" % output)
+    try:
+        cpus_after_addition = int(output)
+    except ValueError:
+        logging.error("Output of '%s': %s", n_cmd, output)
+        raise error.TestFail("Unable to get CPU count after CPU addition")
+
+    if cpus_after_addition != total_cpus:
+        raise error.TestFail("%s CPUs are showing up under "
+                             "/sys/devices/system/cpu, was expecting %s" %
+                             (cpus_after_addition, total_cpus))
+
+    error.context("locating online files for guest's new CPUs")
+    r_cmd = 'find /sys/devices/system/cpu/cpu[1-99]/online -maxdepth 0 -type f'
+    online_files = session.cmd(r_cmd)
+    logging.debug("CPU online files detected: %s", online_files)
+    online_files = online_files.split().sort()
+
+    if not online_files:
+        raise error.TestFail("Could not find CPUs that can be "
+                             "enabled/disabled on guest")
+
+    for online_file in online_files:
+        cpu_regexp = re.compile("cpu(\d+)", re.IGNORECASE)
+        cpu_id = cpu_regexp.findall(online_file)[0]
+        error.context("changing online status for CPU %s" % cpu_id)
+        check_online_status = session.cmd("cat %s" % online_file)
+        try:
+            check_online_status = int(check_online_status)
+        except ValueError:
+            raise error.TestFail("Unable to get online status from CPU %s" %
+                                 cpu_id)
+        assert(check_online_status in [0, 1])
+        if check_online_status == 0:
+            error.context("Bringing CPU %s online" % cpu_id)
+            session.cmd("echo 1 > %s" % online_file)
+
+    # Now that all CPUs were onlined, let's execute the
+    # autotest CPU Hotplug test
+    control_path = os.path.join(test.bindir, "autotest_control",
+                                "cpu_hotplug.control")
+
+    timeout = int(params.get("cpu_hotplug_timeout"), 300)
+    error.context("running cpu_hotplug autotest after cpu addition")
+    virt_test_utils.run_autotest(vm, session, control_path, timeout,
+                                 test.outputdir, params)
+
+    # Last, but not least, let's offline/online the CPUs in the guest
+    # several times
+    irq = 15
+    irq_mask = "f0"
+    for i in xrange(onoff_iterations):
+        session.cmd("echo %s > /proc/irq/%s/smp_affinity" % (irq_mask, irq))
+        for online_file in online_files:
+            session.cmd("echo 0 > %s" % online_file)
+        for online_file in online_files:
+            session.cmd("echo 1 > %s" % online_file)
diff --git a/client/tests/kvm/tests/floppy.py b/client/tests/kvm/tests/floppy.py
new file mode 100644
index 0000000..e868235
--- /dev/null
+++ b/client/tests/kvm/tests/floppy.py
@@ -0,0 +1,71 @@
+import logging, time, os
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+
+
+@error.context_aware
+def run_floppy(test, params, env):
+    """
+    Test virtual floppy of guest:
+
+    1) Create a floppy disk image on host
+    2) Start the guest with this floppy image.
+    3) Make a file system on guest virtual floppy.
+    4) Calculate md5sum value of a file and copy it into floppy.
+    5) Verify whether the md5sum does match.
+
+    @param test: KVM test object.
+    @param params: Dictionary with the test parameters.
+    @param env: Dictionary with test environment.
+    """
+    def master_floppy(params):
+        error.context("creating test floppy")
+        floppy = os.path.abspath(params.get("floppy"))
+        utils.run("dd if=/dev/zero of=%s bs=512 count=2880" % floppy)
+
+
+    master_floppy(params)
+    vm = env.get_vm(params["main_vm"])
+    vm.create()
+
+    timeout = int(params.get("login_timeout", 360))
+    session = vm.wait_for_login(timeout=timeout)
+
+    dest_dir = params.get("mount_dir")
+    # If mount_dir specified, treat guest as a Linux OS
+    # Some Linux distribution does not load floppy at boot and Windows
+    # needs time to load and init floppy driver
+    if dest_dir:
+        status = session.cmd("modprobe floppy")
+    else:
+        time.sleep(20)
+
+    error.context("Formating floppy disk before using it")
+    format_cmd = params.get("format_floppy_cmd")
+    session.cmd(format_cmd, timeout=120)
+    logging.info("Floppy disk formatted successfully")
+
+    source_file = params.get("source_file")
+    dest_file = params.get("dest_file")
+
+    if dest_dir:
+        error.context("Mounting floppy")
+        session.cmd("mount /dev/fd0 %s" % dest_dir)
+    error.context("Testing floppy")
+    session.cmd(params.get("test_floppy_cmd"))
+
+    try:
+        error.context("Copying file to the floppy")
+        session.cmd("%s %s %s" % (params.get("copy_cmd"), source_file,
+                    dest_file))
+        logging.info("Succeed to copy file '%s' into floppy disk" % source_file)
+
+        error.context("Checking if the file is unchanged after copy")
+        session.cmd("%s %s %s" % (params.get("diff_file_cmd"), source_file,
+                    dest_file))
+    finally:
+        clean_cmd = "%s %s" % (params.get("clean_cmd"), dest_file)
+        session.cmd(clean_cmd)
+        if dest_dir:
+            session.cmd("umount %s" % dest_dir)
+        session.close()
diff --git a/client/tests/kvm/tests/hdparm.py b/client/tests/kvm/tests/hdparm.py
new file mode 100644
index 0000000..388049a
--- /dev/null
+++ b/client/tests/kvm/tests/hdparm.py
@@ -0,0 +1,89 @@
+import re, logging
+from autotest_lib.client.common_lib import error
+
+
+@error.context_aware
+def run_hdparm(test, params, env):
+    """
+    Test hdparm setting on linux guest os. This case will:
+    1) Set/record parameters value of hard disk to low performance status.
+    2) Perform device/cache read timings then record the results.
+    3) Set/record parameters value of hard disk to high performance status.
+    4) Perform device/cache read timings then compare two results.
+
+    @param test: KVM test object.
+    @param params: Dictionary with the test parameters.
+    @param env: Dictionary with test environment.
+    """
+    def check_setting_result(set_cmd, timeout):
+        params = re.findall("(-[a-zA-Z])([0-9]*)", set_cmd)
+        disk = re.findall("(\/+[a-z]*\/[a-z]*$)", set_cmd)[0]
+        for (param, value) in params:
+            cmd = "hdparm %s %s" % (param, disk)
+            (s, output) = session.cmd_status_output(cmd, timeout)
+            if s != 0:
+                raise error.TestError("Fail to get %s parameter value. "
+                                      "Output is:\n%s" % (param, output.strip()))
+            if value not in output:
+                raise error.TestFail("Fail to set %s parameter to value: %s"
+                                     % (param, value))
+
+
+    def perform_read_timing(disk, timeout, num=5):
+        results = 0
+        for i in range(num):
+            cmd = params.get("device_cache_read_cmd") % disk
+            (s, output) = session.cmd_status_output(cmd, timeout)
+            if s != 0:
+                raise error.TestFail("Fail to perform device/cache read"
+                                     " timings \nOutput is: %s\n" % output)
+            logging.info("Output of device/cache read timing check (%s of %s):"
+                         % (i + 1, num))
+            for line in output.strip().splitlines():
+                logging.info(line)
+            (result, unit) = re.findall("= *([0-9]*.+[0-9]*) ([a-zA-Z]*)",
+                             output)[1]
+            if unit == "kB":
+                result = float(result)/1024.0
+            results += float(result)
+        return results/num
+
+
+    vm = env.get_vm(params["main_vm"])
+    vm.create()
+    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
+    try:
+        timeout = float(params.get("cmd_timeout", 60))
+        cmd = params.get("get_disk_cmd")
+        output = session.cmd(cmd)
+        disk = output.strip()
+
+        error.context("Setting hard disk to lower performance")
+        cmd = params.get("low_status_cmd") % disk
+        session.cmd(cmd, timeout)
+
+        error.context("Checking hard disk keyval under lower performance "
+                      "settings")
+        check_setting_result(cmd, timeout)
+        low_result = perform_read_timing(disk, timeout)
+        logging.info("Average buffered disk read speed under low performance "
+                     "settings: %.2f MB/sec" % low_result)
+
+        error.context("Setting hard disk to higher performance")
+        cmd = params.get("high_status_cmd") % disk
+        session.cmd(cmd, timeout)
+
+        error.context("Checking hard disk keyval under higher performance "
+                      "settings")
+        check_setting_result(cmd, timeout)
+        high_result = perform_read_timing(disk, timeout)
+        logging.info("Average buffered disk read speed under high performance "
+                     "settings: %.2f MB/sec" % high_result)
+
+        if not float(high_result) > float(low_result):
+            raise error.TestFail("High performance setting does not "
+                                 "increase read speed\n")
+
+    finally:
+        if session:
+            session.close()
diff --git a/client/tests/kvm/tests/nmi_watchdog.py b/client/tests/kvm/tests/nmi_watchdog.py
new file mode 100644
index 0000000..a4b2349
--- /dev/null
+++ b/client/tests/kvm/tests/nmi_watchdog.py
@@ -0,0 +1,60 @@
+import time, logging
+from autotest_lib.client.common_lib import error
+
+
+@error.context_aware
+def run_nmi_watchdog(test, params, env):
+    """
+    Test the function of nmi injection and verify the response of guest
+
+    1) Log in the guest
+    2) Add 'watchdog=1' to boot option
+    2) Check if guest's NMI counter augment after injecting nmi
+
+    @param test: kvm test object
+    @param params: Dictionary with the test parameters.
+    @param env: Dictionary with test environment.
+    """
+    vm = env.get_vm(params["main_vm"])
+    vm.verify_alive()
+    timeout=int(params.get("login_timeout", 360))
+    session = vm.wait_for_login(timeout=timeout)
+    get_nmi_cmd= params.get("get_nmi_cmd")
+    kernel_version = session.get_command_output("uname -r").strip()
+    nmi_watchdog_type = int(params.get("nmi_watchdog_type"))
+    update_kernel_cmd = ("grubby --update-kernel=/boot/vmlinuz-%s "
+                         "--args='nmi_watchdog=%d'" %
+                         (kernel_version, nmi_watchdog_type))
+
+    error.context("Add 'nmi_watchdog=%d' to guest kernel cmdline and reboot"
+                  % nmi_watchdog_type)
+    session.cmd(update_kernel_cmd)
+    time.sleep(int(params.get("sleep_before_reset", 10)))
+    session = vm.reboot(session, method='shell', timeout=timeout)
+    try:
+        error.context("Getting guest's number of vcpus")
+        guest_cpu_num = session.cmd(params.get("cpu_chk_cmd"))
+
+        error.context("Getting guest's NMI counter")
+        output = session.cmd(get_nmi_cmd)
+        logging.debug(output.strip())
+        nmi_counter1 = output.split()[1:]
+
+        logging.info("Waiting 60 seconds to see if guest's NMI counter "
+                     "increases")
+        time.sleep(60)
+
+        error.context("Getting guest's NMI counter 2nd time")
+        output = session.cmd(get_nmi_cmd)
+        logging.debug(output.strip())
+        nmi_counter2 = output.split()[1:]
+
+        error.context("")
+        for i in range(int(guest_cpu_num)):
+            logging.info("vcpu: %s, nmi_counter1: %s, nmi_counter2: %s" %
+                         (i, nmi_counter1[i], nmi_counter2[i]))
+            if int(nmi_counter2[i]) <= int(nmi_counter1[i]):
+                raise error.TestFail("Guest's NMI counter did not increase "
+                                     "after 60 seconds")
+    finally:
+        session.close()
diff --git a/client/tests/kvm/tests/usb.py b/client/tests/kvm/tests/usb.py
new file mode 100644
index 0000000..4d4aa30
--- /dev/null
+++ b/client/tests/kvm/tests/usb.py
@@ -0,0 +1,90 @@
+import logging, os
+from autotest_lib.client.common_lib import error
+
+
+@error.context_aware
+def run_usb(test, params, env):
+    """
+    Test usb device of guest
+
+    1) create a image file by qemu-img
+    2) boot up a guest add this file as a usb device
+    3) check usb device information by execute monitor/guest command
+
+    @param test: kvm test object
+    @param params: Dictionary with the test parameters
+    @param env: Dictionary with test environment.
+    """
+    vm = env.get_vm(params["main_vm"])
+    vm.create()
+
+    session = vm.wait_for_login(timeout=int(params.get("login_timeout", 360)))
+
+    output = vm.monitor.cmd("info usb")
+    if "Product QEMU USB MSD" not in output:
+        logging.debug(output)
+        raise error.TestFail("Could not find mass storage device")
+
+    output = session.cmd("lsusb -v")
+    # No bus specified, default using "usb.0" for "usb-storage"
+    for i in ["ID 0000:0000", "Mass Storage", "SCSI", "QEMU USB HARDDRIVE"]:
+        if i not in output:
+            logging.debug(output)
+            raise error.TestFail("No '%s' in the output of 'lsusb -v'" % i)
+
+    output = session.cmd("fdisk -l")
+    if params.get("fdisk_string") not in output:
+        for line in output.splitlines():
+            logging.debug(line)
+        raise error.TestFail("Could not detect the usb device on fdisk output")
+
+    error.context("Formatting USB disk")
+    devname = session.cmd("ls /dev/disk/by-path/* | grep usb").strip()
+    session.cmd("yes | mkfs %s" % devname,
+                timeout=int(params.get("format_timeout")))
+
+    error.context("Mounting USB disk")
+    session.cmd("mount %s /mnt" % devname)
+
+    error.context("Creating comparison file")
+    c_file = '/tmp/usbfile'
+    session.cmd("dd if=/dev/random of=%s bs=1M count=1" % c_file)
+
+    error.context("Copying %s to USB disk" % c_file)
+    session.cmd("cp %s /mnt" % c_file)
+
+    error.context("Unmounting USB disk before file comparison")
+    session.cmd("umount %s" % devname)
+
+    error.context("Mounting USB disk for file comparison")
+    session.cmd("mount %s /mnt" % devname)
+
+    error.context("Determining md5sum for file on root fs and in USB disk")
+    md5_root = session.cmd("md5sum %s" % c_file).strip()
+    md5_usb = session.cmd("md5sum /mnt/%s" % os.path.basename(c_file)).strip()
+    md5_root = md5_root.split()[0]
+    md5_usb = md5_usb.split()[0]
+
+    error.context("")
+    if md5_root != md5_usb:
+        raise error.TestError("MD5 mismatch between file on root fs and on "
+                              "USB disk")
+
+    error.context("Unmounting USB disk after file comparison")
+    session.cmd("umount %s" % devname)
+
+    error.context("Checking if there are I/O error messages in dmesg")
+    output = session.get_command_output("dmesg")
+    io_error_msg = []
+    for line in output.splitlines():
+        if "Buffer I/O error" in line:
+            io_error_msg.append(line)
+
+    if io_error_msg:
+        e_msg = "IO error found on guest's dmesg when formatting USB device"
+        logging.error(e_msg)
+        for line in io_error_msg:
+            logging.error(line)
+        raise error.TestFail(e_msg)
+
+    session.close()
diff --git a/client/tests/wb_kupdate/wb_kupdate.py b/client/tests/wb_kupdate/wb_kupdate.py
index 9d77ed8..d180e65 100644
--- a/client/tests/wb_kupdate/wb_kupdate.py
+++ b/client/tests/wb_kupdate/wb_kupdate.py
@@ -241,7 +241,7 @@
             # Check if there is a need to remove the previously written file.
             if remove_previous:
                 logging.debug('Removing previous file instance.')
-                os.remove(file_name)
+                os.remove(sparse_file)
             else:
                 logging.debug('Not removing previous file instance.')
 
diff --git a/client/virt/kvm_monitor.py b/client/virt/kvm_monitor.py
index 3980da8..7e6a055 100644
--- a/client/virt/kvm_monitor.py
+++ b/client/virt/kvm_monitor.py
@@ -120,7 +120,10 @@
 
     def _data_available(self, timeout=0):
         timeout = max(0, timeout)
-        return bool(select.select([self._socket], [], [], timeout)[0])
+        try:
+            return bool(select.select([self._socket], [], [], timeout)[0])
+        except socket.error, e:
+            raise MonitorSocketError("Verifying data on monitor socket", e)
 
 
     def _recvall(self):
@@ -174,7 +177,6 @@
             # Find the initial (qemu) prompt
             s, o = self._read_up_to_qemu_prompt(20)
             if not s:
-                self._close_sock()
                 raise MonitorProtocolError("Could not find (qemu) prompt "
                                            "after connecting to monitor. "
                                            "Output so far: %r" % o)
@@ -432,7 +434,6 @@
             try:
                 json
             except NameError:
-                self._close_sock()
                 raise MonitorNotSupportedError("QMP requires the json module "
                                                "(Python 2.6 and up)")
 
@@ -447,7 +448,6 @@
                     break
                 time.sleep(0.1)
             else:
-                self._close_sock()
                 raise MonitorProtocolError("No QMP greeting message received")
 
             # Issue qmp_capabilities
diff --git a/client/virt/kvm_vm.py b/client/virt/kvm_vm.py
index a2f22b4..f7b8345 100644
--- a/client/virt/kvm_vm.py
+++ b/client/virt/kvm_vm.py
@@ -617,7 +617,6 @@
         @raise TAPCreationError: If fail to create tap fd
         @raise BRAddIfError: If fail to add a tap to a bridge
         @raise TAPBringUpError: If fail to bring up a tap
-        @raise PrivateBridgeError: If fail to bring the private bridge
         """
         error.context("creating '%s'" % self.name)
         self.destroy(free_mac_addresses=False)
@@ -692,8 +691,6 @@
                 if nic_params.get("nic_mode") == "tap":
                     ifname = self.get_ifname(vlan)
                     brname = nic_params.get("bridge")
-                    if brname == "private":
-                        brname = virt_test_setup.PrivateBridgeConfig().brname
                     tapfd = virt_utils.open_tap("/dev/net/tun", ifname)
                     virt_utils.add_to_bridge(ifname, brname)
                     virt_utils.bring_up_ifname(ifname)
diff --git a/client/virt/tests/file_transfer.py b/client/virt/tests/file_transfer.py
index 5f6672d..2d0ffad 100644
--- a/client/virt/tests/file_transfer.py
+++ b/client/virt/tests/file_transfer.py
@@ -74,7 +74,7 @@
 
     finally:
         logging.info('Cleaning temp file on guest')
-        session.cmd("rm -rf %s" % guest_path)
+        session.cmd("%s %s" % (clean_cmd, guest_path))
         logging.info('Cleaning temp files on host')
         try:
             os.remove(host_path)
diff --git a/client/virt/tests/iozone_windows.py b/client/virt/tests/iozone_windows.py
index 4046106..b4779c6 100644
--- a/client/virt/tests/iozone_windows.py
+++ b/client/virt/tests/iozone_windows.py
@@ -27,7 +27,7 @@
     c = params.get("iozone_cmd")
     t = int(params.get("iozone_timeout"))
     logging.info("Running IOzone command on guest, timeout %ss", t)
-    results = session.cmd_output(cmd=c, timeout=t, print_func=logging.debug)
+    results = session.cmd_output(cmd=c, timeout=t)
     utils.open_write_close(results_path, results)
 
     # Postprocess the results using the IOzone postprocessing module
diff --git a/client/virt/tests/netstress_kill_guest.py b/client/virt/tests/netstress_kill_guest.py
new file mode 100644
index 0000000..e7e0116
--- /dev/null
+++ b/client/virt/tests/netstress_kill_guest.py
@@ -0,0 +1,148 @@
+import logging, os, signal, re, time
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
+from autotest_lib.client.virt import aexpect, virt_utils
+
+
+def run_netstress_kill_guest(test, params, env):
+    """
+    Try stop network interface in VM when other VM try to communicate.
+
+    @param test: kvm test object
+    @param params: Dictionary with the test parameters
+    @param env: Dictionary with test environment.
+    """
+    def get_corespond_ip(ip):
+        """
+        Get local ip address which is used for contact ip.
+
+        @param ip: Remote ip
+        @return: Local corespond IP.
+        """
+        result = utils.run("ip route get %s" % (ip)).stdout
+        ip = re.search("src (.+)", result)
+        if ip is not None:
+            ip = ip.groups()[0]
+        return ip
+
+
+    def get_ethernet_driver(session):
+        """
+        Get driver of network cards.
+
+        @param session: session to machine
+        """
+        modules = []
+        out = session.cmd("ls -l --color=never "
+                          "/sys/class/net/*/device/driver/module")
+        for module in out.split("\n"):
+            modules.append(module.split("/")[-1])
+        modules.remove("")
+        return set(modules)
+
+
+    def kill_and_check(vm):
+        vm_pid = vm.get_pid()
+        vm.destroy(gracefully=False)
+        time.sleep(2)
+        try:
+            os.kill(vm_pid, 0)
+            logging.error("VM is not dead")
+            raise error.TestFail("VM is not dead after sending signal 0 to it")
+        except OSError:
+            logging.info("VM is dead")
+
+
+    def netload_kill_problem(session_serial):
+        netperf_dir = os.path.join(os.environ['AUTODIR'], "tests/netperf2")
+        setup_cmd = params.get("setup_cmd")
+        clean_cmd = params.get("clean_cmd")
+        firewall_flush = "iptables -F"
+
+        try:
+            utils.run(firewall_flush)
+        except:
+            logging.warning("Could not flush firewall rules on guest")
+
+        try:
+            session_serial.cmd(firewall_flush)
+        except aexpect.ShellError:
+            logging.warning("Could not flush firewall rules on guest")
+
+        for i in params.get("netperf_files").split():
+            vm.copy_files_to(os.path.join(netperf_dir, i), "/tmp")
+
+        guest_ip = vm.get_address(0)
+        server_ip = get_corespond_ip(guest_ip)
+
+        logging.info("Setup and run netperf on host and guest")
+        session_serial.cmd(setup_cmd % "/tmp", timeout=200)
+        utils.run(setup_cmd % netperf_dir)
+
+        try:
+            session_serial.cmd(clean_cmd)
+        except:
+            pass
+        session_serial.cmd(params.get("netserver_cmd") % "/tmp")
+
+        utils.run(clean_cmd, ignore_status=True)
+        utils.run(params.get("netserver_cmd") % netperf_dir)
+
+        server_netperf_cmd = params.get("netperf_cmd") % (netperf_dir, "TCP_STREAM",
+                                        guest_ip, params.get("packet_size", "1500"))
+        quest_netperf_cmd = params.get("netperf_cmd") % ("/tmp", "TCP_STREAM",
+                                       server_ip, params.get("packet_size", "1500"))
+
+        tcpdump = env.get("tcpdump")
+        pid = None
+        if tcpdump:
+            # Stop the background tcpdump process
+            try:
+                pid = int(utils.system_output("pidof tcpdump"))
+                logging.debug("Stopping the background tcpdump")
+                os.kill(pid, signal.SIGSTOP)
+            except:
+                pass
+
+        try:
+            logging.info("Start heavy network load host <=> guest.")
+            session_serial.sendline(quest_netperf_cmd)
+            utils.BgJob(server_netperf_cmd)
+
+            #Wait for create big network usage.
+            time.sleep(10)
+            kill_and_check(vm)
+
+        finally:
+            utils.run(clean_cmd, ignore_status=True)
+            if tcpdump and pid:
+                logging.debug("Resuming the background tcpdump")
+                logging.info("pid is %s" % pid)
+                os.kill(pid, signal.SIGCONT)
+
+
+    def netdriver_kill_problem(session_serial):
+        modules = get_ethernet_driver(session_serial)
+        logging.debug(modules)
+        for _ in range(50):
+            for module in modules:
+                session_serial.cmd("rmmod %s" % (module))
+                time.sleep(0.2)
+            for module in modules:
+                session_serial.cmd("modprobe %s" % (module))
+                time.sleep(0.2)
+        kill_and_check(vm)
+
+
+    vm = env.get_vm(params["main_vm"])
+    vm.verify_alive()
+    login_timeout = int(params.get("login_timeout", 360))
+    session = vm.wait_for_login(timeout=login_timeout)
+    session.close()
+    session_serial = vm.wait_for_serial_login(timeout=login_timeout)
+
+    mode = params.get("mode")
+    if mode == "driver":
+        netdriver_kill_problem(session_serial)
+    elif mode == "load":
+        netload_kill_problem(session_serial)
diff --git a/client/virt/tests/softlockup.py b/client/virt/tests/softlockup.py
new file mode 100644
index 0000000..0864d52
--- /dev/null
+++ b/client/virt/tests/softlockup.py
@@ -0,0 +1,147 @@
+import logging, os, socket, time
+from autotest_lib.client.bin import utils
+from autotest_lib.client.common_lib import error
+
+def run_softlockup(test, params, env):
+    """
+    soft lockup/drift test with stress.
+
+    1) Boot up a VM.
+    2) Build stress on host and guest.
+    3) run heartbeat with the given options on server and host.
+    3) Run for a relatively long time length. ex: 12, 18 or 24 hours.
+    4) Output the test result and observe drift.
+
+    @param test: KVM test object.
+    @param params: Dictionary with the test parameters.
+    @param env: Dictionary with test environment.
+    """
+    stress_setup_cmd = params.get("stress_setup_cmd")
+    stress_cmd = params.get("stress_cmd")
+    server_setup_cmd = params.get("server_setup_cmd")
+    drift_cmd = params.get("drift_cmd")
+    kill_stress_cmd = params.get("kill_stress_cmd")
+    kill_monitor_cmd = params.get("kill_monitor_cmd")
+
+    threshold = int(params.get("stress_threshold"))
+    monitor_log_file_server = params.get("monitor_log_file_server")
+    monitor_log_file_client = params.get("monitor_log_file_client")
+    test_length = int(3600 * float(params.get("test_length")))
+    monitor_port = int(params.get("monitor_port"))
+
+    vm = env.get_vm(params["main_vm"])
+    login_timeout = int(params.get("login_timeout", 360))
+    stress_dir = os.path.join(os.environ['AUTODIR'], "tests/stress")
+    monitor_dir = os.path.join(test.bindir, 'deps')
+
+
+    def _kill_guest_programs(session, kill_stress_cmd, kill_monitor_cmd):
+        logging.info("Kill stress and monitor on guest")
+        try:
+            session.cmd(kill_stress_cmd)
+        except:
+            pass
+        try:
+            session.cmd(kill_monitor_cmd)
+        except:
+            pass
+
+
+    def _kill_host_programs(kill_stress_cmd, kill_monitor_cmd):
+        logging.info("Kill stress and monitor on host")
+        utils.run(kill_stress_cmd, ignore_status=True)
+        utils.run(kill_monitor_cmd, ignore_status=True)
+
+
+    def host():
+        logging.info("Setup monitor server on host")
+        # Kill previous instances of the host load programs, if any
+        _kill_host_programs(kill_stress_cmd, kill_monitor_cmd)
+        # Cleanup previous log instances
+        if os.path.isfile(monitor_log_file_server):
+            os.remove(monitor_log_file_server)
+        # Opening firewall ports on host
+        utils.run("iptables -F", ignore_status=True)
+
+        # Run heartbeat on host
+        utils.run(server_setup_cmd % (monitor_dir, threshold,
+                                      monitor_log_file_server, monitor_port))
+
+        logging.info("Build stress on host")
+        # Uncompress and build stress on host
+        utils.run(stress_setup_cmd % stress_dir)
+
+        logging.info("Run stress on host")
+        # stress_threads = 2 * n_cpus
+        threads_host = 2 * utils.count_cpus()
+        # Run stress test on host
+        utils.run(stress_cmd % (stress_dir, threads_host))
+
+
+    def guest():
+        try:
+            host_ip = socket.gethostbyname(socket.gethostname())
+        except socket.error:
+            try:
+                # Hackish, but works well on stand alone (laptop) setups
+                # with access to the internet. If this fails, well, then
+                # not much else can be done...
+                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+                s.connect(("redhat.com", 80))
+                host_ip = s.getsockname()[0]
+            except socket.error, (value, e):
+                raise error.TestError("Could not determine host IP: %d %s" %
+                                      (value, e))
+
+        # Now, starting the guest
+        vm.verify_alive()
+        session = vm.wait_for_login(timeout=login_timeout)
+
+        # Kill previous instances of the load programs, if any
+        _kill_guest_programs(session, kill_stress_cmd, kill_monitor_cmd)
+        # Clean up previous log instances
+        session.cmd("rm -f %s" % monitor_log_file_client)
+
+        # Opening firewall ports on guest
+        try:
+            session.cmd("iptables -F")
+        except:
+            pass
+
+        # Get required files and copy them from host to guest
+        monitor_path = os.path.join(test.bindir, 'deps', 'heartbeat_slu.py')
+        stress_path = os.path.join(os.environ['AUTODIR'], "tests", "stress",
+                                   "stress-1.0.4.tar.gz")
+        vm.copy_files_to(monitor_path, "/tmp")
+        vm.copy_files_to(stress_path, "/tmp")
+
+        logging.info("Setup monitor client on guest")
+        # Start heartbeat on guest
+        session.cmd(params.get("client_setup_cmd") %
+                    ("/tmp", host_ip, monitor_log_file_client, monitor_port))
+
+        logging.info("Build stress on guest")
+        # Uncompress and build stress on guest
+        session.cmd(stress_setup_cmd % "/tmp", timeout=200)
+
+        logging.info("Run stress on guest")
+        # stress_threads = 2 * n_vcpus
+        threads_guest = 2 * int(params.get("smp", 1))
+        # Run stress test on guest
+        session.cmd(stress_cmd % ("/tmp", threads_guest))
+
+        # Wait and report
+        logging.debug("Wait for %d s", test_length)
+        time.sleep(test_length)
+
+        # Kill instances of the load programs on both guest and host
+        _kill_guest_programs(session, kill_stress_cmd, kill_monitor_cmd)
+        _kill_host_programs(kill_stress_cmd, kill_monitor_cmd)
+
+        # Collect drift
+        drift = utils.system_output(drift_cmd %  monitor_log_file_server)
+        logging.info("Drift noticed: %s", drift)
+
+
+    host()
+    guest()
diff --git a/client/virt/virt_env_process.py b/client/virt/virt_env_process.py
index 12918eb..8ab9e3d 100644
--- a/client/virt/virt_env_process.py
+++ b/client/virt/virt_env_process.py
@@ -86,7 +86,7 @@
 
     scrdump_filename = os.path.join(test.debugdir, "pre_%s.ppm" % name)
     try:
-        if vm.monitor:
+        if vm.monitor and params.get("take_regular_screendumps") == "yes":
             vm.monitor.screendump(scrdump_filename, debug=False)
     except kvm_monitor.MonitorError, e:
         logging.warn(e)
@@ -122,7 +122,7 @@
 
     scrdump_filename = os.path.join(test.debugdir, "post_%s.ppm" % name)
     try:
-        if vm.monitor:
+        if vm.monitor and params.get("take_regular_screenshots") == "yes":
             vm.monitor.screendump(scrdump_filename, debug=False)
     except kvm_monitor.MonitorError, e:
         logging.warn(e)
@@ -163,7 +163,7 @@
             raise
 
 
-def process(test, params, env, image_func, vm_func):
+def process(test, params, env, image_func, vm_func, vm_first=False):
     """
     Pre- or post-process VMs and images according to the instructions in params.
     Call image_func for each image listed in params and vm_func for each VM.
@@ -177,13 +177,20 @@
     # Get list of VMs specified for this test
     for vm_name in params.objects("vms"):
         vm_params = params.object_params(vm_name)
-        # Get list of images specified for this VM
-        for image_name in vm_params.objects("images"):
-            image_params = vm_params.object_params(image_name)
-            # Call image_func for each image
-            image_func(test, image_params)
-        # Call vm_func for each vm
-        vm_func(test, vm_params, env, vm_name)
+        if not vm_first:
+            # Get list of images specified for this VM
+            for image_name in vm_params.objects("images"):
+                image_params = vm_params.object_params(image_name)
+                # Call image_func for each image
+                image_func(test, image_params)
+            # Call vm_func for each vm
+            vm_func(test, vm_params, env, vm_name)
+        else:
+            vm_func(test, vm_params, env, vm_name)
+            for image_name in vm_params.objects("images"):
+                image_params = vm_params.object_params(image_name)
+                image_func(test, image_params)
+
 
 
 @error.context_aware
@@ -198,10 +205,6 @@
     """
     error.context("preprocessing")
 
-    if params.get("bridge") == "private":
-        brcfg = virt_test_setup.PrivateBridgeConfig(params)
-        brcfg.setup()
-
     # Start tcpdump if it isn't already running
     if "address_cache" not in env:
         env["address_cache"] = {}
@@ -293,7 +296,7 @@
     error.context("postprocessing")
 
     # Postprocess all VMs and images
-    process(test, params, env, postprocess_image, postprocess_vm)
+    process(test, params, env, postprocess_image, postprocess_vm, vm_first=True)
 
     # Terminate the screendump thread
     global _screendump_thread, _screendump_thread_termination_event
@@ -368,10 +371,6 @@
                         int(params.get("post_command_timeout", "600")),
                         params.get("post_command_noncritical") == "yes")
 
-    if params.get("bridge") == "private":
-        brcfg = virt_test_setup.PrivateBridgeConfig()
-        brcfg.cleanup()
-
 
 def postprocess_on_error(test, params, env):
     """
diff --git a/client/virt/virt_test_setup.py b/client/virt/virt_test_setup.py
index 1539cac..334c3cf 100644
--- a/client/virt/virt_test_setup.py
+++ b/client/virt/virt_test_setup.py
@@ -1,7 +1,7 @@
 """
 Library to perform pre/post test setup for KVM autotest.
 """
-import os, logging, time, re, sre, random
+import os, logging, time, re, random
 from autotest_lib.client.common_lib import error
 from autotest_lib.client.bin import utils
 
@@ -60,7 +60,7 @@
             tmp_list = re.split(';', test_config)
         while len(tmp_list) > 0:
             tmp_cfg = tmp_list.pop()
-            test_cfg[re.split(":", tmp_cfg)[0]] = sre.split(":", tmp_cfg)[1]
+            test_cfg[re.split(":", tmp_cfg)[0]] = re.split(":", tmp_cfg)[1]
         # Save host current config, so we can restore it during cleanup
         # We will only save the writeable part of the config files
         original_config = {}
@@ -289,189 +289,3 @@
             return
         utils.system("echo 0 > %s" % self.kernel_hp_file)
         logging.debug("Hugepage memory successfuly dealocated")
-
-
-class PrivateBridgeError(Exception):
-    def __init__(self, brname):
-        self.brname = brname
-
-    def __str__(self):
-        return "Bridge %s not available after setup" % self.brname
-
-
-class PrivateBridgeConfig(object):
-    __shared_state = {}
-    def __init__(self, params=None):
-        self.__dict__ = self.__shared_state
-        if params is not None:
-            self.brname = params.get("priv_brname", 'atbr0')
-            self.subnet = params.get("priv_subnet", '192.168.58')
-            self.ip_version = params.get("bridge_ip_version", "ipv4")
-            self.dhcp_server_pid = None
-            ports = params.get("priv_bridge_ports", '53 67').split()
-            s_port = params.get("guest_port_remote_shell", "10022")
-            if s_port not in ports:
-                ports.append(s_port)
-            ft_port = params.get("guest_port_file_transfer", "10023")
-            if ft_port not in ports:
-                ports.append(ft_port)
-            u_port = params.get("guest_port_unattended_install", "13323")
-            if u_port not in ports:
-                ports.append(u_port)
-            self.iptables_rules = self._assemble_iptables_rules(ports)
-
-
-    def _assemble_iptables_rules(self, port_list):
-        rules = []
-        index = 0
-        for port in port_list:
-            index += 1
-            rules.append("INPUT %s -i %s -p tcp -m tcp --dport %s -j ACCEPT" %
-                         (index, self.brname, port))
-            index += 1
-            rules.append("INPUT %s -i %s -p udp -m udp --dport %s -j ACCEPT" %
-                         (index, self.brname, port))
-        rules.append("FORWARD 1 -m physdev --physdev-is-bridged -j ACCEPT")
-        rules.append("FORWARD 2 -d %s.0/24 -o %s -m state "
-                     "--state RELATED,ESTABLISHED -j ACCEPT" %
-                     (self.subnet, self.brname))
-        rules.append("FORWARD 3 -s %s.0/24 -i %s -j ACCEPT" %
-                     (self.subnet, self.brname))
-        rules.append("FORWARD 4 -i %s -o %s -j ACCEPT" %
-                     (self.brname, self.brname))
-        return rules
-
-
-    def _add_bridge(self):
-        utils.system("brctl addbr %s" % self.brname)
-        ip_fwd_path = "/proc/sys/net/%s/ip_forward" % self.ip_version
-        ip_fwd = open(ip_fwd_path, "w")
-        ip_fwd.write("1\n")
-        utils.system("brctl stp %s on" % self.brname)
-        utils.system("brctl setfd %s 0" % self.brname)
-
-
-    def _bring_bridge_up(self):
-        utils.system("ifconfig %s %s.1 up" % (self.brname, self.subnet))
-
-
-    def _iptables_add(self, cmd):
-        return utils.system("iptables -I %s" % cmd)
-
-
-    def _iptables_del(self, cmd):
-        return utils.system("iptables -D %s" % cmd)
-
-
-    def _enable_nat(self):
-        for rule in self.iptables_rules:
-            self._iptables_add(rule)
-
-
-    def _start_dhcp_server(self):
-        utils.run("service dnsmasq stop")
-        utils.run("dnsmasq --strict-order --bind-interfaces "
-                  "--listen-address %s.1 --dhcp-range %s.2,%s.254 "
-                  "--dhcp-lease-max=253 "
-                  "--dhcp-no-override "
-                  "--pid-file=/tmp/dnsmasq.pid "
-                  "--log-facility=/tmp/dnsmasq.log" %
-                  (self.subnet, self.subnet, self.subnet))
-        self.dhcp_server_pid = None
-        try:
-            self.dhcp_server_pid = int(open('/tmp/dnsmasq.pid', 'r').read())
-        except ValueError:
-            raise PrivateBridgeError(self.brname)
-        logging.debug("Started internal DHCP server with PID %s",
-                      self.dhcp_server_pid)
-
-
-    def _verify_bridge(self):
-        brctl_output = utils.system_output("brctl show")
-        if self.brname not in brctl_output:
-            raise PrivateBridgeError(self.brname)
-
-
-    def setup(self):
-        brctl_output = utils.system_output("brctl show")
-        if self.brname not in brctl_output:
-            logging.debug("Configuring KVM test private bridge %s", self.brname)
-            try:
-                self._add_bridge()
-            except:
-                self._remove_bridge()
-                raise
-            try:
-                self._bring_bridge_up()
-            except:
-                self._bring_bridge_down()
-                self._remove_bridge()
-                raise
-            try:
-                self._enable_nat()
-            except:
-                self._disable_nat()
-                self._bring_bridge_down()
-                self._remove_bridge()
-                raise
-            try:
-                self._start_dhcp_server()
-            except:
-                self._stop_dhcp_server()
-                self._disable_nat()
-                self._bring_bridge_down()
-                self._remove_bridge()
-                raise
-            self._verify_bridge()
-
-
-    def _stop_dhcp_server(self):
-        if self.dhcp_server_pid is not None:
-            try:
-                os.kill(self.dhcp_server_pid, 15)
-            except OSError:
-                pass
-        else:
-            try:
-                dhcp_server_pid = int(open('/tmp/dnsmasq.pid', 'r').read())
-            except ValueError:
-                return
-            try:
-                os.kill(dhcp_server_pid, 15)
-            except OSError:
-                pass
-
-
-    def _bring_bridge_down(self):
-        utils.system("ifconfig %s down" % self.brname, ignore_status=True)
-
-
-    def _disable_nat(self):
-        for rule in self.iptables_rules:
-            split_list = rule.split(' ')
-            # We need to remove numbering here
-            split_list.pop(1)
-            rule = " ".join(split_list)
-            self._iptables_del(rule)
-
-
-    def _remove_bridge(self):
-        utils.system("brctl delbr %s" % self.brname, ignore_status=True)
-
-
-    def cleanup(self):
-        brctl_output = utils.system_output("brctl show")
-        cleanup = False
-        for line in brctl_output.split("\n"):
-            if line.startswith(self.brname):
-                # len == 4 means there is a TAP using the bridge
-                # so don't try to clean it up
-                if len(line.split()) < 4:
-                    cleanup = True
-                    break
-        if cleanup:
-            logging.debug("Cleaning up KVM test private bridge %s", self.brname)
-            self._stop_dhcp_server()
-            self._disable_nat()
-            self._bring_bridge_down()
-            self._remove_bridge()
diff --git a/client/virt/virt_test_utils.py b/client/virt/virt_test_utils.py
index 26407bc..7c3343b 100644
--- a/client/virt/virt_test_utils.py
+++ b/client/virt/virt_test_utils.py
@@ -451,7 +451,10 @@
         @param vm: VM object.
         @param local_path: Local path.
         @param remote_path: Remote path.
+
+        @return: Whether the hash differs (True) or not (False).
         """
+        hash_differs = False
         local_hash = utils.hash_file(local_path)
         basename = os.path.basename(local_path)
         output = session.cmd_output("md5sum %s" % remote_path)
@@ -466,13 +469,18 @@
             # temporary problem
             remote_hash = "0"
         if remote_hash != local_hash:
-            logging.debug("Copying %s to guest", basename)
+            hash_differs = True
+            logging.debug("Copying %s to guest "
+                          "(remote hash: %s, local hash:%s)",
+                          basename, remote_hash, local_hash)
             vm.copy_files_to(local_path, remote_path)
+        return hash_differs
 
 
-    def extract(vm, remote_path, dest_dir="."):
+    def extract(vm, remote_path, dest_dir):
         """
-        Extract a .tar.bz2 file on the guest.
+        Extract the autotest .tar.bz2 file on the guest, ensuring the final
+        destination path will be dest_dir.
 
         @param vm: VM object
         @param remote_path: Remote file path
@@ -480,11 +488,23 @@
         """
         basename = os.path.basename(remote_path)
         logging.debug("Extracting %s on VM %s", basename, vm.name)
-        e_cmd = "tar xjvf %s -C %s" % (remote_path, dest_dir)
-        session.cmd(e_cmd, timeout=120)
+        session.cmd("rm -rf %s" % dest_dir)
+        dirname = os.path.dirname(remote_path)
+        session.cmd("cd %s" % dirname)
+        session.cmd("mkdir -p %s" % os.path.dirname(dest_dir))
+        e_cmd = "tar xjvf %s -C %s" % (basename, os.path.dirname(dest_dir))
+        output = session.cmd(e_cmd, timeout=120)
+        autotest_dirname = ""
+        for line in output.splitlines():
+            autotest_dirname = line.split("/")[0]
+            break
+        if autotest_dirname != os.path.basename(dest_dir):
+            session.cmd("cd %s" % os.path.dirname(dest_dir))
+            session.cmd("mv %s %s" %
+                        (autotest_dirname, os.path.basename(dest_dir)))
 
 
-    def get_results():
+    def get_results(guest_autotest_path):
         """
         Copy autotest results present on the guest back to the host.
         """
@@ -492,15 +512,16 @@
         guest_results_dir = os.path.join(outputdir, "guest_autotest_results")
         if not os.path.exists(guest_results_dir):
             os.mkdir(guest_results_dir)
-        vm.copy_files_from("%s/results/default/*" % autotest_path,
+        vm.copy_files_from("%s/results/default/*" % guest_autotest_path,
                            guest_results_dir)
 
 
-    def get_results_summary():
+    def get_results_summary(guest_autotest_path):
         """
         Get the status of the tests that were executed on the host and close
         the session where autotest was being executed.
         """
+        session.cmd("cd %s" % guest_autotest_path)
         output = session.cmd_output("cat results/*/status")
         try:
             results = scan_results.parse_results(output)
@@ -524,36 +545,43 @@
         mig_timeout = float(params.get("mig_timeout", "3600"))
         mig_protocol = params.get("migration_protocol", "tcp")
 
-    compressed_autotest_path = os.path.relpath("/tmp/autotest.tar.bz2")
+    compressed_autotest_path = "/tmp/autotest.tar.bz2"
+    destination_autotest_path = "/usr/local/autotest"
 
     # To avoid problems, let's make the test use the current AUTODIR
     # (autotest client path) location
-    autotest_path = os.path.relpath(os.environ['AUTODIR'])
+    autotest_path = os.environ['AUTODIR']
+    autotest_basename = os.path.basename(autotest_path)
+    autotest_parentdir = os.path.dirname(autotest_path)
 
     # tar the contents of bindir/autotest
-    cmd = "tar cvjf %s %s/*" % (compressed_autotest_path, autotest_path)
+    cmd = ("cd %s; tar cvjf %s %s/*" %
+           (autotest_parentdir, compressed_autotest_path, autotest_basename))
     # Until we have nested virtualization, we don't need the kvm test :)
-    cmd += " --exclude=%s/tests/kvm" % autotest_path
-    cmd += " --exclude=%s/results" % autotest_path
-    cmd += " --exclude=%s/tmp" % autotest_path
-    cmd += " --exclude=%s/control*" % autotest_path
+    cmd += " --exclude=%s/tests/kvm" % autotest_basename
+    cmd += " --exclude=%s/results" % autotest_basename
+    cmd += " --exclude=%s/tmp" % autotest_basename
+    cmd += " --exclude=%s/control*" % autotest_basename
     cmd += " --exclude=*.pyc"
     cmd += " --exclude=*.svn"
     cmd += " --exclude=*.git"
     utils.run(cmd)
 
     # Copy autotest.tar.bz2
-    copy_if_hash_differs(vm, compressed_autotest_path, compressed_autotest_path)
+    update = copy_if_hash_differs(vm, compressed_autotest_path,
+                                  compressed_autotest_path)
 
     # Extract autotest.tar.bz2
-    extract(vm, compressed_autotest_path, "/")
+    if update:
+        extract(vm, compressed_autotest_path, destination_autotest_path)
 
-    vm.copy_files_to(control_path, os.path.join(autotest_path, 'control'))
+    vm.copy_files_to(control_path,
+                     os.path.join(destination_autotest_path, 'control'))
 
     # Run the test
     logging.info("Running autotest control file %s on guest, timeout %ss",
                  os.path.basename(control_path), timeout)
-    session.cmd("cd %s" % autotest_path)
+    session.cmd("cd %s" % destination_autotest_path)
     try:
         session.cmd("rm -f control.state")
         session.cmd("rm -rf results/*")
@@ -575,7 +603,7 @@
                 bg.start()
 
                 while bg.is_alive():
-                    logging.info("Tests is not ended, start a round of"
+                    logging.info("Autotest job did not end, start a round of "
                                  "migration")
                     vm.migrate(timeout=mig_timeout, protocol=mig_protocol)
             else:
@@ -587,20 +615,20 @@
                 bg.join()
     except aexpect.ShellTimeoutError:
         if vm.is_alive():
-            get_results()
-            get_results_summary()
+            get_results(destination_autotest_path)
+            get_results_summary(destination_autotest_path)
             raise error.TestError("Timeout elapsed while waiting for job to "
                                   "complete")
         else:
             raise error.TestError("Autotest job on guest failed "
                                   "(VM terminated during job)")
     except aexpect.ShellProcessTerminatedError:
-        get_results()
+        get_results(destination_autotest_path)
         raise error.TestError("Autotest job on guest failed "
                               "(Remote session terminated during job)")
 
-    results = get_results_summary()
-    get_results()
+    results = get_results_summary(destination_autotest_path)
+    get_results(destination_autotest_path)
 
     # Make a list of FAIL/ERROR/ABORT results (make sure FAIL results appear
     # before ERROR results, and ERROR results appear before ABORT results)
diff --git a/contrib/virt/README b/contrib/virt/README
index f7be9b3..fbf8ce7 100644
--- a/contrib/virt/README
+++ b/contrib/virt/README
@@ -20,7 +20,7 @@
 Instalation:
 ------------
 
-1) copy the site_job.py file to <autotest_root>/cli/,
+1) copy (or link) the site_job.py file to <autotest_root>/cli/,
 usually /usr/local/autotest/cli.
 
 2) validate it is working by running:
@@ -31,7 +31,7 @@
 
 ...
   -T, --template        Control file is actually a template
-  --extra-cartesian-config=EXTRA_CARTESIAN_CONFIG
+  -x EXTRA_CARTESIAN_CONFIG, --extra-cartesian-config=EXTRA_CARTESIAN_CONFIG
                         Add extra configuration to the cartesian config file
   --timestamp           Add a timestamp to the name of the job
   --koji-arch=KOJI_ARCH
@@ -56,7 +56,7 @@
 
   # <autotest_root>/cli/atest job create -s -m "yourmail@yourdomain.org" \
     -f "<autotest_root>/contrib/virt/control.template" -T --timestamp \
-    --extra-cartesian-config='only qemu-git..sanity' "Upstream qemu.git sanity"
+    -x 'only qemu-git..sanity' "Upstream qemu.git sanity"
 
 2) To run a test with specific packages built on koji:
 
@@ -65,10 +65,10 @@
     --koji-tag=f15 --koji-pkg=':qemu-kvm:qemu-kvm,qemu-img,qemu-kvm-tools' \
     --koji-pkg='seabios' --koji-pkg='vgabios' --koji-pkg=':gpxe:gpxe-roms-qemu' \
     --koji-pkg=':spice-server:spice-server' \
-    --extra-cartersian-config='only f15-koji..sanity' "Fedora 15 Koji Sanity"
+    -x 'only f15-koji..sanity' "Fedora 15 Koji Sanity"
 
 
-Contribute by (who to bug):
----------------------------
+Contributed by (who to bug):
+----------------------------
 Cleber Rosa (crosa@redhat.com)
 Lucas Meneghel Rodrigues (lmr@redhat.com)
diff --git a/contrib/virt/site_job.py b/contrib/virt/site_job.py
index e75b438..98c738b 100644
--- a/contrib/virt/site_job.py
+++ b/contrib/virt/site_job.py
@@ -24,7 +24,8 @@
         super(site_job_create, self).__init__()
         self.parser.add_option('-T', '--template', action='store_true',
                                help='Control file is actually a template')
-        self.parser.add_option('--extra-cartesian-config',
+        self.parser.add_option('-x', '--extra-cartesian-config',
+                               action='append',
                                help='Add extra configuration to the cartesian '
                                'config file')
         self.parser.add_option('--timestamp', action='store_true',
@@ -131,7 +132,7 @@
         '''
         extra = []
         if self.command_line_options.extra_cartesian_config:
-            extra.append(self.command_line_options.extra_cartesian_config)
+            extra += self.command_line_options.extra_cartesian_config
 
         if self.command_line_options.koji_tag:
             extra.append("koji_tag = %s" % self.command_line_options.koji_tag)
diff --git a/database/database_connection_unittest.py b/database/database_connection_unittest.py
index b5386af..058ed4d 100755
--- a/database/database_connection_unittest.py
+++ b/database/database_connection_unittest.py
@@ -6,7 +6,7 @@
 from autotest_lib.client.common_lib.test_utils import mock
 from autotest_lib.database import database_connection
 
-_CONFIG_SECTION = 'TKO'
+_CONFIG_SECTION = 'AUTOTEST_WEB'
 _HOST = 'myhost'
 _USER = 'myuser'
 _PASS = 'mypass'
diff --git a/frontend/db/backends/afe_sqlite/validation.py b/frontend/db/backends/afe_sqlite/validation.py
deleted file mode 100644
index 616d7d8..0000000
--- a/frontend/db/backends/afe_sqlite/validation.py
+++ /dev/null
@@ -1 +0,0 @@
-from django.db.backends.sqlite3.validation import *
diff --git a/frontend/settings.py b/frontend/settings.py
index 0b29abd..f3fe423 100644
--- a/frontend/settings.py
+++ b/frontend/settings.py
@@ -20,7 +20,7 @@
 MANAGERS = ADMINS
 
 def _get_config(config_key, default=None):
-  return c.get_config_value(_section, config_key, default=default)
+    return c.get_config_value(_section, config_key, default=default)
 
 AUTOTEST_DEFAULT = {
     'ENGINE': 'autotest_lib.frontend.db.backends.afe',
diff --git a/frontend/shared/resource_lib.py b/frontend/shared/resource_lib.py
index fff8ff0..86cc583 100644
--- a/frontend/shared/resource_lib.py
+++ b/frontend/shared/resource_lib.py
@@ -322,7 +322,7 @@
 
     def __init__(self, request, instance):
         assert self.model is not None
-        super(Entry, self).__init__(request)
+        super(InstanceEntry, self).__init__(request)
         self.instance = instance
         self._is_prepared_for_full_representation = False
 
diff --git a/frontend/tko/csv_encoder.py b/frontend/tko/csv_encoder.py
index 27bced8..f12e878 100644
--- a/frontend/tko/csv_encoder.py
+++ b/frontend/tko/csv_encoder.py
@@ -24,7 +24,7 @@
 
 
     def encode(self):
-        raise NotImplemented
+        raise NotImplementedError
 
 
 class UnhandledMethodEncoder(CsvEncoder):
diff --git a/global_config.ini b/global_config.ini
index cf11be9..459183b 100644
--- a/global_config.ini
+++ b/global_config.ini
@@ -27,17 +27,6 @@
 # is too much verbosity for 'production' systems, hence turned off by default.
 sql_debug_mode: False
 
-[TKO]
-host: localhost
-database: tko
-db_type: mysql
-user: autotest
-password: please_set_this_password
-
-[PLANNER]
-# 3 months
-execution_engine_timeout: 2160
-
 [AUTOSERV]
 # Autotest potential install paths
 client_autodir_paths: /usr/local/autotest
@@ -45,6 +34,9 @@
 [CLIENT]
 drop_caches: True
 drop_caches_between_iterations: True
+# Specify an alternate location to store the test results
+#output_dir: /var/log/autotest/
+output_dir:
 
 [SERVER]
 hostname: autotest
diff --git a/mirror/database.py b/mirror/database.py
index 3cbcf6d..5396b4a 100644
--- a/mirror/database.py
+++ b/mirror/database.py
@@ -24,7 +24,7 @@
 
     def __eq__(self, other):
         if not isinstance(other, item):
-            return NotImplemented
+            return NotImplementedError
 
         return (self.name == other.name and self.size == other.size and
                 self.timestamp == other.timestamp)
@@ -46,7 +46,7 @@
         Should be implemented to open and read the persistent contents of
         the database and return it as a key->value dictionary.
         """
-        raise NotImplemented('get_dictionary not implemented')
+        raise NotImplementedError('get_dictionary not implemented')
 
 
     def merge_dictionary(self, values):
@@ -55,7 +55,7 @@
         database persistent contents (ie to update existent entries and to add
         those that do not exist).
         """
-        raise NotImplemented('merge_dictionary not implemented')
+        raise NotImplementedError('merge_dictionary not implemented')
 
 
 class dict_database(database):
diff --git a/mirror/source.py b/mirror/source.py
index ec60250..4c6e51c 100644
--- a/mirror/source.py
+++ b/mirror/source.py
@@ -24,7 +24,7 @@
 
 
     def get_new_files(self):
-        raise NotImplemented('get_new_files not implemented')
+        raise NotImplementedError('get_new_files not implemented')
 
 
     def store_files(self, files):
diff --git a/mirror/trigger.py b/mirror/trigger.py
index 87e5e6d..f1b5091 100644
--- a/mirror/trigger.py
+++ b/mirror/trigger.py
@@ -1,4 +1,4 @@
-import email.Message, os, re, smtplib
+import email, os, re, smtplib
 
 from autotest_lib.server import frontend
 
@@ -32,7 +32,7 @@
 
         @param kernel_list: a sequence of kernel filenames (strings)
         """
-        raise NotImplemented('__call__ not implemented')
+        raise NotImplementedError('__call__ not implemented')
 
 
 class map_action(base_action):
diff --git a/server/frontend.py b/server/frontend.py
index 0850c58..eb7b23c 100644
--- a/server/frontend.py
+++ b/server/frontend.py
@@ -798,7 +798,7 @@
         self.hash = hash
         self.__dict__.update(hash)
         self.job = Job(afe, self.job)
-        if self.host:
+        if getattr(self, 'host'):
             self.host = Host(afe, self.host)
 
 
diff --git a/server/hosts/logfile_monitor.py b/server/hosts/logfile_monitor.py
index 9595cc8..e5990f3 100644
--- a/server/hosts/logfile_monitor.py
+++ b/server/hosts/logfile_monitor.py
@@ -123,7 +123,6 @@
     # Setup warning stream before we actually launch
     warning_stream = os.fdopen(r, 'r', 0)
 
-    devnull_r = open(os.devnull, 'r')
     devnull_w = open(os.devnull, 'w')
     # Launch console.py locally
     console_proc = subprocess.Popen(
diff --git a/server/hosts/monitors/console.py b/server/hosts/monitors/console.py
index 69d5447..c516f9f 100755
--- a/server/hosts/monitors/console.py
+++ b/server/hosts/monitors/console.py
@@ -3,8 +3,9 @@
 # Script for translating console output (from STDIN) into Autotest
 # warning messages.
 
-import optparse, os, sys
-import monitors_util
+import gzip, optparse, os, signal, sys, time
+import common
+from autotest_lib.server.hosts.monitors import monitors_util
 
 PATTERNS_PATH = os.path.join(os.path.dirname(__file__), 'console_patterns')
 
@@ -20,13 +21,53 @@
     help='Path to alert hook patterns file')
 
 
+def _open_logfile(logfile_base_name):
+    """Opens an output file using the given name.
+
+    A timestamp and compression is added to the name.
+
+    @param logfile_base_name - The log file path without a compression suffix.
+    @returns An open file like object.  Its close method must be called before
+            exiting or data may be lost due to internal buffering.
+    """
+    timestamp = int(time.time())
+    while True:
+        logfile_name = '%s.%d-%d.gz' % (logfile_base_name,
+                                        timestamp, os.getpid())
+        if not os.path.exists(logfile_name):
+            break
+        timestamp += 1
+    logfile = gzip.GzipFile(logfile_name, 'w')
+    return logfile
+
+
+def _set_logfile_close_signal_handler(logfile):
+    """Setup a signal handler to explicitly call logfile.close() and exit.
+
+    Because we are writing a compressed file we need to make sure we properly
+    close to flush our internal buffer on exit. logfile_monitor.py sends us
+    a SIGTERM and waits 5 seconds for before sending a SIGKILL so we have
+    plenty of time to do this.
+
+    @param logfile - An open file object to be closed on SIGTERM.
+    """
+    def _on_signal_close_logfile_before_exit(unused_signal_no, unused_frame):
+        logfile.close()
+        os.exit(1)
+    signal.signal(signal.SIGTERM, _on_signal_close_logfile_before_exit)
+
+
+def _unset_signal_handler():
+    signal.signal(signal.SIGTERM, signal.SIG_DFL)
+
+
 def main():
     (options, args) = parser.parse_args()
     if len(args) != 2:
         parser.print_help()
         sys.exit(1)
 
-    logfile = open(args[0], 'a', 0)
+    logfile = _open_logfile(args[0])
     warnfile = os.fdopen(int(args[1]), 'w', 0)
     # For now we aggregate all the alert_hooks.
     alert_hooks = []
@@ -34,8 +75,13 @@
         alert_hooks.extend(monitors_util.build_alert_hooks_from_path(
                 patterns_path, warnfile))
 
-    monitors_util.process_input(
-        sys.stdin, logfile, options.log_timestamp_format, alert_hooks)
+    _set_logfile_close_signal_handler(logfile)
+    try:
+        monitors_util.process_input(
+            sys.stdin, logfile, options.log_timestamp_format, alert_hooks)
+    finally:
+        logfile.close()
+        _unset_signal_handler()
 
 
 if __name__ == '__main__':
diff --git a/server/hosts/monitors/console_unittest.py b/server/hosts/monitors/console_unittest.py
new file mode 100755
index 0000000..b079a68
--- /dev/null
+++ b/server/hosts/monitors/console_unittest.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+
+"""Tests for console.py"""
+
+import os, shutil, signal, StringIO, tempfile
+
+import common
+from autotest_lib.client.common_lib.test_utils import mock
+from autotest_lib.client.common_lib.test_utils import unittest
+from autotest_lib.server.hosts.monitors import console
+
+class console_test(unittest.TestCase):
+    def setUp(self):
+        self.god = mock.mock_god()
+        self.tempdir = tempfile.mkdtemp()
+
+
+    def tearDown(self):
+        shutil.rmtree(self.tempdir)
+
+
+    def test_open_logfile(self):
+        path = os.path.join(self.tempdir, 'its-log-log')
+        fun_log = console._open_logfile(path)
+        fun_log.write("it's big it's heavy it's wood.\n")
+        fun_log.close()
+
+        # Open it again to ensure the original gets renamed.
+        fun_log = console._open_logfile(path)
+        fun_log.write("it's better than bad, it's good!\n")
+        fun_log.close()
+
+        log_file_list = os.listdir(self.tempdir)
+        self.assertEqual(2, len(log_file_list))
+        for name in log_file_list:
+            self.assertTrue(name.startswith('its-log-log.'),
+                            'unexpected name %s' % name)
+            self.assertTrue(name.endswith('.gz'), 'unexpected name %s' % name)
+
+
+    def test_logfile_close_signal_handler(self):
+        self.god.stub_function(os, 'exit')
+        os.exit.expect_call(1)
+        logfile = StringIO.StringIO()
+        console._set_logfile_close_signal_handler(logfile)
+        try:
+            self.assertFalse(logfile.closed)
+            os.kill(os.getpid(), signal.SIGTERM)
+        finally:
+            console._unset_signal_handler()
+        self.god.check_playback()
+        self.assertTrue(logfile.closed)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/server/hosts/ssh_host.py b/server/hosts/ssh_host.py
index 2f5a080..6085578 100644
--- a/server/hosts/ssh_host.py
+++ b/server/hosts/ssh_host.py
@@ -181,8 +181,7 @@
 
         # We ignore the status, because we will handle it at the end.
         result = self.run(command, timeout, ignore_status=True,
-                          connect_timeout=connect_timeout,
-                          stderr_is_expected=ignore_status)
+                          connect_timeout=connect_timeout)
 
         # Look for the patterns, in order
         for (regexp, stream) in ((stderr_err_regexp, result.stderr),
diff --git a/server/self-test/autotest_test.py b/server/self-test/autotest_test.py
index cf4e9a9..6e9df7b 100755
--- a/server/self-test/autotest_test.py
+++ b/server/self-test/autotest_test.py
@@ -11,14 +11,11 @@
 import sys
 import unittest
 
-# Adjust the path so Python can find the autoserv modules
-src = os.path.abspath("%s/.." % (os.path.dirname(sys.argv[0]),))
-if src not in sys.path:
-    sys.path.insert(1, src)
+import common
 
-import utils
-import autotest
-import hosts
+from autotest_lib.server import utils
+from autotest_lib.server import autotest
+from autotest_lib.server import hosts
 
 
 class AutotestTestCase(unittest.TestCase):
diff --git a/server/self-test/common.py b/server/self-test/common.py
new file mode 100644
index 0000000..41607e1
--- /dev/null
+++ b/server/self-test/common.py
@@ -0,0 +1,8 @@
+import os, sys
+dirname = os.path.dirname(sys.modules[__name__].__file__)
+autotest_dir = os.path.abspath(os.path.join(dirname, "..", ".."))
+client_dir = os.path.join(autotest_dir, "client")
+sys.path.insert(0, client_dir)
+import setup_modules
+sys.path.pop(0)
+setup_modules.setup(base_path=autotest_dir, root_module_name="autotest_lib")
diff --git a/server/self-test/utils_test.py b/server/self-test/utils_test.py
index fffbf9a..e1b2de3 100755
--- a/server/self-test/utils_test.py
+++ b/server/self-test/utils_test.py
@@ -12,13 +12,9 @@
 import os.path
 import unittest
 
-# Adjust the path so Python can find the autoserv modules
-src = os.path.abspath("%s/.." % (os.path.dirname(sys.argv[0]),))
-if src not in sys.path:
-    sys.path.insert(1, src)
+import common
 
-import utils
-
+from autotest_lib.server import utils
 
 
 class UtilsTestCase(unittest.TestCase):
diff --git a/server/source_kernel.py b/server/source_kernel.py
index bdd5891..6d5850f 100644
--- a/server/source_kernel.py
+++ b/server/source_kernel.py
@@ -22,7 +22,7 @@
     implement the unimplemented methods in parent classes.
     """
     def __init__(self, k):
-        super(kernel.Kernel, self).__init__()
+        super(SourceKernel, self).__init__()
         self.__kernel = k
         self.__patch_list = []
         self.__config_file = None
diff --git a/tko/parsers/base.py b/tko/parsers/base.py
index 37429b6..eb57643 100644
--- a/tko/parsers/base.py
+++ b/tko/parsers/base.py
@@ -61,10 +61,10 @@
     def make_job(dir):
         """ Create a new instance of the job model used by the
         parser, given a results directory."""
-        raise NotImplemented
+        raise NotImplementedError
 
 
     def state_iterator(self, buffer):
         """ A generator method that implements the actual parser
         state machine. """
-        raise NotImplemented
+        raise NotImplementedError
diff --git a/tko/parsers/test/__init__.py b/tko/parsers/test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tko/parsers/test/__init__.py
diff --git a/tko/parsers/test/templates/__init__.py b/tko/parsers/test/templates/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tko/parsers/test/templates/__init__.py
diff --git a/tko/parsers/test/templates/scenario_package_common.py b/tko/parsers/test/templates/scenario_package_common.py
index 0dc6e77..08a914c 100644
--- a/tko/parsers/test/templates/scenario_package_common.py
+++ b/tko/parsers/test/templates/scenario_package_common.py
@@ -1,7 +1,7 @@
-# This is meant to run from within a scenerio package
+# This is meant to run from within a scenario package
 import os, sys
 dirname = os.path.dirname(sys.modules[__name__].__file__)
-autotest_dir = os.path.abspath(os.path.join(dirname, "..", "..", "..", "..", ".."))
+autotest_dir = os.path.abspath(os.path.join(dirname, "..", "..", "..", ".."))
 client_dir = os.path.join(autotest_dir, "client")
 sys.path.insert(0, client_dir)
 import setup_modules
diff --git a/utils/run_pylint.py b/utils/run_pylint.py
index 3c3e225..515814a 100755
--- a/utils/run_pylint.py
+++ b/utils/run_pylint.py
@@ -53,15 +53,15 @@
 blacklist = ['/contrib/*', '/frontend/afe/management.py']
 
 # only show errors
-# there are two major sources of E1101/E1103 false positives:
+# there are three major sources of E1101/E1103/E1120 false positives:
 # * common_lib.enum.Enum objects
 # * DB model objects (scheduler models are the worst, but Django models also
 #   generate some errors)
 if pylint_version >= 0.21:
-    pylint_base_opts = ['--disable=W,R,C,E1101,E1103']
+    pylint_base_opts = ['--disable=W,R,C,E1101,E1103,E1120']
 else:
     pylint_base_opts = ['--disable-msg-cat=warning,refactor,convention',
-                        '--disable-msg=E1101,E1103']
+                        '--disable-msg=E1101,E1103,E1120']
 pylint_base_opts += ['--reports=no',
                      '--include-ids=y']