[PATCH 06/11] hyperv: attach virtual disks when defining domains
Daniel P. Berrangé
berrange at redhat.com
Thu Nov 26 14:48:10 UTC 2020
On Tue, Nov 24, 2020 at 02:48:35PM -0500, Matt Coleman wrote:
> Co-authored-by: Sri Ramanujam <sramanujam at datto.com>
> Signed-off-by: Matt Coleman <matt at datto.com>
> ---
> 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 :|
More information about the libvir-list
mailing list