[libvirt] [PATCH 1/3] bridge_driver: Return the live state info of a given virtual network
Laine Stump
laine at laine.org
Wed Feb 4 01:07:01 UTC 2015
On 02/02/2015 09:08 AM, Lin Ma wrote:
> It constructs a temporary static config of the network, Obtains all of
> attached interfaces information through netcf, Then removes the config.
>
> Signed-off-by: Lin Ma <lma at suse.com>
> ---
> include/libvirt/libvirt-network.h | 1 +
> src/Makefile.am | 3 +
> src/network/bridge_driver.c | 141 ++++++++++++++++++++++++++++++++++-
> src/network/bridge_driver_platform.h | 7 ++
> tests/Makefile.am | 4 +
> 5 files changed, 155 insertions(+), 1 deletion(-)
>
> diff --git a/include/libvirt/libvirt-network.h b/include/libvirt/libvirt-network.h
> index 308f27f..9b09546 100644
> --- a/include/libvirt/libvirt-network.h
> +++ b/include/libvirt/libvirt-network.h
> @@ -30,6 +30,7 @@
>
> typedef enum {
> VIR_NETWORK_XML_INACTIVE = (1 << 0), /* dump inactive network information */
> + VIR_NETWORK_XML_IFACE_ATTACHED = (1 << 1), /* dump current live state */
> } virNetworkXMLFlags;
>
> /**
> diff --git a/src/Makefile.am b/src/Makefile.am
> index b41c6d4..d22ae7e 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -1412,6 +1412,9 @@ if WITH_NETWORK
> noinst_LTLIBRARIES += libvirt_driver_network_impl.la
> libvirt_driver_network_la_SOURCES =
> libvirt_driver_network_la_LIBADD = libvirt_driver_network_impl.la
> +if WITH_NETCF
> +libvirt_driver_network_la_LIBADD += $(NETCF_LIBS)
> +endif WITH_NETCF
> if WITH_DRIVER_MODULES
> mod_LTLIBRARIES += libvirt_driver_network.la
> libvirt_driver_network_la_LIBADD += ../gnulib/lib/libgnu.la \
> diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
> index c56e8f2..1e49e2e 100644
> --- a/src/network/bridge_driver.c
> +++ b/src/network/bridge_driver.c
> @@ -3333,8 +3333,17 @@ static char *networkGetXMLDesc(virNetworkPtr net,
> virNetworkObjPtr network;
> virNetworkDefPtr def;
> char *ret = NULL;
> +#ifdef WITH_NETCF
> + struct netcf_if *iface = NULL;
> + char *bridge = NULL;
> + char *if_xml_tmp = NULL;
> + xmlDocPtr xml = NULL;
> + xmlXPathContextPtr ctxt = NULL;
> + xmlXPathObjectPtr obj = NULL;
> +#endif
>
> - virCheckFlags(VIR_NETWORK_XML_INACTIVE, NULL);
> + virCheckFlags(VIR_NETWORK_XML_INACTIVE |
> + VIR_NETWORK_XML_IFACE_ATTACHED, NULL);
>
> if (!(network = networkObjFromNetwork(net)))
> return ret;
> @@ -3342,6 +3351,135 @@ static char *networkGetXMLDesc(virNetworkPtr net,
> if (virNetworkGetXMLDescEnsureACL(net->conn, network->def) < 0)
> goto cleanup;
>
> +#ifdef WITH_NETCF
> + if ((flags & VIR_NETWORK_XML_INACTIVE) && network->newDef) {
> + def = network->newDef;
> + ret = virNetworkDefFormat(def, flags);
> + }
> + else if (flags & VIR_NETWORK_XML_IFACE_ATTACHED) {
> + if (!(network->def->bridge)) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("network '%s' does not have a bridge name."),
> + network->def->name);
> + goto cleanup;
> + }
> + ignore_value(VIR_STRDUP(bridge, network->def->bridge));
> +
> + if (virAsprintf(&if_xml_tmp,
> + "<interface type='bridge' name='%s'>"
> + "<start mode='none'/><bridge/></interface>",
> + bridge) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("failed to generate temp xml for network"));
> + goto cleanup;
> + }
> +
> + if (ncf_init(&driver->netcf, NULL) != 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("failed to init netcf"));
> + goto cleanup;
> + }
> +
> + // create a temp bridge configuration file
> + iface = ncf_define(driver->netcf, if_xml_tmp);
NACK. This is very much against what netcf (and the virInterface API)
was intended to do, and doing this is nearly *guaranteed* to completely
mess up NetworkManager, which monitors the ifcfg files that are created
by ncf_define.
This is one of the things that we regularly have to tell people that
they *shouldn't* do - the bridge devices created by libvirt must never
be referenced in a system config file; those are by definition
persistent (even though you're deleting it after a short time), and
immediately come in the radar of whatever host system daemon is managing
the persistent network device configs.
Also, I'm not sure I like having netcf called by the bridge driver.
Anyway, if all you want to do is check whether or not a network is in
use, an even more reasonable thing would be to simply look at the
connections attribute of the net (i.e. def->connections) and check that
it is 0 - every connection from a libvirt-managed guest is counted there
(and it's re-computed every time libvirtd is restarted), and anybody who
connects to a libvirt-created bridge without going through libvirt to do
it deserves what they get.
> + if (!iface) {
> + virReportError(VIR_ERR_XML_ERROR,
> + _("failed to define the temp bridge %s"), bridge);
> + ncf_close(driver->netcf);
> + goto cleanup;
> + }
> +
> + ret = ncf_if_xml_state(iface);
> + if (!ret) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("could not get bridge XML description"));
> + ncf_if_free(iface);
> + ncf_close(driver->netcf);
> + goto cleanup;
> + }
> +
> + // remove the temp bridge configuration file
> + if (ncf_if_undefine(iface) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("failed to undefine the temp bridge %s"), bridge);
> + ncf_if_free(iface);
> + ncf_close(driver->netcf);
> + ret = NULL;
> + goto cleanup;
> + }
> + ncf_if_free(iface);
> + ncf_close(driver->netcf);
> +
> + // remove the dummp tap interface section from the result
> + if (network->def->mac_specified) {
> + char *macTapIfName = networkBridgeDummyNicName(network->def->bridge);
> + if (macTapIfName) {
> + char mac[VIR_MAC_STRING_BUFLEN];
> + xmlNodePtr cur = NULL, matchNode = NULL;
> + xmlChar *br_xml = NULL;
> + int br_xml_size;
> + char buf[64];
> + size_t i;
> + int diff_mac;
> + virMacAddrFormat(&network->def->mac, mac);
> + snprintf(buf, sizeof(buf), "./bridge/interface[@name='%s']",
> + macTapIfName);
> + if (!(xml = virXMLParseStringCtxt(ret,
> + _("(bridge interface "
> + "definition)"), &ctxt))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + ("Failed to parse network configuration"));
> + VIR_FREE(macTapIfName);
> + ret = NULL;
> + goto cleanup;
> + }
> + obj = xmlXPathEval(BAD_CAST buf, ctxt);
> + if (obj == NULL || obj->type != XPATH_NODESET ||
> + obj->nodesetval == NULL || obj->nodesetval->nodeNr == 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("No interface found whose name is %s"),
> + macTapIfName);
> + VIR_FREE(macTapIfName);
> + ret = NULL;
> + goto cleanup;
> + }
> + VIR_FREE(macTapIfName);
> + for (i = 0; i < obj->nodesetval->nodeNr; i++) {
> + cur = obj->nodesetval->nodeTab[i]->children;
> + while (cur != NULL) {
> + if (cur->type == XML_ELEMENT_NODE &&
> + xmlStrEqual(cur->name, BAD_CAST "mac")) {
> + char *tmp_mac = virXMLPropString(cur, "address");
> + diff_mac = virMacAddrCompare(tmp_mac, mac);
> + VIR_FREE(tmp_mac);
> + if (!diff_mac) {
> + matchNode = obj->nodesetval->nodeTab[i];
> + xmlUnlinkNode(matchNode);
> + break;
> + }
> + }
> + cur = cur->next;
> + }
> + }
> + xmlDocDumpMemory(xml, &br_xml, &br_xml_size);
> + ret = (char *)br_xml;
> + }
> + }
> + }
> + else {
> + def = network->def;
> + ret = virNetworkDefFormat(def, flags);
> + }
> +
> + cleanup:
> + xmlXPathFreeObject(obj);
> + xmlXPathFreeContext(ctxt);
> + xmlFreeDoc(xml);
> + VIR_FREE(if_xml_tmp);
> + VIR_FREE(bridge);
> + if (network)
> + virNetworkObjUnlock(network);
> +#else
> if ((flags & VIR_NETWORK_XML_INACTIVE) && network->newDef)
> def = network->newDef;
> else
> @@ -3352,6 +3490,7 @@ static char *networkGetXMLDesc(virNetworkPtr net,
> cleanup:
> if (network)
> virNetworkObjUnlock(network);
> +#endif
> return ret;
> }
>
> diff --git a/src/network/bridge_driver_platform.h b/src/network/bridge_driver_platform.h
> index 1e8264a..43ea1c3 100644
> --- a/src/network/bridge_driver_platform.h
> +++ b/src/network/bridge_driver_platform.h
> @@ -24,6 +24,9 @@
> #ifndef __VIR_BRIDGE_DRIVER_PLATFORM_H__
> # define __VIR_BRIDGE_DRIVER_PLATFORM_H__
>
> +#ifdef WITH_NETCF
> +# include <netcf.h>
> +#endif
> # include "internal.h"
> # include "virthread.h"
> # include "virdnsmasq.h"
> @@ -34,6 +37,10 @@
> struct _virNetworkDriverState {
> virMutex lock;
>
> +#ifdef WITH_NETCF
> + struct netcf *netcf;
> +#endif
> +
> virNetworkObjList networks;
>
> char *networkConfigDir;
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> index 938270c..0662337 100644
> --- a/tests/Makefile.am
> +++ b/tests/Makefile.am
> @@ -67,6 +67,10 @@ LDADDS = \
> $(GNULIB_LIBS) \
> ../src/libvirt.la
>
> +if WITH_NETCF
> +LDADDS += $(NETCF_LIBS)
> +endif WITH_NETCF
> +
> EXTRA_DIST = \
> bhyvexml2argvdata \
> bhyvexml2xmloutdata \
More information about the libvir-list
mailing list