From 442d6a0527311a2ad9b723b22fc7ec90c42f6bc6 Mon Sep 17 00:00:00 2001 From: Bogdan Purcareata Date: Fri, 5 Apr 2013 08:26:40 -0400 Subject: [PATCH] Implement support for This allows a container-type domain to have exclusive access to one of the host's NICs. Wire with the lxc_controller - when moving the newly created veth devices into a new namespace, also look for any hostdev devices that should be moved. Note: once the container domain has been destroyed, there is no code that moves the interfaces back to the original namespace. This does happen, though, probably due to default cleanup on namespace destruction. Signed-off-by: Bogdan Purcareata --- src/lxc/lxc_container.c | 23 ++++++++++++++++++++--- src/lxc/lxc_controller.c | 16 ++++++++++++++++ src/lxc/lxc_hostdev.c | 1 + tests/lxcxml2xmldata/lxc-hostdev.xml | 5 +++++ 4 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 002ba9e9d6..1e8a3db2d1 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -1551,7 +1551,6 @@ cleanup: return ret; } - static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef, virDomainHostdevDefPtr def, const char *dstprefix, @@ -1582,6 +1581,9 @@ static int lxcContainerSetupHostdevCaps(virDomainDefPtr vmDef, case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: return lxcContainerSetupHostdevCapsMisc(vmDef, def, dstprefix, securityDriver); + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET: + return 0; // case is handled in virLXCControllerMoveInterfaces + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported host device mode %s"), @@ -2286,6 +2288,22 @@ virArch lxcContainerGetAlt32bitArch(virArch arch) } +static bool +lxcNeedNetworkNamespace(virDomainDefPtr def) +{ + size_t i; + if (def->nets != NULL) + return true; + if (def->features & (1 << VIR_DOMAIN_FEATURE_PRIVNET)) + return true; + for (i = 0 ; i < def->nhostdevs ; i++) { + if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES && + def->hostdevs[i]->source.caps.type == VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET) + return true; + } + return false; +} + /** * lxcContainerStart: * @def: pointer to virtual machine structure @@ -2329,8 +2347,7 @@ int lxcContainerStart(virDomainDefPtr def, cflags |= CLONE_NEWUSER; } - if (def->nets != NULL || - (def->features & (1 << VIR_DOMAIN_FEATURE_PRIVNET))) { + if (lxcNeedNetworkNamespace(def)) { VIR_DEBUG("Enable network namespaces"); cflags |= CLONE_NEWNET; } diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 6425ff167b..f2462ef5fe 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1050,12 +1050,28 @@ cleanup2: static int virLXCControllerMoveInterfaces(virLXCControllerPtr ctrl) { size_t i; + virDomainDefPtr def = ctrl->def; for (i = 0 ; i < ctrl->nveths ; i++) { if (virNetDevSetNamespace(ctrl->veths[i], ctrl->initpid) < 0) return -1; } + for (i = 0; i < def->nhostdevs; i ++) { + virDomainHostdevDefPtr hdev = def->hostdevs[i]; + + if (hdev->mode != VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES) + continue; + + virDomainHostdevCaps hdcaps = hdev->source.caps; + + if (hdcaps.type != VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET) + continue; + + if (virNetDevSetNamespace(hdcaps.u.net.iface, ctrl->initpid) < 0) + return -1; + } + return 0; } diff --git a/src/lxc/lxc_hostdev.c b/src/lxc/lxc_hostdev.c index 33b0b60a69..53a1a31f7f 100644 --- a/src/lxc/lxc_hostdev.c +++ b/src/lxc/lxc_hostdev.c @@ -307,6 +307,7 @@ int virLXCPrepareHostDevices(virLXCDriverPtr driver, switch (dev->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET: break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, diff --git a/tests/lxcxml2xmldata/lxc-hostdev.xml b/tests/lxcxml2xmldata/lxc-hostdev.xml index b022cc714b..befe0db329 100644 --- a/tests/lxcxml2xmldata/lxc-hostdev.xml +++ b/tests/lxcxml2xmldata/lxc-hostdev.xml @@ -31,5 +31,10 @@ /dev/tty0 + + + eth0 + +