@@ -547,6 +547,7 @@ class VirtioGuest:
@param in_files: Array of input files.
@param out_files: Array of output files.
@param cachesize: Cachesize.
+ @param mode: Mode of switch.
"""
self.ports = self._get_port_status()
@@ -556,7 +557,7 @@ class VirtioGuest:
s = self.Switch(in_f, out_f, self.exit_thread, cachesize, mode)
s.start()
self.threads.append(s)
- print "PASS: Start switch"
+ print "PASS: Start switch."
def exit_threads(self):
@@ -266,11 +266,12 @@ def run_virtio_console(test, params, env):
"""
Random data sender thread.
"""
- def __init__(self, port, data, event):
+ def __init__(self, port, data, event, quiet=False):
"""
@param port: Destination port.
@param data: The data intend to be send in a loop.
@param event: Exit event.
+ @param quiet: If true don't raise event when crash.
"""
Thread.__init__(self)
self.port = port
@@ -282,14 +283,20 @@ def run_virtio_console(test, params, env):
self.data = data
self.exitevent = event
self.idx = 0
+ self.quiet = quiet
def run(self):
logging.debug("ThSend %s: run", self.getName())
- while not self.exitevent.isSet():
- self.idx += self.port.send(self.data)
- logging.debug("ThSend %s: exit(%d)", self.getName(),
- self.idx)
+ try:
+ while not self.exitevent.isSet():
+ self.idx += self.port.send(self.data)
+ logging.debug("ThSend %s: exit(%d)", self.getName(),
+ self.idx)
+ except Exception as ints:
+ if not self.quiet:
+ raise ints
+ logging.debug(ints)
class ThSendCheck(Thread):
@@ -352,11 +359,12 @@ def run_virtio_console(test, params, env):
"""
Recieves data and throws it away.
"""
- def __init__(self, port, event, blocklen=1024):
+ def __init__(self, port, event, blocklen=1024, quiet=False):
"""
@param port: Data source port.
@param event: Exit event.
@param blocklen: Block length.
+ @param quiet: If true don't raise event when crash.
"""
Thread.__init__(self)
self.port = port
@@ -365,16 +373,24 @@ def run_virtio_console(test, params, env):
self.exitevent = event
self.blocklen = blocklen
self.idx = 0
+ self.quiet = quiet
+
+
def run(self):
logging.debug("ThRecv %s: run", self.getName())
- while not self.exitevent.isSet():
- # TODO: Workaround, it didn't work with select :-/
- try:
- self.idx += len(self.port.recv(self.blocklen))
- except socket.timeout:
- pass
- self.port.settimeout(self._port_timeout)
- logging.debug("ThRecv %s: exit(%d)", self.getName(), self.idx)
+ try:
+ while not self.exitevent.isSet():
+ # TODO: Workaround, it didn't work with select :-/
+ try:
+ self.idx += len(self.port.recv(self.blocklen))
+ except socket.timeout:
+ pass
+ self.port.settimeout(self._port_timeout)
+ logging.debug("ThRecv %s: exit(%d)", self.getName(), self.idx)
+ except Exception as ints:
+ if not self.quiet:
+ raise ints
+ logging.debug(ints)
class ThRecvCheck(Thread):
@@ -621,7 +637,7 @@ def run_virtio_console(test, params, env):
consoles = []
serialports = []
tmp_dir = tempfile.mkdtemp(prefix="virtio-console-", dir="/tmp/")
- params['extra_params'] = ''
+ params['extra_params'] = standard_extra_params
if not spread:
pci = "virtio-serial-pci0"
@@ -638,7 +654,7 @@ def run_virtio_console(test, params, env):
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,bus=%s"
+ "name=console-%d,id=console-%d,bus=%s"
% (i, i, i, pci))
for i in range(no_console, no_console + no_serialport):
@@ -651,8 +667,8 @@ def run_virtio_console(test, params, env):
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,bus=%s"
- % (i, i, i, pci))
+ "name=serialport-%d,id=serialport-%d,"
+ "bus=%s" % (i, i, i, pci))
(vm, session, sserial) = _restore_vm()
@@ -1190,6 +1206,181 @@ def run_virtio_console(test, params, env):
logging.info("Logged in after migration")
+ def _virtio_dev_create(vm, ports_name, pciid, id, console="no"):
+ """
+ Add virtio serialport device.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param ports_name: Structure of ports.
+ @param pciid: Id of virtio-serial-pci device.
+ @param id: Id of port.
+ @param console: if "yes" inicialize console.
+ """
+ port = "serialport-"
+ port_type = "virtserialport"
+ if console == "yes":
+ port = "console-"
+ port_type = "virtconsole"
+ port += "%d%d" % (pciid, id)
+ ret = vm[0].monitors[0].cmd("device_add %s,"
+ "bus=virtio-serial-pci%d.0,"
+ "id=%s,"
+ "name=%s"
+ % (port_type, pciid, port, port))
+ ports_name.append([ port, console])
+ if ret != "":
+ logging.error(ret)
+
+
+ def _virtio_dev_del(vm, ports_name, pciid, id):
+ """
+ Del virtio serialport device.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param ports_name: Structure of ports.
+ @param pciid: Id of virtio-serial-pci device.
+ @param id: Id of port.
+ """
+ port = filter(lambda x: x[0].endswith("-%d%d" % (pciid, id)),
+ ports_name)
+ ret = vm[0].monitors[0].cmd("device_del %s"
+ % (port[0][0]))
+ ports_name.remove(port[0])
+ if ret != "":
+ logging.error(ret)
+
+
+ def thotplug(vm, consoles, console="no", timeout=1):
+ """
+ Try hotplug function of virtio-consoles ports.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param consoles: Consoles.
+ @param console: If "yes" inicialize console.
+ @param timeout: Timeout between hotplug operations.
+ """
+ logging.info("Timeout between hotplug operations t=%fs" % timeout)
+ _reset_vm(vm, consoles, 1, 1)
+ ports_name = []
+ ports_name.append(['serialport-1','no'])
+ ports_name.append(['console-0','yes'])
+
+ logging.info("Test corect initialization of hotplug ports.")
+ for id in range(1,5): #count of pci device
+ ret = vm[0].monitors[0].cmd("device_add virtio-serial-pci,"
+ "id=virtio-serial-pci%d" % (id))
+ if ret != "":
+ logging.error(ret)
+ for i in range(id*5+5): #max port 30
+ _virtio_dev_create(vm, ports_name, id, i, console)
+ time.sleep(timeout)
+
+ # Test corect initialization of hotplug ports.
+ time.sleep(10) #Timeout for port initialization.
+ _init_guest(vm, 10)
+ on_guest('virt.init(%s)' % (ports_name), vm, 10)
+
+ logging.info("Delete ports when ports are used.")
+ # Delete ports when ports are used.
+ if not consoles[0][0].is_open:
+ consoles[0][0].open()
+ if not consoles[1][0].is_open:
+ consoles[1][0].open()
+ on_guest("virt.loopback(['%s'], ['%s'], 1024,"
+ "virt.LOOP_POLL)" % (consoles[0][0].name,
+ consoles[1][0].name), vm, 10)
+ exit_event = threading.Event()
+ send = ThSend(consoles[0][0].sock, "Data", exit_event, quiet = True)
+ recv = ThRecv(consoles[1][0].sock, exit_event, quiet = True)
+ send.start()
+ time.sleep(2)
+ recv.start()
+
+ # Try delete ports under load.
+ ret = vm[0].monitors[0].cmd("device_del serialport-1")
+ ret += vm[0].monitors[0].cmd("device_del console-0")
+ ports_name.remove(['serialport-1','no'])
+ ports_name.remove(['console-0','yes'])
+ if ret != "":
+ logging.error(ret)
+
+ exit_event.set()
+ send.join()
+ recv.join()
+ on_guest("virt.exit_threads()", vm, 10)
+ on_guest('guest_exit()', vm, 10)
+
+ logging.info("Trying add maximum count of ports to one pci device.")
+ # Try add ports.
+ for i in range(30): #max port 30
+ _virtio_dev_create(vm, ports_name, 0, i, console)
+ time.sleep(timeout)
+ _init_guest(vm, 10)
+ time.sleep(10)
+ on_guest('virt.init(%s)' % (ports_name), vm, 20)
+ on_guest('guest_exit()', vm, 10)
+
+ logging.info("Trying delete and add again part of ports.")
+ # Try delete.
+ for i in range(25): #max port 30
+ _virtio_dev_del(vm, ports_name, 0, i)
+ time.sleep(timeout)
+ _init_guest(vm, 10)
+ on_guest('virt.init(%s)' % (ports_name), vm, 10)
+ on_guest('guest_exit()', vm, 10)
+
+ # Try add ports.
+ for i in range(5): #max port 30
+ _virtio_dev_create(vm, ports_name, 0, i, console)
+ time.sleep(timeout)
+ _init_guest(vm, 10)
+ on_guest('virt.init(%s)' % (ports_name), vm, 10)
+ on_guest('guest_exit()', vm, 10)
+
+ logging.info("Trying 100 times add and delete one port.")
+ # Try 100 times add and delete one port.
+ for i in range(100):
+ _virtio_dev_del(vm, ports_name, 0, 0)
+ time.sleep(timeout)
+ _virtio_dev_create(vm, ports_name, 0, 0, console)
+ time.sleep(timeout)
+ _init_guest(vm, 10)
+ on_guest('virt.init(%s)' % (ports_name), vm, 10)
+ on_guest('guest_exit()', vm, 10)
+
+
+ def thotplug_no_timeout(vm, consoles, console="no"):
+ """
+ Start hotplug test without any timeout.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param consoles: Consoles which should be close before rmmod.
+ @param console: If "yes" inicialize console.
+ """
+ thotplug(vm, consoles, console, 0)
+
+
+ def thotplug_virtio_pci(vm, consoles):
+ """
+ Test hotplug of virtio-serial-pci.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param consoles: Consoles which should be close before rmmod.
+ """
+ vm[0].destroy(gracefully = False)
+ (vm, consoles) = _vm_create(1, 1, False)
+ id = 1
+ ret = vm[0].monitors[0].cmd("device_add virtio-serial-pci,"
+ "id=virtio-serial-pci%d" % (id))
+ time.sleep(10)
+ ret += vm[0].monitors[0].cmd("device_del virtio-serial-pci%d" % (id))
+ time.sleep(10)
+ ret += vm[0].monitors[0].cmd("device_add virtio-serial-pci,"
+ "id=virtio-serial-pci%d" % (id))
+ if ret != "":
+ logging.error(ret)
+
+
def tloopback(vm, consoles, params):
"""
Virtio console loopback subtest.
@@ -1446,6 +1637,11 @@ def run_virtio_console(test, params, env):
logging.error("Python died/is stucked/have remaining threads")
logging.debug(tmp)
try:
+ kernel_bug = _search_kernel_crashlog(vm[0].serial_console, 10)
+ if kernel_bug is not None:
+ logging.error(kernel_bug)
+ raise error.TestFail("Kernel crash.")
+
if vm[4] == True:
raise error.TestFail("Kernel crash.")
match, tmp = _on_guest("guest_exit()", vm, 10)
@@ -1493,6 +1689,22 @@ def run_virtio_console(test, params, env):
_clean_ports(vm, consoles)
+ def _reset_vm(vm, consoles, no_console=1, no_serialport=1):
+ """
+ Destroy and reload vm.
+
+ @param vm: Target virtual machine [vm, session, tmp_dir, ser_session].
+ @param consoles: Consoles which should be close and than renew.
+ @param no_console: Number of desired virtconsoles.
+ @param no_serialport: Number of desired virtserialports.
+ """
+ vm[0].destroy(gracefully=False)
+ shutil.rmtree(vm[2]) # Remove virtio sockets tmp directory
+ (_vm, _consoles) = _vm_create(no_console, no_serialport)
+ consoles[:] = _consoles[:]
+ vm[:] = _vm[:]
+
+
def clean_reload_vm(vm, consoles, expected=False):
"""
Reloads and boots the damaged vm
@@ -1504,15 +1716,11 @@ def run_virtio_console(test, params, env):
print "Scheduled vm reboot"
else:
print "SCHWARZENEGGER is CLEANING"
- vm[0].destroy(gracefully=False)
- shutil.rmtree(vm[2]) # Remove virtio sockets tmp directory
- (_vm, _consoles) = _vm_create(len(consoles[0]), len(consoles[1]))
- consoles[:] = _consoles[:]
- vm[:] = _vm[:]
+ _reset_vm(vm, consoles, len(consoles[0]), len(consoles[1]))
init_guest(vm, consoles)
- def test_smoke(test, vm, consoles, params):
+ def test_smoke(test, vm, consoles, params, global_params):
"""
Virtio console smoke test.
@@ -1523,41 +1731,43 @@ def run_virtio_console(test, params, env):
@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;...'
+ @param global_params: Params defined by tests_base.conf.
"""
# 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]
- subtest.headline(headline)
- subtest.do_test(tcheck_zero_sym, [vm], cleanup=False)
- subtest.do_test(topen, [vm, send_pt], True)
- subtest.do_test(tclose, [vm, send_pt], True)
- subtest.do_test(tmulti_open, [vm, send_pt])
- subtest.do_test(tpooling, [vm, send_pt])
- subtest.do_test(tsigio, [vm, send_pt])
- subtest.do_test(tlseek, [vm, send_pt])
- subtest.do_test(trw_host_offline, [vm, send_pt])
- subtest.do_test(trw_host_offline_big_data, [vm, send_pt],
- cleanup=False)
- subtest.do_test(trw_notconnect_guest,
- [vm, send_pt, consoles])
- subtest.do_test(trw_nonblocking_mode, [vm, send_pt])
- subtest.do_test(trw_blocking_mode, [vm, send_pt])
- subtest.do_test(tbasic_loopback, [vm, send_pt, recv_pt, data],
- True)
-
-
- def test_multiport(test, vm, consoles, params):
+ if (global_params.get('smoke_test') == "yes"):
+ 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]
+ subtest.headline(headline)
+ subtest.do_test(tcheck_zero_sym, [vm], cleanup=False)
+ subtest.do_test(topen, [vm, send_pt], True)
+ subtest.do_test(tclose, [vm, send_pt], True)
+ subtest.do_test(tmulti_open, [vm, send_pt])
+ subtest.do_test(tpooling, [vm, send_pt])
+ subtest.do_test(tsigio, [vm, send_pt])
+ subtest.do_test(tlseek, [vm, send_pt])
+ subtest.do_test(trw_host_offline, [vm, send_pt])
+ subtest.do_test(trw_host_offline_big_data, [vm, send_pt],
+ cleanup=False)
+ subtest.do_test(trw_notconnect_guest,
+ [vm, send_pt, consoles])
+ subtest.do_test(trw_nonblocking_mode, [vm, send_pt])
+ subtest.do_test(trw_blocking_mode, [vm, send_pt])
+ subtest.do_test(tbasic_loopback, [vm, send_pt, recv_pt, data],
+ True)
+
+
+ def test_multiport(test, vm, consoles, params, global_params):
"""
This is group of test which test virtio_console in maximal load and
with multiple ports.
@@ -1566,34 +1776,59 @@ def run_virtio_console(test, params, env):
@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;...'
+ @param global_params: Params defined by tests_base.conf.
"""
subtest.headline("test_multiport:")
# Test Loopback
- subtest.do_test(tloopback, [vm, consoles, params[0]])
+ if (global_params.get('loopback_test') == "yes"):
+ subtest.do_test(tloopback, [vm, consoles, params[0]])
# Test Performance
- subtest.do_test(tperf, [vm, consoles, params[1]])
+ if (global_params.get('perf_test') == "yes"):
+ subtest.do_test(tperf, [vm, consoles, params[1]])
- def test_destructive(test, vm, consoles):
+ def test_destructive(test, vm, consoles, global_params):
"""
This is group of test is destructive.
@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 global_params: Params defined by tests_base.conf.
"""
subtest.headline("test_destructive:")
- # Test rmmod
- subtest.do_test(trmmod, [vm, consoles])
- subtest.do_test(tmax_serial_ports, [vm, consoles])
- subtest.do_test(tmax_console_ports, [vm, consoles])
- subtest.do_test(tmax_mix_serial_conosle_port, [vm, consoles])
- subtest.do_test(tshutdown, [vm, consoles])
- subtest.do_test(tmigrate_offline, [vm, consoles])
+ # Uses stronger clean up function
+ (_cleanup_func, _cleanup_args) = subtest.get_cleanup_func()
+ subtest.set_cleanup_func(clean_reload_vm, [vm, consoles])
+
+ if (global_params.get('rmmod_test') == "yes"):
+ subtest.do_test(trmmod,[vm, consoles])
+ if (global_params.get('max_ports_test') == "yes"):
+ subtest.do_test(tmax_serial_ports, [vm, consoles])
+ subtest.do_test(tmax_console_ports, [vm, consoles])
+ subtest.do_test(tmax_mix_serial_conosle_port, [vm, consoles])
+ if (global_params.get('shutdown_test') == "yes"):
+ subtest.do_test(tshutdown, [vm, consoles])
+ if (global_params.get('migrate_test') == "yes"):
+ subtest.do_test(tmigrate_offline, [vm, consoles])
+ if (global_params.get('hotplug_serial_test') == "yes"):
+ subtest.do_test(thotplug, [vm, consoles])
+ subtest.do_test(thotplug_no_timeout, [vm, consoles])
+ if (global_params.get('hotplug_console_test') == "yes"):
+ subtest.do_test(thotplug, [vm, consoles, "yes"])
+ subtest.do_test(thotplug_no_timeout, [vm, consoles, "yes"])
+ if (global_params.get('hotplug_pci_test') == "yes"):
+ subtest.do_test(thotplug_virtio_pci, [vm, consoles])
+
+ subtest.set_cleanup_func(_cleanup_func, _cleanup_args)
# INITIALIZE
+ if "extra_params" in params:
+ standard_extra_params = params['extra_params']
+ else:
+ standard_extra_params = ""
tsmoke_params = params.get('virtio_console_smoke', '')
tloopback_params = params.get('virtio_console_loopback', '')
@@ -1638,17 +1873,14 @@ def run_virtio_console(test, params, env):
subtest.set_cleanup_func(clean_ports, [vm, consoles])
# Test Smoke
- test_smoke(subtest, vm, consoles, tsmoke_params)
+ test_smoke(subtest, vm, consoles, tsmoke_params, params)
# Test multiport functionality and performance.
- test_multiport(subtest, vm, consoles, [tloopback_params, tperf_params])
+ test_multiport(subtest, vm, consoles, [tloopback_params, tperf_params],
+ params)
- # Test destructive test.
- # Uses stronger clean up function
- (_cleanup_func, _cleanup_args) = subtest.get_cleanup_func()
- subtest.set_cleanup_func(clean_reload_vm, [vm, consoles])
- test_destructive(subtest, vm, consoles)
- subtest.set_cleanup_func(_cleanup_func, _cleanup_args)
+ #Test destructive test.
+ test_destructive(subtest, vm, consoles, params)
finally:
logging.info(("Summary: %d tests passed %d test failed :\n" %
(subtest.passed, subtest.failed)) +
@@ -759,13 +759,25 @@ variants:
# smoke params - $console_type:data_string
# FIXME: test_smoke doesn't work with console yet (virtio_console bug)
# "serialport;console:Custom data"
+ smoke_test = yes
virtio_console_smoke = "serialport"
# loopback params - '$source_console_type@buffer_length:$destination_console_type1@buffer_length:...:$loopback_buffer_length;...'
+ loopback_test = yes
virtio_console_loopback = "serialport:serialport;serialport@1024:serialport@32:console@1024:console@8:16"
# perf params - $console_type@buffer_length:$test_duration
# FIXME: test_perf doesn't work with console yet (virtio_console bug)
# virtio_console_perf = "serialport;serialport@1000000:120;console@1024:60"
+ perf_test = yes
virtio_console_perf = "serialport;serialport@1000000:120"
+ #Enable destructive tests: "test_name = yes"
+ #Disable test: change yes or delete key.
+ rmmod_test = yes
+ max_ports_test = yes
+ shutdown_test = yes
+ migrate_test = yes
+ hotplug_test = yes
+ hotplug_serial_test = yes
+ hotplug_console_test = no
# This unit test module is for older branches of KVM that use the
# kvmctl test harness (such as the code shipped with RHEL 5.x)