https://bugzilla.redhat.com/show_bug.cgi?id=1007754
When attaching a new device, we need to check if its boot order
configuration is compatible with current domain definition.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/conf/domain_conf.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 1 +
2 files changed, 80 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ecfec0d..05e9d3a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2565,6 +2565,53 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
return 0;
}
+virDomainDeviceInfoPtr
+virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
+{
+ switch ((virDomainDeviceType) device->type) {
+ case VIR_DOMAIN_DEVICE_DISK:
+ return &device->data.disk->info;
+ case VIR_DOMAIN_DEVICE_FS:
+ return &device->data.fs->info;
+ case VIR_DOMAIN_DEVICE_NET:
+ return &device->data.net->info;
+ case VIR_DOMAIN_DEVICE_INPUT:
+ return &device->data.input->info;
+ case VIR_DOMAIN_DEVICE_SOUND:
+ return &device->data.sound->info;
+ case VIR_DOMAIN_DEVICE_VIDEO:
+ return &device->data.video->info;
+ case VIR_DOMAIN_DEVICE_HOSTDEV:
+ return device->data.hostdev->info;
+ case VIR_DOMAIN_DEVICE_WATCHDOG:
+ return &device->data.watchdog->info;
+ case VIR_DOMAIN_DEVICE_CONTROLLER:
+ return &device->data.controller->info;
+ case VIR_DOMAIN_DEVICE_HUB:
+ return &device->data.hub->info;
+ case VIR_DOMAIN_DEVICE_REDIRDEV:
+ return &device->data.redirdev->info;
+ case VIR_DOMAIN_DEVICE_SMARTCARD:
+ return &device->data.smartcard->info;
+ case VIR_DOMAIN_DEVICE_CHR:
+ return &device->data.chr->info;
+ case VIR_DOMAIN_DEVICE_MEMBALLOON:
+ return &device->data.memballoon->info;
+ case VIR_DOMAIN_DEVICE_NVRAM:
+ return &device->data.nvram->info;
+ case VIR_DOMAIN_DEVICE_RNG:
+ return &device->data.rng->info;
+
+ /* The following devices do not contain virDomainDeviceInfo */
+ case VIR_DOMAIN_DEVICE_LEASE:
+ case VIR_DOMAIN_DEVICE_GRAPHICS:
+ case VIR_DOMAIN_DEVICE_LAST:
+ case VIR_DOMAIN_DEVICE_NONE:
+ break;
+ }
+ return NULL;
+}
+
static bool
virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info, unsigned int flags)
{
@@ -17823,11 +17870,30 @@ virDomainDeviceIsUSB(virDomainDeviceDefPtr dev)
return false;
}
+static int
+virDomainDeviceInfoCheckBootIndex(virDomainDefPtr def ATTRIBUTE_UNUSED,
+ virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
+ virDomainDeviceInfoPtr info,
+ void *opaque)
+{
+ virDomainDeviceInfoPtr newinfo = opaque;
+
+ if (info->bootIndex == newinfo->bootIndex) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("boot order %d is already used by another device"),
+ newinfo->bootIndex);
+ return -1;
+ }
+ return 0;
+}
+
int
virDomainDefCompatibleDevice(virDomainDefPtr def,
virDomainDeviceDefPtr dev,
virDomainDeviceAction action)
{
+ virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(dev);
+
if (action != VIR_DOMAIN_DEVICE_ACTION_ATTACH)
return 0;
@@ -17840,6 +17906,19 @@ virDomainDefCompatibleDevice(virDomainDefPtr def,
return -1;
}
+ if (info && info->bootIndex > 0) {
+ if (def->os.nBootDevs > 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("per-device boot elements cannot be used"
+ " together with os/boot elements"));
+ return -1;
+ }
+ if (virDomainDeviceInfoIterate(def,
+ virDomainDeviceInfoCheckBootIndex,
+ info) < 0)
+ return -1;
+ }
+
return 0;
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index d5d5fd3..bf12414 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2291,6 +2291,7 @@ virDomainDeviceDefPtr virDomainDeviceDefCopy(virDomainDeviceDefPtr
src,
virDomainXMLOptionPtr xmlopt);
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
int type);
+virDomainDeviceInfoPtr virDomainDeviceGetInfo(virDomainDeviceDefPtr device);
int virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst,
virDomainDeviceInfoPtr src);
void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info);
--
1.9.1