diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c index aac41ba5af..36cef4c270 100644 --- a/src/esx/esx_driver.c +++ b/src/esx/esx_driver.c @@ -2232,6 +2232,42 @@ esxDomainXMLFromNative(virConnectPtr conn, const char *nativeFormat, +static char * +esxDomainXMLToNative(virConnectPtr conn, const char *nativeFormat, + const char *domainXml, + unsigned int flags ATTRIBUTE_UNUSED) +{ + esxPrivate *priv = (esxPrivate *)conn->privateData; + virDomainDefPtr def = NULL; + char *vmx = NULL; + + if (priv->phantom) { + ESX_ERROR(conn, VIR_ERR_OPERATION_INVALID, + "Not possible with a phantom connection"); + return NULL; + } + + if (STRNEQ(nativeFormat, "vmware-vmx")) { + ESX_ERROR(conn, VIR_ERR_INVALID_ARG, + "Unsupported config format '%s'", nativeFormat); + return NULL; + } + + def = virDomainDefParseString(conn, priv->caps, domainXml, 0); + + if (def == NULL) { + return NULL; + } + + vmx = esxVMX_FormatConfig(conn, def, priv->host->apiVersion); + + virDomainDefFree(def); + + return vmx; +} + + + static int esxListDefinedDomains(virConnectPtr conn, char **const names, int maxnames) { @@ -3093,7 +3129,7 @@ static virDriver esxDriver = { NULL, /* nodeGetSecurityModel */ esxDomainDumpXML, /* domainDumpXML */ esxDomainXMLFromNative, /* domainXMLFromNative */ - NULL, /* domainXMLToNative */ + esxDomainXMLToNative, /* domainXMLToNative */ esxListDefinedDomains, /* listDefinedDomains */ esxNumberOfDefinedDomains, /* numOfDefinedDomains */ esxDomainCreate, /* domainCreate */ diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c index 9a0191ead7..dea2a12e48 100644 --- a/src/esx/esx_vmx.c +++ b/src/esx/esx_vmx.c @@ -58,7 +58,7 @@ def->cpumask = <=> sched.cpu.affinity = "" def->os ->type = "hvm" -->arch +->arch = <=> guestOS = "" # if ends with -64 than is x86_64, otherwise is i686 ->machine ->nBootDevs ->bootDevs @@ -98,7 +98,7 @@ def->disks[0]... ->device = _DISK_DEVICE_DISK <=> scsi0:0.deviceType = "scsi-hardDisk" # defaults to ? ->bus = _DISK_BUS_SCSI ->src = .vmdk <=> scsi0:0.fileName = ".vmdk" -->dst = sd[ * 16 + mapped to [a-z]+] +->dst = sd[ * 15 + mapped to [a-z]+] ->driverName = <=> scsi0.virtualDev = "" # default depends on guestOS value ->driverType ->cachemode <=> scsi0:0.writeThrough = "" # defaults to false, true -> _DISK_CACHE_WRITETHRU, false _DISK_CACHE_DEFAULT @@ -109,7 +109,6 @@ def->disks[0]... ## disks: ide hard drive from .vmdk image ###################################### - ide0.present = "true" # defaults to "false" ide0:0.present = "true" # defaults to "false" ide0:0.startConnected = "true" # defaults to "true" @@ -143,7 +142,7 @@ def->disks[0]... ->device = _DISK_DEVICE_CDROM <=> scsi0:0.deviceType = "cdrom-image" # defaults to ? ->bus = _DISK_BUS_SCSI ->src = .iso <=> scsi0:0.fileName = ".iso" -->dst = sd[ * 16 + mapped to [a-z]+] +->dst = sd[ * 15 + mapped to [a-z]+] ->driverName = <=> scsi0.virtualDev = "" # default depends on guestOS value ->driverType ->cachemode @@ -154,7 +153,6 @@ def->disks[0]... ## disks: ide cdrom from .iso image ############################################ - ide0.present = "true" # defaults to "false" ide0:0.present = "true" # defaults to "false" ide0:0.startConnected = "true" # defaults to "true" @@ -194,7 +192,6 @@ def->disks[0]... ## disks: ide cdrom from host device ########################################### - ide0.present = "true" # defaults to "false" ide0:0.present = "true" # defaults to "false" ide0:0.startConnected = "true" # defaults to "true" ide0:0.clientDevice = "false" # defaults to "false" @@ -289,17 +286,18 @@ def->nets[0]... ... ->type = _NET_TYPE_BRIDGE <=> ethernet0.connectionType = "bridged" # defaults to "bridged" +->data.bridge.brname = <=> ethernet0.networkName = "" ## nets: hostonly ############################################################## -... # FIXME: maybe not supported by ESX? +... # FIXME: Investigate if ESX supports this ->type = _NET_TYPE_NETWORK <=> ethernet0.connectionType = "hostonly" # defaults to "bridged" ## nets: nat ################################################################### -... # FIXME: maybe not supported by ESX? +... # FIXME: Investigate if ESX supports this ->type = _NET_TYPE_USER <=> ethernet0.connectionType = "nat" # defaults to "bridged" @@ -307,7 +305,8 @@ def->nets[0]... ... ->type = _NET_TYPE_BRIDGE <=> ethernet0.connectionType = "custom" # defaults to "bridged" -->data.bridge.brname = <=> ethernet0.vnet = "" +->data.bridge.brname = <=> ethernet0.networkName = "" +->ifname = <=> ethernet0.vnet = "" @@ -328,6 +327,7 @@ def->serials[0]... ->type = _CHR_TYPE_DEV <=> serial0.fileType = "device" ->data.file.path = <=> serial0.fileName = "" # e.g. "/dev/ttyS0" ??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable +??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable ## serials: file ############################################################### @@ -335,32 +335,37 @@ def->serials[0]... ->type = _CHR_TYPE_FILE <=> serial0.fileType = "file" ->data.file.path = <=> serial0.fileName = "" # e.g. "serial0.file" ??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable +??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable ## serials: pipe, far end -> app ############################################### ->type = _CHR_TYPE_PIPE <=> serial0.fileType = "pipe" ->data.file.path = <=> serial0.fileName = "" # e.g. "serial0.pipe" -??? <=> serial0.pipe.endPoint = "client" # defaults to "server", FIXME: not representable +??? <=> serial0.pipe.endPoint = "client" # defaults to ?, FIXME: not representable ??? <=> serial0.tryNoRxLoss = "true" # defaults to "false", FIXME: not representable +??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable ->type = _CHR_TYPE_PIPE <=> serial0.fileType = "pipe" ->data.file.path = <=> serial0.fileName = "" # e.g. "serial0.pipe" -??? <=> serial0.pipe.endPoint = "server" # defaults to "server", FIXME: not representable +??? <=> serial0.pipe.endPoint = "server" # defaults to ?, FIXME: not representable ??? <=> serial0.tryNoRxLoss = "true" # defaults to "false", FIXME: not representable +??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable ## serials: pipe, far end -> vm ################################################ ->type = _CHR_TYPE_PIPE <=> serial0.fileType = "pipe" ->data.file.path = <=> serial0.fileName = "" # e.g. "serial0.pipe" -??? <=> serial0.pipe.endPoint = "client" # defaults to "server", FIXME: not representable +??? <=> serial0.pipe.endPoint = "client" # defaults to ?, FIXME: not representable ??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable +??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable ->type = _CHR_TYPE_PIPE <=> serial0.fileType = "pipe" ->data.file.path = <=> serial0.fileName = "" # e.g. "serial0.pipe" -??? <=> serial0.pipe.endPoint = "server" # defaults to "server", FIXME: not representable +??? <=> serial0.pipe.endPoint = "server" # defaults to ?, FIXME: not representable ??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable +??? <=> serial0.yieldOnMsrRead = "true" # defaults to "false", FIXME: not representable @@ -389,6 +394,21 @@ def->parallels[0]... ->data.file.path = <=> parallel0.fileName = "" # e.g. "parallel0.file" ??? <=> parallel0.bidirectional = "" # must be "false" for fileType = "file", FIXME: not representable + + +################################################################################ +## sound ####################################################################### + + sound.present = "true" # defaults to "false" + sound.startConnected = "true" # defaults to "true" + sound.autodetect = "true" + sound.fileName = "-1" + + FIXME: Investigate if ESX supports this, + at least the VI Client GUI has no + options to add a sound device, but + the VI API contains a VirtualSoundCard + */ #define VIR_FROM_THIS VIR_FROM_ESX @@ -404,6 +424,169 @@ def->parallels[0]... +int +esxVMX_SCSIDiskNameToControllerAndID(virConnectPtr conn, const char *name, + int *controller, int *id) +{ + int idx; + + if (! STRPREFIX(name, "sd")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML attribute 'dev' of entry " + "'devices/disk/target' to start with 'sd'"); + return -1; + } + + idx = virDiskNameToIndex(name); + + if (idx < 0) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Could not parse valid disk index from '%s'", name); + return -1; + } + + /* Each of the 4 SCSI controllers offers 15 IDs for devices */ + if (idx >= (4 * 15)) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "SCSI disk index (parsed from '%s') is too large", name); + return -1; + } + + *controller = idx / 15; + *id = idx % 15; + + /* Skip the controller ifself with ID 7 */ + if (*id >= 7) { + ++(*id); + } + + return 0; +} + + + +int +esxVMX_IDEDiskNameToControllerAndID(virConnectPtr conn, const char *name, + int *controller, int *id) +{ + int idx; + + if (! STRPREFIX(name, "hd")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML attribute 'dev' of entry " + "'devices/disk/target' to start with 'hd'"); + return -1; + } + + idx = virDiskNameToIndex(name); + + if (idx < 0) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Could not parse valid disk index from '%s'", name); + return -1; + } + + /* Each of the 2 IDE controllers offers 2 IDs for devices */ + if (idx >= (2 * 2)) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "IDE disk index (parsed from '%s') is too large", name); + return -1; + } + + *controller = idx / 2; + *id = idx % 2; + + return 0; +} + + + +int +esxVMX_FloppyDiskNameToController(virConnectPtr conn, const char *name, + int *controller) +{ + int idx; + + if (! STRPREFIX(name, "fd")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML attribute 'dev' of entry " + "'devices/disk/target' to start with 'fd'"); + return -1; + } + + idx = virDiskNameToIndex(name); + + if (idx < 0) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Could not parse valid disk index from '%s'", name); + return -1; + } + + if (idx >= 2) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Floppy disk index (parsed from '%s') is too large", name); + return -1; + } + + *controller = idx; + + return 0; +} + + + +int +esxVMX_GatherSCSIControllers(virConnectPtr conn, virDomainDefPtr def, + char *virtualDev[4], int present[4]) +{ + virDomainDiskDefPtr disk; + int i, controller, id; + + /* Check for continuous use of the same virtualDev per SCSI controller */ + for (i = 0; i < def->ndisks; ++i) { + disk = def->disks[i]; + + if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) { + continue; + } + + if (disk->driverName != NULL && + STRCASENEQ(disk->driverName, "buslogic") && + STRCASENEQ(disk->driverName, "lsilogic")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML entry 'devices/disk/target' to be " + "'buslogic' or 'lsilogic' but found '%s'", + disk->driverName); + return -1; + } + + if (esxVMX_SCSIDiskNameToControllerAndID(conn, disk->dst, + &controller, &id) < 0) { + return -1; + } + + present[controller] = 1; + + if (virtualDev[controller] == NULL) { + virtualDev[controller] = disk->driverName; + } else if (STRCASENEQ(virtualDev[controller], disk->driverName)) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Inconsistent driver usage ('%s' is not '%s') on SCSI " + "controller index %d", virtualDev[controller], + disk->driverName, controller); + return -1; + } + } + + return 0; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VMX -> Domain XML + */ + virDomainDefPtr esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, esxVI_APIVersion apiVersion) @@ -416,6 +599,7 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, long long memory = 0; long long numvcpus = 0; char *sched_cpu_affinity = NULL; + char *guestOS = NULL; int controller; int port; int present; @@ -436,6 +620,7 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, def->virtType = VIR_DOMAIN_VIRT_VMWARE; /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */ def->id = -1; + /* vmx:config.version */ if (esxUtil_GetConfigLong(conn, conf, "config.version", &config_version, 0, 0) < 0) { goto failure; @@ -448,6 +633,7 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, goto failure; } + /* vmx:virtualHW.version */ if (esxUtil_GetConfigLong(conn, conf, "virtualHW.version", &virtualHW_version, 0, 0) < 0) { goto failure; @@ -490,19 +676,19 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, goto failure; } - /* def:uuid */ + /* vmx:uuid.bios -> def:uuid */ /* FIXME: Need to handle 'uuid.action = "create"' */ if (esxUtil_GetConfigUUID(conn, conf, "uuid.bios", def->uuid, 1) < 0) { goto failure; } - /* def:name */ + /* vmx:displayName -> def:name */ if (esxUtil_GetConfigString(conn, conf, "displayName", &def->name, 1) < 0) { goto failure; } - /* def:maxmem */ + /* vmx:memsize -> def:maxmem */ if (esxUtil_GetConfigLong(conn, conf, "memsize", &memsize, 32, 1) < 0) { goto failure; } @@ -516,7 +702,7 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, def->maxmem = memsize * 1024; /* Scale from megabytes to kilobytes */ - /* def:memory */ + /* vmx:sched.mem.max -> def:memory */ if (esxUtil_GetConfigLong(conn, conf, "sched.mem.max", &memory, memsize, 1) < 0) { goto failure; @@ -532,7 +718,7 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, def->memory = def->maxmem; } - /* def:vcpus */ + /* vmx:numvcpus -> def:vcpus */ if (esxUtil_GetConfigLong(conn, conf, "numvcpus", &numvcpus, 1, 1) < 0) { goto failure; } @@ -546,7 +732,7 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, def->vcpus = numvcpus; - /* def:cpumask */ + /* vmx:sched.cpu.affinity -> def:cpumask */ // VirtualMachine:config.cpuAffinity.affinitySet if (esxUtil_GetConfigString(conn, conf, "sched.cpu.affinity", &sched_cpu_affinity, 1) < 0) { @@ -630,6 +816,22 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, goto failure; } + /* vmx:guestOS -> def:os.arch */ + if (esxUtil_GetConfigString(conn, conf, "guestOS", &guestOS, 1) < 0) { + goto failure; + } + + if (guestOS != NULL && esxUtil_EqualSuffix(guestOS, "-64")) { + def->os.arch = strdup("x86_64"); + } else { + def->os.arch = strdup("i686"); + } + + if (def->os.arch == NULL) { + virReportOOMError(conn); + goto failure; + } + /* def->emulator def->features*/ @@ -640,8 +842,8 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, /* def:graphics */ /* FIXME */ - /* def:disks: 4 * 16 scsi + 2 * 2 ide + 2 floppy = 70 */ - if (VIR_ALLOC_N(def->disks, 72) < 0) { + /* def:disks: 4 * 15 scsi + 2 * 2 ide + 2 floppy = 66 */ + if (VIR_ALLOC_N(def->disks, 66) < 0) { virReportOOMError(conn); goto failure; } @@ -803,14 +1005,15 @@ esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, } } -cleanup: + cleanup: virConfFree(conf); VIR_FREE(sched_cpu_affinity); + VIR_FREE(guestOS); VIR_FREE(scsi_virtualDev); return def; -failure: + failure: virDomainDefFree(def); def = NULL; @@ -851,7 +1054,7 @@ esxVMX_ParseSCSIController(virConnectPtr conn, virConfPtr conf, int controller, } if (esxUtil_GetConfigString(conn, conf, virtualDev_name, - virtualDev, 0) < 0) { + virtualDev, 1) < 0) { goto failure; } @@ -866,7 +1069,7 @@ esxVMX_ParseSCSIController(virConnectPtr conn, virConfPtr conf, int controller, return 0; -failure: + failure: VIR_FREE(*virtualDev); return -1; @@ -998,8 +1201,9 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus, goto failure; } - (*def)->dst = esxVMX_IndexToDiskName(conn, controller * 16 + id, - "sd"); + (*def)->dst = + esxVMX_IndexToDiskName + (conn, controller * 15 + (id < 7 ? id : id - 1), "sd"); if ((*def)->dst == NULL) { goto failure; @@ -1040,9 +1244,9 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus, } } else { ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "Unsupported bus type '%s' for '%s' device type", - virDomainDiskBusTypeToString (bus), - virDomainDiskDeviceTypeToString (device)); + "Unsupported bus type '%s' for device type '%s'", + virDomainDiskBusTypeToString(bus), + virDomainDiskDeviceTypeToString(device)); goto failure; } } else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) { @@ -1066,15 +1270,15 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus, } } else { ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, - "Unsupported bus type '%s' for '%s' device type", - virDomainDiskBusTypeToString (bus), - virDomainDiskDeviceTypeToString (device)); + "Unsupported bus type '%s' for device type '%s'", + virDomainDiskBusTypeToString(bus), + virDomainDiskDeviceTypeToString(device)); goto failure; } } else { ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Unsupported device type '%s'", - virDomainDiskDeviceTypeToString (device)); + virDomainDiskDeviceTypeToString(device)); goto failure; } @@ -1118,7 +1322,7 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus, if (clientDevice) { /* * Just ignore devices in client mode, because I have no clue how to - * handle them (e.g. assign an image) without the VI client GUI. + * handle them (e.g. assign an image) without the VI Client GUI. */ goto ignore; } @@ -1160,6 +1364,16 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus, } } + if (writeThrough && virtualDev == NULL) { + /* + * FIXME: If no virtualDev is explicit specified need to get + * the default based on the guestOS. The mechanism to + * obtain the default is currently missing + */ + VIR_WARN0("No explicit SCSI driver specified in VMX config, " + "cannot represent explicit specified cachemode"); + } + (*def)->type = VIR_DOMAIN_DISK_TYPE_FILE; (*def)->src = fileName; (*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU @@ -1244,11 +1458,11 @@ esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus, } else { ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Unsupported device type '%s'", - virDomainDiskDeviceTypeToString (device)); + virDomainDiskDeviceTypeToString(device)); goto failure; } -cleanup: + cleanup: VIR_FREE(prefix); VIR_FREE(deviceType); VIR_FREE(fileType); @@ -1256,10 +1470,10 @@ cleanup: return result; -failure: + failure: result = -1; -ignore: + ignore: virDomainDiskDefFree(*def); *def = NULL; @@ -1299,6 +1513,9 @@ esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller, char vnet_name[48] = ""; char *vnet = NULL; + char networkName_name[48] = ""; + char *networkName = NULL; + if (def == NULL || *def != NULL) { ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); return -1; @@ -1325,6 +1542,7 @@ esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller, ESX_BUILD_VMX_NAME(generatedAddress); ESX_BUILD_VMX_NAME(address); ESX_BUILD_VMX_NAME(virtualDev); + ESX_BUILD_VMX_NAME(networkName); ESX_BUILD_VMX_NAME(vnet); /* vmx:present */ @@ -1403,7 +1621,16 @@ esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller, goto failure; } - /* vmx:vnet -> def:data.bridge.brname */ + /* vmx:networkName -> def:data.bridge.brname */ + if ((connectionType == NULL || + STRCASEEQ(connectionType, "bridged") || + STRCASEEQ(connectionType, "custom")) && + esxUtil_GetConfigString(conn, conf, networkName_name, + &networkName, 0) < 0) { + goto failure; + } + + /* vmx:vnet -> def:data.ifname */ if (connectionType != NULL && STRCASEEQ(connectionType, "custom") && esxUtil_GetConfigString(conn, conf, vnet_name, &vnet, 0) < 0) { goto failure; @@ -1413,8 +1640,10 @@ esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller, if (connectionType == NULL || STRCASEEQ(connectionType, "bridged")) { (*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE; (*def)->model = virtualDev; + (*def)->data.bridge.brname = networkName; virtualDev = NULL; + networkName = NULL; } else if (STRCASEEQ(connectionType, "hostonly")) { /* FIXME */ ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, @@ -1430,9 +1659,11 @@ esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller, } else if (STRCASEEQ(connectionType, "custom")) { (*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE; (*def)->model = virtualDev; - (*def)->data.bridge.brname = vnet; + (*def)->data.bridge.brname = networkName; + (*def)->ifname = vnet; virtualDev = NULL; + networkName = NULL; vnet = NULL; } else { ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, @@ -1441,7 +1672,7 @@ esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller, goto failure; } -cleanup: + cleanup: VIR_FREE(connectionType); VIR_FREE(addressType); VIR_FREE(generatedAddress); @@ -1451,10 +1682,10 @@ cleanup: return result; -failure: + failure: result = -1; -ignore: + ignore: virDomainNetDefFree(*def); *def = NULL; @@ -1546,10 +1777,15 @@ esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port, fileName = NULL; } else if (STRCASEEQ(fileType, "pipe")) { - /* FIXME */ - VIR_WARN("Serial port %d has currently unsupported type '%s', " - "ignoring it", port, fileType); - goto ignore; + /* + * FIXME: Differences between client/server and VM/application pipes + * not representable in domain XML form + */ + (*def)->dstPort = port; + (*def)->type = VIR_DOMAIN_CHR_TYPE_PIPE; + (*def)->data.file.path = fileName; + + fileName = NULL; } else { ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Expecting VMX entry '%s' to be 'device', 'file' or 'pipe' " @@ -1557,16 +1793,16 @@ esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port, goto failure; } -cleanup: + cleanup: VIR_FREE(fileType); VIR_FREE(fileName); return result; -failure: + failure: result = -1; -ignore: + ignore: virDomainChrDefFree(*def); *def = NULL; @@ -1664,18 +1900,667 @@ esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port, goto failure; } -cleanup: + cleanup: VIR_FREE(fileType); VIR_FREE(fileName); return result; -failure: + failure: result = -1; -ignore: + ignore: virDomainChrDefFree(*def); *def = NULL; goto cleanup; } + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Domain XML -> VMX + */ + +char * +esxVMX_FormatConfig(virConnectPtr conn, virDomainDefPtr def, + esxVI_APIVersion apiVersion) +{ + int i; + int sched_cpu_affinity_length; + unsigned char zero[VIR_UUID_BUFLEN]; + virBuffer buffer = VIR_BUFFER_INITIALIZER; + char *vmx = NULL; + + memset(zero, 0, VIR_UUID_BUFLEN); + + if (def->virtType != VIR_DOMAIN_VIRT_VMWARE) { /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */ + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting virt type to be '%s' but found '%s'", + virDomainVirtTypeToString(VIR_DOMAIN_VIRT_VMWARE), + virDomainVirtTypeToString(def->virtType)); + return NULL; + } + + /* vmx:config.version */ + virBufferAddLit(&buffer, "config.version = \"8\"\n"); + + /* vmx:virtualHW.version */ + switch (apiVersion) { + case esxVI_APIVersion_25: + virBufferAddLit(&buffer, "virtualHW.version = \"4\"\n"); + break; + + case esxVI_APIVersion_40: + virBufferAddLit(&buffer, "virtualHW.version = \"7\"\n"); + break; + + default: + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting VI API version 2.5 or 4.0"); + goto failure; + } + + /* def:arch -> vmx:guestOS */ + if (def->os.arch == NULL || STRCASEEQ(def->os.arch, "i686")) { + virBufferAddLit(&buffer, "guestOS = \"other\"\n"); + } else if (STRCASEEQ(def->os.arch, "x86_64")) { + virBufferAddLit(&buffer, "guestOS = \"other-64\"\n"); + } else { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML attribute 'arch' of entry 'os/type' " + "to be 'i686' or 'x86_64' but found '%s'", def->os.arch); + goto failure; + } + + /* def:uuid -> vmx:uuid.action, vmx:uuid.bios */ + if (memcmp(def->uuid, zero, VIR_UUID_BUFLEN) == 0) { + virBufferAddLit(&buffer, "uuid.action = \"create\"\n"); + } else { + virBufferVSprintf(&buffer, "uuid.bios = \"%02x %02x %02x %02x %02x %02x " + "%02x %02x-%02x %02x %02x %02x %02x %02x %02x %02x\"\n", + def->uuid[0], def->uuid[1], def->uuid[2], def->uuid[3], + def->uuid[4], def->uuid[5], def->uuid[6], def->uuid[7], + def->uuid[8], def->uuid[9], def->uuid[10], def->uuid[11], + def->uuid[12], def->uuid[13], def->uuid[14], + def->uuid[15]); + } + + /* def:name -> vmx:displayName */ + virBufferVSprintf(&buffer, "displayName = \"%s\"\n", def->name); + + /* def:maxmem -> vmx:memsize */ + if (def->maxmem <= 0 || def->maxmem % 4096 != 0) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML entry 'memory' to be an unsigned " + "integer (multiple of 4096) but found %lld", + (unsigned long long)def->maxmem); + goto failure; + } + + /* Scale from kilobytes to megabytes */ + virBufferVSprintf(&buffer, "memsize = \"%d\"\n", + (int)(def->maxmem / 1024)); + + /* def:memory -> vmx:sched.mem.max */ + if (def->memory < def->maxmem) { + if (def->memory <= 0 || def->memory % 1024 != 0) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML entry 'currentMemory' to be an " + "unsigned integer (multiple of 1024) but found %lld", + (unsigned long long)def->memory); + goto failure; + } + + /* Scale from kilobytes to megabytes */ + virBufferVSprintf(&buffer, "sched.mem.max = \"%d\"\n", + (int)(def->memory / 1024)); + } + + /* vmx:numvcpus -> def:vcpus */ + if (def->vcpus <= 0 || (def->vcpus % 2 != 0 && def->vcpus != 1)) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML entry 'vcpu' to be an unsigned " + "integer (1 or a multiple of 2) but found %d", + (int)def->vcpus); + goto failure; + } + + virBufferVSprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus); + + /* def:cpumask -> vmx:sched.cpu.affinity */ + if (def->cpumasklen > 0) { + virBufferAddLit(&buffer, "sched.cpu.affinity = \""); + + sched_cpu_affinity_length = 0; + + for (i = 0; i < def->cpumasklen; ++i) { + if (def->cpumask[i]) { + ++sched_cpu_affinity_length; + } + } + + if (sched_cpu_affinity_length < def->vcpus) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML attribute 'cpuset' of entry " + "'vcpu' to contains at least %d CPU(s)", + (int)def->vcpus); + goto failure; + } + + for (i = 0; i < def->cpumasklen; ++i) { + if (def->cpumask[i]) { + virBufferVSprintf(&buffer, "%d", i); + + if (sched_cpu_affinity_length > 1) { + virBufferAddChar(&buffer, ','); + } + + --sched_cpu_affinity_length; + } + } + + virBufferAddLit(&buffer, "\"\n"); + } + + /* def:disks */ + int scsi_present[4] = { 0, 0, 0, 0 }; + char *scsi_virtualDev[4] = { NULL, NULL, NULL, NULL }; + + if (esxVMX_GatherSCSIControllers(conn, def, scsi_virtualDev, + scsi_present) < 0) { + goto failure; + } + + for (i = 0; i < 4; ++i) { + if (scsi_present[i]) { + virBufferVSprintf(&buffer, "scsi%d.present = \"true\"\n", i); + + if (scsi_virtualDev[i] != NULL) { + virBufferVSprintf(&buffer, "scsi%d.virtualDev = \"%s\"\n", i, + scsi_virtualDev[i]); + } + } + } + + for (i = 0; i < def->ndisks; ++i) { + switch (def->disks[i]->device) { + case VIR_DOMAIN_DISK_DEVICE_DISK: + if (esxVMX_FormatHardDisk(conn, def->disks[i], &buffer) < 0) { + goto failure; + } + + break; + + case VIR_DOMAIN_DISK_DEVICE_CDROM: + if (esxVMX_FormatCDROM(conn, def->disks[i], &buffer) < 0) { + goto failure; + } + + break; + + case VIR_DOMAIN_DISK_DEVICE_FLOPPY: + if (esxVMX_FormatFloppy(conn, def->disks[i], &buffer) < 0) { + goto failure; + } + + break; + + default: + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Unsuppotred disk device type '%s'", + virDomainDiskDeviceTypeToString(def->disks[i]->device)); + goto failure; + } + } + + /* def:fss */ + /* FIXME */ + + /* def:nets */ + for (i = 0; i < def->nnets; ++i) { + if (esxVMX_FormatEthernet(conn, def->nets[i], i, &buffer) < 0) { + goto failure; + } + } + + /* def:inputs */ + /* FIXME */ + + /* def:sounds */ + /* FIXME */ + + /* def:hostdevs */ + /* FIXME */ + + /* def:serials */ + for (i = 0; i < def->nserials; ++i) { + if (esxVMX_FormatSerial(conn, def->serials[i], &buffer) < 0) { + goto failure; + } + } + + /* def:parallels */ + for (i = 0; i < def->nparallels; ++i) { + if (esxVMX_FormatParallel(conn, def->parallels[i], &buffer) < 0) { + goto failure; + } + } + + /* Get final VMX output */ + if (virBufferError(&buffer)) { + virReportOOMError(conn); + goto failure; + } + + vmx = virBufferContentAndReset(&buffer); + + return vmx; + + failure: + if (vmx == NULL) { + vmx = virBufferContentAndReset(&buffer); + } + + VIR_FREE(vmx); + + return NULL; +} + + + +int +esxVMX_FormatHardDisk(virConnectPtr conn, virDomainDiskDefPtr def, + virBufferPtr buffer) +{ + int controller, id; + const char *busName = NULL; + const char *entryPrefix = NULL; + const char *deviceTypePrefix = NULL; + + if (def->device != VIR_DOMAIN_DISK_DEVICE_DISK) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); + return -1; + } + + if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) { + busName = "SCSI"; + entryPrefix = "scsi"; + deviceTypePrefix = "scsi"; + + if (esxVMX_SCSIDiskNameToControllerAndID(conn, def->dst, + &controller, &id) < 0) { + return -1; + } + } else if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) { + busName = "IDE"; + entryPrefix = "ide"; + deviceTypePrefix = "ata"; + + if (esxVMX_IDEDiskNameToControllerAndID(conn, def->dst, + &controller, &id) < 0) { + return -1; + } + } else { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Unsupported bus type '%s' for harddisk", + virDomainDiskBusTypeToString(def->bus)); + return -1; + } + + if (def->type != VIR_DOMAIN_DISK_TYPE_FILE) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "%s harddisk '%s' has unsupported type '%s', expecting '%s'", + busName, def->dst, virDomainDiskTypeToString(def->type), + virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE)); + return -1; + } + + virBufferVSprintf(buffer, "%s%d:%d.present = \"true\"\n", + entryPrefix, controller, id); + virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"%s-hardDisk\"\n", + entryPrefix, controller, id, deviceTypePrefix); + + if (def->src != NULL) { + if (! esxUtil_EqualSuffix(def->src, ".vmdk")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Image file for %s harddisk '%s' has unsupported suffix, " + "expecting '.vmdk'", busName, def->dst); + return -1; + } + + virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n", + entryPrefix, controller, id, def->src); + } + + if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) { + if (def->cachemode == VIR_DOMAIN_DISK_CACHE_WRITETHRU) { + virBufferVSprintf(buffer, "%s%d:%d.writeThrough = \"true\"\n", + entryPrefix, controller, id); + } else if (def->cachemode != VIR_DOMAIN_DISK_CACHE_DEFAULT) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "%s harddisk '%s' has unsupported cache mode '%s'", + busName, def->dst, + virDomainDiskCacheTypeToString(def->cachemode)); + return -1; + } + } + + return 0; +} + + + +int +esxVMX_FormatCDROM(virConnectPtr conn, virDomainDiskDefPtr def, + virBufferPtr buffer) +{ + int controller, id; + const char *busName = NULL; + const char *entryPrefix = NULL; + + if (def->device != VIR_DOMAIN_DISK_DEVICE_CDROM) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); + return -1; + } + + if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI) { + busName = "SCSI"; + entryPrefix = "scsi"; + + if (esxVMX_SCSIDiskNameToControllerAndID(conn, def->dst, + &controller, &id) < 0) { + return -1; + } + } else if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) { + busName = "IDE"; + entryPrefix = "ide"; + + if (esxVMX_IDEDiskNameToControllerAndID(conn, def->dst, + &controller, &id) < 0) { + return -1; + } + } else { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Unsupported bus type '%s' for cdrom", + virDomainDiskBusTypeToString(def->bus)); + return -1; + } + + virBufferVSprintf(buffer, "%s%d:%d.present = \"true\"\n", + entryPrefix, controller, id); + + if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) { + virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"cdrom-image\"\n", + entryPrefix, controller, id); + } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) { + virBufferVSprintf(buffer, "%s%d:%d.deviceType = \"atapi-cdrom\"\n", + entryPrefix, controller, id); + } else { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "%s cdrom '%s' has unsupported type '%s', expecting '%s' " + "or '%s'", busName, def->dst, + virDomainDiskTypeToString(def->type), + virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE), + virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_BLOCK)); + return -1; + } + + if (def->src != NULL) { + if (def->type == VIR_DOMAIN_DISK_TYPE_FILE && + ! esxUtil_EqualSuffix(def->src, ".iso")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Image file for %s cdrom '%s' has unsupported suffix, " + "expecting '.iso'", busName, def->dst); + return -1; + } + + virBufferVSprintf(buffer, "%s%d:%d.fileName = \"%s\"\n", + entryPrefix, controller, id, def->src); + } + + return 0; +} + + + +int +esxVMX_FormatFloppy(virConnectPtr conn, virDomainDiskDefPtr def, + virBufferPtr buffer) +{ + int controller; + + if (def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument"); + return -1; + } + + if (esxVMX_FloppyDiskNameToController(conn, def->dst, &controller) < 0) { + return -1; + } + + virBufferVSprintf(buffer, "floppy%d.present = \"true\"\n", controller); + + if (def->type == VIR_DOMAIN_DISK_TYPE_FILE) { + virBufferVSprintf(buffer, "floppy%d.fileType = \"file\"\n", + controller); + } else if (def->type == VIR_DOMAIN_DISK_TYPE_BLOCK) { + virBufferVSprintf(buffer, "floppy%d.fileType = \"device\"\n", + controller); + } else { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Floppy '%s' has unsupported type '%s', expecting '%s' " + "or '%s'", def->dst, + virDomainDiskTypeToString(def->type), + virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_FILE), + virDomainDiskTypeToString(VIR_DOMAIN_DISK_TYPE_BLOCK)); + return -1; + } + + if (def->src != NULL) { + if (def->type == VIR_DOMAIN_DISK_TYPE_FILE && + ! esxUtil_EqualSuffix(def->src, ".flp")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Image file for floppy '%s' has unsupported suffix, " + "expecting '.flp'", def->dst); + return -1; + } + + virBufferVSprintf(buffer, "floppy%d.fileName = \"%s\"\n", controller, + def->src); + } + + return 0; +} + + + +int +esxVMX_FormatEthernet(virConnectPtr conn, virDomainNetDefPtr def, + int controller, virBufferPtr buffer) +{ + char mac_string[VIR_MAC_STRING_BUFLEN]; + + if (controller < 0 || controller > 3) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Ethernet controller index %d out of [0..3] range", + controller); + return -1; + } + + virBufferVSprintf(buffer, "ethernet%d.present = \"true\"\n", controller); + + /* def:model -> vmx:virtualDev */ + if (def->model != NULL) { + if (STRCASENEQ(def->model, "vlance") && + STRCASENEQ(def->model, "vmxnet") && + STRCASENEQ(def->model, "e1000")) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML entry 'devices/interfase/model' " + "to be 'vlance' or 'vmxnet' or 'e1000' but found '%s'", + def->model); + return -1; + } + + virBufferVSprintf(buffer, "ethernet%d.virtualDev = \"%s\"\n", + controller, def->model); + } + + /* def:type, def:ifname -> vmx:connectionType */ + switch (def->type) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + virBufferVSprintf(buffer, "ethernet%d.networkName = \"%s\"\n", + controller, def->data.bridge.brname); + + if (def->ifname != NULL) { + virBufferVSprintf(buffer, "ethernet%d.connectionType = \"custom\"\n", + controller); + virBufferVSprintf(buffer, "ethernet%d.vnet = \"%s\"\n", + controller, def->ifname); + } else { + virBufferVSprintf(buffer, "ethernet%d.connectionType = \"bridged\"\n", + controller); + } + + break; + + default: + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Unsupported net type '%s'", + virDomainNetTypeToString(def->type)); + return -1; + } + + virFormatMacAddr(def->mac, mac_string); + + if (def->mac[0] == 0x00 && def->mac[1] == 0x0c && def->mac[2] == 0x29) { + virBufferVSprintf(buffer, "ethernet%d.addressType = \"generated\"\n", + controller); + virBufferVSprintf(buffer, "ethernet%d.generatedAddress = \"%s\"\n", + controller, mac_string); + } else if (def->mac[0] == 0x00 && def->mac[1] == 0x50 && + def->mac[2] == 0x56) { + virBufferVSprintf(buffer, "ethernet%d.addressType = \"static\"\n", + controller); + virBufferVSprintf(buffer, "ethernet%d.address = \"%s\"\n", + controller, mac_string); + } else { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Unsupported MAC address prefix '%02X:%02X:%02X', expecting " + "'00:0c:29' or '00:50:56'", + def->mac[0], def->mac[1], def->mac[2]); + return -1; + } + + return 0; +} + + + +int +esxVMX_FormatSerial(virConnectPtr conn, virDomainChrDefPtr def, + virBufferPtr buffer) +{ + if (def->dstPort < 0 || def->dstPort > 3) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Serial port index %d out of [0..3] range", def->dstPort); + return -1; + } + + if (def->data.file.path == NULL) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML attribute 'path' of entry " + "'devices/serial/source' to be present"); + return -1; + } + + virBufferVSprintf(buffer, "serial%d.present = \"true\"\n", def->dstPort); + + /* def:type -> vmx:fileType */ + switch (def->type) { + case VIR_DOMAIN_CHR_TYPE_DEV: + virBufferVSprintf(buffer, "serial%d.fileType = \"device\"\n", + def->dstPort); + break; + + case VIR_DOMAIN_CHR_TYPE_FILE: + virBufferVSprintf(buffer, "serial%d.fileType = \"file\"\n", + def->dstPort); + break; + + case VIR_DOMAIN_CHR_TYPE_PIPE: + virBufferVSprintf(buffer, "serial%d.fileType = \"pipe\"\n", + def->dstPort); + /* FIXME: Based on VI Client GUI default */ + virBufferVSprintf(buffer, "serial%d.pipe.endPoint = \"client\"\n", + def->dstPort); + /* FIXME: Based on VI Client GUI default */ + virBufferVSprintf(buffer, "serial%d.tryNoRxLoss = \"false\"\n", + def->dstPort); + break; + + default: + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Unsupported character device type '%s'", + virDomainChrTypeToString(def->type)); + return -1; + } + + /* def:data.file.path -> vmx:fileName */ + virBufferVSprintf(buffer, "serial%d.fileName = \"%s\"\n", + def->dstPort, def->data.file.path); + + /* vmx:yieldOnMsrRead */ + /* FIXME: Based on VI Client GUI default */ + virBufferVSprintf(buffer, "serial%d.yieldOnMsrRead = \"true\"\n", + def->dstPort); + + return 0; +} + + + +int +esxVMX_FormatParallel(virConnectPtr conn, virDomainChrDefPtr def, + virBufferPtr buffer) +{ + if (def->dstPort < 0 || def->dstPort > 2) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Parallel port index %d out of [0..2] range", def->dstPort); + return -1; + } + + if (def->data.file.path == NULL) { + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Expecting domain XML attribute 'path' of entry " + "'devices/parallel/source' to be present"); + return -1; + } + + virBufferVSprintf(buffer, "parallel%d.present = \"true\"\n", def->dstPort); + + /* def:type -> vmx:fileType */ + switch (def->type) { + case VIR_DOMAIN_CHR_TYPE_DEV: + virBufferVSprintf(buffer, "parallel%d.fileType = \"device\"\n", + def->dstPort); + break; + + case VIR_DOMAIN_CHR_TYPE_FILE: + virBufferVSprintf(buffer, "parallel%d.fileType = \"file\"\n", + def->dstPort); + break; + + default: + ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, + "Unsupported character device type '%s'", + virDomainChrTypeToString(def->type)); + return -1; + } + + /* def:data.file.path -> vmx:fileName */ + virBufferVSprintf(buffer, "parallel%d.fileName = \"%s\"\n", + def->dstPort, def->data.file.path); + + return 0; +} diff --git a/src/esx/esx_vmx.h b/src/esx/esx_vmx.h index 8288003d91..1d77232d22 100644 --- a/src/esx/esx_vmx.h +++ b/src/esx/esx_vmx.h @@ -24,9 +24,33 @@ #define __ESX_VMX_H__ #include "internal.h" +#include "conf.h" #include "domain_conf.h" #include "esx_vi.h" +char * +esxVMX_IndexToDiskName(virConnectPtr conn, int idx, const char *prefix); + +int +esxVMX_SCSIDiskNameToControllerAndID(virConnectPtr conn, const char *name, + int *controller, int *id); +int +esxVMX_IDEDiskNameToControllerAndID(virConnectPtr conn, const char *name, + int *controller, int *id); +int +esxVMX_FloppyDiskNameToController(virConnectPtr conn, const char *name, + int *controller); + +int +esxVMX_GatherSCSIControllers(virConnectPtr conn, virDomainDefPtr conf, + char *virtualDev[4], int present[4]); + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * VMX -> Domain XML + */ + virDomainDefPtr esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, esxVI_APIVersion apiVersion); @@ -35,9 +59,6 @@ int esxVMX_ParseSCSIController(virConnectPtr conn, virConfPtr conf, int controller, int *present, char **virtualDev); -char * -esxVMX_IndexToDiskName(virConnectPtr conn, int idx, const char *prefix); - int esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus, int controller, int id, const char *virtualDev, @@ -54,4 +75,38 @@ int esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port, virDomainChrDefPtr *def); + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Domain XML -> VMX + */ + +char * +esxVMX_FormatConfig(virConnectPtr conn, virDomainDefPtr def, + esxVI_APIVersion apiVersion); + +int +esxVMX_FormatHardDisk(virConnectPtr conn, virDomainDiskDefPtr def, + virBufferPtr buffer); + +int +esxVMX_FormatCDROM(virConnectPtr conn, virDomainDiskDefPtr def, + virBufferPtr buffer); + +int +esxVMX_FormatFloppy(virConnectPtr conn, virDomainDiskDefPtr def, + virBufferPtr buffer); + +int +esxVMX_FormatEthernet(virConnectPtr conn, virDomainNetDefPtr def, + int controller, virBufferPtr buffer); + +int +esxVMX_FormatSerial(virConnectPtr conn, virDomainChrDefPtr def, + virBufferPtr buffer); + +int +esxVMX_FormatParallel(virConnectPtr conn, virDomainChrDefPtr def, + virBufferPtr buffer); + #endif /* __ESX_VMX_H__ */