[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