https://bugzilla.redhat.com/show_bug.cgi?id=1180955
Up till now, there was only one format for UEFI and NVRAM store
file. However, it's possible to convert the files to qcow2
(which supports interesting features, like snapshotting, for
instance). Therefore, we want to allow format selection over the
UEFI and NVRAM store file. By default, the format is raw, but
users can choose qcow2. In the domain XML this is expressed as
@format attribute to <loader/> and <nvram/> elements.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
docs/formatdomain.html.in | 18 +++++++---
docs/schemas/domaincommon.rng | 16 +++++++++
src/conf/domain_conf.c | 34 ++++++++++++++++--
src/conf/domain_conf.h | 11 ++++++
src/libvirt_private.syms | 2 ++
.../qemuxml2xmlout-bios-nvram.xml | 40 ++++++++++++++++++++++
tests/qemuxml2xmltest.c | 2 +-
7 files changed, 116 insertions(+), 7 deletions(-)
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-bios-nvram.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0c3343e..12150f2 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -102,8 +102,8 @@
...
<os>
<type>hvm</type>
- <loader readonly='yes'
type='rom'>/usr/lib/xen/boot/hvmloader</loader>
- <nvram
template='/usr/share/OVMF/OVMF_VARS.fd'>/var/lib/libvirt/nvram/guest_VARS.fd</nvram>
+ <loader readonly='yes' type='rom'
format='raw'>/usr/lib/xen/boot/hvmloader</loader>
+ <nvram template='/usr/share/OVMF/OVMF_VARS.fd'
format='raw'>/var/lib/libvirt/nvram/guest_VARS.fd</nvram>
<boot dev='hd'/>
<boot dev='cdrom'/>
<bootmenu enable='yes' timeout='3000'/>
@@ -139,7 +139,12 @@
<code>pflash</code>. It tells the hypervisor where in the guest
memory the file should be mapped. For instance, if the loader
path points to an UEFI image, <code>type</code> should be
- <code>pflash</code>.</dd>
+ <code>pflash</code>.<span class="since">Since
1.2.12</span> it's
+ possible to determine the loader format too. However, other values than
+ <code>raw</code> make sense only if the UEFI image file is writable
+ (that is, the image and variable store is not split), that is when
+ <code>readonly</code> is no. Accepted values are
<code>raw</code>
+ which is the default or <code>qcow2</code>.</dd>
<dt><code>nvram</code></dt>
<dd>Some UEFI firmwares may want to use a non-volatile memory to store
some variables. In the host, this is represented as a file and the path
@@ -150,7 +155,12 @@
from the config file. Note, that for transient domains 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). <span class="since">Since
1.2.8</span></dd>
+ persistent). <span class="since">Since 1.2.8</span>
+ Then, <span class="since">since 1.2.12</span> it's
possible to choose
+ the NVRAM file format: <code>raw</code> for raw NVRAM file (the
+ default) or <code>qcow2</code> if the file has qcow2 format. Note
that
+ if used, the template file must be in the same format. Libvirt does no
+ format conversion.</dd>
<dt><code>boot</code></dt>
<dd>The <code>dev</code> attribute takes one of the values
"fd", "hd",
"cdrom" or "network" and is used to specify the next boot
device
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 85b3709..0010557 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -258,6 +258,14 @@
</choice>
</attribute>
</optional>
+ <optional>
+ <attribute name="format">
+ <choice>
+ <value>raw</value>
+ <value>qcow2</value>
+ </choice>
+ </attribute>
+ </optional>
<ref name="absFilePath"/>
</element>
</optional>
@@ -269,6 +277,14 @@
</attribute>
</optional>
<optional>
+ <attribute name="format">
+ <choice>
+ <value>raw</value>
+ <value>qcow2</value>
+ </choice>
+ </attribute>
+ </optional>
+ <optional>
<ref name="absFilePath"/>
</optional>
</element>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ae18255..bc23c6c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -794,6 +794,11 @@ VIR_ENUM_IMPL(virDomainLoader,
"rom",
"pflash")
+VIR_ENUM_IMPL(virDomainLoaderFormat,
+ VIR_DOMAIN_LOADER_FORMAT_LAST,
+ "raw",
+ "qcow2")
+
/* Internal mapping: subset of block job types that can be present in
* <mirror> XML (remaining types are not two-phase). */
VIR_ENUM_DECL(virDomainBlockJob)
@@ -12624,9 +12629,11 @@ virDomainLoaderDefParseXML(xmlNodePtr loader_node,
int ret = -1;
char *readonly_str = NULL;
char *type_str = NULL;
+ char *format_str = NULL;
readonly_str = virXMLPropString(loader_node, "readonly");
type_str = virXMLPropString(loader_node, "type");
+ format_str = virXMLPropString(loader_node, "format");
loader->path = (char *) xmlNodeGetContent(loader_node);
if (readonly_str &&
@@ -12646,15 +12653,33 @@ virDomainLoaderDefParseXML(xmlNodePtr loader_node,
loader->type = type;
}
+ if (format_str && loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH
&&
+ (loader->format = virDomainLoaderFormatTypeFromString(format_str)) < 0) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("unknown format value to <loader/>: %s"),
+ format_str);
+ goto cleanup;
+ }
+
if (nvram_node) {
+ VIR_FREE(format_str);
loader->nvram = (char *)xmlNodeGetContent(nvram_node);
loader->templt = virXMLPropString(nvram_node, "template");
+ format_str = virXMLPropString(nvram_node, "format");
+
+ if (format_str &&
+ (loader->nvramFormat = virDomainLoaderFormatTypeFromString(format_str))
< 0) {
+ virReportError(VIR_ERR_XML_DETAIL,
+ _("unknown format value to <nvram/>: %s"),
format_str);
+ goto cleanup;
+ }
}
ret = 0;
cleanup:
VIR_FREE(readonly_str);
VIR_FREE(type_str);
+ VIR_FREE(format_str);
return ret;
}
@@ -19287,12 +19312,17 @@ virDomainLoaderDefFormat(virBufferPtr buf,
if (loader->readonly)
virBufferAsprintf(buf, " readonly='%s'", readonly);
- virBufferAsprintf(buf, " type='%s'>", type);
+ virBufferAsprintf(buf, " type='%s'", type);
+ if (loader->type == VIR_DOMAIN_LOADER_TYPE_PFLASH)
+ virBufferAsprintf(buf, " format='%s'",
+ virDomainLoaderFormatTypeToString(loader->format));
- virBufferEscapeString(buf, "%s</loader>\n", loader->path);
+ virBufferEscapeString(buf, ">%s</loader>\n", loader->path);
if (loader->nvram || loader->templt) {
virBufferAddLit(buf, "<nvram");
virBufferEscapeString(buf, " template='%s'",
loader->templt);
+ virBufferAsprintf(buf, " format='%s'",
+ virDomainLoaderFormatTypeToString(loader->nvramFormat));
if (loader->nvram)
virBufferEscapeString(buf, ">%s</nvram>\n",
loader->nvram);
else
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ac1f4f8..7ea7714 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1729,14 +1729,25 @@ typedef enum {
VIR_ENUM_DECL(virDomainLoader)
+typedef enum {
+ VIR_DOMAIN_LOADER_FORMAT_RAW = 0,
+ VIR_DOMAIN_LOADER_FORMAT_QCOW2,
+
+ VIR_DOMAIN_LOADER_FORMAT_LAST
+} virDomainLoaderFormat;
+
+VIR_ENUM_DECL(virDomainLoaderFormat)
+
typedef struct _virDomainLoaderDef virDomainLoaderDef;
typedef virDomainLoaderDef *virDomainLoaderDefPtr;
struct _virDomainLoaderDef {
char *path;
int readonly; /* enum virTristateBool */
virDomainLoader type;
+ virDomainLoaderFormat format;
char *nvram; /* path to non-volatile RAM */
char *templt; /* user override of path to master nvram */
+ virDomainLoaderFormat nvramFormat;
};
void virDomainLoaderDefFree(virDomainLoaderDefPtr loader);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fb5d003..5db851c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -316,6 +316,8 @@ virDomainLifecycleTypeToString;
virDomainListFree;
virDomainLiveConfigHelperMethod;
virDomainLoaderDefFree;
+virDomainLoaderFormatTypeFromString;
+virDomainLoaderFormatTypeToString;
virDomainLoaderTypeFromString;
virDomainLoaderTypeToString;
virDomainLockFailureTypeFromString;
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-bios-nvram.xml
b/tests/qemuxml2xmloutdata/qemuxml2xmlout-bios-nvram.xml
new file mode 100644
index 0000000..d29df38
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-bios-nvram.xml
@@ -0,0 +1,40 @@
+<domain type='qemu'>
+ <name>test-bios</name>
+ <uuid>362d1fc1-df7d-193e-5c18-49a71bd1da66</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <loader readonly='yes' type='pflash'
format='raw'>/usr/share/OVMF/OVMF_CODE.fd</loader>
+ <nvram format='raw'>/usr/share/OVMF/OVMF_VARS.fd</nvram>
+ <boot dev='hd'/>
+ <bootmenu enable='yes'/>
+ </os>
+ <features>
+ <acpi/>
+ </features>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0'
target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0'/>
+ <controller type='ide' index='0'/>
+ <controller type='pci' index='0' model='pci-root'/>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='tablet' bus='usb'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 1166534..5238b09 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -404,7 +404,7 @@ mymain(void)
DO_TEST_DIFFERENT("numatune-memnode");
DO_TEST("numatune-memnode-no-memory");
- DO_TEST("bios-nvram");
+ DO_TEST_DIFFERENT("bios-nvram");
DO_TEST("tap-vhost");
DO_TEST("shmem");
--
2.0.5