mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-03 15:43:51 +00:00
Introduce per-device boot element
Currently, boot order can be specified per device class but there is no way to specify exact disk/NIC device to boot from. This patch adds <boot order='N'/> element which can be used inside <disk/> and <interface/>. This is incompatible with the older os/boot element. Since not all hypervisors support per-device boot specification, new deviceboot flag is included in capabilities XML for hypervisors which understand the new boot element. Presence of the flag allows (but doesn't require) users to use the new style boot order specification.
This commit is contained in:
parent
f5456ffd9d
commit
94234fa2f8
@ -55,6 +55,7 @@ BIOS you will see</p>
|
|||||||
</arch>
|
</arch>
|
||||||
<features>
|
<features>
|
||||||
<cpuselection/>
|
<cpuselection/>
|
||||||
|
<deviceboot/>
|
||||||
</features>
|
</features>
|
||||||
</guest></span>
|
</guest></span>
|
||||||
...
|
...
|
||||||
|
@ -103,8 +103,11 @@
|
|||||||
<dd>The <code>dev</code> attribute takes one of the values "fd", "hd",
|
<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
|
"cdrom" or "network" and is used to specify the next boot device
|
||||||
to consider. The <code>boot</code> element can be repeated multiple
|
to consider. The <code>boot</code> element can be repeated multiple
|
||||||
times to setup a priority list of boot devices to try in turn.
|
times to setup a priority list of boot devices to try in turn. The
|
||||||
<span class="since">Since 0.1.3</span>
|
<code>boot</code> element cannot be used if per-device boot elements
|
||||||
|
are used (see <a href="#elementsDisks">disks</a> and
|
||||||
|
<a href="#elementsNICS">network interfaces</a> sections below.
|
||||||
|
<span class="since">Since 0.1.3, per-device boot since 0.8.8</span>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><code>bootmenu</code></dt>
|
<dt><code>bootmenu</code></dt>
|
||||||
<dd> Whether or not to enable an interactive boot menu prompt on guest
|
<dd> Whether or not to enable an interactive boot menu prompt on guest
|
||||||
@ -625,6 +628,7 @@
|
|||||||
<driver name="tap" type="aio" cache="default"/>
|
<driver name="tap" type="aio" cache="default"/>
|
||||||
<source file='/var/lib/xen/images/fv0'/>
|
<source file='/var/lib/xen/images/fv0'/>
|
||||||
<target dev='hda' bus='ide'/>
|
<target dev='hda' bus='ide'/>
|
||||||
|
<boot order='2'/>
|
||||||
<encryption type='...'>
|
<encryption type='...'>
|
||||||
...
|
...
|
||||||
</encryption>
|
</encryption>
|
||||||
@ -640,6 +644,7 @@
|
|||||||
<host name="hostname" port="7000"/>
|
<host name="hostname" port="7000"/>
|
||||||
</source>
|
</source>
|
||||||
<target dev="hdb" bus="ide"/>
|
<target dev="hdb" bus="ide"/>
|
||||||
|
<boot order='1'/>
|
||||||
</disk>
|
</disk>
|
||||||
</devices>
|
</devices>
|
||||||
...</pre>
|
...</pre>
|
||||||
@ -692,6 +697,14 @@
|
|||||||
controls the cache mechanism, possible values are "default", "none",
|
controls the cache mechanism, possible values are "default", "none",
|
||||||
"writethrough" and "writeback". <span class="since">Since 0.1.8</span>
|
"writethrough" and "writeback". <span class="since">Since 0.1.8</span>
|
||||||
</dd>
|
</dd>
|
||||||
|
<dt><code>boot</code></dt>
|
||||||
|
<dd>Specifies that the disk is bootable. The <code>order</code>
|
||||||
|
attribute determines the order in which devices will be tried during
|
||||||
|
boot sequence. The per-device <code>boot</code> elements cannot be
|
||||||
|
used together with general boot elements in
|
||||||
|
<a href="#elementsOSBIOS">BIOS bootloader</a> section.
|
||||||
|
<span class="since">Since 0.8.8</span>
|
||||||
|
</dd>
|
||||||
<dt><code>encryption</code></dt>
|
<dt><code>encryption</code></dt>
|
||||||
<dd>If present, specifies how the volume is encrypted. See
|
<dd>If present, specifies how the volume is encrypted. See
|
||||||
the <a href="formatstorageencryption.html">Storage Encryption</a> page
|
the <a href="formatstorageencryption.html">Storage Encryption</a> page
|
||||||
@ -813,6 +826,7 @@
|
|||||||
<source bridge='xenbr0'/>
|
<source bridge='xenbr0'/>
|
||||||
<mac address='00:16:3e:5d:c7:9e'/>
|
<mac address='00:16:3e:5d:c7:9e'/>
|
||||||
<script path='vif-bridge'/>
|
<script path='vif-bridge'/>
|
||||||
|
<boot order='1'/>
|
||||||
</interface>
|
</interface>
|
||||||
</devices>
|
</devices>
|
||||||
...</pre>
|
...</pre>
|
||||||
@ -1090,6 +1104,29 @@ qemu-kvm -net nic,model=? /dev/null
|
|||||||
ignored.
|
ignored.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h5><a name="elementsNICSBoot">Specifying boot order</a></h5>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
...
|
||||||
|
<devices>
|
||||||
|
<interface type='network'>
|
||||||
|
<source network='default'/>
|
||||||
|
<target dev='vnet1'/>
|
||||||
|
<b><boot order='1'/></b>
|
||||||
|
</interface>
|
||||||
|
</devices>
|
||||||
|
...</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
For hypervisors which support this, you can set exact NIC which should
|
||||||
|
be used for network boot. The <code>order</code> attribute determines
|
||||||
|
the order in which devices will be tried during boot sequence. The
|
||||||
|
per-device <code>boot</code> elements cannot be used together with
|
||||||
|
general boot elements in
|
||||||
|
<a href="#elementsOSBIOS">BIOS bootloader</a> section.
|
||||||
|
<span class="since">Since 0.8.8</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
<h4><a name="elementsInput">Input devices</a></h4>
|
<h4><a name="elementsInput">Input devices</a></h4>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -121,9 +121,9 @@
|
|||||||
</optional>
|
</optional>
|
||||||
<choice>
|
<choice>
|
||||||
<ref name="osbootkernel"/>
|
<ref name="osbootkernel"/>
|
||||||
<oneOrMore>
|
<zeroOrMore>
|
||||||
<ref name="osbootdev"/>
|
<ref name="osbootdev"/>
|
||||||
</oneOrMore>
|
</zeroOrMore>
|
||||||
</choice>
|
</choice>
|
||||||
<optional>
|
<optional>
|
||||||
<element name="bootmenu">
|
<element name="bootmenu">
|
||||||
@ -525,6 +525,9 @@
|
|||||||
<ref name="driver"/>
|
<ref name="driver"/>
|
||||||
</optional>
|
</optional>
|
||||||
<ref name="target"/>
|
<ref name="target"/>
|
||||||
|
<optional>
|
||||||
|
<ref name="deviceBoot"/>
|
||||||
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<element name="readonly">
|
<element name="readonly">
|
||||||
<empty/>
|
<empty/>
|
||||||
@ -963,6 +966,7 @@
|
|||||||
- the IP address bound to the interface
|
- the IP address bound to the interface
|
||||||
- the name of the script used to set up the binding
|
- the name of the script used to set up the binding
|
||||||
- the target device used
|
- the target device used
|
||||||
|
- boot order
|
||||||
-->
|
-->
|
||||||
<define name="interface-options">
|
<define name="interface-options">
|
||||||
<interleave>
|
<interleave>
|
||||||
@ -1035,6 +1039,9 @@
|
|||||||
</optional>
|
</optional>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="deviceBoot"/>
|
||||||
|
</optional>
|
||||||
</interleave>
|
</interleave>
|
||||||
</define>
|
</define>
|
||||||
<define name="virtualPortProfile">
|
<define name="virtualPortProfile">
|
||||||
@ -2008,6 +2015,15 @@
|
|||||||
</optional>
|
</optional>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
<define name="deviceBoot">
|
||||||
|
<element name="boot">
|
||||||
|
<attribute name="order">
|
||||||
|
<ref name="positiveInteger"/>
|
||||||
|
</attribute>
|
||||||
|
<empty/>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Optional hypervisor extensions in their own namespace:
|
Optional hypervisor extensions in their own namespace:
|
||||||
QEmu
|
QEmu
|
||||||
|
@ -782,7 +782,8 @@ virCapabilitiesFormatXML(virCapsPtr caps)
|
|||||||
if (STREQ(caps->guests[i]->features[j]->name, "pae") ||
|
if (STREQ(caps->guests[i]->features[j]->name, "pae") ||
|
||||||
STREQ(caps->guests[i]->features[j]->name, "nonpae") ||
|
STREQ(caps->guests[i]->features[j]->name, "nonpae") ||
|
||||||
STREQ(caps->guests[i]->features[j]->name, "ia64_be") ||
|
STREQ(caps->guests[i]->features[j]->name, "ia64_be") ||
|
||||||
STREQ(caps->guests[i]->features[j]->name, "cpuselection")) {
|
STREQ(caps->guests[i]->features[j]->name, "cpuselection") ||
|
||||||
|
STREQ(caps->guests[i]->features[j]->name, "deviceboot")) {
|
||||||
virBufferVSprintf(&xml, " <%s/>\n",
|
virBufferVSprintf(&xml, " <%s/>\n",
|
||||||
caps->guests[i]->features[j]->name);
|
caps->guests[i]->features[j]->name);
|
||||||
} else {
|
} else {
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "ignore-value.h"
|
#include "ignore-value.h"
|
||||||
#include "storage_file.h"
|
#include "storage_file.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "bitmap.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
#define VIR_FROM_THIS VIR_FROM_DOMAIN
|
||||||
|
|
||||||
@ -1529,6 +1530,50 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainDeviceBootParseXML(xmlNodePtr node,
|
||||||
|
int *bootIndex,
|
||||||
|
virBitmapPtr bootMap)
|
||||||
|
{
|
||||||
|
char *order;
|
||||||
|
int boot;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
order = virXMLPropString(node, "order");
|
||||||
|
if (!order) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("missing boot order attribute"));
|
||||||
|
goto cleanup;
|
||||||
|
} else if (virStrToLong_i(order, NULL, 10, &boot) < 0 ||
|
||||||
|
boot <= 0) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("incorrect boot order '%s', expecting positive integer"),
|
||||||
|
order);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bootMap) {
|
||||||
|
bool set;
|
||||||
|
if (virBitmapGetBit(bootMap, boot - 1, &set) < 0) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("boot orders have to be contiguous and starting from 1"));
|
||||||
|
goto cleanup;
|
||||||
|
} else if (set) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("boot order %d used for more than one device"), boot);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
ignore_value(virBitmapSetBit(bootMap, boot - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
*bootIndex = boot;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(order);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainParseLegacyDeviceAddress(char *devaddr,
|
virDomainParseLegacyDeviceAddress(char *devaddr,
|
||||||
virDomainDevicePCIAddressPtr pci)
|
virDomainDevicePCIAddressPtr pci)
|
||||||
@ -1614,7 +1659,9 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
|
|||||||
static virDomainDiskDefPtr
|
static virDomainDiskDefPtr
|
||||||
virDomainDiskDefParseXML(virCapsPtr caps,
|
virDomainDiskDefParseXML(virCapsPtr caps,
|
||||||
xmlNodePtr node,
|
xmlNodePtr node,
|
||||||
int flags) {
|
virBitmapPtr bootMap,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
virDomainDiskDefPtr def;
|
virDomainDiskDefPtr def;
|
||||||
xmlNodePtr cur, host;
|
xmlNodePtr cur, host;
|
||||||
char *type = NULL;
|
char *type = NULL;
|
||||||
@ -1760,6 +1807,10 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
} else if ((serial == NULL) &&
|
} else if ((serial == NULL) &&
|
||||||
(xmlStrEqual(cur->name, BAD_CAST "serial"))) {
|
(xmlStrEqual(cur->name, BAD_CAST "serial"))) {
|
||||||
serial = (char *)xmlNodeGetContent(cur);
|
serial = (char *)xmlNodeGetContent(cur);
|
||||||
|
} else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
|
||||||
|
if (virDomainDeviceBootParseXML(cur, &def->bootIndex,
|
||||||
|
bootMap))
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
@ -2297,7 +2348,9 @@ static virDomainNetDefPtr
|
|||||||
virDomainNetDefParseXML(virCapsPtr caps,
|
virDomainNetDefParseXML(virCapsPtr caps,
|
||||||
xmlNodePtr node,
|
xmlNodePtr node,
|
||||||
xmlXPathContextPtr ctxt,
|
xmlXPathContextPtr ctxt,
|
||||||
int flags ATTRIBUTE_UNUSED) {
|
virBitmapPtr bootMap,
|
||||||
|
int flags ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
virDomainNetDefPtr def;
|
virDomainNetDefPtr def;
|
||||||
xmlNodePtr cur;
|
xmlNodePtr cur;
|
||||||
char *macaddr = NULL;
|
char *macaddr = NULL;
|
||||||
@ -2407,6 +2460,10 @@ virDomainNetDefParseXML(virCapsPtr caps,
|
|||||||
xmlStrEqual(cur->name, BAD_CAST "state")) {
|
xmlStrEqual(cur->name, BAD_CAST "state")) {
|
||||||
/* Legacy back-compat. Don't add any more attributes here */
|
/* Legacy back-compat. Don't add any more attributes here */
|
||||||
devaddr = virXMLPropString(cur, "devaddr");
|
devaddr = virXMLPropString(cur, "devaddr");
|
||||||
|
} else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
|
||||||
|
if (virDomainDeviceBootParseXML(cur, &def->bootIndex,
|
||||||
|
bootMap))
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
@ -4394,7 +4451,8 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
|
|||||||
|
|
||||||
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
|
||||||
dev->type = VIR_DOMAIN_DEVICE_DISK;
|
dev->type = VIR_DOMAIN_DEVICE_DISK;
|
||||||
if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, flags)))
|
if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node,
|
||||||
|
NULL, flags)))
|
||||||
goto error;
|
goto error;
|
||||||
} else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) {
|
} else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) {
|
||||||
dev->type = VIR_DOMAIN_DEVICE_FS;
|
dev->type = VIR_DOMAIN_DEVICE_FS;
|
||||||
@ -4402,7 +4460,8 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
|
|||||||
goto error;
|
goto error;
|
||||||
} else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
|
} else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
|
||||||
dev->type = VIR_DOMAIN_DEVICE_NET;
|
dev->type = VIR_DOMAIN_DEVICE_NET;
|
||||||
if (!(dev->data.net = virDomainNetDefParseXML(caps, node, ctxt, flags)))
|
if (!(dev->data.net = virDomainNetDefParseXML(caps, node, ctxt,
|
||||||
|
NULL, flags)))
|
||||||
goto error;
|
goto error;
|
||||||
} else if (xmlStrEqual(node->name, BAD_CAST "input")) {
|
} else if (xmlStrEqual(node->name, BAD_CAST "input")) {
|
||||||
dev->type = VIR_DOMAIN_DEVICE_INPUT;
|
dev->type = VIR_DOMAIN_DEVICE_INPUT;
|
||||||
@ -4673,12 +4732,21 @@ static char *virDomainDefDefaultEmulator(virDomainDefPtr def,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
|
virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
|
||||||
virDomainDefPtr def)
|
virDomainDefPtr def,
|
||||||
|
unsigned long *bootCount)
|
||||||
{
|
{
|
||||||
xmlNodePtr *nodes = NULL;
|
xmlNodePtr *nodes = NULL;
|
||||||
int i, n;
|
int i, n;
|
||||||
char *bootstr;
|
char *bootstr;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
unsigned long deviceBoot;
|
||||||
|
|
||||||
|
if (virXPathULong("count(./devices/disk[boot]"
|
||||||
|
"|./devices/interface[boot])", ctxt, &deviceBoot) < 0) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("cannot count boot devices"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* analysis of the boot devices */
|
/* analysis of the boot devices */
|
||||||
if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) {
|
if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) {
|
||||||
@ -4687,6 +4755,13 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n > 0 && deviceBoot) {
|
||||||
|
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("per-device boot elements cannot be used"
|
||||||
|
" together with os/boot elements"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0 ; i < n && i < VIR_DOMAIN_BOOT_LAST ; i++) {
|
for (i = 0 ; i < n && i < VIR_DOMAIN_BOOT_LAST ; i++) {
|
||||||
int val;
|
int val;
|
||||||
char *dev = virXMLPropString(nodes[i], "dev");
|
char *dev = virXMLPropString(nodes[i], "dev");
|
||||||
@ -4705,7 +4780,7 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
|
|||||||
VIR_FREE(dev);
|
VIR_FREE(dev);
|
||||||
def->os.bootDevs[def->os.nBootDevs++] = val;
|
def->os.bootDevs[def->os.nBootDevs++] = val;
|
||||||
}
|
}
|
||||||
if (def->os.nBootDevs == 0) {
|
if (def->os.nBootDevs == 0 && !deviceBoot) {
|
||||||
def->os.nBootDevs = 1;
|
def->os.nBootDevs = 1;
|
||||||
def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
|
def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
|
||||||
}
|
}
|
||||||
@ -4719,6 +4794,7 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
|
|||||||
VIR_FREE(bootstr);
|
VIR_FREE(bootstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*bootCount = deviceBoot;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
@ -4739,6 +4815,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
virDomainDefPtr def;
|
virDomainDefPtr def;
|
||||||
unsigned long count;
|
unsigned long count;
|
||||||
bool uuid_generated = false;
|
bool uuid_generated = false;
|
||||||
|
virBitmapPtr bootMap = NULL;
|
||||||
|
unsigned long bootMapSize = 0;
|
||||||
|
|
||||||
if (VIR_ALLOC(def) < 0) {
|
if (VIR_ALLOC(def) < 0) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
@ -5055,9 +5133,11 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
def->os.loader = virXPathString("string(./os/loader[1])", ctxt);
|
def->os.loader = virXPathString("string(./os/loader[1])", ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (STREQ(def->os.type, "hvm") &&
|
if (STREQ(def->os.type, "hvm")) {
|
||||||
virDomainDefParseBootXML(ctxt, def) < 0) {
|
if (virDomainDefParseBootXML(ctxt, def, &bootMapSize) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
if (bootMapSize && !(bootMap = virBitmapAlloc(bootMapSize)))
|
||||||
|
goto no_memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
def->emulator = virXPathString("string(./devices/emulator[1])", ctxt);
|
def->emulator = virXPathString("string(./devices/emulator[1])", ctxt);
|
||||||
@ -5078,6 +5158,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
for (i = 0 ; i < n ; i++) {
|
for (i = 0 ; i < n ; i++) {
|
||||||
virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps,
|
virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps,
|
||||||
nodes[i],
|
nodes[i],
|
||||||
|
bootMap,
|
||||||
flags);
|
flags);
|
||||||
if (!disk)
|
if (!disk)
|
||||||
goto error;
|
goto error;
|
||||||
@ -5134,6 +5215,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
virDomainNetDefPtr net = virDomainNetDefParseXML(caps,
|
virDomainNetDefPtr net = virDomainNetDefParseXML(caps,
|
||||||
nodes[i],
|
nodes[i],
|
||||||
ctxt,
|
ctxt,
|
||||||
|
bootMap,
|
||||||
flags);
|
flags);
|
||||||
if (!net)
|
if (!net)
|
||||||
goto error;
|
goto error;
|
||||||
@ -5533,6 +5615,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
if (virDomainDefAddImplicitControllers(def) < 0)
|
if (virDomainDefAddImplicitControllers(def) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
virBitmapFree(bootMap);
|
||||||
|
|
||||||
return def;
|
return def;
|
||||||
|
|
||||||
no_memory:
|
no_memory:
|
||||||
@ -5542,6 +5626,7 @@ no_memory:
|
|||||||
error:
|
error:
|
||||||
VIR_FREE(tmp);
|
VIR_FREE(tmp);
|
||||||
VIR_FREE(nodes);
|
VIR_FREE(nodes);
|
||||||
|
virBitmapFree(bootMap);
|
||||||
virDomainDefFree(def);
|
virDomainDefFree(def);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -6157,6 +6242,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
virBufferVSprintf(buf, " <target dev='%s' bus='%s'/>\n",
|
virBufferVSprintf(buf, " <target dev='%s' bus='%s'/>\n",
|
||||||
def->dst, bus);
|
def->dst, bus);
|
||||||
|
|
||||||
|
if (def->bootIndex)
|
||||||
|
virBufferVSprintf(buf, " <boot order='%d'/>\n", def->bootIndex);
|
||||||
if (def->readonly)
|
if (def->readonly)
|
||||||
virBufferAddLit(buf, " <readonly/>\n");
|
virBufferAddLit(buf, " <readonly/>\n");
|
||||||
if (def->shared)
|
if (def->shared)
|
||||||
@ -6401,6 +6488,8 @@ virDomainNetDefFormat(virBufferPtr buf,
|
|||||||
virBufferVSprintf(buf, ">\n%s </filterref>\n", attrs);
|
virBufferVSprintf(buf, ">\n%s </filterref>\n", attrs);
|
||||||
VIR_FREE(attrs);
|
VIR_FREE(attrs);
|
||||||
}
|
}
|
||||||
|
if (def->bootIndex)
|
||||||
|
virBufferVSprintf(buf, " <boot order='%d'/>\n", def->bootIndex);
|
||||||
|
|
||||||
if (def->tune.sndbuf_specified) {
|
if (def->tune.sndbuf_specified) {
|
||||||
virBufferAddLit(buf, " <tune>\n");
|
virBufferAddLit(buf, " <tune>\n");
|
||||||
|
@ -197,6 +197,7 @@ struct _virDomainDiskDef {
|
|||||||
char *serial;
|
char *serial;
|
||||||
int cachemode;
|
int cachemode;
|
||||||
int error_policy;
|
int error_policy;
|
||||||
|
int bootIndex;
|
||||||
unsigned int readonly : 1;
|
unsigned int readonly : 1;
|
||||||
unsigned int shared : 1;
|
unsigned int shared : 1;
|
||||||
virDomainDeviceInfo info;
|
virDomainDeviceInfo info;
|
||||||
@ -351,6 +352,7 @@ struct _virDomainNetDef {
|
|||||||
unsigned long sndbuf;
|
unsigned long sndbuf;
|
||||||
} tune;
|
} tune;
|
||||||
char *ifname;
|
char *ifname;
|
||||||
|
int bootIndex;
|
||||||
virDomainDeviceInfo info;
|
virDomainDeviceInfo info;
|
||||||
char *filter;
|
char *filter;
|
||||||
virNWFilterHashTablePtr filterparams;
|
virNWFilterHashTablePtr filterparams;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user