This patch implements BalloonInstanceMemory function of the LXCHypervisor. Memory ballooning for the LXC container can be done by using memory.limit_in_bytes and memory.memsw.limit_in_bytes cgroup parameter. The Linux kernel does not kill processes inside the cgroup which is tried to shrink its memory accounted, so the update for memory.memsw.limit_in_bytes can be fail even if the update for memory.limit_in_bytes was succeed, so this function must care about all cgroup memory limit parameters consistency for update.
Signed-off-by: Yuto KAWAMURA(kawamuray) <[email protected]> --- lib/hypervisor/hv_lxc.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/lib/hypervisor/hv_lxc.py b/lib/hypervisor/hv_lxc.py index e94862f..8594628 100644 --- a/lib/hypervisor/hv_lxc.py +++ b/lib/hypervisor/hv_lxc.py @@ -23,6 +23,7 @@ """ +import errno import os import os.path import logging @@ -749,8 +750,35 @@ class LXCHypervisor(hv_base.BaseHypervisor): @param mem: actual memory size to use for instance runtime """ - # Currently lxc instances don't have memory limits - pass + mem_in_bytes = mem * 1024 ** 2 + current_mem_usage = self._GetCgroupMemoryLimit(instance.name) + is_shrink = mem_in_bytes <= current_mem_usage + + # memory.memsw.limit_in_bytes is the superlimit of the memory.limit_in_bytes + # so the order of setting these parameters is quite important. + cgparams = ["memory.memsw.limit_in_bytes", "memory.limit_in_bytes"] + if is_shrink: + cgparams.reverse() + + for i, cgparam in enumerate(cgparams): + try: + self._SetCgroupInstanceValue(instance.name, cgparam, str(mem_in_bytes)) + except EnvironmentError, err: + if is_shrink and err.errno == errno.EBUSY: + logging.warn("Unable to reclaim memory or swap usage from instance" + " %s", instance.name) + # Restore changed parameters for an atomicity + for restore_param in cgparams[0:i]: + try: + self._SetCgroupInstanceValue(instance.name, restore_param, + str(current_mem_usage)) + except EnvironmentError, restore_err: + logging.warn("Can't restore the cgroup parameter %s of %s: %s", + restore_param, instance.name, restore_err) + + raise HypervisorError("Failed to balloon the memory of %s, can't set" + " cgroup parameter %s: %s" % + (instance.name, cgparam, err)) def GetNodeInfo(self, hvparams=None): """Return information about the node. -- 2.0.4
