LXC: add support for the memory controller
authorFaidon Liambotis <paravoid@debian.org>
Sun, 23 Dec 2012 16:14:25 +0000 (18:14 +0200)
committerGuido Trotter <ultrotter@google.com>
Sat, 2 Feb 2013 10:52:45 +0000 (11:52 +0100)
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

index d8ba8a8..d7deee8 100644 (file)
@@ -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")