[libvirt] [PATCH v3] lxc: Inherit namespace feature

From: Imran Khan <ik.nitk@gmail.com> This patch adds feature for lxc containers to inherit namespaces. This is very similar to what lxc-tools or docker provides. Look for "man lxc-start" and you will find that you can pass command args as [ --share-[net|ipc|uts] name|pid ]. Or check out docker networking option in which you can give --net=container:NAME_or_ID as an option for sharing +namespace.
From this patch you can add extra libvirt option to share namespace in following way.
<lxc:namespace> <lxc:sharenet type='netns' value='red'/> <lxc:shareipc type='pid' value='12345'/> <lxc:shareuts type='name' value='container1'/> </lxc:namespace> The netns option is specific to sharenet. It can be used to inherit from existing network namespace. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- docs/drvlxc.html.in | 21 ++++++ docs/schemas/domaincommon.rng | 42 ++++++++++++ po/POTFILES.in | 1 + src/Makefile.am | 6 +- src/lxc/lxc_conf.c | 2 +- src/lxc/lxc_container.c | 71 ++++++++++++++++++-- src/lxc/lxc_container.h | 2 + src/lxc/lxc_controller.c | 45 ++++++++++++- src/lxc/lxc_domain.c | 149 ++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_domain.h | 26 ++++++++ src/lxc/lxc_process.c | 149 ++++++++++++++++++++++++++++++++++++++++++ tests/lxcxml2xmltest.c | 1 + 12 files changed, 506 insertions(+), 9 deletions(-) diff --git a/docs/drvlxc.html.in b/docs/drvlxc.html.in index a094bd9..d6c57c4 100644 --- a/docs/drvlxc.html.in +++ b/docs/drvlxc.html.in @@ -590,6 +590,27 @@ Note that allowing capabilities that are normally dropped by default can serious affect the security of the container and the host. </p> +<h2><a name="share">Inherit namespaces</a></h2> + +<p> +Libvirt allows you to inherit the namespace from container/process just like lxc tools +or docker provides to share the network namespace. The following can be used to share +required namespaces. If we want to share only one then the other namespaces can be ignored. +The netns option is specific to sharenet. It can be used in cases we want to use existing network namespace +rather than creating new network namespace for the container. In this case privnet option will be +ignored. +</p> +<pre> +<domain type='lxc' xmlns:lxc='http://libvirt.org/schemas/domain/lxc/1.0'> +... +<lxc:namespace> + <lxc:sharenet type='netns' value='red'/> + <lxc:shareuts type='name' value='container1'/> + <lxc:shareipc type='pid' value='12345'/> +</lxc:namespace> +</domain> +</pre> + <h2><a name="usage">Container usage / management</a></h2> <p> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 043c975..fa026cd 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -68,6 +68,9 @@ <ref name='qemucmdline'/> </optional> <optional> + <ref name='lxcsharens'/> + </optional> + <optional> <ref name='keywrap'/> </optional> </interleave> @@ -5057,6 +5060,45 @@ </element> </define> + <!-- + Optional hypervisor extensions in their own namespace: + LXC + --> + <define name="lxcsharens"> + <element name="namespace" ns="http://libvirt.org/schemas/domain/lxc/1.0"> + <zeroOrMore> + <element name="sharenet"> + <attribute name="type"> + <choice> + <value>netns</value> + <value>name</value> + <value>pid</value> + </choice> + </attribute> + <attribute name='value'/> + </element> + <element name="shareipc"> + <attribute name="type"> + <choice> + <value>name</value> + <value>pid</value> + </choice> + </attribute> + <attribute name='value'/> + </element> + <element name="shareuts"> + <attribute name="type"> + <choice> + <value>name</value> + <value>pid</value> + </choice> + </attribute> + <attribute name='value'/> + </element> + </zeroOrMore> + </element> + </define> + <define name="metadata"> <element name="metadata"> <zeroOrMore> 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 c4d49a5..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) $(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.c b/src/lxc/lxc_conf.c index b689b92..8ada531 100644 --- a/src/lxc/lxc_conf.c +++ b/src/lxc/lxc_conf.c @@ -213,7 +213,7 @@ lxcDomainXMLConfInit(void) { return virDomainXMLOptionNew(&virLXCDriverDomainDefParserConfig, &virLXCDriverPrivateDataCallbacks, - NULL); + &virLXCDriverDomainXMLNamespace); } diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 11e9514..d52f57e 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -27,6 +27,7 @@ #include <config.h> #include <fcntl.h> +#include <sched.h> #include <limits.h> #include <stdlib.h> #include <stdio.h> @@ -38,7 +39,6 @@ #include <mntent.h> #include <sys/reboot.h> #include <linux/reboot.h> - /* Yes, we want linux private one, for _syscall2() macro */ #include <linux/unistd.h> @@ -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 */ @@ -2342,6 +2378,7 @@ int lxcContainerStart(virDomainDefPtr def, int *passFDs, int control, int handshakefd, + int *nsInheritFDs, size_t nttyPaths, char **ttyPaths) { @@ -2359,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 */ @@ -2368,7 +2406,7 @@ int lxcContainerStart(virDomainDefPtr def, stacktop = stack + stacksize; - cflags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|SIGCHLD; + cflags = CLONE_NEWPID|CLONE_NEWNS|SIGCHLD; if (userns_required(def)) { if (userns_supported()) { @@ -2381,10 +2419,31 @@ int lxcContainerStart(virDomainDefPtr def, return -1; } } + 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 (lxcNeedNetworkNamespace(def)) { - VIR_DEBUG("Enable network namespaces"); - cflags |= CLONE_NEWNET; + if (nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC] == -1) { + cflags |= CLONE_NEWIPC; + } else { + VIR_DEBUG("Inheriting an IPC namespace"); + } + + if (nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHAREUTS] == -1) { + cflags |= CLONE_NEWUTS; + } else { + VIR_DEBUG("Inheriting a UTS namespace"); } VIR_DEBUG("Cloning container init process"); diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h index 67292ab..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,6 +61,7 @@ int lxcContainerStart(virDomainDefPtr def, int *passFDs, int control, int handshakefd, + int *nsInheritFDs, size_t nttyPaths, char **ttyPaths); diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 48a3597..19190dd 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -119,6 +119,8 @@ struct _virLXCController { size_t npassFDs; int *passFDs; + int *nsFDs; + size_t nconsoles; virLXCControllerConsolePtr consoles; char *devptmx; @@ -2391,6 +2393,7 @@ virLXCControllerRun(virLXCControllerPtr ctrl) ctrl->passFDs, control[1], containerhandshake[1], + ctrl->nsFDs, ctrl->nconsoles, containerTTYPaths)) < 0) goto cleanup; @@ -2400,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; @@ -2468,6 +2474,7 @@ int main(int argc, char *argv[]) const char *name = NULL; size_t nveths = 0; char **veths = NULL; + int ns_fd[VIR_LXC_DOMAIN_NAMESPACE_LAST]; int handshakeFd = -1; bool bg = false; const struct option options[] = { @@ -2478,6 +2485,9 @@ int main(int argc, char *argv[]) { "passfd", 1, NULL, 'p' }, { "handshakefd", 1, NULL, 's' }, { "security", 1, NULL, 'S' }, + { "share-net", 1, NULL, 'N' }, + { "share-ipc", 1, NULL, 'I' }, + { "share-uts", 1, NULL, 'U' }, { "help", 0, NULL, 'h' }, { 0, 0, 0, 0 }, }; @@ -2489,6 +2499,9 @@ int main(int argc, char *argv[]) size_t i; const char *securityDriver = "none"; + for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) + ns_fd[i] = -1; + if (setlocale(LC_ALL, "") == NULL || bindtextdomain(PACKAGE, LOCALEDIR) == NULL || textdomain(PACKAGE) == NULL || @@ -2504,7 +2517,7 @@ int main(int argc, char *argv[]) while (1) { int c; - c = getopt_long(argc, argv, "dn:v:p:m:c:s:h:S:", + c = getopt_long(argc, argv, "dn:v:p:m:c:s:h:S:N:I:U:", options, NULL); if (c == -1) @@ -2552,6 +2565,30 @@ int main(int argc, char *argv[]) } break; + case 'N': + if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHARENET]) < 0) { + fprintf(stderr, "malformed --share-net argument '%s'", + optarg); + goto cleanup; + } + break; + + case 'I': + if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC]) < 0) { + fprintf(stderr, "malformed --share-ipc argument '%s'", + optarg); + goto cleanup; + } + break; + + case 'U': + if (virStrToLong_i(optarg, NULL, 10, &ns_fd[VIR_LXC_DOMAIN_NAMESPACE_SHAREUTS]) < 0) { + fprintf(stderr, "malformed --share-uts argument '%s'", + optarg); + goto cleanup; + } + break; + case 'S': securityDriver = optarg; break; @@ -2569,6 +2606,9 @@ int main(int argc, char *argv[]) fprintf(stderr, " -v VETH, --veth VETH\n"); fprintf(stderr, " -s FD, --handshakefd FD\n"); fprintf(stderr, " -S NAME, --security NAME\n"); + fprintf(stderr, " -N FD, --share-net FD\n"); + fprintf(stderr, " -I FD, --share-ipc FD\n"); + fprintf(stderr, " -U FD, --share-uts FD\n"); fprintf(stderr, " -h, --help\n"); fprintf(stderr, "\n"); goto cleanup; @@ -2621,6 +2661,9 @@ int main(int argc, char *argv[]) ctrl->passFDs = passFDs; ctrl->npassFDs = npassFDs; + for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) + ctrl->nsFDs[i] = ns_fd[i]; + for (i = 0; i < nttyFDs; i++) { if (virLXCControllerAddConsole(ctrl, ttyFDs[i]) < 0) goto cleanup; diff --git a/src/lxc/lxc_domain.c b/src/lxc/lxc_domain.c index 2f377d8..e3da9f0 100644 --- a/src/lxc/lxc_domain.c +++ b/src/lxc/lxc_domain.c @@ -26,8 +26,13 @@ #include "viralloc.h" #include "virlog.h" #include "virerror.h" +#include <libxml/xpathInternals.h> +#include "virstring.h" +#include "virutil.h" +#include "virfile.h" #define VIR_FROM_THIS VIR_FROM_LXC +#define LXC_NAMESPACE_HREF "http://libvirt.org/schemas/domain/lxc/1.0" VIR_LOG_INIT("lxc.lxc_domain"); @@ -41,6 +46,150 @@ static void *virLXCDomainObjPrivateAlloc(void) return priv; } +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) +{ + size_t i; + lxcDomainDefPtr lxcDef = nsdata; + for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) + VIR_FREE(lxcDef->ns_val[i]); + VIR_FREE(nsdata); +} + +static int +lxcDomainDefNamespaceParse(xmlDocPtr xml ATTRIBUTE_UNUSED, + xmlNodePtr root ATTRIBUTE_UNUSED, + xmlXPathContextPtr ctxt, + void **data) +{ + lxcDomainDefPtr lxcDef = NULL; + xmlNodePtr *nodes = NULL; + bool uses_lxc_ns = false; + xmlNodePtr node; + int feature; + int n; + char *tmp = NULL; + size_t i; + + if (xmlXPathRegisterNs(ctxt, BAD_CAST "lxc", BAD_CAST LXC_NAMESPACE_HREF) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to register xml namespace '%s'"), + LXC_NAMESPACE_HREF); + return -1; + } + + if (VIR_ALLOC(lxcDef) < 0) + return -1; + + node = ctxt->node; + if ((n = virXPathNodeSet("./lxc:namespace/*", ctxt, &nodes)) < 0) + goto error; + uses_lxc_ns |= n > 0; + + for (i = 0; i < n; i++) { + if ((feature = virLXCDomainNamespaceTypeFromString( + (const char *) nodes[i]->name)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported Namespace feature: %s"), + nodes[i]->name); + goto error; + } + + ctxt->node = nodes[i]; + + 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); + ctxt->node = node; + if (uses_lxc_ns) + *data = lxcDef; + else + VIR_FREE(lxcDef); + return 0; + error: + VIR_FREE(nodes); + lxcDomainDefNamespaceFree(lxcDef); + return -1; +} + + +static int +lxcDomainDefNamespaceFormatXML(virBufferPtr buf, + void *nsdata) +{ + lxcDomainDefPtr lxcDef = nsdata; + size_t i; + + if (!lxcDef) + return 0; + + virBufferAddLit(buf, "<lxc:namespace>\n"); + virBufferAdjustIndent(buf, 2); + + 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); + virBufferAddLit(buf, "</lxc:namespace>\n"); + return 0; +} + +static const char * +lxcDomainDefNamespaceHref(void) +{ + return "xmlns:lxc='" LXC_NAMESPACE_HREF "'"; +} + + +virDomainXMLNamespace virLXCDriverDomainXMLNamespace = { + .parse = lxcDomainDefNamespaceParse, + .free = lxcDomainDefNamespaceFree, + .format = lxcDomainDefNamespaceFormatXML, + .href = lxcDomainDefNamespaceHref, +}; + + static void virLXCDomainObjPrivateFree(void *data) { virLXCDomainObjPrivatePtr priv = data; diff --git a/src/lxc/lxc_domain.h b/src/lxc/lxc_domain.h index 751aece..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; @@ -41,6 +66,7 @@ struct _virLXCDomainObjPrivate { virCgroupPtr cgroup; }; +extern virDomainXMLNamespace virLXCDriverDomainXMLNamespace; extern virDomainXMLPrivateDataCallbacks virLXCDriverPrivateDataCallbacks; extern virDomainDefParserConfig virLXCDriverDomainDefParserConfig; diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index e99b039..9699377 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -359,6 +359,135 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, return ret; } +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 + * @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) +{ + size_t 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; + + 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; + } + } + + return 0; +} /** * virLXCProcessSetupInterfaces: @@ -764,6 +893,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, char **veths, int *ttyFDs, size_t nttyFDs, + int *nsInheritFDs, int *files, size_t nfiles, int handshakefd, @@ -825,6 +955,19 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, virCommandPassFD(cmd, files[i], 0); } + for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) { + if (nsInheritFDs[i] > 0) { + char *tmp = NULL; + if (virAsprintf(&tmp, "--share-%s", + nsInfoLocal[i]) < 0) + goto cleanup; + virCommandAddArg(cmd, tmp); + virCommandAddArgFormat(cmd, "%d", nsInheritFDs[i]); + virCommandPassFD(cmd, nsInheritFDs[i], 0); + VIR_FREE(tmp); + } + } + virCommandAddArgPair(cmd, "--security", virSecurityManagerGetModel(driver->securityManager)); @@ -1032,6 +1175,7 @@ int virLXCProcessStart(virConnectPtr conn, off_t pos = -1; char ebuf[1024]; char *timestamp; + int nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_LAST]; virCommandPtr cmd = NULL; virLXCDomainObjPrivatePtr priv = vm->privateData; virCapsPtr caps = NULL; @@ -1204,6 +1348,10 @@ int virLXCProcessStart(virConnectPtr conn, if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) < 0) goto cleanup; + VIR_DEBUG("Setting up namespaces if any"); + if (virLXCProcessSetupNamespaces(conn, vm->def->namespaceData, nsInheritFDs) < 0) + goto cleanup; + VIR_DEBUG("Preparing to launch"); if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR|S_IWUSR)) < 0) { @@ -1223,6 +1371,7 @@ int virLXCProcessStart(virConnectPtr conn, vm, nveths, veths, ttyFDs, nttyFDs, + nsInheritFDs, files, nfiles, handshakefds[1], &logfd, diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c index 3e00347..8d824b9 100644 --- a/tests/lxcxml2xmltest.c +++ b/tests/lxcxml2xmltest.c @@ -133,6 +133,7 @@ mymain(void) DO_TEST("filesystem-root"); DO_TEST("idmap"); DO_TEST("capabilities"); + DO_TEST("sharenet"); virObjectUnref(caps); virObjectUnref(xmlopt); -- 2.4.3

On 14.08.2015 14:09, Daniel P. Berrange wrote:
From: Imran Khan <ik.nitk@gmail.com>
This patch adds feature for lxc containers to inherit namespaces. This is very similar to what lxc-tools or docker provides. Look for "man lxc-start" and you will find that you can pass command args as [ --share-[net|ipc|uts] name|pid ]. Or check out docker networking option in which you can give --net=container:NAME_or_ID as an option for sharing +namespace.
From this patch you can add extra libvirt option to share
s/>//
namespace in following way.
<lxc:namespace> <lxc:sharenet type='netns' value='red'/> <lxc:shareipc type='pid' value='12345'/> <lxc:shareuts type='name' value='container1'/> </lxc:namespace>
The netns option is specific to sharenet. It can be used to inherit from existing network namespace.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- docs/drvlxc.html.in | 21 ++++++ docs/schemas/domaincommon.rng | 42 ++++++++++++ po/POTFILES.in | 1 + src/Makefile.am | 6 +- src/lxc/lxc_conf.c | 2 +- src/lxc/lxc_container.c | 71 ++++++++++++++++++-- src/lxc/lxc_container.h | 2 + src/lxc/lxc_controller.c | 45 ++++++++++++- src/lxc/lxc_domain.c | 149 ++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_domain.h | 26 ++++++++ src/lxc/lxc_process.c | 149 ++++++++++++++++++++++++++++++++++++++++++ tests/lxcxml2xmltest.c | 1 + 12 files changed, 506 insertions(+), 9 deletions(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index e99b039..9699377 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -359,6 +359,135 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, return ret; }
+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"
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; +} + +
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c index 3e00347..8d824b9 100644 --- a/tests/lxcxml2xmltest.c +++ b/tests/lxcxml2xmltest.c @@ -133,6 +133,7 @@ mymain(void) DO_TEST("filesystem-root"); DO_TEST("idmap"); DO_TEST("capabilities"); + DO_TEST("sharenet");
Have you forgot to git add tests/lxcxml2xmldata/lxc-sharenet.xml? I like the idea though. I'm tempted to ACK this if you fix all the small issues I've raised. Michal

Thanks to Daniel for making additional changes. And Thanks Michal for review it again. This patch has some functionality breakages. I am working on it. will send the new patch soon -imran On Thu, Aug 20, 2015 at 4:53 AM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 14.08.2015 14:09, Daniel P. Berrange wrote:
From: Imran Khan <ik.nitk@gmail.com>
This patch adds feature for lxc containers to inherit namespaces. This is very similar to what lxc-tools or docker provides. Look for "man lxc-start" and you will find that you can pass command args as [ --share-[net|ipc|uts] name|pid ]. Or check out docker networking option in which you can give --net=container:NAME_or_ID as an option for sharing +namespace.
From this patch you can add extra libvirt option to share
s/>//
namespace in following way.
<lxc:namespace> <lxc:sharenet type='netns' value='red'/> <lxc:shareipc type='pid' value='12345'/> <lxc:shareuts type='name' value='container1'/> </lxc:namespace>
The netns option is specific to sharenet. It can be used to inherit from existing network namespace.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- docs/drvlxc.html.in | 21 ++++++ docs/schemas/domaincommon.rng | 42 ++++++++++++ po/POTFILES.in | 1 + src/Makefile.am | 6 +- src/lxc/lxc_conf.c | 2 +- src/lxc/lxc_container.c | 71 ++++++++++++++++++-- src/lxc/lxc_container.h | 2 + src/lxc/lxc_controller.c | 45 ++++++++++++- src/lxc/lxc_domain.c | 149 ++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_domain.h | 26 ++++++++ src/lxc/lxc_process.c | 149 ++++++++++++++++++++++++++++++++++++++++++ tests/lxcxml2xmltest.c | 1 + 12 files changed, 506 insertions(+), 9 deletions(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index e99b039..9699377 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -359,6 +359,135 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, return ret; }
+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"
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; +} + +
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c index 3e00347..8d824b9 100644 --- a/tests/lxcxml2xmltest.c +++ b/tests/lxcxml2xmltest.c @@ -133,6 +133,7 @@ mymain(void) DO_TEST("filesystem-root"); DO_TEST("idmap"); DO_TEST("capabilities"); + DO_TEST("sharenet");
Have you forgot to git add tests/lxcxml2xmldata/lxc-sharenet.xml? I like the idea though. I'm tempted to ACK this if you fix all the small issues I've raised.
Michal

Have tested the code changes. here are the logs. Please review the patch sent in another mail. Really appreciate the efforts to make the code very efficient. test logs: imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// create ../lxc/cn-02.xml Domain cn02 created from ../lxc/cn-02.xml imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ cat ../lxc/share_lxc.xml | grep -A 3 -B 3 share <type>exe</type> </os> <lxc:namespace> <lxc:sharenet type='name' value='cn02'/> </lxc:namespace> <vcpu>1</vcpu> <clock offset='utc'/> imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// list Id Name State ---------------------------------------------------- 6828 cn02 running imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// create ../lxc/share_lxc.xml Domain cn-03 created from ../lxc/share_lxc.xml imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// list Id Name State ---------------------------------------------------- 6828 cn02 running 8774 cn-03 running imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn02 --noseclabel /sbin/ifconfig eth0 eth0 Link encap:Ethernet HWaddr 52:54:00:a7:e5:3d inet addr:192.168.122.183 Bcast:192.168.122.255 Mask:255.255.255.0 inet6 addr: fe80::5054:ff:fea7:e53d/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:105 errors:0 dropped:2 overruns:0 frame:0 TX packets:58 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:14169 (14.1 KB) TX bytes:32554 (32.5 KB) imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn-03 --noseclabel /sbin/ifconfig eth0 eth0 Link encap:Ethernet HWaddr 52:54:00:a7:e5:3d inet addr:192.168.122.183 Bcast:192.168.122.255 Mask:255.255.255.0 inet6 addr: fe80::5054:ff:fea7:e53d/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:114 errors:0 dropped:2 overruns:0 frame:0 TX packets:64 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:15289 (15.2 KB) TX bytes:40891 (40.8 KB) imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// destroy cn02 Domain cn02 destroyed imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn-03 --noseclabel /sbin/ifconfig eth0 eth0: error fetching interface information: Device not found error: internal error: Child process (10238) unexpected exit status 1 imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ip netns exec red ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:32 errors:0 dropped:0 overruns:0 frame:0 TX packets:32 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:2528 (2.5 KB) TX bytes:2528 (2.5 KB) imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// list Id Name State ---------------------------------------------------- 8774 cn-03 running imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// destroy cn-03 Domain cn-03 destroyed imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ cat ../lxc/share_lxc.xml | grep -A 3 -B 3 share <type>exe</type> </os> <lxc:namespace> <lxc:sharenet type='netns' value='red'/> </lxc:namespace> <vcpu>1</vcpu> <clock offset='utc'/> imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// create ../lxc/share_lxc.xml Domain cn-03 created from ../lxc/share_lxc.xml imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn-03 --noseclabel /sbin/ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:48 errors:0 dropped:0 overruns:0 frame:0 TX packets:48 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3792 (3.7 KB) TX bytes:3792 (3.7 KB) imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// destroy cn-03Domain cn-03 destroyed imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ip netns exec red ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:48 errors:0 dropped:0 overruns:0 frame:0 TX packets:48 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3792 (3.7 KB) TX bytes:3792 (3.7 KB) imran@imran-VirtualBox:~/programming/libvirt$ cat ../lxc/share_lxc.xml | grep -A 3 -B 3 share<type>exe</type> </os> <lxc:namespace> <lxc:sharenet type='pid' value='1'/> </lxc:namespace> <vcpu>1</vcpu> <clock offset='utc'/> imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// create ../lxc/share_lxc.xml Domain cn-03 created from ../lxc/share_lxc.xml imran@imran-VirtualBox:~/programming/libvirt$ ifconfig eth0 eth0 Link encap:Ethernet HWaddr 08:00:27:a8:fd:bf inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fea8:fdbf/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:178204 errors:13 dropped:0 overruns:0 frame:0 TX packets:88943 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:251962232 (251.9 MB) TX bytes:4930611 (4.9 MB) Interrupt:19 Base address:0xd020 imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn-03 --noseclabel /sbin/ifconfig eth0 eth0 Link encap:Ethernet HWaddr 08:00:27:a8:fd:bf inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fea8:fdbf/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:178204 errors:13 dropped:0 overruns:0 frame:0 TX packets:88943 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:251962232 (251.9 MB) TX bytes:4930611 (4.9 MB) Interrupt:19 Base address:0xd020 imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// destroy cn-03 Domain cn-03 destroyed imran@imran-VirtualBox:~/programming/libvirt$ ifconfig eth0 eth0 Link encap:Ethernet HWaddr 08:00:27:a8:fd:bf inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fea8:fdbf/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:178204 errors:13 dropped:0 overruns:0 frame:0 TX packets:88943 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:251962232 (251.9 MB) TX bytes:4930611 (4.9 MB) Interrupt:19 Base address:0xd020 imran@imran-VirtualBox:~/programming/libvirt$ On Thu, Aug 20, 2015 at 4:10 PM, Imran Khan <ik.nitk@gmail.com> wrote:
Thanks to Daniel for making additional changes. And Thanks Michal for review it again. This patch has some functionality breakages. I am working on it. will send the new patch soon
-imran
On Thu, Aug 20, 2015 at 4:53 AM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 14.08.2015 14:09, Daniel P. Berrange wrote:
From: Imran Khan <ik.nitk@gmail.com>
This patch adds feature for lxc containers to inherit namespaces. This is very similar to what lxc-tools or docker provides. Look for "man lxc-start" and you will find that you can pass command args as [ --share-[net|ipc|uts] name|pid ]. Or check out docker networking option in which you can give --net=container:NAME_or_ID as an option for sharing +namespace.
From this patch you can add extra libvirt option to share
s/>//
namespace in following way.
<lxc:namespace> <lxc:sharenet type='netns' value='red'/> <lxc:shareipc type='pid' value='12345'/> <lxc:shareuts type='name' value='container1'/> </lxc:namespace>
The netns option is specific to sharenet. It can be used to inherit from existing network namespace.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- docs/drvlxc.html.in | 21 ++++++ docs/schemas/domaincommon.rng | 42 ++++++++++++ po/POTFILES.in | 1 + src/Makefile.am | 6 +- src/lxc/lxc_conf.c | 2 +- src/lxc/lxc_container.c | 71 ++++++++++++++++++-- src/lxc/lxc_container.h | 2 + src/lxc/lxc_controller.c | 45 ++++++++++++- src/lxc/lxc_domain.c | 149 ++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_domain.h | 26 ++++++++ src/lxc/lxc_process.c | 149 ++++++++++++++++++++++++++++++++++++++++++ tests/lxcxml2xmltest.c | 1 + 12 files changed, 506 insertions(+), 9 deletions(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index e99b039..9699377 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -359,6 +359,135 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, return ret; }
+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"
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; +} + +
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c index 3e00347..8d824b9 100644 --- a/tests/lxcxml2xmltest.c +++ b/tests/lxcxml2xmltest.c @@ -133,6 +133,7 @@ mymain(void) DO_TEST("filesystem-root"); DO_TEST("idmap"); DO_TEST("capabilities"); + DO_TEST("sharenet");
Have you forgot to git add tests/lxcxml2xmldata/lxc-sharenet.xml? I like the idea though. I'm tempted to ACK this if you fix all the small issues I've raised.
Michal

Hello experts, Gentle reminder ! thanks a lot for all the help !! -imran On Thu, Aug 20, 2015 at 7:20 PM, Imran Khan <ik.nitk@gmail.com> wrote:
Have tested the code changes. here are the logs. Please review the patch sent in another mail.
Really appreciate the efforts to make the code very efficient.
test logs:
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// create ../lxc/cn-02.xml Domain cn02 created from ../lxc/cn-02.xml
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ cat ../lxc/share_lxc.xml | grep -A 3 -B 3 share <type>exe</type> </os> <lxc:namespace> <lxc:sharenet type='name' value='cn02'/> </lxc:namespace> <vcpu>1</vcpu> <clock offset='utc'/> imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// list Id Name State ---------------------------------------------------- 6828 cn02 running
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// create ../lxc/share_lxc.xml Domain cn-03 created from ../lxc/share_lxc.xml
imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// list Id Name State ---------------------------------------------------- 6828 cn02 running 8774 cn-03 running
imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn02 --noseclabel /sbin/ifconfig eth0 eth0 Link encap:Ethernet HWaddr 52:54:00:a7:e5:3d inet addr:192.168.122.183 Bcast:192.168.122.255 Mask:255.255.255.0 inet6 addr: fe80::5054:ff:fea7:e53d/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:105 errors:0 dropped:2 overruns:0 frame:0 TX packets:58 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:14169 (14.1 KB) TX bytes:32554 (32.5 KB)
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn-03 --noseclabel /sbin/ifconfig eth0 eth0 Link encap:Ethernet HWaddr 52:54:00:a7:e5:3d inet addr:192.168.122.183 Bcast:192.168.122.255 Mask:255.255.255.0 inet6 addr: fe80::5054:ff:fea7:e53d/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:114 errors:0 dropped:2 overruns:0 frame:0 TX packets:64 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:15289 (15.2 KB) TX bytes:40891 (40.8 KB)
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// destroy cn02 Domain cn02 destroyed
imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn-03 --noseclabel /sbin/ifconfig eth0 eth0: error fetching interface information: Device not found error: internal error: Child process (10238) unexpected exit status 1
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ip netns exec red ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:32 errors:0 dropped:0 overruns:0 frame:0 TX packets:32 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:2528 (2.5 KB) TX bytes:2528 (2.5 KB)
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// list Id Name State ---------------------------------------------------- 8774 cn-03 running
imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// destroy cn-03 Domain cn-03 destroyed
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ cat ../lxc/share_lxc.xml | grep -A 3 -B 3 share <type>exe</type> </os> <lxc:namespace> <lxc:sharenet type='netns' value='red'/> </lxc:namespace> <vcpu>1</vcpu> <clock offset='utc'/> imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// create ../lxc/share_lxc.xml Domain cn-03 created from ../lxc/share_lxc.xml
imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn-03 --noseclabel /sbin/ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:48 errors:0 dropped:0 overruns:0 frame:0 TX packets:48 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3792 (3.7 KB) TX bytes:3792 (3.7 KB)
imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// destroy cn-03Domain cn-03 destroyed
imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ imran@imran-VirtualBox:~/programming/libvirt$ sudo ip netns exec red ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:48 errors:0 dropped:0 overruns:0 frame:0 TX packets:48 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3792 (3.7 KB) TX bytes:3792 (3.7 KB)
imran@imran-VirtualBox:~/programming/libvirt$ cat ../lxc/share_lxc.xml | grep -A 3 -B 3 share<type>exe</type> </os> <lxc:namespace> <lxc:sharenet type='pid' value='1'/> </lxc:namespace> <vcpu>1</vcpu> <clock offset='utc'/> imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// create ../lxc/share_lxc.xml Domain cn-03 created from ../lxc/share_lxc.xml
imran@imran-VirtualBox:~/programming/libvirt$ ifconfig eth0 eth0 Link encap:Ethernet HWaddr 08:00:27:a8:fd:bf inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fea8:fdbf/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:178204 errors:13 dropped:0 overruns:0 frame:0 TX packets:88943 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:251962232 (251.9 MB) TX bytes:4930611 (4.9 MB) Interrupt:19 Base address:0xd020
imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// lxc-enter-namespace cn-03 --noseclabel /sbin/ifconfig eth0 eth0 Link encap:Ethernet HWaddr 08:00:27:a8:fd:bf inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fea8:fdbf/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:178204 errors:13 dropped:0 overruns:0 frame:0 TX packets:88943 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:251962232 (251.9 MB) TX bytes:4930611 (4.9 MB) Interrupt:19 Base address:0xd020
imran@imran-VirtualBox:~/programming/libvirt$ sudo ./run ./tools/virsh -c lxc:/// destroy cn-03 Domain cn-03 destroyed
imran@imran-VirtualBox:~/programming/libvirt$ ifconfig eth0 eth0 Link encap:Ethernet HWaddr 08:00:27:a8:fd:bf inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fea8:fdbf/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:178204 errors:13 dropped:0 overruns:0 frame:0 TX packets:88943 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:251962232 (251.9 MB) TX bytes:4930611 (4.9 MB) Interrupt:19 Base address:0xd020
imran@imran-VirtualBox:~/programming/libvirt$
On Thu, Aug 20, 2015 at 4:10 PM, Imran Khan <ik.nitk@gmail.com> wrote:
Thanks to Daniel for making additional changes. And Thanks Michal for review it again. This patch has some functionality breakages. I am working on it. will send the new patch soon
-imran
On Thu, Aug 20, 2015 at 4:53 AM, Michal Privoznik <mprivozn@redhat.com> wrote:
On 14.08.2015 14:09, Daniel P. Berrange wrote:
From: Imran Khan <ik.nitk@gmail.com>
This patch adds feature for lxc containers to inherit namespaces. This is very similar to what lxc-tools or docker provides. Look for "man lxc-start" and you will find that you can pass command args as [ --share-[net|ipc|uts] name|pid ]. Or check out docker networking option in which you can give --net=container:NAME_or_ID as an option for sharing +namespace.
From this patch you can add extra libvirt option to share
s/>//
namespace in following way.
<lxc:namespace> <lxc:sharenet type='netns' value='red'/> <lxc:shareipc type='pid' value='12345'/> <lxc:shareuts type='name' value='container1'/> </lxc:namespace>
The netns option is specific to sharenet. It can be used to inherit from existing network namespace.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- docs/drvlxc.html.in | 21 ++++++ docs/schemas/domaincommon.rng | 42 ++++++++++++ po/POTFILES.in | 1 + src/Makefile.am | 6 +- src/lxc/lxc_conf.c | 2 +- src/lxc/lxc_container.c | 71 ++++++++++++++++++-- src/lxc/lxc_container.h | 2 + src/lxc/lxc_controller.c | 45 ++++++++++++- src/lxc/lxc_domain.c | 149 ++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_domain.h | 26 ++++++++ src/lxc/lxc_process.c | 149 ++++++++++++++++++++++++++++++++++++++++++ tests/lxcxml2xmltest.c | 1 + 12 files changed, 506 insertions(+), 9 deletions(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index e99b039..9699377 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -359,6 +359,135 @@ char *virLXCProcessSetupInterfaceDirect(virConnectPtr conn, return ret; }
+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"
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; +} + +
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c index 3e00347..8d824b9 100644 --- a/tests/lxcxml2xmltest.c +++ b/tests/lxcxml2xmltest.c @@ -133,6 +133,7 @@ mymain(void) DO_TEST("filesystem-root"); DO_TEST("idmap"); DO_TEST("capabilities"); + DO_TEST("sharenet");
Have you forgot to git add tests/lxcxml2xmldata/lxc-sharenet.xml? I like the idea though. I'm tempted to ACK this if you fix all the small issues I've raised.
Michal

On 08/14/2015 08:09 AM, Daniel P. Berrange wrote:
From: Imran Khan <ik.nitk@gmail.com>
This patch adds feature for lxc containers to inherit namespaces. This is very similar to what lxc-tools or docker provides. Look for "man lxc-start" and you will find that you can pass command args as [ --share-[net|ipc|uts] name|pid ]. Or check out docker networking option in which you can give --net=container:NAME_or_ID as an option for sharing +namespace.
From this patch you can add extra libvirt option to share namespace in following way.
<lxc:namespace> <lxc:sharenet type='netns' value='red'/> <lxc:shareipc type='pid' value='12345'/> <lxc:shareuts type='name' value='container1'/> </lxc:namespace>
The netns option is specific to sharenet. It can be used to inherit from existing network namespace.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- docs/drvlxc.html.in | 21 ++++++ docs/schemas/domaincommon.rng | 42 ++++++++++++ po/POTFILES.in | 1 + src/Makefile.am | 6 +- src/lxc/lxc_conf.c | 2 +- src/lxc/lxc_container.c | 71 ++++++++++++++++++-- src/lxc/lxc_container.h | 2 + src/lxc/lxc_controller.c | 45 ++++++++++++- src/lxc/lxc_domain.c | 149 ++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_domain.h | 26 ++++++++ src/lxc/lxc_process.c | 149 ++++++++++++++++++++++++++++++++++++++++++ tests/lxcxml2xmltest.c | 1 + 12 files changed, 506 insertions(+), 9 deletions(-)
... Coverity found a resource leak...
@@ -2342,6 +2378,7 @@ int lxcContainerStart(virDomainDefPtr def, int *passFDs, int control, int handshakefd, + int *nsInheritFDs, size_t nttyPaths, char **ttyPaths) { @@ -2359,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 */ @@ -2368,7 +2406,7 @@ int lxcContainerStart(virDomainDefPtr def,
stacktop = stack + stacksize;
- cflags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|SIGCHLD; + cflags = CLONE_NEWPID|CLONE_NEWNS|SIGCHLD;
if (userns_required(def)) { if (userns_supported()) { @@ -2381,10 +2419,31 @@ int lxcContainerStart(virDomainDefPtr def, return -1; } } + 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;
This leaks 'stack'... Sending a patch shortly. John
+ } + VIR_DEBUG("Inheriting a net namespace"); + }
- if (lxcNeedNetworkNamespace(def)) { - VIR_DEBUG("Enable network namespaces"); - cflags |= CLONE_NEWNET; + if (nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC] == -1) { + cflags |= CLONE_NEWIPC; + } else { + VIR_DEBUG("Inheriting an IPC namespace"); + } + + if (nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHAREUTS] == -1) { + cflags |= CLONE_NEWUTS; + } else { + VIR_DEBUG("Inheriting a UTS namespace"); }
VIR_DEBUG("Cloning container init process");
participants (4)
-
Daniel P. Berrange
-
Imran Khan
-
John Ferlan
-
Michal Privoznik