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