Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Unified Diff: client/tests/kvm/tests/virtio_console.py

Issue 6246035: Merge remote branch 'cros/upstream' into master (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/autotest.git@master
Patch Set: patch Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: client/tests/kvm/tests/virtio_console.py
diff --git a/client/tests/kvm/tests/virtio_console.py b/client/tests/kvm/tests/virtio_console.py
index 008ec63724343b7ccd3079eb63fde88bcc22be52..af32bf2f337f4bd7b6cda8c7877ea4f182717ba7 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
+import kvm_subprocess, kvm_test_utils, kvm_preprocessing
def run_virtio_console(test, params, env):
@@ -30,7 +31,228 @@ 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.
+ @param cleanup: If true call cleanup function after crash of test.
+ @return: Return what returned executed subtest.
+ @raise TestError: If collapse of test is fatal raise forward
+ exception from subtest.
+ """
+ if args == None:
+ args = []
+ res = [None, function.func_name, args]
+ try:
+ logging.debug("Start test %s.", function.func_name)
+ ret = function(*args)
+ res[0] = True
+ logging.info(self.result_to_string(res))
+ self.result.append(res)
+ 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
+ res[0] = False
+ logging.info(self.result_to_string(res))
+ self.result.append(res)
+ self.failed += 1
+
+ if cleanup:
+ try:
+ self.cleanup_func(*self.cleanup_args)
+ except:
+ error.TestFail("Cleanup function crash too.")
+ if fatal:
+ raise
+
+
+ def is_failed(self):
+ """
+ @return: If any of subtest not pass return True.
+ """
+ if self.failed > 0:
+ return True
+ else:
+ return 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]
+ if result[0]:
+ status = "PASS"
+ else:
+ status = "FAIL"
+ return ("Subtest (%s(%s)): --> %s") % (result[1], sargs, status)
+
+
+ def result_to_string(self, result):
+ """
+ @param result: Result of test.
+ """
+ if result[0]:
+ status = "PASS"
+ else:
+ status = "FAIL"
+ return ("Subtest (%s): --> %s") % (result[1], status)
+
+
+ def headline(self, msg):
+ """
+ Add headline to result output.
+
+ @param msg: Test of headline
+ """
+ self.result.append([msg])
+
+
+ def _gen_res(self, format_func):
+ """
+ Format result with foramting function
+
+ @param format_func: Func for formating result.
+ """
+ result = ""
+ for res in self.result:
+ if (len(res) == 3):
+ result += format_func(res) + "\n"
+ else:
+ result += res[0] + "\n"
+ return result
+
+
+ def get_full_text_result(self):
+ """
+ @return string with text form of result
+ """
+ return self._gen_res(lambda str: self.result_to_string_debug(str))
+
+
+ def get_text_result(self):
+ """
+ @return string with text form of result
+ """
+ return self._gen_res(lambda str: self.result_to_string(str))
+
+
+ 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 +275,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 +307,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 +331,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 +356,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,33 +364,33 @@ 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.
"""
- def __init__(self, port, buffer, event, blocklen=1024):
+ def __init__(self, port, buf, event, blocklen=1024):
"""
@param port: Source port.
- @param buffer: Control data buffer (FIFO).
+ @param buf: Control data buffer (FIFO).
@param length: Amount of data we want to receive.
@param blocklen: Block length.
"""
Thread.__init__(self)
self.port = port
- self.buffer = buffer
+ self.buffer = buf
self.exitevent = event
self.blocklen = blocklen
self.idx = 0
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 +408,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,31 +431,32 @@ 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.
+ Execute virtio_console_guest.py on guest, wait until it is initialized.
@param vm: Informations about the guest.
@param timeout: Timeout that will be used to verify if the script
started properly.
"""
- logging.debug("compile virtio_guest.py on guest %s", vm[0].name)
- vm[1].sendline("python -OO /tmp/virtio_guest.py -c &&"
+ logging.debug("compile virtio_console_guest.py on guest %s", vm[0].name)
+
+ (match, data) = _on_guest("python -OO /tmp/virtio_console_guest.py -c &&"
"echo -n 'PASS: Compile virtio_guest finished' ||"
- "echo -n 'FAIL: Compile virtio_guest failed'")
- (match, data) = vm[1].read_until_last_line_matches(["PASS:", "FAIL:"],
- timeout)
- if match == 1 or match is None:
+ "echo -n 'FAIL: Compile virtio_guest failed'",
+ vm, timeout)
+
+ if match != 0:
raise error.TestFail("Command console_switch.py on guest %s failed."
"\nreturn code: %s\n output:\n%s" %
(vm[0].name, match, data))
- logging.debug("Starting virtio_guest.py on guest %s", vm[0].name)
- vm[1].sendline("python /tmp/virtio_guest.pyo &&"
+ logging.debug("Starting virtio_console_guest.py on guest %s", vm[0].name)
+ vm[1].sendline()
+ (match, data) = _on_guest("python /tmp/virtio_console_guest.pyo &&"
"echo -n 'PASS: virtio_guest finished' ||"
- "echo -n 'FAIL: virtio_guest failed'")
- (match, data) = vm[1].read_until_last_line_matches(["PASS:", "FAIL:"],
- timeout)
- if match == 1 or match is None:
+ "echo -n 'FAIL: virtio_guest failed'",
+ vm, timeout)
+ if match != 0:
raise error.TestFail("Command console_switch.py on guest %s failed."
"\nreturn code: %s\n output:\n%s" %
(vm[0].name, match, data))
@@ -384,6 +464,47 @@ def run_virtio_console(test, params, env):
time.sleep(2)
+ def init_guest(vm, consoles):
+ """
+ Prepares guest, executes virtio_console_guest.py and initializes test.
+
+ @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 _search_kernel_crashlog(vm, timeout = 2):
+ """
+ Find kernel crash message.
+
+ @param vm: Informations about the guest.
+ @param timeout: Timeout used to verify expected output.
+
+ @return: Kernel crash log or None.
+ """
+ data = vm[3].read_nonblocking()
+ match = re.search("^BUG:", data, re.MULTILINE)
+ if match == None:
+ return None
+
+ match = re.search(r"^BUG:.*^---\[ end trace .* \]---",
+ data, re.DOTALL |re.MULTILINE)
+ if match == None:
+ data += vm[3].read_until_last_line_matches(
+ ["---\[ end trace .* \]---"],timeout)
+
+ match = re.search(r"(^BUG:.*^---\[ end trace .* \]---)",
+ data, re.DOTALL |re.MULTILINE)
+ return match.group(0)
+
+
+
def _on_guest(command, vm, timeout=2):
"""
Execute given command inside the script's main loop, indicating the vm
@@ -395,12 +516,23 @@ def run_virtio_console(test, params, env):
@return: Tuple (match index, data)
"""
- logging.debug("Executing '%s' on virtio_guest.py loop, vm: %s," +
+ logging.debug("Executing '%s' on virtio_console_guest.py loop, vm: %s," +
"timeout: %s", command, vm[0].name, timeout)
vm[1].sendline(command)
- (match, data) = vm[1].read_until_last_line_matches(["PASS:",
- "FAIL:[Failed to execute]"],
- timeout)
+ try:
+ (match, data) = vm[1].read_until_last_line_matches(["PASS:",
+ "FAIL:"],
+ timeout)
+
+ except (kvm_subprocess.ExpectError):
+ match = None
+ data = "Timeout."
+
+ kcrash_data = _search_kernel_crashlog(vm)
+ if (kcrash_data != None):
+ logging.error(kcrash_data)
+ vm[4] = True
+
return (match, data)
@@ -418,36 +550,13 @@ def run_virtio_console(test, params, env):
"""
match, data = _on_guest(command, vm, timeout)
if match == 1 or match is None:
- raise error.TestFail("Failed to execute '%s' on virtio_guest.py, "
+ raise error.TestFail("Failed to execute '%s' on virtio_console_guest.py, "
"vm: %s, output:\n%s" %
(command, vm[0].name, data))
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 +572,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 +580,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,11 +591,18 @@ 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.
@return: Tuple with (guest information, consoles information)
- guest informations = [vm, session, tmp_dir]
+ guest informations = [vm, session, tmp_dir, kcrash]
consoles informations = [consoles[], serialports[]]
"""
consoles = []
@@ -494,204 +610,326 @@ def run_virtio_console(test, params, env):
tmp_dir = tempfile.mkdtemp(prefix="virtio-console-", dir="/tmp/")
if not params.get('extra_params'):
params['extra_params'] = ''
- params['extra_params'] += " -device virtio-serial"
- for i in range(0, no_console):
+ for i in range(0, no_console):
+ # Spread consoles between multiple PCI devices (2 per a dev)
+ if not i % 2:
+ pci = "virtio-serial-pci%d" % (i / 2)
+ params['extra_params'] += (" -device virtio-serial-pci,id="
+ + pci)
+ pci += ".0"
params['extra_params'] += (" -chardev socket,path=%s/%d,id=vc%d,"
"server,nowait" % (tmp_dir, i, i))
params['extra_params'] += (" -device virtconsole,chardev=vc%d,"
- "name=console-%d,id=c%d" % (i, i, i))
+ "name=console-%d,id=c%d,bus=%s"
+ % (i, i, i, pci))
for i in range(no_console, no_console + no_serialport):
+ # Spread seroal ports between multiple PCI devices (2 per a dev)
+ if not i % 2:
+ pci = "virtio-serial-pci%d" % (i / 2)
+ params['extra_params'] += (" -device virtio-serial-pci,id="
+ + pci)
+ pci += ".0"
params['extra_params'] += (" -chardev socket,path=%s/%d,id=vs%d,"
"server,nowait" % (tmp_dir, i, i))
params['extra_params'] += (" -device virtserialport,chardev=vs%d,"
- "name=serialport-%d,id=p%d" % (i, i, i))
-
+ "name=serialport-%d,id=p%d,bus=%s"
+ % (i, i, i, pci))
logging.debug("Booting first guest %s", params.get("main_vm"))
kvm_preprocessing.preprocess_vm(test, params, env,
params.get("main_vm"))
+ vm = env.get_vm(params.get("main_vm"))
- vm = kvm_utils.env_get_vm(env, params.get("main_vm"))
+ session = vm.wait_for_login(timeout=float(params.get("boot_timeout", 240)))
- session = kvm_test_utils.wait_for_login(vm, 0,
+ sserial = kvm_test_utils.wait_for_login(vm, 0,
float(params.get("boot_timeout", 240)),
- 0, 2)
+ 0, 2, serial=True)
# 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]
+ kcrash = False
+ return [vm, session, tmp_dir, sserial, kcrash], [consoles, serialports]
- def test_smoke(vm, consoles, params):
+
+ def topen(vm, port):
"""
- Virtio console smoke test.
+ Open virtioconsole port.
- Tests the basic functionalities (poll, read/write with and without
- connected host, etc.
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param port: Port identifier.
+ """
+ on_guest("virt.open('%s')" % (port.name), vm, 10)
+ port.open()
- @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;...'
+
+ def tmulti_open(vm, port):
"""
- logging.info("Smoke test: Tests the basic capabilities of "
- "virtio_consoles.")
- # PREPARE
- for param in params.split(';'):
- if not param:
- continue
- logging.info("test_smoke: params: %s", param)
- param = param.split(':')
- if len(param) > 1:
- data = param[1]
- else:
- data = "Smoke test data"
- param = (param[0] == 'serialport')
- send_pt = consoles[param][0]
- recv_pt = consoles[param][1]
+ Multiopen virtioconsole port.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param port: Port identifier.
+ """
+ on_guest("virt.close('%s')" % (port.name), vm, 10)
+ on_guest("virt.open('%s')" % (port.name), vm, 10)
+ (match, data) = _on_guest("virt.open('%s')" % (port.name), vm, 10)
+ # Console is permitted to open the device multiple times
+ if port.port_type == "yes": #is console?
+ if match != 0: #Multiopen not pass
+ raise error.TestFail("Unexpected fail of opening the console"
+ " device for the 2nd time.\n%s" % data)
+ else:
+ if match != 1: #Multiopen not fail:
+ raise error.TestFail("Unexpetded pass of opening the"
+ " serialport device for the 2nd time.")
+ elif not "[Errno 24]" in data:
+ raise error.TestFail("Multiple opening fail but with another"
+ " exception %s" % data)
+ port.open()
+
+ def tclose(vm, port):
+ """
+ Close socket.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param port: Port to open.
+ """
+ on_guest("virt.close('%s')" % (port.name), vm, 10)
+ port.close()
+
+
+ def tpooling(vm, port):
+ """
+ Test try pooling function.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @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, 10)
+
+ # 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, 10)
+
+ # Poll (HUP)
+ on_guest("virt.recv('%s', 4, 1024, False)" % (port.name), vm, 10)
+ 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 tsigio(vm, port):
+ """
+ Test try sigio function.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param port: Port used in test.
+ """
+ if port.is_open:
+ port.close()
+
+ # Enable sigio on specific port
+ on_guest("virt.async('%s', True, 0)" %
+ (port.name) , vm, 10)
+ on_guest("virt.get_sigio_poll_return('%s')" % (port.name) , vm, 10)
+
+ #Test sigio when port open
+ on_guest("virt.set_pool_want_return('%s', select.POLLOUT)" %
+ (port.name), vm, 10)
+ port.open()
+ match = _on_guest("virt.get_sigio_poll_return('%s')" %
+ (port.name) , vm, 10)[0]
+ if match == 1:
+ raise error.TestFail("Problem with HUP on console port.")
+
+ #Test sigio when port receive data
+ on_guest("virt.set_pool_want_return('%s', select.POLLOUT |"
+ " select.POLLIN)" % (port.name), vm, 10)
+ port.sock.sendall("0123456789")
+ on_guest("virt.get_sigio_poll_return('%s')" % (port.name) , vm, 10)
+
+ #Test sigio port close event
+ on_guest("virt.set_pool_want_return('%s', select.POLLHUP |"
+ " select.POLLIN)" % (port.name), vm, 10)
+ port.close()
+ on_guest("virt.get_sigio_poll_return('%s')" % (port.name) , vm, 10)
+
+ #Test sigio port open event and persistence of written data on port.
+ on_guest("virt.set_pool_want_return('%s', select.POLLOUT |"
+ " select.POLLIN)" % (port.name), vm, 10)
+ port.open()
+ on_guest("virt.get_sigio_poll_return('%s')" % (port.name) , vm, 10)
+
+ #Test event when erase data.
+ on_guest("virt.clean_port('%s')" % (port.name), vm, 10)
+ port.close()
+ on_guest("virt.set_pool_want_return('%s', select.POLLOUT)"
+ % (port.name), vm, 10)
+ port.open()
+ on_guest("virt.get_sigio_poll_return('%s')" % (port.name) , vm, 10)
+
+ # Disable sigio on specific port
+ on_guest("virt.async('%s', False, 0)" %
+ (port.name) , vm, 10)
+
+
+ def tlseek(vm, port):
+ """
+ Tests the correct handling of lseek (expected fail)
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param port: Port used in test.
+ """
+ # The virt.lseek returns PASS when the seek fails
+ on_guest("virt.lseek('%s', 0, 0)" % (port.name), vm, 10)
- # 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):
- """
- Virtio console loopback test.
+
+ def trw_host_offline(vm, port):
+ """
+ Guest read/write from host when host is disconnected.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param port: Port used in test.
+ """
+ if port.is_open:
+ port.close()
+
+ on_guest("virt.recv('%s', 0, 1024, False)" % port.name, vm, 10)
+ match, tmp = _on_guest("virt.send('%s', 10, False)"
+ % port.name, vm, 10)
+ 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, 10)
+
+
+ def trw_blocking_mode(vm, port):
+ """
+ Guest read\write data in blocking mode.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param port: Port used in test.
+ """
+ # Blocking mode
+ if not port.is_open:
+ port.open()
+ on_guest("virt.blocking('%s', True)" % port.name, vm, 10)
+ # Recv should timed out
+ match, tmp = _on_guest("virt.recv('%s', 10, 1024, False)" %
+ port.name, vm, 10)
+ 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, 10)
+
+
+ def trw_nonblocking_mode(vm, port):
+ """
+ Guest read\write data in nonblocking mode.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @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, 10)
+ # Recv should return FAIL with 0 received data
+ match, tmp = _on_guest("virt.recv('%s', 10, 1024, False)" %
+ port.name, vm, 10)
+ 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, 10)
+
+
+ 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, ser_session].
+ @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, 10)
+ 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 tloopback(vm, consoles, params):
+ """
+ Virtio console loopback subtest.
Creates loopback on the vm machine between send_pt and recv_pts
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, ser_session].
+ @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 +968,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 +984,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, 10)
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 +1016,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 +1025,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, ser_session].
+ @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,111 +1055,233 @@ 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
+ time_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, 10)
+ 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.sleep(time_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, 10)[0]:
time.sleep(1)
_guest_exit_threads(vm, [port], [])
- if (_time > slice):
+ if (_time > time_slice):
logging.error(
- "Test ran %fs longer which is more than one slice", _time)
+ "Test ran %fs longer which is more than one time slice", _time)
else:
logging.debug("Test ran %fs longer", _time)
- stats = process_stats(stats[1:], slice*1048576)
+ stats = process_stats(stats[1:], time_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()
- on_guest("virt.send_loop()", vm, 2)
+ loads.start()
+ on_guest("virt.send_loop()", vm, 10)
_time = time.time()
for i in range(100):
stats.append(thread.idx)
- time.sleep(slice)
+ time.sleep(time_slice)
_time = time.time() - _time - duration
- print_load([loads[1].get_load(), loads[2].get_load()],
- loads[0].get_load())
- on_guest("virt.exit_threads()", vm, 2)
+ logging.info("\n" + loads.get_cpu_status_string()[:-1])
+ logging.info("\n" + loads.get_mem_status_string()[:-1])
+ on_guest("virt.exit_threads()", vm, 10)
exit_event.set()
thread.join()
- if (_time > slice): # Deviation is higher than 1 slice
+ if (_time > time_slice): # Deviation is higher than 1 time_slice
logging.error(
- "Test ran %fs longer which is more than one slice", _time)
+ "Test ran %fs longer which is more than one time slice", _time)
else:
- logging.debug("Test ran %fs longer" % _time)
- stats = process_stats(stats[1:], slice*1048576)
+ logging.debug("Test ran %fs longer", _time)
+ stats = process_stats(stats[1:], time_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):
+ """
+ Read all data all port from both side of port.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param consoles: Consoles which should be clean.
+ """
+ for ctype in consoles:
+ for port in ctype:
+ openned = port.is_open
+ port.clean_port()
+ #on_guest("virt.blocking('%s', True)" % port.name, vm, 10)
+ on_guest("virt.clean_port('%s'),1024" % port.name, vm, 10)
+ if not openned:
+ port.close()
+ on_guest("virt.close('%s'),1024" % port.name, vm, 10)
+
+
+ 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 vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param consoles: Consoles which should be clean.
+ """
+ # Check if python is still alive
+ print "CLEANING"
+ match, tmp = _on_guest("is_alive()", vm, 10)
+ if (match == None) or (match != 0):
+ logging.error("Python died/is stuck/has remaining threads")
+ logging.debug(tmp)
+ try:
+ if vm[4] == True:
+ raise error.TestFail("Kernel crash.")
+ match, tmp = _on_guest("guest_exit()", vm, 10)
+ if (match == None) or (match == 0):
+ vm[1].close()
+ vm[1] = vm[0].wait_for_login(timeout=float(params.get("boot_timeout", 240)))
+ on_guest("killall -9 python "
+ "&& echo -n PASS: python killed"
+ "|| echo -n PASS: python died",
+ vm, 10)
+
+ init_guest(vm, consoles)
+ _clean_ports(vm, consoles)
+
+ except (error.TestFail, kvm_subprocess.ExpectError,
+ Exception), inst:
+ logging.error(inst)
+ logging.error("Virtio-console driver is irreparably"
+ " blocked. Every comd end with sig KILL."
+ "Try reboot vm for continue in testing.")
+ vm[1] = vm[0].reboot(vm[1], "system_reset")
+ init_guest(vm, consoles)
+ match = _on_guest("virt.clean_port('%s'),1024" %
+ consoles[0][0].name, vm, 10)[0]
+
+ if (match == None) or (match != 0):
+ raise error.TestFail("Virtio-console driver is irrepar"
+ "ably blocked. Every comd end"
+ " with sig KILL. Neither the "
+ "restart did not help.")
+ _clean_ports(vm, consoles)
+
+
+ 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 test: Main test object.
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param consoles: Field of virtio ports with the minimum of 2 items.
+ @param params: Test parameters '$console_type:$data;...'
+ """
+ # PREPARE
+ for param in params.split(';'):
+ if not param:
+ continue
+ headline = "test_smoke: params: %s" % (param)
+ logging.info(headline)
+ param = param.split(':')
+ if len(param) > 1:
+ data = param[1]
+ else:
+ data = "Smoke test data"
+ param = (param[0] == 'serialport')
+ send_pt = consoles[param][0]
+ recv_pt = consoles[param][1]
+ test.headline(headline)
+ test.do_test(topen, [vm, send_pt], True)
+ test.do_test(tclose, [vm, send_pt], True)
+ test.do_test(tmulti_open, [vm, send_pt])
+ test.do_test(tpooling, [vm, send_pt])
+ test.do_test(tsigio, [vm, send_pt])
+ test.do_test(tlseek, [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], True)
+
+
+ def test_multiport(test, vm, consoles, params):
+ """
+ This is group of test which test virtio_console in maximal load and
+ with multiple ports.
+
+ @param test: Main test object.
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param consoles: Field of virtio ports with the minimum of 2 items.
+ @param params: Test parameters '$console_type:$data;...'
+ """
+ test.headline("test_multiport:")
+ #Test Loopback
+ test.do_test(tloopback, [vm, consoles, params[0]])
+
+ #Test Performance
+ test.do_test(tperf, [vm, consoles, params[1]])
# 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:
@@ -924,28 +1290,34 @@ def run_virtio_console(test, params, env):
vm, consoles = _vm_create(no_consoles, no_serialports)
- # Copy allocator.py into guests
+ # Copy virtio_console_guest.py into guests
pwd = os.path.join(os.environ['AUTODIR'], 'tests/kvm')
- vksmd_src = os.path.join(pwd, "scripts/virtio_guest.py")
+ vksmd_src = os.path.join(pwd, "scripts/virtio_console_guest.py")
dst_dir = "/tmp"
- if not vm[0].copy_files_to(vksmd_src, dst_dir):
- raise error.TestFail("copy_files_to failed %s" % vm[0].name)
+ vm[0].copy_files_to(vksmd_src, dst_dir)
# 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)
+ test = SubTest()
+ try:
+ init_guest(vm, consoles)
+
+ test.set_cleanup_func(clean_ports, [vm, consoles])
+ #Test Smoke
+ test_smoke(test, vm, consoles, tsmoke_params)
+
+ #Test multiport functionality and performance.
+ test_multiport(test, vm, consoles, [tloopback_params, tperf_params])
+ finally:
+ logging.info(("Summary: %d tests passed %d test failed :\n" %
+ (test.passed, test.failed)) + test.get_text_result())
+
+ if test.is_failed():
+ raise error.TestFail("Virtio_console test FAILED.")
+
# CLEANUP
vm[1].close()
vm[0].destroy(gracefully=False)
shutil.rmtree(vm[2])
-

Powered by Google App Engine
This is Rietveld 408576698