提交 3ba0469c 编写于 作者: C Cédric Bosdonnat

lxc network configuration allows setting target container NIC name

LXC network devices can now be assigned a custom NIC device name on the
container side. For example, this is configured with:

    <interface type='network'>
      <source network='default'/>
      <guest dev="eth1"/>
    </interface>

In this example the network card will appear as eth1 in the guest.
上级 d659b412
...@@ -3810,6 +3810,23 @@ qemu-kvm -net nic,model=? /dev/null ...@@ -3810,6 +3810,23 @@ qemu-kvm -net nic,model=? /dev/null
targets using these prefixes will be ignored. targets using these prefixes will be ignored.
</p> </p>
<p>
Note that for LXC containers, this defines the name of the interface
on the host side. <span class="since">Since 1.2.7</span>, to define
the name of the device on the guest side, the <code>guest</code>
element should be used, as in the following snippet:
</p>
<pre>
...
&lt;devices&gt;
&lt;interface type='network'&gt;
&lt;source network='default'/&gt;
<b>&lt;guest dev='myeth'/&gt;</b>
&lt;/interface&gt;
&lt;/devices&gt;
...</pre>
<h5><a name="elementsNICSBoot">Specifying boot order</a></h5> <h5><a name="elementsNICSBoot">Specifying boot order</a></h5>
<pre> <pre>
......
...@@ -2218,6 +2218,23 @@ ...@@ -2218,6 +2218,23 @@
<empty/> <empty/>
</element> </element>
</optional> </optional>
<optional>
<element name="guest">
<interleave>
<optional>
<attribute name="dev">
<ref name="deviceName"/>
</attribute>
</optional>
<optional>
<attribute name="actual">
<ref name="deviceName"/>
</attribute>
</optional>
</interleave>
<empty/>
</element>
</optional>
<optional> <optional>
<element name="mac"> <element name="mac">
<attribute name="address"> <attribute name="address">
......
...@@ -1388,6 +1388,8 @@ void virDomainNetDefFree(virDomainNetDefPtr def) ...@@ -1388,6 +1388,8 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
VIR_FREE(def->virtPortProfile); VIR_FREE(def->virtPortProfile);
VIR_FREE(def->script); VIR_FREE(def->script);
VIR_FREE(def->ifname); VIR_FREE(def->ifname);
VIR_FREE(def->ifname_guest);
VIR_FREE(def->ifname_guest_actual);
virDomainDeviceInfoClear(&def->info); virDomainDeviceInfoClear(&def->info);
...@@ -6608,6 +6610,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -6608,6 +6610,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
char *bridge = NULL; char *bridge = NULL;
char *dev = NULL; char *dev = NULL;
char *ifname = NULL; char *ifname = NULL;
char *ifname_guest = NULL;
char *ifname_guest_actual = NULL;
char *script = NULL; char *script = NULL;
char *address = NULL; char *address = NULL;
char *port = NULL; char *port = NULL;
...@@ -6722,6 +6726,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -6722,6 +6726,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
/* An auto-generated target name, blank it out */ /* An auto-generated target name, blank it out */
VIR_FREE(ifname); 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 && } else if (!linkstate &&
xmlStrEqual(cur->name, BAD_CAST "link")) { xmlStrEqual(cur->name, BAD_CAST "link")) {
linkstate = virXMLPropString(cur, "state"); linkstate = virXMLPropString(cur, "state");
...@@ -7022,6 +7030,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, ...@@ -7022,6 +7030,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
def->ifname = ifname; def->ifname = ifname;
ifname = NULL; 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 /* NIC model (see -net nic,model=?). We only check that it looks
* reasonable, not that it is a supported NIC type. FWIW kvm * reasonable, not that it is a supported NIC type. FWIW kvm
...@@ -15849,6 +15865,17 @@ virDomainNetDefFormat(virBufferPtr buf, ...@@ -15849,6 +15865,17 @@ virDomainNetDefFormat(virBufferPtr buf,
/* Skip auto-generated target names for inactive config. */ /* Skip auto-generated target names for inactive config. */
virBufferEscapeString(buf, "<target dev='%s'/>\n", def->ifname); virBufferEscapeString(buf, "<target dev='%s'/>\n", def->ifname);
} }
if (def->ifname_guest || def->ifname_guest_actual) {
virBufferAddLit(buf, "<guest");
/* Skip auto-generated target names for inactive config. */
if (def->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) { if (def->model) {
virBufferEscapeString(buf, "<model type='%s'/>\n", virBufferEscapeString(buf, "<model type='%s'/>\n",
def->model); def->model);
......
...@@ -923,6 +923,8 @@ struct _virDomainNetDef { ...@@ -923,6 +923,8 @@ struct _virDomainNetDef {
} tune; } tune;
char *script; char *script;
char *ifname; char *ifname;
char *ifname_guest;
char *ifname_guest_actual;
virDomainDeviceInfo info; virDomainDeviceInfo info;
char *filter; char *filter;
virNWFilterHashTablePtr filterparams; virNWFilterHashTablePtr filterparams;
......
...@@ -464,6 +464,21 @@ static int lxcContainerSetID(virDomainDefPtr def) ...@@ -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: * lxcContainerRenameAndEnableInterfaces:
* @nveths: number of interfaces * @nveths: number of interfaces
...@@ -475,16 +490,23 @@ static int lxcContainerSetID(virDomainDefPtr def) ...@@ -475,16 +490,23 @@ static int lxcContainerSetID(virDomainDefPtr def)
* *
* Returns 0 on success or nonzero in case of error * Returns 0 on success or nonzero in case of error
*/ */
static int lxcContainerRenameAndEnableInterfaces(bool privNet, static int lxcContainerRenameAndEnableInterfaces(virDomainDefPtr vmDef,
size_t nveths, size_t nveths,
char **veths) char **veths)
{ {
int rc = 0; int rc = 0;
size_t i; size_t i;
char *newname = NULL; char *newname = NULL;
virDomainNetDefPtr netDef;
bool privNet = vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] ==
VIR_DOMAIN_FEATURE_STATE_ON;
for (i = 0; i < nveths; i++) { 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; rc = -1;
goto error_out; goto error_out;
} }
...@@ -1866,8 +1888,7 @@ static int lxcContainerChild(void *data) ...@@ -1866,8 +1888,7 @@ static int lxcContainerChild(void *data)
} }
/* rename and enable interfaces */ /* rename and enable interfaces */
if (lxcContainerRenameAndEnableInterfaces(vmDef->features[VIR_DOMAIN_FEATURE_PRIVNET] == if (lxcContainerRenameAndEnableInterfaces(vmDef,
VIR_DOMAIN_FEATURE_STATE_ON,
argv->nveths, argv->nveths,
argv->veths) < 0) { argv->veths) < 0) {
goto cleanup; goto cleanup;
......
...@@ -259,6 +259,8 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn, ...@@ -259,6 +259,8 @@ char *virLXCProcessSetupInterfaceBridged(virConnectPtr conn,
if (virNetDevSetMAC(containerVeth, &net->mac) < 0) if (virNetDevSetMAC(containerVeth, &net->mac) < 0)
goto cleanup; goto cleanup;
if (VIR_STRDUP(net->ifname_guest_actual, containerVeth) < 0)
goto cleanup;
if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) { if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac, if (virNetDevOpenvswitchAddPort(brname, parentVeth, &net->mac,
...@@ -369,6 +371,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, ...@@ -369,6 +371,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
{ {
int ret = -1; int ret = -1;
size_t i; size_t i;
size_t niface = 0;
for (i = 0; i < def->nnets; i++) { for (i = 0; i < def->nnets; i++) {
char *veth = NULL; char *veth = NULL;
...@@ -452,6 +455,13 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, ...@@ -452,6 +455,13 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
} }
(*veths)[(*nveths)-1] = veth; (*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; ret = 0;
...@@ -471,6 +481,17 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn, ...@@ -471,6 +481,17 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
return ret; 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; extern virLXCDriverPtr lxc_driver;
static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon, static void virLXCProcessMonitorEOFNotify(virLXCMonitorPtr mon,
...@@ -1307,6 +1328,9 @@ int virLXCProcessStart(virConnectPtr conn, ...@@ -1307,6 +1328,9 @@ int virLXCProcessStart(virConnectPtr conn,
vm, false) < 0) vm, false) < 0)
goto error; goto error;
/* We don't need the temporary NIC names anymore, clear them */
virLXCProcessCleanInterfaces(vm->def);
/* Write domain status to disk. /* Write domain status to disk.
* *
* XXX: Earlier we wrote the plain "live" domain XML to this * XXX: Earlier we wrote the plain "live" domain XML to this
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
<mac address='00:16:3e:0f:ef:8a'/> <mac address='00:16:3e:0f:ef:8a'/>
<source bridge='bri0'/> <source bridge='bri0'/>
<target dev='veth0'/> <target dev='veth0'/>
<guest dev='eth2'/>
</interface> </interface>
<console type='pty'> <console type='pty'>
<target type='lxc' port='0'/> <target type='lxc' port='0'/>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册