diff --git a/docs/drvesx.html.in b/docs/drvesx.html.in
index 88c70bc967..e8cee77ae5 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 9289c8f9e4..2d22ce4028 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 b52656166c..5b59c0143a 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 2a60515a45..9ef687b4c3 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 ff65178079..b4b33f6aa1 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 ff3e3d1d69..82bc9b6fbd 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 c69e116d29..9035233b91 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;
+ }
- if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ for (i = 0; i < def->ncontrollers; ++i) {
+ controller = def->controllers[i];
+
+ 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 a9015fb6b5..3ccae7a15d 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,