Currently "virsh setmem" is not allowed to use against inactive domains.
By applying this patch, we can change the memory size of inactive domains
by "virsh setmem".
Signed-off-by: Taku Izumi <izumi.taku(a)jp.fujitsu.com>
---
tools/virsh.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 62 insertions(+), 8 deletions(-)
Index: libvirt-git/tools/virsh.c
===================================================================
--- libvirt-git.orig/tools/virsh.c
+++ libvirt-git/tools/virsh.c
@@ -2919,39 +2919,93 @@ cmdSetmem(vshControl *ctl, const vshCmd
virDomainPtr dom;
virDomainInfo info;
unsigned long kilobytes;
- int ret = TRUE;
+ int ret = FALSE;
+
+ char *xmlStr;
+ virBuffer memBuf = VIR_BUFFER_INITIALIZER;
+ xmlDocPtr xmlDocObj = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ xmlXPathObjectPtr result = NULL;
+ xmlChar *newXml = NULL;
+ int newXmlSize;
if (!vshConnectionUsability(ctl, ctl->conn))
- return FALSE;
+ return ret;
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
- return FALSE;
+ return ret;
kilobytes = vshCommandOptUL(cmd, "kilobytes", NULL);
if (kilobytes <= 0) {
virDomainFree(dom);
vshError(ctl, _("Invalid value of %lu for memory size"), kilobytes);
- return FALSE;
+ return ret;
}
if (virDomainGetInfo(dom, &info) != 0) {
virDomainFree(dom);
vshError(ctl, "%s", _("Unable to verify MaxMemorySize"));
- return FALSE;
+ return ret;
}
if (kilobytes > info.maxMem) {
virDomainFree(dom);
vshError(ctl, _("Requested memory size %lu kb is larger than maximum of %lu
kb"),
kilobytes, info.maxMem);
- return FALSE;
+ return ret;
}
- if (virDomainSetMemory(dom, kilobytes) != 0) {
- ret = FALSE;
+ if (virDomainIsActive(dom) == 1) {
+ if (virDomainSetMemory(dom, kilobytes) == 0)
+ ret = TRUE;
+ virDomainFree(dom);
+ return ret;
}
+ /* domain is inactive */
+
+ xmlStr = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_SECURE |
+ VIR_DOMAIN_XML_INACTIVE);
+ if (!xmlStr)
+ goto cleanup;
+
+ xmlDocObj = xmlReadDoc((const xmlChar *)xmlStr, "domain.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ if (!xmlDocObj)
+ goto cleanup;
+
+ ctxt = xmlXPathNewContext(xmlDocObj);
+ if (!ctxt)
+ goto cleanup;
+
+ result = xmlXPathEvalExpression((xmlChar *)"/domain/currentMemory", ctxt);
+ if (xmlXPathNodeSetIsEmpty(result->nodesetval) ||
+ result->nodesetval->nodeNr != 1 ||
+ result->nodesetval->nodeTab[0]->type != XML_ELEMENT_NODE) {
+ goto cleanup;
+ }
+
+ virBufferVSprintf(&memBuf, "%lu", kilobytes);
+ xmlNodeSetContent(result->nodesetval->nodeTab[0],
+ (const xmlChar *)virBufferContentAndReset(&memBuf));
+ xmlDocDumpMemory(xmlDocObj, &newXml, &newXmlSize);
+ if (!newXml)
+ goto cleanup;
+
virDomainFree(dom);
+ dom = virDomainDefineXML(ctl->conn, (char *)newXml);
+ if (dom)
+ ret = TRUE;
+
+cleanup:
+ xmlFree(newXml);
+ xmlXPathFreeContext(ctxt);
+ xmlFreeDoc(xmlDocObj);
+ VIR_FREE(xmlStr);
+ if (dom)
+ virDomainFree(dom);
+
return ret;
}