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.
Co-authored: Daniel P. Berrange <berrange@redhat.com>
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>
<optional>
<ref name='qemucmdline'/>
</optional>
+ <optional>
+ <ref name='lxcsharens'/>
+ </optional>
<optional>
<ref name='keywrap'/>
</optional>
</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>
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
-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)
{
return virDomainXMLOptionNew(&virLXCDriverDomainDefParserConfig,
&virLXCDriverPrivateDataCallbacks,
- NULL);
+ &virLXCDriverDomainXMLNamespace);
}
#include <config.h>
#include <fcntl.h>
+#include <sched.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <mntent.h>
#include <sys/reboot.h>
#include <linux/reboot.h>
-
/* Yes, we want linux private one, for _syscall2() macro */
#include <linux/unistd.h>
size_t nttyPaths;
char **ttyPaths;
int handshakefd;
+ int *nsInheritFDs;
};
static int lxcContainerMountFSBlock(virDomainFSDefPtr fs,
#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
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
*/
int *passFDs,
int control,
int handshakefd,
+ int *nsInheritFDs,
size_t nttyPaths,
char **ttyPaths)
{
.monitor = control,
.nttyPaths = nttyPaths,
.ttyPaths = ttyPaths,
- .handshakefd = handshakefd
+ .handshakefd = handshakefd,
+ .nsInheritFDs = nsInheritFDs,
};
/* allocate a stack for the container */
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()) {
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 (!nsInheritFDs || nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHAREIPC] == -1) {
+ cflags |= CLONE_NEWIPC;
+ } else {
+ VIR_DEBUG("Inheriting an IPC namespace");
+ }
- if (lxcNeedNetworkNamespace(def)) {
- VIR_DEBUG("Enable network namespaces");
- cflags |= CLONE_NEWNET;
+ 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");
# define LXC_CONTAINER_H
# include "lxc_conf.h"
+# include "lxc_domain.h"
# include "security/security_manager.h"
enum {
int *passFDs,
int control,
int handshakefd,
+ int *nsInheritFDs,
size_t nttyPaths,
char **ttyPaths);
size_t npassFDs;
int *passFDs;
+ int *nsFDs;
+
size_t nconsoles;
virLXCControllerConsolePtr consoles;
char *devptmx;
VIR_FREE(ctrl->nbdpids);
+ VIR_FREE(ctrl->nsFDs);
virCgroupFree(&ctrl->cgroup);
/* This must always be the last thing to be closed */
ctrl->passFDs,
control[1],
containerhandshake[1],
+ ctrl->nsFDs,
ctrl->nconsoles,
containerTTYPaths)) < 0)
goto cleanup;
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;
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[] = {
{ "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 },
};
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 ||
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)
}
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;
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;
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;
#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");
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;
# 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;
virCgroupPtr cgroup;
};
+extern virDomainXMLNamespace virLXCDriverDomainXMLNamespace;
extern virDomainXMLPrivateDataCallbacks virLXCDriverPrivateDataCallbacks;
extern virDomainDefParserConfig virLXCDriverDomainDefParserConfig;
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:
char **veths,
int *ttyFDs,
size_t nttyFDs,
+ int *nsInheritFDs,
int *files,
size_t nfiles,
int handshakefd,
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));
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;
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) {
vm,
nveths, veths,
ttyFDs, nttyFDs,
+ nsInheritFDs,
files, nfiles,
handshakefds[1],
&logfd,
--- /dev/null
+<domain type='lxc' xmlns:lxc='http://libvirt.org/schemas/domain/lxc/1.0'>
+ <name>jessie</name>
+ <uuid>e21987a5-e98e-9c99-0e35-803e4d9ad1fe</uuid>
+ <memory unit='KiB'>1048576</memory>
+ <currentMemory unit='KiB'>1048576</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <resource>
+ <partition>/machine</partition>
+ </resource>
+ <os>
+ <type arch='x86_64'>exe</type>
+ <init>/sbin/init</init>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/libexec/libvirt_lxc</emulator>
+ <filesystem type='mount' accessmode='passthrough'>
+ <source dir='/mach/jessie'/>
+ <target dir='/'/>
+ </filesystem>
+ <console type='pty'>
+ <target type='lxc' port='0'/>
+ </console>
+ </devices>
+ <lxc:namespace>
+ <lxc:sharenet type='netns' value='red'/>
+ <lxc:shareipc type='pid' value='12345'/>
+ <lxc:shareuts type='name' value='container1'/>
+ </lxc:namespace>
+</domain>
DO_TEST("filesystem-root");
DO_TEST("idmap");
DO_TEST("capabilities");
+ DO_TEST("sharenet");
virObjectUnref(caps);
virObjectUnref(xmlopt);