[libvirt] [PATCH 5/7] LXC: Create host devices for container on host side

Gao feng gaofeng at cn.fujitsu.com
Mon Jul 15 06:08:00 UTC 2013


Otherwise the container will fail to start if we
enable user namespace, since there is no rights to
do mknod in uninit user namespace.

Signed-off-by: Gao feng <gaofeng at cn.fujitsu.com>
---
 src/lxc/lxc_container.c  | 263 ---------------------------------------
 src/lxc/lxc_controller.c | 313 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 313 insertions(+), 263 deletions(-)

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 6bc259b..955ad41 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1367,72 +1367,6 @@ static int lxcContainerMountAllFS(virDomainDefPtr vmDef,
 }
 
 
-static int lxcContainerSetupHostdevSubsysUSB(virDomainDefPtr vmDef,
-                                             virDomainHostdevDefPtr def,
-                                             virSecurityManagerPtr securityDriver)
-{
-    int ret = -1;
-    char *src = NULL;
-    char *dstdir = NULL;
-    char *dstfile = NULL;
-    struct stat sb;
-    mode_t mode;
-
-    if (virAsprintf(&dstdir, USB_DEVFS "/%03d",
-                    def->source.subsys.u.usb.bus) < 0)
-        goto cleanup;
-
-    if (virAsprintf(&dstfile, "%s/%03d",
-                    dstdir,
-                    def->source.subsys.u.usb.device) < 0)
-        goto cleanup;
-
-    if (virAsprintf(&src, "/.oldroot/%s", dstfile) < 0)
-        goto cleanup;
-
-    if (stat(src, &sb) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to access %s"), src);
-        goto cleanup;
-    }
-
-    if (!S_ISCHR(sb.st_mode)) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("USB source %s was not a character device"),
-                       src);
-        goto cleanup;
-    }
-
-    mode = 0700 | S_IFCHR;
-
-    if (virFileMakePath(dstdir) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to create %s"), dstdir);
-        goto cleanup;
-    }
-
-    VIR_DEBUG("Creating dev %s (%d,%d)",
-              dstfile, major(sb.st_rdev), minor(sb.st_rdev));
-    if (mknod(dstfile, mode, sb.st_rdev) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to create device %s"),
-                             dstfile);
-        goto cleanup;
-    }
-
-    if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0)
-        goto cleanup;
-
-    ret = 0;
-
-cleanup:
-    VIR_FREE(src);
-    VIR_FREE(dstfile);
-    VIR_FREE(dstdir);
-    return ret;
-}
-
-
 int lxcContainerSetupHostdevCapsMakePath(const char *dev)
 {
     int ret = -1;
@@ -1459,199 +1393,6 @@ cleanup:
 }
 
 
-static int lxcContainerSetupHostdevCapsStorage(virDomainDefPtr vmDef,
-                                               virDomainHostdevDefPtr def,
-                                               virSecurityManagerPtr securityDriver)
-{
-    char *src = NULL;
-    int ret = -1;
-    struct stat sb;
-    mode_t mode;
-    char *dev = def->source.caps.u.storage.block;
-
-    if (dev == NULL) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Missing storage host block path"));
-        goto cleanup;
-    }
-
-    if (virAsprintf(&src, "/.oldroot/%s", dev) < 0)
-        goto cleanup;
-
-    if (stat(src, &sb) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to access %s"),
-                             src);
-        goto cleanup;
-    }
-
-    if (!S_ISBLK(sb.st_mode)) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("Storage source %s must be a block device"),
-                       dev);
-        goto cleanup;
-    }
-
-    if (lxcContainerSetupHostdevCapsMakePath(dev) < 0) {
-        virReportError(errno,
-                       _("Failed to create directory for device %s"),
-                       dev);
-        goto cleanup;
-    }
-
-    mode = 0700 | S_IFBLK;
-
-    VIR_DEBUG("Creating dev %s (%d,%d)", dev,
-              major(sb.st_rdev), minor(sb.st_rdev));
-    if (mknod(dev, mode, sb.st_rdev) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to create device %s"),
-                             dev);
-        goto cleanup;
-    }
-
-    if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0)
-        goto cleanup;
-
-    ret = 0;
-
-cleanup:
-    VIR_FREE(src);
-    return ret;
-}
-
-
-static int lxcContainerSetupHostdevCapsMisc(virDomainDefPtr vmDef,
-                                            virDomainHostdevDefPtr def,
-                                            virSecurityManagerPtr securityDriver)
-{
-    char *src = NULL;
-    int ret = -1;
-    struct stat sb;
-    mode_t mode;
-    char *dev = def->source.caps.u.misc.chardev;
-
-    if (dev == NULL) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("Missing storage host block path"));
-        goto cleanup;
-    }
-
-    if (virAsprintf(&src, "/.oldroot/%s", dev) < 0)
-        goto cleanup;
-
-    if (stat(src, &sb) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to access %s"),
-                             src);
-        goto cleanup;
-    }
-
-    if (!S_ISCHR(sb.st_mode)) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("Storage source %s must be a character device"),
-                       dev);
-        goto cleanup;
-    }
-
-    if (lxcContainerSetupHostdevCapsMakePath(dev) < 0) {
-        virReportError(errno,
-                       _("Failed to create directory for device %s"),
-                       dev);
-        goto cleanup;
-    }
-
-    mode = 0700 | S_IFCHR;
-
-    VIR_DEBUG("Creating dev %s (%d,%d)", dev,
-              major(sb.st_rdev), minor(sb.st_rdev));
-    if (mknod(dev, mode, sb.st_rdev) < 0) {
-        virReportSystemError(errno,
-                             _("Unable to create device %s"),
-                             dev);
-        goto cleanup;
-    }
-
-    if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0)
-        goto cleanup;
-
-    ret = 0;
-
-cleanup:
-    VIR_FREE(src);
-    return ret;
-}
-
-static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef,
-                                          virDomainHostdevDefPtr def,
-                                          virSecurityManagerPtr securityDriver)
-{
-    switch (def->source.subsys.type) {
-    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
-        return lxcContainerSetupHostdevSubsysUSB(vmDef, def, securityDriver);
-
-    default:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("Unsupported host device mode %s"),
-                       virDomainHostdevSubsysTypeToString(def->source.subsys.type));
-        return -1;
-    }
-}
-
-
-static int lxcContainerSetupHostdevCaps(virDomainDefPtr vmDef,
-                                        virDomainHostdevDefPtr def,
-                                        virSecurityManagerPtr securityDriver)
-{
-    switch (def->source.subsys.type) {
-    case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
-        return lxcContainerSetupHostdevCapsStorage(vmDef, def, securityDriver);
-
-    case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
-        return lxcContainerSetupHostdevCapsMisc(vmDef, def, securityDriver);
-
-    case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET:
-        return 0; // case is handled in virLXCControllerMoveInterfaces
-
-    default:
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("Unsupported host device mode %s"),
-                       virDomainHostdevCapsTypeToString(def->source.subsys.type));
-        return -1;
-    }
-}
-
-
-static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef,
-                                        virSecurityManagerPtr securityDriver)
-{
-    size_t i;
-    VIR_DEBUG("Setting up hostdevs");
-
-    for (i = 0; i < vmDef->nhostdevs; i++) {
-        virDomainHostdevDefPtr def = vmDef->hostdevs[i];
-        switch (def->mode) {
-        case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
-            if (lxcContainerSetupHostdevSubsys(vmDef, def, securityDriver) < 0)
-                return -1;
-            break;
-        case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
-            if (lxcContainerSetupHostdevCaps(vmDef, def, securityDriver) < 0)
-                return -1;
-            break;
-        default:
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("Unsupported host device mode %s"),
-                           virDomainHostdevModeTypeToString(def->mode));
-            return -1;
-        }
-    }
-
-    VIR_DEBUG("Setup all hostdevs");
-    return 0;
-}
-
-
 /* Got a FS mapped to /, we're going the pivot_root
  * approach to do a better-chroot-than-chroot
  * this is based on this thread http://lkml.org/lkml/2008/3/5/29
@@ -1743,10 +1484,6 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
     if (lxcContainerMountAllFS(vmDef, sec_mount_options) < 0)
         goto cleanup;
 
-    /* Sets up any extra host devices from guest config */
-    if (lxcContainerSetupAllHostdevs(vmDef, securityDriver) < 0)
-        goto cleanup;
-
    /* Gets rid of all remaining mounts from host OS, including /.oldroot itself */
     if (lxcContainerUnmountSubtree("/.oldroot", true) < 0)
         goto cleanup;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 4907af4..dbb053a 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1288,6 +1288,316 @@ cleanup:
 }
 
 
+static int
+virLXCControllerSetupHostdevSubsysUSB(virDomainDefPtr vmDef,
+                                      virDomainHostdevDefPtr def,
+                                      virSecurityManagerPtr securityDriver)
+{
+    int ret = -1;
+    char *src = NULL;
+    char *dstdir = NULL;
+    char *dstfile = NULL;
+    char *vroot = NULL;
+    struct stat sb;
+    mode_t mode;
+
+    if (virAsprintf(&src, USB_DEVFS "/%03d/%03d",
+                    def->source.subsys.u.usb.bus,
+                    def->source.subsys.u.usb.device) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&vroot, "/%s/%s.dev/bus/usb/",
+                    LXC_STATE_DIR, vmDef->name) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&dstdir, "%s/%03d/", vroot,
+                    def->source.subsys.u.usb.bus) < 0)
+        goto cleanup;
+
+    if (virAsprintf(&dstfile, "%s/%03d", dstdir,
+                    def->source.subsys.u.usb.device) < 0)
+        goto cleanup;
+
+    if (stat(src, &sb) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to access %s"), src);
+        goto cleanup;
+    }
+
+    if (!S_ISCHR(sb.st_mode)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("USB source %s was not a character device"),
+                       src);
+        goto cleanup;
+    }
+
+    mode = 0700 | S_IFCHR;
+
+    if (virFileMakePath(dstdir) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to create %s"), dstdir);
+        goto cleanup;
+    }
+
+    VIR_DEBUG("Creating dev %s (%d,%d)",
+              dstfile, major(sb.st_rdev), minor(sb.st_rdev));
+    if (mknod(dstfile, mode, sb.st_rdev) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to create device %s"),
+                             dstfile);
+        goto cleanup;
+    }
+
+    if (virSecurityManagerSetHostdevLabel(securityDriver,
+                                          vmDef, def, vroot) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(src);
+    VIR_FREE(dstfile);
+    VIR_FREE(dstdir);
+    VIR_FREE(vroot);
+    return ret;
+}
+
+
+static int
+virLXCControllerSetupHostdevCapsStorage(virDomainDefPtr vmDef,
+                                        virDomainHostdevDefPtr def,
+                                        virSecurityManagerPtr securityDriver)
+{
+    char *dst = NULL;
+    char *path = NULL;
+    int len = 0;
+    int ret = -1;
+    struct stat sb;
+    mode_t mode;
+    char *dev = def->source.caps.u.storage.block;
+
+    if (dev == NULL) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Missing storage host block path"));
+        goto cleanup;
+    }
+
+    if (VIR_STRDUP(path, dev) < 0)
+        goto cleanup;
+
+    while (*(path + len) == '/')
+        len++;
+
+    if (virAsprintf(&dst, "/%s/%s.dev/%s",
+                    LXC_STATE_DIR, vmDef->name,
+                    strchr(path + len, '/')) < 0)
+        goto cleanup;
+
+    if (stat(dev, &sb) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to access %s"),
+                             dev);
+        goto cleanup;
+    }
+
+    if (!S_ISBLK(sb.st_mode)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Storage source %s must be a block device"),
+                       dev);
+        goto cleanup;
+    }
+
+    if (lxcContainerSetupHostdevCapsMakePath(dst) < 0) {
+        virReportError(errno,
+                       _("Failed to create directory for device %s"),
+                       dev);
+        goto cleanup;
+    }
+
+    mode = 0700 | S_IFBLK;
+
+    VIR_DEBUG("Creating dev %s (%d,%d)", dst,
+              major(sb.st_rdev), minor(sb.st_rdev));
+    if (mknod(dst, mode, sb.st_rdev) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to create device %s"),
+                             dst);
+        goto cleanup;
+    }
+
+    def->source.caps.u.storage.block = dst;
+    if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+cleanup:
+    def->source.caps.u.storage.block = dev;
+    VIR_FREE(dst);
+    VIR_FREE(path);
+    return ret;
+}
+
+
+static int
+virLXCControllerSetupHostdevCapsMisc(virDomainDefPtr vmDef,
+                                     virDomainHostdevDefPtr def,
+                                     virSecurityManagerPtr securityDriver)
+{
+    char *dst = NULL;
+    char *path = NULL;
+    int len = 0;
+    int ret = -1;
+    struct stat sb;
+    mode_t mode;
+    char *dev = def->source.caps.u.misc.chardev;
+
+    if (dev == NULL) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("Missing storage host block path"));
+        goto cleanup;
+    }
+
+    if (VIR_STRDUP(path, dev) < 0)
+        goto cleanup;
+
+    while (*(path + len) == '/')
+        len++;
+
+    if (virAsprintf(&dst, "/%s/%s.dev/%s",
+                    LXC_STATE_DIR, vmDef->name,
+                    strchr(path + len, '/')) < 0)
+        goto cleanup;
+
+    if (stat(dev, &sb) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to access %s"),
+                             dev);
+        goto cleanup;
+    }
+
+    if (!S_ISCHR(sb.st_mode)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Storage source %s must be a character device"),
+                       dev);
+        goto cleanup;
+    }
+
+    if (lxcContainerSetupHostdevCapsMakePath(dst) < 0) {
+        virReportError(errno,
+                       _("Failed to create directory for device %s"),
+                       dst);
+        goto cleanup;
+    }
+
+    mode = 0700 | S_IFCHR;
+
+    VIR_DEBUG("Creating dev %s (%d,%d)", dst,
+              major(sb.st_rdev), minor(sb.st_rdev));
+    if (mknod(dst, mode, sb.st_rdev) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to create device %s"),
+                             dev);
+        goto cleanup;
+    }
+
+    def->source.caps.u.misc.chardev = dst;
+    if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+cleanup:
+    def->source.caps.u.misc.chardev = dev;
+    VIR_FREE(dst);
+    VIR_FREE(path);
+    return ret;
+}
+
+static int
+virLXCControllerSetupHostdevSubsys(virDomainDefPtr vmDef,
+                                   virDomainHostdevDefPtr def,
+                                   virSecurityManagerPtr securityDriver)
+{
+    switch (def->source.subsys.type) {
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+        return virLXCControllerSetupHostdevSubsysUSB(vmDef,
+                                                     def,
+                                                     securityDriver);
+
+    default:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Unsupported host device mode %s"),
+                       virDomainHostdevSubsysTypeToString(def->source.subsys.type));
+        return -1;
+    }
+}
+
+
+static int
+virLXCControllerSetupHostdevCaps(virDomainDefPtr vmDef,
+                                 virDomainHostdevDefPtr def,
+                                 virSecurityManagerPtr securityDriver)
+{
+    switch (def->source.subsys.type) {
+    case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
+        return virLXCControllerSetupHostdevCapsStorage(vmDef,
+                                                       def,
+                                                       securityDriver);
+
+    case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
+        return virLXCControllerSetupHostdevCapsMisc(vmDef,
+                                                    def,
+                                                    securityDriver);
+
+    case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET:
+        return 0; // case is handled in virLXCControllerMoveInterfaces
+
+    default:
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Unsupported host device mode %s"),
+                       virDomainHostdevCapsTypeToString(def->source.subsys.type));
+        return -1;
+    }
+}
+
+
+static int
+virLXCControllerSetupAllHostdevs(virLXCControllerPtr ctrl)
+{
+    size_t i;
+    virDomainDefPtr vmDef = ctrl->def;
+    virSecurityManagerPtr securityDriver = ctrl->securityManager;
+    VIR_DEBUG("Setting up hostdevs");
+
+    for (i = 0; i < vmDef->nhostdevs; i++) {
+        virDomainHostdevDefPtr def = vmDef->hostdevs[i];
+        switch (def->mode) {
+        case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
+            if (virLXCControllerSetupHostdevSubsys(vmDef,
+                                                   def,
+                                                   securityDriver) < 0)
+                return -1;
+            break;
+        case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
+            if (virLXCControllerSetupHostdevCaps(vmDef,
+                                                 def,
+                                                 securityDriver) < 0)
+                return -1;
+            break;
+        default:
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("Unsupported host device mode %s"),
+                           virDomainHostdevModeTypeToString(def->mode));
+            return -1;
+        }
+    }
+
+    VIR_DEBUG("Setup all hostdevs");
+    return 0;
+}
+
+
 static int virLXCControllerSetupDisk(virLXCControllerPtr ctrl,
                                      virDomainDiskDefPtr def,
                                      virSecurityManagerPtr securityDriver)
@@ -1800,6 +2110,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
     if (virLXCControllerSetupAllDisks(ctrl) < 0)
         goto cleanup;
 
+    if (virLXCControllerSetupAllHostdevs(ctrl) < 0)
+        goto cleanup;
+
     if (virLXCControllerSetupFuse(ctrl) < 0)
         goto cleanup;
 
-- 
1.8.3.1




More information about the libvir-list mailing list