提交 cf8cf8a5 编写于 作者: M Matthias Bolte

esx: Add autodetection for the SCSI controller model

This works for file-backed SCSI disk device with a datastore
related source path.
上级 afb85c58
......@@ -292,6 +292,15 @@ 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. Autodetection fails when a
SCSI controller has multiple disks attached and the SCSI controller
models referenced in the <code>.vmdk</code> files are inconsistent.
<span class="since">Since 0.8.3</span>
</dd>
<dt><code>buslogic</code></dt>
<dd>
BusLogic SCSI controller for older guests.
......
......@@ -676,6 +676,7 @@
<optional>
<attribute name="model">
<choice>
<value>auto</value>
<value>buslogic</value>
<value>lsilogic</value>
<value>lsisas1068</value>
......
......@@ -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",
......
......@@ -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,
......
......@@ -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
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册