diff mbox

[KVM-AUTOTEST,1/2,virtio-console] Add subtest layer and prepare to add new tests.

Message ID 1290433139-13805-1-git-send-email-jzupka@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jiri Zupka Nov. 22, 2010, 1:38 p.m. UTC
None
diff mbox

Patch

diff --git a/client/tests/kvm/scripts/virtio_guest.py b/client/tests/kvm/scripts/virtio_guest.py
index 4862ef2..87727c7 100755
--- a/client/tests/kvm/scripts/virtio_guest.py
+++ b/client/tests/kvm/scripts/virtio_guest.py
@@ -3,35 +3,23 @@ 
 """
 Auxiliary script used to send data between ports on guests.
 
-@copyright: 2008-2009 Red Hat Inc.
+@copyright: 2010 Red Hat, Inc.
 @author: Jiri Zupka (jzupka@redhat.com)
 @author: Lukas Doktor (ldoktor@redhat.com)
 """
-#from _pydev_SimpleXMLRPCServer import fcntl
-
-"""
-TODO:
-virt.init([consoles])   # sysfs, udev, OK
-virt.open(name)
-virt.close(name)
-virt.poll(name, eventmask, timeout) # poll.register(), poll.poll(),
-return event
-virt.send(name, length) # host disconnected
-virt.recv(name, length) # host disconnected
-virt.blocking(name, true)   # true = blocking, false = nonblocking
-virt.loopback(in_names, out_names, type="None")  # use select/poll
-"""
-
 import threading
 from threading import Thread
-import os, time, select, re, random, sys, array, fcntl, array, subprocess
+import os, time, select, re, random, sys, array
+import fcntl, array, subprocess, traceback
 
 DEBUGPATH = "/sys/kernel/debug"
 SYSFSPATH = "/sys/class/virtio-ports/"
 
 
-class virtio_guest():
-
+class VirtioGuest:
+    """
+    Test tools of virtio_ports.
+    """
     LOOP_NONE = 0
     LOOP_POLL = 1
     LOOP_SELECT = 2
@@ -125,7 +113,7 @@  class virtio_guest():
         print "PASS: Init and check virtioconsole files in system."
 
 
-    class switch(Thread):
+    class Switch(Thread):
         """
         Thread that sends data between ports.
         """
@@ -137,7 +125,7 @@  class virtio_guest():
             @param method: Method of read/write access.
             @param cachesize: Block to receive and send.
             """
-            Thread.__init__(self)
+            Thread.__init__(self, name="Switch")
 
             self.in_files = in_files
             self.out_files = out_files
@@ -211,15 +199,15 @@  class virtio_guest():
 
 
         def run(self):
-            if (self.method == virtio_guest.LOOP_POLL):
+            if (self.method == VirtioGuest.LOOP_POLL):
                 self._poll_mode()
-            elif (self.method == virtio_guest.LOOP_SELECT):
+            elif (self.method == VirtioGuest.LOOP_SELECT):
                 self._select_mode()
             else:
                 self._none_mode()
 
 
-    class sender(Thread):
+    class Sender(Thread):
         """
         Creates a thread which sends random blocks of data to dst port.
         """
@@ -228,7 +216,7 @@  class virtio_guest():
             @param port: Destination port
             @param length: Length of the random data block
             """
-            Thread.__init__(self)
+            Thread.__init__(self, name="Sender")
             self.port = port
             self.exit_thread = event
             self.data = array.array('L')
@@ -296,7 +284,20 @@  class virtio_guest():
         if (mask[0][1] & expected) == expected:
             print "PASS: Events: " + str
         else:
-            print "FAIL: Events: " + str
+            estr = ""
+            if (expected & select.POLLIN):
+                estr += "IN "
+            if (expected & select.POLLPRI):
+                estr += "PRI IN "
+            if (expected & select.POLLOUT):
+                estr += "OUT "
+            if (expected & select.POLLERR):
+                estr += "ERR "
+            if (expected & select.POLLHUP):
+                estr += "HUP "
+            if (expected & select.POLLMSG):
+                estr += "MSG "
+            print "FAIL: Events: " + str + "  Expected: " + estr
 
 
     def blocking(self, port, mode=False):
@@ -306,8 +307,7 @@  class virtio_guest():
         @param port: port to set mode
         @param mode: False to set nonblock mode, True for block mode
         """
-        path = self.ports[port]["path"]
-        fd = self.files[path]
+        fd = self._open([port])[0]
 
         try:
             fl = fcntl.fcntl(fd, fcntl.F_GETFL)
@@ -336,24 +336,28 @@  class virtio_guest():
             if path in self.files.keys():
                 descriptor = self.files[path]
                 del self.files[path]
-        try:
-            os.close(descriptor)
-        except Exception as inst:
-            print "FAIL: Closing the file: " + str(inst)
-            return
+            if descriptor != None:
+                try:
+                    os.close(descriptor)
+                except Exception as inst:
+                    print "FAIL: Closing the file: " + str(inst)
+                    return
         print "PASS: Close"
 
 
-    def open(self, in_files):
+    def open(self, in_file):
         """
         Direct open devices.
 
-        @param in_files: Array of files.
+        @param in_file: Array of files.
         @return: Array of descriptors.
         """
-        name = self.ports[in_files]["path"]
+        name = self.ports[in_file]["path"]
         try:
             self.files[name] = os.open(name, os.O_RDWR)
+            if (self.ports[in_file]["is_console"] == "yes"):
+                print os.system("stty -F %s raw -echo" % (name))
+                print os.system("stty -F %s -a" % (name))
             print "PASS: Open all filles correctly."
         except Exception as inst:
             print "%s\nFAIL: Failed open file %s" % (str(inst), name)
@@ -374,7 +378,7 @@  class virtio_guest():
         in_f = self._open(in_files)
         out_f = self._open(out_files)
 
-        s = self.switch(in_f, out_f, self.exit_thread, cachesize, mode)
+        s = self.Switch(in_f, out_f, self.exit_thread, cachesize, mode)
         s.start()
         self.threads.append(s)
         print "PASS: Start switch"
@@ -412,7 +416,7 @@  class virtio_guest():
         self.ports = self._get_port_status()
         in_f = self._open([port])
 
-        self.threads.append(self.sender(in_f[0], self.exit_thread, length))
+        self.threads.append(self.Sender(in_f[0], self.exit_thread, length))
         print "PASS: Sender prepare"
 
 
@@ -484,6 +488,28 @@  class virtio_guest():
                    (length, len(recvs)))
 
 
+    def clean_port(self, port, buffer=1024):
+        in_f = self._open([port])
+        ret = select.select([in_f[0]], [], [], 1.0)
+        buf = ""
+        if ret[0]:
+            buf = os.read(in_f[0], buffer)
+        print ("PASS: Rest in socket: " + buf)
+
+
+def is_alive():
+    """
+    Check is only main thread is alive and if guest react.
+    """
+    if threading.activeCount() == 1:
+        print ("PASS: Guest is ok no thread alive")
+    else:
+        threads = ""
+        for thread in threading.enumerate():
+            threads += thread.name + ", "
+        print ("FAIL: On guest run thread. Active thread:" + threads)
+
+
 def compile():
     """
     Compile virtio_guest.py to speed up.
@@ -501,12 +527,19 @@  def main():
     if (len(sys.argv) > 1) and (sys.argv[1] == "-c"):
         compile()
 
-    virt = virtio_guest()
+    virt = VirtioGuest()
     print "PASS: Start"
 
     while True:
         str = raw_input()
-        exec str
+        try:
+            exec str
+        except:
+            exc_type, exc_value, exc_traceback = sys.exc_info()
+            print "On Guest exception from: \n" + "".join(
+                                    traceback.format_exception(exc_type,
+                                                               exc_value,
+                                                               exc_traceback))
 
 
 if __name__ == "__main__":
diff --git a/client/tests/kvm/tests/virtio_console.py b/client/tests/kvm/tests/virtio_console.py
index aa668e1..d69c0a5 100644
--- a/client/tests/kvm/tests/virtio_console.py
+++ b/client/tests/kvm/tests/virtio_console.py
@@ -1,15 +1,16 @@ 
 """
 virtio_console test
 
-@copyright: Red Hat 2010
+@copyright: 2010 Red Hat, Inc.
 """
 import array, logging, os, random, re, select, shutil, socket, sys, tempfile
-import threading, time
+import threading, time, traceback
 from collections import deque
 from threading import Thread
 
 import kvm_subprocess, kvm_test_utils, kvm_utils, kvm_preprocessing
 from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
 
 
 def run_virtio_console(test, params, env):
@@ -30,7 +31,194 @@  def run_virtio_console(test, params, env):
     @param params: Dictionary with the test parameters
     @param env: Dictionary with test environment
     """
-    class th_send(Thread):
+    class SubTest(object):
+        """
+        Collect result of subtest of main test.
+        """
+        def __init__(self):
+            """
+            Initialize object
+            """
+            self.result = []
+            self.passed = 0
+            self.failed = 0
+            self.cleanup_func = None
+            self.cleanup_args = None
+
+
+        def set_cleanup_func(self, func, args):
+            """
+            Set cleanup function which is called when subtest fails.
+
+            @param func: Function which should be called when test fails.
+            @param args: Arguments of cleanup function.
+            """
+            self.cleanup_func = func
+            self.cleanup_args = args
+
+
+        def do_test(self, function, args=None, fatal=False, cleanup=True):
+            """
+            Execute subtest function.
+
+            @param function: Object of function.
+            @param args: List of arguments of function.
+            @param fatal: If true exception is forwarded to main test.
+            @return: Return what returned executed subtest.
+            @raise TestError: If collapse of test is fatal raise forward
+                        exception from subtest.
+            """
+            if args == None:
+                args = []
+            try:
+                logging.debug("Start test %s." % function.func_name)
+                ret = function(*args)
+                logging.info(self.result_to_string((True, function.func_name,
+                                                    args)))
+                self.result.append((True, function.func_name, args))
+                self.passed += 1
+                return ret
+            except:
+                exc_type, exc_value, exc_traceback = sys.exc_info()
+                logging.error("In function (" + function.func_name + "):")
+                logging.error("Call from:\n" +
+                              traceback.format_stack()[-2][:-1])
+                logging.error("Exception from:\n" +
+                              "".join(traceback.format_exception(
+                                                        exc_type, exc_value,
+                                                        exc_traceback.tb_next)))
+                #Clean up environment after subTest crash
+                if cleanup:
+                    self.cleanup_func(*self.cleanup_args)
+                logging.info(self.result_to_string((False, function.func_name,
+                                                    args)))
+                self.result.append((False, function.func_name, args))
+                self.failed += 1
+                if fatal:
+                    raise
+
+
+        def is_failed(self):
+            """
+            @return: If any of subtest not pass return True.
+            """
+            return True if self.failed > 0 else False
+
+        def get_result(self):
+            """
+            @return: Result of subtests.
+               Format:
+                 tuple(pass/fail,function_name,call_arguments)
+            """
+            return self.result
+
+
+        def result_to_string_debug(self, result):
+            """
+            @param result: Result of test.
+            """
+            sargs = ""
+            for arg in result[2]:
+                sargs += str(arg) + ","
+            sargs = sargs[:-1]
+            return ("Subtest (%s(%s)):  -->%s") % (result[1], sargs,
+                                             "PASS"if result[0] else "FAIL")
+
+
+        def result_to_string(self, result):
+            """
+            @param result: Result of test.
+            """
+            return ("Subtest (%s):  -->%s") % (result[1], "PASS"if result[0]
+                                                               else "FAIL")
+
+
+        def get_full_text_result(self):
+            """
+            @return string with text form of result
+            """
+            result = ""
+            for res in self.result:
+                result += self.result_to_string_debug(res) + "\n"
+            return result
+
+
+        def get_text_result(self):
+            """
+            @return string with text form of result
+            """
+            result = ""
+            for res in self.result:
+                result += self.result_to_string(res) + "\n"
+            return result
+
+
+    class Port(object):
+        """
+        Define structure to keep information about used port.
+        """
+        def __init__(self, sock, name, port_type, path):
+            """
+            @param vm: virtual machine object that port owned
+            @param sock: Socket of port if port is open.
+            @param name: Name of port for guest side.
+            @param port_type: Type of port yes = console, no= serialport.
+            @param path: Path to port on host side.
+            """
+            self.sock = sock
+            self.name = name
+            self.port_type = port_type
+            self.path = path
+            self.is_open = False
+
+
+        def for_guest(self):
+            """
+            Format data for communication with guest side.
+            """
+            return [self.name, self.port_type]
+
+
+        def open(self):
+            """
+            Open port on host side.
+            """
+            self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+            self.sock.connect(self.path)
+            self.is_open = True
+
+
+        def clean_port(self):
+            """
+            Clean all data from opened port on host side.
+            """
+            if self.is_open:
+                self.close()
+            self.open()
+            ret = select.select([self.sock], [], [], 1.0)
+            if ret[0]:
+                buf = self.sock.recv(1024)
+                logging.debug("Rest in socket: " + buf)
+
+
+        def close(self):
+            """
+            Close port.
+            """
+            self.sock.shutdown(socket.SHUT_RDWR)
+            self.sock.close()
+            self.is_open = False
+
+
+        def __str__(self):
+            """
+            Convert to text.
+            """
+            return ("%s,%s,%s,%s,%d" % ("Socket", self.name, self.port_type,
+                                        self.path, self.is_open))
+
+
+    class ThSend(Thread):
         """
         Random data sender thread.
         """
@@ -53,14 +241,14 @@  def run_virtio_console(test, params, env):
 
 
         def run(self):
-            logging.debug("th_send %s: run", self.getName())
+            logging.debug("ThSend %s: run", self.getName())
             while not self.exitevent.isSet():
                 self.idx += self.port.send(self.data)
-            logging.debug("th_send %s: exit(%d)", self.getName(),
+            logging.debug("ThSend %s: exit(%d)", self.getName(),
                           self.idx)
 
 
-    class th_send_check(Thread):
+    class ThSendCheck(Thread):
         """
         Random data sender thread.
         """
@@ -85,7 +273,7 @@  def run_virtio_console(test, params, env):
 
 
         def run(self):
-            logging.debug("th_send_check %s: run", self.getName())
+            logging.debug("ThSendCheck %s: run", self.getName())
             too_much_data = False
             while not self.exitevent.isSet():
                 # FIXME: workaround the problem with qemu-kvm stall when too
@@ -109,14 +297,14 @@  def run_virtio_console(test, params, env):
                         idx = self.port.send(buf)
                         buf = buf[idx:]
                         self.idx += idx
-            logging.debug("th_send_check %s: exit(%d)", self.getName(),
+            logging.debug("ThSendCheck %s: exit(%d)", self.getName(),
                           self.idx)
             if too_much_data:
-                logging.error("th_send_check: workaround the 'too_much_data'"
+                logging.error("ThSendCheck: workaround the 'too_much_data'"
                               "bug")
 
 
-    class th_recv(Thread):
+    class ThRecv(Thread):
         """
         Recieves data and throws it away.
         """
@@ -134,7 +322,7 @@  def run_virtio_console(test, params, env):
             self.blocklen = blocklen
             self.idx = 0
         def run(self):
-            logging.debug("th_recv %s: run", self.getName())
+            logging.debug("ThRecv %s: run", self.getName())
             while not self.exitevent.isSet():
                 # TODO: Workaround, it didn't work with select :-/
                 try:
@@ -142,10 +330,10 @@  def run_virtio_console(test, params, env):
                 except socket.timeout:
                     pass
             self.port.settimeout(self._port_timeout)
-            logging.debug("th_recv %s: exit(%d)", self.getName(), self.idx)
+            logging.debug("ThRecv %s: exit(%d)", self.getName(), self.idx)
 
 
-    class th_recv_check(Thread):
+    class ThRecvCheck(Thread):
         """
         Random data receiver/checker thread.
         """
@@ -165,10 +353,10 @@  def run_virtio_console(test, params, env):
 
 
         def run(self):
-            logging.debug("th_recv_check %s: run", self.getName())
+            logging.debug("ThRecvCheck %s: run", self.getName())
             while not self.exitevent.isSet():
                 ret = select.select([self.port], [], [], 1.0)
-                if ret and (not self.exitevent.isSet()):
+                if ret[0] and (not self.exitevent.isSet()):
                     buf = self.port.recv(self.blocklen)
                     if buf:
                         # Compare the recvd data with the control data
@@ -186,156 +374,13 @@  def run_virtio_console(test, params, env):
                                 for buf in self.buffer:
                                     ch_ += buf
                                 logging.error("Queue = %s", repr(ch_))
-                                raise error.TestFail("th_recv_check: incorrect "
+                                raise error.TestFail("ThRecvCheck: incorrect "
                                                      "data")
                         self.idx += len(buf)
-            logging.debug("th_recv_check %s: exit(%d)", self.getName(),
+            logging.debug("ThRecvCheck %s: exit(%d)", self.getName(),
                           self.idx)
 
 
-    class cpu_load():
-        """
-        Get average cpu load between start and get_load.
-        """
-        def __init__ (self):
-            self.old_load = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-            self.startTime = 0
-            self.endTime = 0
-
-
-        def _get_cpu_load(self):
-            # Let's see if we can calc system load.
-            try:
-                f = open("/proc/stat", "r")
-                tmp = f.readlines(200)
-                f.close()
-            except:
-                logging.critical("Error reading /proc/stat")
-                error.TestFail("average_cpu_load: Error reading /proc/stat")
-
-            # 200 bytes should be enough because the information we need
-            # is typically stored in the first line
-            # Info about individual processors (not yet supported) is in
-            # the second (third, ...?) line
-            for line in tmp:
-                if line[0:4] == "cpu ":
-                    reg = re.compile('[0-9]+')
-                    load_values = reg.findall(line)
-                    # extract values from /proc/stat
-                    load = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-                    for i in range(8):
-                        load[i] = int(load_values[i]) - self.old_load[i]
-
-                    for i in range(8):
-                        self.old_load[i] = int(load_values[i])
-                    return load
-
-
-        def start (self):
-            """
-            Start CPU usage measurement
-            """
-            self.old_load = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-            self.startTime = time.time()
-            self._get_cpu_load()
-
-
-        def get_load(self):
-            """
-            Get and reset CPU usage
-
-            @return: return group cpu (user[%], system[%], sum[%], testTime[s])
-            """
-            self.endTime = time.time()
-            testTime = self.endTime - self.startTime
-            load = self._get_cpu_load()
-
-            user = load[0] / testTime
-            system = load[2] / testTime
-            sum = user + system
-
-            return (user, system, sum, testTime)
-
-
-    class pid_load():
-        """
-        Get average process cpu load between start and get_load
-        """
-        def __init__ (self, pid, name):
-            self.old_load = [0, 0]
-            self.startTime = 0
-            self.endTime = 0
-            self.pid = pid
-            self.name = name
-
-
-        def _get_cpu_load(self, pid):
-            # Let's see if we can calc system load.
-            try:
-                f = open("/proc/%d/stat" % (pid), "r")
-                line = f.readline()
-                f.close()
-            except:
-                logging.critical("Error reading /proc/%d/stat", pid)
-                error.TestFail("average_process_cpu_load: Error reading "
-                               "/proc/stat")
-            else:
-                reg = re.compile('[0-9]+')
-                load_values = reg.findall(line)
-                del load_values[0:11]
-                # extract values from /proc/stat
-                load = [0, 0]
-                for i in range(2):
-                    load[i] = int(load_values[i]) - self.old_load[i]
-
-                for i in range(2):
-                    self.old_load[i] = int(load_values[i])
-                return load
-
-
-        def start (self):
-            """
-            Start CPU usage measurement
-            """
-            self.old_load = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-            self.startTime = time.time()
-            self._get_cpu_load(self.pid)
-
-
-        def get_load(self):
-            """
-            Get and reset CPU usage.
-
-            @return: Group cpu
-                    (pid, user[%], system[%], sum[%], testTime[s])
-            """
-            self.endTime = time.time()
-            testTime = self.endTime - self.startTime
-            load = self._get_cpu_load(self.pid)
-
-            user = load[0] / testTime
-            system = load[1] / testTime
-            sum = user + system
-
-            return (self.name, self.pid, user, system, sum, testTime)
-
-
-    def print_load(process, system):
-        """
-        Print load in tabular mode.
-
-        @param process: List of process statistic tuples.
-        @param system: Tuple of system cpu usage.
-        """
-
-        logging.info("%-10s %6s %5s %5s %5s %11s",
-                     "NAME", "PID", "USER", "SYS", "SUM", "TIME")
-        for pr in process:
-            logging.info("%-10s %6d %4.0f%% %4.0f%% %4.0f%% %10.3fs" % pr)
-        logging.info("TOTAL:     ------ %4.0f%% %4.0f%% %4.0f%% %10.3fs" %
-                     system)
-
-
     def process_stats(stats, scale=1.0):
         """
         Process and print the statistic.
@@ -352,7 +397,7 @@  def run_virtio_console(test, params, env):
         return stats
 
 
-    def init_guest(vm, timeout=2):
+    def _init_guest(vm, timeout=2):
         """
         Execute virtio_guest.py on guest, wait until it is initialized.
 
@@ -384,6 +429,21 @@  def run_virtio_console(test, params, env):
         time.sleep(2)
 
 
+    def init_guest(vm, consoles):
+        """
+        Prepares guest, executes virtio_guest.py and initialize for testing
+
+        @param vm: Informations about the guest.
+        @param consoles: Informations about consoles
+        """
+        conss = []
+        for mode in consoles:
+            for cons in mode:
+                conss.append(cons.for_guest())
+        _init_guest(vm, 10)
+        on_guest("virt.init(%s)" % (conss), vm, 10)
+
+
     def _on_guest(command, vm, timeout=2):
         """
         Execute given command inside the script's main loop, indicating the vm
@@ -425,29 +485,6 @@  def run_virtio_console(test, params, env):
         return (match, data)
 
 
-    def socket_readall(sock, read_timeout, mesagesize):
-        """
-        Read everything from the socket.
-
-        @param sock: Socket.
-        @param read_timeout: Read timeout.
-        @param mesagesize: Size of message.
-        """
-        sock_decriptor = sock.fileno()
-        sock.settimeout(read_timeout)
-        message = ""
-        try:
-            while (len(message) < mesagesize):
-                message += sock.recv(mesagesize)
-        except Exception as inst:
-            if (inst.args[0] == "timed out"):
-                logging.debug("Reading timeout")
-            else:
-                logging.debug(inst)
-        sock.setblocking(1)
-        return message
-
-
     def _guest_exit_threads(vm, send_pts, recv_pts):
         """
         Safely executes on_guest("virt.exit_threads()") using workaround of
@@ -463,7 +500,7 @@  def run_virtio_console(test, params, env):
             logging.debug("Workaround the stuck thread on guest")
             # Thread is stucked in read/write
             for send_pt in send_pts:
-                send_pt[0].sendall(".")
+                send_pt.sock.sendall(".")
         elif match != 0:
             # Something else
             raise error.TestFail("Unexpected fail\nMatch: %s\nData:\n%s"
@@ -471,8 +508,8 @@  def run_virtio_console(test, params, env):
 
         # Read-out all remaining data
         for recv_pt in recv_pts:
-            while select.select([recv_pt[0]], [], [], 0.1)[0]:
-                recv_pt[0].recv(1024)
+            while select.select([recv_pt.sock], [], [], 0.1)[0]:
+                recv_pt.sock.recv(1024)
 
         # This will cause fail in case anything went wrong.
         on_guest("print 'PASS: nothing'", vm, 10)
@@ -482,6 +519,13 @@  def run_virtio_console(test, params, env):
         """
         Creates the VM and connects the specified number of consoles and serial
         ports.
+        Ports are allocated by 2 per 1 virtio-serial-pci device starting with
+        console. (3+2 => CC|CS|S; 0+2 => SS; 3+4 => CC|CS|SS|S, ...) This way
+        it's easy to test communication on the same or different
+        virtio-serial-pci device.
+        Further in tests the consoles are being picked always from the first
+        available one (3+2: 2xC => CC|cs|s <communication on the same PCI>;
+        2xC,1xS => CC|cS|s <communication between 2 PCI devs)
 
         @param no_console: Number of desired virtconsoles.
         @param no_serialport: Number of desired virtserialports.
@@ -508,12 +552,10 @@  def run_virtio_console(test, params, env):
             params['extra_params'] += (" -device virtserialport,chardev=vs%d,"
                                        "name=serialport-%d,id=p%d" % (i, i, i))
 
-
         logging.debug("Booting first guest %s", params.get("main_vm"))
         kvm_preprocessing.preprocess_vm(test, params, env,
                                         params.get("main_vm"))
 
-
         vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
 
         session = kvm_test_utils.wait_for_login(vm, 0,
@@ -522,30 +564,219 @@  def run_virtio_console(test, params, env):
 
         # connect the sockets
         for i in range(0, no_console):
-            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            sock.connect("%s/%d" % (tmp_dir, i))
-            consoles.append([sock, "console-%d" % i, "yes"])
+            consoles.append(Port(None ,"console-%d" % i,
+                                 "yes", "%s/%d" % (tmp_dir, i)))
         for i in range(no_console, no_console + no_serialport):
-            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            sock.connect("%s/%d" % (tmp_dir, i))
-            serialports.append([sock, "serialport-%d" % i, "no"])
+            serialports.append(Port(None ,"serialport-%d" % i,
+                                    "no", "%s/%d" % (tmp_dir, i)))
 
         return [vm, session, tmp_dir], [consoles, serialports]
 
 
-    def test_smoke(vm, consoles, params):
+    def topen(vm, port):
+        """
+        Open virtioconsole port.
+
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param port: Port identifier.
+        """
+        on_guest("virt.open('%s')" % (port.name), vm, 2)
+        port.open()
+
+
+    def tmulti_open(vm, port):
+        """
+        Multiopen virtioconsole port.
+
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param port: Port identifier.
+        """
+        on_guest("virt.close('%s')" % (port.name), vm, 2)
+        on_guest("virt.open('%s')" % (port.name), vm, 2)
+        match = _on_guest("virt.open('%s')" % (port.name), vm, 2)[0]
+        # Console is permitted to open the device multiple times
+        if match != 0 and port.port_type == "yes":
+            raise error.TestFail("Unexpected fail of openning the console"
+                                 " device for the 2nd time.")
+        # Serial port is forbidden to open the device multiple times
+        elif match != 1 and port.port_type == "no":
+            raise error.TestFail("Unexpetded pass of oppening the serialport"
+                                 " device for the 2nd time.")
+        port.open()
+
+    def tclose(vm, port):
+        """
+        Close socket.
+
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param port: Port to open.
+        """
+        on_guest("virt.close('%s')" % (port.name), vm, 2)
+        port.close()
+
+
+    def tpooling(vm, port):
+        """
+        Test try pooling function.
+
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param port: Port used in test.
+        """
+        # Poll (OUT)
+        on_guest("virt.poll('%s', %s)" % (port.name, select.POLLOUT), vm,
+                 2)
+
+        # Poll (IN, OUT)
+        port.sock.sendall("test")
+        for test in [select.POLLIN, select.POLLOUT]:
+            on_guest("virt.poll('%s', %s)" % (port.name, test), vm, 2)
+
+        # Poll (IN HUP)
+        # I store the socket informations and close the socket
+        port.close()
+        for test in [select.POLLIN, select.POLLHUP]:
+            on_guest("virt.poll('%s', %s)" % (port.name, test), vm, 2)
+
+        # Poll (HUP)
+        on_guest("virt.recv('%s', 4, 1024, False)" % (port.name), vm, 2)
+        on_guest("virt.poll('%s', %s)" % (port.name, select.POLLHUP), vm,
+                 2)
+
+        # Reconnect the socket
+        port.open()
+        # Redefine socket in consoles
+        on_guest("virt.poll('%s', %s)" % (port.name, select.POLLOUT), vm,
+                 2)
+
+
+    def trw_host_offline(vm, port):
+        """
+        Guest read/write from host when host is disconnected.
+
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param port: Port used in test.
+        """
+        if port.is_open:
+            port.close()
+
+        # Read should pass
+        # FIXME: Console doesn't support polling (POLLHUP without host shoots
+        # the guest OS)
+        if port.port_type != "yes":
+            on_guest("virt.recv('%s', 0, 1024, False)" % port.name, vm, 2)
+        else: # Skip this test on virtio-console port
+            raise error.TestFail("This test is unable to run with virtio"
+                                 " console. Please see the in_code FIXME"
+                                 " note for more info.\n"
+                                 "Skipping this round.")
+        # Write should timed-out
+        match, tmp = _on_guest("virt.send('%s', 10, False)"
+                                % port.name, vm, 2)
+        if match != None:
+            raise error.TestFail("Write on guest while host disconnected "
+                                 "didn't timed out.\nOutput:\n%s"
+                                 % tmp)
+
+        port.open()
+
+        if (port.sock.recv(1024) < 10):
+            raise error.TestFail("Didn't received data from guest")
+        # Now the _on_guest("virt.send('%s'... command should be finished
+        on_guest("print 'PASS: nothing'", vm, 2)
+
+
+    def trw_blocking_mode(vm, port):
+        """
+        Guest read\write data in blocking mode.
+
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param port: Port used in test.
+        """
+        # Blocking mode
+        if not port.is_open:
+            port.open()
+        on_guest("virt.blocking('%s', True)" % port.name, vm, 2)
+        # Recv should timed out
+        match, tmp = _on_guest("virt.recv('%s', 10, 1024, False)" %
+                               port.name, vm, 2)
+        if match == 0:
+            raise error.TestFail("Received data even when non were sent\n"
+                                 "Data:\n%s" % tmp)
+        elif match != None:
+            raise error.TestFail("Unexpected fail\nMatch: %s\nData:\n%s" %
+                                 (match, tmp))
+        port.sock.sendall("1234567890")
+        # Now guest received the data end escaped from the recv()
+        on_guest("print 'PASS: nothing'", vm, 2)
+
+
+    def trw_nonblocking_mode(vm, port):
+        """
+        Guest read\write data in nonblocking mode.
+
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param port: Port used in test.
+        """
+        # Non-blocking mode
+        if not port.is_open:
+            port.open()
+        on_guest("virt.blocking('%s', False)" % port.name, vm, 2)
+        # Recv should return FAIL with 0 received data
+        match, tmp = _on_guest("virt.recv('%s', 10, 1024, False)" %
+                              port.name, vm, 2)
+        if match == 0:
+            raise error.TestFail("Received data even when non were sent\n"
+                                 "Data:\n%s" % tmp)
+        elif match == None:
+            raise error.TestFail("Timed out, probably in blocking mode\n"
+                                 "Data:\n%s" % tmp)
+        elif match != 1:
+            raise error.TestFail("Unexpected fail\nMatch: %s\nData:\n%s" %
+                                 (match, tmp))
+        port.sock.sendall("1234567890")
+        on_guest("virt.recv('%s', 10, 1024, False)" % port.name, vm, 2)
+
+
+    def tbasic_loopback(vm, send_port, recv_port, data="Smoke test data"):
+        """
+        Easy loop back test with loop over only two port.
+
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param port: Port used in test.
+        """
+        if not send_port.is_open:
+            send_port.open()
+        if not recv_port.is_open:
+            recv_port.open()
+        on_guest("virt.loopback(['%s'], ['%s'], 1024, virt.LOOP_NONE)" %
+                     (send_port.name, recv_port.name), vm, 2)
+        send_port.sock.sendall(data)
+        tmp = ""
+        i = 0
+        while i <= 10:
+            i += 1
+            ret = select.select([recv_port.sock], [], [], 1.0)
+            if ret:
+                tmp += recv_port.sock.recv(1024)
+            if len(tmp) >= len(data):
+                break
+        if tmp != data:
+            raise error.TestFail("Incorrect data: '%s' != '%s'",
+                                 data, tmp)
+        _guest_exit_threads(vm, [send_port], [recv_port])
+
+
+    def test_smoke(test, vm, consoles, params):
         """
         Virtio console smoke test.
 
         Tests the basic functionalities (poll, read/write with and without
         connected host, etc.
 
-        @param vm: target virtual machine [vm, session, tmp_dir]
-        @param consoles: a field of virtio ports with the minimum of 2 items
-        @param params: test parameters '$console_type:$data;...'
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param consoles: Field of virtio ports with the minimum of 2 items.
+        @param params: Test parameters '$console_type:$data;...'
         """
-        logging.info("Smoke test: Tests the basic capabilities of "
-                     "virtio_consoles.")
         # PREPARE
         for param in params.split(';'):
             if not param:
@@ -560,121 +791,18 @@  def run_virtio_console(test, params, env):
             send_pt = consoles[param][0]
             recv_pt = consoles[param][1]
 
-            # TEST
-            # Poll (OUT)
-            on_guest("virt.poll('%s', %s)" % (send_pt[1], select.POLLOUT), vm,
-                     2)
-
-            # Poll (IN, OUT)
-            send_pt[0].sendall("test")
-            for test in [select.POLLIN, select.POLLOUT]:
-                on_guest("virt.poll('%s', %s)" % (send_pt[1], test), vm, 2)
-
-            # Poll (IN HUP)
-            # I store the socket informations and close the socket
-            sock = send_pt[0]
-            send_pt[0] = sock.getpeername()
-            sock.shutdown(2)
-            sock.close()
-            del sock
-            for test in [select.POLLIN, select.POLLHUP]:
-                on_guest("virt.poll('%s', %s)" % (send_pt[1], test), vm, 2)
-
-            # Poll (HUP)
-            on_guest("virt.recv('%s', 4, 1024, False)" % (send_pt[1]), vm, 2)
-            on_guest("virt.poll('%s', %s)" % (send_pt[1], select.POLLHUP), vm,
-                     2)
-
-            # Reconnect the socket
-            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            sock.connect(send_pt[0])
-            send_pt[0] = sock
-            # Redefine socket in consoles
-            consoles[param][0] = send_pt
-            on_guest("virt.poll('%s', %s)" % (send_pt[1], select.POLLOUT), vm,
-                     2)
-
-            # Read/write without host connected
-            # I store the socket informations and close the socket
-            sock = send_pt[0]
-            send_pt[0] = sock.getpeername()
-            sock.shutdown(2)
-            sock.close()
-            del sock
-            # Read should pass
-            on_guest("virt.recv('%s', 0, 1024, False)" % send_pt[1], vm, 2)
-            # Write should timed-out
-            match, tmp = _on_guest("virt.send('%s', 10, False)"
-                                    % send_pt[1], vm, 2)
-            if match != None:
-                raise error.TestFail("Read on guest while host disconnected "
-                                     "didn't timed out.\nOutput:\n%s"
-                                     % tmp)
-            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            sock.connect(send_pt[0])
-            send_pt[0] = sock
-
-            # Redefine socket in consoles
-            consoles[param][0] = send_pt
-            if (send_pt[0].recv(1024) < 10):
-                raise error.TestFail("Didn't received data from guest")
-            # Now the _on_guest("virt.send('%s'... command should be finished
-            on_guest("print 'PASS: nothing'", vm, 2)
-
-            # Non-blocking mode
-            on_guest("virt.blocking('%s', False)" % send_pt[1], vm, 2)
-            # Recv should return FAIL with 0 received data
-            match, tmp = _on_guest("virt.recv('%s', 10, 1024, False)" %
-                                   send_pt[1], vm, 2)
-            if match == 0:
-                raise error.TestFail("Received data even when non were sent\n"
-                                     "Data:\n%s" % tmp)
-            elif match == None:
-                raise error.TestFail("Timed out, probably in blocking mode\n"
-                                     "Data:\n%s" % tmp)
-            elif match != 1:
-                raise error.TestFail("Unexpected fail\nMatch: %s\nData:\n%s" %
-                                     (match, tmp))
-            send_pt[0].sendall("1234567890")
-            on_guest("virt.recv('%s', 10, 1024, False)" % send_pt[1], vm, 2)
-
-            # Blocking mode
-            on_guest("virt.blocking('%s', True)" % send_pt[1], vm, 2)
-            # Recv should timed out
-            match, tmp = _on_guest("virt.recv('%s', 10, 1024, False)" %
-                                   send_pt[1], vm, 2)
-            if match == 0:
-                raise error.TestFail("Received data even when non were sent\n"
-                                     "Data:\n%s" % tmp)
-            elif match != None:
-                raise error.TestFail("Unexpected fail\nMatch: %s\nData:\n%s" %
-                                     (match, tmp))
-            send_pt[0].sendall("1234567890")
-            # Now guest received the data end escaped from the recv()
-            on_guest("print 'PASS: nothing'", vm, 2)
-
-            # Basic loopback test
-            on_guest("virt.loopback(['%s'], ['%s'], 1024, virt.LOOP_NONE)" %
-                     (send_pt[1], recv_pt[1]), vm, 2)
-            send_pt[0].sendall(data)
-            tmp = ""
-            i = 0
-            while i <= 10:
-                i += 1
-                ret = select.select([recv_pt[0]], [], [], 1.0)
-                if ret:
-                    tmp += recv_pt[0].recv(1024)
-                if len(tmp) >= len(data):
-                    break
-            if tmp != data:
-                raise error.TestFail("Incorrect data: '%s' != '%s'",
-                                     data, tmp)
-            _guest_exit_threads(vm, [send_pt], [recv_pt])
-
-        return consoles
-
-
-    def test_loopback(vm, consoles, params):
+            test.do_test(topen, [vm, send_pt] , True)
+            test.do_test(tclose, [vm, send_pt], True)
+            test.do_test(tmulti_open, [vm, send_pt], True)
+            test.do_test(tpooling, [vm, send_pt])
+            test.do_test(trw_host_offline, [vm, send_pt])
+            test.do_test(trw_nonblocking_mode, [vm, send_pt])
+            test.do_test(trw_blocking_mode, [vm, send_pt])
+            test.do_test(tbasic_loopback, [vm, send_pt, recv_pt], data)
+
+
+
+    def tloopback(vm, consoles, params):
         """
         Virtio console loopback test.
 
@@ -682,16 +810,13 @@  def run_virtio_console(test, params, env):
         ports and sends length amount of data through this connection.
         It validates the correctness of the data sent.
 
-        @param vm: target virtual machine [vm, session, tmp_dir]
-        @param consoles: a field of virtio ports with the minimum of 2 items
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param consoles: Field of virtio ports with the minimum of 2 items.
         @param params: test parameters, multiple recievers allowed.
             '$source_console_type@buffer_length:
              $destination_console_type1@$buffer_length:...:
              $loopback_buffer_length;...'
         """
-        logging.info("Loopback test: Creates a loopback between sender port "
-                     "and receiving port, send data through this connection, "
-                     "verify data correctness.")
         # PREPARE
         for param in params.split(';'):
             if not param:
@@ -730,6 +855,13 @@  def run_virtio_console(test, params, env):
             if len(buf_len) == (idx_console + idx_serialport):
                 buf_len.append(1024)
 
+            for p in recv_pts:
+                if not p.is_open:
+                    p.open()
+
+            if not send_pt.is_open:
+                send_pt.open()
+
             if len(recv_pts) == 0:
                 raise error.TestFail("test_loopback: incorrect recv consoles"
                                      "definition")
@@ -739,21 +871,22 @@  def run_virtio_console(test, params, env):
             for i in range(0, len(recv_pts)):
                 queues.append(deque())
 
-            tmp = "'%s'" % recv_pts[0][1]
+            tmp = "'%s'" % recv_pts[0].name
             for recv_pt in recv_pts[1:]:
-                tmp += ", '%s'" % (recv_pt[1])
+                tmp += ", '%s'" % (recv_pt.name)
             on_guest("virt.loopback(['%s'], [%s], %d, virt.LOOP_POLL)"
-                     % (send_pt[1], tmp, buf_len[-1]), vm, 2)
+                     % (send_pt.name, tmp, buf_len[-1]), vm, 2)
 
             exit_event = threading.Event()
 
             # TEST
-            thread = th_send_check(send_pt[0], exit_event, queues, buf_len[0])
+            thread = ThSendCheck(send_pt.sock, exit_event, queues,
+                                   buf_len[0])
             thread.start()
             threads.append(thread)
 
             for i in range(len(recv_pts)):
-                thread = th_recv_check(recv_pts[i][0], queues[i], exit_event,
+                thread = ThRecvCheck(recv_pts[i].sock, queues[i], exit_event,
                                        buf_len[i + 1])
                 thread.start()
                 threads.append(thread)
@@ -770,8 +903,8 @@  def run_virtio_console(test, params, env):
 
             # Read-out all remaining data
             for recv_pt in recv_pts:
-                while select.select([recv_pt[0]], [], [], 0.1)[0]:
-                    recv_pt[0].recv(1024)
+                while select.select([recv_pt.sock], [], [], 0.1)[0]:
+                    recv_pt.sock.recv(1024)
 
             _guest_exit_threads(vm, [send_pt], recv_pts)
 
@@ -779,19 +912,17 @@  def run_virtio_console(test, params, env):
             del threads[:]
 
 
-    def test_perf(vm, consoles, params):
+    def tperf(vm, consoles, params):
         """
         Tests performance of the virtio_console tunel. First it sends the data
         from host to guest and than back. It provides informations about
         computer utilisation and statistic informations about the troughput.
 
-        @param vm: target virtual machine [vm, session, tmp_dir]
-        @param consoles: a field of virtio ports with the minimum of 2 items
+        @param vm: Target virtual machine [vm, session, tmp_dir].
+        @param consoles: Field of virtio ports with the minimum of 2 items.
         @param params: test parameters:
                 '$console_type@$buffer_length:$test_duration;...'
         """
-        logging.info("Performance test: Measure performance for the "
-                     "virtio console tunnel")
         for param in params.split(';'):
             if not param:
                 continue
@@ -811,39 +942,38 @@  def run_virtio_console(test, params, env):
             param = (param[0] == 'serialport')
             port = consoles[param][0]
 
+            if not port.is_open:
+                port.open()
+
             data = ""
             for i in range(buf_len):
                 data += "%c" % random.randrange(255)
 
             exit_event = threading.Event()
-            slice = float(duration)/100
+            slice = float(duration) / 100
 
             # HOST -> GUEST
             on_guest('virt.loopback(["%s"], [], %d, virt.LOOP_NONE)' %
-                     (port[1], buf_len), vm, 2)
-            thread = th_send(port[0], data, exit_event)
+                     (port.name, buf_len), vm, 2)
+            thread = ThSend(port.sock, data, exit_event)
             stats = array.array('f', [])
-            loads = []
-            loads.append(cpu_load())
-            loads.append(pid_load(os.getpid(), 'autotest'))
-            loads.append(pid_load(vm[0].get_pid(), 'VM'))
-
-            for load in loads:
-                load.start()
+            loads = utils.SystemLoad([(os.getpid(), 'autotest'),
+                                      (vm[0].get_pid(), 'VM'), 0])
+            loads.start()
             _time = time.time()
             thread.start()
             for i in range(100):
                 stats.append(thread.idx)
                 time.sleep(slice)
             _time = time.time() - _time - duration
-            print_load([loads[1].get_load(), loads[2].get_load()],
-                       loads[0].get_load())
+            logging.info("\n" + loads.get_cpu_status_string()[:-1])
+            logging.info("\n" + loads.get_mem_status_string()[:-1])
             exit_event.set()
             thread.join()
 
             # Let the guest read-out all the remaining data
             while not _on_guest("virt.poll('%s', %s)" %
-                                (port[1], select.POLLIN), vm, 2)[0]:
+                                (port.name, select.POLLIN), vm, 2)[0]:
                 time.sleep(1)
 
             _guest_exit_threads(vm, [port], [])
@@ -853,30 +983,29 @@  def run_virtio_console(test, params, env):
                 "Test ran %fs longer which is more than one slice", _time)
             else:
                 logging.debug("Test ran %fs longer", _time)
-            stats = process_stats(stats[1:], slice*1048576)
+            stats = process_stats(stats[1:], slice * 1048576)
             logging.debug("Stats = %s", stats)
             logging.info("Host -> Guest [MB/s] (min/med/max) = %.3f/%.3f/%.3f",
-                         stats[0], stats[len(stats)/2], stats[-1])
+                        stats[0], stats[len(stats) / 2], stats[-1])
 
             del thread
 
             # GUEST -> HOST
             exit_event.clear()
             stats = array.array('f', [])
-            on_guest("virt.send_loop_init('%s', %d)" % (port[1], buf_len),
+            on_guest("virt.send_loop_init('%s', %d)" % (port.name, buf_len),
                      vm, 30)
-            thread = th_recv(port[0], exit_event, buf_len)
+            thread = ThRecv(port.sock, exit_event, buf_len)
             thread.start()
-            for load in loads:
-                load.start()
+            loads.start()
             on_guest("virt.send_loop()", vm, 2)
             _time = time.time()
             for i in range(100):
                 stats.append(thread.idx)
                 time.sleep(slice)
             _time = time.time() - _time - duration
-            print_load([loads[1].get_load(), loads[2].get_load()],
-                       loads[0].get_load())
+            logging.info("\n" + loads.get_cpu_status_string()[:-1])
+            logging.info("\n" + loads.get_mem_status_string()[:-1])
             on_guest("virt.exit_threads()", vm, 2)
             exit_event.set()
             thread.join()
@@ -885,37 +1014,86 @@  def run_virtio_console(test, params, env):
                 "Test ran %fs longer which is more than one slice", _time)
             else:
                 logging.debug("Test ran %fs longer" % _time)
-            stats = process_stats(stats[1:], slice*1048576)
+            stats = process_stats(stats[1:], slice * 1048576)
             logging.debug("Stats = %s", stats)
             logging.info("Guest -> Host [MB/s] (min/med/max) = %.3f/%.3f/%.3f",
-                         stats[0], stats[len(stats)/2], stats[-1])
+                         stats[0], stats[len(stats) / 2], stats[-1])
 
             del thread
-
             del exit_event
-            del loads[:]
+
+
+    def clean_ports(vm, consoles):
+        """
+        Clean state of all ports and set port to default state.
+        Default state:
+           No data on port or in port buffer.
+           Read mode = blocking.
+
+        @param consoles: Consoles which should be clean.
+        """
+        # Check if python is still alive
+        print "CLEANED"
+        match, tmp = _on_guest("is_alive()", vm, 10)
+        if (match == None) or (match != 0):
+            logging.error("Python died/is stucked/have remaining threads")
+            vm[1].close()
+            vm[1] = kvm_test_utils.wait_for_login(vm[0], 0,
+                                         float(params.get("boot_timeout", 240)),
+                                         0, 2)
+            (match, data) = _on_guest("killall -9 python "
+                                      "&& echo -n PASS: python killed"
+                                      "|| echo -n PASS: python was death",
+                                      vm, 30)
+            if (match == None):
+                # killall -9 command didn't finished - python stucked
+                raise error.TestFail("Python is really stucked - "
+                                     "can't kill -9 it")
+
+            on_guest("rmmod -f virtio_console && echo -n PASS: rmmod "
+                     "|| echo -n FAIL: rmmod", vm, 10)
+            on_guest("modprobe virtio_console "
+                     "&& echo -n PASS: modprobe || echo -n FAIL: modprobe",
+                     vm, 10)
+
+            init_guest(vm, consoles)
+            (match, data) = _on_guest("virt.clean_port('%s'),1024" %
+                                      consoles[0][0].name, vm, 2)
+            if (match == None) or (match != 0):
+                raise error.TestFail("Virtio-console driver is irreparably"
+                                     " blocked. Every comd end with sig KILL.")
+
+        for ctype in consoles:
+            for port in ctype:
+                openned = port.is_open
+                port.clean_port()
+                #on_guest("virt.blocking('%s', True)" % port.name, vm, 2)
+                on_guest("virt.clean_port('%s'),1024" % port.name, vm, 2)
+                if not openned:
+                    port.close()
 
 
     # INITIALIZE
-    test_smoke_params = params.get('virtio_console_smoke', '')
-    test_loopback_params = params.get('virtio_console_loopback', '')
-    test_perf_params = params.get('virtio_console_perf', '')
+
+    tsmoke_params = params.get('virtio_console_smoke', '')
+    tloopback_params = params.get('virtio_console_loopback', '')
+    tperf_params = params.get('virtio_console_perf', '')
 
     no_serialports = 0
     no_consoles = 0
     # consoles required for Smoke test
-    if (test_smoke_params.count('serialport')):
+    if (tsmoke_params.count('serialport')):
         no_serialports = max(2, no_serialports)
-    if (test_smoke_params.count('console')):
+    if (tsmoke_params.count('console')):
         no_consoles = max(2, no_consoles)
     # consoles required for Loopback test
-    for param in test_loopback_params.split(';'):
+    for param in tloopback_params.split(';'):
         no_serialports = max(no_serialports, param.count('serialport'))
         no_consoles = max(no_consoles, param.count('console'))
     # consoles required for Performance test
-    if (test_perf_params.count('serialport')):
+    if (tperf_params.count('serialport')):
         no_serialports = max(1, no_serialports)
-    if (test_perf_params.count('console')):
+    if (tperf_params.count('console')):
         no_consoles = max(1, no_consoles)
 
     if (no_serialports + no_consoles) == 0:
@@ -933,16 +1111,27 @@  def run_virtio_console(test, params, env):
 
     # ACTUAL TESTING
     # Defines all available consoles; tests udev and sysfs
-    conss = []
-    for mode in consoles:
-        for cons in mode:
-            conss.append(cons[1:3])
-    init_guest(vm, 10)
-    on_guest("virt.init(%s)" % (conss), vm, 10)
-
-    consoles = test_smoke(vm, consoles, test_smoke_params)
-    test_loopback(vm, consoles, test_loopback_params)
-    test_perf(vm, consoles, test_perf_params)
+    init_guest(vm, consoles)
+
+    test = SubTest()
+    test.set_cleanup_func(clean_ports, [vm, consoles])
+    #Test Smoke
+    test_smoke(test, vm, consoles, tsmoke_params)
+
+    #Test Loopback
+    test.do_test(tloopback, [vm, consoles, tloopback_params])
+
+    #Test Performance
+    test.do_test(tperf, [vm, consoles, tperf_params])
+
+    logging.info(("Summary: %d tests passed  %d test failed :\n" %
+                  (test.passed, test.failed)) + test.get_text_result())
+    logging.debug(("Summary: %d tests passed  %d test failed :\n" %
+                   (test.passed, test.failed)) + test.get_full_text_result())
+
+    if test.is_failed():
+        raise error.TestFail("Virtio_console test FAILED.")
+
 
     # CLEANUP
     vm[1].close()