[libvirt] [PATCH 18/21] Added hypervDomainAttachDisk, internal implementation for disk attachement (required Msvm_ResourceAllocationSettingData and Msvm_AllocationCapabilities classes)

Yves Vinter yves.vinter at bull.net
Wed Oct 8 12:34:03 UTC 2014


From: yvinter <yves.vinter at bull.net>

---
 src/hyperv/hyperv_driver.c            | 377 ++++++++++++++++++++++++++++++++++
 src/hyperv/hyperv_wmi_generator.input |  41 ++++
 2 files changed, 418 insertions(+)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index f68eaad..cbe4397 100644
--- a/src/hyperv/hyperv_driver.c
+++ b/src/hyperv/hyperv_driver.c
@@ -2424,6 +2424,383 @@ hypervDomainUndefine(virDomainPtr domain)
 
 
 
+/*
+ * Creates the attribute __PATH for the RASD object
+ * The attribute is build like this:
+ *   \\<host_name>\root\virtualization:Msvm_ResourceAllocationSettingData.InstanceID="<rasdInstanceID>"
+ *   where backslashes in rasdInstanceID are doubled
+ */
+static int
+hypervGetResourceAllocationSettingDataPATH(virDomainPtr domain, char *rasdInstanceID, char **__path)
+{
+    char uuid_string[VIR_UUID_STRING_BUFLEN];
+    hypervPrivate *priv = domain->conn->privateData;
+    virBuffer query = VIR_BUFFER_INITIALIZER;
+    Msvm_ComputerSystem *computerSystem = NULL;
+    char *strTemp = NULL;
+    int result = -1, i = 0, j = 0, n = 0;
+    
+    virUUIDFormat(domain->uuid, uuid_string);
+    
+    /* Get host name */
+    virBufferAsprintf(&query,
+                      "associators of "
+                      "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+                      "Name=\"%s\"} "
+                      "where AssocClass = Msvm_HostedDependency "
+                      "ResultClass = Msvm_ComputerSystem",
+                      uuid_string);
+    if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
+        goto cleanup;
+    }
+    if (computerSystem == NULL) {
+        virReportError(VIR_ERR_NO_DOMAIN, _("No domain with UUID %s"), uuid_string);
+        goto cleanup;
+    }
+    
+    /* Count the number of backslash character */
+    strTemp = strchr(rasdInstanceID, '\\');
+    while (strTemp != NULL) {
+        n++;
+        strTemp = strchr(++strTemp, '\\');
+    }
+    /* Double the blackslashes */
+    if (VIR_ALLOC_N(strTemp, strlen(rasdInstanceID) + 1 + n) < 0)
+        goto cleanup;
+    while (rasdInstanceID[i] != '\0') {
+        strTemp[j] = rasdInstanceID[i];
+        if (rasdInstanceID[i] == '\\') {
+            j++;
+            strTemp[j] = '\\';
+        }
+        i++;
+        j++;
+    }
+    strTemp[j] = '\0';
+
+    /* Create the attribute __PATH */
+    /* FIXME: *__path allocated with 255 characters (static value) */
+    if (VIR_ALLOC_N(*__path, 255) < 0)
+        goto cleanup;
+    sprintf(*__path, "\\\\");
+    strcat(*__path, computerSystem->data->ElementName);
+    strcat(*__path, "\\root\\virtualization:Msvm_ResourceAllocationSettingData.InstanceID=\"");
+    strcat(*__path, strTemp);
+    strcat(*__path, "\"");
+    
+    result = 0;
+    
+ cleanup:
+    VIR_FREE(strTemp);
+    hypervFreeObject(priv, (hypervObject *)computerSystem);
+    virBufferFreeAndReset(&query);
+
+    return result;
+}
+
+
+
+/* hypervDomainAttachDisk
+ * FIXME:
+ *   - added ressources must me removed in case of error
+ *   - allow attaching disks on iSCSI (implemented only on IDE)
+ *   - allow attaching ISO images (on DVD devices)
+ *   - implement associated detach method
+ */
+ATTRIBUTE_UNUSED static int
+hypervDomainAttachDisk(virDomainPtr domain, virDomainDiskDefPtr disk)
+{
+    int result = -1, nb_params;
+    const char *selector = "CreationClassName=Msvm_VirtualSystemManagementService";
+    char uuid_string[VIR_UUID_STRING_BUFLEN];
+    char *ideRasdPath = NULL, *newDiskDrivePath = NULL;
+    char ideControler[2], ideControlerAddr[2];
+    hypervPrivate *priv = domain->conn->privateData;
+    virBuffer query = VIR_BUFFER_INITIALIZER;
+    Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
+    Msvm_ResourceAllocationSettingData *resourceAllocationSettingData = NULL;
+    Msvm_ResourceAllocationSettingData *resourceAllocationSettingData2 = NULL;
+    Msvm_ResourceAllocationSettingData *resourceAllocationSettingData3 = NULL;
+    Msvm_ResourceAllocationSettingData *resourceAllocationSettingData4 = NULL;
+    Msvm_ResourceAllocationSettingData *ideRasd = NULL;  /* resourceAllocationSettingData subtree -> do not disallocate */
+    Msvm_ResourceAllocationSettingData *diskRasd = NULL;  /* resourceAllocationSettingData2 subtree -> do not disallocate */
+    Msvm_ResourceAllocationSettingData *newDiskDrive = NULL;  /* resourceAllocationSettingData3 subtree -> do not disallocate */
+    Msvm_AllocationCapabilities *allocationCapabilities  = NULL;
+    Msvm_AllocationCapabilities *allocationCapabilities2  = NULL;
+    invokeXmlParam *params = NULL;
+    properties_t *tab_props = NULL;
+    eprParam eprparam1, eprparam2;
+    embeddedParam embeddedparam1, embeddedparam2;
+    
+    /* Initialization */
+    virUUIDFormat(domain->uuid, uuid_string);
+    
+    /* Set IDE Controler 0 or 1 and address 0 or 1 */
+    if (STREQ(disk->dst, "hda")) {
+        sprintf(ideControler, "%d", 0);
+        sprintf(ideControlerAddr, "%d", 0);
+    } else if (STREQ(disk->dst, "hdb")) {
+        sprintf(ideControler, "%d", 0);
+        sprintf(ideControlerAddr, "%d", 1);
+    } else if (STREQ(disk->dst, "hdc")) {
+        sprintf(ideControler, "%d", 1);
+        sprintf(ideControlerAddr, "%d", 0);
+    } else if (STREQ(disk->dst, "hdd")) {
+        sprintf(ideControler, "%d", 1);
+        sprintf(ideControlerAddr, "%d", 1);
+    } else {
+        /* IDE Controler 0 and address 0 choosen by default */
+        sprintf(ideControler, "%d", 0);
+        sprintf(ideControlerAddr, "%d", 0);
+    }
+    
+    VIR_DEBUG("src=%s, dst=IDE Controller %s:%s, uuid=%s",
+              disk->src->path, ideControler, ideControlerAddr, uuid_string);
+    
+    /* Get the current VM settings object */
+    virBufferAsprintf(&query,
+                      "associators of "
+                      "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
+                      "Name=\"%s\"} "
+                      "where AssocClass = Msvm_SettingsDefineState "
+                      "ResultClass = Msvm_VirtualSystemSettingData",
+                      uuid_string);
+    if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query, &virtualSystemSettingData) < 0) {
+        goto cleanup;
+    }
+    
+    /* Get the settings for IDE Controller on the VM */
+    virBufferFreeAndReset(&query);
+    virBufferAsprintf(&query,
+                      "associators of "
+                      "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+                      "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+                      "ResultClass = Msvm_ResourceAllocationSettingData",
+                      virtualSystemSettingData->data->InstanceID);
+    if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query, &resourceAllocationSettingData) < 0) {
+        goto cleanup;
+    }
+    ideRasd = resourceAllocationSettingData;
+    while (ideRasd != NULL) {
+        if (ideRasd->data->ResourceType == 5 && STREQ(ideRasd->data->Address, ideControler)) {
+            /* IDE Controller 0 or 1 */
+            break;
+        }
+        ideRasd = ideRasd->next;
+    }
+    if (ideRasd == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not find IDE Controller %s"), ideControler);
+        goto cleanup;
+    }
+    
+    /* Get the settings for 'Microsoft Synthetic Disk Drive' */
+    virBufferFreeAndReset(&query);
+    virBufferAddLit(&query, MSVM_ALLOCATIONCAPABILITIES_WQL_SELECT);
+    virBufferAddLit(&query, "WHERE ResourceSubType = 'Microsoft Synthetic Disk Drive'");
+    if (hypervGetMsvmAllocationCapabilitiesList(priv, &query, &allocationCapabilities) < 0) {
+        goto cleanup;
+    }
+    
+    /* Get default values for 'Microsoft Synthetic Disk Drive' */
+    virBufferFreeAndReset(&query);
+    virBufferAsprintf(&query,
+                      "associators of "
+                      "{Msvm_AllocationCapabilities.InstanceID=\"%s\"} "
+                      "where AssocClass = Msvm_SettingsDefineCapabilities "
+                      "ResultClass = Msvm_ResourceAllocationSettingData",
+                      allocationCapabilities->data->InstanceID);
+    if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query, &resourceAllocationSettingData2) < 0) {
+        goto cleanup;
+    }
+    diskRasd = resourceAllocationSettingData2;
+    while (diskRasd != NULL) {
+        if (strstr(diskRasd->data->InstanceID, "Default") != NULL) {
+            /* Default values */
+            break;
+        }
+        diskRasd = diskRasd->next;
+    }
+    if (diskRasd == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not get default values for 'Microsoft Synthetic Disk Drive'"));
+        goto cleanup;
+    }
+    
+    /* Create the attribute _PATH for the RASD object */
+    if (hypervGetResourceAllocationSettingDataPATH(domain, ideRasd->data->InstanceID, &ideRasdPath) < 0) {
+        goto cleanup;
+    }
+    
+    /* Add default disk drive */
+    /* Prepare EPR param */
+    virBufferFreeAndReset(&query);
+    virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+    virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string);
+    eprparam1.query = &query;
+    eprparam1.wmiProviderURI = ROOT_VIRTUALIZATION;
+    
+    /* Prepare EMBEDDED param 1 */
+    embeddedparam1.nbProps = 4;
+    if (VIR_ALLOC_N(tab_props, embeddedparam1.nbProps) < 0)
+        goto cleanup;
+    (*tab_props).name = "Parent";
+    (*tab_props).val = ideRasdPath;
+    (*(tab_props+1)).name = "Address";
+    (*(tab_props+1)).val = ideControlerAddr;
+    (*(tab_props+2)).name = "ResourceType";
+    (*(tab_props+2)).val = "22";
+    (*(tab_props+3)).name = "ResourceSubType";
+    (*(tab_props+3)).val = diskRasd->data->ResourceSubType;
+    embeddedparam1.instanceName =  MSVM_RESOURCEALLOCATIONSETTINGDATA_CLASSNAME;
+    embeddedparam1.prop_t = tab_props;
+    
+    /* Create invokeXmlParam tab */
+    nb_params = 2;
+    if (VIR_ALLOC_N(params, nb_params) < 0)
+        goto cleanup;
+    (*params).name = "TargetSystem";
+    (*params).type = EPR_PARAM;
+    (*params).param = &eprparam1;
+    (*(params+1)).name = "ResourceSettingData";
+    (*(params+1)).type = EMBEDDED_PARAM;
+    (*(params+1)).param = &embeddedparam1;
+    
+    if (hypervInvokeMethod(priv, params, nb_params, "AddVirtualSystemResources",
+                           MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add default disk drive"));
+        goto cleanup;
+    }
+    
+    /* Get the instance of the new default drive disk */
+    virBufferFreeAndReset(&query);
+    virBufferAsprintf(&query,
+                      "associators of "
+                      "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
+                      "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
+                      "ResultClass = Msvm_ResourceAllocationSettingData",
+                      virtualSystemSettingData->data->InstanceID);
+    if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query, &resourceAllocationSettingData3) < 0) {
+        goto cleanup;
+    }
+    newDiskDrive = resourceAllocationSettingData3;
+    while (newDiskDrive != NULL) {
+        if (newDiskDrive->data->ResourceType == 22 &&
+            STREQ(newDiskDrive->data->ResourceSubType, "Microsoft Synthetic Disk Drive") &&
+            STREQ(newDiskDrive->data->Parent, ideRasdPath) &&
+            STREQ(newDiskDrive->data->Address, ideControlerAddr)) {
+            break;
+        }
+        newDiskDrive = newDiskDrive->next;
+    }
+    if (newDiskDrive == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not find 'Microsoft Synthetic Disk Drive'"));
+        goto cleanup;
+    }
+    
+    /* Get the settings for 'Microsoft Virtual Hard Disk' */
+    virBufferFreeAndReset(&query);
+    virBufferAddLit(&query, MSVM_ALLOCATIONCAPABILITIES_WQL_SELECT);
+    virBufferAddLit(&query, "WHERE ResourceSubType = 'Microsoft Virtual Hard Disk'");
+    if (hypervGetMsvmAllocationCapabilitiesList(priv, &query, &allocationCapabilities2) < 0) {
+        goto cleanup;
+    }
+    
+    /* Get default values for 'Microsoft Virtual Hard Drive' */
+    virBufferFreeAndReset(&query);
+    virBufferAsprintf(&query,
+                      "associators of "
+                      "{Msvm_AllocationCapabilities.InstanceID=\"%s\"} "
+                      "where AssocClass = Msvm_SettingsDefineCapabilities "
+                      "ResultClass = Msvm_ResourceAllocationSettingData",
+                      allocationCapabilities2->data->InstanceID);
+    if (hypervGetMsvmResourceAllocationSettingDataList(priv, &query, &resourceAllocationSettingData4) < 0) {
+        goto cleanup;
+    }
+    diskRasd = resourceAllocationSettingData4;
+    while (diskRasd != NULL) {
+        if (strstr(diskRasd->data->InstanceID, "Default") != NULL) {
+            /* Default values */
+            break;
+        }
+        diskRasd = diskRasd->next;
+    }
+    if (diskRasd == NULL) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not get default values for 'Microsoft Virtual Hard Drive'"));
+        goto cleanup;
+    }
+    
+    /* Create the attribute _PATH for the RASD object */
+    if (hypervGetResourceAllocationSettingDataPATH(domain, newDiskDrive->data->InstanceID, &newDiskDrivePath) < 0) {
+        goto cleanup;
+    }
+    
+    /* Add the new VHD */
+    /* Prepare EPR param 2 */
+    virBufferFreeAndReset(&query);
+    virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
+    virBufferAsprintf(&query, "where Name = \"%s\"", uuid_string);
+    eprparam2.query = &query;
+    eprparam2.wmiProviderURI = ROOT_VIRTUALIZATION;
+    
+    /* Prepare EMBEDDED param 2 */
+    VIR_FREE(tab_props);
+    embeddedparam2.nbProps = 4;
+    if (VIR_ALLOC_N(tab_props, embeddedparam2.nbProps) < 0)
+        goto cleanup;
+    (*tab_props).name = "Parent";
+    (*tab_props).val = newDiskDrivePath;
+    (*(tab_props+1)).name = "Connection";
+    (*(tab_props+1)).val = disk->src->path;
+    (*(tab_props+2)).name = "ResourceType";
+    (*(tab_props+2)).val = "21";
+    (*(tab_props+3)).name = "ResourceSubType";
+    (*(tab_props+3)).val = diskRasd->data->ResourceSubType;
+    embeddedparam2.instanceName = MSVM_RESOURCEALLOCATIONSETTINGDATA_CLASSNAME;
+    embeddedparam2.prop_t = tab_props;
+    
+    /* Create invokeXmlParam tab */
+    VIR_FREE(params);
+    nb_params = 2;
+    if (VIR_ALLOC_N(params, nb_params) < 0)
+        goto cleanup;
+    (*params).name = "TargetSystem";
+    (*params).type = EPR_PARAM;
+    (*params).param = &eprparam2;
+    (*(params+1)).name = "ResourceSettingData";
+    (*(params+1)).type = EMBEDDED_PARAM;
+    (*(params+1)).param = &embeddedparam2;
+    
+    if (hypervInvokeMethod(priv, params, nb_params, "AddVirtualSystemResources",
+                           MSVM_VIRTUALSYSTEMMANAGEMENTSERVICE_RESOURCE_URI, selector) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("Could not attach hard disk drive"));
+        goto cleanup;
+    }
+    
+    result = 0;
+    
+ cleanup:
+    VIR_FREE(ideRasdPath);
+    VIR_FREE(newDiskDrivePath);
+    VIR_FREE(tab_props);
+    VIR_FREE(params);
+    hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
+    hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData);
+    hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData2);
+    hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData3);
+    hypervFreeObject(priv, (hypervObject *)resourceAllocationSettingData4);
+    hypervFreeObject(priv, (hypervObject *)allocationCapabilities);
+    hypervFreeObject(priv, (hypervObject *)allocationCapabilities2);
+    virBufferFreeAndReset(&query);
+    
+    return result;
+}
+
+
+
 static virDriver hypervDriver = {
     .no = VIR_DRV_HYPERV,
     .name = "Hyper-V",
diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input
index 79b5ee2..24d399f 100644
--- a/src/hyperv/hyperv_wmi_generator.input
+++ b/src/hyperv/hyperv_wmi_generator.input
@@ -605,3 +605,44 @@ class Msvm_VirtualSystemGlobalSettingData
 	boolean  AllowFullSCSICommandSet
 	string   Version
 end
+
+
+class Msvm_ResourceAllocationSettingData
+	string  Caption
+	string  Description
+	string  InstanceID
+	string  ElementName
+	uint16  ResourceType
+	string  OtherResourceType
+	string  ResourceSubType
+	string  PoolID
+	uint16  ConsumerVisibility
+	string  HostResource[]
+	string  AllocationUnits
+	uint64  VirtualQuantity
+	uint64  Reservation
+	uint64  Limit
+	uint32  Weight
+	boolean AutomaticAllocation
+	boolean AutomaticDeallocation
+	string  Parent
+	string  Connection[]
+	string  Address
+	uint16  MappingBehavior
+	string  VirtualSystemIdentifiers[]
+end
+
+
+class Msvm_AllocationCapabilities
+	string Caption
+	string Description
+	string ElementName
+	string InstanceID
+	string OtherResourceType
+	uint16 RequestTypesSupported
+	string ResourceSubType
+	uint16 ResourceType
+	uint16 SharingMode
+	uint16 SupportedAddStates[]
+	uint16 SupportedRemoveStates[]
+end
-- 
1.9.1




More information about the libvir-list mailing list