esx: Add support for memtune/min_guarantee

Also add a test case for the VMX handling of it.
This commit is contained in:
Matthias Bolte 2010-11-06 18:53:39 +01:00
parent 38eec464f8
commit 809926db8f
11 changed files with 280 additions and 11 deletions

View File

@ -4149,6 +4149,135 @@ esxDomainSnapshotDelete(virDomainSnapshotPtr snapshot, unsigned int flags)
static int
esxDomainSetMemoryParameters(virDomainPtr domain, virMemoryParameterPtr params,
int nparams, unsigned int flags)
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_VirtualMachineConfigSpec *spec = NULL;
esxVI_ManagedObjectReference *task = NULL;
esxVI_TaskInfoState taskInfoState;
int i;
virCheckFlags(0, -1);
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
if (esxVI_LookupVirtualMachineByUuidAndPrepareForTask
(priv->primary, domain->uuid, NULL, &virtualMachine,
priv->autoAnswer) < 0 ||
esxVI_VirtualMachineConfigSpec_Alloc(&spec) < 0 ||
esxVI_ResourceAllocationInfo_Alloc(&spec->memoryAllocation) < 0) {
goto cleanup;
}
for (i = 0; i < nparams; ++i) {
if (STREQ (params[i].field, VIR_DOMAIN_MEMORY_MIN_GUARANTEE) &&
params[i].type == VIR_DOMAIN_SCHED_FIELD_ULLONG) {
if (esxVI_Long_Alloc(&spec->memoryAllocation->reservation) < 0) {
goto cleanup;
}
spec->memoryAllocation->reservation->value =
params[i].value.ul / 1024; /* Scale from kilobytes to megabytes */
} else {
ESX_ERROR(VIR_ERR_INVALID_ARG, _("Unknown field '%s'"),
params[i].field);
goto cleanup;
}
}
if (esxVI_ReconfigVM_Task(priv->primary, virtualMachine->obj, spec,
&task) < 0 ||
esxVI_WaitForTaskCompletion(priv->primary, task, domain->uuid,
esxVI_Occurrence_RequiredItem,
priv->autoAnswer, &taskInfoState) < 0) {
goto cleanup;
}
if (taskInfoState != esxVI_TaskInfoState_Success) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR, "%s",
_("Could not change memory parameters"));
goto cleanup;
}
result = 0;
cleanup:
esxVI_ObjectContent_Free(&virtualMachine);
esxVI_VirtualMachineConfigSpec_Free(&spec);
esxVI_ManagedObjectReference_Free(&task);
return result;
}
static int
esxDomainGetMemoryParameters(virDomainPtr domain, virMemoryParameterPtr params,
int *nparams, unsigned int flags)
{
int result = -1;
esxPrivate *priv = domain->conn->privateData;
esxVI_String *propertyNameList = NULL;
esxVI_ObjectContent *virtualMachine = NULL;
esxVI_Long *reservation = NULL;
virCheckFlags(0, -1);
if (*nparams == 0) {
*nparams = 1; /* min_guarantee */
return 0;
}
if (*nparams < 1) {
ESX_ERROR(VIR_ERR_INVALID_ARG, "%s",
_("Parameter array must have space for 1 item"));
return -1;
}
if (esxVI_EnsureSession(priv->primary) < 0) {
return -1;
}
if (esxVI_String_AppendValueToList
(&propertyNameList, "config.memoryAllocation.reservation") < 0 ||
esxVI_LookupVirtualMachineByUuid(priv->primary, domain->uuid,
propertyNameList, &virtualMachine,
esxVI_Occurrence_RequiredItem) < 0 ||
esxVI_GetLong(virtualMachine, "config.memoryAllocation.reservation",
&reservation, esxVI_Occurrence_RequiredItem) < 0) {
goto cleanup;
}
if (virStrcpyStatic(params[0].field,
VIR_DOMAIN_MEMORY_MIN_GUARANTEE) == NULL) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Field %s too big for destination"),
VIR_DOMAIN_MEMORY_MIN_GUARANTEE);
goto cleanup;
}
params[0].type = VIR_DOMAIN_SCHED_FIELD_ULLONG;
params[0].value.ul = reservation->value * 1024; /* Scale from megabytes to kilobytes */
*nparams = 1;
result = 0;
cleanup:
esxVI_String_Free(&propertyNameList);
esxVI_ObjectContent_Free(&virtualMachine);
esxVI_Long_Free(&reservation);
return result;
}
static virDriver esxDriver = {
VIR_DRV_ESX,
"ESX",
@ -4251,8 +4380,8 @@ static virDriver esxDriver = {
esxDomainRevertToSnapshot, /* domainRevertToSnapshot */
esxDomainSnapshotDelete, /* domainSnapshotDelete */
NULL, /* qemuDomainMonitorCommand */
NULL, /* domainSetMemoryParameters */
NULL, /* domainGetMemoryParameters */
esxDomainSetMemoryParameters, /* domainSetMemoryParameters */
esxDomainGetMemoryParameters, /* domainGetMemoryParameters */
};

View File

@ -1840,6 +1840,37 @@ esxVI_GetBoolean(esxVI_ObjectContent *objectContent, const char *propertyName,
return 0;
}
int
esxVI_GetLong(esxVI_ObjectContent *objectContent, const char *propertyName,
esxVI_Long **value, esxVI_Occurrence occurence)
{
esxVI_DynamicProperty *dynamicProperty;
if (value == NULL || *value != NULL) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, "%s", _("Invalid argument"));
return -1;
}
for (dynamicProperty = objectContent->propSet; dynamicProperty != NULL;
dynamicProperty = dynamicProperty->_next) {
if (STREQ(dynamicProperty->name, propertyName)) {
if (esxVI_Long_CastFromAnyType(dynamicProperty->val, value) < 0) {
return -1;
}
break;
}
}
if (*value == NULL && occurence == esxVI_Occurrence_RequiredItem) {
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Missing '%s' property"), propertyName);
return -1;
}
return 0;
}
int

View File

@ -302,6 +302,9 @@ int esxVI_GetBoolean(esxVI_ObjectContent *objectContent,
const char *propertyName,
esxVI_Boolean *value, esxVI_Occurrence occurence);
int esxVI_GetLong(esxVI_ObjectContent *objectContent, const char *propertyName,
esxVI_Long **value, esxVI_Occurrence occurence);
int esxVI_GetStringValue(esxVI_ObjectContent *objectContent,
const char *propertyName,
char **value, esxVI_Occurrence occurence);

View File

@ -1235,6 +1235,11 @@ ESX_VI__TEMPLATE__VALIDATE(Long,
/* esxVI_Long_AppendToList */
ESX_VI__TEMPLATE__LIST__APPEND(Long)
/* esxVI_Long_CastFromAnyType */
ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(Long,
{
})
/* esxVI_Long_Serialize */
ESX_VI__TEMPLATE__SERIALIZE(Long,
{

View File

@ -227,6 +227,7 @@ int esxVI_Long_Alloc(esxVI_Long **number);
void esxVI_Long_Free(esxVI_Long **numberList);
int esxVI_Long_Validate(esxVI_Long *number);
int esxVI_Long_AppendToList(esxVI_Long **numberList, esxVI_Long *number);
int esxVI_Long_CastFromAnyType(esxVI_AnyType *anyType, esxVI_Long **number);
int esxVI_Long_Serialize(esxVI_Long *number, const char *element,
virBufferPtr output);
int esxVI_Long_SerializeList(esxVI_Long *numberList, const char *element,

View File

@ -50,6 +50,7 @@ def->uuid = <value> <=> uuid.bios = "<value>"
def->name = <value> <=> displayName = "<value>"
def->mem.max_balloon = <value kilobyte> <=> memsize = "<value megabyte>" # must be a multiple of 4, defaults to 32
def->mem.cur_balloon = <value kilobyte> <=> sched.mem.max = "<value megabyte>" # defaults to "unlimited" -> def->mem.cur_balloon = def->mem.max_balloon
def->mem.min_guarantee = <value kilobyte> <=> sched.mem.minsize = "<value megabyte>" # defaults to 0
def->maxvcpus = <value> <=> numvcpus = "<value>" # must be 1 or a multiple of 2, defaults to 1
def->cpumask = <uint list> <=> sched.cpu.affinity = "<uint list>"
@ -874,7 +875,8 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
long long config_version = 0;
long long virtualHW_version = 0;
long long memsize = 0;
long long memory = 0;
long long sched_mem_max = 0;
long long sched_mem_minsize = 0;
long long numvcpus = 0;
char *sched_cpu_affinity = NULL;
char *guestOS = NULL;
@ -1047,22 +1049,38 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx,
def->mem.max_balloon = memsize * 1024; /* Scale from megabytes to kilobytes */
/* vmx:sched.mem.max -> def:memory */
if (esxUtil_GetConfigLong(conf, "sched.mem.max", &memory, memsize,
/* vmx:sched.mem.max -> def:mem.cur_balloon */
if (esxUtil_GetConfigLong(conf, "sched.mem.max", &sched_mem_max, memsize,
true) < 0) {
goto cleanup;
}
if (memory < 0) {
memory = memsize;
if (sched_mem_max < 0) {
sched_mem_max = memsize;
}
def->mem.cur_balloon = memory * 1024; /* Scale from megabytes to kilobytes */
def->mem.cur_balloon = sched_mem_max * 1024; /* Scale from megabytes to kilobytes */
if (def->mem.cur_balloon > def->mem.max_balloon) {
def->mem.cur_balloon = def->mem.max_balloon;
}
/* vmx:sched.mem.minsize -> def:mem.min_guarantee */
if (esxUtil_GetConfigLong(conf, "sched.mem.minsize", &sched_mem_minsize, 0,
true) < 0) {
goto cleanup;
}
if (sched_mem_minsize < 0) {
sched_mem_minsize = 0;
}
def->mem.min_guarantee = sched_mem_minsize * 1024; /* Scale from megabytes to kilobytes */
if (def->mem.min_guarantee > def->mem.max_balloon) {
def->mem.min_guarantee = def->mem.max_balloon;
}
/* vmx:numvcpus -> def:vcpus */
if (esxUtil_GetConfigLong(conf, "numvcpus", &numvcpus, 1, true) < 0) {
goto cleanup;
@ -2594,12 +2612,12 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
virBufferVSprintf(&buffer, "memsize = \"%d\"\n",
(int)(def->mem.max_balloon / 1024));
/* def:memory -> vmx:sched.mem.max */
/* def:mem.cur_balloon -> vmx:sched.mem.max */
if (def->mem.cur_balloon < def->mem.max_balloon) {
if (def->mem.cur_balloon <= 0 || def->mem.cur_balloon % 1024 != 0) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML entry 'currentMemory' to be an "
"unsigned integer (multiple of 1024) but found %lld"),
"unsigned integer (multiple of 1024) but found %llu"),
(unsigned long long)def->mem.cur_balloon);
goto cleanup;
}
@ -2609,6 +2627,21 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def,
(int)(def->mem.cur_balloon / 1024));
}
/* def:mem.min_guarantee -> vmx:sched.mem.minsize */
if (def->mem.min_guarantee > 0) {
if (def->mem.min_guarantee % 1024 != 0) {
ESX_ERROR(VIR_ERR_INTERNAL_ERROR,
_("Expecting domain XML entry 'memtune/min_guarantee' to "
"be an unsigned integer (multiple of 1024) but found %llu"),
(unsigned long long)def->mem.min_guarantee);
goto cleanup;
}
/* Scale from kilobytes to megabytes */
virBufferVSprintf(&buffer, "sched.mem.minsize = \"%d\"\n",
(int)(def->mem.min_guarantee / 1024));
}
/* def:maxvcpus -> vmx:numvcpus */
if (def->vcpus != def->maxvcpus) {
ESX_ERROR(VIR_ERR_CONFIG_UNSUPPORTED, "%s",

View File

@ -52,7 +52,7 @@ snapshot.action = "keep"
sched.cpu.min = "0"
sched.cpu.units = "mhz"
sched.cpu.shares = "normal"
sched.mem.minsize = "0"
sched.mem.minsize = "256"
sched.mem.shares = "normal"
tools.upgrade.policy = "manual"
cpuid.80000001.eax = "--------------------------------"

View File

@ -4,6 +4,9 @@
<description>Centos 5.5 64bit Server</description>
<memory>2097152</memory>
<currentMemory>2097152</currentMemory>
<memtune>
<min_guarantee>262144</min_guarantee>
</memtune>
<vcpu>2</vcpu>
<os>
<type arch='x86_64'>hvm</type>

View File

@ -0,0 +1,26 @@
.encoding = "UTF-8"
config.version = "8"
virtualHW.version = "4"
guestOS = "other-64"
uuid.bios = "42 3e 94 a9 a1 c7 b3 1d-71 61 76 c7 58 6c 83 0e"
displayName = "vmtest.local"
annotation = "Centos 5.5 64bit Server"
memsize = "2048"
sched.mem.minsize = "256"
numvcpus = "2"
scsi0.present = "true"
scsi0.virtualDev = "lsilogic"
scsi0:0.present = "true"
scsi0:0.deviceType = "scsi-hardDisk"
scsi0:0.fileName = "/vmfs/volumes/datastore/directory/vmtest-000001.vmdk"
ide0:0.present = "true"
ide0:0.deviceType = "cdrom-image"
ide0:0.fileName = "/vmfs/volumes/4af0231d-1eff559a-6369-0024e84773b6/isos/CentOS-5.5-x86_64-bin-DVD-1of2.iso"
floppy0.present = "false"
floppy1.present = "false"
ethernet0.present = "true"
ethernet0.virtualDev = "e1000"
ethernet0.networkName = "VM-LAN"
ethernet0.connectionType = "bridged"
ethernet0.addressType = "vpx"
ethernet0.generatedAddress = "00:50:56:BE:00:15"

View File

@ -0,0 +1,37 @@
<domain type='vmware'>
<name>vmtest.local</name>
<uuid>423e94a9-a1c7-b31d-7161-76c7586c830e</uuid>
<description>Centos 5.5 64bit Server</description>
<memory>2097152</memory>
<currentMemory>2097152</currentMemory>
<memtune>
<min_guarantee>262144</min_guarantee>
</memtune>
<vcpu>2</vcpu>
<os>
<type arch='x86_64'>hvm</type>
</os>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<disk type='file' device='disk'>
<source file='[datastore] directory/vmtest-000001.vmdk'/>
<target dev='sda' bus='scsi'/>
<address type='drive' controller='0' bus='0' unit='0'/>
</disk>
<disk type='file' device='cdrom'>
<source file='[4af0231d-1eff559a-6369-0024e84773b6] isos/CentOS-5.5-x86_64-bin-DVD-1of2.iso'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' unit='0'/>
</disk>
<controller type='scsi' index='0' model='lsilogic'/>
<controller type='ide' index='0'/>
<interface type='bridge'>
<mac address='00:50:56:be:00:15'/>
<source bridge='VM-LAN'/>
<model type='e1000'/>
</interface>
</devices>
</domain>

View File

@ -269,6 +269,7 @@ mymain(int argc, char **argv)
DO_TEST("esx-in-the-wild-2", "esx-in-the-wild-2", esxVI_ProductVersion_ESX35);
DO_TEST("esx-in-the-wild-3", "esx-in-the-wild-3", esxVI_ProductVersion_ESX35);
DO_TEST("esx-in-the-wild-4", "esx-in-the-wild-4", esxVI_ProductVersion_ESX35);
DO_TEST("esx-in-the-wild-5", "esx-in-the-wild-5", esxVI_ProductVersion_ESX35);
DO_TEST("gsx-in-the-wild-1", "gsx-in-the-wild-1", esxVI_ProductVersion_ESX35);
DO_TEST("gsx-in-the-wild-2", "gsx-in-the-wild-2", esxVI_ProductVersion_ESX35);