This patch introduces the logic to support remote NVRAM and adds 'type' attribute to nvram element. Sample XML with new annotation: <nvram type='network'> <source protocol='iscsi' name='iqn.2013-07.com.example:iscsi-nopool/0'> <host name='example.com' port='6000'/> </source> </nvram> or <nvram type='file'> <source file='/var/lib/libvirt/nvram/guest_VARS.fd'/> </nvram> Signed-off-by: Prerna Saxena <prerna.saxena@xxxxxxxxxxx> Signed-off-by: Florian Schmidt <flosch@xxxxxxxxxxx> Signed-off-by: Rohit Kumar <rohit.kumar3@xxxxxxxxxxx> --- src/conf/domain_conf.c | 81 +++++++++++++++++++++++++++++++++------- src/qemu/qemu_firmware.c | 6 +++ 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b83c2f0e6a..bc8c7e0d6f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -17866,6 +17866,42 @@ virDomainLoaderDefParseXML(xmlNodePtr node, } +static int +virDomainNvramDefParseXML(virStorageSource *nvram, + xmlXPathContextPtr ctxt, + virDomainXMLOption *opt, + unsigned int flags) +{ + g_autofree char *nvramType = NULL; + xmlNodePtr source; + + nvramType = virXPathString("string(./os/nvram/@type)", ctxt); + + /* if nvramType==NULL read old-style, else + * if there's a type, read new style */ + if (!nvramType) { + nvram->type = VIR_STORAGE_TYPE_FILE; + nvram->path = virXPathString("string(./os/nvram[1])", ctxt); + return 0; + } else { + if ((nvram->type = virStorageTypeFromString(nvramType)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown disk type '%s'"), nvramType); + return -1; + } + source = virXPathNode("./os/nvram/source[1]", ctxt); + if (!source) { + virReportError(VIR_ERR_XML_ERROR, + _("Missing source element with nvram type '%s'"), + nvramType); + return -1; + } + return virDomainStorageSourceParse(source, ctxt, nvram, flags, opt); + } + return 0; +} + + static int virDomainSchedulerParseCommonAttrs(xmlNodePtr node, virProcessSchedPolicy *policy, @@ -18251,7 +18287,9 @@ virDomainDefParseBootFirmwareOptions(virDomainDef *def, static int virDomainDefParseBootLoaderOptions(virDomainDef *def, - xmlXPathContextPtr ctxt) + xmlXPathContextPtr ctxt, + virDomainXMLOption *xmlopt, + unsigned int flags) { xmlNodePtr loader_node = virXPathNode("./os/loader[1]", ctxt); const bool fwAutoSelect = def->os.firmware != VIR_DOMAIN_OS_DEF_FIRMWARE_NONE; @@ -18268,8 +18306,10 @@ virDomainDefParseBootLoaderOptions(virDomainDef *def, if (virXPathNode("./os/nvram[1]", ctxt)) { def->os.loader->nvram = g_new0(virStorageSource, 1); - def->os.loader->nvram->path = virXPathString("string(./os/nvram[1])", ctxt); - def->os.loader->nvram->type = VIR_STORAGE_TYPE_FILE; + + if (virDomainNvramDefParseXML(def->os.loader->nvram, + ctxt, xmlopt, flags) < 0) + return -1; } if (!fwAutoSelect) def->os.loader->nvramTemplate = virXPathString("string(./os/nvram[1]/@template)", ctxt); @@ -18324,7 +18364,9 @@ virDomainDefParseBootAcpiOptions(virDomainDef *def, static int virDomainDefParseBootOptions(virDomainDef *def, - xmlXPathContextPtr ctxt) + xmlXPathContextPtr ctxt, + virDomainXMLOption *xmlopt, + unsigned int flags) { /* * Booting options for different OS types.... @@ -18342,7 +18384,7 @@ virDomainDefParseBootOptions(virDomainDef *def, if (virDomainDefParseBootFirmwareOptions(def, ctxt) < 0) return -1; - if (virDomainDefParseBootLoaderOptions(def, ctxt) < 0) + if (virDomainDefParseBootLoaderOptions(def, ctxt, xmlopt, flags) < 0) return -1; if (virDomainDefParseBootAcpiOptions(def, ctxt) < 0) @@ -18358,7 +18400,7 @@ virDomainDefParseBootOptions(virDomainDef *def, case VIR_DOMAIN_OSTYPE_UML: virDomainDefParseBootKernelOptions(def, ctxt); - if (virDomainDefParseBootLoaderOptions(def, ctxt) < 0) + if (virDomainDefParseBootLoaderOptions(def, ctxt, xmlopt, flags) < 0) return -1; break; @@ -19649,7 +19691,7 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, if (virDomainDefClockParse(def, ctxt) < 0) return NULL; - if (virDomainDefParseBootOptions(def, ctxt) < 0) + if (virDomainDefParseBootOptions(def, ctxt, xmlopt, flags) < 0) return NULL; /* analysis of the disk devices */ @@ -26949,9 +26991,11 @@ virDomainHugepagesFormat(virBuffer *buf, virBufferAddLit(buf, "</hugepages>\n"); } -static void +static int virDomainLoaderDefFormat(virBuffer *buf, - virDomainLoaderDef *loader) + virDomainLoaderDef *loader, + virDomainXMLOption *xmlopt, + unsigned int flags) { g_auto(virBuffer) loaderAttrBuf = VIR_BUFFER_INITIALIZER; g_auto(virBuffer) loaderChildBuf = VIR_BUFFER_INITIALIZER; @@ -26976,10 +27020,20 @@ virDomainLoaderDefFormat(virBuffer *buf, virBufferEscapeString(&nvramAttrBuf, " template='%s'", loader->nvramTemplate); if (loader->nvram) { - if (loader->nvram->type == VIR_STORAGE_TYPE_FILE) + if (loader->nvram->type == VIR_STORAGE_TYPE_FILE) { virBufferEscapeString(&nvramChildBuf, "%s", loader->nvram->path); + virXMLFormatElementInternal(buf, "nvram", &nvramAttrBuf, &nvramChildBuf, false, false); + } else { + virBufferEscapeString(&nvramAttrBuf, " type='%s'", virStorageTypeToString(loader->nvram->type)); + if (virDomainDiskSourceFormat(&nvramChildBuf, loader->nvram, "source", 0, + 0, false, flags, true, xmlopt) < 0) { + return -1; + } + virXMLFormatElementInternal(buf, "nvram", &nvramAttrBuf, &nvramChildBuf, false, true); + } } - virXMLFormatElementInternal(buf, "nvram", &nvramAttrBuf, &nvramChildBuf, false, false); + + return 0; } static void @@ -28180,8 +28234,9 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, if (def->os.initgroup) virBufferAsprintf(buf, "<initgroup>%s</initgroup>\n", def->os.initgroup); - if (def->os.loader) - virDomainLoaderDefFormat(buf, def->os.loader); + if (def->os.loader && + virDomainLoaderDefFormat(buf, def->os.loader, xmlopt, flags) < 0) + return -1; virBufferEscapeString(buf, "<kernel>%s</kernel>\n", def->os.kernel); virBufferEscapeString(buf, "<initrd>%s</initrd>\n", diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c index 6556a613a8..22ad7d42a1 100644 --- a/src/qemu/qemu_firmware.c +++ b/src/qemu/qemu_firmware.c @@ -1375,6 +1375,12 @@ qemuFirmwareFillDomain(virQEMUDriver *driver, && virFileExists(def->os.loader->nvram->path)) return 0; + + if (!reset_nvram && def->os.loader->nvram && + def->os.loader->nvram->type == VIR_STORAGE_TYPE_NETWORK && + def->os.loader->nvram->path) + return 0; + /* ... then we want to consult JSON FW descriptors first, * but we don't want to fail if we haven't found a match. */ needResult = false; -- 2.25.1