mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
hyperv: XML parsing of storage volumes
dumpxml can now serialize: * floppy drives * file-backed and device-backed disk drives * images mounted to virtual CD/DVD drives * IDE and SCSI controllers Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Co-authored-by: Sri Ramanujam <sramanujam@datto.com> Signed-off-by: Matt Coleman <matt@datto.com>
This commit is contained in:
parent
5245a7ae4c
commit
a7a1d1f59e
@ -293,6 +293,400 @@ hypervCapsInit(hypervPrivate *priv)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Virtual device functions
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
hypervGetDeviceParentRasdFromDeviceId(const char *parentDeviceId,
|
||||||
|
Msvm_ResourceAllocationSettingData *list,
|
||||||
|
Msvm_ResourceAllocationSettingData **out)
|
||||||
|
{
|
||||||
|
Msvm_ResourceAllocationSettingData *entry = list;
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
|
while (entry) {
|
||||||
|
g_autofree char *escapedDeviceId = virStringReplace(entry->data->InstanceID, "\\", "\\\\");
|
||||||
|
g_autofree char *expectedSuffix = g_strdup_printf("%s\"", escapedDeviceId);
|
||||||
|
|
||||||
|
if (g_str_has_suffix(parentDeviceId, expectedSuffix)) {
|
||||||
|
*out = entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*out)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Failed to locate parent device with ID '%s'"),
|
||||||
|
parentDeviceId);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Functions for deserializing device entries
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
hypervDomainDefAppendController(virDomainDefPtr def,
|
||||||
|
int idx,
|
||||||
|
virDomainControllerType controllerType)
|
||||||
|
{
|
||||||
|
virDomainControllerDefPtr controller = NULL;
|
||||||
|
|
||||||
|
if (!(controller = virDomainControllerDefNew(controllerType)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
controller->idx = idx;
|
||||||
|
|
||||||
|
if (VIR_APPEND_ELEMENT(def->controllers, def->ncontrollers, controller) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervDomainDefAppendIDEController(virDomainDefPtr def)
|
||||||
|
{
|
||||||
|
return hypervDomainDefAppendController(def, 0, VIR_DOMAIN_CONTROLLER_TYPE_IDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervDomainDefAppendSCSIController(virDomainDefPtr def, int idx)
|
||||||
|
{
|
||||||
|
return hypervDomainDefAppendController(def, idx, VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervDomainDefAppendDisk(virDomainDefPtr def,
|
||||||
|
virDomainDiskDefPtr disk,
|
||||||
|
virDomainDiskBus busType,
|
||||||
|
int diskNameOffset,
|
||||||
|
const char *diskNamePrefix,
|
||||||
|
int maxControllers,
|
||||||
|
Msvm_ResourceAllocationSettingData **controllers,
|
||||||
|
Msvm_ResourceAllocationSettingData *diskParent,
|
||||||
|
Msvm_ResourceAllocationSettingData *diskController)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
int ctrlr_idx = -1;
|
||||||
|
int addr = -1;
|
||||||
|
|
||||||
|
if (virStrToLong_i(diskParent->data->AddressOnParent, NULL, 10, &addr) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (addr < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Find controller index */
|
||||||
|
for (i = 0; i < maxControllers; i++) {
|
||||||
|
if (diskController == controllers[i]) {
|
||||||
|
ctrlr_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctrlr_idx < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not find controller for disk!"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
disk->bus = busType;
|
||||||
|
disk->dst = virIndexToDiskName(ctrlr_idx * diskNameOffset + addr, diskNamePrefix);
|
||||||
|
if (busType == VIR_DOMAIN_DISK_BUS_IDE) {
|
||||||
|
disk->info.addr.drive.controller = 0;
|
||||||
|
disk->info.addr.drive.bus = ctrlr_idx;
|
||||||
|
} else {
|
||||||
|
disk->info.addr.drive.controller = ctrlr_idx;
|
||||||
|
disk->info.addr.drive.bus = 0;
|
||||||
|
}
|
||||||
|
disk->info.addr.drive.target = 0;
|
||||||
|
disk->info.addr.drive.unit = addr;
|
||||||
|
|
||||||
|
if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervDomainDefParseFloppyStorageExtent(virDomainDefPtr def, virDomainDiskDefPtr disk)
|
||||||
|
{
|
||||||
|
disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
|
||||||
|
disk->dst = g_strdup("fda");
|
||||||
|
|
||||||
|
if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervDomainDefParseVirtualExtent(hypervPrivate *priv,
|
||||||
|
virDomainDefPtr def,
|
||||||
|
Msvm_StorageAllocationSettingData *disk_entry,
|
||||||
|
Msvm_ResourceAllocationSettingData *rasd,
|
||||||
|
Msvm_ResourceAllocationSettingData **ideChannels,
|
||||||
|
Msvm_ResourceAllocationSettingData **scsiControllers)
|
||||||
|
{
|
||||||
|
Msvm_ResourceAllocationSettingData *diskParent = NULL;
|
||||||
|
Msvm_ResourceAllocationSettingData *controller = NULL;
|
||||||
|
virDomainDiskDefPtr disk = NULL;
|
||||||
|
int result = -1;
|
||||||
|
|
||||||
|
if (disk_entry->data->HostResource.count < 1)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(disk = virDomainDiskDefNew(priv->xmlopt))) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not allocate disk definition"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get disk associated with storage extent */
|
||||||
|
if (hypervGetDeviceParentRasdFromDeviceId(disk_entry->data->Parent, rasd, &diskParent) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* get associated controller */
|
||||||
|
if (hypervGetDeviceParentRasdFromDeviceId(diskParent->data->Parent, rasd, &controller) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* common fields first */
|
||||||
|
disk->src->type = VIR_STORAGE_TYPE_FILE;
|
||||||
|
disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
|
||||||
|
|
||||||
|
/* note if it's a CDROM disk */
|
||||||
|
if (STREQ(disk_entry->data->ResourceSubType, "Microsoft:Hyper-V:Virtual CD/DVD Disk"))
|
||||||
|
disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
|
||||||
|
else
|
||||||
|
disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
|
||||||
|
|
||||||
|
/* copy in the source path */
|
||||||
|
virDomainDiskSetSource(disk, *(char **)disk_entry->data->HostResource.data);
|
||||||
|
|
||||||
|
/* controller-specific fields */
|
||||||
|
if (controller->data->ResourceType == MSVM_RASD_RESOURCETYPE_PARALLEL_SCSI_HBA) {
|
||||||
|
if (hypervDomainDefAppendDisk(def, disk, VIR_DOMAIN_DISK_BUS_SCSI,
|
||||||
|
64, "sd", HYPERV_MAX_SCSI_CONTROLLERS,
|
||||||
|
scsiControllers, diskParent, controller) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else if (controller->data->ResourceType == MSVM_RASD_RESOURCETYPE_IDE_CONTROLLER) {
|
||||||
|
if (hypervDomainDefAppendDisk(def, disk, VIR_DOMAIN_DISK_BUS_IDE,
|
||||||
|
2, "hd", HYPERV_MAX_IDE_CHANNELS,
|
||||||
|
ideChannels, diskParent, controller) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else if (controller->data->ResourceType == MSVM_RASD_RESOURCETYPE_OTHER &&
|
||||||
|
diskParent->data->ResourceType == MSVM_RASD_RESOURCETYPE_DISKETTE_DRIVE) {
|
||||||
|
if (hypervDomainDefParseFloppyStorageExtent(def, disk) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
|
||||||
|
} else {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Unrecognized controller type %d"),
|
||||||
|
controller->data->ResourceType);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (result != 0 && disk)
|
||||||
|
virDomainDiskDefFree(disk);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervDomainDefParsePhysicalDisk(hypervPrivate *priv,
|
||||||
|
virDomainDefPtr def,
|
||||||
|
Msvm_ResourceAllocationSettingData *entry,
|
||||||
|
Msvm_ResourceAllocationSettingData *rasd,
|
||||||
|
Msvm_ResourceAllocationSettingData **ideChannels,
|
||||||
|
Msvm_ResourceAllocationSettingData **scsiControllers)
|
||||||
|
{
|
||||||
|
int result = -1;
|
||||||
|
Msvm_ResourceAllocationSettingData *controller = NULL;
|
||||||
|
Msvm_DiskDrive *diskdrive = NULL;
|
||||||
|
virDomainDiskDefPtr disk = NULL;
|
||||||
|
char **hostResource = entry->data->HostResource.data;
|
||||||
|
g_autofree char *hostEscaped = NULL;
|
||||||
|
g_autofree char *driveNumberStr = NULL;
|
||||||
|
g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER;
|
||||||
|
int addr = -1, ctrlr_idx = -1;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
if (virStrToLong_i(entry->data->AddressOnParent, NULL, 10, &addr) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (addr < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (hypervGetDeviceParentRasdFromDeviceId(entry->data->Parent, rasd, &controller) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* create disk definition */
|
||||||
|
if (!(disk = virDomainDiskDefNew(priv->xmlopt))) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not allocate disk def"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Query Msvm_DiskDrive for the DriveNumber */
|
||||||
|
hostEscaped = virStringReplace(*hostResource, "\\\"", "\"");
|
||||||
|
hostEscaped = virStringReplace(hostEscaped, "\\", "\\\\");
|
||||||
|
|
||||||
|
/* quotes must be preserved, so virBufferEscapeSQL can't be used */
|
||||||
|
virBufferAsprintf(&query,
|
||||||
|
MSVM_DISKDRIVE_WQL_SELECT "WHERE __PATH='%s'",
|
||||||
|
hostEscaped);
|
||||||
|
|
||||||
|
if (hypervGetWmiClass(Msvm_DiskDrive, &diskdrive) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!diskdrive) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not find Msvm_DiskDrive object"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
driveNumberStr = g_strdup_printf("%u", diskdrive->data->DriveNumber);
|
||||||
|
virDomainDiskSetSource(disk, driveNumberStr);
|
||||||
|
|
||||||
|
if (addr < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (controller->data->ResourceType == MSVM_RASD_RESOURCETYPE_PARALLEL_SCSI_HBA) {
|
||||||
|
for (i = 0; i < HYPERV_MAX_SCSI_CONTROLLERS; i++) {
|
||||||
|
if (controller == scsiControllers[i]) {
|
||||||
|
ctrlr_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
|
||||||
|
disk->dst = virIndexToDiskName(ctrlr_idx * 64 + addr, "sd");
|
||||||
|
disk->info.addr.drive.unit = addr;
|
||||||
|
disk->info.addr.drive.controller = ctrlr_idx;
|
||||||
|
disk->info.addr.drive.bus = 0;
|
||||||
|
} else if (controller->data->ResourceType == MSVM_RASD_RESOURCETYPE_IDE_CONTROLLER) {
|
||||||
|
for (i = 0; i < HYPERV_MAX_IDE_CHANNELS; i++) {
|
||||||
|
if (controller == ideChannels[i]) {
|
||||||
|
ctrlr_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
|
||||||
|
disk->dst = virIndexToDiskName(ctrlr_idx * 4 + addr, "hd");
|
||||||
|
disk->info.addr.drive.unit = addr;
|
||||||
|
disk->info.addr.drive.controller = 0;
|
||||||
|
disk->info.addr.drive.bus = ctrlr_idx;
|
||||||
|
} else {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid controller type for LUN"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
disk->info.addr.drive.target = 0;
|
||||||
|
virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK);
|
||||||
|
disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
|
||||||
|
|
||||||
|
disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
|
||||||
|
|
||||||
|
if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (result != 0 && disk)
|
||||||
|
virDomainDiskDefFree(disk);
|
||||||
|
hypervFreeObject(priv, (hypervObject *)diskdrive);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
hypervDomainDefParseStorage(hypervPrivate *priv,
|
||||||
|
virDomainDefPtr def,
|
||||||
|
Msvm_ResourceAllocationSettingData *rasd,
|
||||||
|
Msvm_StorageAllocationSettingData *sasd)
|
||||||
|
{
|
||||||
|
Msvm_ResourceAllocationSettingData *entry = rasd;
|
||||||
|
Msvm_StorageAllocationSettingData *disk_entry = sasd;
|
||||||
|
Msvm_ResourceAllocationSettingData *ideChannels[HYPERV_MAX_IDE_CHANNELS];
|
||||||
|
Msvm_ResourceAllocationSettingData *scsiControllers[HYPERV_MAX_SCSI_CONTROLLERS];
|
||||||
|
bool hasIdeController = false;
|
||||||
|
int channel = -1;
|
||||||
|
int scsi_idx = 0;
|
||||||
|
|
||||||
|
/* first pass: populate storage controllers */
|
||||||
|
while (entry) {
|
||||||
|
if (entry->data->ResourceType == MSVM_RASD_RESOURCETYPE_IDE_CONTROLLER) {
|
||||||
|
channel = entry->data->Address[0] - '0';
|
||||||
|
ideChannels[channel] = entry;
|
||||||
|
if (!hasIdeController) {
|
||||||
|
/* Hyper-V represents its PIIX4 controller's two channels as separate objects. */
|
||||||
|
if (hypervDomainDefAppendIDEController(def) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not add IDE controller"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
hasIdeController = true;
|
||||||
|
}
|
||||||
|
} else if (entry->data->ResourceType == MSVM_RASD_RESOURCETYPE_PARALLEL_SCSI_HBA) {
|
||||||
|
scsiControllers[scsi_idx++] = entry;
|
||||||
|
if (hypervDomainDefAppendSCSIController(def, scsi_idx - 1) < 0) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not parse SCSI controller"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* second pass: populate physical disks */
|
||||||
|
entry = rasd;
|
||||||
|
while (entry) {
|
||||||
|
if (entry->data->ResourceType == MSVM_RASD_RESOURCETYPE_DISK_DRIVE &&
|
||||||
|
entry->data->HostResource.count > 0) {
|
||||||
|
char **hostResource = entry->data->HostResource.data;
|
||||||
|
|
||||||
|
if (strstr(*hostResource, "NODRIVE")) {
|
||||||
|
/* Hyper-V doesn't let you define LUNs with no connection */
|
||||||
|
VIR_DEBUG("Skipping empty LUN '%s'", *hostResource);
|
||||||
|
entry = entry->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hypervDomainDefParsePhysicalDisk(priv, def, entry, rasd,
|
||||||
|
ideChannels, scsiControllers) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* third pass: populate virtual disks */
|
||||||
|
while (disk_entry) {
|
||||||
|
if (hypervDomainDefParseVirtualExtent(priv, def, disk_entry, rasd,
|
||||||
|
ideChannels, scsiControllers) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
disk_entry = disk_entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Driver functions
|
* Driver functions
|
||||||
*/
|
*/
|
||||||
@ -1249,6 +1643,8 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
|
Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
|
||||||
Msvm_ProcessorSettingData *processorSettingData = NULL;
|
Msvm_ProcessorSettingData *processorSettingData = NULL;
|
||||||
Msvm_MemorySettingData *memorySettingData = NULL;
|
Msvm_MemorySettingData *memorySettingData = NULL;
|
||||||
|
Msvm_ResourceAllocationSettingData *rasd = NULL;
|
||||||
|
Msvm_StorageAllocationSettingData *sasd = NULL;
|
||||||
|
|
||||||
virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
|
virCheckFlags(VIR_DOMAIN_XML_COMMON_FLAGS, NULL);
|
||||||
|
|
||||||
@ -1275,6 +1671,18 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
&memorySettingData) < 0)
|
&memorySettingData) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
if (hypervGetResourceAllocationSD(priv,
|
||||||
|
virtualSystemSettingData->data->InstanceID,
|
||||||
|
&rasd) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hypervGetStorageAllocationSD(priv,
|
||||||
|
virtualSystemSettingData->data->InstanceID,
|
||||||
|
&sasd) < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill struct */
|
/* Fill struct */
|
||||||
def->virtType = VIR_DOMAIN_VIRT_HYPERV;
|
def->virtType = VIR_DOMAIN_VIRT_HYPERV;
|
||||||
|
|
||||||
@ -1324,7 +1732,20 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
|
|
||||||
def->os.type = VIR_DOMAIN_OSTYPE_HVM;
|
def->os.type = VIR_DOMAIN_OSTYPE_HVM;
|
||||||
|
|
||||||
/* FIXME: devices section is totally missing */
|
/* Allocate space for all potential devices */
|
||||||
|
|
||||||
|
/* 256 scsi drives + 4 ide drives */
|
||||||
|
def->disks = g_new0(virDomainDiskDefPtr,
|
||||||
|
HYPERV_MAX_SCSI_CONTROLLERS * HYPERV_MAX_DRIVES_PER_SCSI_CONTROLLER +
|
||||||
|
HYPERV_MAX_IDE_CHANNELS * HYPERV_MAX_DRIVES_PER_IDE_CHANNEL);
|
||||||
|
def->ndisks = 0;
|
||||||
|
|
||||||
|
/* 1 ide & 4 scsi controllers */
|
||||||
|
def->controllers = g_new0(virDomainControllerDefPtr, 5);
|
||||||
|
def->ncontrollers = 0;
|
||||||
|
|
||||||
|
if (hypervDomainDefParseStorage(priv, def, rasd, sasd) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* XXX xmlopts must be non-NULL */
|
/* XXX xmlopts must be non-NULL */
|
||||||
xml = virDomainDefFormat(def, NULL,
|
xml = virDomainDefFormat(def, NULL,
|
||||||
@ -1336,6 +1757,8 @@ hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
|
|||||||
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
|
hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
|
||||||
hypervFreeObject(priv, (hypervObject *)processorSettingData);
|
hypervFreeObject(priv, (hypervObject *)processorSettingData);
|
||||||
hypervFreeObject(priv, (hypervObject *)memorySettingData);
|
hypervFreeObject(priv, (hypervObject *)memorySettingData);
|
||||||
|
hypervFreeObject(priv, (hypervObject *)rasd);
|
||||||
|
hypervFreeObject(priv, (hypervObject *)sasd);
|
||||||
|
|
||||||
return xml;
|
return xml;
|
||||||
}
|
}
|
||||||
|
@ -22,4 +22,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#define HYPERV_MAX_SCSI_CONTROLLERS 4
|
||||||
|
#define HYPERV_MAX_DRIVES_PER_SCSI_CONTROLLER 64
|
||||||
|
#define HYPERV_MAX_IDE_CHANNELS 2
|
||||||
|
#define HYPERV_MAX_DRIVES_PER_IDE_CHANNEL 2
|
||||||
|
|
||||||
int hypervRegister(void);
|
int hypervRegister(void);
|
||||||
|
@ -28,10 +28,12 @@
|
|||||||
#include "virerror.h"
|
#include "virerror.h"
|
||||||
#include "hyperv_util.h"
|
#include "hyperv_util.h"
|
||||||
#include "capabilities.h"
|
#include "capabilities.h"
|
||||||
|
#include "domain_conf.h"
|
||||||
|
|
||||||
typedef struct _hypervPrivate hypervPrivate;
|
typedef struct _hypervPrivate hypervPrivate;
|
||||||
struct _hypervPrivate {
|
struct _hypervPrivate {
|
||||||
hypervParsedUri *parsedUri;
|
hypervParsedUri *parsedUri;
|
||||||
WsManClient *client;
|
WsManClient *client;
|
||||||
virCapsPtr caps;
|
virCapsPtr caps;
|
||||||
|
virDomainXMLOptionPtr xmlopt;
|
||||||
};
|
};
|
||||||
|
@ -1490,6 +1490,32 @@ hypervGetMsvmVirtualSystemSettingDataFromUUID(hypervPrivate *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetResourceAllocationSD(hypervPrivate *priv,
|
||||||
|
const char *id,
|
||||||
|
Msvm_ResourceAllocationSettingData **data)
|
||||||
|
{
|
||||||
|
g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER;
|
||||||
|
virBufferEscapeSQL(&query,
|
||||||
|
"ASSOCIATORS OF {Msvm_VirtualSystemSettingData.InstanceID='%s'} "
|
||||||
|
"WHERE AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
||||||
|
"ResultClass = Msvm_ResourceAllocationSettingData",
|
||||||
|
id);
|
||||||
|
|
||||||
|
if (hypervGetWmiClass(Msvm_ResourceAllocationSettingData, data) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!*data) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Could not look up resource allocation setting data with virtual system instance ID '%s'"),
|
||||||
|
id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
hypervGetProcessorSD(hypervPrivate *priv,
|
hypervGetProcessorSD(hypervPrivate *priv,
|
||||||
const char *id,
|
const char *id,
|
||||||
@ -1536,6 +1562,25 @@ hypervGetMemorySD(hypervPrivate *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
hypervGetStorageAllocationSD(hypervPrivate *priv,
|
||||||
|
const char *id,
|
||||||
|
Msvm_StorageAllocationSettingData **data)
|
||||||
|
{
|
||||||
|
g_auto(virBuffer) query = VIR_BUFFER_INITIALIZER;
|
||||||
|
virBufferEscapeSQL(&query,
|
||||||
|
"ASSOCIATORS OF {Msvm_VirtualSystemSettingData.InstanceID='%s'} "
|
||||||
|
"WHERE AssocClass = Msvm_VirtualSystemSettingDataComponent "
|
||||||
|
"ResultClass = Msvm_StorageAllocationSettingData",
|
||||||
|
id);
|
||||||
|
|
||||||
|
if (hypervGetWmiClass(Msvm_StorageAllocationSettingData, data) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* Msvm_VirtualSystemManagementService
|
* Msvm_VirtualSystemManagementService
|
||||||
*/
|
*/
|
||||||
|
@ -236,6 +236,10 @@ int hypervGetMsvmVirtualSystemSettingDataFromUUID(hypervPrivate *priv,
|
|||||||
const char *uuid_string,
|
const char *uuid_string,
|
||||||
Msvm_VirtualSystemSettingData **list);
|
Msvm_VirtualSystemSettingData **list);
|
||||||
|
|
||||||
|
int hypervGetResourceAllocationSD(hypervPrivate *priv,
|
||||||
|
const char *id,
|
||||||
|
Msvm_ResourceAllocationSettingData **data);
|
||||||
|
|
||||||
int hypervGetProcessorSD(hypervPrivate *priv,
|
int hypervGetProcessorSD(hypervPrivate *priv,
|
||||||
const char *id,
|
const char *id,
|
||||||
Msvm_ProcessorSettingData **data);
|
Msvm_ProcessorSettingData **data);
|
||||||
@ -244,6 +248,10 @@ int hypervGetMemorySD(hypervPrivate *priv,
|
|||||||
const char *vssd_instanceid,
|
const char *vssd_instanceid,
|
||||||
Msvm_MemorySettingData **list);
|
Msvm_MemorySettingData **list);
|
||||||
|
|
||||||
|
int hypervGetStorageAllocationSD(hypervPrivate *priv,
|
||||||
|
const char *id,
|
||||||
|
Msvm_StorageAllocationSettingData **data);
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* Msvm_VirtualSystemManagementService
|
* Msvm_VirtualSystemManagementService
|
||||||
*/
|
*/
|
||||||
|
@ -98,6 +98,25 @@ enum _Msvm_ConcreteJob_JobState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* Msvm_ResourceAllocationSettingData
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* https://docs.microsoft.com/en-us/windows/win32/hyperv_v2/msvm-resourceallocationsettingdata */
|
||||||
|
enum _Msvm_ResourceAllocationSettingData_ResourceType {
|
||||||
|
MSVM_RASD_RESOURCETYPE_OTHER = 1,
|
||||||
|
MSVM_RASD_RESOURCETYPE_IDE_CONTROLLER = 5,
|
||||||
|
MSVM_RASD_RESOURCETYPE_PARALLEL_SCSI_HBA = 6,
|
||||||
|
MSVM_RASD_RESOURCETYPE_DISKETTE_DRIVE = 14,
|
||||||
|
MSVM_RASD_RESOURCETYPE_CD_DRIVE = 15,
|
||||||
|
MSVM_RASD_RESOURCETYPE_DVD_DRIVE = 16,
|
||||||
|
MSVM_RASD_RESOURCETYPE_DISK_DRIVE = 17,
|
||||||
|
MSVM_RASD_RESOURCETYPE_STORAGE_EXTENT = 19,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* WMI
|
* WMI
|
||||||
*/
|
*/
|
||||||
|
@ -601,6 +601,34 @@ class Msvm_VirtualSystemManagementService
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class Msvm_ResourceAllocationSettingData
|
||||||
|
string InstanceID
|
||||||
|
string Caption
|
||||||
|
string Description
|
||||||
|
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 AddressOnParent
|
||||||
|
string VirtualQuantityUnits
|
||||||
|
string VirtualSystemIdentifiers[]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
class Msvm_Keyboard
|
class Msvm_Keyboard
|
||||||
string InstanceID
|
string InstanceID
|
||||||
string Caption
|
string Caption
|
||||||
@ -688,3 +716,109 @@ class Msvm_ShutdownComponent
|
|||||||
uint16 AdditionalAvailability[]
|
uint16 AdditionalAvailability[]
|
||||||
uint64 MaxQuiesceTime
|
uint64 MaxQuiesceTime
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class Msvm_DiskDrive
|
||||||
|
string InstanceID
|
||||||
|
string Caption
|
||||||
|
string Description
|
||||||
|
string ElementName
|
||||||
|
datetime InstallDate
|
||||||
|
string Name
|
||||||
|
uint16 OperationalStatus[]
|
||||||
|
string StatusDescriptions[]
|
||||||
|
string Status
|
||||||
|
uint16 HealthState
|
||||||
|
uint16 CommunicationStatus
|
||||||
|
uint16 DetailedStatus
|
||||||
|
uint16 OperatingStatus
|
||||||
|
uint16 PrimaryStatus
|
||||||
|
uint16 EnabledState
|
||||||
|
string OtherEnabledState
|
||||||
|
uint16 RequestedState
|
||||||
|
uint16 EnabledDefault
|
||||||
|
datetime TimeOfLastStateChange
|
||||||
|
uint16 AvailableRequestedStates[]
|
||||||
|
uint16 TransitioningToState
|
||||||
|
string SystemCreationClassName
|
||||||
|
string SystemName
|
||||||
|
string CreationClassName
|
||||||
|
string DeviceID
|
||||||
|
boolean PowerManagementSupported
|
||||||
|
uint16 PowerManagementCapabilities[]
|
||||||
|
uint16 Availability
|
||||||
|
uint16 StatusInfo
|
||||||
|
uint32 LastErrorCode
|
||||||
|
string ErrorDescription
|
||||||
|
boolean ErrorCleared
|
||||||
|
string OtherIdentifyingInfo[]
|
||||||
|
uint64 PowerOnHours
|
||||||
|
uint64 TotalPowerOnHours
|
||||||
|
string IdentifyingDescriptions[]
|
||||||
|
uint16 AdditionalAvailability[]
|
||||||
|
uint64 MaxQuiesceTime
|
||||||
|
uint16 Capabilities[]
|
||||||
|
string CapabilityDescriptions[]
|
||||||
|
string ErrorMethodology
|
||||||
|
string CompressionMethod
|
||||||
|
uint32 NumberOfMediaSupported
|
||||||
|
uint64 MaxMediaSize
|
||||||
|
uint64 DefaultBlockSize
|
||||||
|
uint64 MaxBlockSize
|
||||||
|
uint64 MinBlockSize
|
||||||
|
boolean NeedsCleaning
|
||||||
|
boolean MediaIsLocked
|
||||||
|
uint16 Security
|
||||||
|
datetime LastCleaned
|
||||||
|
uint64 MaxAccessTime
|
||||||
|
uint32 UncompressedDataRate
|
||||||
|
uint64 LoadTime
|
||||||
|
uint64 UnloadTime
|
||||||
|
uint64 MountCount
|
||||||
|
datetime TimeOfLastMount
|
||||||
|
uint64 TotalMountTime
|
||||||
|
string UnitsDescription
|
||||||
|
uint64 MaxUnitsBeforeCleaning
|
||||||
|
uint64 UnitsUsed
|
||||||
|
uint32 DriveNumber
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
class Msvm_StorageAllocationSettingData
|
||||||
|
string InstanceID
|
||||||
|
string Caption
|
||||||
|
string Description
|
||||||
|
string ElementName
|
||||||
|
uint16 ResourceType
|
||||||
|
string OtherResourceType
|
||||||
|
string ResourceSubType
|
||||||
|
string PoolID
|
||||||
|
uint16 ConsumerVisibility
|
||||||
|
string HostResource[]
|
||||||
|
string AllocationUnits
|
||||||
|
uint64 VirtualQuantity
|
||||||
|
uint64 Limit
|
||||||
|
uint32 Weight
|
||||||
|
boolean AutomaticAllocation
|
||||||
|
boolean AutomaticDeallocation
|
||||||
|
string Parent
|
||||||
|
string Connection[]
|
||||||
|
string Address
|
||||||
|
uint16 MappingBehavior
|
||||||
|
string AddressOnParent
|
||||||
|
uint64 VirtualResourceBlockSize
|
||||||
|
string VirtualQuantityUnits
|
||||||
|
uint16 Access
|
||||||
|
uint64 HostResourceBlockSize
|
||||||
|
uint64 Reservation
|
||||||
|
uint64 HostExtentStartingAddress
|
||||||
|
string HostExtentName
|
||||||
|
uint16 HostExtentNameFormat
|
||||||
|
string OtherHostExtentNameFormat
|
||||||
|
uint16 HostExtentNameNamespace
|
||||||
|
string OtherHostExtentNameNamespace
|
||||||
|
uint64 IOPSLimit
|
||||||
|
uint64 IOPSReservation
|
||||||
|
string IOPSAllocationUnits
|
||||||
|
boolean PersistentReservationsSupported
|
||||||
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user