提交 a3609121 编写于 作者: L Laine Stump

network: save bridge name in ActualNetDef when actualType==network too

When the actualType of a virDomainNetDef is "network", it means that
we are connecting to a libvirt-managed network (routed, natted, or
isolated) which does use a bridge device (created by libvirt). In the
past we have required drivers such as qemu to call the public API to
retrieve the bridge name in this case (even though it is available in
the NetDef's ActualNetDef if the actualType is "bridge" (i.e., an
externally-created bridge that isn't managed by libvirt). There is no
real reason for this difference, and as a matter of fact it
complicates things for qemu. Also, there is another bridge-related
attribute (macTableManager) that will need to be available in both
cases, so this makes things consistent.

In order to avoid problems when restarting libvirtd after an update
from an older version that *doesn't* store the network's bridgename in
the ActualNetDef, we also need to put it in place during
networkNotifyActualDevice() (this function is run for each interface
of each domain whenever libvirtd is restarted).

Along with making the bridge name available in the internal object, it
is also now reported in the <source> element of the <interface> state
XML (or the <actual> subelement in the internally-stored format).

The one oddity about this change is that usually there is a separate
union for every different "type" in a higher level object (e.g. in the
case of a virDomainNetDef there are separate "network" and "bridge"
members of the union that pivots on the type), but in this case
network and bridge types both have exactly the same attributes, so the
"bridge" member is used for both type==network and type==bridge.
上级 40961978
...@@ -1354,6 +1354,7 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def) ...@@ -1354,6 +1354,7 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
switch (def->type) { switch (def->type) {
case VIR_DOMAIN_NET_TYPE_BRIDGE: case VIR_DOMAIN_NET_TYPE_BRIDGE:
case VIR_DOMAIN_NET_TYPE_NETWORK:
VIR_FREE(def->data.bridge.brname); VIR_FREE(def->data.bridge.brname);
break; break;
case VIR_DOMAIN_NET_TYPE_DIRECT: case VIR_DOMAIN_NET_TYPE_DIRECT:
...@@ -7106,9 +7107,12 @@ virDomainActualNetDefParseXML(xmlNodePtr node, ...@@ -7106,9 +7107,12 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
goto error; goto error;
} }
VIR_FREE(class_id); VIR_FREE(class_id);
} else if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { }
if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
actual->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
char *brname = virXPathString("string(./source/@bridge)", ctxt); char *brname = virXPathString("string(./source/@bridge)", ctxt);
if (!brname) {
if (!brname && actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing <source> element with bridge name in " _("Missing <source> element with bridge name in "
"interface's <actual> element")); "interface's <actual> element"));
...@@ -17126,60 +17130,59 @@ virDomainHostdevDefFormatCaps(virBufferPtr buf, ...@@ -17126,60 +17130,59 @@ virDomainHostdevDefFormatCaps(virBufferPtr buf,
static int static int
virDomainActualNetDefContentsFormat(virBufferPtr buf, virDomainActualNetDefContentsFormat(virBufferPtr buf,
virDomainNetDefPtr def, virDomainNetDefPtr def,
const char *typeStr,
bool inSubelement, bool inSubelement,
unsigned int flags) unsigned int flags)
{ {
const char *mode; int actualType = virDomainNetGetActualType(def);
switch (virDomainNetGetActualType(def)) {
case VIR_DOMAIN_NET_TYPE_BRIDGE:
virBufferEscapeString(buf, "<source bridge='%s'/>\n",
virDomainNetGetActualBridgeName(def));
break;
case VIR_DOMAIN_NET_TYPE_DIRECT:
virBufferAddLit(buf, "<source");
virBufferEscapeString(buf, " dev='%s'",
virDomainNetGetActualDirectDev(def));
mode = virNetDevMacVLanModeTypeToString(virDomainNetGetActualDirectMode(def)); if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
if (!mode) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected source mode %d"),
virDomainNetGetActualDirectMode(def));
return -1;
}
virBufferAsprintf(buf, " mode='%s'/>\n", mode);
break;
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
if (virDomainHostdevDefFormatSubsys(buf, virDomainNetGetActualHostdev(def), if (virDomainHostdevDefFormatSubsys(buf, virDomainNetGetActualHostdev(def),
flags, true) < 0) { flags, true) < 0) {
return -1; return -1;
} }
break; } else {
virBufferAddLit(buf, "<source");
case VIR_DOMAIN_NET_TYPE_NETWORK: if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK && !inSubelement) {
if (!inSubelement) { /* When we're putting our output into the <actual>
/* the <source> element isn't included in <actual> * subelement rather than the main <interface>, the
* (i.e. when we're putting our output into a subelement * network name isn't included in the <source> because the
* rather than inline) because the main element has the * main interface element's <source> has the same info
* same info already. If we're outputting inline, though, * already. If we've been called to output directly into
* we *do* need to output <source>, because the caller * the main element's <source> though (the case here -
* won't have done it. * "!inSubElement"), we *do* need to output the network
* name, because the caller won't have done it).
*/ */
virBufferEscapeString(buf, "<source network='%s'/>\n", virBufferEscapeString(buf, " network='%s'", def->data.network.name);
def->data.network.name);
} }
if (def->data.network.actual && def->data.network.actual->class_id) if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
virBufferAsprintf(buf, "<class id='%u'/>\n", actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
def->data.network.actual->class_id); /* actualType == NETWORK includes the name of the bridge
break; * that is used by the network, whether we are
default: * "inSubElement" or not.
virReportError(VIR_ERR_INTERNAL_ERROR, */
_("unexpected actual net type %s"), typeStr); virBufferEscapeString(buf, " bridge='%s'",
return -1; virDomainNetGetActualBridgeName(def));
} else if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
const char *mode;
virBufferEscapeString(buf, " dev='%s'",
virDomainNetGetActualDirectDev(def));
mode = virNetDevMacVLanModeTypeToString(virDomainNetGetActualDirectMode(def));
if (!mode) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected source mode %d"),
virDomainNetGetActualDirectMode(def));
return -1;
}
virBufferAsprintf(buf, " mode='%s'", mode);
}
virBufferAddLit(buf, "/>\n");
}
if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT &&
def->data.network.actual && def->data.network.actual->class_id) {
virBufferAsprintf(buf, "<class id='%u'/>\n",
def->data.network.actual->class_id);
} }
if (virNetDevVlanFormat(virDomainNetGetActualVlan(def), buf) < 0) if (virNetDevVlanFormat(virDomainNetGetActualVlan(def), buf) < 0)
...@@ -17227,7 +17230,7 @@ virDomainActualNetDefFormat(virBufferPtr buf, ...@@ -17227,7 +17230,7 @@ virDomainActualNetDefFormat(virBufferPtr buf,
virBufferAddLit(buf, ">\n"); virBufferAddLit(buf, ">\n");
virBufferAdjustIndent(buf, 2); virBufferAdjustIndent(buf, 2);
if (virDomainActualNetDefContentsFormat(buf, def, typeStr, true, flags) < 0) if (virDomainActualNetDefContentsFormat(buf, def, true, flags) < 0)
return -1; return -1;
virBufferAdjustIndent(buf, -2); virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</actual>\n"); virBufferAddLit(buf, "</actual>\n");
...@@ -17398,7 +17401,7 @@ virDomainNetDefFormat(virBufferPtr buf, ...@@ -17398,7 +17401,7 @@ virDomainNetDefFormat(virBufferPtr buf,
* the standard place... (this is for public reporting of * the standard place... (this is for public reporting of
* interface status) * interface status)
*/ */
if (virDomainActualNetDefContentsFormat(buf, def, typeStr, false, flags) < 0) if (virDomainActualNetDefContentsFormat(buf, def, false, flags) < 0)
return -1; return -1;
} else { } else {
/* ...but if we've asked for the inactive XML (rather than /* ...but if we've asked for the inactive XML (rather than
...@@ -20751,7 +20754,8 @@ virDomainNetGetActualBridgeName(virDomainNetDefPtr iface) ...@@ -20751,7 +20754,8 @@ virDomainNetGetActualBridgeName(virDomainNetDefPtr iface)
return iface->data.bridge.brname; return iface->data.bridge.brname;
if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK && if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
iface->data.network.actual && iface->data.network.actual &&
iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) (iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_NETWORK))
return iface->data.network.actual->data.bridge.brname; return iface->data.network.actual->data.bridge.brname;
return NULL; return NULL;
} }
......
...@@ -3795,6 +3795,15 @@ networkAllocateActualDevice(virDomainDefPtr dom, ...@@ -3795,6 +3795,15 @@ networkAllocateActualDevice(virDomainDefPtr dom,
*/ */
iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK; iface->data.network.actual->type = VIR_DOMAIN_NET_TYPE_NETWORK;
/* we also store the bridge device
* in iface->data.network.actual->data.bridge for later use
* after the domain's tap device is created (to attach to the
* bridge and set flood/learning mode on the tap device)
*/
if (VIR_STRDUP(iface->data.network.actual->data.bridge.brname,
netdef->bridge) < 0)
goto error;
if (networkPlugBandwidth(network, iface) < 0) if (networkPlugBandwidth(network, iface) < 0)
goto error; goto error;
...@@ -4131,6 +4140,17 @@ networkNotifyActualDevice(virDomainDefPtr dom, ...@@ -4131,6 +4140,17 @@ networkNotifyActualDevice(virDomainDefPtr dom,
} }
netdef = network->def; netdef = network->def;
/* if we're restarting libvirtd after an upgrade from a version
* that didn't save bridge name in actualNetDef for
* actualType==network, we need to copy it in so that it will be
* available in all cases
*/
if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK &&
!iface->data.network.actual->data.bridge.brname &&
(VIR_STRDUP(iface->data.network.actual->data.bridge.brname,
netdef->bridge) < 0))
goto error;
if (!iface->data.network.actual || if (!iface->data.network.actual ||
(actualType != VIR_DOMAIN_NET_TYPE_DIRECT && (actualType != VIR_DOMAIN_NET_TYPE_DIRECT &&
actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV)) { actualType != VIR_DOMAIN_NET_TYPE_HOSTDEV)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册