diff --git a/docs/drvlxc.html.in b/docs/drvlxc.html.in index a094bd9256..d6c57c4fb1 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.

+

Inherit namespaces

+ +

+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. +

+
+<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>
+
+

Container usage / management

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 337c985909..ccc74cceac 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -67,6 +67,9 @@ + + + @@ -5057,6 +5060,45 @@ + + + + + + + + netns + name + pid + + + + + + + + name + pid + + + + + + + + name + pid + + + + + + + + diff --git a/po/POTFILES.in b/po/POTFILES.in index 1e52e6af02..46220f714d 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 9667292607..57a06e88ea 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1320,7 +1320,12 @@ 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 b689b92d95..8ada5311de 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 11e9514e07..8011ed065d 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include - /* Yes, we want linux private one, for _syscall2() macro */ #include @@ -111,6 +111,7 @@ struct __lxc_child_argv { size_t nttyPaths; char **ttyPaths; int handshakefd; + int *nsInheritFDs; }; static int lxcContainerMountFSBlock(virDomainFSDefPtr fs, @@ -2143,6 +2144,35 @@ static int lxcContainerDropCapabilities(virDomainDefPtr def ATTRIBUTE_UNUSED, #endif +/** + * lxcAttach_ns: + * @ns_fd: array of namespaces to attach + */ +static int lxcAttachNS(int *ns_fd) +{ + size_t i; + if (ns_fd) + 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 || 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 || nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC] == -1) { + cflags |= CLONE_NEWIPC; + } else { + VIR_DEBUG("Inheriting an IPC namespace"); + } + + if (!nsInheritFDs || 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 67292ab2ab..33eaab49c4 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 48a3597ed2..a94e819e87 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; @@ -287,6 +289,7 @@ static void virLXCControllerFree(virLXCControllerPtr ctrl) VIR_FREE(ctrl->nbdpids); + VIR_FREE(ctrl->nsFDs); virCgroupFree(&ctrl->cgroup); /* This must always be the last thing to be closed */ @@ -2391,6 +2394,7 @@ virLXCControllerRun(virLXCControllerPtr ctrl) ctrl->passFDs, control[1], containerhandshake[1], + ctrl->nsFDs, ctrl->nconsoles, containerTTYPaths)) < 0) goto cleanup; @@ -2400,6 +2404,10 @@ virLXCControllerRun(virLXCControllerPtr ctrl) for (i = 0; i < ctrl->npassFDs; i++) VIR_FORCE_CLOSE(ctrl->passFDs[i]); + if (ctrl->nsFDs) + for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) + VIR_FORCE_CLOSE(ctrl->nsFDs[i]); + if (virLXCControllerSetupCgroupLimits(ctrl) < 0) goto cleanup; @@ -2468,6 +2476,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 +2487,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 +2501,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 +2519,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 +2567,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 +2608,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 +2663,19 @@ int main(int argc, char *argv[]) ctrl->passFDs = passFDs; ctrl->npassFDs = npassFDs; + for (i = 0; i < VIR_LXC_DOMAIN_NAMESPACE_LAST; i++) { + if (ns_fd[i] != -1) { + if (!ctrl->nsFDs) {/*allocate only once */ + size_t j = 0; + if (VIR_ALLOC_N(ctrl->nsFDs, VIR_LXC_DOMAIN_NAMESPACE_LAST) < 0) + goto cleanup; + for (j = 0; j < VIR_LXC_DOMAIN_NAMESPACE_LAST; j++) + ctrl->nsFDs[j] = -1; + } + 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 2f377d8dcb..e3da9f0536 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 +#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, "\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, "\n", + virLXCDomainNamespaceTypeToString(i), + virLXCDomainNamespaceSourceTypeToString( + lxcDef->ns_source[i]), + lxcDef->ns_val[i]); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\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 751aecef8e..2119c78990 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 e99b039755..ade0ed7c0a 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -359,6 +359,143 @@ 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; + virLXCDomainObjPrivatePtr priv; + char *path; + + vm = virDomainObjListFindByName(driver->domains, name); + if (!vm) { + virReportError(VIR_ERR_NO_DOMAIN, + _("No domain with matching name '%s'"), name); + return -1; + } + + priv = vm->privateData; + if (!priv->initpid) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Init pid is not yet available")); + goto cleanup; + } + + if (virAsprintf(&path, "/proc/%lld/ns/%s", + (long long int)priv->initpid, + 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 +901,7 @@ virLXCProcessBuildControllerCmd(virLXCDriverPtr driver, char **veths, int *ttyFDs, size_t nttyFDs, + int *nsInheritFDs, int *files, size_t nfiles, int handshakefd, @@ -825,6 +963,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 +1183,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 +1356,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 +1379,7 @@ int virLXCProcessStart(virConnectPtr conn, vm, nveths, veths, ttyFDs, nttyFDs, + nsInheritFDs, files, nfiles, handshakefds[1], &logfd, diff --git a/tests/lxcxml2xmldata/lxc-sharenet.xml b/tests/lxcxml2xmldata/lxc-sharenet.xml new file mode 100644 index 0000000000..a2b8d1b949 --- /dev/null +++ b/tests/lxcxml2xmldata/lxc-sharenet.xml @@ -0,0 +1,33 @@ + + jessie + e21987a5-e98e-9c99-0e35-803e4d9ad1fe + 1048576 + 1048576 + 1 + + /machine + + + exe + /sbin/init + + + destroy + restart + restart + + /usr/libexec/libvirt_lxc + + + + + + + + + + + + + + diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c index 3e00347483..8d824b9bcf 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);