Existing implementation of GetCgroupMountPoint has a problem because there is no guarantee that the first element of /proc/mounts which has fstype == cgroup contains all cgroup subsystems. Changes made by this commit are: - Introduce _MountCgroupSubsystem method to mount cgroup subsystem fs manually. - Introduce _GetOrPrepareCgroupSubsysMountPoint method to check if cgroup subsystem is already mounted, and invoke _MountCgroupSubsystem if not. Return the path of mounted subsystem. - Replace invokation of GetCgroupMountPoint by _GetOrPrepareCgroupSubsysMountPoint.
Signed-off-by: Yuto KAWAMURA(kawamuray) <[email protected]> --- lib/hypervisor/hv_lxc.py | 58 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/lib/hypervisor/hv_lxc.py b/lib/hypervisor/hv_lxc.py index 9aa833a..15548a5 100644 --- a/lib/hypervisor/hv_lxc.py +++ b/lib/hypervisor/hv_lxc.py @@ -54,6 +54,7 @@ class LXCHypervisor(hv_base.BaseHypervisor): """ _ROOT_DIR = pathutils.RUN_DIR + "/lxc" + _CGROUP_ROOT_DIR = _ROOT_DIR + "/cgroup" _DEVS = [ "c 1:3", # /dev/null "c 1:5", # /dev/zero @@ -155,6 +156,33 @@ class LXCHypervisor(hv_base.BaseHypervisor): raise HypervisorError("Failed to load instance stash file %s : %s" % (stash_file, err)) + @classmethod + def _MountCgroupSubsystem(cls, subsystem): + """Mount cgroup subsystem fs under the cgroup root dir. + + @type subsystem: string + @param subsystem: cgroup subsystem name to mount + @rtype string + @return path of subsystem mount point + + """ + subsys_dir = utils.PathJoin(cls._GetCgroupMountPoint(), subsystem) + if not os.path.isdir(subsys_dir): + try: + os.makedirs(subsys_dir) + except EnvironmentError, err: + raise HypervisorError("Failed to create directory %s: %s" % + (subsys_dir, err)) + + mount_cmd = ["mount", "-t", "cgroup", "-o", subsystem, subsystem, + subsys_dir] + result = utils.RunCmd(mount_cmd) + if result.failed: + raise HypervisorError("Failed to mount cgroup subsystem '%s': %s" % + (subsystem, result.output)) + + return subsys_dir + def _CleanupInstance(self, instance_name, stash): """Actual implementation of instance cleanup procedure. @@ -186,17 +214,33 @@ class LXCHypervisor(hv_base.BaseHypervisor): @classmethod def _GetCgroupMountPoint(cls): - for _, mountpoint, fstype, _ in utils.GetMounts(): - if fstype == "cgroup": - return mountpoint - raise errors.HypervisorError("The cgroup filesystem is not mounted") + """Return the directory that should be the base of cgroup fs. + + """ + return cls._CGROUP_ROOT_DIR + + @classmethod + def _GetOrPrepareCgroupSubsysMountPoint(cls, subsystem): + """Prepare cgroup subsystem mount point. + + @type subsystem: string + @param subsystem: cgroup subsystem name to mount + @rtype string + @return path of subsystem mount point + + """ + for _, mpoint, fstype, options in utils.GetMounts(): + if fstype == "cgroup" and subsystem in options.split(","): + return mpoint + + return cls._MountCgroupSubsystem(subsystem) @classmethod def _GetCgroupCpuList(cls, instance_name): """Return the list of CPU ids for an instance. """ - cgroup = cls._GetCgroupMountPoint() + cgroup = cls._GetOrPrepareCgroupSubsysMountPoint("cpuset") try: cpus = utils.ReadFile(utils.PathJoin(cgroup, 'lxc', instance_name, @@ -212,7 +256,7 @@ class LXCHypervisor(hv_base.BaseHypervisor): """Return the memory limit for an instance """ - cgroup = cls._GetCgroupMountPoint() + cgroup = cls._GetOrPrepareCgroupSubsysMountPoint("memory") try: memory = int(utils.ReadFile(utils.PathJoin(cgroup, 'lxc', instance_name, @@ -328,7 +372,7 @@ class LXCHypervisor(hv_base.BaseHypervisor): # Memory # Conditionally enable, memory resource controller might be disabled - cgroup = self._GetCgroupMountPoint() + cgroup = self._GetOrPrepareCgroupSubsysMountPoint("memory") 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]) -- 1.8.5.5
