]> git.proxmox.com Git - mirror_lxc.git/commitdiff
python: Add add_device() function
authorStéphane Graber <stgraber@ubuntu.com>
Thu, 22 Nov 2012 22:35:44 +0000 (17:35 -0500)
committerStéphane Graber <stgraber@ubuntu.com>
Mon, 26 Nov 2012 14:31:52 +0000 (09:31 -0500)
This introduces a new add_devices() call to the python API.

Parameters:
 - path => Mandatory, path to a character or block device on the host
 - destpath => Optional, alternative path inside the container

The function will allow the node in the container's devices cgroup and
then create the entry in the container.

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
src/python-lxc/lxc/__init__.py

index 183c7789ffba0de4dc6ae60e65387c0f82e3e1cb..907303e3396cbfded149722bfd151685e6905906 100644 (file)
@@ -25,6 +25,7 @@ import _lxc
 import glob
 import os
 import subprocess
+import stat
 import tempfile
 import time
 import warnings
@@ -149,6 +150,66 @@ class Container(_lxc.Container):
         _lxc.Container.__init__(self, name)
         self.network = ContainerNetworkList(self)
 
+    def add_device(self, path, destpath=None):
+        """
+            Add device to running container.
+        """
+
+        if not destpath:
+            destpath = path
+
+        if not os.path.exists(path):
+            return False
+
+        # Lookup the source
+        path_stat = os.stat(path)
+        mode = stat.S_IMODE(path_stat.st_mode)
+
+        # Lookup the cgroup
+        cgroup_path = None
+        with open("/proc/%s/cgroup" % self.init_pid, "r") as fd:
+            for line in fd:
+                if ":devices:" in line:
+                    cgroup_path = line.split(":")[-1].strip()
+                    break
+            else:
+                return False
+
+        # Lookup the cgroup mount point
+        cgroup = None
+        with open("/proc/mounts", "r") as fd:
+            for line in fd:
+                mount = line.split()
+                if (mount[2] == "cgroup" and "devices" in mount[3]
+                        and os.path.exists("%s/%s" % (mount[1], cgroup_path))):
+                    cgroup = "%s/%s" % (mount[1], cgroup_path)
+                    break
+
+        if not os.path.exists(cgroup):
+            return False
+
+        # Allow the target
+        with open("%s/devices.allow" % cgroup, "a") as fd:
+            if stat.S_ISBLK(path_stat.st_mode):
+                fd.write("b %s:%s rwm" % (int(path_stat.st_rdev / 256),
+                                          int(path_stat.st_rdev % 256)))
+            elif stat.S_ISCHR(path_stat.st_mode):
+                fd.write("c %s:%s rwm" % (int(path_stat.st_rdev / 256),
+                                          int(path_stat.st_rdev % 256)))
+
+        # Create the target
+        rootfs = "/proc/%s/root/" % self.init_pid
+        container_path = "%s/%s" % (rootfs, destpath)
+
+        if os.path.exists(container_path):
+            os.remove(container_path)
+
+        os.mknod(container_path, path_stat.st_mode, path_stat.st_rdev)
+        os.chmod(container_path, mode)
+        os.chown(container_path, 0, 0)
+
+        return True
+
     def append_config_item(self, key, value):
         """
             Append 'value' to 'key', assuming 'key' is a list.