To alter our behavior depending on whether the kernel used supports certain cgroup parameters or not, this patch adds a helper function capable of checking that. The function is heavily based on earlier functions for reading cgroup parameter values, with some refactoring to keep the code in a readable state.
Signed-off-by: Hrvoje Ribicic <r...@google.com> --- lib/hypervisor/hv_lxc.py | 52 +++++++++++++++++++--------- test/py/ganeti.hypervisor.hv_lxc_unittest.py | 34 +++++++++++++----- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/lib/hypervisor/hv_lxc.py b/lib/hypervisor/hv_lxc.py index aa3072f..5ee0e04 100644 --- a/lib/hypervisor/hv_lxc.py +++ b/lib/hypervisor/hv_lxc.py @@ -336,37 +336,36 @@ class LXCHypervisor(hv_base.BaseHypervisor): return cgroups @classmethod - def _GetCgroupInstanceSubsysDir(cls, instance_name, subsystem): - """Return the directory of the cgroup subsystem for the instance. + def _GetCgroupSubsysDir(cls, subsystem): + """Return the directory of the cgroup subsystem we use. - @type instance_name: string - @param instance_name: instance name @type subsystem: string @param subsystem: cgroup subsystem name - @rtype string - @return path of the instance hierarchy directory for the subsystem + @rtype: string + @return: path of the hierarchy directory for the subsystem """ subsys_dir = cls._GetOrPrepareCgroupSubsysMountPoint(subsystem) base_group = cls._GetCurrentCgroupSubsysGroups().get(subsystem, "") - return utils.PathJoin(subsys_dir, base_group, "lxc", instance_name) + return utils.PathJoin(subsys_dir, base_group, "lxc") @classmethod - def _GetCgroupInstanceParamPath(cls, instance_name, param_name): + def _GetCgroupParamPath(cls, param_name, instance_name=None): """Return the path of the specified cgroup parameter file. - @type instance_name: string - @param instance_name: instance name @type param_name: string @param param_name: cgroup subsystem parameter name - @rtype string - @return path of the cgroup subsystem parameter file + @rtype: string + @return: path of the cgroup subsystem parameter file """ subsystem = param_name.split(".", 1)[0] - subsys_dir = cls._GetCgroupInstanceSubsysDir(instance_name, subsystem) - return utils.PathJoin(subsys_dir, param_name) + subsys_dir = cls._GetCgroupSubsysDir(subsystem) + if instance_name is not None: + return utils.PathJoin(subsys_dir, instance_name, param_name) + else: + return utils.PathJoin(subsys_dir, param_name) @classmethod def _GetCgroupInstanceValue(cls, instance_name, param_name): @@ -380,7 +379,8 @@ class LXCHypervisor(hv_base.BaseHypervisor): @return value read from cgroup subsystem fs """ - param_path = cls._GetCgroupInstanceParamPath(instance_name, param_name) + param_path = cls._GetCgroupParamPath(param_name, + instance_name=instance_name) return utils.ReadFile(param_path).rstrip("\n") @classmethod @@ -395,7 +395,8 @@ class LXCHypervisor(hv_base.BaseHypervisor): @param param_value: cgroup subsystem parameter value to be set """ - param_path = cls._GetCgroupInstanceParamPath(instance_name, param_name) + param_path = cls._GetCgroupParamPath(param_name, + instance_name=instance_name) # When interacting with cgroup fs, errno is quite important information # to see what happened when setting a cgroup parameter, so just throw # an error to the upper level. @@ -411,6 +412,25 @@ class LXCHypervisor(hv_base.BaseHypervisor): os.close(fd) @classmethod + def _IsCgroupParameterPresent(cls, parameter, hvparams=None): + """Return whether a cgroup parameter can be used. + + This is checked by seeing whether there is a file representation of the + parameter in the location where the cgroup is mounted. + + @type parameter: string + @param parameter: The name of the parameter. + @param hvparams: dict + @param hvparams: The hypervisor parameters, optional. + @rtype: boolean + + """ + cls._EnsureCgroupMounts(hvparams) + param_path = cls._GetCgroupParamPath(parameter) + + return os.path.exists(param_path) + + @classmethod def _GetCgroupCpuList(cls, instance_name): """Return the list of CPU ids for an instance. diff --git a/test/py/ganeti.hypervisor.hv_lxc_unittest.py b/test/py/ganeti.hypervisor.hv_lxc_unittest.py index 208ddcf..a403d48 100755 --- a/test/py/ganeti.hypervisor.hv_lxc_unittest.py +++ b/test/py/ganeti.hypervisor.hv_lxc_unittest.py @@ -178,23 +178,39 @@ class TestCgroupReadData(LXCHypervisorTestCase): @patch_object(LXCHypervisor, "_GetOrPrepareCgroupSubsysMountPoint") @patch_object(LXCHypervisor, "_GetCurrentCgroupSubsysGroups") - def testGetCgroupInstanceSubsysDir(self, getcgg_mock, getmp_mock): + def testGetCgroupSubsysDir(self, getcgg_mock, getmp_mock): getmp_mock.return_value = "/cg" getcgg_mock.return_value = {"cpuset": "grp"} - self.assertEqual(self.hv._GetCgroupInstanceSubsysDir("instance1", "memory"), - "/cg/lxc/instance1") - self.assertEqual(self.hv._GetCgroupInstanceSubsysDir("instance1", "cpuset"), - "/cg/grp/lxc/instance1") + self.assertEqual( + self.hv._GetCgroupSubsysDir("memory"), "/cg/lxc" + ) + self.assertEqual( + self.hv._GetCgroupSubsysDir("cpuset"), "/cg/grp/lxc" + ) - @patch_object(LXCHypervisor, "_GetCgroupInstanceSubsysDir") + @patch_object(LXCHypervisor, "_GetOrPrepareCgroupSubsysMountPoint") + @patch_object(LXCHypervisor, "_GetCurrentCgroupSubsysGroups") + def testGetCgroupParamPath(self, getcgg_mock, getmp_mock): + getmp_mock.return_value = "/cg" + getcgg_mock.return_value = {"cpuset": "grp"} + self.assertEqual( + self.hv._GetCgroupParamPath("memory.memsw.limit_in_bytes", + instance_name="instance1"), + "/cg/lxc/instance1/memory.memsw.limit_in_bytes" + ) + self.assertEqual( + self.hv._GetCgroupParamPath("cpuset.cpus"), + "/cg/grp/lxc/cpuset.cpus" + ) + + @patch_object(LXCHypervisor, "_GetCgroupSubsysDir") def testGetCgroupInstanceValue(self, getdir_mock): - getdir_mock.return_value = utils.PathJoin(self.cgroot, "memory", "lxc", - "instance1") + getdir_mock.return_value = utils.PathJoin(self.cgroot, "memory", "lxc") self.assertEqual(self.hv._GetCgroupInstanceValue("instance1", "memory.limit_in_bytes"), "128") getdir_mock.return_value = utils.PathJoin(self.cgroot, "cpuset", - "some_group", "lxc", "instance1") + "some_group", "lxc") self.assertEqual(self.hv._GetCgroupInstanceValue("instance1", "cpuset.cpus"), "0-1") -- 2.2.0.rc0.207.ga3a616c