2009-07-23 20:21:08 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* esx_vmx.c: VMX related methods for the VMware ESX driver
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "virterror_internal.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "esx_util.h"
|
|
|
|
#include "esx_vmx.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
mapping:
|
|
|
|
|
|
|
|
domain-xml <=> vmx
|
|
|
|
|
|
|
|
|
|
|
|
config.version = "8" # essential
|
2009-07-27 12:27:09 +00:00
|
|
|
virtualHW.version = "4" # essential for ESX 3.5
|
|
|
|
virtualHW.version = "7" # essential for ESX 4.0
|
2009-07-23 20:21:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
??? <=> guestOS = "<value>" # essential, FIXME: not representable
|
|
|
|
def->id = <value> <=> ??? # not representable
|
|
|
|
def->uuid = <value> <=> uuid.bios = "<value>"
|
|
|
|
def->name = <value> <=> displayName = "<value>"
|
|
|
|
def->maxmem = <value kilobyte> <=> memsize = "<value megabyte>" # must be a multiple of 4, defaults to 32
|
|
|
|
def->memory = <value kilobyte> <=> sched.mem.max = "<value megabyte>" # defaults to "unlimited" -> def->memory = def->maxmem
|
|
|
|
def->vcpus = <value> <=> numvcpus = "<value>" # must be 1 or a multiple of 2, defaults to 1
|
|
|
|
def->cpumask = <uint list> <=> sched.cpu.affinity = "<uint list>"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
## os ##########################################################################
|
|
|
|
|
|
|
|
def->os
|
|
|
|
|
|
|
|
->type = "hvm"
|
|
|
|
->arch
|
|
|
|
->machine
|
|
|
|
->nBootDevs
|
|
|
|
->bootDevs
|
|
|
|
->init
|
|
|
|
->kernel
|
|
|
|
->initrd
|
|
|
|
->cmdline
|
|
|
|
->root
|
|
|
|
->loader
|
|
|
|
->bootloader
|
|
|
|
->bootloaderArgs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
## disks #######################################################################
|
|
|
|
|
|
|
|
scsi[0..3]:[0..6,8..15] -> <controller>:<id>
|
|
|
|
ide[0..1]:[0..1] -> <controller>:<id>
|
|
|
|
floppy[0..1] -> <controller>
|
|
|
|
|
|
|
|
def->disks[0]...
|
|
|
|
|
|
|
|
## disks: scsi hard drive from .vmdk image #####################################
|
|
|
|
|
|
|
|
scsi0.present = "true" # defaults to "false"
|
|
|
|
scsi0:0.present = "true" # defaults to "false"
|
|
|
|
scsi0:0.startConnected = "true" # defaults to "true"
|
|
|
|
|
|
|
|
??? <=> scsi0:0.mode = "persistent" # defaults to "persistent"
|
|
|
|
scsi0:0.mode = "undoable"
|
|
|
|
scsi0:0.mode = "independent-persistent"
|
|
|
|
scsi0:0.mode = "independent-nonpersistent"
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _DISK_TYPE_FILE <=> scsi0:0.deviceType = "scsi-hardDisk" # defaults to ?
|
|
|
|
->device = _DISK_DEVICE_DISK <=> scsi0:0.deviceType = "scsi-hardDisk" # defaults to ?
|
|
|
|
->bus = _DISK_BUS_SCSI
|
|
|
|
->src = <value>.vmdk <=> scsi0:0.fileName = "<value>.vmdk"
|
|
|
|
->dst = sd[<controller> * 16 + <id> mapped to [a-z]+]
|
|
|
|
->driverName = <driver> <=> scsi0.virtualDev = "<driver>" # default depends on guestOS value
|
|
|
|
->driverType
|
|
|
|
->cachemode <=> scsi0:0.writeThrough = "<value>" # defaults to false, true -> _DISK_CACHE_WRITETHRU, false _DISK_CACHE_DEFAULT
|
|
|
|
->readonly
|
|
|
|
->shared
|
|
|
|
->slotnum
|
|
|
|
|
|
|
|
|
|
|
|
## 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"
|
|
|
|
|
|
|
|
??? <=> ide0:0.mode = "persistent" # defaults to "persistent"
|
|
|
|
ide0:0.mode = "undoable"
|
|
|
|
ide0:0.mode = "independent-persistent"
|
|
|
|
ide0:0.mode = "independent-nonpersistent"
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _DISK_TYPE_FILE <=> ide0:0.deviceType = "ata-hardDisk" # defaults to ?
|
|
|
|
->device = _DISK_DEVICE_DISK <=> ide0:0.deviceType = "ata-hardDisk" # defaults to ?
|
|
|
|
->bus = _DISK_BUS_IDE
|
|
|
|
->src = <value>.vmdk <=> ide0:0.fileName = "<value>.vmdk"
|
|
|
|
->dst = hd[<controller> * 2 + <id> mapped to [a-z]+]
|
|
|
|
->driverName
|
|
|
|
->driverType
|
|
|
|
->cachemode <=> ide0:0.writeThrough = "<value>" # defaults to false, true -> _DISK_CACHE_WRITETHRU, false _DISK_CACHE_DEFAULT
|
|
|
|
->readonly
|
|
|
|
->shared
|
|
|
|
->slotnum
|
|
|
|
|
|
|
|
|
|
|
|
## disks: scsi cdrom from .iso image ###########################################
|
|
|
|
|
|
|
|
scsi0.present = "true" # defaults to "false"
|
|
|
|
scsi0:0.present = "true" # defaults to "false"
|
|
|
|
scsi0:0.startConnected = "true" # defaults to "true"
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _DISK_TYPE_FILE <=> scsi0:0.deviceType = "cdrom-image" # defaults to ?
|
|
|
|
->device = _DISK_DEVICE_CDROM <=> scsi0:0.deviceType = "cdrom-image" # defaults to ?
|
|
|
|
->bus = _DISK_BUS_SCSI
|
|
|
|
->src = <value>.iso <=> scsi0:0.fileName = "<value>.iso"
|
|
|
|
->dst = sd[<controller> * 16 + <id> mapped to [a-z]+]
|
|
|
|
->driverName = <driver> <=> scsi0.virtualDev = "<driver>" # default depends on guestOS value
|
|
|
|
->driverType
|
|
|
|
->cachemode
|
|
|
|
->readonly
|
|
|
|
->shared
|
|
|
|
->slotnum
|
|
|
|
|
|
|
|
|
|
|
|
## 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"
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _DISK_TYPE_FILE <=> ide0:0.deviceType = "cdrom-image" # defaults to ?
|
|
|
|
->device = _DISK_DEVICE_CDROM <=> ide0:0.deviceType = "cdrom-image" # defaults to ?
|
|
|
|
->bus = _DISK_BUS_IDE
|
|
|
|
->src = <value>.iso <=> ide0:0.fileName = "<value>.iso"
|
|
|
|
->dst = hd[<controller> * 2 + <id> mapped to [a-z]+]
|
|
|
|
->driverName
|
|
|
|
->driverType
|
|
|
|
->cachemode
|
|
|
|
->readonly
|
|
|
|
->shared
|
|
|
|
->slotnum
|
|
|
|
|
|
|
|
|
|
|
|
## disks: scsi cdrom from host device ##########################################
|
|
|
|
|
|
|
|
scsi0.present = "true" # defaults to "false"
|
|
|
|
scsi0:0.present = "true" # defaults to "false"
|
|
|
|
scsi0:0.startConnected = "true" # defaults to "true"
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _DISK_TYPE_BLOCK <=> scsi0:0.deviceType = "atapi-cdrom" # defaults to ?
|
|
|
|
->device = _DISK_DEVICE_CDROM <=> scsi0:0.deviceType = "atapi-cdrom" # defaults to ?
|
|
|
|
->bus = _DISK_BUS_SCSI
|
|
|
|
->src = <value> <=> scsi0:0.fileName = "<value>" # e.g. "/dev/scd0" ?
|
|
|
|
->dst = sd[<controller> * 16 + <id> mapped to [a-z]+]
|
|
|
|
->driverName = <driver> <=> scsi0.virtualDev = "<driver>" # default depends on guestOS value
|
|
|
|
->driverType
|
|
|
|
->cachemode
|
|
|
|
->readonly
|
|
|
|
->shared
|
|
|
|
->slotnum
|
|
|
|
|
|
|
|
|
|
|
|
## 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"
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _DISK_TYPE_BLOCK <=> ide0:0.deviceType = "atapi-cdrom" # defaults to ?
|
|
|
|
->device = _DISK_DEVICE_CDROM <=> ide0:0.deviceType = "atapi-cdrom" # defaults to ?
|
|
|
|
->bus = _DISK_BUS_IDE
|
|
|
|
->src = <value> <=> ide0:0.fileName = "<value>" # e.g. "/dev/scd0"
|
|
|
|
->dst = hd[<controller> * 2 + <id> mapped to [a-z]+]
|
|
|
|
->driverName
|
|
|
|
->driverType
|
|
|
|
->cachemode
|
|
|
|
->readonly
|
|
|
|
->shared
|
|
|
|
->slotnum
|
|
|
|
|
|
|
|
|
|
|
|
## disks: floppy from .flp image ###############################################
|
|
|
|
|
|
|
|
floppy0.present = "true" # defaults to "false"
|
|
|
|
floppy0.startConnected = "true" # defaults to "true"
|
|
|
|
floppy0.clientDevice = "false" # defaults to "false"
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _DISK_TYPE_FILE <=> floppy0.fileType = "file" # defaults to ?
|
|
|
|
->device = _DISK_DEVICE_FLOPPY
|
|
|
|
->bus = _DISK_BUS_FDC
|
|
|
|
->src = <value>.flp <=> floppy0.fileName = "<value>.flp"
|
|
|
|
->dst = fd[<controller> mapped to [a-z]+]
|
|
|
|
->driverName
|
|
|
|
->driverType
|
|
|
|
->cachemode
|
|
|
|
->readonly
|
|
|
|
->shared
|
|
|
|
->slotnum
|
|
|
|
|
|
|
|
|
|
|
|
## disks: floppy from host device ##############################################
|
|
|
|
|
|
|
|
floppy0.present = "true" # defaults to "false"
|
|
|
|
floppy0.startConnected = "true" # defaults to "true"
|
|
|
|
floppy0.clientDevice = "false" # defaults to "false"
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _DISK_TYPE_BLOCK <=> floppy0.fileType = "device" # defaults to ?
|
|
|
|
->device = _DISK_DEVICE_FLOPPY
|
|
|
|
->bus = _DISK_BUS_FDC
|
|
|
|
->src = <value> <=> floppy0.fileName = "<value>" # e.g. "/dev/fd0"
|
|
|
|
->dst = fd[<controller> mapped to [a-z]+]
|
|
|
|
->driverName
|
|
|
|
->driverType
|
|
|
|
->cachemode
|
|
|
|
->readonly
|
|
|
|
->shared
|
|
|
|
->slotnum
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
## nets ########################################################################
|
|
|
|
|
|
|
|
ethernet[0..3] -> <controller>
|
|
|
|
|
|
|
|
ethernet0.present = "true" # defaults to "false"
|
|
|
|
ethernet0.startConnected = "true" # defaults to "true"
|
|
|
|
|
|
|
|
ethernet0.networkName = "VM Network" # FIXME
|
|
|
|
|
|
|
|
def->nets[0]...
|
|
|
|
->model = <model> <=> ethernet0.virtualDev = "<model>" # default depends on guestOS value
|
|
|
|
|
|
|
|
|
|
|
|
ethernet0.addressType = "generated" # default to "generated"
|
|
|
|
ethernet0.generatedAddressOffset = "0" # ?
|
|
|
|
->mac = <value> <=> ethernet0.generatedAddress = "<value>"
|
|
|
|
|
|
|
|
|
|
|
|
ethernet0.addressType = "static" # default to "generated"
|
|
|
|
->mac = <value> <=> ethernet0.address = "<value>"
|
|
|
|
|
|
|
|
# 00:0c:29 prefix for autogenerated mac's
|
|
|
|
# 00:50:56 prefix for manual configured mac's
|
|
|
|
# 00:05:69 old prefix from esx 1.5
|
|
|
|
|
|
|
|
|
|
|
|
## nets: bridged ###############################################################
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _NET_TYPE_BRIDGE <=> ethernet0.connectionType = "bridged" # defaults to "bridged"
|
|
|
|
|
|
|
|
|
|
|
|
## nets: hostonly ##############################################################
|
|
|
|
|
|
|
|
... # FIXME: maybe not supported by ESX?
|
|
|
|
->type = _NET_TYPE_NETWORK <=> ethernet0.connectionType = "hostonly" # defaults to "bridged"
|
|
|
|
|
|
|
|
|
|
|
|
## nets: nat ###################################################################
|
|
|
|
|
|
|
|
... # FIXME: maybe not supported by ESX?
|
|
|
|
->type = _NET_TYPE_USER <=> ethernet0.connectionType = "nat" # defaults to "bridged"
|
|
|
|
|
|
|
|
|
|
|
|
## nets: custom ################################################################
|
|
|
|
|
|
|
|
...
|
|
|
|
->type = _NET_TYPE_BRIDGE <=> ethernet0.connectionType = "custom" # defaults to "bridged"
|
|
|
|
->data.bridge.brname = <value> <=> ethernet0.vnet = "<value>"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
## serials #####################################################################
|
|
|
|
|
|
|
|
serial[0..3] -> <port>
|
|
|
|
|
|
|
|
serial0.present = "true" # defaults to "false"
|
|
|
|
serial0.startConnected = "true" # defaults to "true"
|
|
|
|
|
|
|
|
def->serials[0]...
|
|
|
|
->dstPort = <port>
|
|
|
|
|
|
|
|
|
|
|
|
## serials: device #############################################################
|
|
|
|
|
|
|
|
->type = _CHR_TYPE_DEV <=> serial0.fileType = "device"
|
|
|
|
->data.file.path = <value> <=> serial0.fileName = "<value>" # e.g. "/dev/ttyS0"
|
|
|
|
??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable
|
|
|
|
|
|
|
|
|
|
|
|
## serials: file ###############################################################
|
|
|
|
|
|
|
|
->type = _CHR_TYPE_FILE <=> serial0.fileType = "file"
|
|
|
|
->data.file.path = <value> <=> serial0.fileName = "<value>" # e.g. "serial0.file"
|
|
|
|
??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable
|
|
|
|
|
|
|
|
|
|
|
|
## serials: pipe, far end -> app ###############################################
|
|
|
|
|
|
|
|
->type = _CHR_TYPE_PIPE <=> serial0.fileType = "pipe"
|
|
|
|
->data.file.path = <value> <=> serial0.fileName = "<value>" # e.g. "serial0.pipe"
|
|
|
|
??? <=> serial0.pipe.endPoint = "client" # defaults to "server", FIXME: not representable
|
|
|
|
??? <=> serial0.tryNoRxLoss = "true" # defaults to "false", FIXME: not representable
|
|
|
|
|
|
|
|
->type = _CHR_TYPE_PIPE <=> serial0.fileType = "pipe"
|
|
|
|
->data.file.path = <value> <=> serial0.fileName = "<value>" # e.g. "serial0.pipe"
|
|
|
|
??? <=> serial0.pipe.endPoint = "server" # defaults to "server", FIXME: not representable
|
|
|
|
??? <=> serial0.tryNoRxLoss = "true" # defaults to "false", FIXME: not representable
|
|
|
|
|
|
|
|
|
|
|
|
## serials: pipe, far end -> vm ################################################
|
|
|
|
|
|
|
|
->type = _CHR_TYPE_PIPE <=> serial0.fileType = "pipe"
|
|
|
|
->data.file.path = <value> <=> serial0.fileName = "<value>" # e.g. "serial0.pipe"
|
|
|
|
??? <=> serial0.pipe.endPoint = "client" # defaults to "server", FIXME: not representable
|
|
|
|
??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable
|
|
|
|
|
|
|
|
->type = _CHR_TYPE_PIPE <=> serial0.fileType = "pipe"
|
|
|
|
->data.file.path = <value> <=> serial0.fileName = "<value>" # e.g. "serial0.pipe"
|
|
|
|
??? <=> serial0.pipe.endPoint = "server" # defaults to "server", FIXME: not representable
|
|
|
|
??? <=> serial0.tryNoRxLoss = "false" # defaults to "false", FIXME: not representable
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
################################################################################
|
|
|
|
## parallels ###################################################################
|
|
|
|
|
|
|
|
parallel[0..2] -> <port>
|
|
|
|
|
|
|
|
parallel0.present = "true" # defaults to "false"
|
|
|
|
parallel0.startConnected = "true" # defaults to "true"
|
|
|
|
|
|
|
|
def->parallels[0]...
|
|
|
|
->dstPort = <port>
|
|
|
|
|
|
|
|
|
|
|
|
## parallels: device #############################################################
|
|
|
|
|
|
|
|
->type = _CHR_TYPE_DEV <=> parallel0.fileType = "device"
|
|
|
|
->data.file.path = <value> <=> parallel0.fileName = "<value>" # e.g. "/dev/parport0"
|
|
|
|
??? <=> parallel0.bidirectional = "<value>" # defaults to ?, FIXME: not representable
|
|
|
|
|
|
|
|
|
|
|
|
## parallels: file #############################################################
|
|
|
|
|
|
|
|
->type = _CHR_TYPE_FILE <=> parallel0.fileType = "file"
|
|
|
|
->data.file.path = <value> <=> parallel0.fileName = "<value>" # e.g. "parallel0.file"
|
|
|
|
??? <=> parallel0.bidirectional = "<value>" # must be "false" for fileType = "file", FIXME: not representable
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_ESX
|
|
|
|
|
|
|
|
#define ESX_ERROR(conn, code, fmt...) \
|
|
|
|
virReportErrorHelper (conn, VIR_FROM_ESX, code, __FILE__, __FUNCTION__, \
|
|
|
|
__LINE__, fmt)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define ESX_BUILD_VMX_NAME(_suffix) \
|
|
|
|
do { \
|
|
|
|
strncpy(_suffix##_name, prefix, sizeof (_suffix##_name) - 1); \
|
|
|
|
_suffix##_name[sizeof (_suffix##_name) - 1] = '\0'; \
|
|
|
|
strncat(_suffix##_name, "."#_suffix, \
|
|
|
|
sizeof (_suffix##_name) - 1 - strlen(_suffix##_name)); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
virDomainDefPtr
|
2009-07-27 12:27:09 +00:00
|
|
|
esxVMX_ParseConfig(virConnectPtr conn, const char *vmx, int serverVersion)
|
2009-07-23 20:21:08 +00:00
|
|
|
{
|
|
|
|
virConfPtr conf = NULL;
|
|
|
|
virDomainDefPtr def = NULL;
|
|
|
|
long long config_version = 0;
|
|
|
|
long long virtualHW_version = 0;
|
|
|
|
long long memsize = 0;
|
|
|
|
long long memory = 0;
|
|
|
|
long long numvcpus = 0;
|
|
|
|
char *sched_cpu_affinity = NULL;
|
|
|
|
int controller;
|
|
|
|
int port;
|
|
|
|
int present;
|
|
|
|
char *scsi_virtualDev = NULL;
|
|
|
|
int id;
|
|
|
|
|
|
|
|
conf = virConfReadMem(vmx, strlen(vmx), VIR_CONF_FLAG_VMX_FORMAT);
|
|
|
|
|
|
|
|
if (conf == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(def) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->virtType = VIR_DOMAIN_VIRT_VMWARE; /* FIXME: maybe add VIR_DOMAIN_VIRT_ESX ? */
|
|
|
|
def->id = -1;
|
|
|
|
|
|
|
|
if (esxUtil_GetConfigLong(conn, conf, "config.version",
|
|
|
|
&config_version, 0, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config_version != 8) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
2009-07-27 12:27:09 +00:00
|
|
|
"Expecting VMX entry 'config.version' to be 8 but found "
|
|
|
|
"%lld", config_version);
|
2009-07-23 20:21:08 +00:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (esxUtil_GetConfigLong(conn, conf, "virtualHW.version",
|
|
|
|
&virtualHW_version, 0, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
2009-07-27 12:27:09 +00:00
|
|
|
switch (serverVersion) {
|
|
|
|
case 35:
|
|
|
|
if (virtualHW_version != 4) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry 'virtualHW.version' to be 4 for "
|
|
|
|
"server version 3.5 but found %lld", virtualHW_version);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 40:
|
|
|
|
if (virtualHW_version != 7) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry 'virtualHW.version' to be 7 for "
|
|
|
|
"server version 4.0 but found %lld", virtualHW_version);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -1:
|
|
|
|
if (virtualHW_version != 4 && virtualHW_version != 7) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry 'virtualHW.version' to be 4 or 7 "
|
|
|
|
"but found %lld", virtualHW_version);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-07-23 20:21:08 +00:00
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
2009-07-27 12:27:09 +00:00
|
|
|
"Expecting server version 3.5 or 4.0 but got %d",
|
|
|
|
serverVersion);
|
2009-07-23 20:21:08 +00:00
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:uuid */
|
|
|
|
/* FIXME: Need to handle 'uuid.action = "create"' */
|
|
|
|
if (esxUtil_GetConfigUUID(conn, conf, "uuid.bios", def->uuid, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:name */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, "displayName",
|
|
|
|
&def->name, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:maxmem */
|
|
|
|
if (esxUtil_GetConfigLong(conn, conf, "memsize", &memsize, 32, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memsize <= 0 || memsize % 4 != 0) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry 'memsize' to be an unsigned "
|
|
|
|
"integer (multiple of 4) but found %lld", memsize);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->maxmem = memsize * 1024; /* Scale from megabytes to kilobytes */
|
|
|
|
|
|
|
|
/* def:memory */
|
|
|
|
if (esxUtil_GetConfigLong(conn, conf, "sched.mem.max", &memory,
|
|
|
|
memsize, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memory < 0) {
|
|
|
|
memory = memsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->memory = memory * 1024; /* Scale from megabytes to kilobytes */
|
|
|
|
|
|
|
|
if (def->memory > def->maxmem) {
|
|
|
|
def->memory = def->maxmem;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:vcpus */
|
|
|
|
if (esxUtil_GetConfigLong(conn, conf, "numvcpus", &numvcpus, 1, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numvcpus <= 0 || (numvcpus % 2 != 0 && numvcpus != 1)) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry 'numvcpus' to be an unsigned "
|
|
|
|
"integer (1 or a multiple of 2) but found %lld", numvcpus);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->vcpus = numvcpus;
|
|
|
|
|
|
|
|
/* def:cpumask */
|
|
|
|
// VirtualMachine:config.cpuAffinity.affinitySet
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, "sched.cpu.affinity",
|
|
|
|
&sched_cpu_affinity, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sched_cpu_affinity != NULL && STRNEQ(sched_cpu_affinity, "all")) {
|
|
|
|
const char *current = sched_cpu_affinity;
|
|
|
|
int number, count = 0;
|
|
|
|
|
|
|
|
def->cpumasklen = 0;
|
|
|
|
|
|
|
|
if (VIR_ALLOC_N(def->cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (*current != '\0') {
|
|
|
|
virSkipSpaces(¤t);
|
|
|
|
|
|
|
|
number = virParseNumber(¤t);
|
|
|
|
|
|
|
|
if (number < 0) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry 'sched.cpu.affinity' to be "
|
|
|
|
"a comma separated list of unsigned integers but "
|
|
|
|
"found '%s'", sched_cpu_affinity);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (number >= VIR_DOMAIN_CPUMASK_LEN) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"VMX entry 'sched.cpu.affinity' contains a %d, this "
|
|
|
|
"value is too large", number);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (number + 1 > def->cpumasklen) {
|
|
|
|
def->cpumasklen = number + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->cpumask[number] = 1;
|
|
|
|
++count;
|
|
|
|
|
|
|
|
virSkipSpaces(¤t);
|
|
|
|
|
|
|
|
if (*current == ',') {
|
|
|
|
++current;
|
|
|
|
} else if (*current == '\0') {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry 'sched.cpu.affinity' to be "
|
|
|
|
"a comma separated list of unsigned integers but "
|
|
|
|
"found '%s'", sched_cpu_affinity);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
virSkipSpaces(¤t);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count < numvcpus) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry 'sched.cpu.affinity' to contain "
|
|
|
|
"at least as many values as 'numvcpus' (%lld) but "
|
|
|
|
"found only %d value(s)", numvcpus, count);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:lifecycle */
|
|
|
|
def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
|
|
|
|
def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
|
|
|
|
def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
|
|
|
|
|
|
|
|
/* def:os */
|
|
|
|
def->os.type = strdup("hvm");
|
|
|
|
|
|
|
|
if (def->os.type == NULL) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
def->emulator
|
|
|
|
def->features*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
def->localtime*/
|
|
|
|
|
|
|
|
/* def:graphics */
|
|
|
|
/* FIXME */
|
|
|
|
|
|
|
|
/* def:disks: 4 * 16 scsi + 2 * 2 ide + 2 floppy = 70 */
|
|
|
|
if (VIR_ALLOC_N(def->disks, 72) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->ndisks = 0;
|
|
|
|
|
|
|
|
/* def:disks (scsi) */
|
|
|
|
for (controller = 0; controller < 4; ++controller) {
|
|
|
|
VIR_FREE(scsi_virtualDev);
|
|
|
|
|
|
|
|
if (esxVMX_ParseSCSIController(conn, conf, controller,
|
|
|
|
&present, &scsi_virtualDev) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! present) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (id = 0; id < 16; ++id) {
|
|
|
|
if (id == 7) {
|
|
|
|
/*
|
|
|
|
* SCSI ID 7 is assigned to the SCSI controller and cannot be
|
|
|
|
* used for disk devices.
|
|
|
|
*/
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
|
|
|
|
VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
|
|
|
|
scsi_virtualDev,
|
|
|
|
&def->disks[def->ndisks]) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->disks[def->ndisks] != NULL) {
|
|
|
|
++def->ndisks;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
|
|
|
|
VIR_DOMAIN_DISK_BUS_SCSI, controller, id,
|
|
|
|
scsi_virtualDev,
|
|
|
|
&def->disks[def->ndisks]) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->disks[def->ndisks] != NULL) {
|
|
|
|
++def->ndisks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:disks (ide) */
|
|
|
|
for (controller = 0; controller < 2; ++controller) {
|
|
|
|
for (id = 0; id < 2; ++id) {
|
|
|
|
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_DISK,
|
|
|
|
VIR_DOMAIN_DISK_BUS_IDE, controller, id,
|
|
|
|
NULL, &def->disks[def->ndisks]) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->disks[def->ndisks] != NULL) {
|
|
|
|
++def->ndisks;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_CDROM,
|
|
|
|
VIR_DOMAIN_DISK_BUS_IDE, controller, id,
|
|
|
|
NULL, &def->disks[def->ndisks]) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->disks[def->ndisks] != NULL) {
|
|
|
|
++def->ndisks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:disks (floppy) */
|
|
|
|
for (controller = 0; controller < 2; ++controller) {
|
|
|
|
if (esxVMX_ParseDisk(conn, conf, VIR_DOMAIN_DISK_DEVICE_FLOPPY,
|
|
|
|
VIR_DOMAIN_DISK_BUS_FDC, controller, -1, NULL,
|
|
|
|
&def->disks[def->ndisks]) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->disks[def->ndisks] != NULL) {
|
|
|
|
++def->ndisks;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:fss */
|
|
|
|
/* FIXME */
|
|
|
|
|
|
|
|
/* def:nets */
|
|
|
|
if (VIR_ALLOC_N(def->nets, 4) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->nnets = 0;
|
|
|
|
|
|
|
|
for (controller = 0; controller < 4; ++controller) {
|
|
|
|
if (esxVMX_ParseEthernet(conn, conf, controller,
|
|
|
|
&def->nets[def->nnets]) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->nets[def->nnets] != NULL) {
|
|
|
|
++def->nnets;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:inputs */
|
|
|
|
/* FIXME */
|
|
|
|
|
|
|
|
/* def:sounds */
|
|
|
|
/* FIXME */
|
|
|
|
|
|
|
|
/* def:hostdevs */
|
|
|
|
/* FIXME */
|
|
|
|
|
|
|
|
/* def:serials */
|
|
|
|
if (VIR_ALLOC_N(def->serials, 4) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->nserials = 0;
|
|
|
|
|
|
|
|
for (port = 0; port < 4; ++port) {
|
|
|
|
if (esxVMX_ParseSerial(conn, conf, port,
|
|
|
|
&def->serials[def->nserials]) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->serials[def->nserials] != NULL) {
|
|
|
|
++def->nserials;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* def:parallels */
|
|
|
|
if (VIR_ALLOC_N(def->parallels, 3) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
def->nparallels = 0;
|
|
|
|
|
|
|
|
for (port = 0; port < 3; ++port) {
|
|
|
|
if (esxVMX_ParseParallel(conn, conf, port,
|
|
|
|
&def->parallels[def->nparallels]) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (def->parallels[def->nparallels] != NULL) {
|
|
|
|
++def->nparallels;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
virConfFree(conf);
|
|
|
|
VIR_FREE(sched_cpu_affinity);
|
|
|
|
VIR_FREE(scsi_virtualDev);
|
|
|
|
|
|
|
|
return def;
|
|
|
|
|
|
|
|
failure:
|
|
|
|
virDomainDefFree(def);
|
|
|
|
def = NULL;
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
esxVMX_ParseSCSIController(virConnectPtr conn, virConfPtr conf, int controller,
|
|
|
|
int *present, char **virtualDev)
|
|
|
|
{
|
|
|
|
char present_name[32];
|
|
|
|
char virtualDev_name[32];
|
|
|
|
|
|
|
|
if (virtualDev == NULL || *virtualDev != NULL) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (controller < 0 || controller > 3) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"SCSI controller index %d out of [0..3] range",
|
|
|
|
controller);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(present_name, "scsiX.present", sizeof (virtualDev_name));
|
|
|
|
strncpy(virtualDev_name, "scsiX.virtualDev", sizeof (virtualDev_name));
|
|
|
|
|
|
|
|
present_name[4] = '0' + controller;
|
|
|
|
virtualDev_name[4] = '0' + controller;
|
|
|
|
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, present_name, present, 0, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! *present) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, virtualDev_name,
|
|
|
|
virtualDev, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*virtualDev != NULL &&
|
|
|
|
STRCASENEQ(*virtualDev, "buslogic") &&
|
|
|
|
STRCASENEQ(*virtualDev, "lsilogic")) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'buslogic' or 'lsilogic' "
|
|
|
|
"but found '%s'", virtualDev_name, *virtualDev);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
failure:
|
|
|
|
VIR_FREE(*virtualDev);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
esxVMX_IndexToDiskName(virConnectPtr conn, int idx, const char *prefix)
|
|
|
|
{
|
|
|
|
char buffer[32] = "";
|
|
|
|
char *name = NULL;
|
|
|
|
size_t length = strlen(prefix);
|
|
|
|
|
|
|
|
if (length > sizeof (buffer) - 2 - 1) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Disk name prefix '%s' is too long", prefix);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(buffer, prefix, sizeof (buffer) - 1);
|
|
|
|
buffer[sizeof (buffer) - 1] = '\0';
|
|
|
|
|
|
|
|
if (idx < 26) {
|
|
|
|
buffer[length] = 'a' + idx;
|
|
|
|
} else if (idx < 702) {
|
|
|
|
buffer[length] = 'a' + idx / 26 - 1;
|
|
|
|
buffer[length + 1] = 'a' + idx % 26;
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Disk index %d is too large", idx);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
name = strdup(buffer);
|
|
|
|
|
|
|
|
if (name == NULL) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
struct _virDomainDiskDef {
|
|
|
|
int type; // partly done
|
|
|
|
int device; // done
|
|
|
|
int bus; // done
|
|
|
|
char *src; // done
|
|
|
|
char *dst; // done
|
|
|
|
char *driverName; // done
|
|
|
|
char *driverType;
|
|
|
|
int cachemode; // done
|
|
|
|
unsigned int readonly : 1;
|
|
|
|
unsigned int shared : 1;
|
|
|
|
int slotnum;
|
|
|
|
};*/
|
|
|
|
|
|
|
|
int
|
|
|
|
esxVMX_ParseDisk(virConnectPtr conn, virConfPtr conf, int device, int bus,
|
|
|
|
int controller, int id, const char *virtualDev,
|
|
|
|
virDomainDiskDefPtr *def)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* device = {VIR_DOMAIN_DISK_DEVICE_DISK, VIR_DOMAIN_DISK_DEVICE_CDROM}
|
|
|
|
* bus = VIR_DOMAIN_DISK_BUS_SCSI
|
|
|
|
* controller = [0..3]
|
|
|
|
* id = [0..6,8..15]
|
|
|
|
* virtualDev = {'buslogic', 'lsilogic'}
|
|
|
|
*
|
|
|
|
* device = {VIR_DOMAIN_DISK_DEVICE_DISK, VIR_DOMAIN_DISK_DEVICE_CDROM}
|
|
|
|
* bus = VIR_DOMAIN_DISK_BUS_IDE
|
|
|
|
* controller = [0..1]
|
|
|
|
* id = [0..1]
|
|
|
|
* virtualDev = NULL
|
|
|
|
*
|
|
|
|
* device = VIR_DOMAIN_DISK_DEVICE_FLOPPY
|
|
|
|
* bus = VIR_DOMAIN_DISK_BUS_FDC
|
|
|
|
* controller = [0..1]
|
|
|
|
* id = -1
|
|
|
|
* virtualDev = NULL
|
|
|
|
*/
|
|
|
|
|
|
|
|
int result = 0;
|
|
|
|
char *prefix = NULL;
|
|
|
|
|
|
|
|
char present_name[32] = "";
|
|
|
|
int present = 0;
|
|
|
|
|
|
|
|
char startConnected_name[32] = "";
|
|
|
|
int startConnected = 0;
|
|
|
|
|
|
|
|
char deviceType_name[32] = "";
|
|
|
|
char *deviceType = NULL;
|
|
|
|
|
|
|
|
char clientDevice_name[32] = "";
|
|
|
|
int clientDevice = 0;
|
|
|
|
|
|
|
|
char fileType_name[32] = "";
|
|
|
|
char *fileType = NULL;
|
|
|
|
|
|
|
|
char fileName_name[32] = "";
|
|
|
|
char *fileName = NULL;
|
|
|
|
|
|
|
|
char writeThrough_name[32] = "";
|
|
|
|
int writeThrough = 0;
|
|
|
|
|
|
|
|
if (def == NULL || *def != NULL) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(*def) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
(*def)->device = device;
|
|
|
|
(*def)->bus = bus;
|
|
|
|
|
|
|
|
/* def:dst, def:driverName */
|
|
|
|
if (device == VIR_DOMAIN_DISK_DEVICE_DISK ||
|
|
|
|
device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
|
|
|
|
if (bus == VIR_DOMAIN_DISK_BUS_SCSI) {
|
|
|
|
if (controller < 0 || controller > 3) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"SCSI controller index %d out of [0..3] range",
|
|
|
|
controller);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id < 0 || id > 15 || id == 7) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"SCSI ID %d out of [0..6,8..15] range", id);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virAsprintf(&prefix, "scsi%d:%d", controller, id) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
(*def)->dst = esxVMX_IndexToDiskName(conn, controller * 16 + id,
|
|
|
|
"sd");
|
|
|
|
|
|
|
|
if ((*def)->dst == NULL) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virtualDev != NULL) {
|
|
|
|
(*def)->driverName = strdup(virtualDev);
|
|
|
|
|
|
|
|
if ((*def)->driverName == NULL) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (bus == VIR_DOMAIN_DISK_BUS_IDE) {
|
|
|
|
if (controller < 0 || controller > 1) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"IDE controller index %d out of [0..1] range",
|
|
|
|
controller);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id < 0 || id > 1) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"IDE ID %d out of [0..1] range", id);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virAsprintf(&prefix, "ide%d:%d", controller, id) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
(*def)->dst = esxVMX_IndexToDiskName(conn, controller * 2 + id,
|
|
|
|
"hd");
|
|
|
|
|
|
|
|
if ((*def)->dst == NULL) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unsupported bus type '%s' for '%s' device type",
|
|
|
|
virDomainDiskBusTypeToString (bus),
|
|
|
|
virDomainDiskDeviceTypeToString (device));
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
} else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
|
|
|
|
if (bus == VIR_DOMAIN_DISK_BUS_FDC) {
|
|
|
|
if (controller < 0 || controller > 1) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Floppy controller index %d out of [0..1] range",
|
|
|
|
controller);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virAsprintf(&prefix, "floppy%d", controller) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
(*def)->dst = esxVMX_IndexToDiskName(conn, controller, "fd");
|
|
|
|
|
|
|
|
if ((*def)->dst == NULL) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unsupported bus type '%s' for '%s' device type",
|
|
|
|
virDomainDiskBusTypeToString (bus),
|
|
|
|
virDomainDiskDeviceTypeToString (device));
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unsupported device type '%s'",
|
|
|
|
virDomainDiskDeviceTypeToString (device));
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
ESX_BUILD_VMX_NAME(present);
|
|
|
|
ESX_BUILD_VMX_NAME(startConnected);
|
|
|
|
ESX_BUILD_VMX_NAME(deviceType);
|
|
|
|
ESX_BUILD_VMX_NAME(clientDevice);
|
|
|
|
ESX_BUILD_VMX_NAME(fileType);
|
|
|
|
ESX_BUILD_VMX_NAME(fileName);
|
|
|
|
ESX_BUILD_VMX_NAME(writeThrough);
|
|
|
|
|
|
|
|
/* vmx:present */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, present_name,
|
|
|
|
&present, 0, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:startConnected */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, startConnected_name,
|
|
|
|
&startConnected, 1, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Need to distiguish between active and inactive domains here */
|
|
|
|
if (! present/* && ! startConnected*/) {
|
|
|
|
goto ignore;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:deviceType -> def:type */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, deviceType_name,
|
|
|
|
&deviceType, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:clientDevice */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, clientDevice_name,
|
|
|
|
&clientDevice, 0, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
goto ignore;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:fileType -> def:type */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, fileType_name, &fileType, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:fileName -> def:src, def:type */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, fileName_name,
|
|
|
|
&fileName, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:writeThrough -> def:cachemode */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, writeThrough_name,
|
|
|
|
&writeThrough, 0, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup virDomainDiskDef */
|
|
|
|
/* FIXME: Need the datastore name for fileName */
|
|
|
|
if (device == VIR_DOMAIN_DISK_DEVICE_DISK) {
|
|
|
|
if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
|
|
|
|
if (deviceType != NULL) {
|
|
|
|
if (bus == VIR_DOMAIN_DISK_BUS_SCSI &&
|
|
|
|
STRCASENEQ(deviceType, "scsi-hardDisk")) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'scsi-hardDisk' "
|
|
|
|
"but found '%s'", deviceType_name, deviceType);
|
|
|
|
goto failure;
|
|
|
|
} else if (bus == VIR_DOMAIN_DISK_BUS_IDE &&
|
|
|
|
STRCASENEQ(deviceType, "ata-hardDisk")) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'ata-hardDisk' "
|
|
|
|
"but found '%s'", deviceType_name, deviceType);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
|
|
|
(*def)->src = fileName;
|
|
|
|
(*def)->cachemode = writeThrough ? VIR_DOMAIN_DISK_CACHE_WRITETHRU
|
|
|
|
: VIR_DOMAIN_DISK_CACHE_DEFAULT;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else if (esxUtil_EqualSuffix(fileName, ".iso") ||
|
|
|
|
STREQ(deviceType, "atapi-cdrom")) {
|
|
|
|
/*
|
|
|
|
* This function was called in order to parse a harddisk device,
|
|
|
|
* but .iso files and 'atapi-cdrom' devices are for CDROM devices
|
|
|
|
* only. Just ignore it, another call to this function to parse a
|
|
|
|
* CDROM device may handle it.
|
|
|
|
*/
|
|
|
|
goto ignore;
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Invalid or not yet handled value '%s' for VMX entry "
|
|
|
|
"'%s'", fileName, fileName_name);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
} else if (device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
|
|
|
|
if (esxUtil_EqualSuffix(fileName, ".iso")) {
|
|
|
|
if (deviceType != NULL) {
|
|
|
|
if (STRCASENEQ(deviceType, "cdrom-image")) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'cdrom-image' "
|
|
|
|
"but found '%s'", deviceType_name, deviceType);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
|
|
|
(*def)->src = fileName;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else if (esxUtil_EqualSuffix(fileName, ".vmdk")) {
|
|
|
|
/*
|
|
|
|
* This function was called in order to parse a CDROM device, but
|
|
|
|
* .vmdk files are for harddisk devices only. Just ignore it,
|
|
|
|
* another call to this function to parse a harddisk device may
|
|
|
|
* handle it.
|
|
|
|
*/
|
|
|
|
goto ignore;
|
|
|
|
} else if (STREQ(deviceType, "atapi-cdrom")) {
|
|
|
|
(*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
|
|
|
|
(*def)->src = fileName;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Invalid or not yet handled value '%s' for VMX entry "
|
|
|
|
"'%s'", fileName, fileName_name);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
} else if (device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
|
|
|
|
if (esxUtil_EqualSuffix(fileName, ".flp")) {
|
|
|
|
if (fileType != NULL) {
|
|
|
|
if (STRCASENEQ(fileType, "file")) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'file' but "
|
|
|
|
"found '%s'", fileType_name, fileType);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(*def)->type = VIR_DOMAIN_DISK_TYPE_FILE;
|
|
|
|
(*def)->src = fileName;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else if (fileType != NULL && STREQ(fileType, "device")) {
|
|
|
|
(*def)->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
|
|
|
|
(*def)->src = fileName;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Invalid or not yet handled value '%s' for VMX entry "
|
|
|
|
"'%s'", fileName, fileName_name);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Unsupported device type '%s'",
|
|
|
|
virDomainDiskDeviceTypeToString (device));
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(prefix);
|
|
|
|
VIR_FREE(deviceType);
|
|
|
|
VIR_FREE(fileType);
|
|
|
|
VIR_FREE(fileName);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
failure:
|
|
|
|
result = -1;
|
|
|
|
|
|
|
|
ignore:
|
|
|
|
virDomainDiskDefFree(*def);
|
|
|
|
*def = NULL;
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
esxVMX_ParseEthernet(virConnectPtr conn, virConfPtr conf, int controller,
|
|
|
|
virDomainNetDefPtr *def)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
char prefix[48] = "";
|
|
|
|
|
|
|
|
char present_name[48] = "";
|
|
|
|
int present = 0;
|
|
|
|
|
|
|
|
char startConnected_name[48] = "";
|
|
|
|
int startConnected = 0;
|
|
|
|
|
|
|
|
char connectionType_name[48] = "";
|
|
|
|
char *connectionType = NULL;
|
|
|
|
|
|
|
|
char addressType_name[48] = "";
|
|
|
|
char *addressType = NULL;
|
|
|
|
|
|
|
|
char generatedAddress_name[48] = "";
|
|
|
|
char *generatedAddress = NULL;
|
|
|
|
|
|
|
|
char address_name[48] = "";
|
|
|
|
char *address = NULL;
|
|
|
|
|
|
|
|
char virtualDev_name[48] = "";
|
|
|
|
char *virtualDev = NULL;
|
|
|
|
|
|
|
|
char vnet_name[48] = "";
|
|
|
|
char *vnet = NULL;
|
|
|
|
|
|
|
|
if (def == NULL || *def != NULL) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (controller < 0 || controller > 3) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Ethernet controller index %d out of [0..3] range",
|
|
|
|
controller);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(*def) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(prefix, "ethernetX", sizeof (prefix));
|
|
|
|
prefix[8] = '0' + controller;
|
|
|
|
|
|
|
|
ESX_BUILD_VMX_NAME(present);
|
|
|
|
ESX_BUILD_VMX_NAME(startConnected);
|
|
|
|
ESX_BUILD_VMX_NAME(connectionType);
|
|
|
|
ESX_BUILD_VMX_NAME(addressType);
|
|
|
|
ESX_BUILD_VMX_NAME(generatedAddress);
|
|
|
|
ESX_BUILD_VMX_NAME(address);
|
|
|
|
ESX_BUILD_VMX_NAME(virtualDev);
|
|
|
|
|
|
|
|
/* vmx:present */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, present_name,
|
|
|
|
&present, 0, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:startConnected */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, startConnected_name,
|
|
|
|
&startConnected, 1, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Need to distiguish between active and inactive domains here */
|
|
|
|
if (! present/* && ! startConnected*/) {
|
|
|
|
goto ignore;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:connectionType -> def:type */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, connectionType_name,
|
|
|
|
&connectionType, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:addressType, vmx:generatedAddress, vmx:address -> def:mac */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, addressType_name,
|
|
|
|
&addressType, 1) < 0 ||
|
|
|
|
esxUtil_GetConfigString(conn, conf, generatedAddress_name,
|
|
|
|
&generatedAddress, 1) < 0 ||
|
|
|
|
esxUtil_GetConfigString(conn, conf, address_name, &address, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addressType == NULL || STRCASEEQ(addressType, "generated")) {
|
|
|
|
if (generatedAddress != NULL) {
|
|
|
|
if (virParseMacAddr(generatedAddress, (*def)->mac) < 0) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be MAC address but "
|
|
|
|
"found '%s'", generatedAddress_name,
|
|
|
|
generatedAddress);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (STRCASEEQ(addressType, "static")) {
|
|
|
|
if (address != NULL) {
|
|
|
|
if (virParseMacAddr(address, (*def)->mac) < 0) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be MAC address but "
|
|
|
|
"found '%s'", address_name, address);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'generated' or 'static' but "
|
|
|
|
"found '%s'", addressType_name, addressType);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:virtualDev -> def:model */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, virtualDev_name,
|
|
|
|
&virtualDev, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virtualDev != NULL &&
|
|
|
|
STRCASENEQ(virtualDev, "vlance") &&
|
|
|
|
STRCASENEQ(virtualDev, "vmxnet") &&
|
|
|
|
STRCASENEQ(virtualDev, "e1000")) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'vlance' or 'vmxnet' or "
|
|
|
|
"'e1000' but found '%s'", virtualDev_name, virtualDev);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:vnet -> def:data.bridge.brname */
|
|
|
|
if (connectionType != NULL && STRCASEEQ(connectionType, "custom") &&
|
|
|
|
esxUtil_GetConfigString(conn, conf, vnet_name, &vnet, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup virDomainNetDef */
|
|
|
|
if (connectionType == NULL || STRCASEEQ(connectionType, "bridged")) {
|
|
|
|
(*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
|
|
|
|
(*def)->model = virtualDev;
|
|
|
|
|
|
|
|
virtualDev = NULL;
|
|
|
|
} else if (STRCASEEQ(connectionType, "hostonly")) {
|
|
|
|
/* FIXME */
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"No yet handled value '%s' for VMX entry '%s'",
|
|
|
|
connectionType, connectionType_name);
|
|
|
|
goto failure;
|
|
|
|
} else if (STRCASEEQ(connectionType, "nat")) {
|
|
|
|
/* FIXME */
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"No yet handled value '%s' for VMX entry '%s'",
|
|
|
|
connectionType, connectionType_name);
|
|
|
|
goto failure;
|
|
|
|
} else if (STRCASEEQ(connectionType, "custom")) {
|
|
|
|
(*def)->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
|
|
|
|
(*def)->model = virtualDev;
|
|
|
|
(*def)->data.bridge.brname = vnet;
|
|
|
|
|
|
|
|
virtualDev = NULL;
|
|
|
|
vnet = NULL;
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Invalid value '%s' for VMX entry '%s'", connectionType,
|
|
|
|
connectionType_name);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(connectionType);
|
|
|
|
VIR_FREE(addressType);
|
|
|
|
VIR_FREE(generatedAddress);
|
|
|
|
VIR_FREE(address);
|
|
|
|
VIR_FREE(virtualDev);
|
|
|
|
VIR_FREE(vnet);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
failure:
|
|
|
|
result = -1;
|
|
|
|
|
|
|
|
ignore:
|
|
|
|
virDomainNetDefFree(*def);
|
|
|
|
*def = NULL;
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
esxVMX_ParseSerial(virConnectPtr conn, virConfPtr conf, int port,
|
|
|
|
virDomainChrDefPtr *def)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
char prefix[48] = "";
|
|
|
|
|
|
|
|
char present_name[48] = "";
|
|
|
|
int present = 0;
|
|
|
|
|
|
|
|
char startConnected_name[48] = "";
|
|
|
|
int startConnected = 0;
|
|
|
|
|
|
|
|
char fileType_name[48] = "";
|
|
|
|
char *fileType = NULL;
|
|
|
|
|
|
|
|
char fileName_name[48] = "";
|
|
|
|
char *fileName = NULL;
|
|
|
|
|
|
|
|
if (def == NULL || *def != NULL) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (port < 0 || port > 3) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Serial port index %d out of [0..3] range", port);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(*def) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(prefix, "serialX", sizeof (prefix));
|
|
|
|
prefix[6] = '0' + port;
|
|
|
|
|
|
|
|
ESX_BUILD_VMX_NAME(present);
|
|
|
|
ESX_BUILD_VMX_NAME(startConnected);
|
|
|
|
ESX_BUILD_VMX_NAME(fileType);
|
|
|
|
ESX_BUILD_VMX_NAME(fileName);
|
|
|
|
|
|
|
|
/* vmx:present */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, present_name,
|
|
|
|
&present, 0, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:startConnected */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, startConnected_name,
|
|
|
|
&startConnected, 1, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Need to distiguish between active and inactive domains here */
|
|
|
|
if (! present/* && ! startConnected*/) {
|
|
|
|
goto ignore;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:fileType -> def:type */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, fileType_name, &fileType, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:fileName -> def:data.file.path */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, fileName_name, &fileName, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup virDomainChrDef */
|
|
|
|
if (STRCASEEQ(fileType, "device")) {
|
|
|
|
(*def)->dstPort = port;
|
|
|
|
(*def)->type = VIR_DOMAIN_CHR_TYPE_DEV;
|
|
|
|
(*def)->data.file.path = fileName;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else if (STRCASEEQ(fileType, "file")) {
|
|
|
|
(*def)->dstPort = port;
|
|
|
|
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
|
|
|
|
(*def)->data.file.path = fileName;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else if (STRCASEEQ(fileType, "pipe")) {
|
|
|
|
/* FIXME */
|
|
|
|
VIR_WARN("Serial port %d has currently unsupported type '%s', "
|
|
|
|
"ignoring it", port, fileType);
|
|
|
|
goto ignore;
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'device', 'file' or 'pipe' "
|
|
|
|
"but found '%s'", fileType_name, fileType);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(fileType);
|
|
|
|
VIR_FREE(fileName);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
failure:
|
|
|
|
result = -1;
|
|
|
|
|
|
|
|
ignore:
|
|
|
|
virDomainChrDefFree(*def);
|
|
|
|
*def = NULL;
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
esxVMX_ParseParallel(virConnectPtr conn, virConfPtr conf, int port,
|
|
|
|
virDomainChrDefPtr *def)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
char prefix[48] = "";
|
|
|
|
|
|
|
|
char present_name[48] = "";
|
|
|
|
int present = 0;
|
|
|
|
|
|
|
|
char startConnected_name[48] = "";
|
|
|
|
int startConnected = 0;
|
|
|
|
|
|
|
|
char fileType_name[48] = "";
|
|
|
|
char *fileType = NULL;
|
|
|
|
|
|
|
|
char fileName_name[48] = "";
|
|
|
|
char *fileName = NULL;
|
|
|
|
|
|
|
|
if (def == NULL || *def != NULL) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR, "Invalid argument");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (port < 0 || port > 2) {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Parallel port index %d out of [0..2] range", port);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(*def) < 0) {
|
|
|
|
virReportOOMError(conn);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(prefix, "parallelX", sizeof (prefix));
|
|
|
|
prefix[8] = '0' + port;
|
|
|
|
|
|
|
|
ESX_BUILD_VMX_NAME(present);
|
|
|
|
ESX_BUILD_VMX_NAME(startConnected);
|
|
|
|
ESX_BUILD_VMX_NAME(fileType);
|
|
|
|
ESX_BUILD_VMX_NAME(fileName);
|
|
|
|
|
|
|
|
/* vmx:present */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, present_name,
|
|
|
|
&present, 0, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:startConnected */
|
|
|
|
if (esxUtil_GetConfigBoolean(conn, conf, startConnected_name,
|
|
|
|
&startConnected, 1, 1) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: Need to distiguish between active and inactive domains here */
|
|
|
|
if (! present/* && ! startConnected*/) {
|
|
|
|
goto ignore;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:fileType -> def:type */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, fileType_name, &fileType, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vmx:fileName -> def:data.file.path */
|
|
|
|
if (esxUtil_GetConfigString(conn, conf, fileName_name, &fileName, 0) < 0) {
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Setup virDomainChrDef */
|
|
|
|
if (STRCASEEQ(fileType, "device")) {
|
|
|
|
(*def)->dstPort = port;
|
|
|
|
(*def)->type = VIR_DOMAIN_CHR_TYPE_DEV;
|
|
|
|
(*def)->data.file.path = fileName;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else if (STRCASEEQ(fileType, "file")) {
|
|
|
|
(*def)->dstPort = port;
|
|
|
|
(*def)->type = VIR_DOMAIN_CHR_TYPE_FILE;
|
|
|
|
(*def)->data.file.path = fileName;
|
|
|
|
|
|
|
|
fileName = NULL;
|
|
|
|
} else {
|
|
|
|
ESX_ERROR(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"Expecting VMX entry '%s' to be 'device' or 'file' but "
|
|
|
|
"found '%s'", fileType_name, fileType);
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(fileType);
|
|
|
|
VIR_FREE(fileName);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
failure:
|
|
|
|
result = -1;
|
|
|
|
|
|
|
|
ignore:
|
|
|
|
virDomainChrDefFree(*def);
|
|
|
|
*def = NULL;
|
|
|
|
|
|
|
|
goto cleanup;
|
|
|
|
}
|