On Tue, Nov 24, 2020 at 02:48:35PM -0500, Matt Coleman wrote: > Co-authored-by: Sri Ramanujam <sramanujam@xxxxxxxxx> > Signed-off-by: Matt Coleman <matt@xxxxxxxxx> > --- > src/hyperv/hyperv_driver.c | 244 +++++++++++++++++++++++++++++++- > src/hyperv/hyperv_wmi_classes.h | 1 + > 2 files changed, 242 insertions(+), 3 deletions(-) > > diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c > index 1ad52e598a..a3da2ec524 100644 > --- a/src/hyperv/hyperv_driver.c > +++ b/src/hyperv/hyperv_driver.c > @@ -327,6 +327,30 @@ hypervGetDeviceParentRasdFromDeviceId(const char *parentDeviceId, > } > > > +static char * > +hypervGetInstanceIDFromXMLResponse(WsXmlDocH response) > +{ > + WsXmlNodeH envelope = NULL; > + char *instanceId = NULL; > + > + envelope = ws_xml_get_soap_envelope(response); > + if (!envelope) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid XML response")); > + return NULL; > + } > + > + instanceId = ws_xml_get_xpath_value(response, (char *)"//w:Selector[@Name='InstanceID']"); > + > + if (!instanceId) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Could not find selectors in method response")); > + return NULL; > + } > + > + return instanceId; > +} > + > + > static int > hypervDomainCreateSCSIController(virDomainPtr domain) > { > @@ -359,10 +383,175 @@ hypervDomainCreateSCSIController(virDomainPtr domain) > > > static int > -hypervDomainAttachStorage(virDomainPtr domain, virDomainDefPtr def) > +hypervDomainAddVirtualDiskParent(virDomainPtr domain, > + virDomainDiskDefPtr disk, > + Msvm_ResourceAllocationSettingData *controller, > + const char *hostname, > + WsXmlDocH *response) > { > + g_autoptr(GHashTable) controllerResource = NULL; > + g_autofree char *parentInstanceIDEscaped = NULL; > + g_autofree char *parent__PATH = NULL; > + g_autofree char *addressString = g_strdup_printf("%u", disk->info.addr.drive.unit); Validate disk->info.type == DRIVE before accessing this field otherwise the union contents is undefined. > + g_autofree char *resourceType = NULL; > + > + resourceType = g_strdup_printf("%d", MSVM_RASD_RESOURCETYPE_DISK_DRIVE); > + > + controllerResource = hypervCreateEmbeddedParam(Msvm_ResourceAllocationSettingData_WmiInfo); > + if (!controllerResource) > + return -1; > + > + parentInstanceIDEscaped = virStringReplace(controller->data->InstanceID, "\\", "\\\\"); > + parent__PATH = g_strdup_printf("\\\\%s\\Root\\Virtualization\\V2:" > + "Msvm_ResourceAllocationSettingData.InstanceID=\"%s\"", > + hostname, parentInstanceIDEscaped); > + if (!parent__PATH) > + return -1; > + > + if (hypervSetEmbeddedProperty(controllerResource, "Parent", parent__PATH) < 0) > + return -1; > + > + if (hypervSetEmbeddedProperty(controllerResource, "AddressOnParent", addressString) < 0) > + return -1; > + > + if (hypervSetEmbeddedProperty(controllerResource, "ResourceType", resourceType) < 0) > + return -1; > + > + if (hypervSetEmbeddedProperty(controllerResource, "ResourceSubType", > + "Microsoft:Hyper-V:Synthetic Disk Drive") < 0) > + return -1; > + > + if (hypervMsvmVSMSAddResourceSettings(domain, &controllerResource, > + Msvm_ResourceAllocationSettingData_WmiInfo, > + response) < 0) > + return -1; > + > + return 0; > +} > + > + > +static int > +hypervDomainAddVirtualHardDisk(virDomainPtr domain, > + virDomainDiskDefPtr disk, > + const char *hostname, > + char *parentInstanceID) > +{ > + g_autoptr(GHashTable) volumeResource = NULL; > + g_autofree char *vhdInstanceIdEscaped = NULL; > + g_autofree char *vhd__PATH = NULL; > + g_autofree char *resourceType = NULL; > + > + resourceType = g_strdup_printf("%d", MSVM_RASD_RESOURCETYPE_LOGICAL_DISK); > + > + volumeResource = hypervCreateEmbeddedParam(Msvm_ResourceAllocationSettingData_WmiInfo); > + if (!volumeResource) > + return -1; > + > + vhdInstanceIdEscaped = virStringReplace(parentInstanceID, "\\", "\\\\"); > + vhd__PATH = g_strdup_printf("\\\\%s\\Root\\Virtualization\\V2:" > + "Msvm_ResourceAllocationSettingData.InstanceID=\"%s\"", > + hostname, vhdInstanceIdEscaped); > + > + if (!vhd__PATH) > + return -1; > + > + if (hypervSetEmbeddedProperty(volumeResource, "Parent", vhd__PATH) < 0) > + return -1; > + > + if (hypervSetEmbeddedProperty(volumeResource, "HostResource", disk->src->path) < 0) > + return -1; > + > + if (hypervSetEmbeddedProperty(volumeResource, "ResourceType", resourceType) < 0) > + return -1; > + > + if (hypervSetEmbeddedProperty(volumeResource, "ResourceSubType", > + "Microsoft:Hyper-V:Virtual Hard Disk") < 0) > + return -1; The disk->device can be disk, or cdrom or floppy. So if you're hadcoding disk, then validate disk->device matches. > + > + if (hypervMsvmVSMSAddResourceSettings(domain, &volumeResource, > + Msvm_ResourceAllocationSettingData_WmiInfo, > + NULL) < 0) > + return -1; > + > + return 0; > +} > + > + > +static int > +hypervDomainAttachVirtualDisk(virDomainPtr domain, > + virDomainDiskDefPtr disk, > + Msvm_ResourceAllocationSettingData *controller, > + const char *hostname) > +{ > + int result = -1; > + g_autofree char *parentInstanceID = NULL; > + WsXmlDocH response = NULL; > + > + VIR_DEBUG("Now attaching disk image '%s' with address %d to bus %d of type %d", > + disk->src->path, disk->info.addr.drive.unit, disk->info.addr.drive.controller, disk->bus); Don't access the disk->info.addr until its type is validated > + > + if (hypervDomainAddVirtualDiskParent(domain, disk, controller, hostname, &response) < 0) > + return -1; > + > + if (!response) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add virtual disk parent")); > + return -1; > + } > + > + parentInstanceID = hypervGetInstanceIDFromXMLResponse(response); > + if (!parentInstanceID) > + goto cleanup; > + > + if (hypervDomainAddVirtualHardDisk(domain, disk, hostname, parentInstanceID) < 0) > + goto cleanup; > + > + result = 0; > + > + cleanup: > + ws_xml_destroy_doc(response); > + > + return result; > +} > + > + > +static int > +hypervDomainAttachStorageVolume(virDomainPtr domain, > + virDomainDiskDefPtr disk, > + Msvm_ResourceAllocationSettingData *controller, > + const char *hostname) > +{ > + switch (disk->device) { > + case VIR_DOMAIN_DISK_DEVICE_DISK: > + if (disk->src->type == VIR_STORAGE_TYPE_FILE) > + return hypervDomainAttachVirtualDisk(domain, disk, controller, hostname); > + else > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unsupported disk type")); > + break; > + default: > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unsupported disk bus")); > + break; > + } > + > + return -1; > +} > + > + > +static int > +hypervDomainAttachStorage(virDomainPtr domain, virDomainDefPtr def, const char *hostname) > +{ > + int result = -1; > + hypervPrivate *priv = domain->conn->privateData; > size_t i = 0; > + char uuid_string[VIR_UUID_STRING_BUFLEN]; > + int num_scsi_controllers = 0; > + int ctrlr_idx = -1; > + Msvm_VirtualSystemSettingData *vssd = NULL; > + Msvm_ResourceAllocationSettingData *rasd = NULL; > + Msvm_ResourceAllocationSettingData *entry = NULL; > + Msvm_ResourceAllocationSettingData *ideChannels[HYPERV_MAX_IDE_CHANNELS]; > + Msvm_ResourceAllocationSettingData *scsiControllers[HYPERV_MAX_SCSI_CONTROLLERS]; > > + /* start with attaching scsi controllers */ > for (i = 0; i < def->ncontrollers; i++) { > if (def->controllers[i]->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) > continue; > @@ -371,7 +560,55 @@ hypervDomainAttachStorage(virDomainPtr domain, virDomainDefPtr def) > return -1; > } > > - return 0; > + virUUIDFormat(domain->uuid, uuid_string); > + > + /* filter through all the rasd entries and isolate our controllers */ > + if (hypervGetMsvmVirtualSystemSettingDataFromUUID(priv, uuid_string, &vssd) < 0) > + goto cleanup; > + > + if (hypervGetResourceAllocationSD(priv, vssd->data->InstanceID, &rasd) < 0) > + goto cleanup; > + > + entry = rasd; > + while (entry) { > + if (entry->data->ResourceType == MSVM_RASD_RESOURCETYPE_IDE_CONTROLLER) > + ideChannels[entry->data->Address[0] - '0'] = entry; > + else if (entry->data->ResourceType == MSVM_RASD_RESOURCETYPE_PARALLEL_SCSI_HBA) > + scsiControllers[num_scsi_controllers++] = entry; > + > + entry = entry->next; > + } > + > + /* now we loop through and attach all the disks */ > + for (i = 0; i < def->ndisks; i++) { > + switch (def->disks[i]->bus) { > + case VIR_DOMAIN_DISK_BUS_IDE: > + ctrlr_idx = def->disks[i]->info.addr.drive.bus; > + if (hypervDomainAttachStorageVolume(domain, def->disks[i], > + ideChannels[ctrlr_idx], hostname) < 0) { > + goto cleanup; > + } > + break; > + case VIR_DOMAIN_DISK_BUS_SCSI: > + ctrlr_idx = def->disks[i]->info.addr.drive.controller; > + if (hypervDomainAttachStorageVolume(domain, def->disks[i], > + scsiControllers[ctrlr_idx], hostname) < 0) { > + goto cleanup; > + } > + break; > + default: > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Unsupported controller type")); > + goto cleanup; > + } > + } > + > + result = 0; > + > + cleanup: > + hypervFreeObject(priv, (hypervObject *)rasd); > + hypervFreeObject(priv, (hypervObject *)vssd); > + > + return result; > } > > > @@ -1991,6 +2228,7 @@ static virDomainPtr > hypervDomainDefineXML(virConnectPtr conn, const char *xml) > { > hypervPrivate *priv = conn->privateData; > + g_autofree char *hostname = hypervConnectGetHostname(conn); > g_autoptr(virDomainDef) def = NULL; > virDomainPtr domain = NULL; > g_autoptr(hypervInvokeParamsList) params = NULL; > @@ -2051,7 +2289,7 @@ hypervDomainDefineXML(virConnectPtr conn, const char *xml) > goto error; > > /* attach all storage */ > - if (hypervDomainAttachStorage(domain, def) < 0) > + if (hypervDomainAttachStorage(domain, def, hostname) < 0) > goto error; > > return domain; > diff --git a/src/hyperv/hyperv_wmi_classes.h b/src/hyperv/hyperv_wmi_classes.h > index 36c0e60c2a..2c03ca3745 100644 > --- a/src/hyperv/hyperv_wmi_classes.h > +++ b/src/hyperv/hyperv_wmi_classes.h > @@ -113,6 +113,7 @@ enum _Msvm_ResourceAllocationSettingData_ResourceType { > MSVM_RASD_RESOURCETYPE_DVD_DRIVE = 16, > MSVM_RASD_RESOURCETYPE_DISK_DRIVE = 17, > MSVM_RASD_RESOURCETYPE_STORAGE_EXTENT = 19, > + MSVM_RASD_RESOURCETYPE_LOGICAL_DISK = 31, > }; > > > -- > 2.27.0 > > Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|