# HG changeset patch
# User Dan Smith <danms(a)us.ibm.com>
# Date 1219084718 25200
# Node ID 80e6ea1a1a296d424e15b3771d6753c3f8bbc5d1
# Parent f40ac4d174324f9ee4c76a4a8832704d3439e7dd
(#2) Override devices in reference configuration, where the ID is the same
Currently, we depend on libvirt to return an error if the client's
combination of ReferenceConfig and ResourceSettings results in a duplicate
device. That error is non-obvious in origin. Since two devices that would
result in the same InstanceID cannot be properly represented by the providers
anyway, this patch adds some logic to properly override such a conflicting
device.
To do this, I had to make sure we set the ID in rasd_to_vdev, which wasn't
previously required. The actual insertion of the device into the appropriate
type list is done by a helper function which checks for (and overrides if
appropriate) a duplicate before tacking the new instance on the end of the
list.
Changes:
We were already making the required space for the additional devices,
but I didn't correctly specify the new size then calling add_device_nodup()
function, resulting in a false failure.
Side note: the classify_resources() function is really getting out of hand
and could use some refactoring.
Signed-off-by: Dan Smith <danms(a)us.ibm.com>
diff -r f40ac4d17432 -r 80e6ea1a1a29 src/Virt_VirtualSystemManagementService.c
--- a/src/Virt_VirtualSystemManagementService.c Fri Aug 15 09:30:30 2008 -0700
+++ b/src/Virt_VirtualSystemManagementService.c Mon Aug 18 11:38:38 2008 -0700
@@ -411,6 +411,9 @@
free(dev->dev.net.mac);
dev->dev.net.mac = strdup(val);
+ free(dev->id);
+ dev->id = strdup(dev->dev.net.mac);
+
op = CMGetObjectPath(inst, NULL);
if (op == NULL) {
CU_DEBUG("Unable to get instance path");
@@ -449,6 +452,9 @@
dev->dev.disk.source = strdup(val);
dev->dev.disk.disk_type = disk_type_from_file(val);
+ free(dev->id);
+ dev->id = strdup(dev->dev.disk.virtual_dev);
+
return NULL;
}
@@ -469,6 +475,9 @@
free(dev->dev.disk.source);
dev->dev.disk.source = strdup(val);
dev->dev.disk.disk_type = DISK_FS;
+
+ free(dev->id);
+ dev->id = strdup(dev->dev.disk.virtual_dev);
return NULL;
}
@@ -621,6 +630,33 @@
return true;
}
+static char *add_device_nodup(struct virt_device *dev,
+ struct virt_device *list,
+ int max,
+ int *index)
+{
+ int i;
+
+ for (i = 0; i < *index; i++) {
+ struct virt_device *ptr = &list[i];
+
+ if (STREQC(ptr->id, dev->id)) {
+ CU_DEBUG("Overriding device %s from refconf",
ptr->id);
+ cleanup_virt_device(ptr);
+ memcpy(ptr, dev, sizeof(*ptr));
+ return NULL;
+ }
+ }
+
+ if (*index == max)
+ return "Internal error: no more device slots";
+
+ memcpy(&list[*index], dev, sizeof(list[*index]));
+ *index += 1;
+
+ return NULL;
+}
+
static const char *classify_resources(CMPIArray *resources,
const char *ns,
struct domain *domain)
@@ -678,15 +714,33 @@
&domain->dev_mem[0],
ns);
} else if (type == CIM_RES_TYPE_DISK) {
+ struct virt_device dev;
+ int dcount = count + domain->dev_disk_ct;
+
+ memset(&dev, 0, sizeof(dev));
msg = rasd_to_vdev(inst,
domain,
-
&domain->dev_disk[domain->dev_disk_ct++],
+ &dev,
ns);
+ if (msg == NULL)
+ msg = add_device_nodup(&dev,
+ domain->dev_disk,
+ dcount,
+ &domain->dev_disk_ct);
} else if (type == CIM_RES_TYPE_NET) {
+ struct virt_device dev;
+ int ncount = count + domain->dev_net_ct;
+
+ memset(&dev, 0, sizeof(dev));
msg = rasd_to_vdev(inst,
domain,
-
&domain->dev_net[domain->dev_net_ct++],
+ &dev,
ns);
+ if (msg == NULL)
+ msg = add_device_nodup(&dev,
+ domain->dev_net,
+ ncount,
+ &domain->dev_net_ct);
}
if (msg != NULL)
return msg;