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

Reply via email to