[libvirt] [PATCH] esx: Add support for memtune/min_guarantee
Matthias Bolte
matthias.bolte at googlemail.com
Sun Nov 7 12:40:42 UTC 2010
Also add a test case for the VMX handling of it.
---
src/esx/esx_driver.c | 133 ++++++++++++++++++++++-
src/esx/esx_vi.c | 31 ++++++
src/esx/esx_vi.h | 3 +
src/esx/esx_vi_types.c | 5 +
src/esx/esx_vi_types.h | 1 +
src/esx/esx_vmx.c | 49 +++++++--
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.vmx | 2 +-
tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml | 3 +
tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx | 26 +++++
tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml | 37 +++++++
tests/xml2vmxtest.c | 1 +
11 files changed, 280 insertions(+), 11 deletions(-)
create mode 100644 tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx
create mode 100644 tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml
diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c
index b3e1284..0591115 100644
--- a/src/esx/esx_driver.c
+++ b/src/esx/esx_driver.c
@@ -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 */
};
diff --git a/src/esx/esx_vi.c b/src/esx/esx_vi.c
index c450730..9c96650 100644
--- a/src/esx/esx_vi.c
+++ b/src/esx/esx_vi.c
@@ -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
diff --git a/src/esx/esx_vi.h b/src/esx/esx_vi.h
index aa47e87..26779ad 100644
--- a/src/esx/esx_vi.h
+++ b/src/esx/esx_vi.h
@@ -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);
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index bb791af..ad45483 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -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,
{
diff --git a/src/esx/esx_vi_types.h b/src/esx/esx_vi_types.h
index f659361..901eda0 100644
--- a/src/esx/esx_vi_types.h
+++ b/src/esx/esx_vi_types.h
@@ -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,
diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c
index 36818df..981b856 100644
--- a/src/esx/esx_vmx.c
+++ b/src/esx/esx_vmx.c
@@ -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",
diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.vmx b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.vmx
index 6b11cc2..650f8fd 100644
--- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.vmx
+++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.vmx
@@ -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 = "--------------------------------"
diff --git a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml
index c324673..d55bf6b 100644
--- a/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml
+++ b/tests/vmx2xmldata/vmx2xml-esx-in-the-wild-5.xml
@@ -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>
diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx
new file mode 100644
index 0000000..cc2485f
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.vmx
@@ -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"
diff --git a/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml
new file mode 100644
index 0000000..d55bf6b
--- /dev/null
+++ b/tests/xml2vmxdata/xml2vmx-esx-in-the-wild-5.xml
@@ -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>
diff --git a/tests/xml2vmxtest.c b/tests/xml2vmxtest.c
index 0881ae9..db7eb53 100644
--- a/tests/xml2vmxtest.c
+++ b/tests/xml2vmxtest.c
@@ -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);
--
1.7.0.4
More information about the libvir-list
mailing list