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