# HG changeset patch
# User Dan Smith <danms(a)us.ibm.com>
# Date 1218817591 25200
# Node ID df2834c111fe5cee0ec322d7a4f10a0083638eae
# Parent 86d7161daef682ba869fbae74133cfd811f1d306
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.
Signed-off-by: Dan Smith <danms(a)us.ibm.com>
diff -r 86d7161daef6 -r df2834c111fe src/Virt_VirtualSystemManagementService.c
--- a/src/Virt_VirtualSystemManagementService.c Thu Aug 14 07:28:22 2008 -0700
+++ b/src/Virt_VirtualSystemManagementService.c Fri Aug 15 09:26:31 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,31 @@
&domain->dev_mem[0],
ns);
} else if (type == CIM_RES_TYPE_DISK) {
+ struct virt_device dev;
+
+ 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,
+ count,
+ &domain->dev_disk_ct);
} else if (type == CIM_RES_TYPE_NET) {
+ struct virt_device dev;
+
+ 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,
+ count,
+ &domain->dev_net_ct);
}
if (msg != NULL)
return msg;