From: Cédric Bosdonnat
+ Note that for LXC containers, this defines the name of the interface
+ on the host side. Since 1.2.7, to define
+ the name of the device on the guest side, the guest
+ element should be used, as in the following snippet:
+
+ ... + <devices> + <interface type='network'> + <source network='default'/> + <guest dev='myeth'/> + </interface> + </devices> + ...+
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 2caeef992c..835bd3c835 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2218,6 +2218,23 @@+ + + ++ ++ ++ + ++ ++ + ++ diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index a1ef374ad5..1e27165e33 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1388,6 +1388,8 @@ void virDomainNetDefFree(virDomainNetDefPtr def) VIR_FREE(def->virtPortProfile); VIR_FREE(def->script); VIR_FREE(def->ifname); + VIR_FREE(def->ifname_guest); + VIR_FREE(def->ifname_guest_actual); virDomainDeviceInfoClear(&def->info); @@ -6608,6 +6610,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, char *bridge = NULL; char *dev = NULL; char *ifname = NULL; + char *ifname_guest = NULL; + char *ifname_guest_actual = NULL; char *script = NULL; char *address = NULL; char *port = NULL; @@ -6722,6 +6726,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, /* An auto-generated target name, blank it out */ VIR_FREE(ifname); } + } else if ((!ifname_guest || !ifname_guest_actual) && + xmlStrEqual(cur->name, BAD_CAST "guest")) { + ifname_guest = virXMLPropString(cur, "dev"); + ifname_guest_actual = virXMLPropString(cur, "actual"); } else if (!linkstate && xmlStrEqual(cur->name, BAD_CAST "link")) { linkstate = virXMLPropString(cur, "state"); @@ -7022,6 +7030,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, def->ifname = ifname; ifname = NULL; } + if (ifname_guest != NULL) { + def->ifname_guest = ifname_guest; + ifname_guest = NULL; + } + if (ifname_guest_actual != NULL) { + def->ifname_guest_actual = ifname_guest_actual; + ifname_guest_actual = NULL; + } /* NIC model (see -net nic,model=?). We only check that it looks * reasonable, not that it is a supported NIC type. FWIW kvm @@ -15849,6 +15865,17 @@ virDomainNetDefFormat(virBufferPtr buf, /* Skip auto-generated target names for inactive config. */ virBufferEscapeString(buf, " \n", def->ifname); } + if (def->ifname_guest || def->ifname_guest_actual) { + virBufferAddLit(buf, " ifname_guest) + virBufferEscapeString(buf, " dev='%s'", def->ifname_guest); + + /* Only set if the host is running, so shouldn't pollute output */ + if (def->ifname_guest_actual) + virBufferEscapeString(buf, " actual='%s'", def->ifname_guest_actual); + virBufferAddLit(buf, "/>\n"); + } if (def->model) { virBufferEscapeString(buf, " \n", def->model); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e4d7988f61..cd3293b398 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -923,6 +923,8 @@ struct _virDomainNetDef { } tune; char *script; char *ifname; + char *ifname_guest; + char *ifname_guest_actual; virDomainDeviceInfo info; char *filter; virNWFilterHashTablePtr filterparams; diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 4d89677814..571983081d 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -464,6 +464,21 @@ static int lxcContainerSetID(virDomainDefPtr def) } +static virDomainNetDefPtr +lxcContainerGetNetDef(virDomainDefPtr vmDef, const char *devName) +{ + size_t i; + virDomainNetDefPtr netDef; + + for (i = 0; i < vmDef->nnets; i++) { + netDef = vmDef->nets[i]; + if (STREQ(netDef->ifname_guest_actual, devName)) + return netDef; + } + + return NULL; +} + /** * lxcContainerRenameAndEnableInterfaces: * @nveths: number of interfaces @@ -475,16 +490,23 @@ static int lxcContainerSetID(virDomainDefPtr def) * * Returns 0 on success or nonzero in case of error */ -static int lxcContainerRenameAndEnableInterfaces(bool privNet, +static int lxcContainerRenameAndEnableInterfaces(virDomainDefPtr vmDef, size_t nveths, char **veths) { int rc = 0; size_t i; char *newname = NULL; + virDomainNetDefPtr netDef; + bool privNet = vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] == + VIR_DOMAIN_FEATURE_STATE_ON; for (i = 0; i < nveths; i++) { - if (virAsprintf(&newname, "eth%zu", i) < 0) { + if (!(netDef = lxcContainerGetNetDef(vmDef, veths[i]))) + return -1; + + newname = netDef->ifname_guest; + if (!newname) { rc = -1; goto error_out; } @@ -1866,8 +1888,7 @@ static int lxcContainerChild(void *data) } /* rename and enable interfaces */ - if (lxcContainerRenameAndEnableInterfaces(vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] == - VIR_DOMAIN_FEATURE_STATE_ON, + if (lxcContainerRenameAndEnableInterfaces(vmDef, argv->nveths, argv->veths) < 0) { goto cleanup; diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c index 854f65d89c..491203544f 100644 --- a/src/lxc/lxc_process.c +++ b/src/lxc/lxc_process.c @@ -259,6 +259,8 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn, if (virNetDevSetMAC(containerVeth, &net->mac) < 0) goto cleanup; + if (VIR_STRDUP(net->ifname_guest_actual, containerVeth) < 0) + goto cleanup; if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) { if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac, @@ -369,6 +371,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, { int ret = -1; size_t i; + size_t niface = 0; for (i = 0; i < def->nnets; i++) { char *veth = NULL; @@ -452,6 +455,13 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, } (*veths)[(*nveths)-1] = veth; + + /* Make sure all net definitions will have a name in the container */ + if (!def->nets[i]->ifname_guest) { + if (virAsprintf(&def->nets[i]->ifname_guest, "eth%zu", niface) < 0) + return -1; + niface++; + } } ret = 0; @@ -471,6 +481,17 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, return ret; } +static void +virLXCProcessCleanInterfaces(virDomainDefPtr def) +{ + size_t i; + + for (i = 0; i < def->nnets; i++) { + VIR_FREE(def->nets[i]->ifname_guest_actual); + VIR_DEBUG("Cleared net names: %s", def->nets[i]->ifname_guest); + } +} + extern virLXCDriverPtr lxc_driver; static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon, @@ -1307,6 +1328,9 @@ int virLXCProcessStart(virConnectPtr conn, vm, false) < 0) goto error; + /* We don't need the temporary NIC names anymore, clear them */ + virLXCProcessCleanInterfaces(vm->def); + /* Write domain status to disk. * * XXX: Earlier we wrote the plain "live" domain XML to this diff --git a/tests/lxcxml2xmldata/lxc-idmap.xml b/tests/lxcxml2xmldata/lxc-idmap.xml index 3cced2107d..946d36357e 100644 --- a/tests/lxcxml2xmldata/lxc-idmap.xml +++ b/tests/lxcxml2xmldata/lxc-idmap.xml @@ -29,6 +29,7 @@ +