Signed-off-by: Marc Hartmayer <mhartmay(a)linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy(a)linux.ibm.com>
---
src/test/test_driver.c | 6 +
tests/objecteventtest.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 327 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index cb5377004df7..6536e41bf4ad 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -444,6 +444,12 @@ static const char *defaultConnXML =
" <os>"
" <type>hvm</type>"
" </os>"
+" <devices>"
+" <disk type='file' device='disk'>"
+" <source file='/tmp/na'/>"
+" <target dev='vda'/>"
+" </disk>"
+" </devices>"
"</domain>"
""
"<network>"
diff --git a/tests/objecteventtest.c b/tests/objecteventtest.c
index 4b12572eb45b..cc7287e2fc66 100644
--- a/tests/objecteventtest.c
+++ b/tests/objecteventtest.c
@@ -472,6 +472,325 @@ testDomainStartStopEvent(const void *data)
return ret;
}
+
+typedef struct {
+ int count_boot_order;
+ int count_os_boot;
+ char *bootdeviceIdentifier;
+ char *kernel;
+ char *initrd;
+ char *cmdline;
+} bootConfiguration;
+
+
+static void
+bootConfigurationFree(bootConfiguration *conf)
+{
+ if (!conf)
+ return;
+
+ VIR_FREE(conf->bootdeviceIdentifier);
+ VIR_FREE(conf->kernel);
+ VIR_FREE(conf->initrd);
+ VIR_FREE(conf->cmdline);
+ VIR_FREE(conf);
+}
+
+
+static bool
+bootConfigurationEqual(bootConfiguration *a,
+ bootConfiguration *b)
+{
+ if (!a || !b)
+ return a == b;
+
+ return a->count_boot_order == b->count_boot_order &&
+ a->count_os_boot == b->count_os_boot &&
+ STREQ_NULLABLE(a->bootdeviceIdentifier, b->bootdeviceIdentifier)
&&
+ STREQ_NULLABLE(a->kernel, b->kernel) &&
+ STREQ_NULLABLE(a->initrd, b->initrd) &&
+ STREQ_NULLABLE(a->cmdline, b->cmdline);
+}
+
+
+/* Caller must free() the returned value */
+static bootConfiguration*
+getBootConfiguration(virDomainPtr dom)
+{
+ bootConfiguration* ret;
+ char *xml = NULL;
+ xmlDocPtr doc = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlNodePtr node = NULL;
+
+ if (VIR_ALLOC(ret) < 0)
+ return NULL;
+
+ if (!(xml = virDomainGetXMLDesc(dom, 0)))
+ goto error;
+
+ if (!(doc = virXMLParseStringCtxt(xml, "(domain_definition)", &ctxt)))
+ goto error;
+
+ ret->kernel = virXPathString("string(./os/kernel[1])", ctxt);
+ ret->initrd = virXPathString("string(./os/initrd[1])", ctxt);
+ ret->cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
+
+ if (virXPathInt("count(./os/boot)", ctxt, &ret->count_boot_order)
< 0)
+ goto error;
+
+ if ((virXPathInt("count(./devices/*/boot[@order='1'])", ctxt,
&ret->count_boot_order) < 0))
+ goto error;
+
+ if (ret->count_boot_order > 0) {
+ node = virXPathNode("./devices/*/boot[@order='1']/..", ctxt);
+ if (!node)
+ goto error;
+
+ ctxt->node = node;
+
+ /* As we're using a heuristic for setting the boot device do
+ * the same here.
+ *
+ * Represents the XML node a disk? */
+ ret->bootdeviceIdentifier = virXPathString("string(./target/@dev)",
ctxt);
+
+ /* Represents the XML node a network interface? (we only allow
+ * MAC addresses as boot device identifier for the tests (at
+ * least for the moment)) */
+ if (!ret->bootdeviceIdentifier)
+ ret->bootdeviceIdentifier =
virXPathString("string(./mac/@address)", ctxt);
+ } else {
+ ret->bootdeviceIdentifier = NULL;
+ }
+
+ cleanup:
+ xmlFreeDoc(doc);
+ xmlXPathFreeContext(ctxt);
+ VIR_FREE(xml);
+ return ret;
+
+ error:
+ bootConfigurationFree(ret);
+ ret = NULL;
+ goto cleanup;
+}
+
+
+static int
+verifyOriginalState(virDomainPtr dom, bootConfiguration *original_conf)
+{
+ bool ret;
+ bootConfiguration *current_conf = getBootConfiguration(dom);
+
+ if (!current_conf)
+ return false;
+
+ ret = bootConfigurationEqual(original_conf,
+ current_conf);
+ bootConfigurationFree(current_conf);
+ return ret;
+}
+
+
+static int
+verifyChanges(virDomainPtr dom,
+ const char *bootdevice,
+ const char *kernel,
+ const char *initrd,
+ const char *cmdline)
+{
+ int ret = -1;
+ bootConfiguration *current_conf;
+
+ if (!(current_conf = getBootConfiguration(dom)))
+ goto cleanup;
+
+ /* verify the new boot order */
+ if (bootdevice) {
+ if (STRNEQ_NULLABLE(current_conf->bootdeviceIdentifier, bootdevice))
+ goto cleanup;
+
+ if (current_conf->count_os_boot != 0)
+ goto cleanup;
+
+ if (current_conf->count_boot_order < 1)
+ goto cleanup;
+ }
+
+ /* verify the other OS node changes */
+ if ((kernel && virStringIsEmpty(kernel) && current_conf->kernel)
||
+ (!virStringIsEmpty(kernel) && STRNEQ_NULLABLE(current_conf->kernel,
kernel)))
+ goto cleanup;
+
+ if ((initrd && virStringIsEmpty(initrd) && current_conf->initrd)
||
+ (!virStringIsEmpty(initrd) && STRNEQ_NULLABLE(current_conf->initrd,
initrd)))
+ goto cleanup;
+
+ if ((cmdline && virStringIsEmpty(cmdline) &&
current_conf->cmdline) ||
+ (!virStringIsEmpty(cmdline) && STRNEQ_NULLABLE(current_conf->cmdline,
cmdline)))
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ bootConfigurationFree(current_conf);
+ return ret;
+}
+
+
+static int
+testDomainCreateWithParamsHelper(virDomainPtr dom, lifecycleEventCounter *counter,
+ bool failure_expected, const char *bootdevice,
+ const char *kernel, const char *initrd,
+ const char *cmdline, unsigned int flags,
bootConfiguration *original_conf)
+{
+ int rc;
+ int ret = -1;
+ virTypedParameterPtr params = NULL;
+ int nparams = 0;
+ int maxparams = 0;
+
+ lifecycleEventCounter_reset(counter);
+
+ if (bootdevice)
+ virTypedParamsAddFromString(¶ms,
+ &nparams,
+ &maxparams,
+ VIR_DOMAIN_CREATE_PARM_DEVICE_IDENTIFIER,
+ VIR_TYPED_PARAM_STRING,
+ bootdevice);
+
+ if (kernel)
+ virTypedParamsAddFromString(¶ms,
+ &nparams,
+ &maxparams,
+ VIR_DOMAIN_CREATE_PARM_KERNEL,
+ VIR_TYPED_PARAM_STRING,
+ kernel);
+
+ if (initrd)
+ virTypedParamsAddFromString(¶ms,
+ &nparams,
+ &maxparams,
+ VIR_DOMAIN_CREATE_PARM_INITRD,
+ VIR_TYPED_PARAM_STRING,
+ initrd);
+
+ if (cmdline)
+ virTypedParamsAddFromString(¶ms,
+ &nparams,
+ &maxparams,
+ VIR_DOMAIN_CREATE_PARM_CMDLINE,
+ VIR_TYPED_PARAM_STRING,
+ cmdline);
+
+ rc = virDomainCreateWithParams(dom,
+ params,
+ nparams,
+ flags);
+ if (rc < 0) {
+ if (failure_expected)
+ ret = 0;
+ goto cleanup;
+ }
+
+ if (virEventRunDefaultImpl() < 0)
+ goto cleanup;
+
+ if (counter->startEvents != 1 ||
+ counter->stopEvents != 0)
+ goto cleanup;
+
+ if (verifyChanges(dom, bootdevice, kernel, initrd, cmdline) < 0)
+ goto cleanup;
+
+ if (virDomainDestroy(dom) < 0)
+ goto cleanup;
+
+ if (verifyOriginalState(dom, original_conf) < 0)
+ goto cleanup;
+
+ if (virEventRunDefaultImpl() < 0)
+ goto cleanup;
+
+ if (counter->startEvents != 1 ||
+ counter->stopEvents != 1)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ virTypedParamsFree(params, nparams);
+ return ret;
+}
+
+
+static int
+testDomainCreateWithParams(const void *data)
+{
+ const objecteventTest *test = data;
+ lifecycleEventCounter counter;
+ int eventId = VIR_DOMAIN_EVENT_ID_LIFECYCLE;
+ int id;
+ int ret = -1;
+ virDomainPtr dom;
+ bootConfiguration *original_boot_conf = NULL;
+
+ dom = virDomainLookupByName(test->conn, "test");
+ if (!dom)
+ return -1;
+
+ /* First clean up, register for the life cycle events, and get the
+ * original, persistent boot configuration of the domain */
+ virDomainDestroy(dom);
+
+ id = virConnectDomainEventRegisterAny(test->conn, dom, eventId,
+
VIR_DOMAIN_EVENT_CALLBACK(&domainLifecycleCb),
+ &counter, NULL);
+
+ if (!(original_boot_conf = getBootConfiguration(dom)))
+ goto cleanup;
+
+ if (testDomainCreateWithParamsHelper(dom, &counter, true,
"notAvailableBootDevice",
+ NULL, NULL, NULL, 0, original_boot_conf) <
0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, false, NULL, NULL, NULL,
+ NULL, 0, original_boot_conf) < 0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, false, NULL,
"newKernel",
+ NULL, NULL, 0, original_boot_conf) < 0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, false, NULL, NULL,
"newInitrd",
+ NULL, 0, original_boot_conf) < 0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, true,
"notAvailableBootDevice",
+ "newInitrd", NULL, NULL, 0,
original_boot_conf) < 0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, false, NULL, NULL, NULL,
"newCmdline",
+ 0, original_boot_conf) < 0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, false, NULL,
"newKernel", "newInitrd",
+ "newCmdline", 0, original_boot_conf)
< 0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, false, NULL, "",
"", "", 0,
+ original_boot_conf) < 0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, false, "vda", NULL,
NULL, NULL,
+ 0, original_boot_conf) < 0)
+ goto cleanup;
+ if (testDomainCreateWithParamsHelper(dom, &counter, false, "vda", NULL,
"blaa", "bla",
+ 0, original_boot_conf) < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ bootConfigurationFree(original_boot_conf);
+ virConnectDomainEventDeregisterAny(test->conn, id);
+ virDomainFree(dom);
+
+ return ret;
+}
+
+
static int
testNetworkCreateXML(const void *data)
{
@@ -864,6 +1183,8 @@ mymain(void)
ret = EXIT_FAILURE;
if (virTestRun("Domain start stop events", testDomainStartStopEvent,
&test) < 0)
ret = EXIT_FAILURE;
+ if (virTestRun("Domain start stop events with params",
testDomainCreateWithParams, &test) < 0)
+ ret = EXIT_FAILURE;
/* Network event tests */
/* Tests requiring the test network not to be set up*/
--
2.13.4