
# HG changeset patch # User Dan Smith <danms@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@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;