[libvirt] [PATCH] esx: Add autodetection for the SCSI controller model

This works for file-backed SCSI disk device with a datastore related source path. --- docs/drvesx.html.in | 6 ++ docs/schemas/domain.rng | 1 + src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + src/esx/esx_vi_generator.input | 149 +++++++++++++++++++++++++++++++++ src/esx/esx_vi_generator.py | 3 + src/esx/esx_vmx.c | 180 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vmx.h | 8 ++- 8 files changed, 344 insertions(+), 5 deletions(-) diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in index f4e7530..75c24cb 100644 --- a/docs/drvesx.html.in +++ b/docs/drvesx.html.in @@ -292,6 +292,12 @@ ethernet0.checkMACAddress = "false" <h4>SCSI controller models</h4> <dl> + <dt><code>auto</code></dt> + <dd> + This isn't a actual controller model. If specified the ESX driver + tries to detect the SCSI controller model referenced in the + <code>.vmdk</code> file and use it. <span class="since">Since 0.8.3</span> + </dd> <dt><code>buslogic</code></dt> <dd> BusLogic SCSI controller for older guests. diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index b171d01..e090366 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -673,6 +673,7 @@ <optional> <attribute name="model"> <choice> + <value>auto</value> <value>buslogic</value> <value>lsilogic</value> <value>lsisas1068</value> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 3cd43c4..eb7fa13 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -140,6 +140,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 3451302..890fa0b 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 ff65178..b4b33f6 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 ff3e3d1..82bc9b6 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 46875f3..f57e046 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" @@ -707,8 +708,172 @@ 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 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_PVSCSI; + } 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 i; virDomainDiskDefPtr disk; @@ -737,6 +902,14 @@ esxVMX_GatherSCSIControllers(virDomainDefPtr def, int virtualDev[4], return -1; } + if (ctx != NULL && + controller->model == VIR_DOMAIN_CONTROLLER_MODEL_AUTO) { + if (esxVMX_AutodetectSCSIControllerModel(ctx, disk, + &controller->model) < 0) { + return -1; + } + } + if (controller->model != -1 && controller->model != VIR_DOMAIN_CONTROLLER_MODEL_BUSLOGIC && controller->model != VIR_DOMAIN_CONTROLLER_MODEL_LSILOGIC && @@ -2611,7 +2784,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 a9015fb..3ccae7a 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, -- 1.7.0.4

On Tue, Jul 06, 2010 at 08:19:55PM +0200, Matthias Bolte wrote:
This works for file-backed SCSI disk device with a datastore related source path. --- docs/drvesx.html.in | 6 ++ docs/schemas/domain.rng | 1 + src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + src/esx/esx_vi_generator.input | 149 +++++++++++++++++++++++++++++++++ src/esx/esx_vi_generator.py | 3 + src/esx/esx_vmx.c | 180 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vmx.h | 8 ++- 8 files changed, 344 insertions(+), 5 deletions(-)
diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in index f4e7530..75c24cb 100644 --- a/docs/drvesx.html.in +++ b/docs/drvesx.html.in @@ -292,6 +292,12 @@ ethernet0.checkMACAddress = "false"
<h4>SCSI controller models</h4> <dl> + <dt><code>auto</code></dt> + <dd> + This isn't a actual controller model. If specified the ESX driver + tries to detect the SCSI controller model referenced in the + <code>.vmdk</code> file and use it. <span class="since">Since 0.8.3</span> + </dd> <dt><code>buslogic</code></dt> <dd> BusLogic SCSI controller for older guests. diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index b171d01..e090366 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -673,6 +673,7 @@ <optional> <attribute name="model"> <choice> + <value>auto</value> <value>buslogic</value> <value>lsilogic</value> <value>lsisas1068</value>
I don't really see how this can sensibly work. A controller can have multiple disks associated with it. Each associated disk has a drive address that uniquely identifies its position on the controller. Now consider a controller of mode 'auto' and attach two disks to it. One VMDK specifies 'lsilogic' and the other VMDK specifies 'lsisas1068'. This is not reconcilable because you have 2 conflicting controller models, but have associated both disks with the same controller object. Furthermore both disks could be LUN 1 on their respective controller, which means you'd now have a uniquness violation on the drive address. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

2010/7/7 Daniel P. Berrange <berrange@redhat.com>:
On Tue, Jul 06, 2010 at 08:19:55PM +0200, Matthias Bolte wrote:
This works for file-backed SCSI disk device with a datastore related source path. --- docs/drvesx.html.in | 6 ++ docs/schemas/domain.rng | 1 + src/conf/domain_conf.c | 1 + src/conf/domain_conf.h | 1 + src/esx/esx_vi_generator.input | 149 +++++++++++++++++++++++++++++++++ src/esx/esx_vi_generator.py | 3 + src/esx/esx_vmx.c | 180 +++++++++++++++++++++++++++++++++++++++- src/esx/esx_vmx.h | 8 ++- 8 files changed, 344 insertions(+), 5 deletions(-)
diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in index f4e7530..75c24cb 100644 --- a/docs/drvesx.html.in +++ b/docs/drvesx.html.in @@ -292,6 +292,12 @@ ethernet0.checkMACAddress = "false"
<h4>SCSI controller models</h4> <dl> + <dt><code>auto</code></dt> + <dd> + This isn't a actual controller model. If specified the ESX driver + tries to detect the SCSI controller model referenced in the + <code>.vmdk</code> file and use it. <span class="since">Since 0.8.3</span> + </dd> <dt><code>buslogic</code></dt> <dd> BusLogic SCSI controller for older guests. diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index b171d01..e090366 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -673,6 +673,7 @@ <optional> <attribute name="model"> <choice> + <value>auto</value> <value>buslogic</value> <value>lsilogic</value> <value>lsisas1068</value>
I don't really see how this can sensibly work.
A controller can have multiple disks associated with it. Each associated disk has a drive address that uniquely identifies its position on the controller.
Now consider a controller of mode 'auto' and attach two disks to it. One VMDK specifies 'lsilogic' and the other VMDK specifies 'lsisas1068'. This is not reconcilable because you have 2 conflicting controller models, but have associated both disks with the same controller object.
In case of detecting conflicting controller models for one controller the autodetection has to fail. The current code just picks the reported model for the first disk and doesn't look at the other disk on the same controller. That's wrong and I fixed this in v2.
Furthermore both disks could be LUN 1 on their respective controller, which means you'd now have a uniquness violation on the drive address.
I don't get what you try to say. The model autodetection doesn't affect the drive address at all and is a per-controller action. Matthias
participants (2)
-
Daniel P. Berrange
-
Matthias Bolte