Since I haven't pushed the series yet, I can easily squash the following patch
into patch 2/4.
Jirka
From 5302f9ca43e26bd23230ba84e169a0e9109d04e8 Mon Sep 17 00:00:00 2001
Message-Id:
<5302f9ca43e26bd23230ba84e169a0e9109d04e8.1295268171.git.jdenemar(a)redhat.com>
From: Jiri Denemark <jdenemar(a)redhat.com>
Date: Mon, 17 Jan 2011 13:25:31 +0100
Subject: [PATCH] Check that boot order sequence is correct
Mail-Followup-To: libvir-list(a)redhat.com
The boot order sequence has to be contiguous starting from 1 and without
duplicates.
---
src/conf/domain_conf.c | 66 ++++++++++++++++++++++++++++++++++++++---------
1 files changed, 53 insertions(+), 13 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index bf8c5fa..645767e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -46,6 +46,7 @@
#include "ignore-value.h"
#include "storage_file.h"
#include "files.h"
+#include "bitmap.h"
#define VIR_FROM_THIS VIR_FROM_DOMAIN
@@ -1531,7 +1532,8 @@ cleanup:
static int
virDomainDeviceBootParseXML(xmlNodePtr node,
- int *bootIndex)
+ int *bootIndex,
+ virBitmapPtr bootMap)
{
char *order;
int boot;
@@ -1550,6 +1552,20 @@ virDomainDeviceBootParseXML(xmlNodePtr node,
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;
@@ -1643,7 +1659,9 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr
def)
static virDomainDiskDefPtr
virDomainDiskDefParseXML(virCapsPtr caps,
xmlNodePtr node,
- int flags) {
+ virBitmapPtr bootMap,
+ int flags)
+{
virDomainDiskDefPtr def;
xmlNodePtr cur, host;
char *type = NULL;
@@ -1790,7 +1808,8 @@ virDomainDiskDefParseXML(virCapsPtr caps,
(xmlStrEqual(cur->name, BAD_CAST "serial"))) {
serial = (char *)xmlNodeGetContent(cur);
} else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
- if (virDomainDeviceBootParseXML(cur, &def->bootIndex))
+ if (virDomainDeviceBootParseXML(cur, &def->bootIndex,
+ bootMap))
goto error;
}
}
@@ -2329,7 +2348,9 @@ static virDomainNetDefPtr
virDomainNetDefParseXML(virCapsPtr caps,
xmlNodePtr node,
xmlXPathContextPtr ctxt,
- int flags ATTRIBUTE_UNUSED) {
+ virBitmapPtr bootMap,
+ int flags ATTRIBUTE_UNUSED)
+{
virDomainNetDefPtr def;
xmlNodePtr cur;
char *macaddr = NULL;
@@ -2440,7 +2461,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
/* Legacy back-compat. Don't add any more attributes here */
devaddr = virXMLPropString(cur, "devaddr");
} else if (xmlStrEqual(cur->name, BAD_CAST "boot")) {
- if (virDomainDeviceBootParseXML(cur, &def->bootIndex))
+ if (virDomainDeviceBootParseXML(cur, &def->bootIndex,
+ bootMap))
goto error;
}
}
@@ -4429,7 +4451,8 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
if (xmlStrEqual(node->name, BAD_CAST "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;
} else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) {
dev->type = VIR_DOMAIN_DEVICE_FS;
@@ -4437,7 +4460,8 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
goto error;
} else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
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;
} else if (xmlStrEqual(node->name, BAD_CAST "input")) {
dev->type = VIR_DOMAIN_DEVICE_INPUT;
@@ -4708,15 +4732,21 @@ static char *virDomainDefDefaultEmulator(virDomainDefPtr def,
static int
virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
- virDomainDefPtr def)
+ virDomainDefPtr def,
+ unsigned long *bootCount)
{
xmlNodePtr *nodes = NULL;
int i, n;
char *bootstr;
int ret = -1;
- bool deviceBoot;
+ unsigned long deviceBoot;
- deviceBoot = virXPathBoolean("boolean(./devices/*/boot)", ctxt) > 0;
+ 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 */
if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) {
@@ -4764,6 +4794,7 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
VIR_FREE(bootstr);
}
+ *bootCount = deviceBoot;
ret = 0;
cleanup:
@@ -4784,6 +4815,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
virDomainDefPtr def;
unsigned long count;
bool uuid_generated = false;
+ virBitmapPtr bootMap = NULL;
+ unsigned long bootMapSize = 0;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -5100,9 +5133,11 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
def->os.loader = virXPathString("string(./os/loader[1])", ctxt);
}
- if (STREQ(def->os.type, "hvm") &&
- virDomainDefParseBootXML(ctxt, def) < 0) {
- goto error;
+ if (STREQ(def->os.type, "hvm")) {
+ if (virDomainDefParseBootXML(ctxt, def, &bootMapSize) < 0)
+ goto error;
+ if (bootMapSize && !(bootMap = virBitmapAlloc(bootMapSize)))
+ goto no_memory;
}
def->emulator = virXPathString("string(./devices/emulator[1])", ctxt);
@@ -5123,6 +5158,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
for (i = 0 ; i < n ; i++) {
virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps,
nodes[i],
+ bootMap,
flags);
if (!disk)
goto error;
@@ -5179,6 +5215,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
virDomainNetDefPtr net = virDomainNetDefParseXML(caps,
nodes[i],
ctxt,
+ bootMap,
flags);
if (!net)
goto error;
@@ -5578,6 +5615,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
if (virDomainDefAddImplicitControllers(def) < 0)
goto error;
+ virBitmapFree(bootMap);
+
return def;
no_memory:
@@ -5587,6 +5626,7 @@ no_memory:
error:
VIR_FREE(tmp);
VIR_FREE(nodes);
+ virBitmapFree(bootMap);
virDomainDefFree(def);
return NULL;
}
--
1.7.4.rc2