提交 b50efe97 编写于 作者: J John Ferlan

conf: Add VM Generation ID parse/format support

The VM Generation ID is a mechanism to provide a unique 128-bit,
cryptographically random, and integer value identifier known as
the GUID (Globally Unique Identifier) to the guest OS. The value
is used to help notify the guest operating system when the virtual
machine is executed with a different configuration.

This patch adds support for a new "genid" XML element similar to
the "uuid" element. The "genid" element can have two forms "<genid/>"
or "<genid>$GUID</genid>". If the $GUID is not provided, libvirt
will generate one and save it in the XML.

Since adding support for a generated GUID (or UUID like) value to
be displayed modifying the xml2xml test to include virrandommock.so
is necessary since it will generate a "known" value.
Signed-off-by: NJohn Ferlan <jferlan@redhat.com>
ACKed-by: NMichal Privoznik <mprivozn@redhat.com>
上级 c7151b0e
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
&lt;domain type='kvm' id='1'&gt; &lt;domain type='kvm' id='1'&gt;
&lt;name&gt;MyGuest&lt;/name&gt; &lt;name&gt;MyGuest&lt;/name&gt;
&lt;uuid&gt;4dea22b3-1d52-d8f3-2516-782e98ab3fa0&lt;/uuid&gt; &lt;uuid&gt;4dea22b3-1d52-d8f3-2516-782e98ab3fa0&lt;/uuid&gt;
&lt;genid&gt;43dc0cf8-809b-4adb-9bea-a9abb5f3d90e&lt;/genid&gt;
&lt;title&gt;A short description - title - of the domain&lt;/title&gt; &lt;title&gt;A short description - title - of the domain&lt;/title&gt;
&lt;description&gt;Some human readable description&lt;/description&gt; &lt;description&gt;Some human readable description&lt;/description&gt;
&lt;metadata&gt; &lt;metadata&gt;
...@@ -61,6 +62,32 @@ ...@@ -61,6 +62,32 @@
specification. <span class="since">Since 0.0.1, sysinfo specification. <span class="since">Since 0.0.1, sysinfo
since 0.8.7</span></dd> since 0.8.7</span></dd>
<dt><code>genid</code></dt>
<dd><span class="since">Since 4.4.0</span>, the <code>genid</code>
element can be used to add a Virtual Machine Generation ID which
exposes a 128-bit, cryptographically random, integer value identifier,
referred to as a Globally Unique Identifier (GUID) using the same
format as the <code>uuid</code>. The value is used to help notify
the guest operating system when the virtual machine is re-executing
something that has already executed before, such as:
<ul>
<li>VM starts executing a snapshot</li>
<li>VM is recovered from backup</li>
<li>VM is failover in a disaster recovery environment</li>
<li>VM is imported, copied, or cloned</li>
</ul>
The guest operating system notices the change and is then able to
react as appropriate by marking its copies of distributed databases
as dirty, re-initializing its random number generator, etc.
<p>
The libvirt XML parser will accept both a provided GUID value
or just &lt;genid/&gt; in which case a GUID will be generated
and saved in the XML. For the transitions such as above, libvirt
will change the GUID before re-executing.</p></dd>
<dt><code>title</code></dt> <dt><code>title</code></dt>
<dd>The optional element <code>title</code> provides space for a <dd>The optional element <code>title</code> provides space for a
short description of the domain. The title should not contain short description of the domain. The title should not contain
......
...@@ -502,6 +502,14 @@ ...@@ -502,6 +502,14 @@
<ref name="UUID"/> <ref name="UUID"/>
</element> </element>
</optional> </optional>
<optional>
<element name="genid">
<choice>
<ref name="UUID"/>
<empty/>
</choice>
</element>
</optional>
</interleave> </interleave>
</define> </define>
<define name="idmap"> <define name="idmap">
......
...@@ -18920,6 +18920,34 @@ virDomainDefParseXML(xmlDocPtr xml, ...@@ -18920,6 +18920,34 @@ virDomainDefParseXML(xmlDocPtr xml,
VIR_FREE(tmp); VIR_FREE(tmp);
} }
/* Extract domain genid - a genid can either be provided or generated */
if ((n = virXPathNodeSet("./genid", ctxt, &nodes)) < 0)
goto error;
if (n > 0) {
if (n != 1) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("element 'genid' can only appear once"));
goto error;
}
def->genidRequested = true;
if (!(tmp = virXPathString("string(./genid)", ctxt))) {
if (virUUIDGenerate(def->genid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("Failed to generate genid"));
goto error;
}
def->genidGenerated = true;
} else {
if (virUUIDParse(tmp, def->genid) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("malformed genid element"));
goto error;
}
}
}
VIR_FREE(nodes);
/* Extract short description of domain (title) */ /* Extract short description of domain (title) */
def->title = virXPathString("string(./title[1])", ctxt); def->title = virXPathString("string(./title[1])", ctxt);
if (def->title && strchr(def->title, '\n')) { if (def->title && strchr(def->title, '\n')) {
...@@ -22034,6 +22062,25 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src, ...@@ -22034,6 +22062,25 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src,
goto error; goto error;
} }
if (src->genidRequested != dst->genidRequested) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Target domain requested genid does not match source"));
goto error;
}
if (src->genidRequested &&
memcmp(src->genid, dst->genid, VIR_UUID_BUFLEN) != 0) {
char guidsrc[VIR_UUID_STRING_BUFLEN];
char guiddst[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(src->genid, guidsrc);
virUUIDFormat(dst->genid, guiddst);
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Target domain genid %s does not match source %s"),
guiddst, guidsrc);
goto error;
}
/* Not strictly ABI related, but we want to make sure domains /* Not strictly ABI related, but we want to make sure domains
* don't get silently re-named through the backdoor when passing * don't get silently re-named through the backdoor when passing
* custom XML into various APIs, since this would create havoc * custom XML into various APIs, since this would create havoc
...@@ -26752,6 +26799,13 @@ virDomainDefFormatInternal(virDomainDefPtr def, ...@@ -26752,6 +26799,13 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virUUIDFormat(uuid, uuidstr); virUUIDFormat(uuid, uuidstr);
virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr); virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
if (def->genidRequested) {
char genidstr[VIR_UUID_STRING_BUFLEN];
virUUIDFormat(def->genid, genidstr);
virBufferAsprintf(buf, "<genid>%s</genid>\n", genidstr);
}
virBufferEscapeString(buf, "<title>%s</title>\n", def->title); virBufferEscapeString(buf, "<title>%s</title>\n", def->title);
virBufferEscapeString(buf, "<description>%s</description>\n", virBufferEscapeString(buf, "<description>%s</description>\n",
......
...@@ -2328,6 +2328,11 @@ struct _virDomainDef { ...@@ -2328,6 +2328,11 @@ struct _virDomainDef {
virDomainVirtType virtType; virDomainVirtType virtType;
int id; int id;
unsigned char uuid[VIR_UUID_BUFLEN]; unsigned char uuid[VIR_UUID_BUFLEN];
unsigned char genid[VIR_UUID_BUFLEN];
bool genidRequested;
bool genidGenerated;
char *name; char *name;
char *title; char *title;
char *description; char *description;
......
<domain type='qemu' id='1'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<genid/>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='none'/>
</devices>
</domain>
<domain type='qemu' id='1'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<genid>e9392370-2917-565e-692b-d057f46512d6</genid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='none'/>
</devices>
</domain>
<domain type='qemu' id='1'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<genid>e9392370-2917-565e-692b-d057f46512d6</genid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='none'/>
</devices>
</domain>
<domain type='qemu' id='1'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<genid>00010203-0405-4607-8809-0a0b0c0d0e0f</genid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='none'/>
</devices>
</domain>
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<genid>00010203-0405-4607-8809-0a0b0c0d0e0f</genid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='none'/>
</devices>
</domain>
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<genid>e9392370-2917-565e-692b-d057f46512d6</genid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<controller type='usb' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
</controller>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<memballoon model='none'/>
</devices>
</domain>
...@@ -276,6 +276,8 @@ mymain(void) ...@@ -276,6 +276,8 @@ mymain(void)
setenv("PATH", "/bin", 1); setenv("PATH", "/bin", 1);
DO_TEST("minimal", NONE); DO_TEST("minimal", NONE);
DO_TEST("genid", NONE);
DO_TEST("genid-auto", NONE);
DO_TEST("machine-core-on", NONE); DO_TEST("machine-core-on", NONE);
DO_TEST("machine-core-off", NONE); DO_TEST("machine-core-off", NONE);
DO_TEST("machine-loadparm-multiple-disks-nets-s390", NONE); DO_TEST("machine-loadparm-multiple-disks-nets-s390", NONE);
...@@ -1220,7 +1222,8 @@ mymain(void) ...@@ -1220,7 +1222,8 @@ mymain(void)
} }
VIR_TEST_MAIN_PRELOAD(mymain, VIR_TEST_MAIN_PRELOAD(mymain,
abs_builddir "/.libs/virpcimock.so") abs_builddir "/.libs/virpcimock.so",
abs_builddir "/.libs/virrandommock.so")
#else #else
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册