When passing in custom driver XML, allow a block like
<domain>
...
<testdriver>
<runstate>3</runstate>
</testdriver>
</domain>
This is only read at initial driver start time, and sets the initial
run state of the object. This is handy for UI testing.
Wire it up for domains, networks, pools, and interfaces. The latter
3 only have a notion of active and inactive, which map to runstate
1 and 0 respectively.
We also take care to unlink this <testdriver> block before passing the
XML to the object parse function. Right now nothing complains, but if
XML parsing became stricter in the future we don't want it to choke
on this custom element.
---
src/test/test_driver.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 116 insertions(+), 7 deletions(-)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index d7b2e40..4be20b1 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -813,6 +813,80 @@ error:
return -1;
}
+/*
+ * Parse object runstate from passed in XML, ex:
+ * <domain>
+ * ...
+ * <testdriver>
+ * <runstate>%d</runstate>
+ * </testdriver>
+ * </domain>
+ */
+static int
+testParseXMLObjectRunstate(xmlXPathContextPtr ctxt,
+ xmlNodePtr node,
+ unsigned int limit,
+ unsigned int def,
+ unsigned int *val)
+{
+ int tmp, ret = -1;
+ unsigned int tmpval;
+ char *xpath = NULL;
+
+ if (virAsprintf(&xpath, "string(%s/testdriver/runstate)",
+ xmlGetNodePath(node)) < 0)
+ goto error;
+
+ tmp = virXPathUInt(xpath, ctxt, &tmpval);
+ if (tmp == 0) {
+ if (tmpval >= limit) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("runstate '%d' out of range'"),
tmpval);
+ goto error;
+ }
+ *val = tmpval;
+ } else if (tmp == -1) {
+ *val = def;
+ } else if (tmp == -2) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("invalid runstate"));
+ goto error;
+ }
+
+ ret = 0;
+error:
+ VIR_FREE(xpath);
+ return ret;
+}
+
+/*
+ * Unlink custom <testdriver> XML before handing the node off
+ * to the object parsing handler, since it may complain about unrecognized
+ * elements (if not now, then in the future)
+ */
+static int
+testNodeUnlinkCustomXML(xmlXPathContextPtr ctxt, xmlNodePtr node)
+{
+ int ret = -1;
+ char *xpath = NULL;
+ xmlNodePtr testnode;
+
+ if (virAsprintf(&xpath, "%s/testdriver",
+ xmlGetNodePath(node)) < 0)
+ goto error;
+
+ testnode = virXPathNode(xpath, ctxt);
+ if (testnode) {
+ xmlUnlinkNode(testnode);
+ xmlFreeNode(testnode);
+ }
+
+ ret = 0;
+error:
+ VIR_FREE(xpath);
+ return ret;
+}
+
static int
testParseDomains(testConnPtr privconn,
const char *file,
@@ -829,11 +903,20 @@ testParseDomains(testConnPtr privconn,
}
for (i = 0; i < num; i++) {
+ unsigned int runstate;
virDomainDefPtr def;
xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "domain");
if (!node)
goto error;
+ if (testParseXMLObjectRunstate(ctxt, node,
+ VIR_DOMAIN_LAST, VIR_DOMAIN_RUNNING,
+ &runstate) < 0)
+ goto error;
+
+ if (testNodeUnlinkCustomXML(ctxt, node) < 0)
+ goto error;
+
def = virDomainDefParseNode(ctxt->doc, node,
privconn->caps, privconn->xmlopt,
1 << VIR_DOMAIN_VIRT_TEST,
@@ -851,11 +934,16 @@ testParseDomains(testConnPtr privconn,
}
obj->persistent = 1;
- if (testDomainStartState(privconn, obj,
- VIR_DOMAIN_RUNNING_BOOTED) < 0) {
- virObjectUnlock(obj);
- goto error;
+ if (runstate != VIR_DOMAIN_SHUTOFF) {
+ if (testDomainStartState(privconn, obj,
+ VIR_DOMAIN_RUNNING_BOOTED) < 0) {
+ virObjectUnlock(obj);
+ goto error;
+ }
+ } else {
+ testDomainShutdownState(NULL, obj, 0);
}
+ virDomainObjSetState(obj, runstate, 0);
virObjectUnlock(obj);
}
@@ -882,11 +970,18 @@ testParseNetworks(testConnPtr privconn,
}
for (i = 0; i < num; i++) {
+ unsigned int runstate;
virNetworkDefPtr def;
xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file, "network");
if (!node)
goto error;
+ if (testParseXMLObjectRunstate(ctxt, node, 1, 1, &runstate) < 0)
+ goto error;
+
+ if (testNodeUnlinkCustomXML(ctxt, node) < 0)
+ goto error;
+
def = virNetworkDefParseNode(ctxt->doc, node);
if (!def)
goto error;
@@ -897,7 +992,7 @@ testParseNetworks(testConnPtr privconn,
}
obj->persistent = 1;
- obj->active = 1;
+ obj->active = runstate;
virNetworkObjUnlock(obj);
}
@@ -923,12 +1018,19 @@ testParseInterfaces(testConnPtr privconn,
}
for (i = 0; i < num; i++) {
+ unsigned int runstate;
virInterfaceDefPtr def;
xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
"interface");
if (!node)
goto error;
+ if (testParseXMLObjectRunstate(ctxt, node, 1, 1, &runstate) < 0)
+ goto error;
+
+ if (testNodeUnlinkCustomXML(ctxt, node) < 0)
+ goto error;
+
def = virInterfaceDefParseNode(ctxt->doc, node);
if (!def)
goto error;
@@ -938,7 +1040,7 @@ testParseInterfaces(testConnPtr privconn,
goto error;
}
- obj->active = 1;
+ obj->active = runstate;
virInterfaceObjUnlock(obj);
}
@@ -1025,12 +1127,19 @@ testParseStorage(testConnPtr privconn,
}
for (i = 0; i < num; i++) {
+ unsigned int runstate;
virStoragePoolDefPtr def;
xmlNodePtr node = testParseXMLDocFromFile(nodes[i], file,
"pool");
if (!node)
goto error;
+ if (testParseXMLObjectRunstate(ctxt, node, 1, 1, &runstate) < 0)
+ goto error;
+
+ if (testNodeUnlinkCustomXML(ctxt, node) < 0)
+ goto error;
+
def = virStoragePoolDefParseNode(ctxt->doc, node);
if (!def)
goto error;
@@ -1045,7 +1154,7 @@ testParseStorage(testConnPtr privconn,
virStoragePoolObjUnlock(obj);
goto error;
}
- obj->active = 1;
+ obj->active = runstate;
/* Find storage volumes */
if (testOpenVolumesForPool(file, ctxt, obj, i+1) < 0) {
--
1.8.3.1