diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in index 88c70bc9672b013b73b7492b88e071d5d91d292a..e8cee77ae5ccbfded89f418afb236341d230212c 100644 --- a/docs/drvesx.html.in +++ b/docs/drvesx.html.in @@ -292,6 +292,15 @@ ethernet0.checkMACAddress = "false"

SCSI controller models

+
auto
+
+ This isn't a actual controller model. If specified the ESX driver + tries to detect the SCSI controller model referenced in the + .vmdk file and use it. Autodetection fails when a + SCSI controller has multiple disks attached and the SCSI controller + models referenced in the .vmdk files are inconsistent. + Since 0.8.3 +
buslogic
BusLogic SCSI controller for older guests. diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 9289c8f9e407d8c7ea13a9101ba8a4ebcdc87e26..2d22ce4028d3bb345974d81cc3a41cd17b146f7b 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -676,6 +676,7 @@ + auto buslogic lsilogic lsisas1068 diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b52656166c0b0d682bd2e3e96132cf3a21040998..5b59c0143a9fb76192e71efdf123c64709730563 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -141,6 +141,7 @@ VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST, "virtio-serial") VIR_ENUM_IMPL(virDomainControllerModel, VIR_DOMAIN_CONTROLLER_MODEL_LAST, + "auto", "buslogic", "lsilogic", "lsisas1068", diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 2a60515a45e5bb6db5ee6aec338c6fbb003bd795..9ef687b4c38755819911e79639d781f66a7f676f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -196,6 +196,7 @@ enum virDomainControllerType { enum virDomainControllerModel { + VIR_DOMAIN_CONTROLLER_MODEL_AUTO, VIR_DOMAIN_CONTROLLER_MODEL_BUSLOGIC, VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC, VIR_DOMAIN_CONTROLLER_MODEL_LSISAS1068, diff --git a/src/esx/esx_vi_generator.input b/src/esx/esx_vi_generator.input index ff651780797d41928ca05b34f7b812d9a3a7a4d1..b4b33f6aa16baf218cc8c94c4b473adc59497b35 100644 --- a/src/esx/esx_vi_generator.input +++ b/src/esx/esx_vi_generator.input @@ -184,6 +184,40 @@ object Event end +object FileInfo + String path r + Long fileSize o + DateTime modification o +end + + +object FileQuery +end + + +object FileQueryFlags + Boolean fileType r + Boolean fileSize r + Boolean modification r +end + + +object FloppyImageFileInfo extends FileInfo +end + + +object FloppyImageFileQuery extends FileQuery +end + + +object FolderFileInfo extends FileInfo +end + + +object FolderFileQuery extends FileQuery +end + + object HostCpuIdInfo Int level r String vendor o @@ -194,6 +228,22 @@ object HostCpuIdInfo end +object HostDatastoreBrowserSearchResults + ManagedObjectReference datastore o + String folderPath o + FileInfo file ol +end + + +object HostDatastoreBrowserSearchSpec + FileQuery query ol + FileQueryFlags details o + Boolean searchCaseInsensitive o + String matchPattern ol + Boolean sortFoldersFirst o +end + + object HostFileSystemVolume String type r String name r @@ -225,6 +275,14 @@ object HostVmfsVolume extends HostFileSystemVolume end +object IsoImageFileInfo extends FileInfo +end + + +object IsoImageFileQuery extends FileQuery +end + + object LocalDatastoreInfo extends DatastoreInfo String path o end @@ -424,6 +482,14 @@ object TaskInfo end +object TemplateConfigFileInfo extends VmConfigFileInfo +end + + +object TemplateConfigFileQuery extends VmConfigFileQuery +end + + object TraversalSpec extends SelectionSpec String type r String path r @@ -502,6 +568,82 @@ object VirtualMachineSnapshotTree end +object VmConfigFileInfo extends FileInfo + Int configVersion o +end + + +object VmConfigFileQuery extends FileQuery + VmConfigFileQueryFilter filter o + VmConfigFileQueryFlags details o +end + + +object VmConfigFileQueryFilter + Int matchConfigVersion ol +end + + +object VmConfigFileQueryFlags + Boolean configVersion r +end + + +object VmDiskFileInfo extends FileInfo + String diskType o + Long capacityKb o + Int hardwareVersion o + String controllerType o + String diskExtents ol +end + + +object VmDiskFileQuery extends FileQuery + VmDiskFileQueryFilter filter o + VmDiskFileQueryFlags details o +end + + +object VmDiskFileQueryFilter + String diskType ol + Int matchHardwareVersion ol + String controllerType ol +end + + +object VmDiskFileQueryFlags + Boolean diskType r + Boolean capacityKb r + Boolean hardwareVersion r + Boolean controllerType o + Boolean diskExtents o +end + + +object VmLogFileInfo extends FileInfo +end + + +object VmLogFileQuery extends FileQuery +end + + +object VmNvramFileInfo extends FileInfo +end + + +object VmNvramFileQuery extends FileQuery +end + + +object VmSnapshotFileInfo extends FileInfo +end + + +object VmSnapshotFileQuery extends FileQuery +end + + object VmfsDatastoreInfo extends DatastoreInfo HostVmfsVolume vmfs o end @@ -658,6 +800,13 @@ method RevertToSnapshot_Task returns ManagedObjectReference r end +method SearchDatastore_Task returns ManagedObjectReference r + ManagedObjectReference _this r + String datastorePath r + HostDatastoreBrowserSearchSpec searchSpec o +end + + method SessionIsActive returns Boolean r ManagedObjectReference _this:SessionManager r String sessionID r diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py index ff3e3d1d69cd38e021d22766cae0d85f45cc8e64..82bc9b6fbdb5eb6593e732eeff6a7863abbf66b3 100755 --- a/src/esx/esx_vi_generator.py +++ b/src/esx/esx_vi_generator.py @@ -1123,7 +1123,10 @@ additional_enum_features = { "ManagedEntityStatus" : Enum.FEATURE__ANY_TYPE additional_object_features = { "DatastoreInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__DYNAMIC_CAST, "Event" : Object.FEATURE__LIST, + "FileInfo" : Object.FEATURE__DYNAMIC_CAST, + "FileQuery" : Object.FEATURE__DYNAMIC_CAST, "HostCpuIdInfo" : Object.FEATURE__ANY_TYPE | Object.FEATURE__LIST, + "HostDatastoreBrowserSearchResults" : Object.FEATURE__ANY_TYPE, "ManagedObjectReference" : Object.FEATURE__ANY_TYPE, "ObjectContent" : Object.FEATURE__DEEP_COPY | Object.FEATURE__LIST, "PerfCounterInfo" : Object.FEATURE__LIST, diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c index c69e116d295971d192905e94e75fcdd85ebbac9f..9035233b9103b9716120eb0fa25dbc90e1a1a591 100644 --- a/src/esx/esx_vmx.c +++ b/src/esx/esx_vmx.c @@ -29,6 +29,7 @@ #include "virterror_internal.h" #include "memory.h" #include "logging.h" +#include "esx_vi_methods.h" #include "esx_private.h" #include "esx_util.h" #include "esx_vmx.h" @@ -433,6 +434,7 @@ def->parallels[0]... * are actually SCSI controller models in the ESX case */ VIR_ENUM_DECL(esxVMX_SCSIControllerModel) VIR_ENUM_IMPL(esxVMX_SCSIControllerModel, VIR_DOMAIN_CONTROLLER_MODEL_LAST, + "auto", /* just to match virDomainControllerModel, will never be used */ "buslogic", "lsilogic", "lsisas1068", @@ -716,34 +718,244 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def, int -esxVMX_GatherSCSIControllers(virDomainDefPtr def, int virtualDev[4], - bool present[4]) +esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx, + virDomainDiskDefPtr def, int *model) { - int i; + int result = -1; + char *datastoreName = NULL; + char *directoryName = NULL; + char *fileName = NULL; + char *datastorePath = NULL; + esxVI_String *propertyNameList = NULL; + esxVI_ObjectContent *datastore = NULL; + esxVI_ManagedObjectReference *hostDatastoreBrowser = NULL; + esxVI_HostDatastoreBrowserSearchSpec *searchSpec = NULL; + esxVI_VmDiskFileQuery *vmDiskFileQuery = NULL; + esxVI_ManagedObjectReference *task = NULL; + esxVI_TaskInfoState taskInfoState; + esxVI_TaskInfo *taskInfo = NULL; + esxVI_HostDatastoreBrowserSearchResults *searchResults = NULL; + esxVI_VmDiskFileInfo *vmDiskFileInfo = NULL; + + if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK || + def->bus != VIR_DOMAIN_DISK_BUS_SCSI || + def->type != VIR_DOMAIN_DISK_TYPE_FILE || + def->src == NULL || + ! STRPREFIX(def->src, "[")) { + /* + * This isn't a file-based SCSI disk device with a datastore related + * source path => do nothing. + */ + return 0; + } + + if (esxUtil_ParseDatastoreRelatedPath(def->src, &datastoreName, + &directoryName, &fileName) < 0) { + goto cleanup; + } + + if (directoryName == NULL) { + if (virAsprintf(&datastorePath, "[%s]", datastoreName) < 0) { + virReportOOMError(); + goto cleanup; + } + } else { + if (virAsprintf(&datastorePath, "[%s] %s", datastoreName, + directoryName) < 0) { + virReportOOMError(); + goto cleanup; + } + } + + /* Lookup HostDatastoreBrowser */ + if (esxVI_String_AppendValueToList(&propertyNameList, "browser") < 0 || + esxVI_LookupDatastoreByName(ctx, datastoreName, propertyNameList, + &datastore, + esxVI_Occurrence_RequiredItem) < 0 || + esxVI_GetManagedObjectReference(datastore, "browser", + &hostDatastoreBrowser, + esxVI_Occurrence_RequiredItem) < 0) { + goto cleanup; + } + + /* Build HostDatastoreBrowserSearchSpec */ + if (esxVI_HostDatastoreBrowserSearchSpec_Alloc(&searchSpec) < 0 || + esxVI_FileQueryFlags_Alloc(&searchSpec->details) < 0) { + goto cleanup; + } + + searchSpec->details->fileType = esxVI_Boolean_True; + searchSpec->details->fileSize = esxVI_Boolean_False; + searchSpec->details->modification = esxVI_Boolean_False; + + if (esxVI_VmDiskFileQuery_Alloc(&vmDiskFileQuery) < 0 || + esxVI_VmDiskFileQueryFlags_Alloc(&vmDiskFileQuery->details) < 0 || + esxVI_FileQuery_AppendToList + (&searchSpec->query, + esxVI_FileQuery_DynamicCast(vmDiskFileQuery)) < 0) { + goto cleanup; + } + + vmDiskFileQuery->details->diskType = esxVI_Boolean_False; + vmDiskFileQuery->details->capacityKb = esxVI_Boolean_False; + vmDiskFileQuery->details->hardwareVersion = esxVI_Boolean_False; + vmDiskFileQuery->details->controllerType = esxVI_Boolean_True; + vmDiskFileQuery->details->diskExtents = esxVI_Boolean_False; + + if (esxVI_String_Alloc(&searchSpec->matchPattern) < 0) { + goto cleanup; + } + + searchSpec->matchPattern->value = fileName; + + /* Search datastore for file */ + if (esxVI_SearchDatastore_Task(ctx, hostDatastoreBrowser, datastorePath, + searchSpec, &task) < 0 || + esxVI_WaitForTaskCompletion(ctx, task, NULL, esxVI_Boolean_False, + &taskInfoState) < 0) { + goto cleanup; + } + + if (taskInfoState != esxVI_TaskInfoState_Success) { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Could not serach in datastore '%s'"), datastoreName); + goto cleanup; + } + + if (esxVI_LookupTaskInfoByTask(ctx, task, &taskInfo) < 0 || + esxVI_HostDatastoreBrowserSearchResults_CastFromAnyType + (taskInfo->result, &searchResults) < 0) { + goto cleanup; + } + + /* Interpret search result */ + vmDiskFileInfo = esxVI_VmDiskFileInfo_DynamicCast(searchResults->file); + + if (vmDiskFileInfo == NULL || vmDiskFileInfo->controllerType == NULL) { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Could not lookup controller model for '%s'"), def->src); + goto cleanup; + } + + if (STRCASEEQ(vmDiskFileInfo->controllerType, + "VirtualBusLogicController")) { + *model = VIR_DOMAIN_CONTROLLER_MODEL_BUSLOGIC; + } else if (STRCASEEQ(vmDiskFileInfo->controllerType, + "VirtualLsiLogicController")) { + *model = VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC; + } else if (STRCASEEQ(vmDiskFileInfo->controllerType, + "VirtualLsiLogicSASController")) { + *model = VIR_DOMAIN_CONTROLLER_MODEL_LSISAS1068; + } else if (STRCASEEQ(vmDiskFileInfo->controllerType, + "ParaVirtualSCSIController")) { + *model = VIR_DOMAIN_CONTROLLER_MODEL_VMPVSCSI; + } else { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Found unexpected controller model '%s' for disk '%s'"), + vmDiskFileInfo->controllerType, def->src); + goto cleanup; + } + + result = 0; + + cleanup: + /* Don't double free fileName */ + if (searchSpec != NULL && searchSpec->matchPattern != NULL) { + searchSpec->matchPattern->value = NULL; + } + + VIR_FREE(datastoreName); + VIR_FREE(directoryName); + VIR_FREE(fileName); + VIR_FREE(datastorePath); + esxVI_String_Free(&propertyNameList); + esxVI_ObjectContent_Free(&datastore); + esxVI_ManagedObjectReference_Free(&hostDatastoreBrowser); + esxVI_HostDatastoreBrowserSearchSpec_Free(&searchSpec); + esxVI_ManagedObjectReference_Free(&task); + esxVI_TaskInfo_Free(&taskInfo); + esxVI_HostDatastoreBrowserSearchResults_Free(&searchResults); + + return result; +} + + + +int +esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def, + int virtualDev[4], bool present[4]) +{ + int result = -1; + int i, k; virDomainDiskDefPtr disk; - virDomainControllerDefPtr controller = NULL; + virDomainControllerDefPtr controller; + bool controllerHasDisksAttached; + int count = 0; + int *autodetectedModels; - for (i = 0; i < def->ndisks; ++i) { - disk = def->disks[i]; + if (VIR_ALLOC_N(autodetectedModels, def->ndisks) < 0) { + virReportOOMError(); + return -1; + } + + for (i = 0; i < def->ncontrollers; ++i) { + controller = def->controllers[i]; - if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) { + if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { + // skip non-SCSI controllers continue; } - controller = NULL; + controllerHasDisksAttached = false; - for (i = 0; i < def->ncontrollers; ++i) { - if (def->controllers[i]->idx == disk->info.addr.drive.controller) { - controller = def->controllers[i]; + for (k = 0; k < def->ndisks; ++k) { + disk = def->disks[k]; + + if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI && + disk->info.addr.drive.controller == controller->idx) { + controllerHasDisksAttached = true; break; } } - if (controller == NULL) { - ESX_ERROR(VIR_ERR_INTERNAL_ERROR, - _("Missing SCSI controller for index %d"), - disk->info.addr.drive.controller); - return -1; + if (! controllerHasDisksAttached) { + // skip SCSI controllers without attached disks + continue; + } + + if (ctx != NULL && + controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO) { + count = 0; + + // try to autodetect the SCSI controller model by collecting + // SCSI controller model of all disks attached to this controller + for (k = 0; k < def->ndisks; ++k) { + disk = def->disks[k]; + + if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI && + disk->info.addr.drive.controller == controller->idx) { + if (esxVMX_AutodetectSCSIControllerModel + (ctx, disk, &autodetectedModels[count]) < 0) { + goto cleanup; + } + + ++count; + } + } + + // autodetection fails when the disks attached to one controller + // have inconsistent SCSI controller models + for (k = 0; k < count; ++k) { + if (autodetectedModels[k] != autodetectedModels[0]) { + ESX_ERROR(VIR_ERR_INTERNAL_ERROR, + _("Disks on SCSI controller %d have inconsistent " + "controller models, cannot autodetect model"), + controller->idx); + goto cleanup; + } + } + + controller->model = autodetectedModels[0]; } if (controller->model != -1 && @@ -756,14 +968,19 @@ esxVMX_GatherSCSIControllers(virDomainDefPtr def, int virtualDev[4], "'controller' to be 'buslogic' or 'lsilogic' or " "'lsisas1068' or 'vmpvscsi' but found '%s'"), virDomainControllerModelTypeToString(controller->model)); - return -1; + goto cleanup; } present[controller->idx] = true; virtualDev[controller->idx] = controller->model; } - return 0; + result = 0; + + cleanup: + VIR_FREE(autodetectedModels); + + return result; } @@ -2620,7 +2837,8 @@ esxVMX_FormatConfig(esxVI_Context *ctx, virCapsPtr caps, virDomainDefPtr def, } } - if (esxVMX_GatherSCSIControllers(def, scsi_virtualDev, scsi_present) < 0) { + if (esxVMX_GatherSCSIControllers(ctx, def, scsi_virtualDev, + scsi_present) < 0) { goto failure; } diff --git a/src/esx/esx_vmx.h b/src/esx/esx_vmx.h index a9015fb6b5891110554ac36455ef2588d8b1533a..3ccae7a15dc822371b513ead1bb3e232ea08e971 100644 --- a/src/esx/esx_vmx.h +++ b/src/esx/esx_vmx.h @@ -48,8 +48,12 @@ esxVMX_HandleLegacySCSIDiskDriverName(virDomainDefPtr def, virDomainDiskDefPtr disk); int -esxVMX_GatherSCSIControllers(virDomainDefPtr def, int virtualDev[4], - bool present[4]); +esxVMX_AutodetectSCSIControllerModel(esxVI_Context *ctx, + virDomainDiskDefPtr def, int *model); + +int +esxVMX_GatherSCSIControllers(esxVI_Context *ctx, virDomainDefPtr def, + int virtualDev[4], bool present[4]); char * esxVMX_AbsolutePathToDatastoreRelatedPath(esxVI_Context *ctx,