Augment definition to include virStorageSourcePtr that more comprehensively describes the nature of backing element. Also include flags for annotating if input XML definition is old-style or new-style. 2) Parse domain XML to generate virDomainLoaderDef & virDomainNvramDef. This patch is used to interpret domain XML and store the Loader & Nvram's backing definitions as virStorageSource. It also identifies if input XML used old or new-style declaration. (This will later be used by the formatter). 3) Format the loader source appropriately. If the initial XML used the old-style declaration as follows: <loader type='pflash'>/path/to/file</loader> we format it as was read. However, if it used new-style declaration: <loader type='pflash' backing='file'> <source file='path/to/file'/> </loader> The formatter identifies that this is a new-style format and renders it likewise. 4) Plumb the loader source into generation of QEMU command line. Given that nvram & loader elements can now be backed by a non-local source too, adjust all steps leading to generation of QEMU command line. 5) Fix the domain def inference logic to correctly account for network-backed pflash devices. 6) Bhyve: Fix command line generation to correctly pick up local loader path. 7) virt-aa-helper: Adjust references to loader & nvram elements to correctly parse the virStorageSource types. 8) Vbox: Adjust references to 'loader' and 'nvram' elements given that these are now represented by virStorageSourcePtr. 9)Xen: Adjust all references to loader & nvram elements given that they are now backed by virStorageSourcePtr --- src/bhyve/bhyve_command.c | 6 +- src/conf/domain_conf.c | 250 +++++++++++++++++++++++++++++++++++++--- src/conf/domain_conf.h | 11 +- src/qemu/qemu_cgroup.c | 13 ++- src/qemu/qemu_command.c | 21 +++- src/qemu/qemu_domain.c | 31 +++-- src/qemu/qemu_driver.c | 7 +- src/qemu/qemu_parse_command.c | 30 ++++- src/qemu/qemu_process.c | 54 ++++++--- src/security/security_dac.c | 6 +- src/security/security_selinux.c | 6 +- src/security/virt-aa-helper.c | 14 ++- src/vbox/vbox_common.c | 11 +- src/xenapi/xenapi_driver.c | 4 +- src/xenconfig/xen_sxpr.c | 19 +-- src/xenconfig/xen_xm.c | 9 +- 16 files changed, 409 insertions(+), 83 deletions(-) diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c index e3f7ded..9e53f40 100644 --- a/src/bhyve/bhyve_command.c +++ b/src/bhyve/bhyve_command.c @@ -521,10 +521,12 @@ virBhyveProcessBuildBhyveCmd(virConnectPtr conn, virCommandAddArgList(cmd, "-s", "0:0,hostbridge", NULL); if (def->os.bootloader == NULL && - def->os.loader) { + def->os.loader && + def->os.loader->src && + def->os.loader->src->type == VIR_STORAGE_TYPE_FILE) { if ((bhyveDriverGetCaps(conn) & BHYVE_CAP_LPC_BOOTROM)) { virCommandAddArg(cmd, "-l"); - virCommandAddArgFormat(cmd, "bootrom,%s", def->os.loader->path); + virCommandAddArgFormat(cmd, "bootrom,%s", def->os.loader->src->path); add_lpc = true; } else { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3689ac0..df2ed3a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2884,8 +2884,8 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr loader) if (!loader) return; - VIR_FREE(loader->path); - VIR_FREE(loader->nvram); + virStorageSourceFree(loader->src); + virStorageSourceFree(loader->nvram); VIR_FREE(loader->templt); VIR_FREE(loader); } @@ -18087,30 +18087,81 @@ virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDefPtr def) static int virDomainLoaderDefParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt, virDomainLoaderDefPtr loader) { int ret = -1; char *readonly_str = NULL; char *secure_str = NULL; char *type_str = NULL; + char *tmp = NULL; + char *lpath = NULL; + xmlNodePtr cur; + xmlXPathContextPtr cur_ctxt = ctxt; + + if (VIR_ALLOC(loader->src) < 0) + goto error; + + loader->src->type = VIR_STORAGE_TYPE_LAST; + loader->oldStyleLoader = false; readonly_str = virXMLPropString(node, "readonly"); secure_str = virXMLPropString(node, "secure"); type_str = virXMLPropString(node, "type"); - loader->path = (char *) xmlNodeGetContent(node); + + if ((tmp = virXMLPropString(node, "backing")) && + (loader->src->type = virStorageTypeFromString(tmp)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown loader type '%s'"), tmp); + VIR_FREE(tmp); + goto error; + } + VIR_FREE(tmp); + + for (cur = node->children; cur != NULL; cur = cur->next) { + if (cur->type != XML_ELEMENT_NODE) + continue; + + if (virXMLNodeNameEqual(cur, "source")) { + /* new-style declaration found */ + if (virDomainStorageSourceParse(cur, cur_ctxt, loader->src, 0) < 0) { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("Error parsing Loader source element")); + goto error; + } + break; + } + } + + /* Old-style absolute path found ? */ + if (loader->src->type == VIR_STORAGE_TYPE_LAST) { + lpath = (char *) xmlNodeGetContent(node); + if (virStringIsEmpty(lpath)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing loader source")); + VIR_FREE(lpath); + goto error; + } + + loader->src->type = VIR_STORAGE_TYPE_FILE; + if (VIR_STRDUP(loader->src->path, lpath) < 0) + goto error; + VIR_FREE(lpath); + loader->oldStyleLoader = true; + } if (readonly_str && (loader->readonly = virTristateBoolTypeFromString(readonly_str)) <= 0) { virReportError(VIR_ERR_XML_DETAIL, _("unknown readonly value: %s"), readonly_str); - goto cleanup; + goto error; } if (secure_str && (loader->secure = virTristateBoolTypeFromString(secure_str)) <= 0) { virReportError(VIR_ERR_XML_DETAIL, _("unknown secure value: %s"), secure_str); - goto cleanup; + goto error; } if (type_str) { @@ -18118,19 +18169,97 @@ virDomainLoaderDefParseXML(xmlNodePtr node, if ((type = virDomainLoaderTypeFromString(type_str)) < 0) { virReportError(VIR_ERR_XML_DETAIL, _("unknown type value: %s"), type_str); - goto cleanup; + goto error; } loader->type = type; } ret = 0; - cleanup: + + exit: VIR_FREE(readonly_str); VIR_FREE(secure_str); VIR_FREE(type_str); + return ret; + error: + virStorageSourceFree(loader->src); + VIR_FREE(lpath); + loader->src = NULL; + goto exit; } +static int +virDomainLoaderNvramDefParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt, + virDomainLoaderDefPtr loader) +{ + int ret = -1; + char *tmp = NULL; + char *npath = NULL; + xmlNodePtr cur; + + if (VIR_ALLOC(loader->nvram) < 0) + goto error; + + loader->nvram->type = VIR_STORAGE_TYPE_LAST; + loader->oldStyleNvram = false; + + if ((tmp = virXMLPropString(node, "backing")) && + (loader->nvram->type = virStorageTypeFromString(tmp)) <= 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown nvram type '%s'"), tmp); + VIR_FREE(tmp); + goto error; + } + VIR_FREE(tmp); + + loader->templt = virXMLPropString(node, "template"); + + for (cur = node->children; cur != NULL; cur = cur->next) { + if (cur->type != XML_ELEMENT_NODE) + continue; + + if (virXMLNodeNameEqual(cur, "source")) { + if (virDomainStorageSourceParse(cur, ctxt, loader->nvram, 0) < 0) { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("Error parsing nvram source element")); + goto error; + } + ret = 0; + break; + } + } + + /* Old-style declaration found */ + if (loader->nvram->type == VIR_STORAGE_TYPE_LAST) { + npath = (char *) xmlNodeGetContent(node); + + /* Suppress failures from lack of NVRAM, + * it will eventually be generated from template*/ + if (virStringIsEmpty(npath)) { + virStorageSourceFree(loader->nvram); + loader->nvram = NULL; + VIR_FREE(npath); + return 0; + } + + if (VIR_STRDUP(loader->nvram->path, npath) < 0) + goto error; + VIR_FREE(npath); + loader->nvram->type = VIR_STORAGE_TYPE_FILE; + loader->oldStyleNvram = true; + ret = 0; + } + return ret; + + error: + virStorageSourceFree(loader->nvram); + loader->nvram = NULL; + VIR_FREE(npath); + VIR_FREE(loader->templt); + return ret; +} static virBitmapPtr virDomainSchedulerParse(xmlNodePtr node, @@ -18523,11 +18652,13 @@ virDomainDefParseBootOptions(virDomainDefPtr def, if (VIR_ALLOC(def->os.loader) < 0) goto error; - if (virDomainLoaderDefParseXML(loader_node, def->os.loader) < 0) + if (virDomainLoaderDefParseXML(loader_node, ctxt, def->os.loader) < 0) goto error; - def->os.loader->nvram = virXPathString("string(./os/nvram[1])", ctxt); - def->os.loader->templt = virXPathString("string(./os/nvram[1]/@template)", ctxt); + if ((loader_node = virXPathNode("./os/nvram[1]", ctxt)) && + (virDomainLoaderNvramDefParseXML(loader_node, ctxt, + def->os.loader) < 0)) + goto error; } } @@ -26217,11 +26348,19 @@ virDomainHugepagesFormat(virBufferPtr buf, static void virDomainLoaderDefFormat(virBufferPtr buf, - virDomainLoaderDefPtr loader) + virDomainLoaderDefPtr loader, + unsigned int flags) { const char *readonly = virTristateBoolTypeToString(loader->readonly); const char *secure = virTristateBoolTypeToString(loader->secure); const char *type = virDomainLoaderTypeToString(loader->type); + const char *backing = NULL; + + virBuffer attrBuf = VIR_BUFFER_INITIALIZER; + virBuffer childBuf = VIR_BUFFER_INITIALIZER; + + virBufferSetChildIndent(&childBuf, buf); + virBufferAddLit(buf, "<loader"); @@ -26231,17 +26370,90 @@ virDomainLoaderDefFormat(virBufferPtr buf, if (loader->secure) virBufferAsprintf(buf, " secure='%s'", secure); - virBufferAsprintf(buf, " type='%s'>", type); + virBufferAsprintf(buf, " type='%s'", type); + if (loader->src && + loader->src->type < VIR_STORAGE_TYPE_LAST) { + if (!loader->oldStyleLoader) { + /* Format this in the new style, using the + * <source> sub-element */ + + if (virDomainStorageSourceFormat(&attrBuf, &childBuf, loader->src, + flags, 0) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot format loader source")); + goto error; + } + + backing = virStorageTypeToString(loader->src->type); + virBufferAsprintf(buf, " backing='%s'>", backing); + virBufferAdjustIndent(buf, 2); + + if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot format loader source")); + goto error; + } + + virBufferAdjustIndent(buf, -2); + + } else { + /* Format this in the old-style, using absolute paths directly. */ + virBufferAsprintf(buf, ">%s", loader->src->path); + } + } else { + virBufferAddLit(buf, ">\n"); + } + + virBufferAddLit(buf, "</loader>\n"); - virBufferEscapeString(buf, "%s</loader>\n", loader->path); if (loader->nvram || loader->templt) { + ignore_value(virBufferContentAndReset(&attrBuf)); + ignore_value(virBufferContentAndReset(&childBuf)); + virBufferSetChildIndent(&childBuf, buf); + virBufferAddLit(buf, "<nvram"); - virBufferEscapeString(buf, " template='%s'", loader->templt); - if (loader->nvram) - virBufferEscapeString(buf, ">%s</nvram>\n", loader->nvram); - else - virBufferAddLit(buf, "/>\n"); + + if (loader->templt) + virBufferEscapeString(buf, " template='%s'", loader->templt); + + if (loader->nvram) { + backing = virStorageTypeToString(loader->nvram->type); + if (!loader->oldStyleNvram) { + + if (virDomainStorageSourceFormat(&attrBuf, &childBuf, + loader->nvram, flags, 0) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot format NVRAM source")); + virBufferAddLit(buf, "></nvram>"); + goto error; + } + + virBufferEscapeString(buf, " backing='%s'>\n", backing); + virBufferAdjustIndent(buf, 2); + + if (virXMLFormatElement(buf, "source", &attrBuf, &childBuf) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Cannot format NVRAM source")); + virBufferAddLit(buf, "</nvram>"); + goto error; + } + + virBufferAdjustIndent(buf, -2); + + } else { + /* old-style NVRAM declaration found */ + virBufferAsprintf(buf, ">%s", loader->nvram->path); + } + } else { + virBufferAddLit(buf, ">\n"); + } + + virBufferAddLit(buf, "</nvram>\n"); } + error: + virBufferFreeAndReset(&attrBuf); + virBufferFreeAndReset(&childBuf); + return; } static void @@ -26918,7 +27130,7 @@ virDomainDefFormatInternal(virDomainDefPtr def, virBufferAsprintf(buf, "<initgroup>%s</initgroup>\n", def->os.initgroup); if (def->os.loader) - virDomainLoaderDefFormat(buf, def->os.loader); + virDomainLoaderDefFormat(buf, def->os.loader, flags); virBufferEscapeString(buf, "<kernel>%s</kernel>\n", def->os.kernel); virBufferEscapeString(buf, "<initrd>%s</initrd>\n", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a78fdee..fb44a90 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1856,15 +1856,22 @@ typedef enum { VIR_ENUM_DECL(virDomainLoader) +struct _virStorageSource; +typedef struct _virStorageSource *virStorageSourcePtr; + typedef struct _virDomainLoaderDef virDomainLoaderDef; typedef virDomainLoaderDef *virDomainLoaderDefPtr; struct _virDomainLoaderDef { - char *path; + virStorageSourcePtr src; int readonly; /* enum virTristateBool */ virDomainLoader type; int secure; /* enum virTristateBool */ - char *nvram; /* path to non-volatile RAM */ + virStorageSourcePtr nvram; /* path to non-voliatile RAM */ char *templt; /* user override of path to master nvram */ + bool oldStyleLoader; /* is this an old-style XML formatting, + * ie, absolute path is directly specified? */ + bool oldStyleNvram; /* is this an old-style XML formatting, + * ie, absolute path is directly specified? */ }; void virDomainLoaderDefFree(virDomainLoaderDefPtr loader); diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index 546a4c8..5c16a48 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -607,16 +607,21 @@ qemuSetupMemoryCgroup(virDomainObjPtr vm) static int qemuSetupFirmwareCgroup(virDomainObjPtr vm) { + virStorageSourcePtr src = NULL; + if (!vm->def->os.loader) return 0; - if (vm->def->os.loader->path && - qemuSetupImagePathCgroup(vm, vm->def->os.loader->path, - vm->def->os.loader->readonly == VIR_TRISTATE_BOOL_YES) < 0) + src = vm->def->os.loader->src; + + if (src->type == VIR_STORAGE_TYPE_FILE && + qemuSetupImagePathCgroup(vm, src->path, + src->readonly == VIR_TRISTATE_BOOL_YES) < 0) return -1; if (vm->def->os.loader->nvram && - qemuSetupImagePathCgroup(vm, vm->def->os.loader->nvram, false) < 0) + vm->def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE && + qemuSetupImagePathCgroup(vm, vm->def->os.loader->nvram->path, false) < 0) return -1; return 0; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9da2d60..ba5283f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -9320,6 +9320,7 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd, virDomainLoaderDefPtr loader = def->os.loader; virBuffer buf = VIR_BUFFER_INITIALIZER; int unit = 0; + char *source = NULL; if (!loader) return; @@ -9327,7 +9328,7 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd, switch ((virDomainLoader) loader->type) { case VIR_DOMAIN_LOADER_TYPE_ROM: virCommandAddArg(cmd, "-bios"); - virCommandAddArg(cmd, loader->path); + virCommandAddArg(cmd, loader->src->path); break; case VIR_DOMAIN_LOADER_TYPE_PFLASH: @@ -9339,9 +9340,14 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd, NULL); } + if (qemuGetDriveSourceString(loader->src, NULL, &source) < 0) + break; + virBufferAddLit(&buf, "file="); - virQEMUBuildBufferEscapeComma(&buf, loader->path); - virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit); + virQEMUBuildBufferEscapeComma(&buf, source); + VIR_FREE(source); + virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", + unit); unit++; if (loader->readonly) { @@ -9354,9 +9360,14 @@ qemuBuildDomainLoaderCommandLine(virCommandPtr cmd, if (loader->nvram) { virBufferFreeAndReset(&buf); + if (qemuGetDriveSourceString(loader->nvram, NULL, &source) < 0) + break; + virBufferAddLit(&buf, "file="); - virQEMUBuildBufferEscapeComma(&buf, loader->nvram); - virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", unit); + virQEMUBuildBufferEscapeComma(&buf, source); + virBufferAsprintf(&buf, ",if=pflash,format=raw,unit=%d", + unit); + unit++; virCommandAddArg(cmd, "-drive"); virCommandAddArgBuffer(cmd, &buf); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index d3beee5..5b73a6e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -3346,6 +3346,9 @@ qemuDomainDefPostParse(virDomainDefPtr def, * function shall not fail in that case. It will be re-run on VM startup * with the capabilities populated. */ virQEMUCapsPtr qemuCaps = parseOpaque; + virDomainLoaderDefPtr ldr = NULL; + char *nvramPath = NULL; + int ret = -1; if (def->os.bootloader || def->os.bootloaderArgs) { @@ -3360,13 +3363,20 @@ qemuDomainDefPostParse(virDomainDefPtr def, goto cleanup; } - if (def->os.loader && - def->os.loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH && - def->os.loader->readonly == VIR_TRISTATE_SWITCH_ON && - !def->os.loader->nvram) { - if (virAsprintf(&def->os.loader->nvram, "%s/%s_VARS.fd", + ldr = def->os.loader; + if (ldr && + ldr->type == VIR_DOMAIN_LOADER_TYPE_PFLASH && + ldr->readonly == VIR_TRISTATE_SWITCH_ON && + !ldr->nvram) { + if (virAsprintf(&nvramPath, "%s/%s_VARS.fd", cfg->nvramDir, def->name) < 0) goto cleanup; + ldr->nvram = virStorageSourceNewFromBackingAbsolute(nvramPath); + if (!ldr->nvram) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to add NVRAM drive %s"), nvramPath); + goto cleanup; + } } if (qemuDomainDefAddDefaultDevices(def, qemuCaps) < 0) @@ -10547,19 +10557,22 @@ qemuDomainSetupLoader(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED, VIR_DEBUG("Setting up loader"); - if (loader) { + if (loader && loader->src) { switch ((virDomainLoader) loader->type) { case VIR_DOMAIN_LOADER_TYPE_ROM: - if (qemuDomainCreateDevice(loader->path, data, false) < 0) + if (loader->src->type == VIR_STORAGE_TYPE_FILE && + qemuDomainCreateDevice(loader->src->path, data, false) < 0) goto cleanup; break; case VIR_DOMAIN_LOADER_TYPE_PFLASH: - if (qemuDomainCreateDevice(loader->path, data, false) < 0) + if (loader->src->type == VIR_STORAGE_TYPE_FILE && + qemuDomainCreateDevice(loader->src->path, data, false) < 0) goto cleanup; if (loader->nvram && - qemuDomainCreateDevice(loader->nvram, data, false) < 0) + loader->nvram->type == VIR_STORAGE_TYPE_FILE && + qemuDomainCreateDevice(loader->nvram->path, data, false) < 0) goto cleanup; break; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e61af23..a056bc4 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7526,12 +7526,13 @@ qemuDomainUndefineFlags(virDomainPtr dom, if (vm->def->os.loader && vm->def->os.loader->nvram && - virFileExists(vm->def->os.loader->nvram)) { + vm->def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE && + virFileExists(vm->def->os.loader->nvram->path)) { if ((flags & VIR_DOMAIN_UNDEFINE_NVRAM)) { - if (unlink(vm->def->os.loader->nvram) < 0) { + if (unlink(vm->def->os.loader->nvram->path) < 0) { virReportSystemError(errno, _("failed to remove nvram: %s"), - vm->def->os.loader->nvram); + vm->def->os.loader->nvram->path); goto endjob; } } else if (!(flags & VIR_DOMAIN_UNDEFINE_KEEP_NVRAM)) { diff --git a/src/qemu/qemu_parse_command.c b/src/qemu/qemu_parse_command.c index 351425f..9b1a86e 100644 --- a/src/qemu/qemu_parse_command.c +++ b/src/qemu/qemu_parse_command.c @@ -650,6 +650,7 @@ qemuParseCommandLineDisk(virDomainXMLOptionPtr xmlopt, int idx = -1; int busid = -1; int unitid = -1; + bool is_firmware = false; if (qemuParseKeywords(val, &keywords, @@ -772,6 +773,9 @@ qemuParseCommandLineDisk(virDomainXMLOptionPtr xmlopt, def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO; } else if (STREQ(values[i], "xen")) { def->bus = VIR_DOMAIN_DISK_BUS_XEN; + } else if (STREQ(values[i], "pflash")) { + def->bus = VIR_DOMAIN_DISK_BUS_LAST; + is_firmware = true; } else if (STREQ(values[i], "sd")) { def->bus = VIR_DOMAIN_DISK_BUS_SD; } @@ -943,8 +947,25 @@ qemuParseCommandLineDisk(virDomainXMLOptionPtr xmlopt, ignore_value(VIR_STRDUP(def->dst, "hda")); } - if (!def->dst) - goto error; + if (!def->dst) { + if (is_firmware && def->bus == VIR_DOMAIN_DISK_BUS_LAST) { + if (!dom->os.loader && (VIR_ALLOC(dom->os.loader) < 0)) + goto error; + if (def->src->readonly) { + /* Loader spec */ + dom->os.loader->src = def->src; + dom->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH; + } else { + /* NVRAM Spec */ + if (!dom->os.loader->nvram && (VIR_ALLOC(dom->os.loader->nvram) < 0)) + goto error; + dom->os.loader->nvram = def->src; + } + } else { + goto error; + } + } + if (STREQ(def->dst, "xvda")) def->dst[3] = 'a' + idx; else @@ -2215,8 +2236,11 @@ qemuParseCommandLine(virCapsPtr caps, } else if (STREQ(arg, "-bios")) { WANT_VALUE(); if (VIR_ALLOC(def->os.loader) < 0 || - VIR_STRDUP(def->os.loader->path, val) < 0) + VIR_ALLOC(def->os.loader->src) < 0 || + VIR_STRDUP(def->os.loader->src->path, val) < 0) goto error; + def->os.loader->src->type = VIR_STORAGE_TYPE_FILE; + def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_ROM; } else if (STREQ(arg, "-initrd")) { WANT_VALUE(); if (VIR_STRDUP(def->os.initrd, val) < 0) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 5b73a61..5d406ef 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4187,25 +4187,53 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, const char *master_nvram_path; ssize_t r; - if (!loader || !loader->nvram || virFileExists(loader->nvram)) + /* This function is used to prepare a pristine local + * NVRAM file based on an existing template. + * The template could be explicitly specified in domain XML + * or inferred from absolute firmware path. + * + * Return early in the following cases: + * (1) loader or NVRAM is not specified. + * (2) loader is not of type 'pflash'. + * (3) NVRAM is already described as 'network-backed' + * (4) NVRAM is file-backed but file already exists. + * (5) Loader is network-backed, and hence impossible to + * infer firmware. + * (6) NVRAM is network-backed, + * hence not easy to customize. + */ + if (!loader || !loader->src || !loader->nvram || + loader->type != VIR_DOMAIN_LOADER_TYPE_PFLASH || + loader->src->type == VIR_STORAGE_TYPE_NETWORK || + loader->nvram->type == VIR_STORAGE_TYPE_NETWORK) + return 0; + + if (loader->nvram->type == VIR_STORAGE_TYPE_FILE && + virFileExists(loader->nvram->path)) return 0; master_nvram_path = loader->templt; - if (!loader->templt) { + /* Even if a template is not specified, we associate "known" EFI firmware + * to their NVRAM templates. + * Ofcourse this only applies to local firmware paths, as it is diffcult + * for libvirt to parse all network paths. + */ + if (!loader->templt && loader->src->type == VIR_STORAGE_TYPE_FILE) { size_t i; for (i = 0; i < cfg->nfirmwares; i++) { - if (STREQ(cfg->firmwares[i]->name, loader->path)) { + if (STREQ(cfg->firmwares[i]->name, loader->src->path)) { master_nvram_path = cfg->firmwares[i]->nvram; break; } } } - if (!master_nvram_path) { - virReportError(VIR_ERR_OPERATION_FAILED, - _("unable to find any master var store for " - "loader: %s"), loader->path); - goto cleanup; + if (!master_nvram_path && loader->nvram) { + /* There is no template description, but an NVRAM spec + * has already been provided. + * Trust the client to have generated the right spec here + */ + return 0; } if ((srcFD = virFileOpenAs(master_nvram_path, O_RDONLY, @@ -4215,13 +4243,13 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, master_nvram_path); goto cleanup; } - if ((dstFD = virFileOpenAs(loader->nvram, + if ((dstFD = virFileOpenAs(loader->nvram->path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, cfg->user, cfg->group, 0)) < 0) { virReportSystemError(-dstFD, _("Failed to create file '%s'"), - loader->nvram); + loader->nvram->path); goto cleanup; } created = true; @@ -4239,7 +4267,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, if (safewrite(dstFD, buf, r) < 0) { virReportSystemError(errno, _("Unable to write to file '%s'"), - loader->nvram); + loader->nvram->path); goto cleanup; } } while (r); @@ -4253,7 +4281,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, if (VIR_CLOSE(dstFD) < 0) { virReportSystemError(errno, _("Unable to close file '%s'"), - loader->nvram); + loader->nvram->path); goto cleanup; } @@ -4263,7 +4291,7 @@ qemuPrepareNVRAM(virQEMUDriverConfigPtr cfg, * copy the file content. Roll back. */ if (ret < 0) { if (created) - unlink(loader->nvram); + unlink(loader->nvram->path); } VIR_FORCE_CLOSE(srcFD); diff --git a/src/security/security_dac.c b/src/security/security_dac.c index 8938e2d..3febea6 100644 --- a/src/security/security_dac.c +++ b/src/security/security_dac.c @@ -1604,7 +1604,8 @@ virSecurityDACRestoreAllLabel(virSecurityManagerPtr mgr, } if (def->os.loader && def->os.loader->nvram && - virSecurityDACRestoreFileLabel(priv, def->os.loader->nvram) < 0) + def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE && + virSecurityDACRestoreFileLabel(priv, def->os.loader->nvram->path) < 0) rc = -1; return rc; @@ -1732,8 +1733,9 @@ virSecurityDACSetAllLabel(virSecurityManagerPtr mgr, return -1; if (def->os.loader && def->os.loader->nvram && + def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE && virSecurityDACSetOwnership(priv, NULL, - def->os.loader->nvram, user, group) < 0) + def->os.loader->nvram->path, user, group) < 0) return -1; if (def->os.kernel && diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index 5f74ef7..bcda939 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -2459,7 +2459,8 @@ virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr, rc = -1; if (def->os.loader && def->os.loader->nvram && - virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram) < 0) + def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE && + virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram->path) < 0) rc = -1; return rc; @@ -2851,8 +2852,9 @@ virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr, /* This is different than kernel or initrd. The nvram store * is really a disk, qemu can read and write to it. */ if (def->os.loader && def->os.loader->nvram && + def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE && secdef && secdef->imagelabel && - virSecuritySELinuxSetFilecon(mgr, def->os.loader->nvram, + virSecuritySELinuxSetFilecon(mgr, def->os.loader->nvram->path, secdef->imagelabel) < 0) return -1; diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index d0f9876..8217d67 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -1063,12 +1063,18 @@ get_files(vahControl * ctl) if (vah_add_file(&buf, ctl->def->os.slic_table, "r") != 0) goto cleanup; - if (ctl->def->os.loader && ctl->def->os.loader->path) - if (vah_add_file(&buf, ctl->def->os.loader->path, "rk") != 0) + if (ctl->def->os.loader && + ctl->def->os.loader->src && + ctl->def->os.loader->src->type == VIR_STORAGE_TYPE_FILE && + ctl->def->os.loader->src->path) + if (vah_add_file(&buf, ctl->def->os.loader->src->path, "rk") != 0) goto cleanup; - if (ctl->def->os.loader && ctl->def->os.loader->nvram) - if (vah_add_file(&buf, ctl->def->os.loader->nvram, "rwk") != 0) + if (ctl->def->os.loader && + ctl->def->os.loader->nvram && + ctl->def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE && + ctl->def->os.loader->nvram->path) + if (vah_add_file(&buf, ctl->def->os.loader->nvram->path, "rwk") != 0) goto cleanup; for (i = 0; i < ctl->def->ngraphics; i++) { diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c index 72a24a3..60451a3 100644 --- a/src/vbox/vbox_common.c +++ b/src/vbox/vbox_common.c @@ -998,11 +998,16 @@ vboxSetBootDeviceOrder(virDomainDefPtr def, vboxDriverPtr data, VIR_DEBUG("def->os.initrd %s", def->os.initrd); VIR_DEBUG("def->os.cmdline %s", def->os.cmdline); VIR_DEBUG("def->os.root %s", def->os.root); - if (def->os.loader) { - VIR_DEBUG("def->os.loader->path %s", def->os.loader->path); + if (def->os.loader && + def->os.loader->src && + def->os.loader->src->type == VIR_STORAGE_TYPE_FILE) { + + VIR_DEBUG("def->os.loader->src->path %s", def->os.loader->src->path); VIR_DEBUG("def->os.loader->readonly %d", def->os.loader->readonly); VIR_DEBUG("def->os.loader->type %d", def->os.loader->type); - VIR_DEBUG("def->os.loader->nvram %s", def->os.loader->nvram); + if (def->os.loader->nvram && + def->os.loader->nvram->type == VIR_STORAGE_TYPE_FILE) + VIR_DEBUG("def->os.loader->nvram->path %s", def->os.loader->nvram->path); } VIR_DEBUG("def->os.bootloader %s", def->os.bootloader); VIR_DEBUG("def->os.bootloaderArgs %s", def->os.bootloaderArgs); diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c index 42b305d..4070660 100644 --- a/src/xenapi/xenapi_driver.c +++ b/src/xenapi/xenapi_driver.c @@ -1444,10 +1444,12 @@ xenapiDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) char *value = NULL; defPtr->os.type = VIR_DOMAIN_OSTYPE_XEN; if (VIR_ALLOC(defPtr->os.loader) < 0 || - VIR_STRDUP(defPtr->os.loader->path, "pygrub") < 0) { + VIR_ALLOC(defPtr->os.loader->src) < 0 || + VIR_STRDUP(defPtr->os.loader->src->path, "pygrub") < 0) { VIR_FREE(boot_policy); goto error; } + defPtr->os.loader->src->type = VIR_STORAGE_TYPE_FILE; xen_vm_get_pv_kernel(session, &value, vm); if (STRNEQ(value, "")) { if (VIR_STRDUP(defPtr->os.kernel, value) < 0) { diff --git a/src/xenconfig/xen_sxpr.c b/src/xenconfig/xen_sxpr.c index e868c05..fd3165c 100644 --- a/src/xenconfig/xen_sxpr.c +++ b/src/xenconfig/xen_sxpr.c @@ -87,15 +87,17 @@ xenParseSxprOS(const struct sexpr *node, int hvm) { if (hvm) { - if (VIR_ALLOC(def->os.loader) < 0) + if ((VIR_ALLOC(def->os.loader) < 0) || + (VIR_ALLOC(def->os.loader->src) < 0)) goto error; - if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader->path) < 0) + def->os.loader->src->type = VIR_STORAGE_TYPE_FILE; + if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader->src->path) < 0) goto error; - if (def->os.loader->path == NULL) { - if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader->path) < 0) + if (def->os.loader->src->path == NULL) { + if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader->src->path) < 0) goto error; - if (def->os.loader->path == NULL) { + if (def->os.loader->src->path == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("domain information incomplete, missing HVM loader")); return -1; @@ -124,7 +126,8 @@ xenParseSxprOS(const struct sexpr *node, /* If HVM kenrel == loader, then old xend, so kill off kernel */ if (hvm && def->os.kernel && - STREQ(def->os.kernel, def->os.loader->path)) { + def->os.loader->src && + STREQ(def->os.kernel, def->os.loader->src->path)) { VIR_FREE(def->os.kernel); } /* Drop kernel argument that has no value */ @@ -2259,9 +2262,9 @@ xenFormatSxpr(virConnectPtr conn, virDomainDefPtr def) if (hvm) { char bootorder[VIR_DOMAIN_BOOT_LAST+1]; if (def->os.kernel) - virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader->path); + virBufferEscapeSexpr(&buf, "(loader '%s')", def->os.loader->src->path); else - virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader->path); + virBufferEscapeSexpr(&buf, "(kernel '%s')", def->os.loader->src->path); virBufferAsprintf(&buf, "(vcpus %u)", virDomainDefGetVcpusMax(def)); if (virDomainDefHasVcpusOffline(def)) diff --git a/src/xenconfig/xen_xm.c b/src/xenconfig/xen_xm.c index 4becb40..408b7b8 100644 --- a/src/xenconfig/xen_xm.c +++ b/src/xenconfig/xen_xm.c @@ -47,8 +47,10 @@ xenParseXMOS(virConfPtr conf, virDomainDefPtr def) const char *boot; if (VIR_ALLOC(def->os.loader) < 0 || - xenConfigCopyString(conf, "kernel", &def->os.loader->path) < 0) + VIR_ALLOC(def->os.loader->src) < 0 || + xenConfigCopyString(conf, "kernel", &def->os.loader->src->path) < 0) return -1; + def->os.loader->src->type = VIR_STORAGE_TYPE_FILE; if (xenConfigGetString(conf, "boot", &boot, "c") < 0) return -1; @@ -484,9 +486,10 @@ xenFormatXMOS(virConfPtr conf, virDomainDefPtr def) if (xenConfigSetString(conf, "builder", "hvm") < 0) return -1; - if (def->os.loader && def->os.loader->path && - xenConfigSetString(conf, "kernel", def->os.loader->path) < 0) + if (def->os.loader && def->os.loader->src && + xenConfigSetString(conf, "kernel", def->os.loader->src->path) < 0) return -1; + def->os.loader->src->type = VIR_STORAGE_TYPE_FILE; for (i = 0; i < def->os.nBootDevs; i++) { switch (def->os.bootDevs[i]) { -- 1.8.1.2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list