From f078c799ae06525e04af29049eef5bc2f4c29fc0 Mon Sep 17 00:00:00 2001
From: Faidon Liambotis <paravoid@debian.org>
Date: Sun, 23 Dec 2012 18:14:25 +0200
Subject: [PATCH] LXC: add support for the memory controller

Add support for the memory resource controller, useful to actually place
memory limits on instances.

Support is still optional, in case the kernel doesn't have it compiled
in, or -in the case of Debian- has it dependent on a kernel command-line
switch (cgroup_enable=memory specifically).

Signed-off-by: Faidon Liambotis <paravoid@debian.org>
Reviewed-by: Guido Trotter <ultrotter@google.com>
---
 lib/hypervisor/hv_lxc.py | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/lib/hypervisor/hv_lxc.py b/lib/hypervisor/hv_lxc.py
index d8ba8a86f..d7deee8d4 100644
--- a/lib/hypervisor/hv_lxc.py
+++ b/lib/hypervisor/hv_lxc.py
@@ -43,8 +43,6 @@ class LXCHypervisor(hv_base.BaseHypervisor):
   TODO:
     - move hardcoded parameters into hypervisor parameters, once we
       have the container-parameter support
-    - implement memory limits, but only optionally, depending on host
-      kernel support
 
   Problems/issues:
     - LXC is very temperamental; in daemon mode, it succeeds or fails
@@ -143,6 +141,22 @@ class LXCHypervisor(hv_base.BaseHypervisor):
 
     return utils.ParseCpuMask(cpus)
 
+  @classmethod
+  def _GetCgroupMemoryLimit(cls, instance_name):
+    """Return the memory limit for an instance
+
+    """
+    cgroup = cls._GetCgroupMountPoint()
+    try:
+      memory = int(utils.ReadFile(utils.PathJoin(cgroup, 'lxc',
+                                           instance_name,
+                                           "memory.limit_in_bytes")))
+    except EnvironmentError:
+      # memory resource controller may be disabled, ignore
+      memory = 0
+
+    return memory
+
   def ListInstances(self):
     """Get the list of running instances.
 
@@ -154,7 +168,7 @@ class LXCHypervisor(hv_base.BaseHypervisor):
 
     @type instance_name: string
     @param instance_name: the instance name
-
+    @rtype: tuple of strings
     @return: (name, id, memory, vcpus, stat, times)
 
     """
@@ -172,7 +186,8 @@ class LXCHypervisor(hv_base.BaseHypervisor):
       return None
 
     cpu_list = self._GetCgroupCpuList(instance_name)
-    return (instance_name, 0, 0, len(cpu_list), 0, 0)
+    memory = self._GetCgroupMemoryLimit(instance_name) / (1024 ** 2)
+    return (instance_name, 0, memory, len(cpu_list), 0, 0)
 
   def GetAllInstancesInfo(self):
     """Get properties of all instances.
@@ -230,6 +245,17 @@ class LXCHypervisor(hv_base.BaseHypervisor):
       out.append("lxc.cgroup.cpuset.cpus = %s" %
                  instance.hvparams[constants.HV_CPU_MASK])
 
+    # Memory
+    # Conditionally enable, memory resource controller might be disabled
+    cgroup = self._GetCgroupMountPoint()
+    if os.path.exists(utils.PathJoin(cgroup, 'memory.limit_in_bytes')):
+        out.append("lxc.cgroup.memory.limit_in_bytes = %dM" %
+                    instance.beparams[constants.BE_MAXMEM])
+
+    if os.path.exists(utils.PathJoin(cgroup, 'memory.memsw.limit_in_bytes')):
+        out.append("lxc.cgroup.memory.memsw.limit_in_bytes = %dM" %
+                    instance.beparams[constants.BE_MAXMEM])
+
     # Device control
     # deny direct device access
     out.append("lxc.cgroup.devices.deny = a")
-- 
GitLab