385
394
->data.file.path = <value> <=> parallel0.fileName = "<value>" # e.g. "parallel0.file"
386
395
??? <=> parallel0.bidirectional = "<value>" # must be "false" for fileType = "file", FIXME: not representable
399
################################################################################
400
## sound #######################################################################
402
sound.present = "true" # defaults to "false"
403
sound.startConnected = "true" # defaults to "true"
404
sound.autodetect = "true"
405
sound.fileName = "-1"
407
FIXME: Investigate if ESX supports this,
408
at least the VI Client GUI has no
409
options to add a sound device, but
410
the VI API contains a VirtualSoundCard
390
414
#define VIR_FROM_THIS VIR_FROM_ESX
392
416
#define ESX_ERROR(conn, code, fmt...) \
393
virReportErrorHelper (conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \
417
virReportErrorHelper(conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \
398
422
#define ESX_BUILD_VMX_NAME(_suffix) \
400
strncpy(_suffix##_name, prefix, sizeof (_suffix##_name) - 1); \
401
_suffix##_name[sizeof (_suffix##_name) - 1] = '\0'; \
402
strncat(_suffix##_name, "."#_suffix, \
403
sizeof (_suffix##_name) - 1 - strlen(_suffix##_name)); \
423
snprintf(_suffix##_name, sizeof(_suffix##_name), "%s."#_suffix, prefix);
428
esxVMX_SCSIDiskNameToControllerAndID(virConnectPtr conn, const char *name,
429
int *controller, int *id)
433
if (! STRPREFIX(name, "sd")) {
434
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
435
"Expecting domain XML attribute 'dev' of entry "
436
"'devices/disk/target' to start with 'sd'");
440
idx = virDiskNameToIndex(name);
443
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
444
"Could not parse valid disk index from '%s'", name);
448
/* Each of the 4 SCSI controllers offers 15 IDs for devices */
449
if (idx >= (4 * 15)) {
450
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
451
"SCSI disk index (parsed from '%s') is too large", name);
455
*controller = idx / 15;
458
/* Skip the controller ifself with ID 7 */
469
esxVMX_IDEDiskNameToControllerAndID(virConnectPtr conn, const char *name,
470
int *controller, int *id)
474
if (! STRPREFIX(name, "hd")) {
475
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
476
"Expecting domain XML attribute 'dev' of entry "
477
"'devices/disk/target' to start with 'hd'");
481
idx = virDiskNameToIndex(name);
484
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
485
"Could not parse valid disk index from '%s'", name);
489
/* Each of the 2 IDE controllers offers 2 IDs for devices */
490
if (idx >= (2 * 2)) {
491
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
492
"IDE disk index (parsed from '%s') is too large", name);
496
*controller = idx / 2;
505
esxVMX_FloppyDiskNameToController(virConnectPtr conn, const char *name,
510
if (! STRPREFIX(name, "fd")) {
511
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
512
"Expecting domain XML attribute 'dev' of entry "
513
"'devices/disk/target' to start with 'fd'");
517
idx = virDiskNameToIndex(name);
520
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
521
"Could not parse valid disk index from '%s'", name);
526
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
527
"Floppy disk index (parsed from '%s') is too large", name);
539
esxVMX_GatherSCSIControllers(virConnectPtr conn, virDomainDefPtr def,
540
char *virtualDev[4], int present[4])
542
virDomainDiskDefPtr disk;
543
int i, controller, id;
545
/* Check for continuous use of the same virtualDev per SCSI controller */
546
for (i = 0; i < def->ndisks; ++i) {
547
disk = def->disks[i];
549
if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
553
if (disk->driverName != NULL &&
554
STRCASENEQ(disk->driverName, "buslogic") &&
555
STRCASENEQ(disk->driverName, "lsilogic")) {
556
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
557
"Expecting domain XML entry 'devices/disk/target' to be "
558
"'buslogic' or 'lsilogic' but found '%s'",
563
if (esxVMX_SCSIDiskNameToControllerAndID(conn, disk->dst,
564
&controller, &id) < 0) {
568
present[controller] = 1;
570
if (virtualDev[controller] == NULL) {
571
virtualDev[controller] = disk->driverName;
572
} else if (STRCASENEQ(virtualDev[controller], disk->driverName)) {
573
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
574
"Inconsistent driver usage ('%s' is not '%s') on SCSI "
575
"controller index %d", virtualDev[controller],
576
disk->driverName, controller);
587
esxVMX_AbsolutePathToDatastoreRelatedPath(virConnectPtr conn,
589
const char *absolutePath)
591
char *datastoreRelatedPath = NULL;
592
char *preliminaryDatastoreName = NULL;
593
char *directoryAndFileName = NULL;
594
esxVI_DynamicProperty *dynamicProperty = NULL;
595
esxVI_ObjectContent *datastore = NULL;
596
const char *datastoreName = NULL;
598
if (sscanf(absolutePath, "/vmfs/volumes/%a[^/]/%a[^\n]",
599
&preliminaryDatastoreName, &directoryAndFileName) != 2) {
600
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
601
"Absolute path '%s' doesn't have expected format "
602
"'/vmfs/volumes/<datastore>/<path>'", absolutePath);
607
if (esxVI_LookupDatastoreByName(conn, ctx, preliminaryDatastoreName,
609
esxVI_Occurence_RequiredItem) < 0) {
613
for (dynamicProperty = datastore->propSet; dynamicProperty != NULL;
614
dynamicProperty = dynamicProperty->_next) {
615
if (STREQ(dynamicProperty->name, "summary.accessible")) {
617
} else if (STREQ(dynamicProperty->name, "summary.name")) {
618
if (esxVI_AnyType_ExpectType(conn, dynamicProperty->val,
619
esxVI_Type_String) < 0) {
623
datastoreName = dynamicProperty->val->string;
625
} else if (STREQ(dynamicProperty->name, "summary.url")) {
628
VIR_WARN("Unexpected '%s' property", dynamicProperty->name);
632
if (datastoreName == NULL) {
633
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
634
"Could not retrieve datastore name for absolute path '%s'",
639
datastoreName = preliminaryDatastoreName;
642
if (virAsprintf(&datastoreRelatedPath, "[%s] %s", datastoreName,
643
directoryAndFileName) < 0) {
644
virReportOOMError(conn);
648
/* FIXME: Check if referenced path/file really exists */
651
VIR_FREE(preliminaryDatastoreName);
652
VIR_FREE(directoryAndFileName);
653
esxVI_ObjectContent_Free(&datastore);
655
return datastoreRelatedPath;
658
VIR_FREE(datastoreRelatedPath);
665
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
670
esxVMX_ParseFileName(virConnectPtr conn, esxVI_Context *ctx,
671
const char *fileName, const char *datastoreName,
672
const char *directoryName)
676
if (STRPREFIX(fileName, "/vmfs/volumes/")) {
677
/* Found absolute path referencing a file inside a datastore */
678
return esxVMX_AbsolutePathToDatastoreRelatedPath(conn, ctx, fileName);
679
} else if (STRPREFIX(fileName, "/")) {
680
/* Found absolute path referencing a file outside a datastore */
681
src = strdup(fileName);
684
virReportOOMError(conn);
688
/* FIXME: Check if referenced path/file really exists */
691
} else if (strchr(fileName, '/') != NULL) {
692
/* Found relative path, this is not supported */
693
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
694
"Found relative path '%s' in VMX file, this is not "
695
"supported", fileName);
698
/* Found single file name referencing a file inside a datastore */
699
if (virAsprintf(&src, "[%s] %s/%s", datastoreName, directoryName,
701
virReportOOMError(conn);
705
/* FIXME: Check if referenced path/file really exists */
409
esxVMX_ParseConfig(virConnectPtr conn, const char *vmx,
714
esxVMX_ParseConfig(virConnectPtr conn, esxVI_Context *ctx, const char *vmx,
715
const char *datastoreName, const char *directoryName,
410
716
esxVI_APIVersion apiVersion)
412
718
virConfPtr conf = NULL;
1686
2052
VIR_FREE(fileType);
1687
2053
VIR_FREE(fileName);
1695
2061
virDomainChrDefFree(*def);
2069
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2074
esxVMX_FormatFileName(virConnectPtr conn, esxVI_Context *ctx ATTRIBUTE_UNUSED,
2077
char *datastoreName = NULL;
2078
char *directoryName = NULL;
2079
char *fileName = NULL;
2080
char *absolutePath = NULL;
2082
if (STRPREFIX(src, "[")) {
2083
/* Found potential datastore related path */
2084
if (esxUtil_ParseDatastoreRelatedPath(conn, src, &datastoreName,
2085
&directoryName, &fileName) < 0) {
2089
if (directoryName == NULL) {
2090
if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s",
2091
datastoreName, fileName) < 0) {
2092
virReportOOMError(conn);
2096
if (virAsprintf(&absolutePath, "/vmfs/volumes/%s/%s/%s",
2097
datastoreName, directoryName, fileName) < 0) {
2098
virReportOOMError(conn);
2102
} else if (STRPREFIX(src, "/")) {
2103
/* Found absolute path */
2104
absolutePath = strdup(src);
2106
if (absolutePath == NULL) {
2107
virReportOOMError(conn);
2111
/* Found relative path, this is not supported */
2112
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2113
"Found relative path '%s' in domain XML, this is not "
2118
/* FIXME: Check if referenced path/file really exists */
2121
VIR_FREE(datastoreName);
2122
VIR_FREE(directoryName);
2125
return absolutePath;
2128
VIR_FREE(absolutePath);
2136
esxVMX_FormatConfig(virConnectPtr conn, esxVI_Context *ctx,
2137
virDomainDefPtr def, esxVI_APIVersion apiVersion)
2140
int sched_cpu_affinity_length;
2141
unsigned char zero[VIR_UUID_BUFLEN];
2142
virBuffer buffer = VIR_BUFFER_INITIALIZER;
2145
memset(zero, 0, VIR_UUID_BUFLEN);
2147
if (def->virtType != VIR_DOMAIN_VIRT_VMWARE) { /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
2148
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2149
"Expecting virt type to be '%s' but found '%s'",
2150
virDomainVirtTypeToString(VIR_DOMAIN_VIRT_VMWARE),
2151
virDomainVirtTypeToString(def->virtType));
2155
/* vmx:config.version */
2156
virBufferAddLit(&buffer, "config.version = \"8\"\n");
2158
/* vmx:virtualHW.version */
2159
switch (apiVersion) {
2160
case esxVI_APIVersion_25:
2161
virBufferAddLit(&buffer, "virtualHW.version = \"4\"\n");
2164
case esxVI_APIVersion_40:
2165
virBufferAddLit(&buffer, "virtualHW.version = \"7\"\n");
2169
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2170
"Expecting VI API version 2.5 or 4.0");
2174
/* def:arch -> vmx:guestOS */
2175
if (def->os.arch == NULL || STRCASEEQ(def->os.arch, "i686")) {
2176
virBufferAddLit(&buffer, "guestOS = \"other\"\n");
2177
} else if (STRCASEEQ(def->os.arch, "x86_64")) {
2178
virBufferAddLit(&buffer, "guestOS = \"other-64\"\n");
2180
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2181
"Expecting domain XML attribute 'arch' of entry 'os/type' "
2182
"to be 'i686' or 'x86_64' but found '%s'", def->os.arch);
2186
/* def:uuid -> vmx:uuid.action, vmx:uuid.bios */
2187
if (memcmp(def->uuid, zero, VIR_UUID_BUFLEN) == 0) {
2188
virBufferAddLit(&buffer, "uuid.action = \"create\"\n");
2190
virBufferVSprintf(&buffer, "uuid.bios = \"%02x %02x %02x %02x %02x %02x "
2191
"%02x %02x-%02x %02x %02x %02x %02x %02x %02x %02x\"\n",
2192
def->uuid[0], def->uuid[1], def->uuid[2], def->uuid[3],
2193
def->uuid[4], def->uuid[5], def->uuid[6], def->uuid[7],
2194
def->uuid[8], def->uuid[9], def->uuid[10], def->uuid[11],
2195
def->uuid[12], def->uuid[13], def->uuid[14],
2199
/* def:name -> vmx:displayName */
2200
virBufferVSprintf(&buffer, "displayName = \"%s\"\n", def->name);
2202
/* def:maxmem -> vmx:memsize */
2203
if (def->maxmem <= 0 || def->maxmem % 4096 != 0) {
2204
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2205
"Expecting domain XML entry 'memory' to be an unsigned "
2206
"integer (multiple of 4096) but found %lld",
2207
(unsigned long long)def->maxmem);
2211
/* Scale from kilobytes to megabytes */
2212
virBufferVSprintf(&buffer, "memsize = \"%d\"\n",
2213
(int)(def->maxmem / 1024));
2215
/* def:memory -> vmx:sched.mem.max */
2216
if (def->memory < def->maxmem) {
2217
if (def->memory <= 0 || def->memory % 1024 != 0) {
2218
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2219
"Expecting domain XML entry 'currentMemory' to be an "
2220
"unsigned integer (multiple of 1024) but found %lld",
2221
(unsigned long long)def->memory);
2225
/* Scale from kilobytes to megabytes */
2226
virBufferVSprintf(&buffer, "sched.mem.max = \"%d\"\n",
2227
(int)(def->memory / 1024));
2230
/* vmx:numvcpus -> def:vcpus */
2231
if (def->vcpus <= 0 || (def->vcpus % 2 != 0 && def->vcpus != 1)) {
2232
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2233
"Expecting domain XML entry 'vcpu' to be an unsigned "
2234
"integer (1 or a multiple of 2) but found %d",
2239
virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus);
2241
/* def:cpumask -> vmx:sched.cpu.affinity */
2242
if (def->cpumasklen > 0) {
2243
virBufferAddLit(&buffer, "sched.cpu.affinity = \"");
2245
sched_cpu_affinity_length = 0;
2247
for (i = 0; i < def->cpumasklen; ++i) {
2248
if (def->cpumask[i]) {
2249
++sched_cpu_affinity_length;
2253
if (sched_cpu_affinity_length < def->vcpus) {
2254
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2255
"Expecting domain XML attribute 'cpuset' of entry "
2256
"'vcpu' to contains at least %d CPU(s)",
2261
for (i = 0; i < def->cpumasklen; ++i) {
2262
if (def->cpumask[i]) {
2263
virBufferVSprintf(&buffer, "%d", i);
2265
if (sched_cpu_affinity_length > 1) {
2266
virBufferAddChar(&buffer, ',');
2269
--sched_cpu_affinity_length;
2273
virBufferAddLit(&buffer, "\"\n");
2277
int scsi_present[4] = { 0, 0, 0, 0 };
2278
char *scsi_virtualDev[4] = { NULL, NULL, NULL, NULL };
2280
if (esxVMX_GatherSCSIControllers(conn, def, scsi_virtualDev,
2281
scsi_present) < 0) {
2285
for (i = 0; i < 4; ++i) {
2286
if (scsi_present[i]) {
2287
virBufferVSprintf(&buffer, "scsi%d.present = \"true\"\n", i);
2289
if (scsi_virtualDev[i] != NULL) {
2290
virBufferVSprintf(&buffer, "scsi%d.virtualDev = \"%s\"\n", i,
2291
scsi_virtualDev[i]);
2296
for (i = 0; i < def->ndisks; ++i) {
2297
switch (def->disks[i]->device) {
2298
case VIR_DOMAIN_DISK_DEVICE_DISK:
2299
if (esxVMX_FormatHardDisk(conn, ctx, def->disks[i], &buffer) < 0) {
2305
case VIR_DOMAIN_DISK_DEVICE_CDROM:
2306
if (esxVMX_FormatCDROM(conn, ctx, def->disks[i], &buffer) < 0) {
2312
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
2313
if (esxVMX_FormatFloppy(conn, ctx, def->disks[i], &buffer) < 0) {
2320
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2321
"Unsuppotred disk device type '%s'",
2322
virDomainDiskDeviceTypeToString(def->disks[i]->device));
2331
for (i = 0; i < def->nnets; ++i) {
2332
if (esxVMX_FormatEthernet(conn, def->nets[i], i, &buffer) < 0) {
2347
for (i = 0; i < def->nserials; ++i) {
2348
if (esxVMX_FormatSerial(conn, ctx, def->serials[i], &buffer) < 0) {
2354
for (i = 0; i < def->nparallels; ++i) {
2355
if (esxVMX_FormatParallel(conn, ctx, def->parallels[i], &buffer) < 0) {
2360
/* Get final VMX output */
2361
if (virBufferError(&buffer)) {
2362
virReportOOMError(conn);
2366
vmx = virBufferContentAndReset(&buffer);
2372
vmx = virBufferContentAndReset(&buffer);
2383
esxVMX_FormatHardDisk(virConnectPtr conn, esxVI_Context *ctx,
2384
virDomainDiskDefPtr def, virBufferPtr buffer)
2387
const char *busName = NULL;
2388
const char *entryPrefix = NULL;
2389
const char *deviceTypePrefix = NULL;
2390
char *fileName = NULL;
2392
if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
2393
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
2397
if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
2399
entryPrefix = "scsi";
2400
deviceTypePrefix = "scsi";
2402
if (esxVMX_SCSIDiskNameToControllerAndID(conn, def->dst,
2403
&controller, &id) < 0) {
2406
} else if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) {
2408
entryPrefix = "ide";
2409
deviceTypePrefix = "ata";
2411
if (esxVMX_IDEDiskNameToControllerAndID(conn, def->dst,
2412
&controller, &id) < 0) {
2416
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2417
"Unsupported bus type '%s' for harddisk",
2418
virDomainDiskBusTypeToString(def->bus));
2422
if (def->type != VIR_DOMAIN_DISK_TYPE_FILE) {
2423
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2424
"%s harddisk '%s' has unsupported type '%s', expecting '%s'",
2425
busName, def->dst, virDomainDiskTypeToString(def->type),
2426
virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE));
2430
virBufferVSprintf(buffer, "%s%d:%d.present = \"true\"\n",
2431
entryPrefix, controller, id);
2432
virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"%s-hardDisk\"\n",
2433
entryPrefix, controller, id, deviceTypePrefix);
2435
if (def->src != NULL) {
2436
if (! virFileHasSuffix(def->src, ".vmdk")) {
2437
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2438
"Image file for %s harddisk '%s' has unsupported suffix, "
2439
"expecting '.vmdk'", busName, def->dst);
2443
fileName = esxVMX_FormatFileName(conn, ctx, def->src);
2445
if (fileName == NULL) {
2449
virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
2450
entryPrefix, controller, id, fileName);
2455
if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
2456
if (def->cachemode == VIR_DOMAIN_DISK_CACHE_WRITETHRU) {
2457
virBufferVSprintf(buffer, "%s%d:%d.writeThrough = \"true\"\n",
2458
entryPrefix, controller, id);
2459
} else if (def->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) {
2460
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2461
"%s harddisk '%s' has unsupported cache mode '%s'",
2463
virDomainDiskCacheTypeToString(def->cachemode));
2474
esxVMX_FormatCDROM(virConnectPtr conn, esxVI_Context *ctx,
2475
virDomainDiskDefPtr def, virBufferPtr buffer)
2478
const char *busName = NULL;
2479
const char *entryPrefix = NULL;
2480
char *fileName = NULL;
2482
if (def->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
2483
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
2487
if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) {
2489
entryPrefix = "scsi";
2491
if (esxVMX_SCSIDiskNameToControllerAndID(conn, def->dst,
2492
&controller, &id) < 0) {
2495
} else if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) {
2497
entryPrefix = "ide";
2499
if (esxVMX_IDEDiskNameToControllerAndID(conn, def->dst,
2500
&controller, &id) < 0) {
2504
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2505
"Unsupported bus type '%s' for cdrom",
2506
virDomainDiskBusTypeToString(def->bus));
2510
virBufferVSprintf(buffer, "%s%d:%d.present = \"true\"\n",
2511
entryPrefix, controller, id);
2513
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
2514
virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"cdrom-image\"\n",
2515
entryPrefix, controller, id);
2517
if (def->src != NULL) {
2518
if (! virFileHasSuffix(def->src, ".iso")) {
2519
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2520
"Image file for %s cdrom '%s' has unsupported "
2521
"suffix, expecting '.iso'", busName, def->dst);
2525
fileName = esxVMX_FormatFileName(conn, ctx, def->src);
2527
if (fileName == NULL) {
2531
virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
2532
entryPrefix, controller, id, fileName);
2536
} else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
2537
virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"atapi-cdrom\"\n",
2538
entryPrefix, controller, id);
2540
if (def->src != NULL) {
2541
virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n",
2542
entryPrefix, controller, id, def->src);
2545
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2546
"%s cdrom '%s' has unsupported type '%s', expecting '%s' "
2547
"or '%s'", busName, def->dst,
2548
virDomainDiskTypeToString(def->type),
2549
virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE),
2550
virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_BLOCK));
2560
esxVMX_FormatFloppy(virConnectPtr conn, esxVI_Context *ctx,
2561
virDomainDiskDefPtr def, virBufferPtr buffer)
2564
char *fileName = NULL;
2566
if (def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
2567
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
2571
if (esxVMX_FloppyDiskNameToController(conn, def->dst, &controller) < 0) {
2575
virBufferVSprintf(buffer, "floppy%d.present = \"true\"\n", controller);
2577
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) {
2578
virBufferVSprintf(buffer, "floppy%d.fileType = \"file\"\n",
2581
if (def->src != NULL) {
2582
if (! virFileHasSuffix(def->src, ".flp")) {
2583
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2584
"Image file for floppy '%s' has unsupported suffix, "
2585
"expecting '.flp'", def->dst);
2589
fileName = esxVMX_FormatFileName(conn, ctx, def->src);
2591
if (fileName == NULL) {
2595
virBufferVSprintf(buffer, "floppy%d.fileName = \"%s\"\n",
2596
controller, fileName);
2600
} else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) {
2601
virBufferVSprintf(buffer, "floppy%d.fileType = \"device\"\n",
2604
if (def->src != NULL) {
2605
virBufferVSprintf(buffer, "floppy%d.fileName = \"%s\"\n",
2606
controller, def->src);
2609
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2610
"Floppy '%s' has unsupported type '%s', expecting '%s' "
2611
"or '%s'", def->dst,
2612
virDomainDiskTypeToString(def->type),
2613
virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE),
2614
virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_BLOCK));
2624
esxVMX_FormatEthernet(virConnectPtr conn, virDomainNetDefPtr def,
2625
int controller, virBufferPtr buffer)
2627
char mac_string[VIR_MAC_STRING_BUFLEN];
2629
if (controller < 0 || controller > 3) {
2630
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2631
"Ethernet controller index %d out of [0..3] range",
2636
virBufferVSprintf(buffer, "ethernet%d.present = \"true\"\n", controller);
2638
/* def:model -> vmx:virtualDev */
2639
if (def->model != NULL) {
2640
if (STRCASENEQ(def->model, "vlance") &&
2641
STRCASENEQ(def->model, "vmxnet") &&
2642
STRCASENEQ(def->model, "e1000")) {
2643
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2644
"Expecting domain XML entry 'devices/interfase/model' "
2645
"to be 'vlance' or 'vmxnet' or 'e1000' but found '%s'",
2650
virBufferVSprintf(buffer, "ethernet%d.virtualDev = \"%s\"\n",
2651
controller, def->model);
2654
/* def:type, def:ifname -> vmx:connectionType */
2655
switch (def->type) {
2656
case VIR_DOMAIN_NET_TYPE_BRIDGE:
2657
virBufferVSprintf(buffer, "ethernet%d.networkName = \"%s\"\n",
2658
controller, def->data.bridge.brname);
2660
if (def->ifname != NULL) {
2661
virBufferVSprintf(buffer, "ethernet%d.connectionType = \"custom\"\n",
2663
virBufferVSprintf(buffer, "ethernet%d.vnet = \"%s\"\n",
2664
controller, def->ifname);
2666
virBufferVSprintf(buffer, "ethernet%d.connectionType = \"bridged\"\n",
2673
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2674
"Unsupported net type '%s'",
2675
virDomainNetTypeToString(def->type));
2679
virFormatMacAddr(def->mac, mac_string);
2681
if ((def->mac[0] == 0x00 && def->mac[1] == 0x0c && def->mac[2] == 0x29) ||
2682
(def->mac[0] == 0x00 && def->mac[1] == 0x50 && def->mac[2] == 0x56)) {
2683
virBufferVSprintf(buffer, "ethernet%d.addressType = \"generated\"\n",
2685
virBufferVSprintf(buffer, "ethernet%d.generatedAddress = \"%s\"\n",
2686
controller, mac_string);
2688
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2689
"Unsupported MAC address prefix '%02X:%02X:%02X', expecting "
2690
"'00:0c:29' or '00:50:56'",
2691
def->mac[0], def->mac[1], def->mac[2]);
2701
esxVMX_FormatSerial(virConnectPtr conn, esxVI_Context *ctx,
2702
virDomainChrDefPtr def, virBufferPtr buffer)
2704
char *fileName = NULL;
2706
if (def->dstPort < 0 || def->dstPort > 3) {
2707
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2708
"Serial port index %d out of [0..3] range", def->dstPort);
2712
if (def->data.file.path == NULL) {
2713
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2714
"Expecting domain XML attribute 'path' of entry "
2715
"'devices/serial/source' to be present");
2719
virBufferVSprintf(buffer, "serial%d.present = \"true\"\n", def->dstPort);
2721
/* def:type -> vmx:fileType and def:data.file.path -> vmx:fileName */
2722
switch (def->type) {
2723
case VIR_DOMAIN_CHR_TYPE_DEV:
2724
virBufferVSprintf(buffer, "serial%d.fileType = \"device\"\n",
2726
virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
2727
def->dstPort, def->data.file.path);
2730
case VIR_DOMAIN_CHR_TYPE_FILE:
2731
virBufferVSprintf(buffer, "serial%d.fileType = \"file\"\n",
2734
fileName = esxVMX_FormatFileName(conn, ctx, def->data.file.path);
2736
if (fileName == NULL) {
2740
virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
2741
def->dstPort, fileName);
2746
case VIR_DOMAIN_CHR_TYPE_PIPE:
2747
virBufferVSprintf(buffer, "serial%d.fileType = \"pipe\"\n",
2749
/* FIXME: Based on VI Client GUI default */
2750
virBufferVSprintf(buffer, "serial%d.pipe.endPoint = \"client\"\n",
2752
/* FIXME: Based on VI Client GUI default */
2753
virBufferVSprintf(buffer, "serial%d.tryNoRxLoss = \"false\"\n",
2755
virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n",
2756
def->dstPort, def->data.file.path);
2760
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2761
"Unsupported character device type '%s'",
2762
virDomainChrTypeToString(def->type));
2766
/* vmx:yieldOnMsrRead */
2767
/* FIXME: Based on VI Client GUI default */
2768
virBufferVSprintf(buffer, "serial%d.yieldOnMsrRead = \"true\"\n",
2777
esxVMX_FormatParallel(virConnectPtr conn, esxVI_Context *ctx,
2778
virDomainChrDefPtr def, virBufferPtr buffer)
2780
char *fileName = NULL;
2782
if (def->dstPort < 0 || def->dstPort > 2) {
2783
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2784
"Parallel port index %d out of [0..2] range", def->dstPort);
2788
if (def->data.file.path == NULL) {
2789
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2790
"Expecting domain XML attribute 'path' of entry "
2791
"'devices/parallel/source' to be present");
2795
virBufferVSprintf(buffer, "parallel%d.present = \"true\"\n", def->dstPort);
2797
/* def:type -> vmx:fileType and def:data.file.path -> vmx:fileName */
2798
switch (def->type) {
2799
case VIR_DOMAIN_CHR_TYPE_DEV:
2800
virBufferVSprintf(buffer, "parallel%d.fileType = \"device\"\n",
2802
virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n",
2803
def->dstPort, def->data.file.path);
2806
case VIR_DOMAIN_CHR_TYPE_FILE:
2807
virBufferVSprintf(buffer, "parallel%d.fileType = \"file\"\n",
2810
fileName = esxVMX_FormatFileName(conn, ctx, def->data.file.path);
2812
if (fileName == NULL) {
2816
virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n",
2817
def->dstPort, fileName);
2823
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
2824
"Unsupported character device type '%s'",
2825
virDomainChrTypeToString(def->type));