[libvirt] [PATCH] Inherit namespace feature 2

Daniel P. Berrange berrange at redhat.com
Fri Aug 14 12:09:56 UTC 2015


On Sun, Aug 09, 2015 at 12:09:32AM +0530, ik.nitk wrote:
> diff --git a/src/Makefile.am b/src/Makefile.am
> index c4d49a5..b2ceda3 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -1320,7 +1320,7 @@ libvirt_driver_lxc_impl_la_CFLAGS = \
>  		-I$(srcdir)/access \
>  		-I$(srcdir)/conf \
>  		$(AM_CFLAGS)
> -libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(FUSE_LIBS)
> +libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(LIBXML_LIBS) libvirt-lxc.la $(FUSE_LIBS)

I understand why you needed libvirt-lxc.la in your v1 of
this patch, but with the code moved into lxc_process.c
this is no longer needed. Only LIBXML_LIBS needs adding.

> diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
> index 8340b1f..72b1d44 100644
> --- a/src/lxc/lxc_conf.h
> +++ b/src/lxc/lxc_conf.h
> @@ -67,6 +67,21 @@ struct _virLXCDriverConfig {
>      bool securityRequireConfined;
>  };
>  
> +
> +typedef enum {
> +    VIR_DOMAIN_NAMESPACE_SHARENET = 0,
> +    VIR_DOMAIN_NAMESPACE_SHAREIPC,
> +    VIR_DOMAIN_NAMESPACE_SHAREUTS,
> +    VIR_DOMAIN_NAMESPACE_LAST,
> +} virDomainNamespace;

We shold really have LXC in the name, eg virLXCDomainNamespace
and VIR_LXC_DOMAIN_NAMESPACE_* constants.

> +
> +typedef struct _lxcDomainDef lxcDomainDef;
> +typedef lxcDomainDef *lxcDomainDefPtr;
> +struct _lxcDomainDef {
> +    char *ns_type[VIR_DOMAIN_NAMESPACE_LAST];

There are only 3 value types, so we should just have an enum
for them too, instead of comparing strings everywhere

> +    char *ns_val[VIR_DOMAIN_NAMESPACE_LAST];
> +};
> +

> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
> index 11e9514..103e9bc 100644
> --- a/src/lxc/lxc_container.c
> +++ b/src/lxc/lxc_container.c


>  /**
>   * lxcContainerStart:
> @@ -2342,13 +2432,17 @@ int lxcContainerStart(virDomainDefPtr def,
>                        int *passFDs,
>                        int control,
>                        int handshakefd,
> +                      int nsInheritFDs[VIR_DOMAIN_NAMESPACE_LAST],
>                        size_t nttyPaths,
>                        char **ttyPaths)
>  {
>      pid_t pid;
> -    int cflags;
> +    int cflags, i;
>      int stacksize = getpagesize() * 4;
>      char *stack, *stacktop;
> +    int savedNsFDs[VIR_DOMAIN_NAMESPACE_LAST];
> +    int preserve_mask = 0;
> +    lxcDomainDefPtr lxcDef;
>      lxc_child_argv_t args = {
>          .config = def,
>          .securityDriver = securityDriver,
> @@ -2368,7 +2462,12 @@ int lxcContainerStart(virDomainDefPtr def,
>  
>      stacktop = stack + stacksize;
>  
> -    cflags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|SIGCHLD;
> +    lxcDef = def->namespaceData;
> +    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
> +       if (lxcDef && lxcDef->ns_type[i])
> +           preserve_mask |= nsInfoLocal[i].clone_flag;
> +
> +    cflags = CLONE_NEWPID|CLONE_NEWNS|SIGCHLD;
>  
>      if (userns_required(def)) {
>          if (userns_supported()) {
> @@ -2381,10 +2480,37 @@ int lxcContainerStart(virDomainDefPtr def,
>              return -1;
>          }
>      }
> +    if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHARENET]) {

We don't actually need lxcDef here at all - we should just look
at the nsInheritFDs list, eg

  if (nsInheritFDs[VIR_DOMAIN_NAMESPACE_SHARENET] != -1) {
     ...

> +        if (lxcNeedNetworkNamespace(def)) {
> +            VIR_DEBUG("Enable network namespaces");
> +            cflags |= CLONE_NEWNET;
> +        }
> +    } else {
> +        VIR_DEBUG("Inheriting a net namespace");

We should report an error in this branch if lxcNeedNetworkNamespace
returns true, as that indicates a contradictory XML config.

> +    }
>  
> -    if (lxcNeedNetworkNamespace(def)) {
> -        VIR_DEBUG("Enable network namespaces");
> -        cflags |= CLONE_NEWNET;
> +    if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHAREIPC]) {
> +        cflags |= CLONE_NEWIPC;
> +    } else {
> +        VIR_DEBUG("Inheriting an IPC namespace");
> +    }
> +
> +    if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHAREUTS]) {
> +        cflags |= CLONE_NEWUTS;
> +    } else {
> +        VIR_DEBUG("Inheriting a UTS namespace");
> +    }
> +
> +    if (lxcDef && lxcPreserve_ns(savedNsFDs, preserve_mask) < 0) {
> +        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
> +                       _("failed to preserve the namespace"));
> +        return -1;
> +    }
> +
> +    if (lxcDef && lxcAttach_ns(nsInheritFDs) < 0) {
> +        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
> +                       _("failed to attach the namespace"));
> +        return -1;
>      }
>  
>      VIR_DEBUG("Cloning container init process");
> @@ -2397,7 +2523,14 @@ int lxcContainerStart(virDomainDefPtr def,
>                               _("Failed to run clone container"));
>          return -1;
>      }
> +    if (lxcDef && lxcAttach_ns(savedNsFDs)) {
> +        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
> +                             _("failed to restore saved namespaces"));
> +    }

You are in libvirt_lxc controller context here, so I see
why you have to preserve & re-attach the original namespace.
If we push the lxcAttach_ns call down into the lxcContainreChild
method, then we're in the container context so can skip the
preserve & re-attach part entirely

> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
> index 110a556..1cbe0b3 100644
> --- a/src/lxc/lxc_controller.c
> +++ b/src/lxc/lxc_controller.c

> diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c
> index 70606f3..5e63969 100644
> --- a/src/lxc/lxc_domain.c
> +++ b/src/lxc/lxc_domain.c
> @@ -26,8 +26,14 @@
>  #include "viralloc.h"
>  #include "virlog.h"
>  #include "virerror.h"
> +#include <fcntl.h>
> +#include <libxml/xpathInternals.h>
> +#include "virstring.h"
> +#include "virutil.h"
> +#include "virfile.h"
>  

> +    for (i = 0; i < n; i++) {
> +        feature =
> +            virDomainNamespaceTypeFromString((const char *) nodes[i]->name);
> +        if (feature < 0) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> +                            _("unsupported Namespace feature: %s"),
> +                            nodes[i]->name);
> +            goto error;
> +        }
> +
> +        ctxt->node = nodes[i];
> +
> +        switch ((virDomainNamespace) feature) {
> +        case VIR_DOMAIN_NAMESPACE_SHARENET:
> +        case VIR_DOMAIN_NAMESPACE_SHAREIPC:
> +        case VIR_DOMAIN_NAMESPACE_SHAREUTS:
> +            {
> +                tmp = virXMLPropString(nodes[i], "type");
> +                if (tmp == NULL) {
> +                    virReportError(VIR_ERR_INTERNAL_ERROR,
> +                                   "%s", _("No lxc environment type specified"));
> +                    goto error;
> +                }
> +                /* save the tmp so that its needed while writing to xml */
> +                lxcDef->ns_type[feature] = tmp;
> +                tmp = virXMLPropString(nodes[i], "value");
> +                if (tmp == NULL) {
> +                    virReportError(VIR_ERR_INTERNAL_ERROR,
> +                                   "%s", _("No lxc environment type specified"));
> +                    goto error;
> +                }
> +                lxcDef->ns_val[feature] = tmp;
> +            }
> +            break;
> +        case VIR_DOMAIN_NAMESPACE_LAST:

The switch() is pretty pointless, because this case is impossible
to reach, so you only ever execute the first case. Thus switch()
can be removed entirely. Also, this is where we should be converting
ns_type to an enum

> +static int
> +lxcDomainDefNamespaceFormatXML(virBufferPtr buf,
> +                               void *nsdata)
> +{
> +    lxcDomainDefPtr lxcDef = nsdata;
> +    size_t j;
> +
> +    if (!lxcDef)
> +       return 0;
> +
> +    virBufferAddLit(buf, "<lxc:namespace>\n");
> +    virBufferAdjustIndent(buf, 2);
> +
> +    for (j = 0; j < VIR_DOMAIN_NAMESPACE_LAST; j++) {
> +        switch ((virDomainNamespace) j) {
> +        case VIR_DOMAIN_NAMESPACE_SHAREIPC:
> +        case VIR_DOMAIN_NAMESPACE_SHAREUTS:
> +        case VIR_DOMAIN_NAMESPACE_SHARENET:
> +            {
> +                if (lxcDef->ns_type[j]) {
> +                    virBufferAsprintf(buf, "<lxc:%s type='%s' value='%s'/>\n",
> +                                      virDomainNamespaceTypeToString(j),
> +                                      lxcDef->ns_type[j],
> +                                      lxcDef->ns_val[j]);
> +                }
> +            }
> +            break;
> +        case VIR_DOMAIN_NAMESPACE_LAST:
> +            break;
> +        }

Again the switch is not required as the _LAST case is impossible
due to the terminating condition of your for() loop/.

> +    }
> +
> +    virBufferAdjustIndent(buf, -2);
> +    virBufferAddLit(buf, "</lxc:namespace>\n");
> +    return 0;
> +}

> diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
> index e99b039..ead7f67 100644
> --- a/src/lxc/lxc_process.c
> +++ b/src/lxc/lxc_process.c
> @@ -359,6 +359,97 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
>      return ret;
>  }
>  
> +static const char *nsInfoLocal[] = { "net", "ipc", "uts" };
> +/**
> + * virLXCProcessSetupNamespaces:
> + * @conn: pointer to connection
> + * @def: pointer to virtual machines namespaceData
> + * @nsFDs: out parameter to store the namespace FD
> + *
> + * Opens the specified namespace that needs to be shared and
> + * will moved into the container namespace later after clone has been called.
> + *
> + * Returns 0 on success or -1 in case of error
> + */
> +static int virLXCProcessSetupNamespaces(virConnectPtr conn,
> +                                        lxcDomainDefPtr lxcDef,
> +                                        int nsFDs[VIR_DOMAIN_NAMESPACE_LAST])
> +{
> +    int i, n, rc = 0;
> +    virDomainPtr dom = NULL;
> +    pid_t pid;
> +    int nfdlist;
> +    int *fdlist;
> +    char *path = NULL;
> +    char *eptr;
> +
> +    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
> +        nsFDs[i] = -1;
> +    /*If there are no namespace to be opened just return success*/
> +    if (lxcDef == NULL) return 0;
> +
> +    if (STREQ_NULLABLE("netns", lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHARENET])) {
> +        if (virAsprintf(&path, "/var/run/netns/%s", lxcDef->ns_val[VIR_DOMAIN_NAMESPACE_SHARENET]) < 0)
> +            return  -1;
> +        nsFDs[VIR_DOMAIN_NAMESPACE_SHARENET] = open(path, O_RDONLY);
> +        VIR_FREE(path);
> +        if (nsFDs[VIR_DOMAIN_NAMESPACE_SHARENET] < 0) {
> +            virReportSystemError(errno,
> +                      _("failed to open netns %s"), lxcDef->ns_val[VIR_DOMAIN_NAMESPACE_SHARENET]);
> +            return -1;
> +        }
> +    }
> +    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
> +        /* If not yet intialized by above: netns*/
> +        if (lxcDef->ns_type[i] && nsFDs[i] == -1) {
> +            pid = strtol(lxcDef->ns_val[i], &eptr, 10);
> +            if (*eptr != '\0' || pid < 1) {

Here you are converting the ns_val to an int and if it fails you're
doing the name based code path. It would be better if you actually
checked the ns_type field since we have it available.

> +                /* check if the domain is running, then set the namespaces
> +                 * to that container
> +                 */
> +                const char *ns[] = { "user", "ipc", "uts", "net", "pid", "mnt" };
> +                dom = virDomainLookupByName(conn, lxcDef->ns_val[i]);
> +                if (!dom) {
> +                    virReportError(virGetLastError()->code,
> +                                   _("Unable to lookup peer container %s"),
> +                                   lxcDef->ns_val[i]);
> +                    rc = -1;
> +                    goto cleanup;
> +                }
> +                if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0) {
> +                    virReportError(virGetLastError()->code,
> +                                   _("Unable to open %s"), lxcDef->ns_val[i]);
> +                    rc = -1;
> +                    goto cleanup;
> +                }
> +                for (n = 0; n < ARRAY_CARDINALITY(ns); n++) {
> +                    if (STREQ(ns[n], nsInfoLocal[i])) {
> +                        nsFDs[i] = fdlist[n];
> +                    } else {
> +                        if (VIR_CLOSE(fdlist[n]) < 0)
> +                           VIR_ERROR(_("failed to close fd. ignoring.."));
> +                    }
> +                }
> +                if (nfdlist > 0)
> +                    VIR_FREE(fdlist);
> +            } else {
> +                if (virAsprintf(&path, "/proc/%d/ns/%s", pid, nsInfoLocal[i]) < 0)
> +                    return -1;
> +                nsFDs[i] = open(path, O_RDONLY);
> +                VIR_FREE(path);
> +                if (nsFDs[i] < 0) {
> +                    virReportSystemError(errno,
> +                      _("failed to open ns %s"), lxcDef->ns_val[i]);
> +                    return -1;
> +                }
> +            }

In general I think these would be better broken into separate methods


There are also misc errors reported from 'make syntax-check' such as
using 'int i' instead of 'size_t i'

Broadly speaking this patch is conceptually good. I've got a variety
of cleanups suggested, and rather than waste your time trying to
fix it up, I've just done them myself. I'll send a v3 patch which I'd
like you to test to ensure I didn't break anything you did.

The differences are

 po/POTFILES.in           |   1 +
 src/Makefile.am          |   6 +-
 src/lxc/lxc_conf.h       |  15 ----
 src/lxc/lxc_container.c  | 172 +++++++++++++------------------------------
 src/lxc/lxc_container.h  |   3 +-
 src/lxc/lxc_controller.c |  17 +++--
 src/lxc/lxc_domain.c     | 109 ++++++++++++---------------
 src/lxc/lxc_domain.h     |  25 +++++++
 src/lxc/lxc_process.c    | 186 ++++++++++++++++++++++++++++-------------------
 9 files changed, 252 insertions(+), 282 deletions(-)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index c58a7c1..dcabcc8 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -85,6 +85,7 @@ src/lxc/lxc_native.c
 src/lxc/lxc_container.c
 src/lxc/lxc_conf.c
 src/lxc/lxc_controller.c
+src/lxc/lxc_domain.c
 src/lxc/lxc_driver.c
 src/lxc/lxc_process.c
 src/libxl/libxl_domain.c
diff --git a/src/Makefile.am b/src/Makefile.am
index b2ceda3..fde11ff 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1320,7 +1320,11 @@ libvirt_driver_lxc_impl_la_CFLAGS = \
 		-I$(srcdir)/access \
 		-I$(srcdir)/conf \
 		$(AM_CFLAGS)
-libvirt_driver_lxc_impl_la_LIBADD = $(CAPNG_LIBS) $(LIBNL_LIBS) $(LIBXML_LIBS) libvirt-lxc.la $(FUSE_LIBS)
+libvirt_driver_lxc_impl_la_LIBADD = \
+		$(CAPNG_LIBS) \
+		$(LIBNL_LIBS) \
+		$(LIBXML_LIBS) \
+		$(FUSE_LIBS)
 if WITH_BLKID
 libvirt_driver_lxc_impl_la_CFLAGS += $(BLKID_CFLAGS)
 libvirt_driver_lxc_impl_la_LIBADD += $(BLKID_LIBS)
diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index 72b1d44..8340b1f 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -67,21 +67,6 @@ struct _virLXCDriverConfig {
     bool securityRequireConfined;
 };
 
-
-typedef enum {
-    VIR_DOMAIN_NAMESPACE_SHARENET = 0,
-    VIR_DOMAIN_NAMESPACE_SHAREIPC,
-    VIR_DOMAIN_NAMESPACE_SHAREUTS,
-    VIR_DOMAIN_NAMESPACE_LAST,
-} virDomainNamespace;
-
-typedef struct _lxcDomainDef lxcDomainDef;
-typedef lxcDomainDef *lxcDomainDefPtr;
-struct _lxcDomainDef {
-    char *ns_type[VIR_DOMAIN_NAMESPACE_LAST];
-    char *ns_val[VIR_DOMAIN_NAMESPACE_LAST];
-};
-
 struct _virLXCDriver {
     virMutex lock;
 
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 103e9bc..d52f57e 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -111,6 +111,7 @@ struct __lxc_child_argv {
     size_t nttyPaths;
     char **ttyPaths;
     int handshakefd;
+    int *nsInheritFDs;
 };
 
 static int lxcContainerMountFSBlock(virDomainFSDefPtr fs,
@@ -2144,6 +2145,35 @@ static int lxcContainerDropCapabilities(virDomainDefPtr def ATTRIBUTE_UNUSED,
 
 
 /**
+ * lxcAttach_ns:
+ * @ns_fd: array of namespaces to attach
+ */
+static int lxcAttachNS(int *ns_fd)
+{
+    size_t i;
+
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) {
+        if (ns_fd[i] < 0)
+            continue;
+         VIR_DEBUG("Setting into namespace\n");
+        /* We get EINVAL if new NS is same as the current
+         * NS, or if the fd namespace doesn't match the
+         * type passed to setns()'s second param. Since we
+         * pass 0, we know the EINVAL is harmless
+         */
+        if (setns(ns_fd[i], 0) < 0 &&
+            errno != EINVAL) {
+            virReportSystemError(errno, _("failed to set namespace '%s'"),
+                                 virLXCDomainNamespaceTypeToString(i));
+            return -1;
+        }
+        VIR_FORCE_CLOSE(ns_fd[i]);
+    }
+    return 0;
+}
+
+
+/**
  * lxcContainerChild:
  * @data: pointer to container arguments
  *
@@ -2172,6 +2202,12 @@ static int lxcContainerChild(void *data)
         goto cleanup;
     }
 
+    if (lxcAttachNS(argv->nsInheritFDs) < 0) {
+        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
+                       _("failed to attach the namespace"));
+        return -1;
+    }
+
     /* Wait for controller to finish setup tasks, including
      * things like move of network interfaces, uid/gid mapping
      */
@@ -2321,96 +2357,6 @@ virArch lxcContainerGetAlt32bitArch(virArch arch)
     return VIR_ARCH_NONE;
 }
 
-struct lxcNSInfo {
-        const char *proc_name;
-        int clone_flag;
-}nsInfoLocal[VIR_DOMAIN_NAMESPACE_LAST] = {
-    [VIR_DOMAIN_NAMESPACE_SHARENET] = {"net", CLONE_NEWNET},
-    [VIR_DOMAIN_NAMESPACE_SHAREIPC] = {"ipc", CLONE_NEWIPC},
-    [VIR_DOMAIN_NAMESPACE_SHAREUTS] = {"uts", CLONE_NEWUTS}
-};
-
-
-static void lxcClose_ns(int ns_fd[VIR_DOMAIN_NAMESPACE_LAST])
-{
-    int i;
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
-        if (ns_fd[i] > -1) {
-            if (VIR_CLOSE(ns_fd[i]) < 0)
-                virReportSystemError(errno, "%s", _("failed to close file"));
-            ns_fd[i] = -1;
-        }
-    }
-}
-
-
-/**
- * lxcPreserve_ns:
- * @ns_fd: array to store current namespace
- * @clone_flags: namespaces that need to be preserved
- */
-static int lxcPreserve_ns(int ns_fd[VIR_DOMAIN_NAMESPACE_LAST], int clone_flags)
-{
-    int i, saved_errno;
-    char *path = NULL;
-
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
-        ns_fd[i] = -1;
-
-    if (!virFileExists("/proc/self/ns")) {
-        virReportSystemError(errno, "%s",
-                             _("Kernel does not support attach; preserve_ns ignored"));
-        return -1;
-    }
-
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
-        if ((clone_flags & nsInfoLocal[i].clone_flag) == 0)
-            continue;
-        if (virAsprintf(&path, "/proc/self/ns/%s",
-                         nsInfoLocal[i].proc_name) < 0)
-              goto error;
-        ns_fd[i] = open(path, O_RDONLY | O_CLOEXEC);
-        if (ns_fd[i] < 0)
-            goto error;
-        VIR_FREE(path);
-    }
-    return 0;
- error:
-    saved_errno = errno;
-    lxcClose_ns(ns_fd);
-    errno = saved_errno;
-    virReportSystemError(errno, _("lxcPreserve_ns failed for '%s'"), path);
-    VIR_FREE(path);
-    return -1;
-}
-
-/**
- * lxcAttach_ns:
- * @ns_fd: array of namespaces to attach
- */
-static int lxcAttach_ns(const int ns_fd[VIR_DOMAIN_NAMESPACE_LAST])
-{
-    int i;
-
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
-        if (ns_fd[i] < 0)
-            continue;
-         VIR_DEBUG("Setting into namespace\n");
-        /* We get EINVAL if new NS is same as the current
-         * NS, or if the fd namespace doesn't match the
-         * type passed to setns()'s second param. Since we
-         * pass 0, we know the EINVAL is harmless
-         */
-        if (setns(ns_fd[i], 0) < 0 &&
-            errno != EINVAL) {
-            virReportSystemError(errno, _("failed to set namespace '%s'")
-                                 , nsInfoLocal[i].proc_name);
-            return -1;
-        }
-    }
-    return 0;
-}
-
 
 /**
  * lxcContainerStart:
@@ -2432,17 +2378,14 @@ int lxcContainerStart(virDomainDefPtr def,
                       int *passFDs,
                       int control,
                       int handshakefd,
-                      int nsInheritFDs[VIR_DOMAIN_NAMESPACE_LAST],
+                      int *nsInheritFDs,
                       size_t nttyPaths,
                       char **ttyPaths)
 {
     pid_t pid;
-    int cflags, i;
+    int cflags;
     int stacksize = getpagesize() * 4;
     char *stack, *stacktop;
-    int savedNsFDs[VIR_DOMAIN_NAMESPACE_LAST];
-    int preserve_mask = 0;
-    lxcDomainDefPtr lxcDef;
     lxc_child_argv_t args = {
         .config = def,
         .securityDriver = securityDriver,
@@ -2453,7 +2396,8 @@ int lxcContainerStart(virDomainDefPtr def,
         .monitor = control,
         .nttyPaths = nttyPaths,
         .ttyPaths = ttyPaths,
-        .handshakefd = handshakefd
+        .handshakefd = handshakefd,
+        .nsInheritFDs = nsInheritFDs,
     };
 
     /* allocate a stack for the container */
@@ -2462,11 +2406,6 @@ int lxcContainerStart(virDomainDefPtr def,
 
     stacktop = stack + stacksize;
 
-    lxcDef = def->namespaceData;
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
-       if (lxcDef && lxcDef->ns_type[i])
-           preserve_mask |= nsInfoLocal[i].clone_flag;
-
     cflags = CLONE_NEWPID|CLONE_NEWNS|SIGCHLD;
 
     if (userns_required(def)) {
@@ -2480,39 +2419,33 @@ int lxcContainerStart(virDomainDefPtr def,
             return -1;
         }
     }
-    if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHARENET]) {
+    if (nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHARENET] == -1) {
         if (lxcNeedNetworkNamespace(def)) {
             VIR_DEBUG("Enable network namespaces");
             cflags |= CLONE_NEWNET;
         }
     } else {
+        if (lxcNeedNetworkNamespace(def)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Config askes for inherit net namespace "
+                             "as well as private network interfaces"));
+            return -1;
+        }
         VIR_DEBUG("Inheriting a net namespace");
     }
 
-    if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHAREIPC]) {
+    if (nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC] == -1) {
         cflags |= CLONE_NEWIPC;
     } else {
         VIR_DEBUG("Inheriting an IPC namespace");
     }
 
-    if (!lxcDef || !lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHAREUTS]) {
+    if (nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHAREUTS] == -1) {
         cflags |= CLONE_NEWUTS;
     } else {
         VIR_DEBUG("Inheriting a UTS namespace");
     }
 
-    if (lxcDef && lxcPreserve_ns(savedNsFDs, preserve_mask) < 0) {
-        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
-                       _("failed to preserve the namespace"));
-        return -1;
-    }
-
-    if (lxcDef && lxcAttach_ns(nsInheritFDs) < 0) {
-        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
-                       _("failed to attach the namespace"));
-        return -1;
-    }
-
     VIR_DEBUG("Cloning container init process");
     pid = clone(lxcContainerChild, stacktop, cflags, &args);
     VIR_FREE(stack);
@@ -2523,14 +2456,7 @@ int lxcContainerStart(virDomainDefPtr def,
                              _("Failed to run clone container"));
         return -1;
     }
-    if (lxcDef && lxcAttach_ns(savedNsFDs)) {
-        virReportError(VIR_ERR_SYSTEM_ERROR, "%s",
-                             _("failed to restore saved namespaces"));
-    }
 
-    /* clean up */
-    if (lxcDef)
-        lxcClose_ns(nsInheritFDs);
     return pid;
 }
 
diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h
index f585a35..33eaab4 100644
--- a/src/lxc/lxc_container.h
+++ b/src/lxc/lxc_container.h
@@ -25,6 +25,7 @@
 # define LXC_CONTAINER_H
 
 # include "lxc_conf.h"
+# include "lxc_domain.h"
 # include "security/security_manager.h"
 
 enum {
@@ -60,7 +61,7 @@ int lxcContainerStart(virDomainDefPtr def,
                       int *passFDs,
                       int control,
                       int handshakefd,
-                      int nsInheritFDs[VIR_DOMAIN_NAMESPACE_LAST],
+                      int *nsInheritFDs,
                       size_t nttyPaths,
                       char **ttyPaths);
 
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 3755ca0..19190dd 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -119,7 +119,7 @@ struct _virLXCController {
     size_t npassFDs;
     int *passFDs;
 
-    int nsFDs[VIR_DOMAIN_NAMESPACE_LAST];
+    int *nsFDs;
 
     size_t nconsoles;
     virLXCControllerConsolePtr consoles;
@@ -2403,6 +2403,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
     for (i = 0; i < ctrl->npassFDs; i++)
         VIR_FORCE_CLOSE(ctrl->passFDs[i]);
 
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++)
+        VIR_FORCE_CLOSE(ctrl->nsFDs[i]);
+
     if (virLXCControllerSetupCgroupLimits(ctrl) < 0)
         goto cleanup;
 
@@ -2471,7 +2474,7 @@ int main(int argc, char *argv[])
     const char *name = NULL;
     size_t nveths = 0;
     char **veths = NULL;
-    int ns_fd[VIR_DOMAIN_NAMESPACE_LAST];
+    int ns_fd[VIR_LXC_DOMAIN_NAMESPACE_LAST];
     int handshakeFd = -1;
     bool bg = false;
     const struct option options[] = {
@@ -2496,7 +2499,7 @@ int main(int argc, char *argv[])
     size_t i;
     const char *securityDriver = "none";
 
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++)
         ns_fd[i] = -1;
 
     if (setlocale(LC_ALL, "") == NULL ||
@@ -2563,7 +2566,7 @@ int main(int argc, char *argv[])
             break;
 
         case 'N':
-            if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_DOMAIN_NAMESPACE_SHARENET]) < 0) {
+            if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHARENET]) < 0) {
                 fprintf(stderr, "malformed --share-net argument '%s'",
                         optarg);
                 goto cleanup;
@@ -2571,7 +2574,7 @@ int main(int argc, char *argv[])
             break;
 
         case 'I':
-            if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_DOMAIN_NAMESPACE_SHAREIPC]) < 0) {
+            if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC]) < 0) {
                 fprintf(stderr, "malformed --share-ipc argument '%s'",
                         optarg);
                 goto cleanup;
@@ -2579,7 +2582,7 @@ int main(int argc, char *argv[])
             break;
 
         case 'U':
-            if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_DOMAIN_NAMESPACE_SHAREUTS]) < 0) {
+            if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHAREUTS]) < 0) {
                 fprintf(stderr, "malformed --share-uts argument '%s'",
                         optarg);
                 goto cleanup;
@@ -2658,7 +2661,7 @@ int main(int argc, char *argv[])
     ctrl->passFDs = passFDs;
     ctrl->npassFDs = npassFDs;
 
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++)
         ctrl->nsFDs[i] = ns_fd[i];
 
     for (i = 0; i < nttyFDs; i++) {
diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c
index ca9da7b..e3da9f0 100644
--- a/src/lxc/lxc_domain.c
+++ b/src/lxc/lxc_domain.c
@@ -26,7 +26,6 @@
 #include "viralloc.h"
 #include "virlog.h"
 #include "virerror.h"
-#include <fcntl.h>
 #include <libxml/xpathInternals.h>
 #include "virstring.h"
 #include "virutil.h"
@@ -47,21 +46,26 @@ static void *virLXCDomainObjPrivateAlloc(void)
     return priv;
 }
 
-VIR_ENUM_DECL(virDomainNamespace)
-VIR_ENUM_IMPL(virDomainNamespace, VIR_DOMAIN_NAMESPACE_LAST,
-    N_("sharenet"),
-    N_("shareipc"),
-    N_("shareuts"))
+VIR_ENUM_IMPL(virLXCDomainNamespace,
+              VIR_LXC_DOMAIN_NAMESPACE_LAST,
+              "sharenet",
+              "shareipc",
+              "shareuts")
+
+VIR_ENUM_IMPL(virLXCDomainNamespaceSource,
+              VIR_LXC_DOMAIN_NAMESPACE_SOURCE_LAST,
+              "none",
+              "name",
+              "pid",
+              "netns")
 
 static void
 lxcDomainDefNamespaceFree(void *nsdata)
 {
-    int j;
+    size_t i;
     lxcDomainDefPtr lxcDef = nsdata;
-    for (j = 0; j < VIR_DOMAIN_NAMESPACE_LAST; j++) {
-       VIR_FREE(lxcDef->ns_type[j]);
-       VIR_FREE(lxcDef->ns_val[j]);
-    }
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++)
+        VIR_FREE(lxcDef->ns_val[i]);
     VIR_FREE(nsdata);
 }
 
@@ -89,11 +93,6 @@ lxcDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
 
     if (VIR_ALLOC(lxcDef) < 0)
         return -1;
-    /* Init ns_herit_fd for namespaces */
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
-        lxcDef->ns_type[i] = NULL;
-        lxcDef->ns_val[i] = NULL;
-    }
 
     node = ctxt->node;
     if ((n = virXPathNodeSet("./lxc:namespace/*", ctxt, &nodes)) < 0)
@@ -101,9 +100,8 @@ lxcDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
     uses_lxc_ns |= n > 0;
 
     for (i = 0; i < n; i++) {
-        feature =
-            virDomainNamespaceTypeFromString((const char *) nodes[i]->name);
-        if (feature < 0) {
+        if ((feature = virLXCDomainNamespaceTypeFromString(
+                 (const char *) nodes[i]->name)) < 0) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                             _("unsupported Namespace feature: %s"),
                             nodes[i]->name);
@@ -112,30 +110,26 @@ lxcDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED,
 
         ctxt->node = nodes[i];
 
-        switch ((virDomainNamespace) feature) {
-        case VIR_DOMAIN_NAMESPACE_SHARENET:
-        case VIR_DOMAIN_NAMESPACE_SHAREIPC:
-        case VIR_DOMAIN_NAMESPACE_SHAREUTS:
-            {
-                tmp = virXMLPropString(nodes[i], "type");
-                if (tmp == NULL) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("No lxc environment type specified"));
-                    goto error;
-                }
-                /* save the tmp so that its needed while writing to xml */
-                lxcDef->ns_type[feature] = tmp;
-                tmp = virXMLPropString(nodes[i], "value");
-                if (tmp == NULL) {
-                    virReportError(VIR_ERR_INTERNAL_ERROR,
-                                   "%s", _("No lxc environment type specified"));
-                    goto error;
-                }
-                lxcDef->ns_val[feature] = tmp;
-            }
-            break;
-        case VIR_DOMAIN_NAMESPACE_LAST:
-            break;
+        if (!(tmp = virXMLPropString(nodes[i], "type"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("No lxc environment type specified"));
+            goto error;
+        }
+        if ((lxcDef->ns_source[feature] =
+             virLXCDomainNamespaceSourceTypeFromString(tmp)) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unknown LXC namespace source '%s'"),
+                           tmp);
+            VIR_FREE(tmp);
+            goto error;
+        }
+        VIR_FREE(tmp);
+
+        if (!(lxcDef->ns_val[feature] =
+              virXMLPropString(nodes[i], "value"))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("No lxc environment type specified"));
+            goto error;
         }
     }
     VIR_FREE(nodes);
@@ -157,7 +151,7 @@ lxcDomainDefNamespaceFormatXML(virBufferPtr buf,
                                void *nsdata)
 {
     lxcDomainDefPtr lxcDef = nsdata;
-    size_t j;
+    size_t i;
 
     if (!lxcDef)
        return 0;
@@ -165,23 +159,15 @@ lxcDomainDefNamespaceFormatXML(virBufferPtr buf,
     virBufferAddLit(buf, "<lxc:namespace>\n");
     virBufferAdjustIndent(buf, 2);
 
-    for (j = 0; j < VIR_DOMAIN_NAMESPACE_LAST; j++) {
-        switch ((virDomainNamespace) j) {
-        case VIR_DOMAIN_NAMESPACE_SHAREIPC:
-        case VIR_DOMAIN_NAMESPACE_SHAREUTS:
-        case VIR_DOMAIN_NAMESPACE_SHARENET:
-            {
-                if (lxcDef->ns_type[j]) {
-                    virBufferAsprintf(buf, "<lxc:%s type='%s' value='%s'/>\n",
-                                      virDomainNamespaceTypeToString(j),
-                                      lxcDef->ns_type[j],
-                                      lxcDef->ns_val[j]);
-                }
-            }
-            break;
-        case VIR_DOMAIN_NAMESPACE_LAST:
-            break;
-        }
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) {
+        if (lxcDef->ns_source[i] == VIR_LXC_DOMAIN_NAMESPACE_SOURCE_NONE)
+            continue;
+
+        virBufferAsprintf(buf, "<lxc:%s type='%s' value='%s'/>\n",
+                          virLXCDomainNamespaceTypeToString(i),
+                          virLXCDomainNamespaceSourceTypeToString(
+                              lxcDef->ns_source[i]),
+                          lxcDef->ns_val[i]);
     }
 
     virBufferAdjustIndent(buf, -2);
@@ -241,6 +227,7 @@ virLXCDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
     } else {
         priv->initpid = thepid;
     }
+
     return 0;
 }
 
diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h
index 25df999..2119c78 100644
--- a/src/lxc/lxc_domain.h
+++ b/src/lxc/lxc_domain.h
@@ -27,6 +27,31 @@
 # include "lxc_conf.h"
 # include "lxc_monitor.h"
 
+typedef enum {
+    VIR_LXC_DOMAIN_NAMESPACE_SHARENET = 0,
+    VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC,
+    VIR_LXC_DOMAIN_NAMESPACE_SHAREUTS,
+    VIR_LXC_DOMAIN_NAMESPACE_LAST,
+} virLXCDomainNamespace;
+
+typedef enum {
+    VIR_LXC_DOMAIN_NAMESPACE_SOURCE_NONE,
+    VIR_LXC_DOMAIN_NAMESPACE_SOURCE_NAME,
+    VIR_LXC_DOMAIN_NAMESPACE_SOURCE_PID,
+    VIR_LXC_DOMAIN_NAMESPACE_SOURCE_NETNS,
+
+    VIR_LXC_DOMAIN_NAMESPACE_SOURCE_LAST,
+} virLXCDomainNamespaceSource;
+
+VIR_ENUM_DECL(virLXCDomainNamespace)
+VIR_ENUM_DECL(virLXCDomainNamespaceSource)
+
+typedef struct _lxcDomainDef lxcDomainDef;
+typedef lxcDomainDef *lxcDomainDefPtr;
+struct _lxcDomainDef {
+    int ns_source[VIR_LXC_DOMAIN_NAMESPACE_LAST]; /* virLXCDomainNamespaceSource */
+    char *ns_val[VIR_LXC_DOMAIN_NAMESPACE_LAST];
+};
 
 typedef struct _virLXCDomainObjPrivate virLXCDomainObjPrivate;
 typedef virLXCDomainObjPrivate *virLXCDomainObjPrivatePtr;
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index ead7f67..9699377 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -359,7 +359,91 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn,
     return ret;
 }
 
-static const char *nsInfoLocal[] = { "net", "ipc", "uts" };
+static const char *nsInfoLocal[VIR_LXC_DOMAIN_NAMESPACE_LAST] = {
+    [VIR_LXC_DOMAIN_NAMESPACE_SHARENET] = "net",
+    [VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC] = "ipc",
+    [VIR_LXC_DOMAIN_NAMESPACE_SHAREUTS] = "uts",
+};
+
+static int virLXCProcessSetupNamespaceName(virConnectPtr conn, int ns_type, const char *name)
+{
+    virLXCDriverPtr driver = conn->privateData;
+    int fd = -1;
+    virDomainObjPtr vm;
+    char *path;
+
+    vm = virDomainObjListFindByName(driver->domains, name);
+    if (!vm) {
+        virReportError(VIR_ERR_NO_DOMAIN,
+                       _("No domain with matching name '%s'"), name);
+        return -1;
+    }
+
+    if (virAsprintf(&path, "/proc/%lld/ns/%s",
+                    (long long int)vm->pid,
+                    nsInfoLocal[ns_type]) < 0)
+        goto cleanup;
+
+    if ((fd = open(path, O_RDONLY)) < 0) {
+        virReportSystemError(errno,
+                             _("failed to open ns %s"),
+                             virLXCDomainNamespaceTypeToString(ns_type));
+        goto cleanup;
+    }
+
+ cleanup:
+    VIR_FREE(path);
+    virObjectUnlock(vm);
+    virObjectUnref(vm);
+    return fd;
+}
+
+
+static int virLXCProcessSetupNamespacePID(int ns_type, const char *name)
+{
+    int fd;
+    char *path;
+
+    if (virAsprintf(&path, "/proc/%s/ns/%s",
+                    name,
+                    nsInfoLocal[ns_type]) < 0)
+        return -1;
+    fd = open(path, O_RDONLY);
+    VIR_FREE(path);
+    if (fd < 0) {
+        virReportSystemError(errno,
+                             _("failed to open ns %s"),
+                             virLXCDomainNamespaceTypeToString(ns_type));
+        return -1;
+    }
+    return fd;
+}
+
+
+static int virLXCProcessSetupNamespaceNet(int ns_type, const char *name)
+{
+    char *path;
+    int fd;
+    if (ns_type != VIR_LXC_DOMAIN_NAMESPACE_SHARENET) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s"
+                       _("'netns' namespace source can only be "
+                         "used with sharenet"));
+        return -1;
+    }
+
+    if (virAsprintf(&path, "/var/run/netns/%s", name) < 0)
+        return  -1;
+    fd = open(path, O_RDONLY);
+    VIR_FREE(path);
+    if (fd < 0) {
+        virReportSystemError(errno,
+                             _("failed to open netns %s"), name);
+        return -1;
+    }
+    return fd;
+}
+
+
 /**
  * virLXCProcessSetupNamespaces:
  * @conn: pointer to connection
@@ -373,82 +457,36 @@ static const char *nsInfoLocal[] = { "net", "ipc", "uts" };
  */
 static int virLXCProcessSetupNamespaces(virConnectPtr conn,
                                         lxcDomainDefPtr lxcDef,
-                                        int nsFDs[VIR_DOMAIN_NAMESPACE_LAST])
+                                        int *nsFDs)
 {
-    int i, n, rc = 0;
-    virDomainPtr dom = NULL;
-    pid_t pid;
-    int nfdlist;
-    int *fdlist;
-    char *path = NULL;
-    char *eptr;
+    size_t i;
 
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++)
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++)
         nsFDs[i] = -1;
     /*If there are no namespace to be opened just return success*/
-    if (lxcDef == NULL) return 0;
-
-    if (STREQ_NULLABLE("netns", lxcDef->ns_type[VIR_DOMAIN_NAMESPACE_SHARENET])) {
-        if (virAsprintf(&path, "/var/run/netns/%s", lxcDef->ns_val[VIR_DOMAIN_NAMESPACE_SHARENET]) < 0)
-            return  -1;
-        nsFDs[VIR_DOMAIN_NAMESPACE_SHARENET] = open(path, O_RDONLY);
-        VIR_FREE(path);
-        if (nsFDs[VIR_DOMAIN_NAMESPACE_SHARENET] < 0) {
-            virReportSystemError(errno,
-                      _("failed to open netns %s"), lxcDef->ns_val[VIR_DOMAIN_NAMESPACE_SHARENET]);
-            return -1;
-        }
-    }
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
-        /* If not yet intialized by above: netns*/
-        if (lxcDef->ns_type[i] && nsFDs[i] == -1) {
-            pid = strtol(lxcDef->ns_val[i], &eptr, 10);
-            if (*eptr != '\0' || pid < 1) {
-                /* check if the domain is running, then set the namespaces
-                 * to that container
-                 */
-                const char *ns[] = { "user", "ipc", "uts", "net", "pid", "mnt" };
-                dom = virDomainLookupByName(conn, lxcDef->ns_val[i]);
-                if (!dom) {
-                    virReportError(virGetLastError()->code,
-                                   _("Unable to lookup peer container %s"),
-                                   lxcDef->ns_val[i]);
-                    rc = -1;
-                    goto cleanup;
-                }
-                if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0) {
-                    virReportError(virGetLastError()->code,
-                                   _("Unable to open %s"), lxcDef->ns_val[i]);
-                    rc = -1;
-                    goto cleanup;
-                }
-                for (n = 0; n < ARRAY_CARDINALITY(ns); n++) {
-                    if (STREQ(ns[n], nsInfoLocal[i])) {
-                        nsFDs[i] = fdlist[n];
-                    } else {
-                        if (VIR_CLOSE(fdlist[n]) < 0)
-                           VIR_ERROR(_("failed to close fd. ignoring.."));
-                    }
-                }
-                if (nfdlist > 0)
-                    VIR_FREE(fdlist);
-            } else {
-                if (virAsprintf(&path, "/proc/%d/ns/%s", pid, nsInfoLocal[i]) < 0)
-                    return -1;
-                nsFDs[i] = open(path, O_RDONLY);
-                VIR_FREE(path);
-                if (nsFDs[i] < 0) {
-                    virReportSystemError(errno,
-                      _("failed to open ns %s"), lxcDef->ns_val[i]);
-                    return -1;
-                }
-            }
+    if (lxcDef == NULL)
+        return 0;
+
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) {
+        switch (lxcDef->ns_source[i]) {
+        case VIR_LXC_DOMAIN_NAMESPACE_SOURCE_NONE:
+            continue;
+        case VIR_LXC_DOMAIN_NAMESPACE_SOURCE_NAME:
+            if ((nsFDs[i] = virLXCProcessSetupNamespaceName(conn, i, lxcDef->ns_val[i])) < 0)
+                return -1;
+            break;
+        case VIR_LXC_DOMAIN_NAMESPACE_SOURCE_PID:
+            if ((nsFDs[i] = virLXCProcessSetupNamespacePID(i, lxcDef->ns_val[i])) < 0)
+                return -1;
+            break;
+        case VIR_LXC_DOMAIN_NAMESPACE_SOURCE_NETNS:
+            if ((nsFDs[i] = virLXCProcessSetupNamespaceNet(i, lxcDef->ns_val[i])) < 0)
+                return -1;
+            break;
         }
     }
- cleanup:
-    if (dom)
-        virDomainFree(dom);
-    return rc;
+
+    return 0;
 }
 
 /**
@@ -855,7 +893,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
                                 char **veths,
                                 int *ttyFDs,
                                 size_t nttyFDs,
-                                int nsInheritFDs[VIR_DOMAIN_NAMESPACE_LAST],
+                                int *nsInheritFDs,
                                 int *files,
                                 size_t nfiles,
                                 int handshakefd,
@@ -917,7 +955,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
         virCommandPassFD(cmd, files[i], 0);
     }
 
-    for (i = 0; i < VIR_DOMAIN_NAMESPACE_LAST; i++) {
+    for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) {
         if (nsInheritFDs[i] > 0) {
             char *tmp = NULL;
             if (virAsprintf(&tmp, "--share-%s",
@@ -1137,7 +1175,7 @@ int virLXCProcessStart(virConnectPtr conn,
     off_t pos = -1;
     char ebuf[1024];
     char *timestamp;
-    int nsInheritFDs[VIR_DOMAIN_NAMESPACE_LAST];
+    int nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_LAST];
     virCommandPtr cmd = NULL;
     virLXCDomainObjPrivatePtr priv = vm->privateData;
     virCapsPtr caps = NULL;
-- 
2.4.3



Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|




More information about the libvir-list mailing list