--- kvm/tests/chardev_hotplug.py | 124 ++++++++++++++++++++++++++++++++++++++++ shared/cfg/subtests.cfg.sample | 7 ++ 2 files changed, 131 insertions(+), 0 deletions(-) create mode 100644 kvm/tests/chardev_hotplug.py
diff --git a/kvm/tests/chardev_hotplug.py b/kvm/tests/chardev_hotplug.py new file mode 100644 index 0000000..64e2b9c --- /dev/null +++ b/kvm/tests/chardev_hotplug.py @@ -0,0 +1,124 @@ +import logging, re, uuid, os, fcntl +from autotest.client.shared import error +from autotest.client import utils + +@error.context_aware +def run_chardev_hotplug(test, params, env): + """ + Test chardev hotplug + + @param test: kvm test object + @param params: Dictionary with the test parameters + @param env: Dictionary with test environment. + """ + + def cmd_qmp_log(vm, cmd, args): + logging.debug("[qmp cmd %s] %s" % (cmd, args)) + reply = vm.monitor.cmd_qmp(cmd, args) + logging.debug("[qmp reply] %s" % reply) + if "error" in reply: + if reply["error"]["class"] == "CommandNotFound": + raise error.TestNAError("qmp command %s not supported" % cmd) + else: + raise error.TestFail("qmp error: %s" % reply["error"]["desc"]) + return reply + + def pci_serial_add(vm, name, addr, chardev): + reply = cmd_qmp_log(vm, 'device_add', { 'driver' : 'pci-serial', + 'id' : name, + 'addr' : addr, + 'chardev' : chardev } ) + return reply + + def device_del(vm, name): + reply = cmd_qmp_log(vm, 'device_del', { 'id' : name } ) + return reply + + def chardev_add(vm, name, kind, args): + backend = { 'type': kind, 'data' : args } + reply = cmd_qmp_log(vm, 'chardev-add', { 'id' : name, + 'backend' : backend } ) + return reply + + def chardev_del(vm, name): + reply = cmd_qmp_log(vm, 'chardev-remove', { 'id' : name } ) + return reply + + def chardev_use(vm, name): + addr = "18.0" + + # hotplug serial adapter + pci_serial_add(vm, "test-serial", addr, name) + session.cmd_status("sleep 1") + session.cmd_status("udevadm settle") + msg_add = session.cmd("dmesg -c | grep %s" % addr) + for line in msg_add.splitlines(): + logging.debug("[dmesg add] %s" % line) + lspci = session.cmd("lspci -vs %s" % addr) + for line in lspci.splitlines(): + logging.debug("[lspci] %s" % line) + + # send message + device = session.cmd("ls /sys/bus/pci/devices/*%s/tty" % addr) + device = device.strip() + logging.info("guest tty device is '%s'" % device) + session.cmd("test -c /dev/%s" % device) + session.cmd("echo 'Hello virttest world' > /dev/%s" % device) + + # unplug serial adapter + device_del(vm, "test-serial") + session.cmd_status("sleep 1") + msg_del = session.cmd("dmesg -c") + for line in msg_del.splitlines(): + logging.debug("[dmesg del] %s" % line) + + error.context("Log into guest", logging.info) + vm = env.get_vm(params["main_vm"]) + vm.verify_alive() + session = vm.wait_for_login() + session.cmd_status("dmesg -c") + + error.context("Test null chardev", logging.info) + chardev_add(vm, "chardev-null", "null", {}) + chardev_use(vm, "chardev-null") + chardev_del(vm, "chardev-null") + + error.context("Test file chardev [path]", logging.info) + filename = "/tmp/chardev-file-%s" % vm.instance + args = { 'out' : { 'type' : 'path', 'data' : filename }} + chardev_add(vm, "chardev-file", "file", args) + chardev_use(vm, "chardev-file") + chardev_del(vm, "chardev-file") + output = utils.system_output("cat %s" % filename) + if output.find("Hello virttest world") == -1: + raise error.TestFail("Guest message not found [%s]" % output) + + error.context("Test file chardev [fd]", logging.info) + (fd_dst, fd_src) = os.pipe() + fl = fcntl.fcntl(fd_dst, fcntl.F_GETFL) + fcntl.fcntl(fd_dst, fcntl.F_SETFL, fl | os.O_NONBLOCK) + vm.monitor.getfd(fd_src, "chardev-fd") + os.close(fd_src) + args = { 'out' : { 'type' : 'fd', 'data' : "chardev-fd" }} + chardev_add(vm, "chardev-file", "file", args) + chardev_use(vm, "chardev-file") + output = os.read(fd_dst, 256) + os.close(fd_dst) + if output.find("Hello virttest world") == -1: + raise error.TestFail("Guest message not found [%s]" % output) + chardev_del(vm, "chardev-file") + + error.context("Test pty chardev", logging.info) + reply = chardev_add(vm, "chardev-pty", "pty", {}) + filename = reply["return"]["data"] + logging.info("host pty device is '%s'" % filename) + fd_dst = os.open(filename, os.O_RDWR | os.O_NONBLOCK) + chardev_use(vm, "chardev-pty") + output = os.read(fd_dst, 256) + os.close(fd_dst) + if output.find("Hello virttest world") == -1: + raise error.TestFail("Guest message not found [%s]" % output) + chardev_del(vm, "chardev-pty") + + error.context("Cleanup", logging.info) + session.close() diff --git a/shared/cfg/subtests.cfg.sample b/shared/cfg/subtests.cfg.sample index 14cbff5..f8b4954 100644 --- a/shared/cfg/subtests.cfg.sample +++ b/shared/cfg/subtests.cfg.sample @@ -3634,6 +3634,13 @@ variants: # Specify the boot device name which you want to test here. boot_device = "iPXE" + - chardev_hotplug: install setup image_copy unattended_install.cdrom + virt_test_type = kvm + type = chardev_hotplug + monitor_type = qmp + restart_vm = yes + kill_vm = yes + - fail_test: virt_test_type = libvirt kvm openvswitch v2v type = fail -- 1.7.1