As my punishment for the break in 7f15ebc7 (fixed in 752596b5dd) I'm introducing this test to make sure it won't happen again. Currently, only test for <graphics/> is supported. --- .gitignore | 1 + tests/Makefile.am | 11 +- tests/qemuhotplugtest.c | 208 +++++++++++++++++++++ .../qemuhotplug-disk-cdrom-nochange.xml | 6 + .../qemuhotplug-graphics-spice-listen.xml | 11 ++ .../qemuhotplug-graphics-spice-nochange.xml | 11 ++ ...qemuhotplug-graphics-spice-timeout-nochange.xml | 1 + ...qemuhotplug-graphics-spice-timeout-password.xml | 1 + .../qemuxml2argv-graphics-spice-listen-network.xml | 45 +++++ 9 files changed, 293 insertions(+), 2 deletions(-) create mode 100644 tests/qemuhotplugtest.c create mode 100644 tests/qemuhotplugtestdata/qemuhotplug-disk-cdrom-nochange.xml create mode 100644 tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-listen.xml create mode 100644 tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-nochange.xml create mode 100644 tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-timeout-nochange.xml create mode 100644 tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-timeout-password.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-listen-network.xml diff --git a/.gitignore b/.gitignore index 7a28941..3efc2e4 100644 --- a/.gitignore +++ b/.gitignore @@ -167,6 +167,7 @@ /tests/openvzutilstest /tests/qemuargv2xmltest /tests/qemuhelptest +/tests/qemuhotplugtest /tests/qemumonitorjsontest /tests/qemumonitortest /tests/qemuxmlnstest diff --git a/tests/Makefile.am b/tests/Makefile.am index 9c9c802..a019eb9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -155,7 +155,7 @@ endif if WITH_QEMU test_programs += qemuxml2argvtest qemuxml2xmltest qemuxmlnstest \ qemuargv2xmltest qemuhelptest domainsnapshotxml2xmltest \ - qemumonitortest qemumonitorjsontest + qemumonitortest qemumonitorjsontest qemuhotplugtest endif if WITH_LXC @@ -405,6 +405,13 @@ qemumonitorjsontest_SOURCES = \ $(NULL) qemumonitorjsontest_LDADD = $(qemu_LDADDS) libqemumonitortestutils.la +qemuhotplugtest_SOURCES = \ + qemuhotplugtest.c \ + testutils.c testutils.h \ + testutilsqemu.c testutilsqemu.h \ + $(NULL) +qemuhotplugtest_LDADD = $(qemu_LDADDS) libqemumonitortestutils.la + domainsnapshotxml2xmltest_SOURCES = \ domainsnapshotxml2xmltest.c testutilsqemu.c testutilsqemu.h \ testutils.c testutils.h @@ -413,7 +420,7 @@ else EXTRA_DIST += qemuxml2argvtest.c qemuxml2xmltest.c qemuargv2xmltest.c \ qemuxmlnstest.c qemuhelptest.c domainsnapshotxml2xmltest.c \ qemumonitortest.c testutilsqemu.c testutilsqemu.h \ - qemumonitorjsontest.c \ + qemumonitorjsontest.c qemuhotplugtest.c \ $(QEMUMONITORTESTUTILS_SOURCES) endif diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c new file mode 100644 index 0000000..ed3ca7f --- /dev/null +++ b/tests/qemuhotplugtest.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2011-2013 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> + +#include "qemu/qemu_conf.h" +#include "qemu/qemu_hotplug.h" +#include "qemumonitortestutils.h" +#include "testutils.h" +#include "testutilsqemu.h" +#include "virerror.h" +#include "virstring.h" +#include "virthread.h" +#include "virfile.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +static virQEMUDriver driver; + +struct qemuHotplugTestData { + const char *domain_filename; + const char *device_filename; + bool fail; + const char *const *mon; +}; + +static int +qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt, + virDomainObjPtr *vm, + const char *filename) +{ + int ret = -1; + + if (!(*vm = virDomainObjNew(xmlopt))) + goto cleanup; + + if (!((*vm)->def = virDomainDefParseFile(filename, + driver.caps, + driver.xmlopt, + QEMU_EXPECTED_VIRT_TYPES, + 0))) + goto cleanup; + + ret = 0; +cleanup: + return ret; +} + +static int +testQemuHotplug(const void *data) +{ + int ret = -1; + struct qemuHotplugTestData *test = (struct qemuHotplugTestData *) data; + char *domain_filename = NULL; + char *device_filename = NULL; + char *device_xml = NULL; + const char *const *tmp; + bool fail = test->fail; + virDomainObjPtr vm = NULL; + virDomainDeviceDefPtr dev = NULL; + virCapsPtr caps = NULL; + qemuMonitorTestPtr test_mon = NULL; + qemuDomainObjPrivatePtr priv; + + if (virAsprintf(&domain_filename, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml", + abs_srcdir, test->domain_filename) < 0 || + virAsprintf(&device_filename, "%s/qemuhotplugtestdata/qemuhotplug-%s.xml", + abs_srcdir, test->device_filename) < 0) + goto cleanup; + + if (!(caps = virQEMUDriverGetCapabilities(&driver, false))) + goto cleanup; + + if (qemuHotplugCreateObjects(driver.xmlopt, &vm, domain_filename) < 0) + goto cleanup; + + priv = vm->privateData; + + if (virtTestLoadFile(device_filename, &device_xml) < 0) + goto cleanup; + + if (!(dev = virDomainDeviceDefParse(device_xml, vm->def, + caps, driver.xmlopt, + VIR_DOMAIN_XML_INACTIVE))) + goto cleanup; + + /* Now is the best time to feed the spoofed monitor with predefined + * replies. */ + if (!(test_mon = qemuMonitorTestNew(true, driver.xmlopt))) + goto cleanup; + + tmp = test->mon; + while (tmp && *tmp) { + const char *command_name; + const char *response; + + if (!(command_name = *tmp++) || + !(response = *tmp++)) + break; + if (qemuMonitorTestAddItem(test_mon, command_name, response) < 0) + goto cleanup; + } + + priv->mon = qemuMonitorTestGetMonitor(test_mon); + priv->monJSON = true; + + /* XXX We need to unlock the monitor here, as + * qemuDomainObjEnterMonitorInternal (called from qemuDomainChangeGraphics) + * tries to lock it again */ + virObjectUnlock(priv->mon); + + /* XXX Ideally, we would call qemuDomainUpdateDeviceLive here. But that + * would require us to provide virConnectPtr and virDomainPtr (they're used + * in case of updating a disk device. So for now, we will proceed with + * breaking the function into pieces. If we ever learn how to fake those + * required object, we can replace this code then. */ + switch (dev->type) { + case VIR_DOMAIN_DEVICE_GRAPHICS: + ret = qemuDomainChangeGraphics(&driver, vm, dev->data.graphics); + break; + default: + if (virTestGetVerbose()) + fprintf(stderr, "device type '%s' cannot be updated", + virDomainDeviceTypeToString(dev->type)); + break; + } + +cleanup: + VIR_FREE(domain_filename); + VIR_FREE(device_filename); + VIR_FREE(device_xml); + /* don't dispose test monitor with VM */ + priv->mon = NULL; + virObjectUnref(vm); + virDomainDeviceDefFree(dev); + virObjectUnref(caps); + qemuMonitorTestFree(test_mon); + return ((ret < 0 && fail) || (!ret && !fail)) ? 0 : -1; +} + +static int +mymain(void) +{ + int ret = 0; + +#if !WITH_YAJL + fputs("libvirt not compiled with yajl, skipping this test\n", stderr); + return EXIT_AM_SKIP; +#endif + + if (virThreadInitialize() < 0 || + !(driver.caps = testQemuCapsInit()) || + !(driver.xmlopt = virQEMUDriverCreateXMLConf(&driver))) + return EXIT_FAILURE; + + virEventRegisterDefaultImpl(); + + driver.config = virQEMUDriverConfigNew(false); + VIR_FREE(driver.config->spiceListen); + VIR_FREE(driver.config->vncListen); + + /* some dummy values from 'config file' */ + if (VIR_STRDUP_QUIET(driver.config->spicePassword, "123456") < 0) + return EXIT_FAILURE; + +#define DO_TEST(file, dev, fial, ...) \ + do { \ + const char *my_mon[] = { __VA_ARGS__, NULL}; \ + struct qemuHotplugTestData data = \ + {.domain_filename = file, .device_filename = dev, .fail = fial, \ + .mon = my_mon}; \ + if (virtTestRun(#file, 1, testQemuHotplug, &data) < 0) \ + ret = -1; \ + } while (0) + + DO_TEST("graphics-spice", "graphics-spice-nochange", false, NULL); + DO_TEST("graphics-spice-timeout", "graphics-spice-timeout-nochange", false, + "set_password", "{\"return\":{}}", "expire_password", "{\"return\":{}}"); + DO_TEST("graphics-spice-timeout", "graphics-spice-timeout-password", false, + "set_password", "{\"return\":{}}", "expire_password", "{\"return\":{}}"); + DO_TEST("graphics-spice", "graphics-spice-listen", true, NULL); + DO_TEST("graphics-spice-listen-network", "graphics-spice-listen-network", false, + "set_password", "{\"return\":{}}", "expire_password", "{\"return\":{}}"); + /* Strange huh? Currently, only graphics can be testet :-P */ + DO_TEST("disk-cdrom", "disk-cdrom-nochange", true, NULL); + + virObjectUnref(driver.caps); + virObjectUnref(driver.xmlopt); + return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIRT_TEST_MAIN(mymain) diff --git a/tests/qemuhotplugtestdata/qemuhotplug-disk-cdrom-nochange.xml b/tests/qemuhotplugtestdata/qemuhotplug-disk-cdrom-nochange.xml new file mode 100644 index 0000000..26841ea --- /dev/null +++ b/tests/qemuhotplugtestdata/qemuhotplug-disk-cdrom-nochange.xml @@ -0,0 +1,6 @@ + <disk type='block' device='disk'> + <driver name='qemu' type='raw'/> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> diff --git a/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-listen.xml b/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-listen.xml new file mode 100644 index 0000000..d4a8d04 --- /dev/null +++ b/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-listen.xml @@ -0,0 +1,11 @@ + <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='192.168.0.1' defaultMode='secure'> + <listen type='address' address='192.168.0.1'/> + <channel name='main' mode='secure'/> + <channel name='inputs' mode='insecure'/> + <image compression='auto_glz'/> + <jpeg compression='auto'/> + <zlib compression='auto'/> + <playback compression='on'/> + <streaming mode='filter'/> + <clipboard copypaste='no'/> + </graphics> diff --git a/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-nochange.xml b/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-nochange.xml new file mode 100644 index 0000000..498ffa2 --- /dev/null +++ b/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-nochange.xml @@ -0,0 +1,11 @@ + <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1' defaultMode='secure'> + <listen type='address' address='127.0.0.1'/> + <channel name='main' mode='secure'/> + <channel name='inputs' mode='insecure'/> + <image compression='auto_glz'/> + <jpeg compression='auto'/> + <zlib compression='auto'/> + <playback compression='on'/> + <streaming mode='filter'/> + <clipboard copypaste='no'/> + </graphics> diff --git a/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-timeout-nochange.xml b/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-timeout-nochange.xml new file mode 100644 index 0000000..f7ea796 --- /dev/null +++ b/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-timeout-nochange.xml @@ -0,0 +1 @@ + <graphics type='spice' port='5900' autoport='no' passwd='sercet' passwdValidTo='2011-05-31T16:11:22' connected='disconnect'/> diff --git a/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-timeout-password.xml b/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-timeout-password.xml new file mode 100644 index 0000000..f826459 --- /dev/null +++ b/tests/qemuhotplugtestdata/qemuhotplug-graphics-spice-timeout-password.xml @@ -0,0 +1 @@ + <graphics type='spice' port='5900' autoport='no' passwd='secret' passwdValidTo='2013-05-31T16:11:22' connected='disconnect'/> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-listen-network.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-listen-network.xml new file mode 100644 index 0000000..34971fe --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice-listen-network.xml @@ -0,0 +1,45 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <input type='mouse' bus='ps2'/> + <graphics autoport='yes' connected='disconnect' keymap='en-us' passwd='password' passwdValidTo='2013-06-20T01:34:37' port='5900' tlsPort='5901' type='spice'> + <listen address='10.65.210.231' network='vdsm-rhevm' type='network'/> + <channel mode='secure' name='main'/> + <channel mode='secure' name='display'/> + <channel mode='secure' name='inputs'/> + <channel mode='secure' name='cursor'/> + <channel mode='secure' name='playback'/> + <channel mode='secure' name='record'/> + <channel mode='secure' name='smartcard'/> + <channel mode='secure' name='usbredir'/> + </graphics> + <video> + <model type='qxl' ram='65536' vram='18432' heads='1'/> + </video> + <video> + <model type='qxl' ram='65536' vram='32768' heads='1'/> + </video> + <memballoon model='virtio'/> + </devices> +</domain> -- 1.8.1.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list