the domain XML <interface> element is updated in the following ways: 1) <virtualportprofile> can be specified when source type='network' (previously it was only valid for source type='direct') (Since virtualPortProfile is going to be used in both the domain and network RNG, its RNG definition was moved into a separate file that will be included by both.) 2) A new attribute "portgroup" has been added to the <source> element. When source type='network' (the only time portgroup is recognized), extra configuration information will be taken from the <portgroup> element of the given name. 3) Each virDomainNetDef now also potentially has a virDomainActualNetDef which is a private object (never exported/imported via the public API, and not defined in the RNG) that is used to maintain information about the physical device that was actually used for a NetDef that was of type VIR_DOMAIN_NET_TYPE_NETWORK. The virDomainActualNetDef will only be parsed/formatted if the parse/format function is called with the VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET flag set (which is only needed when saving/loading a running domain's state info to the stateDir). --- The internal flag created a lot of discussion on the list, and what was finally decided on was to leave the existing VIR_DOMAIN_XML_INTERNAL_STATUS in the regular flags (and also put my new VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET there), but put in a compile-time protection against re-using those bits for the public API, and a runtime check to make sure nobody calls the public API with those bits on. Eric took care of this in a separate patch, which was pushed on Monday. Comments on other changes from V1 are here: https://www.redhat.com/archives/libvir-list/2011-July/msg01289.html https://www.redhat.com/archives/libvir-list/2011-July/msg01290.html docs/formatdomain.html.in | 61 ++++- docs/schemas/domain.rng | 8 + src/conf/domain_conf.c | 284 +++++++++++++++++++- src/conf/domain_conf.h | 40 +++ src/libvirt_private.syms | 7 +- src/libxl/libxl_driver.c | 4 +- .../qemuxml2argv-net-virtio-network-portgroup.xml | 33 +++ tests/qemuxml2xmltest.c | 1 + 8 files changed, 411 insertions(+), 27 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index a54ee6a..8f42ba9 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1369,24 +1369,55 @@ <p> <strong><em> This is the recommended config for general guest connectivity on - hosts with dynamic / wireless networking configs + hosts with dynamic / wireless networking configs (or multi-host + environments where the host hardware details are described + separately in a <code><network></code> + definition <span class="since">Since 0.9.4</span>). </em></strong> </p> <p> - Provides a virtual network using a bridge device in the host. - Depending on the virtual network configuration, the network may be - totally isolated, NAT'ing to an explicit network device, or NAT'ing to - the default route. DHCP and DNS are provided on the virtual network in - all cases and the IP range can be determined by examining the virtual - network config with '<code>virsh net-dumpxml [networkname]</code>'. - There is one virtual network called 'default' setup out - of the box which does NAT'ing to the default route and has an IP range of - <code>192.168.122.0/255.255.255.0</code>. Each guest will have an - associated tun device created with a name of vnetN, which can also be - overridden with the <target> element (see + + Provides a connection whose details are described by the named + network definition. Depending on the virtual network's "forward + mode" configuration, the network may be totally isolated + (no <code><forward></code> element given), NAT'ing to an + explicit network device or to the default route + (<code><forward mode='nat'></code>), routed with no NAT + (<code><forward mode='route'/></code>), or connected + directly to one of the host's network interfaces (via macvtap) + or bridge devices ((<code><forward + mode='bridge|private|vepa|passthrough'/></code> <span class="since">Since + 0.9.4</span>) + </p> + <p> + For networks with a forward mode of bridge, private, vepa, and + passthrough, it is assumed that the host has any necessary DNS + and DHCP services already setup outside the scope of libvirt. In + the case of isolated, nat, and routed networks, DHCP and DNS are + provided on the virtual network by libvirt, and the IP range can + be determined by examining the virtual network config with + '<code>virsh net-dumpxml [networkname]</code>'. There is one + virtual network called 'default' setup out of the box which does + NAT'ing to the default route and has an IP range + of <code>192.168.122.0/255.255.255.0</code>. Each guest will + have an associated tun device created with a name of vnetN, + which can also be overridden with the <target> element + (see <a href="#elementsNICSTargetOverride">overriding the target element</a>). </p> + <p> + When the source of an interface is a network, + a <code>portgroup</code> can be specified along with the name of + the network; one network may have multiple portgroups defined, + with each portgroup containing slightly different configuration + information for different classes of network + connections. <span class="since">Since 0.9.4</span>). Also, + similar to <code>direct</code> network connections (described + below), a connection of type <code>network</code> may specify + a <code>virtportprofile</code> element, with configuration data + to be forwarded to a vepa or 802.1Qbh compliant switch. + </p> <pre> ... @@ -1396,9 +1427,13 @@ </interface> ... <interface type='network'> - <source network='default'/> + <source network='default' portgroup='engineering'/> <target dev='vnet7'/> <mac address="00:11:22:33:44:55"/> + <virtualport type='802.1Qbg'> + <parameters managerid='11' typeid='1193047' typeidversion='2' instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/> + </virtualport> + </interface> </devices> ...</pre> diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 2f656ed..07c63bd 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1026,8 +1026,16 @@ <attribute name="network"> <ref name="deviceName"/> </attribute> + <optional> + <attribute name="portgroup"> + <ref name="deviceName"/> + </attribute> + </optional> <empty/> </element> + <optional> + <ref name="virtualPortProfile"/> + </optional> <ref name="interface-options"/> </interleave> </group> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 24f9b00..4c58633 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -56,10 +56,11 @@ * verify that it doesn't overflow an unsigned int when shifting */ verify(VIR_DOMAIN_VIRT_LAST <= 32); -/* Private flag used internally by virDomainSaveStatus and - * virDomainObjParseFile. */ +/* Private flags used internally by virDomainSaveStatus and + * virDomainLoadStatus. */ typedef enum { VIR_DOMAIN_XML_INTERNAL_STATUS = (1<<16), /* dump internal domain status information */ + VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET = (1<<17), /* dump/parse <actual> element */ } virDomainXMLInternalFlags; VIR_ENUM_IMPL(virDomainTaint, VIR_DOMAIN_TAINT_LAST, @@ -734,6 +735,25 @@ void virDomainFSDefFree(virDomainFSDefPtr def) VIR_FREE(def); } +void +virDomainActualNetDefFree(virDomainActualNetDefPtr def) +{ + if (!def) + return; + + switch (def->type) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + VIR_FREE(def->data.bridge.brname); + break; + case VIR_DOMAIN_NET_TYPE_DIRECT: + VIR_FREE(def->data.direct.linkdev); + VIR_FREE(def->data.direct.virtPortProfile); + break; + default: + break; + } +} + void virDomainNetDefFree(virDomainNetDefPtr def) { if (!def) @@ -756,6 +776,9 @@ void virDomainNetDefFree(virDomainNetDefPtr def) case VIR_DOMAIN_NET_TYPE_NETWORK: VIR_FREE(def->data.network.name); + VIR_FREE(def->data.network.portgroup); + VIR_FREE(def->data.network.virtPortProfile); + virDomainActualNetDefFree(def->data.network.actual); break; case VIR_DOMAIN_NET_TYPE_BRIDGE: @@ -2586,6 +2609,80 @@ cleanup: goto cleanup; } +static int +virDomainActualNetDefParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt, + virDomainActualNetDefPtr *def) +{ + virDomainActualNetDefPtr actual = NULL; + int ret = -1; + xmlNodePtr save_ctxt = ctxt->node; + char *type = NULL; + char *mode = NULL; + + if (VIR_ALLOC(actual) < 0) { + virReportOOMError(); + return -1; + } + + ctxt->node = node; + + type = virXMLPropString(node, "type"); + if (!type) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing type attribute in interface's <actual> element")); + goto error; + } + if ((int)(actual->type = virDomainNetTypeFromString(type)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown type '%s' in interface's <actual> element"), type); + goto error; + } + if (actual->type != VIR_DOMAIN_NET_TYPE_BRIDGE && + actual->type != VIR_DOMAIN_NET_TYPE_DIRECT) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unsupported type '%s' in interface's <actual> element"), + type); + goto error; + } + + if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + actual->data.bridge.brname = virXPathString("string(./source[1]/@bridge)", ctxt); + } else if (actual->type == VIR_DOMAIN_NET_TYPE_DIRECT) { + xmlNodePtr virtPortNode; + + actual->data.direct.linkdev = virXPathString("string(./source[1]/@dev)", ctxt); + + mode = virXPathString("string(./source[1]/@mode)", ctxt); + if (mode) { + int m; + if ((m = virMacvtapModeTypeFromString(mode)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("Unkown mode '%s' in interface <actual> element"), + mode); + goto error; + } + actual->data.direct.mode = m; + } + + virtPortNode = virXPathNode("./virtualport", ctxt); + if (virtPortNode && + virVirtualPortProfileParamsParseXML(virtPortNode, + &actual->data.direct.virtPortProfile) < 0) { + goto error; + } + } + + *def = actual; + actual = NULL; + ret = 0; +error: + VIR_FREE(type); + VIR_FREE(mode); + + ctxt->node = save_ctxt; + return ret; +} /* Parse the XML definition for a network interface * @param node XML nodeset to parse for net definition @@ -2603,6 +2700,7 @@ virDomainNetDefParseXML(virCapsPtr caps, char *macaddr = NULL; char *type = NULL; char *network = NULL; + char *portgroup = NULL; char *bridge = NULL; char *dev = NULL; char *ifname = NULL; @@ -2619,6 +2717,7 @@ virDomainNetDefParseXML(virCapsPtr caps, char *mode = NULL; virNWFilterHashTablePtr filterparams = NULL; virVirtualPortProfileParamsPtr virtPort = NULL; + virDomainActualNetDefPtr actual = NULL; xmlNodePtr oldnode = ctxt->node; int ret; @@ -2650,6 +2749,7 @@ virDomainNetDefParseXML(virCapsPtr caps, (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) && (xmlStrEqual(cur->name, BAD_CAST "source"))) { network = virXMLPropString(cur, "network"); + portgroup = virXMLPropString(cur, "portgroup"); } else if ((internal == NULL) && (def->type == VIR_DOMAIN_NET_TYPE_INTERNAL) && (xmlStrEqual(cur->name, BAD_CAST "source"))) { @@ -2665,7 +2765,8 @@ virDomainNetDefParseXML(virCapsPtr caps, dev = virXMLPropString(cur, "dev"); mode = virXMLPropString(cur, "mode"); } else if ((virtPort == NULL) && - (def->type == VIR_DOMAIN_NET_TYPE_DIRECT) && + ((def->type == VIR_DOMAIN_NET_TYPE_DIRECT) || + (def->type == VIR_DOMAIN_NET_TYPE_NETWORK)) && xmlStrEqual(cur->name, BAD_CAST "virtualport")) { if (virVirtualPortProfileParamsParseXML(cur, &virtPort) < 0) goto error; @@ -2713,6 +2814,12 @@ virDomainNetDefParseXML(virCapsPtr caps, if (virDomainDeviceBootParseXML(cur, &def->bootIndex, bootMap)) goto error; + } else if ((actual == NULL) && + (flags & VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) && + (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) && + xmlStrEqual(cur->name, BAD_CAST "actual")) { + if (virDomainActualNetDefParseXML(cur, ctxt, &actual) < 0) + goto error; } } cur = cur->next; @@ -2761,6 +2868,12 @@ virDomainNetDefParseXML(virCapsPtr caps, } def->data.network.name = network; network = NULL; + def->data.network.portgroup = portgroup; + portgroup = NULL; + def->data.network.virtPortProfile = virtPort; + virtPort = NULL; + def->data.network.actual = actual; + actual = NULL; break; case VIR_DOMAIN_NET_TYPE_ETHERNET: @@ -2956,11 +3069,13 @@ cleanup: ctxt->node = oldnode; VIR_FREE(macaddr); VIR_FREE(network); + VIR_FREE(portgroup); VIR_FREE(address); VIR_FREE(port); VIR_FREE(ifname); VIR_FREE(dev); VIR_FREE(virtPort); + virDomainActualNetDefFree(actual); VIR_FREE(script); VIR_FREE(bridge); VIR_FREE(model); @@ -6772,7 +6887,8 @@ virDomainDefPtr virDomainDefParseNode(virCapsPtr caps, } ctxt->node = root; - def = virDomainDefParseXML(caps, xml, root, ctxt, expectedVirtTypes, flags); + def = virDomainDefParseXML(caps, xml, root, ctxt, expectedVirtTypes, + flags); cleanup: xmlXPathFreeContext(ctxt); @@ -6803,7 +6919,8 @@ virDomainObjParseNode(virCapsPtr caps, } ctxt->node = root; - obj = virDomainObjParseXML(caps, xml, ctxt, expectedVirtTypes, flags); + obj = virDomainObjParseXML(caps, xml, ctxt, expectedVirtTypes, + flags); cleanup: xmlXPathFreeContext(ctxt); @@ -8529,6 +8646,67 @@ virDomainFSDefFormat(virBufferPtr buf, } static int +virDomainActualNetDefFormat(virBufferPtr buf, + virDomainActualNetDefPtr def) +{ + int ret = -1; + const char *type; + const char *mode; + + if (!def) + return 0; + + type = virDomainNetTypeToString(def->type); + if (!type) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected net type %d"), def->type); + return ret; + } + + if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE && + def->type != VIR_DOMAIN_NET_TYPE_DIRECT) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected net type %s"), type); + goto error; + } + virBufferAsprintf(buf, " <actual type='%s'>\n", type); + + switch (def->type) { + case VIR_DOMAIN_NET_TYPE_BRIDGE: + if (def->data.bridge.brname) { + virBufferEscapeString(buf, " <source bridge='%s'/>\n", + def->data.bridge.brname); + } + break; + + case VIR_DOMAIN_NET_TYPE_DIRECT: + virBufferAddLit(buf, " <source"); + if (def->data.direct.linkdev) + virBufferEscapeString(buf, " dev='%s'", + def->data.direct.linkdev); + + mode = virMacvtapModeTypeToString(def->data.direct.mode); + if (!mode) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected source mode %d"), + def->data.direct.mode); + return ret; + } + virBufferAsprintf(buf, " mode='%s'/>\n", mode); + virVirtualPortProfileFormat(buf, def->data.direct.virtPortProfile, + " "); + break; + default: + break; + } + virBufferAddLit(buf, " </actual>\n"); + + ret = 0; +error: + return ret; +} + +static int virDomainNetDefFormat(virBufferPtr buf, virDomainNetDefPtr def, unsigned int flags) @@ -8551,8 +8729,18 @@ virDomainNetDefFormat(virBufferPtr buf, switch (def->type) { case VIR_DOMAIN_NET_TYPE_NETWORK: - virBufferEscapeString(buf, " <source network='%s'/>\n", + virBufferEscapeString(buf, " <source network='%s'", def->data.network.name); + if (def->data.network.portgroup) { + virBufferEscapeString(buf, " portgroup='%s'", + def->data.network.portgroup); + } + virBufferAddLit(buf, "/>\n"); + virVirtualPortProfileFormat(buf, def->data.network.virtPortProfile, + " "); + if ((flags & VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) && + (virDomainActualNetDefFormat(buf, def->data.network.actual) < 0)) + return -1; break; case VIR_DOMAIN_NET_TYPE_ETHERNET: @@ -9437,9 +9625,11 @@ virDomainHostdevDefFormat(virBufferPtr buf, VIR_DOMAIN_XML_INACTIVE | \ VIR_DOMAIN_XML_UPDATE_CPU) -verify((VIR_DOMAIN_XML_INTERNAL_STATUS & DUMPXML_FLAGS) == 0); +verify(((VIR_DOMAIN_XML_INTERNAL_STATUS | + VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) + & DUMPXML_FLAGS) == 0); -/* This internal version can accept VIR_DOMAIN_XML_INTERNAL_STATUS, +/* This internal version can accept VIR_DOMAIN_XML_INTERNAL_*, * whereas the public version cannot. */ static char * virDomainDefFormatInternal(virDomainDefPtr def, @@ -9451,7 +9641,10 @@ virDomainDefFormatInternal(virDomainDefPtr def, const char *type = NULL; int n, allones = 1; - virCheckFlags(DUMPXML_FLAGS | VIR_DOMAIN_XML_INTERNAL_STATUS, NULL); + virCheckFlags(DUMPXML_FLAGS | + VIR_DOMAIN_XML_INTERNAL_STATUS | + VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET, + NULL); if (!(type = virDomainVirtTypeToString(def->virtType))) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -10008,7 +10201,10 @@ int virDomainSaveStatus(virCapsPtr caps, const char *statusDir, virDomainObjPtr obj) { - unsigned int flags = VIR_DOMAIN_XML_SECURE|VIR_DOMAIN_XML_INTERNAL_STATUS; + unsigned int flags = (VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_INTERNAL_STATUS | + VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET); + int ret = -1; char *xml; @@ -10099,7 +10295,8 @@ static virDomainObjPtr virDomainLoadStatus(virCapsPtr caps, goto error; if (!(obj = virDomainObjParseFile(caps, statusFile, expectedVirtTypes, - VIR_DOMAIN_XML_INTERNAL_STATUS))) + VIR_DOMAIN_XML_INTERNAL_STATUS | + VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET))) goto error; virUUIDFormat(obj->def->uuid, uuidstr); @@ -11096,3 +11293,68 @@ virDomainStateReasonFromString(virDomainState state, const char *reason) return -1; } + + +/* Some access functions to gloss over the difference between NetDef + * (<interface>) and ActualNetDef (<actual>). If the NetDef has an + * ActualNetDef, return the requested value from the ActualNetDef, + * otherwise return the value from the NetDef. + */ + +int +virDomainNetGetActualType(virDomainNetDefPtr iface) +{ + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) + return iface->type; + if (!iface->data.network.actual) + return iface->type; + return iface->data.network.actual->type; +} + +char * +virDomainNetGetActualBridgeName(virDomainNetDefPtr iface) +{ + if (iface->type == VIR_DOMAIN_NET_TYPE_BRIDGE) + return iface->data.bridge.brname; + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) + return NULL; + if (!iface->data.network.actual) + return NULL; + return iface->data.network.actual->data.bridge.brname; +} + +char * +virDomainNetGetActualDirectDev(virDomainNetDefPtr iface) +{ + if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT) + return iface->data.direct.linkdev; + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) + return NULL; + if (!iface->data.network.actual) + return NULL; + return iface->data.network.actual->data.direct.linkdev; +} + +int +virDomainNetGetActualDirectMode(virDomainNetDefPtr iface) +{ + if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT) + return iface->data.direct.mode; + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) + return 0; + if (!iface->data.network.actual) + return 0; + return iface->data.network.actual->data.direct.mode; +} + +virVirtualPortProfileParamsPtr +virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr iface) +{ + if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT) + return iface->data.direct.virtPortProfile; + if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK) + return NULL; + if (!iface->data.network.actual) + return NULL; + return iface->data.network.actual->data.direct.virtPortProfile; +} diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 69e74dc..9e9db41 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -343,6 +343,27 @@ enum virDomainNetVirtioTxModeType { VIR_DOMAIN_NET_VIRTIO_TX_MODE_LAST, }; +/* Config that was actually used to bring up interface, after + * resolving network reference. This is private data, only used within + * libvirt, but still must maintain backward compatibility, because + * different versions of libvirt may read the same data file. + */ +typedef struct _virDomainActualNetDef virDomainActualNetDef; +typedef virDomainActualNetDef *virDomainActualNetDefPtr; +struct _virDomainActualNetDef { + enum virDomainNetType type; + union { + struct { + char *brname; + } bridge; + struct { + char *linkdev; + int mode; /* enum virMacvtapMode from util/macvtap.h */ + virVirtualPortProfileParamsPtr virtPortProfile; + } direct; + } data; +}; + /* Stores the virtual network interface configuration */ typedef struct _virDomainNetDef virDomainNetDef; typedef virDomainNetDef *virDomainNetDefPtr; @@ -369,6 +390,17 @@ struct _virDomainNetDef { } socket; /* any of NET_CLIENT or NET_SERVER or NET_MCAST */ struct { char *name; + char *portgroup; + virVirtualPortProfileParamsPtr virtPortProfile; + /* actual has info about the currently used physical + * device (if the network is of type + * bridge/private/vepa/passthrough). This is saved in the + * domain state, but never written to persistent config, + * since it needs to be re-allocated whenever the domain + * is restarted. It is also never shown to the user, and + * the user cannot specify it in XML documents. + */ + virDomainActualNetDefPtr actual; } network; struct { char *brname; @@ -1338,6 +1370,7 @@ void virDomainDiskDefFree(virDomainDiskDefPtr def); void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def); void virDomainControllerDefFree(virDomainControllerDefPtr def); void virDomainFSDefFree(virDomainFSDefPtr def); +void virDomainActualNetDefFree(virDomainActualNetDefPtr def); void virDomainNetDefFree(virDomainNetDefPtr def); void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def); void virDomainChrDefFree(virDomainChrDefPtr def); @@ -1448,6 +1481,13 @@ int virDomainNetIndexByMac(virDomainDefPtr def, const unsigned char *mac); int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net); int virDomainNetRemoveByMac(virDomainDefPtr def, const unsigned char *mac); +int virDomainNetGetActualType(virDomainNetDefPtr iface); +char *virDomainNetGetActualBridgeName(virDomainNetDefPtr iface); +char *virDomainNetGetActualDirectDev(virDomainNetDefPtr iface); +int virDomainNetGetActualDirectMode(virDomainNetDefPtr iface); +virVirtualPortProfileParamsPtr +virDomainNetGetActualDirectVirtPortProfile(virDomainNetDefPtr iface); + int virDomainControllerInsert(virDomainDefPtr def, virDomainControllerDefPtr controller); void virDomainControllerInsertPreAlloced(virDomainDefPtr def, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fba596e..63e8aea 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -223,6 +223,7 @@ virDomainAuditVcpu; # domain_conf.h virDiskNameToBusDeviceIndex; virDiskNameToIndex; +virDomainActualNetDefFree; virDomainAssignDef; virDomainChrConsoleTargetTypeFromString; virDomainChrConsoleTargetTypeToString; @@ -329,6 +330,11 @@ virDomainLoadAllConfigs; virDomainMemballoonModelTypeFromString; virDomainMemballoonModelTypeToString; virDomainNetDefFree; +virDomainNetGetActualBridgeName; +virDomainNetGetActualDirectDev; +virDomainNetGetActualDirectMode; +virDomainNetGetActualType; +virDomainNetGetActualDirectVirtPortProfile; virDomainNetIndexByMac; virDomainNetInsert; virDomainNetRemoveByMac; @@ -743,7 +749,6 @@ virNetworkSaveConfig; virNetworkSetBridgeMacAddr; virNetworkSetBridgeName; - # node_device_conf.h virNodeDevCapTypeToString; virNodeDevCapsDefFree; diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index cc37d05..8c983f2 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -707,7 +707,7 @@ libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm, } vm->def->id = domid; - if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL) + if ((dom_xml = virDomainDefFormat(vm->def)) == NULL) goto error; if (libxl_userdata_store(&priv->ctx, domid, "libvirt-xml", @@ -1852,7 +1852,7 @@ libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm, goto cleanup; } - if ((xml = virDomainDefFormat(vm->def, 0)) == NULL) + if ((xml = virDomainDefFormat(vm->def)) == NULL) goto cleanup; xml_len = strlen(xml) + 1; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml new file mode 100644 index 0000000..0f6e076 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml @@ -0,0 +1,33 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory>219136</memory> + <currentMemory>219136</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest1'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' unit='0'/> + </disk> + <controller type='ide' index='0'/> + <interface type='network'> + <mac address='00:11:22:33:44:55'/> + <source network='rednet' portgroup='bob'/> + <virtualport type='802.1Qbg'> + <parameters managerid='11' typeid='1193047' typeidversion='2' instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/> + </virtualport> + <model type='virtio'/> + </interface> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index f22872f..6b1fbf5 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -158,6 +158,7 @@ mymain(void) DO_TEST("net-virtio-device"); DO_TEST("net-eth"); DO_TEST("net-eth-ifname"); + DO_TEST("net-virtio-network-portgroup"); DO_TEST("sound"); DO_TEST("serial-vc"); -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list