From: Rohit Kumar Date: Wed, 4 May 2022 16:51:12 +0000 (-0700) Subject: conf: Add support to parse/format for NVRAM X-Git-Tag: v8.5.0-rc1~75 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=468a0a6027120a5d923f84e8675c75df980d84ac;p=thirdparty%2Flibvirt.git conf: Add support to parse/format for NVRAM This patch introduces the logic to format and parse remote NVRAM. Update NVRAM element schema, and docs for supporting network backed NVRAM. NVRAM backed over network would give the flexibility to start the VM on any host without having to worry about where to get the latest nvram image. or In the qemu driver we will support the new definition only with qemu's supporting -blockdev. Signed-off-by: Prerna Saxena Signed-off-by: Florian Schmidt Signed-off-by: Rohit Kumar Signed-off-by: Peter Krempa Reviewed-by: Ján Tomko Tested-by: Rohit Kumar --- diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index 7da625380c..b6a3495093 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -135,6 +135,35 @@ harddisk, cdrom, network) determining where to obtain/find the boot image. ... + + ... + + hvm + /usr/share/OVMF/OVMF_CODE.fd + + + + + + ... + + + ... + + hvm + /usr/share/OVMF/OVMF_CODE.fd + + + + + + + + + + + ... + ... @@ -224,6 +253,15 @@ harddisk, cdrom, network) determining where to obtain/find the boot image. if the NVRAM file has been created by libvirt it is left behind and it is management application's responsibility to save and remove file (if needed to be persistent). :since:`Since 1.2.8` + + :since:`Since 8.5.0`, it's possible for the element to have ``type`` attribute + (accepts values ``file``, ``block`` and ``network``) in that case the NVRAM + storage is described by a ```` sub-element with the same syntax as + ``disk``'s source. See `Hard drives, floppy disks, CDROMs`_. + + **Note:** ``network`` backed NVRAM the variables are not instantiated from + the ``template`` and it's user's responsibility to provide a valid NVRAM image. + ``boot`` The ``dev`` attribute takes one of the values "fd", "hd", "cdrom" or "network" and is used to specify the next boot device to consider. The diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 21e383c148..d3aa827acc 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -18013,6 +18013,51 @@ virDomainLoaderDefParseXML(xmlNodePtr node, } +static int +virDomainNvramDefParseXML(virDomainLoaderDef *loader, + xmlXPathContextPtr ctxt, + virDomainXMLOption *xmlopt, + unsigned int flags) +{ + g_autofree char *nvramType = virXPathString("string(./os/nvram/@type)", ctxt); + g_autoptr(virStorageSource) src = virStorageSourceNew(); + + src->type = VIR_STORAGE_TYPE_FILE; + src->format = VIR_STORAGE_FILE_RAW; + + if (!nvramType) { + char *nvramPath = NULL; + + if (!(nvramPath = virXPathString("string(./os/nvram[1])", ctxt))) + return 0; /* no nvram */ + + src->path = nvramPath; + } else { + xmlNodePtr sourceNode; + + if ((src->type = virStorageTypeFromString(nvramType)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown disk type '%s'"), nvramType); + return -1; + } + + if (!(sourceNode = virXPathNode("./os/nvram/source[1]", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing source element for nvram")); + return -1; + } + + if (virDomainStorageSourceParse(sourceNode, ctxt, src, flags, xmlopt) < 0) + return -1; + + loader->newStyleNVRAM = true; + } + + loader->nvram = g_steal_pointer(&src); + return 0; +} + + static int virDomainSchedulerParseCommonAttrs(xmlNodePtr node, virProcessSchedPolicy *policy, @@ -18398,11 +18443,12 @@ 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; - g_autofree char *nvramPath = NULL; if (!loader_node) return 0; @@ -18414,12 +18460,8 @@ virDomainDefParseBootLoaderOptions(virDomainDef *def, fwAutoSelect) < 0) return -1; - if ((nvramPath = virXPathString("string(./os/nvram[1])", ctxt))) { - def->os.loader->nvram = virStorageSourceNew(); - def->os.loader->nvram->path = g_steal_pointer(&nvramPath); - def->os.loader->nvram->type = VIR_STORAGE_TYPE_FILE; - def->os.loader->nvram->format = VIR_STORAGE_FILE_RAW; - } + if (virDomainNvramDefParseXML(def->os.loader, ctxt, xmlopt, flags) < 0) + return -1; if (!fwAutoSelect) def->os.loader->nvramTemplate = virXPathString("string(./os/nvram[1]/@template)", ctxt); @@ -18474,7 +18516,9 @@ virDomainDefParseBootAcpiOptions(virDomainDef *def, static int virDomainDefParseBootOptions(virDomainDef *def, - xmlXPathContextPtr ctxt) + xmlXPathContextPtr ctxt, + virDomainXMLOption *xmlopt, + unsigned int flags) { /* * Booting options for different OS types.... @@ -18492,7 +18536,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) @@ -18508,7 +18552,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; @@ -19808,7 +19852,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 */ @@ -27161,26 +27205,48 @@ virDomainHugepagesFormat(virBuffer *buf, } -static void +static int virDomainLoaderDefFormatNvram(virBuffer *buf, - virDomainLoaderDef *loader) + virDomainLoaderDef *loader, + virDomainXMLOption *xmlopt, + unsigned int flags) { g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER; - g_auto(virBuffer) childBuf = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) childBufDirect = VIR_BUFFER_INITIALIZER; + g_auto(virBuffer) childBufChild = VIR_BUFFER_INIT_CHILD(buf); + virBuffer *childBuf = &childBufDirect; + bool childNewline = false; virBufferEscapeString(&attrBuf, " template='%s'", loader->nvramTemplate); + if (loader->nvram) { - if (loader->nvram->type == VIR_STORAGE_TYPE_FILE) - virBufferEscapeString(&childBuf, "%s", loader->nvram->path); + virStorageSource *src = loader->nvram; + + if (!loader->newStyleNVRAM) { + virBufferEscapeString(&childBufDirect, "%s", src->path); + } else { + childNewline = true; + childBuf = &childBufChild; + + virBufferAsprintf(&attrBuf, " type='%s'", virStorageTypeToString(src->type)); + + if (virDomainDiskSourceFormat(&childBufChild, src, "source", 0, + false, flags, false, false, xmlopt) < 0) + return -1; + } } - virXMLFormatElementInternal(buf, "nvram", &attrBuf, &childBuf, false, false); + virXMLFormatElementInternal(buf, "nvram", &attrBuf, childBuf, false, childNewline); + + return 0; } -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; @@ -27201,7 +27267,10 @@ virDomainLoaderDefFormat(virBuffer *buf, virXMLFormatElementInternal(buf, "loader", &loaderAttrBuf, &loaderChildBuf, false, false); - virDomainLoaderDefFormatNvram(buf, loader); + if (virDomainLoaderDefFormatNvram(buf, loader, xmlopt, flags) < 0) + return -1; + + return 0; } static void @@ -28454,8 +28523,9 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, if (def->os.initgroup) virBufferAsprintf(buf, "%s\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, "%s\n", def->os.kernel); virBufferEscapeString(buf, "%s\n", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 1b0ec83857..292fd62beb 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2254,6 +2254,7 @@ struct _virDomainLoaderDef { virDomainLoader type; virTristateBool secure; virStorageSource *nvram; + bool newStyleNVRAM; char *nvramTemplate; /* user override of path to master nvram */ }; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index efd49cfa01..3ba4da46a4 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -333,7 +333,14 @@ - + + + + + + + + diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index cf3968413c..f8aa83c1cb 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -609,6 +609,13 @@ qemuValidateDomainDefNvram(const virDomainDef *def, if (!src) return 0; + if (def->os.loader->newStyleNVRAM && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_BLOCKDEV)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("modern nvram specification is not supported by this qemu")); + return -1; + } + switch (src->type) { case VIR_STORAGE_TYPE_FILE: case VIR_STORAGE_TYPE_BLOCK: