[libvirt] [PATCH 0/2] interface driver build cleanup and udev backend addition

Refactored the cross use of netcf and interface for the interface driver into only interface driver references. Made netcf the primary backend provider for the interface driver. Added a udev based read-only interface driver backend to be used when netcf support is not built in. Untested: * udev: Does it display devices that are part of a bond. * netcf: developed all this on distros without netcf support. Unknown: * Should virInterfaceGetXMLDesc() be implemented for the udev backend? It will as a result contain a lot less info than the netcf based backend would for the same device (e.g. does the device start on boot). Doug Goldstein (2): build: define WITH_INTERFACE for the driver interface: add udev based backend for virInterface configure.ac | 37 ++- daemon/Makefile.am | 2 +- daemon/libvirtd.c | 8 +- src/Makefile.am | 34 ++- .../{netcf_driver.c => interface_backend_netcf.c} | 2 +- src/interface/interface_backend_udev.c | 377 ++++++++++++++++++++ .../{netcf_driver.h => interface_driver.h} | 0 tests/virdrivermoduletest.c | 2 +- tools/virsh.c | 4 +- 9 files changed, 449 insertions(+), 17 deletions(-) rename src/interface/{netcf_driver.c => interface_backend_netcf.c} (99%) create mode 100644 src/interface/interface_backend_udev.c rename src/interface/{netcf_driver.h => interface_driver.h} (100%) -- 1.7.8.6

Based exclusively on work by Eric Blake in a patch posted with the same subject. However some modifications related to comments and my plans to add another backend. Added WITH_INTERFACE as the only automake variable deciding whether to build the driver and using WITH_NETCF to identify that we're wanting to use the netcf library as the backend. * configure.ac: Added with_interface * src/interface/netcf_driver.c: Renamed.. * src/interface/interface_backend_netcf.c: ..to this to match storage. * src/interface/netcf_driver.h: Renamed.. * src/interface/interface_driver.h: ..to this. * daemon/Makefile.am: Respect WITH_INTERFACE and WITH_NETCF. Signed-off-by: Doug Goldstein <cardoe@cardoe.com> --- configure.ac | 33 ++++++++++++++++++- daemon/Makefile.am | 2 +- daemon/libvirtd.c | 8 ++-- src/Makefile.am | 24 +++++++++++--- .../{netcf_driver.c => interface_backend_netcf.c} | 2 +- .../{netcf_driver.h => interface_driver.h} | 0 tests/virdrivermoduletest.c | 2 +- tools/virsh.c | 4 +- 8 files changed, 58 insertions(+), 17 deletions(-) rename src/interface/{netcf_driver.c => interface_backend_netcf.c} (99%) rename src/interface/{netcf_driver.h => interface_driver.h} (100%) diff --git a/configure.ac b/configure.ac index 028a80d..fd546fc 100644 --- a/configure.ac +++ b/configure.ac @@ -1967,7 +1967,6 @@ AM_CONDITIONAL([WITH_NETCF], [test "$with_netcf" = "yes"]) AC_SUBST([NETCF_CFLAGS]) AC_SUBST([NETCF_LIBS]) - AC_ARG_WITH([secrets], AC_HELP_STRING([--with-secrets], [with local secrets management driver @<:@default=yes@:>@]),[],[with_secrets=yes]) @@ -2806,6 +2805,36 @@ if test "$with_nwfilter" = "yes" ; then fi AM_CONDITIONAL([WITH_NWFILTER], [test "$with_nwfilter" = "yes"]) +dnl check if the interface driver should be compiled +AC_ARG_WITH([interface], + AC_HELP_STRING([--with-interface], + [with host interface driver @<:@default=check@:>@]), [], + [with_interface=check]) + +dnl Don't compile the interface driver without libvirtd +if test "$with_libvirtd" = "no" ; then + with_interface=no +fi + +dnl The interface driver depends on the netcf library +if test "$with_interface:$with_netcf" = "check:yes" ; then + with_interface=yes +fi + +if test "$with_interface:$with_netcf" = "check:no" ; then + with_interface=no +fi + +if test "$with_interface:$with_netcf" = "yes:no" ; then + AC_MSG_ERROR([Requested the Interface driver without netcf support]) +fi + +if test "$with_interface" = "yes" ; then + AC_DEFINE_UNQUOTED([WITH_INTERFACE], [1], + [whether the interface driver is enabled]) +fi +AM_CONDITIONAL([WITH_INTERFACE], [test "$with_interface" = "yes"]) + dnl libblkid is used by several storage drivers; therefore we probe dnl for it unconditionally. AC_ARG_WITH([libblkid], @@ -3017,7 +3046,7 @@ AC_MSG_NOTICE([ Test: $with_test]) AC_MSG_NOTICE([ Remote: $with_remote]) AC_MSG_NOTICE([ Network: $with_network]) AC_MSG_NOTICE([ Libvirtd: $with_libvirtd]) -AC_MSG_NOTICE([ netcf: $with_netcf]) +AC_MSG_NOTICE([Interface: $with_interface]) AC_MSG_NOTICE([ macvtap: $with_macvtap]) AC_MSG_NOTICE([ virtport: $with_virtualport]) AC_MSG_NOTICE([]) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index b00fc13..fbd5a5e 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -147,7 +147,7 @@ if WITH_NETWORK libvirtd_LDADD += ../src/libvirt_driver_network.la endif -if WITH_NETCF +if WITH_INTERFACE libvirtd_LDADD += ../src/libvirt_driver_interface.la endif diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 352d4fe..e8d7ce1 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -75,8 +75,8 @@ # ifdef WITH_NETWORK # include "network/bridge_driver.h" # endif -# ifdef WITH_NETCF -# include "interface/netcf_driver.h" +# ifdef WITH_INTERFACE +# include "interface/interface_driver.h" # endif # ifdef WITH_STORAGE # include "storage/storage_driver.h" @@ -379,7 +379,7 @@ static void daemonInitialize(void) # ifdef WITH_NWFILTER virDriverLoadModule("nwfilter"); # endif -# ifdef WITH_NETCF +# ifdef WITH_INTERFACE virDriverLoadModule("interface"); # endif # ifdef WITH_QEMU @@ -401,7 +401,7 @@ static void daemonInitialize(void) # ifdef WITH_NETWORK networkRegister(); # endif -# ifdef WITH_NETCF +# ifdef WITH_INTERFACE interfaceRegister(); # endif # ifdef WITH_STORAGE diff --git a/src/Makefile.am b/src/Makefile.am index 95e1bea..72c4d6c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -548,8 +548,17 @@ PARALLELS_DRIVER_SOURCES = \ NETWORK_DRIVER_SOURCES = \ network/bridge_driver.h network/bridge_driver.c -INTERFACE_DRIVER_SOURCES = \ - interface/netcf_driver.h interface/netcf_driver.c +INTERFACE_DRIVER_SOURCES = + +if WITH_INTERFACE +INTERFACE_DRIVER_SOURCES += \ + interface/interface_driver.h +endif + +if WITH_NETCF +INTERFACE_DRIVER_SOURCES += \ + interface/interface_backend_netcf.c +endif SECRET_DRIVER_SOURCES = \ secret/secret_driver.h secret/secret_driver.c @@ -1017,7 +1026,7 @@ endif EXTRA_DIST += network/default.xml -if WITH_NETCF +if WITH_INTERFACE if WITH_DRIVER_MODULES mod_LTLIBRARIES += libvirt_driver_interface.la else @@ -1025,10 +1034,13 @@ noinst_LTLIBRARIES += libvirt_driver_interface.la # Stateful, so linked to daemon instead #libvirt_la_BUILT_LIBADD += libvirt_driver_interface.la endif -libvirt_driver_interface_la_CFLAGS = $(NETCF_CFLAGS) \ - -I$(top_srcdir)/src/conf $(AM_CFLAGS) +libvirt_driver_interface_la_CFLAGS = -I$(top_srcdir)/src/conf $(AM_CFLAGS) libvirt_driver_interface_la_LDFLAGS = $(AM_LDFLAGS) -libvirt_driver_interface_la_LIBADD = $(NETCF_LIBS) +libvirt_driver_interface_la_LIBADD = +if WITH_NETCF +libvirt_driver_interface_la_CFLAGS += $(NETCF_CFLAGS) +libvirt_driver_interface_la_LIBADD += $(NETCF_LIBS) +endif if WITH_DRIVER_MODULES libvirt_driver_interface_la_LIBADD += ../gnulib/lib/libgnu.la libvirt_driver_interface_la_LDFLAGS += -module -avoid-version diff --git a/src/interface/netcf_driver.c b/src/interface/interface_backend_netcf.c similarity index 99% rename from src/interface/netcf_driver.c rename to src/interface/interface_backend_netcf.c index 935be66..9285b08 100644 --- a/src/interface/netcf_driver.c +++ b/src/interface/interface_backend_netcf.c @@ -27,7 +27,7 @@ #include "virterror_internal.h" #include "datatypes.h" -#include "netcf_driver.h" +#include "interface_driver.h" #include "interface_conf.h" #include "memory.h" diff --git a/src/interface/netcf_driver.h b/src/interface/interface_driver.h similarity index 100% rename from src/interface/netcf_driver.h rename to src/interface/interface_driver.h diff --git a/tests/virdrivermoduletest.c b/tests/virdrivermoduletest.c index 4d6e91e..8762de4 100644 --- a/tests/virdrivermoduletest.c +++ b/tests/virdrivermoduletest.c @@ -79,7 +79,7 @@ mymain(void) #ifdef WITH_NWFILTER TEST("nwfilter", NULL); #endif -#ifdef WITH_NETCF +#ifdef WITH_INTERFACE TEST("interface", NULL); #endif #ifdef WITH_QEMU diff --git a/tools/virsh.c b/tools/virsh.c index 7a5b92c..b8ec663 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2643,8 +2643,8 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) #ifdef WITH_BRIDGE vshPrint(ctl, " Bridging"); #endif -#ifdef WITH_NETCF - vshPrint(ctl, " Interface"); +#if defined(WITH_INTERFACE) && defined(WITH_NETCF) + vshPrint(ctl, " Interface (netcf)"); #endif #ifdef WITH_NWFILTER vshPrint(ctl, " Nwfilter"); -- 1.7.8.6

On Sun, Sep 02, 2012 at 10:44:16PM -0500, Doug Goldstein wrote:
Based exclusively on work by Eric Blake in a patch posted with the same subject. However some modifications related to comments and my plans to add another backend.
Added WITH_INTERFACE as the only automake variable deciding whether to build the driver and using WITH_NETCF to identify that we're wanting to use the netcf library as the backend.
* configure.ac: Added with_interface * src/interface/netcf_driver.c: Renamed.. * src/interface/interface_backend_netcf.c: ..to this to match storage. * src/interface/netcf_driver.h: Renamed.. * src/interface/interface_driver.h: ..to this. * daemon/Makefile.am: Respect WITH_INTERFACE and WITH_NETCF.
Signed-off-by: Doug Goldstein <cardoe@cardoe.com> --- configure.ac | 33 ++++++++++++++++++- daemon/Makefile.am | 2 +- daemon/libvirtd.c | 8 ++-- src/Makefile.am | 24 +++++++++++--- .../{netcf_driver.c => interface_backend_netcf.c} | 2 +- .../{netcf_driver.h => interface_driver.h} | 0 tests/virdrivermoduletest.c | 2 +- tools/virsh.c | 4 +- 8 files changed, 58 insertions(+), 17 deletions(-) rename src/interface/{netcf_driver.c => interface_backend_netcf.c} (99%) rename src/interface/{netcf_driver.h => interface_driver.h} (100%)
diff --git a/configure.ac b/configure.ac index 028a80d..fd546fc 100644 --- a/configure.ac +++ b/configure.ac @@ -1967,7 +1967,6 @@ AM_CONDITIONAL([WITH_NETCF], [test "$with_netcf" = "yes"]) AC_SUBST([NETCF_CFLAGS]) AC_SUBST([NETCF_LIBS])
- AC_ARG_WITH([secrets], AC_HELP_STRING([--with-secrets], [with local secrets management driver @<:@default=yes@:>@]),[],[with_secrets=yes])
@@ -2806,6 +2805,36 @@ if test "$with_nwfilter" = "yes" ; then fi AM_CONDITIONAL([WITH_NWFILTER], [test "$with_nwfilter" = "yes"])
+dnl check if the interface driver should be compiled +AC_ARG_WITH([interface], + AC_HELP_STRING([--with-interface], + [with host interface driver @<:@default=check@:>@]), [], + [with_interface=check]) + +dnl Don't compile the interface driver without libvirtd +if test "$with_libvirtd" = "no" ; then + with_interface=no +fi + +dnl The interface driver depends on the netcf library +if test "$with_interface:$with_netcf" = "check:yes" ; then + with_interface=yes +fi + +if test "$with_interface:$with_netcf" = "check:no" ; then + with_interface=no +fi + +if test "$with_interface:$with_netcf" = "yes:no" ; then + AC_MSG_ERROR([Requested the Interface driver without netcf support]) +fi + +if test "$with_interface" = "yes" ; then + AC_DEFINE_UNQUOTED([WITH_INTERFACE], [1], + [whether the interface driver is enabled]) +fi +AM_CONDITIONAL([WITH_INTERFACE], [test "$with_interface" = "yes"]) + dnl libblkid is used by several storage drivers; therefore we probe dnl for it unconditionally. AC_ARG_WITH([libblkid], @@ -3017,7 +3046,7 @@ AC_MSG_NOTICE([ Test: $with_test]) AC_MSG_NOTICE([ Remote: $with_remote]) AC_MSG_NOTICE([ Network: $with_network]) AC_MSG_NOTICE([ Libvirtd: $with_libvirtd]) -AC_MSG_NOTICE([ netcf: $with_netcf]) +AC_MSG_NOTICE([Interface: $with_interface]) AC_MSG_NOTICE([ macvtap: $with_macvtap]) AC_MSG_NOTICE([ virtport: $with_virtualport]) AC_MSG_NOTICE([]) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index b00fc13..fbd5a5e 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -147,7 +147,7 @@ if WITH_NETWORK libvirtd_LDADD += ../src/libvirt_driver_network.la endif
-if WITH_NETCF +if WITH_INTERFACE libvirtd_LDADD += ../src/libvirt_driver_interface.la endif
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 352d4fe..e8d7ce1 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -75,8 +75,8 @@ # ifdef WITH_NETWORK # include "network/bridge_driver.h" # endif -# ifdef WITH_NETCF -# include "interface/netcf_driver.h" +# ifdef WITH_INTERFACE +# include "interface/interface_driver.h" # endif # ifdef WITH_STORAGE # include "storage/storage_driver.h" @@ -379,7 +379,7 @@ static void daemonInitialize(void) # ifdef WITH_NWFILTER virDriverLoadModule("nwfilter"); # endif -# ifdef WITH_NETCF +# ifdef WITH_INTERFACE virDriverLoadModule("interface"); # endif # ifdef WITH_QEMU @@ -401,7 +401,7 @@ static void daemonInitialize(void) # ifdef WITH_NETWORK networkRegister(); # endif -# ifdef WITH_NETCF +# ifdef WITH_INTERFACE interfaceRegister(); # endif # ifdef WITH_STORAGE diff --git a/src/Makefile.am b/src/Makefile.am index 95e1bea..72c4d6c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -548,8 +548,17 @@ PARALLELS_DRIVER_SOURCES = \ NETWORK_DRIVER_SOURCES = \ network/bridge_driver.h network/bridge_driver.c
-INTERFACE_DRIVER_SOURCES = \ - interface/netcf_driver.h interface/netcf_driver.c +INTERFACE_DRIVER_SOURCES = + +if WITH_INTERFACE +INTERFACE_DRIVER_SOURCES += \ + interface/interface_driver.h +endif + +if WITH_NETCF +INTERFACE_DRIVER_SOURCES += \ + interface/interface_backend_netcf.c +endif
SECRET_DRIVER_SOURCES = \ secret/secret_driver.h secret/secret_driver.c @@ -1017,7 +1026,7 @@ endif EXTRA_DIST += network/default.xml
-if WITH_NETCF +if WITH_INTERFACE if WITH_DRIVER_MODULES mod_LTLIBRARIES += libvirt_driver_interface.la else @@ -1025,10 +1034,13 @@ noinst_LTLIBRARIES += libvirt_driver_interface.la # Stateful, so linked to daemon instead #libvirt_la_BUILT_LIBADD += libvirt_driver_interface.la endif -libvirt_driver_interface_la_CFLAGS = $(NETCF_CFLAGS) \ - -I$(top_srcdir)/src/conf $(AM_CFLAGS) +libvirt_driver_interface_la_CFLAGS = -I$(top_srcdir)/src/conf $(AM_CFLAGS) libvirt_driver_interface_la_LDFLAGS = $(AM_LDFLAGS) -libvirt_driver_interface_la_LIBADD = $(NETCF_LIBS) +libvirt_driver_interface_la_LIBADD = +if WITH_NETCF +libvirt_driver_interface_la_CFLAGS += $(NETCF_CFLAGS) +libvirt_driver_interface_la_LIBADD += $(NETCF_LIBS) +endif if WITH_DRIVER_MODULES libvirt_driver_interface_la_LIBADD += ../gnulib/lib/libgnu.la libvirt_driver_interface_la_LDFLAGS += -module -avoid-version diff --git a/src/interface/netcf_driver.c b/src/interface/interface_backend_netcf.c similarity index 99% rename from src/interface/netcf_driver.c rename to src/interface/interface_backend_netcf.c index 935be66..9285b08 100644 --- a/src/interface/netcf_driver.c +++ b/src/interface/interface_backend_netcf.c @@ -27,7 +27,7 @@
#include "virterror_internal.h" #include "datatypes.h" -#include "netcf_driver.h" +#include "interface_driver.h" #include "interface_conf.h" #include "memory.h"
diff --git a/src/interface/netcf_driver.h b/src/interface/interface_driver.h similarity index 100% rename from src/interface/netcf_driver.h rename to src/interface/interface_driver.h diff --git a/tests/virdrivermoduletest.c b/tests/virdrivermoduletest.c index 4d6e91e..8762de4 100644 --- a/tests/virdrivermoduletest.c +++ b/tests/virdrivermoduletest.c @@ -79,7 +79,7 @@ mymain(void) #ifdef WITH_NWFILTER TEST("nwfilter", NULL); #endif -#ifdef WITH_NETCF +#ifdef WITH_INTERFACE TEST("interface", NULL); #endif #ifdef WITH_QEMU diff --git a/tools/virsh.c b/tools/virsh.c index 7a5b92c..b8ec663 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2643,8 +2643,8 @@ vshShowVersion(vshControl *ctl ATTRIBUTE_UNUSED) #ifdef WITH_BRIDGE vshPrint(ctl, " Bridging"); #endif -#ifdef WITH_NETCF - vshPrint(ctl, " Interface"); +#if defined(WITH_INTERFACE) && defined(WITH_NETCF) + vshPrint(ctl, " Interface (netcf)"); #endif #ifdef WITH_NWFILTER vshPrint(ctl, " Nwfilter");
Overall, I like the idea to being able to fallback to udev, and this clearly goes in the right direction. I think a patch for libvirt.spec.in replacing the _without_netcf with _without_interface and doing the corresponding adjustments would be needed though. But I recognize you are not in a good situation to make this patch :-) so that should probably be done after commiting that patch set, assuming you get an ACK for example from Laine since that touches his area of expertise :-) Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

Add a read-only udev based backend for virInterface. Useful for distros that do not have netcf support yet. Multiple libvirt based utilities use a HAL based fallback when virInterface is not available which is less than ideal. This implements: * virConnectNumOfInterfaces() * virConnectListInterfaces() * virConnectNumOfDefinedInterfaces() * virConnectListDefinedInterfaces() * virConnectInterfaceLookupByName() * virConnectInterfaceLookupByMACString() Signed-off-by: Doug Goldstein <cardoe@cardoe.com> --- configure.ac | 10 +- src/Makefile.am | 12 +- src/interface/interface_backend_udev.c | 377 ++++++++++++++++++++++++++++++++ 3 files changed, 395 insertions(+), 4 deletions(-) create mode 100644 src/interface/interface_backend_udev.c diff --git a/configure.ac b/configure.ac index fd546fc..c2ad8e2 100644 --- a/configure.ac +++ b/configure.ac @@ -2822,11 +2822,15 @@ if test "$with_interface:$with_netcf" = "check:yes" ; then fi if test "$with_interface:$with_netcf" = "check:no" ; then - with_interface=no + if test "$with_udev" = "yes" ; then + with_interface=yes + else + with_interface=no + fi fi -if test "$with_interface:$with_netcf" = "yes:no" ; then - AC_MSG_ERROR([Requested the Interface driver without netcf support]) +if test "$with_interface:$with_netcf:$with_udev" = "yes:no:no" ; then + AC_MSG_ERROR([Requested the Interface driver without netcf or udev support]) fi if test "$with_interface" = "yes" ; then diff --git a/src/Makefile.am b/src/Makefile.am index 72c4d6c..7143ae0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -553,11 +553,16 @@ INTERFACE_DRIVER_SOURCES = if WITH_INTERFACE INTERFACE_DRIVER_SOURCES += \ interface/interface_driver.h -endif if WITH_NETCF INTERFACE_DRIVER_SOURCES += \ interface/interface_backend_netcf.c +else +if HAVE_UDEV +INTERFACE_DRIVER_SOURCES += \ + interface/interface_backend_udev.c +endif +endif endif SECRET_DRIVER_SOURCES = \ @@ -1040,6 +1045,11 @@ libvirt_driver_interface_la_LIBADD = if WITH_NETCF libvirt_driver_interface_la_CFLAGS += $(NETCF_CFLAGS) libvirt_driver_interface_la_LIBADD += $(NETCF_LIBS) +else +if HAVE_UDEV +libvirt_driver_interface_la_CFLAGS += $(UDEV_CFLAGS) +libvirt_driver_interface_la_LIBADD += $(UDEV_LIBS) +endif endif if WITH_DRIVER_MODULES libvirt_driver_interface_la_LIBADD += ../gnulib/lib/libgnu.la diff --git a/src/interface/interface_backend_udev.c b/src/interface/interface_backend_udev.c new file mode 100644 index 0000000..b1a4be3 --- /dev/null +++ b/src/interface/interface_backend_udev.c @@ -0,0 +1,377 @@ + +#include <config.h> + +#include <libudev.h> + +#include "virterror_internal.h" +#include "datatypes.h" +#include "interface_driver.h" +#include "interface_conf.h" +#include "memory.h" + +#define VIR_FROM_THIS VIR_FROM_INTERFACE + +struct udev_iface_driver { + struct udev *udev; +}; + +enum udev_status { UDEV_IFACE_ACTIVE, UDEV_IFACE_INACTIVE, UDEV_IFACE_ALL }; + +static struct udev_enumerate * +udevIfaceGetDevices(struct udev *udev, enum udev_status status) +{ + struct udev_enumerate *enumerate; + + /* Check input params for sanity */ + if (!udev) + return NULL; + + /* Create a new enumeration to create a list */ + enumerate = udev_enumerate_new(udev); + + if (!enumerate) + return NULL; + + /* Enumerate all network subsystem devices */ + udev_enumerate_add_match_subsystem(enumerate, "net"); + + /* Ignore devices that are part of a bridge */ + udev_enumerate_add_nomatch_sysattr(enumerate, "brport/state", NULL); + + /* State of the device */ + switch (status) { + case UDEV_IFACE_ACTIVE: + udev_enumerate_add_match_sysattr(enumerate, "operstate", "up"); + break; + + case UDEV_IFACE_INACTIVE: + udev_enumerate_add_match_sysattr(enumerate, "operstate", "down"); + break; + + case UDEV_IFACE_ALL: + break; + } + + /* We don't want to see the TUN devices that QEMU creates for other gets + * running on this machine. By saying nomatch NULL, we just are getting + * devices without the tun_flags sysattr. + */ + udev_enumerate_add_nomatch_sysattr(enumerate, "tun_flags", NULL); + + return enumerate; +} + +static virDrvOpenStatus +udevIfaceOpenInterface(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) +{ + struct udev_iface_driver *driverState = NULL; + + if (VIR_ALLOC(driverState) < 0) { + virReportOOMError(); + goto err; + } + + driverState->udev = udev_new(); + if (!driverState->udev) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to create udev context")); + goto err; + } + + conn->interfacePrivateData = driverState; + + return VIR_DRV_OPEN_SUCCESS; + +err: + VIR_FREE(driverState); + + return VIR_DRV_OPEN_ERROR; +} + +static int +udevIfaceCloseInterface(virConnectPtr conn) +{ + struct udev_iface_driver *driverState; + + if (conn->interfacePrivateData != NULL) { + driverState = conn->interfacePrivateData; + + udev_unref(driverState->udev); + + VIR_FREE(driverState); + } + + conn->interfacePrivateData = NULL; + return 0; +} + +static int +udevIfaceNumOfInterfaces(virConnectPtr conn) +{ + struct udev_iface_driver *driverState = conn->interfacePrivateData; + struct udev *udev = udev_ref(driverState->udev); + struct udev_enumerate *enumerate = NULL; + struct udev_list_entry *devices; + struct udev_list_entry *dev_entry; + int count = 0; + + enumerate = udevIfaceGetDevices(udev, UDEV_IFACE_ACTIVE); + + if (!enumerate) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to get number of active interfaces on host")); + return -1; + } + + /* Do the scan to load up the enumeration */ + udev_enumerate_scan_devices(enumerate); + + /* Get a list we can walk */ + devices = udev_enumerate_get_list_entry(enumerate); + + /* For each item so we can count */ + udev_list_entry_foreach(dev_entry, devices) { + count++; + } + + udev_enumerate_unref(enumerate); + + udev_unref(udev); + + return count; +} + +static int +udevIfaceListInterfaces(virConnectPtr conn, char **const names, int names_len) +{ + struct udev_iface_driver *driverState = conn->interfacePrivateData; + struct udev *udev = udev_ref(driverState->udev); + struct udev_enumerate *enumerate = NULL; + struct udev_list_entry *devices; + struct udev_list_entry *dev_entry; + int count = 0; + + enumerate = udevIfaceGetDevices(udev, UDEV_IFACE_ACTIVE); + + if (!enumerate) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to get list of active interfaces on host")); + return -1; + } + + /* Do the scan to load up the enumeration */ + udev_enumerate_scan_devices(enumerate); + + /* Get a list we can walk */ + devices = udev_enumerate_get_list_entry(enumerate); + + /* For each item so we can count */ + udev_list_entry_foreach(dev_entry, devices) { + struct udev_device *dev; + const char *path; + + path = udev_list_entry_get_name(dev_entry); + dev = udev_device_new_from_syspath(udev, path); + names[count] = strdup(udev_device_get_sysname(dev)); + udev_device_unref(dev); + + count++; + if (count > names_len) + break; + } + + udev_enumerate_unref(enumerate); + + udev_unref(udev); + + return count; +} + +static int +udevIfaceNumOfDefinedInterfaces(virConnectPtr conn) +{ + struct udev_iface_driver *driverState = conn->interfacePrivateData; + struct udev *udev = udev_ref(driverState->udev); + struct udev_enumerate *enumerate = NULL; + struct udev_list_entry *devices; + struct udev_list_entry *dev_entry; + int count = 0; + + enumerate = udevIfaceGetDevices(udev, UDEV_IFACE_INACTIVE); + + if (!enumerate) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to get number of defined interfaces on host")); + return -1; + } + + /* Do the scan to load up the enumeration */ + udev_enumerate_scan_devices(enumerate); + + /* Get a list we can walk */ + devices = udev_enumerate_get_list_entry(enumerate); + + /* For each item so we can count */ + udev_list_entry_foreach(dev_entry, devices) { + count++; + } + + udev_enumerate_unref(enumerate); + + udev_unref(udev); + + return count; +} + +static int +udevIfaceListDefinedInterfaces(virConnectPtr conn, + char **const names, + int names_len) +{ + struct udev_iface_driver *driverState = conn->interfacePrivateData; + struct udev *udev = udev_ref(driverState->udev); + struct udev_enumerate *enumerate = NULL; + struct udev_list_entry *devices; + struct udev_list_entry *dev_entry; + int count = 0; + + enumerate = udevIfaceGetDevices(udev, UDEV_IFACE_INACTIVE); + + if (!enumerate) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to get list of defined interfaces on host")); + return -1; + } + + /* Do the scan to load up the enumeration */ + udev_enumerate_scan_devices(enumerate); + + /* Get a list we can walk */ + devices = udev_enumerate_get_list_entry(enumerate); + + /* For each item so we can count */ + udev_list_entry_foreach(dev_entry, devices) { + struct udev_device *dev; + const char *path; + + path = udev_list_entry_get_name(dev_entry); + dev = udev_device_new_from_syspath(udev, path); + names[count] = strdup(udev_device_get_sysname(dev)); + udev_device_unref(dev); + + count++; + if (count > names_len) + break; + } + + udev_enumerate_unref(enumerate); + + udev_unref(udev); + + return count; +} + +static virInterfacePtr +udevIfaceLookupByName(virConnectPtr conn, const char *name) +{ + struct udev_iface_driver *driverState = conn->interfacePrivateData; + struct udev *udev = udev_ref(driverState->udev); + struct udev_device *dev; + const char *macaddr; + virInterfacePtr ret; + + /* get a device reference based on the device name */ + dev = udev_device_new_from_subsystem_sysname(udev, "net", name); + if (!dev) { + virReportError(VIR_ERR_NO_INTERFACE, + _("couldn't find interface named '%s'"), + name); + return NULL; + } + + macaddr = udev_device_get_sysattr_value(dev, "address"); + ret = virGetInterface(conn, name, macaddr); + udev_device_unref(dev); + + udev_unref(udev); + + return ret; +} + +static virInterfacePtr +udevIfaceLookupByMACString(virConnectPtr conn, const char *macstr) +{ + struct udev_iface_driver *driverState = conn->interfacePrivateData; + struct udev *udev = udev_ref(driverState->udev); + struct udev_enumerate *enumerate = NULL; + struct udev_list_entry *dev_entry; + struct udev_device *dev; + const char *name; + virInterfacePtr ret; + + enumerate = udevIfaceGetDevices(udev, UDEV_IFACE_ALL); + + if (!enumerate) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to lookup interface with MAC address '%s'"), + macstr); + return NULL; + } + + /* Match on MAC */ + udev_enumerate_add_match_sysattr(enumerate, "address", macstr); + + /* Do the scan to load up the enumeration */ + udev_enumerate_scan_devices(enumerate); + + /* Get a list we can walk */ + dev_entry = udev_enumerate_get_list_entry(enumerate); + + /* Check that we got something back */ + if (!dev_entry) { + virReportError(VIR_ERR_NO_INTERFACE, + _("couldn't find interface with MAC address '%s'"), + macstr); + return NULL; + } + + /* Check that we didn't get multiple items back */ + if (udev_list_entry_get_next(dev_entry)) { + virReportError(VIR_ERR_MULTIPLE_INTERFACES, + _("the MAC address '%s' matches multiple interfaces"), + macstr); + return NULL; + } + + dev = udev_device_new_from_syspath(udev, udev_list_entry_get_name(dev_entry)); + name = udev_device_get_sysname(dev); + ret = virGetInterface(conn, name, macstr); + udev_device_unref(dev); + + udev_enumerate_unref(enumerate); + + udev_unref(udev); + + return ret; +} +static virInterfaceDriver udevIfaceDriver = { + "Interface", + .open = udevIfaceOpenInterface, + .close = udevIfaceCloseInterface, + .numOfInterfaces = udevIfaceNumOfInterfaces, + .listInterfaces = udevIfaceListInterfaces, + .numOfDefinedInterfaces = udevIfaceNumOfDefinedInterfaces, + .listDefinedInterfaces = udevIfaceListDefinedInterfaces, + .interfaceLookupByName = udevIfaceLookupByName, + .interfaceLookupByMACString = udevIfaceLookupByMACString, +}; + +int +interfaceRegister(void) { + if (virRegisterInterfaceDriver(&udevIfaceDriver) < 0) + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to register udev interface driver")); + return 0; +} -- 1.7.8.6
participants (2)
-
Daniel Veillard
-
Doug Goldstein