From 73bc0114832c6ad66d3b6067aa981109248c7bde Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Wed, 20 May 2009 14:26:49 +0000 Subject: [PATCH] Add the Interface config APIs * configure.in include/libvirt/libvirt.h[.in] include/libvirt/virterror.h qemud/remote.c qemud/remote_dispatch_args.h qemud/remote_dispatch_prototypes.h qemud/remote_dispatch_ret.h qemud/remote_dispatch_table.h qemud/remote_protocol.[chx] src/Makefile.am src/datatypes.c src/datatypes.h src/driver.h src/libvirt.c src/remote_internal.c src/virterror.c src/libvirt_private.syms src/libvirt_public.syms: Add the Interface config APIs and remote stubs for those, patch by Laine Stump * AUTHORS: add Laine daniel --- AUTHORS | 1 + ChangeLog | 13 + configure.in | 35 +- include/libvirt/libvirt.h | 50 +++ include/libvirt/libvirt.h.in | 50 +++ include/libvirt/virterror.h | 4 + qemud/remote.c | 235 +++++++++++ qemud/remote_dispatch_args.h | 8 + qemud/remote_dispatch_prototypes.h | 63 +++ qemud/remote_dispatch_ret.h | 6 + qemud/remote_dispatch_table.h | 45 +++ qemud/remote_protocol.c | 147 +++++++ qemud/remote_protocol.h | 123 ++++++ qemud/remote_protocol.x | 86 ++++- src/Makefile.am | 5 + src/datatypes.c | 160 ++++++++ src/datatypes.h | 31 ++ src/driver.h | 60 +++ src/libvirt.c | 601 +++++++++++++++++++++++++++++ src/libvirt_private.syms | 1 + src/libvirt_public.syms | 14 + src/remote_internal.c | 352 +++++++++++++++++ src/virterror.c | 21 + 23 files changed, 2107 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 228a44c9fb..e4c2a32745 100644 --- a/AUTHORS +++ b/AUTHORS @@ -69,6 +69,7 @@ Patches have also been contributed by: Takahashi Tomohiro Serge E. Hallyn Soren Hansen + Laine Stump [....send patches to get your name here....] diff --git a/ChangeLog b/ChangeLog index 4bce5506e3..e8b44286d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Wed May 20 16:23:10 CEST 2009 Daniel Veillard + + * configure.in include/libvirt/libvirt.h[.in] + include/libvirt/virterror.h qemud/remote.c + qemud/remote_dispatch_args.h qemud/remote_dispatch_prototypes.h + qemud/remote_dispatch_ret.h qemud/remote_dispatch_table.h + qemud/remote_protocol.[chx] src/Makefile.am src/datatypes.c + src/datatypes.h src/driver.h src/libvirt.c src/remote_internal.c + src/virterror.c src/libvirt_private.syms src/libvirt_public.syms: + Add the Interface config APIs and remote stubs for those, patch + by Laine Stump + * AUTHORS: add Laine + Wed May 20 15:35:35 CEST 2009 Daniel Veillard * qemud/qemud.c src/console.c src/network_driver.c diff --git a/configure.in b/configure.in index 50b4761fff..73a02d2b78 100644 --- a/configure.in +++ b/configure.in @@ -28,6 +28,7 @@ GNUTLS_REQUIRED="1.0.25" AVAHI_REQUIRED="0.6.0" POLKIT_REQUIRED="0.6" PARTED_REQUIRED="1.8.0" +NETCF_REQUIRED="0.0.1" dnl Checks for C compiler. AC_PROG_CC @@ -792,9 +793,31 @@ if test "$with_qemu:$with_lxc:$with_network" != "no:no:no"; then fi AM_CONDITIONAL([WITH_BRIDGE], [test "$with_bridge" = "yes"]) -dnl -dnl Storage driver checks -dnl +dnl netcf library +AC_ARG_WITH([netcf], +[ --with-netcf libnetcf support to configure physical host network interfaces], +[], [with_netcf=check]) + +NETCF_CFLAGS= +NETCF_LIBS= +if test "$with_netcf" = "yes" -o "$with_netcf" = "check"; then + PKG_CHECK_MODULES(NETCF, netcf >= $NETCF_REQUIRED, + [with_netcf=yes], [ + if test "$with_netcf" = "check" ; then + with_netcf=no + else + AC_MSG_ERROR( + [You must install libnetcf >= $NETCF_REQUIRED to compile libvirt]) + fi + ]) + if test "$with_netcf" = "yes" ; then + AC_DEFINE_UNQUOTED([WITH_NETCF], 1, + [whether libnetcf is available to configure physical host network interfaces]) + fi +fi +AM_CONDITIONAL([WITH_NETCF], [test "$with_netcf" = "yes"]) +AC_SUBST([NETCF_CFLAGS]) +AC_SUBST([NETCF_LIBS]) AC_ARG_WITH([storage-fs], [ --with-storage-fs with FileSystem backend for the storage driver (on)],[],[with_storage_fs=check]) @@ -1395,6 +1418,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([]) AC_MSG_NOTICE([Storage Drivers]) AC_MSG_NOTICE([]) @@ -1462,6 +1486,11 @@ AC_MSG_NOTICE([ devkit: $DEVKIT_CFLAGS $DEVKIT_LIBS]) else AC_MSG_NOTICE([ devkit: no]) fi +if test "$with_netcf" = "yes" ; then +AC_MSG_NOTICE([ netcf: $NETCF_CFLAGS $NETCF_LIBS]) +else +AC_MSG_NOTICE([ netcf: no]) +fi AC_MSG_NOTICE([]) AC_MSG_NOTICE([Test suite]) AC_MSG_NOTICE([]) diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index 3de3688a25..5835f70c17 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -854,6 +854,56 @@ int virNetworkGetAutostart (virNetworkPtr network, int virNetworkSetAutostart (virNetworkPtr network, int autostart); +/* + * Physical host interface configuration API + */ + +/** + * virInterface: + * + * a virInterface is a private structure representing a virtual interface. + */ +typedef struct _virInterface virInterface; + +/** + * virInterfacePtr: + * + * a virInterfacePtr is pointer to a virInterface private structure, this is the + * type used to reference a virtual interface in the API. + */ +typedef virInterface *virInterfacePtr; + +virConnectPtr virInterfaceGetConnect (virInterfacePtr interface); + +int virConnectNumOfInterfaces (virConnectPtr conn); +int virConnectListInterfaces (virConnectPtr conn, + char **const names, + int maxnames); + +virInterfacePtr virInterfaceLookupByName (virConnectPtr conn, + const char *name); +virInterfacePtr virInterfaceLookupByMACString (virConnectPtr conn, + const char *mac); + +const char* virInterfaceGetName (virInterfacePtr interface); +const char* virInterfaceGetMACString (virInterfacePtr interface); + +char * virInterfaceGetXMLDesc (virInterfacePtr interface, + unsigned int flags); +virInterfacePtr virInterfaceDefineXML (virConnectPtr conn, + const char *xmlDesc, + unsigned int flags); + +int virInterfaceUndefine (virInterfacePtr interface); + +int virInterfaceCreate (virInterfacePtr interface, + unsigned int flags); + +int virInterfaceDestroy (virInterfacePtr interface, + unsigned int flags); + +int virInterfaceRef (virInterfacePtr interface); +int virInterfaceFree (virInterfacePtr interface); /** * virStoragePool: diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 6b0c1d8e70..60048aec96 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -854,6 +854,56 @@ int virNetworkGetAutostart (virNetworkPtr network, int virNetworkSetAutostart (virNetworkPtr network, int autostart); +/* + * Physical host interface configuration API + */ + +/** + * virInterface: + * + * a virInterface is a private structure representing a virtual interface. + */ +typedef struct _virInterface virInterface; + +/** + * virInterfacePtr: + * + * a virInterfacePtr is pointer to a virInterface private structure, this is the + * type used to reference a virtual interface in the API. + */ +typedef virInterface *virInterfacePtr; + +virConnectPtr virInterfaceGetConnect (virInterfacePtr interface); + +int virConnectNumOfInterfaces (virConnectPtr conn); +int virConnectListInterfaces (virConnectPtr conn, + char **const names, + int maxnames); + +virInterfacePtr virInterfaceLookupByName (virConnectPtr conn, + const char *name); +virInterfacePtr virInterfaceLookupByMACString (virConnectPtr conn, + const char *mac); + +const char* virInterfaceGetName (virInterfacePtr interface); +const char* virInterfaceGetMACString (virInterfacePtr interface); + +char * virInterfaceGetXMLDesc (virInterfacePtr interface, + unsigned int flags); +virInterfacePtr virInterfaceDefineXML (virConnectPtr conn, + const char *xmlDesc, + unsigned int flags); + +int virInterfaceUndefine (virInterfacePtr interface); + +int virInterfaceCreate (virInterfacePtr interface, + unsigned int flags); + +int virInterfaceDestroy (virInterfacePtr interface, + unsigned int flags); + +int virInterfaceRef (virInterfacePtr interface); +int virInterfaceFree (virInterfacePtr interface); /** * virStoragePool: diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 4677ebc1b2..3613ac2995 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -63,6 +63,7 @@ typedef enum { VIR_FROM_XEN_INOTIFY, /* Error from xen inotify layer */ VIR_FROM_SECURITY, /* Error from security framework */ VIR_FROM_VBOX, /* Error from VirtualBox driver */ + VIR_FROM_INTERFACE, /* Error when operating on an interface */ } virErrorDomain; @@ -158,6 +159,9 @@ typedef enum { VIR_ERR_NO_NODE_DEVICE,/* node device not found */ VIR_ERR_NO_SECURITY_MODEL, /* security model not found */ VIR_ERR_OPERATION_INVALID, /* operation is not applicable at this time */ + VIR_WAR_NO_INTERFACE, /* failed to start interface driver */ + VIR_ERR_NO_INTERFACE, /* interface driver not running */ + VIR_ERR_INVALID_INTERFACE, /* invalid interface object */ } virErrorNumber; /** diff --git a/qemud/remote.c b/qemud/remote.c index f9aa926f4f..8716017b86 100644 --- a/qemud/remote.c +++ b/qemud/remote.c @@ -62,10 +62,12 @@ static void remoteDispatchFormatError (remote_error *rerr, ATTRIBUTE_FORMAT(printf, 2, 3); static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain); static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network); +static virInterfacePtr get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface interface); static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool); static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol); static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src); static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src); +static void make_nonnull_interface (remote_nonnull_interface *interface_dst, virInterfacePtr interface_src); static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src); static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src); static void make_nonnull_node_device (remote_nonnull_node_device *dev_dst, virNodeDevicePtr dev_src); @@ -2561,6 +2563,225 @@ remoteDispatchNumOfNetworks (struct qemud_server *server ATTRIBUTE_UNUSED, } +/*-------------------------------------------------------------*/ +static int +remoteDispatchNumOfInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + void *args ATTRIBUTE_UNUSED, + remote_num_of_interfaces_ret *ret) +{ + + ret->num = virConnectNumOfInterfaces (conn); + if (ret->num == -1) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + return 0; +} + +static int +remoteDispatchListInterfaces (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_list_interfaces_args *args, + remote_list_interfaces_ret *ret) +{ + + if (args->maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) { + remoteDispatchFormatError (rerr, + "%s", _("maxnames > REMOTE_INTERFACE_NAME_LIST_MAX")); + return -1; + } + + /* Allocate return buffer. */ + if (VIR_ALLOC_N(ret->names.names_val, args->maxnames) < 0) { + remoteDispatchOOMError(rerr); + return -1; + } + + ret->names.names_len = + virConnectListInterfaces (conn, + ret->names.names_val, args->maxnames); + if (ret->names.names_len == -1) { + VIR_FREE(ret->names.names_len); + remoteDispatchConnError(rerr, conn); + return -1; + } + + return 0; +} + +static int +remoteDispatchInterfaceLookupByName (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_interface_lookup_by_name_args *args, + remote_interface_lookup_by_name_ret *ret) +{ + virInterfacePtr interface; + + interface = virInterfaceLookupByName (conn, args->name); + if (interface == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + make_nonnull_interface (&ret->interface, interface); + virInterfaceFree(interface); + return 0; +} + +static int +remoteDispatchInterfaceLookupByMacString (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_interface_lookup_by_mac_string_args *args, + remote_interface_lookup_by_mac_string_ret *ret) +{ + virInterfacePtr interface; + + interface = virInterfaceLookupByMACString (conn, args->mac); + if (interface == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + make_nonnull_interface (&ret->interface, interface); + virInterfaceFree(interface); + return 0; +} + +static int +remoteDispatchInterfaceGetXmlDesc (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_interface_get_xml_desc_args *args, + remote_interface_get_xml_desc_ret *ret) +{ + virInterfacePtr interface; + + interface = get_nonnull_interface (conn, args->interface); + if (interface == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + /* remoteDispatchClientRequest will free this. */ + ret->xml = virInterfaceGetXMLDesc (interface, args->flags); + if (!ret->xml) { + virInterfaceFree(interface); + remoteDispatchConnError(rerr, conn); + return -1; + } + virInterfaceFree(interface); + return 0; +} + +static int +remoteDispatchInterfaceDefineXml (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_interface_define_xml_args *args, + remote_interface_define_xml_ret *ret) +{ + virInterfacePtr interface; + + interface = virInterfaceDefineXML (conn, args->xml, args->flags); + if (interface == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + make_nonnull_interface (&ret->interface, interface); + virInterfaceFree(interface); + return 0; +} + +static int +remoteDispatchInterfaceUndefine (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_interface_undefine_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virInterfacePtr interface; + + interface = get_nonnull_interface (conn, args->interface); + if (interface == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (virInterfaceUndefine (interface) == -1) { + virInterfaceFree(interface); + remoteDispatchConnError(rerr, conn); + return -1; + } + virInterfaceFree(interface); + return 0; +} + +static int +remoteDispatchInterfaceCreate (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_interface_create_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virInterfacePtr interface; + + interface = get_nonnull_interface (conn, args->interface); + if (interface == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (virInterfaceCreate (interface, args->flags) == -1) { + virInterfaceFree(interface); + remoteDispatchConnError(rerr, conn); + return -1; + } + virInterfaceFree(interface); + return 0; +} + +static int +remoteDispatchInterfaceDestroy (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_interface_destroy_args *args, + void *ret ATTRIBUTE_UNUSED) +{ + virInterfacePtr interface; + + interface = get_nonnull_interface (conn, args->interface); + if (interface == NULL) { + remoteDispatchConnError(rerr, conn); + return -1; + } + + if (virInterfaceDestroy (interface, args->flags) == -1) { + virInterfaceFree(interface); + remoteDispatchConnError(rerr, conn); + return -1; + } + virInterfaceFree(interface); + return 0; +} + +/*-------------------------------------------------------------*/ + static int remoteDispatchAuthList (struct qemud_server *server, struct qemud_client *client, @@ -4560,6 +4781,12 @@ get_nonnull_network (virConnectPtr conn, remote_nonnull_network network) return virGetNetwork (conn, network.name, BAD_CAST network.uuid); } +static virInterfacePtr +get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface interface) +{ + return virGetInterface (conn, interface.name, interface.mac); +} + static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool) { @@ -4590,6 +4817,14 @@ make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src) memcpy (net_dst->uuid, net_src->uuid, VIR_UUID_BUFLEN); } +static void +make_nonnull_interface (remote_nonnull_interface *interface_dst, + virInterfacePtr interface_src) +{ + interface_dst->name = strdup (interface_src->name); + interface_dst->mac = strdup (interface_src->mac); +} + static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src) { diff --git a/qemud/remote_dispatch_args.h b/qemud/remote_dispatch_args.h index 8f8b05b57f..27b840f7ad 100644 --- a/qemud/remote_dispatch_args.h +++ b/qemud/remote_dispatch_args.h @@ -106,3 +106,11 @@ remote_node_device_create_xml_args val_remote_node_device_create_xml_args; remote_node_device_destroy_args val_remote_node_device_destroy_args; remote_storage_vol_create_xml_from_args val_remote_storage_vol_create_xml_from_args; + remote_list_interfaces_args val_remote_list_interfaces_args; + remote_interface_lookup_by_name_args val_remote_interface_lookup_by_name_args; + remote_interface_lookup_by_mac_string_args val_remote_interface_lookup_by_mac_string_args; + remote_interface_get_xml_desc_args val_remote_interface_get_xml_desc_args; + remote_interface_define_xml_args val_remote_interface_define_xml_args; + remote_interface_undefine_args val_remote_interface_undefine_args; + remote_interface_create_args val_remote_interface_create_args; + remote_interface_destroy_args val_remote_interface_destroy_args; diff --git a/qemud/remote_dispatch_prototypes.h b/qemud/remote_dispatch_prototypes.h index 1a2d98b7cb..9918aee298 100644 --- a/qemud/remote_dispatch_prototypes.h +++ b/qemud/remote_dispatch_prototypes.h @@ -408,6 +408,55 @@ static int remoteDispatchGetVersion( remote_error *err, void *args, remote_get_version_ret *ret); +static int remoteDispatchInterfaceCreate( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_interface_create_args *args, + void *ret); +static int remoteDispatchInterfaceDefineXml( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_interface_define_xml_args *args, + remote_interface_define_xml_ret *ret); +static int remoteDispatchInterfaceDestroy( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_interface_destroy_args *args, + void *ret); +static int remoteDispatchInterfaceGetXmlDesc( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_interface_get_xml_desc_args *args, + remote_interface_get_xml_desc_ret *ret); +static int remoteDispatchInterfaceLookupByMacString( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_interface_lookup_by_mac_string_args *args, + remote_interface_lookup_by_mac_string_ret *ret); +static int remoteDispatchInterfaceLookupByName( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_interface_lookup_by_name_args *args, + remote_interface_lookup_by_name_ret *ret); +static int remoteDispatchInterfaceUndefine( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_interface_undefine_args *args, + void *ret); static int remoteDispatchListDefinedDomains( struct qemud_server *server, struct qemud_client *client, @@ -436,6 +485,13 @@ static int remoteDispatchListDomains( remote_error *err, remote_list_domains_args *args, remote_list_domains_ret *ret); +static int remoteDispatchListInterfaces( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_list_interfaces_args *args, + remote_list_interfaces_ret *ret); static int remoteDispatchListNetworks( struct qemud_server *server, struct qemud_client *client, @@ -667,6 +723,13 @@ static int remoteDispatchNumOfDomains( remote_error *err, void *args, remote_num_of_domains_ret *ret); +static int remoteDispatchNumOfInterfaces( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + void *args, + remote_num_of_interfaces_ret *ret); static int remoteDispatchNumOfNetworks( struct qemud_server *server, struct qemud_client *client, diff --git a/qemud/remote_dispatch_ret.h b/qemud/remote_dispatch_ret.h index 75e2ca6413..45021822a6 100644 --- a/qemud/remote_dispatch_ret.h +++ b/qemud/remote_dispatch_ret.h @@ -90,3 +90,9 @@ remote_node_get_security_model_ret val_remote_node_get_security_model_ret; remote_node_device_create_xml_ret val_remote_node_device_create_xml_ret; remote_storage_vol_create_xml_from_ret val_remote_storage_vol_create_xml_from_ret; + remote_num_of_interfaces_ret val_remote_num_of_interfaces_ret; + remote_list_interfaces_ret val_remote_list_interfaces_ret; + remote_interface_lookup_by_name_ret val_remote_interface_lookup_by_name_ret; + remote_interface_lookup_by_mac_string_ret val_remote_interface_lookup_by_mac_string_ret; + remote_interface_get_xml_desc_ret val_remote_interface_get_xml_desc_ret; + remote_interface_define_xml_ret val_remote_interface_define_xml_ret; diff --git a/qemud/remote_dispatch_table.h b/qemud/remote_dispatch_table.h index e601a6c812..92e0d40e42 100644 --- a/qemud/remote_dispatch_table.h +++ b/qemud/remote_dispatch_table.h @@ -632,3 +632,48 @@ .args_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_from_args, .ret_filter = (xdrproc_t) xdr_remote_storage_vol_create_xml_from_ret, }, +{ /* NumOfInterfaces => 126 */ + .fn = (dispatch_fn) remoteDispatchNumOfInterfaces, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_remote_num_of_interfaces_ret, +}, +{ /* ListInterfaces => 127 */ + .fn = (dispatch_fn) remoteDispatchListInterfaces, + .args_filter = (xdrproc_t) xdr_remote_list_interfaces_args, + .ret_filter = (xdrproc_t) xdr_remote_list_interfaces_ret, +}, +{ /* InterfaceLookupByName => 128 */ + .fn = (dispatch_fn) remoteDispatchInterfaceLookupByName, + .args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_name_args, + .ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_name_ret, +}, +{ /* InterfaceLookupByMacString => 129 */ + .fn = (dispatch_fn) remoteDispatchInterfaceLookupByMacString, + .args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args, + .ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret, +}, +{ /* InterfaceGetXmlDesc => 130 */ + .fn = (dispatch_fn) remoteDispatchInterfaceGetXmlDesc, + .args_filter = (xdrproc_t) xdr_remote_interface_get_xml_desc_args, + .ret_filter = (xdrproc_t) xdr_remote_interface_get_xml_desc_ret, +}, +{ /* InterfaceDefineXml => 131 */ + .fn = (dispatch_fn) remoteDispatchInterfaceDefineXml, + .args_filter = (xdrproc_t) xdr_remote_interface_define_xml_args, + .ret_filter = (xdrproc_t) xdr_remote_interface_define_xml_ret, +}, +{ /* InterfaceUndefine => 132 */ + .fn = (dispatch_fn) remoteDispatchInterfaceUndefine, + .args_filter = (xdrproc_t) xdr_remote_interface_undefine_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* InterfaceCreate => 133 */ + .fn = (dispatch_fn) remoteDispatchInterfaceCreate, + .args_filter = (xdrproc_t) xdr_remote_interface_create_args, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* InterfaceDestroy => 134 */ + .fn = (dispatch_fn) remoteDispatchInterfaceDestroy, + .args_filter = (xdrproc_t) xdr_remote_interface_destroy_args, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/qemud/remote_protocol.c b/qemud/remote_protocol.c index e9b84aa026..a15db3139d 100644 --- a/qemud/remote_protocol.c +++ b/qemud/remote_protocol.c @@ -59,6 +59,17 @@ xdr_remote_nonnull_network (XDR *xdrs, remote_nonnull_network *objp) return TRUE; } +bool_t +xdr_remote_nonnull_interface (XDR *xdrs, remote_nonnull_interface *objp) +{ + + if (!xdr_remote_nonnull_string (xdrs, &objp->name)) + return FALSE; + if (!xdr_remote_nonnull_string (xdrs, &objp->mac)) + return FALSE; + return TRUE; +} + bool_t xdr_remote_nonnull_storage_pool (XDR *xdrs, remote_nonnull_storage_pool *objp) { @@ -1477,6 +1488,142 @@ xdr_remote_network_set_autostart_args (XDR *xdrs, remote_network_set_autostart_a return TRUE; } +bool_t +xdr_remote_num_of_interfaces_ret (XDR *xdrs, remote_num_of_interfaces_ret *objp) +{ + + if (!xdr_int (xdrs, &objp->num)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_list_interfaces_args (XDR *xdrs, remote_list_interfaces_args *objp) +{ + + if (!xdr_int (xdrs, &objp->maxnames)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_list_interfaces_ret (XDR *xdrs, remote_list_interfaces_ret *objp) +{ + char **objp_cpp0 = (char **) (void *) &objp->names.names_val; + + if (!xdr_array (xdrs, objp_cpp0, (u_int *) &objp->names.names_len, REMOTE_INTERFACE_NAME_LIST_MAX, + sizeof (remote_nonnull_string), (xdrproc_t) xdr_remote_nonnull_string)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_lookup_by_name_args (XDR *xdrs, remote_interface_lookup_by_name_args *objp) +{ + + if (!xdr_remote_nonnull_string (xdrs, &objp->name)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_lookup_by_name_ret (XDR *xdrs, remote_interface_lookup_by_name_ret *objp) +{ + + if (!xdr_remote_nonnull_interface (xdrs, &objp->interface)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_lookup_by_mac_string_args (XDR *xdrs, remote_interface_lookup_by_mac_string_args *objp) +{ + + if (!xdr_remote_nonnull_string (xdrs, &objp->mac)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_lookup_by_mac_string_ret (XDR *xdrs, remote_interface_lookup_by_mac_string_ret *objp) +{ + + if (!xdr_remote_nonnull_interface (xdrs, &objp->interface)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_get_xml_desc_args (XDR *xdrs, remote_interface_get_xml_desc_args *objp) +{ + + if (!xdr_remote_nonnull_interface (xdrs, &objp->interface)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_get_xml_desc_ret (XDR *xdrs, remote_interface_get_xml_desc_ret *objp) +{ + + if (!xdr_remote_nonnull_string (xdrs, &objp->xml)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_define_xml_args (XDR *xdrs, remote_interface_define_xml_args *objp) +{ + + if (!xdr_remote_nonnull_string (xdrs, &objp->xml)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_define_xml_ret (XDR *xdrs, remote_interface_define_xml_ret *objp) +{ + + if (!xdr_remote_nonnull_interface (xdrs, &objp->interface)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_undefine_args (XDR *xdrs, remote_interface_undefine_args *objp) +{ + + if (!xdr_remote_nonnull_interface (xdrs, &objp->interface)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_create_args (XDR *xdrs, remote_interface_create_args *objp) +{ + + if (!xdr_remote_nonnull_interface (xdrs, &objp->interface)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_destroy_args (XDR *xdrs, remote_interface_destroy_args *objp) +{ + + if (!xdr_remote_nonnull_interface (xdrs, &objp->interface)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + bool_t xdr_remote_auth_list_ret (XDR *xdrs, remote_auth_list_ret *objp) { diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h index 9ee17a966f..280cba613b 100644 --- a/qemud/remote_protocol.h +++ b/qemud/remote_protocol.h @@ -28,6 +28,7 @@ typedef remote_nonnull_string *remote_string; #define REMOTE_CPUMAPS_MAX 16384 #define REMOTE_MIGRATE_COOKIE_MAX 256 #define REMOTE_NETWORK_NAME_LIST_MAX 256 +#define REMOTE_INTERFACE_NAME_LIST_MAX 256 #define REMOTE_STORAGE_POOL_NAME_LIST_MAX 256 #define REMOTE_STORAGE_VOL_NAME_LIST_MAX 1024 #define REMOTE_NODE_DEVICE_NAME_LIST_MAX 16384 @@ -57,6 +58,12 @@ struct remote_nonnull_network { }; typedef struct remote_nonnull_network remote_nonnull_network; +struct remote_nonnull_interface { + remote_nonnull_string name; + remote_nonnull_string mac; +}; +typedef struct remote_nonnull_interface remote_nonnull_interface; + struct remote_nonnull_storage_pool { remote_nonnull_string name; remote_uuid uuid; @@ -822,6 +829,83 @@ struct remote_network_set_autostart_args { }; typedef struct remote_network_set_autostart_args remote_network_set_autostart_args; +struct remote_num_of_interfaces_ret { + int num; +}; +typedef struct remote_num_of_interfaces_ret remote_num_of_interfaces_ret; + +struct remote_list_interfaces_args { + int maxnames; +}; +typedef struct remote_list_interfaces_args remote_list_interfaces_args; + +struct remote_list_interfaces_ret { + struct { + u_int names_len; + remote_nonnull_string *names_val; + } names; +}; +typedef struct remote_list_interfaces_ret remote_list_interfaces_ret; + +struct remote_interface_lookup_by_name_args { + remote_nonnull_string name; +}; +typedef struct remote_interface_lookup_by_name_args remote_interface_lookup_by_name_args; + +struct remote_interface_lookup_by_name_ret { + remote_nonnull_interface interface; +}; +typedef struct remote_interface_lookup_by_name_ret remote_interface_lookup_by_name_ret; + +struct remote_interface_lookup_by_mac_string_args { + remote_nonnull_string mac; +}; +typedef struct remote_interface_lookup_by_mac_string_args remote_interface_lookup_by_mac_string_args; + +struct remote_interface_lookup_by_mac_string_ret { + remote_nonnull_interface interface; +}; +typedef struct remote_interface_lookup_by_mac_string_ret remote_interface_lookup_by_mac_string_ret; + +struct remote_interface_get_xml_desc_args { + remote_nonnull_interface interface; + u_int flags; +}; +typedef struct remote_interface_get_xml_desc_args remote_interface_get_xml_desc_args; + +struct remote_interface_get_xml_desc_ret { + remote_nonnull_string xml; +}; +typedef struct remote_interface_get_xml_desc_ret remote_interface_get_xml_desc_ret; + +struct remote_interface_define_xml_args { + remote_nonnull_string xml; + u_int flags; +}; +typedef struct remote_interface_define_xml_args remote_interface_define_xml_args; + +struct remote_interface_define_xml_ret { + remote_nonnull_interface interface; +}; +typedef struct remote_interface_define_xml_ret remote_interface_define_xml_ret; + +struct remote_interface_undefine_args { + remote_nonnull_interface interface; +}; +typedef struct remote_interface_undefine_args remote_interface_undefine_args; + +struct remote_interface_create_args { + remote_nonnull_interface interface; + u_int flags; +}; +typedef struct remote_interface_create_args remote_interface_create_args; + +struct remote_interface_destroy_args { + remote_nonnull_interface interface; + u_int flags; +}; +typedef struct remote_interface_destroy_args remote_interface_destroy_args; + struct remote_auth_list_ret { struct { u_int types_len; @@ -1429,6 +1513,15 @@ enum remote_procedure { REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123, REMOTE_PROC_NODE_DEVICE_DESTROY = 124, REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125, + REMOTE_PROC_NUM_OF_INTERFACES = 126, + REMOTE_PROC_LIST_INTERFACES = 127, + REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, + REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129, + REMOTE_PROC_INTERFACE_GET_XML_DESC = 130, + REMOTE_PROC_INTERFACE_DEFINE_XML = 131, + REMOTE_PROC_INTERFACE_UNDEFINE = 132, + REMOTE_PROC_INTERFACE_CREATE = 133, + REMOTE_PROC_INTERFACE_DESTROY = 134, }; typedef enum remote_procedure remote_procedure; @@ -1464,6 +1557,7 @@ extern bool_t xdr_remote_string (XDR *, remote_string*); extern bool_t xdr_remote_uuid (XDR *, remote_uuid); extern bool_t xdr_remote_nonnull_domain (XDR *, remote_nonnull_domain*); extern bool_t xdr_remote_nonnull_network (XDR *, remote_nonnull_network*); +extern bool_t xdr_remote_nonnull_interface (XDR *, remote_nonnull_interface*); extern bool_t xdr_remote_nonnull_storage_pool (XDR *, remote_nonnull_storage_pool*); extern bool_t xdr_remote_nonnull_storage_vol (XDR *, remote_nonnull_storage_vol*); extern bool_t xdr_remote_nonnull_node_device (XDR *, remote_nonnull_node_device*); @@ -1587,6 +1681,20 @@ extern bool_t xdr_remote_network_get_bridge_name_ret (XDR *, remote_network_get extern bool_t xdr_remote_network_get_autostart_args (XDR *, remote_network_get_autostart_args*); extern bool_t xdr_remote_network_get_autostart_ret (XDR *, remote_network_get_autostart_ret*); extern bool_t xdr_remote_network_set_autostart_args (XDR *, remote_network_set_autostart_args*); +extern bool_t xdr_remote_num_of_interfaces_ret (XDR *, remote_num_of_interfaces_ret*); +extern bool_t xdr_remote_list_interfaces_args (XDR *, remote_list_interfaces_args*); +extern bool_t xdr_remote_list_interfaces_ret (XDR *, remote_list_interfaces_ret*); +extern bool_t xdr_remote_interface_lookup_by_name_args (XDR *, remote_interface_lookup_by_name_args*); +extern bool_t xdr_remote_interface_lookup_by_name_ret (XDR *, remote_interface_lookup_by_name_ret*); +extern bool_t xdr_remote_interface_lookup_by_mac_string_args (XDR *, remote_interface_lookup_by_mac_string_args*); +extern bool_t xdr_remote_interface_lookup_by_mac_string_ret (XDR *, remote_interface_lookup_by_mac_string_ret*); +extern bool_t xdr_remote_interface_get_xml_desc_args (XDR *, remote_interface_get_xml_desc_args*); +extern bool_t xdr_remote_interface_get_xml_desc_ret (XDR *, remote_interface_get_xml_desc_ret*); +extern bool_t xdr_remote_interface_define_xml_args (XDR *, remote_interface_define_xml_args*); +extern bool_t xdr_remote_interface_define_xml_ret (XDR *, remote_interface_define_xml_ret*); +extern bool_t xdr_remote_interface_undefine_args (XDR *, remote_interface_undefine_args*); +extern bool_t xdr_remote_interface_create_args (XDR *, remote_interface_create_args*); +extern bool_t xdr_remote_interface_destroy_args (XDR *, remote_interface_destroy_args*); extern bool_t xdr_remote_auth_list_ret (XDR *, remote_auth_list_ret*); extern bool_t xdr_remote_auth_sasl_init_ret (XDR *, remote_auth_sasl_init_ret*); extern bool_t xdr_remote_auth_sasl_start_args (XDR *, remote_auth_sasl_start_args*); @@ -1680,6 +1788,7 @@ extern bool_t xdr_remote_string (); extern bool_t xdr_remote_uuid (); extern bool_t xdr_remote_nonnull_domain (); extern bool_t xdr_remote_nonnull_network (); +extern bool_t xdr_remote_nonnull_interface (); extern bool_t xdr_remote_nonnull_storage_pool (); extern bool_t xdr_remote_nonnull_storage_vol (); extern bool_t xdr_remote_nonnull_node_device (); @@ -1803,6 +1912,20 @@ extern bool_t xdr_remote_network_get_bridge_name_ret (); extern bool_t xdr_remote_network_get_autostart_args (); extern bool_t xdr_remote_network_get_autostart_ret (); extern bool_t xdr_remote_network_set_autostart_args (); +extern bool_t xdr_remote_num_of_interfaces_ret (); +extern bool_t xdr_remote_list_interfaces_args (); +extern bool_t xdr_remote_list_interfaces_ret (); +extern bool_t xdr_remote_interface_lookup_by_name_args (); +extern bool_t xdr_remote_interface_lookup_by_name_ret (); +extern bool_t xdr_remote_interface_lookup_by_mac_string_args (); +extern bool_t xdr_remote_interface_lookup_by_mac_string_ret (); +extern bool_t xdr_remote_interface_get_xml_desc_args (); +extern bool_t xdr_remote_interface_get_xml_desc_ret (); +extern bool_t xdr_remote_interface_define_xml_args (); +extern bool_t xdr_remote_interface_define_xml_ret (); +extern bool_t xdr_remote_interface_undefine_args (); +extern bool_t xdr_remote_interface_create_args (); +extern bool_t xdr_remote_interface_destroy_args (); extern bool_t xdr_remote_auth_list_ret (); extern bool_t xdr_remote_auth_sasl_init_ret (); extern bool_t xdr_remote_auth_sasl_start_args (); diff --git a/qemud/remote_protocol.x b/qemud/remote_protocol.x index 1f27350938..0bd7e6f7d6 100644 --- a/qemud/remote_protocol.x +++ b/qemud/remote_protocol.x @@ -79,6 +79,9 @@ const REMOTE_MIGRATE_COOKIE_MAX = 256; /* Upper limit on lists of network names. */ const REMOTE_NETWORK_NAME_LIST_MAX = 256; +/* Upper limit on lists of interface names. */ +const REMOTE_INTERFACE_NAME_LIST_MAX = 256; + /* Upper limit on lists of storage pool names. */ const REMOTE_STORAGE_POOL_NAME_LIST_MAX = 256; @@ -146,6 +149,12 @@ struct remote_nonnull_network { remote_uuid uuid; }; +/* An interface which may not be NULL. */ +struct remote_nonnull_interface { + remote_nonnull_string name; + remote_nonnull_string mac; +}; + /* A storage pool which may not be NULL. */ struct remote_nonnull_storage_pool { remote_nonnull_string name; @@ -770,6 +779,71 @@ struct remote_network_set_autostart_args { }; +/* Interface calls: */ + +struct remote_num_of_interfaces_ret { + int num; +}; + +struct remote_list_interfaces_args { + int maxnames; +}; + +struct remote_list_interfaces_ret { + remote_nonnull_string names; +}; + +struct remote_interface_lookup_by_name_args { + remote_nonnull_string name; +}; + +struct remote_interface_lookup_by_name_ret { + remote_nonnull_interface interface; +}; + +struct remote_interface_lookup_by_mac_string_args { + remote_nonnull_string mac; +}; + +struct remote_interface_lookup_by_mac_string_ret { + remote_nonnull_interface interface; +}; + +struct remote_interface_get_xml_desc_args { + remote_nonnull_interface interface; + unsigned int flags; +}; + +struct remote_interface_get_xml_desc_ret { + remote_nonnull_string xml; +}; + +struct remote_interface_define_xml_args { + remote_nonnull_string xml; + unsigned int flags; +}; + +struct remote_interface_define_xml_ret { + remote_nonnull_interface interface; +}; + +struct remote_interface_undefine_args { + remote_nonnull_interface interface; +}; + +struct remote_interface_create_args { + remote_nonnull_interface interface; + unsigned int flags; +}; + +struct remote_interface_destroy_args { + remote_nonnull_interface interface; + unsigned int flags; +}; + + +/* Auth calls: */ + struct remote_auth_list_ret { remote_auth_type types; }; @@ -1299,7 +1373,17 @@ enum remote_procedure { REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123, REMOTE_PROC_NODE_DEVICE_DESTROY = 124, - REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125 + REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125, + + REMOTE_PROC_NUM_OF_INTERFACES = 126, + REMOTE_PROC_LIST_INTERFACES = 127, + REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, + REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129, + REMOTE_PROC_INTERFACE_GET_XML_DESC = 130, + REMOTE_PROC_INTERFACE_DEFINE_XML = 131, + REMOTE_PROC_INTERFACE_UNDEFINE = 132, + REMOTE_PROC_INTERFACE_CREATE = 133, + REMOTE_PROC_INTERFACE_DESTROY = 134 }; /* Custom RPC structure. */ diff --git a/src/Makefile.am b/src/Makefile.am index 5490089a27..81331686c9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -352,6 +352,11 @@ endif libvirt_driver_network_la_SOURCES = $(NETWORK_DRIVER_SOURCES) endif +if WITH_NETCF +libvirt_driver_interface_la_CFLAGS = $(NETCF_CFLAGS) +libvirt_driver_interface_la_LDFLAGS = $(NETCF_LIBS) +endif + # Needed to keep automake quiet about conditionals libvirt_driver_storage_la_SOURCES = if WITH_STORAGE_DIR diff --git a/src/datatypes.c b/src/datatypes.c index eceb839b3f..e1227aaac5 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -66,6 +66,20 @@ virNetworkFreeName(virNetworkPtr network, const char *name ATTRIBUTE_UNUSED) return (virUnrefNetwork(network)); } +/** + * virInterfaceFreeName: + * @interface: a interface object + * + * Destroy the interface object, this is just used by the interface hash callback. + * + * Returns 0 in case of success and -1 in case of failure. + */ +static int +virInterfaceFreeName(virInterfacePtr interface, const char *name ATTRIBUTE_UNUSED) +{ + return (virUnrefInterface(interface)); +} + /** * virStoragePoolFreeName: * @pool: a pool object @@ -119,12 +133,16 @@ virGetConnect(void) { ret->networkDriver = NULL; ret->privateData = NULL; ret->networkPrivateData = NULL; + ret->interfacePrivateData = NULL; ret->domains = virHashCreate(20); if (ret->domains == NULL) goto failed; ret->networks = virHashCreate(20); if (ret->networks == NULL) goto failed; + ret->interfaces = virHashCreate(20); + if (ret->interfaces == NULL) + goto failed; ret->storagePools = virHashCreate(20); if (ret->storagePools == NULL) goto failed; @@ -144,6 +162,8 @@ failed: virHashFree(ret->domains, (virHashDeallocator) virDomainFreeName); if (ret->networks != NULL) virHashFree(ret->networks, (virHashDeallocator) virNetworkFreeName); + if (ret->interfaces != NULL) + virHashFree(ret->interfaces, (virHashDeallocator) virInterfaceFreeName); if (ret->storagePools != NULL) virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName); if (ret->storageVols != NULL) @@ -173,6 +193,8 @@ virReleaseConnect(virConnectPtr conn) { virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName); if (conn->networks != NULL) virHashFree(conn->networks, (virHashDeallocator) virNetworkFreeName); + if (conn->interfaces != NULL) + virHashFree(conn->interfaces, (virHashDeallocator) virInterfaceFreeName); if (conn->storagePools != NULL) virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName); if (conn->storageVols != NULL) @@ -487,6 +509,144 @@ virUnrefNetwork(virNetworkPtr network) { } +/** + * virGetInterface: + * @conn: the hypervisor connection + * @name: pointer to the interface name + * @mac: pointer to the mac + * + * Lookup if the interface is already registered for that connection, + * if yes return a new pointer to it, if no allocate a new structure, + * and register it in the table. In any case a corresponding call to + * virUnrefInterface() is needed to not leak data. + * + * Returns a pointer to the interface, or NULL in case of failure + */ +virInterfacePtr +virGetInterface(virConnectPtr conn, const char *name, const char *mac) { + virInterfacePtr ret = NULL; + + if ((!VIR_IS_CONNECT(conn)) || (name == NULL) || (mac == NULL)) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + virMutexLock(&conn->lock); + + /* TODO search by MAC first as they are better differentiators */ + + ret = (virInterfacePtr) virHashLookup(conn->interfaces, name); + /* TODO check the MAC */ + if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { + virReportOOMError(conn); + goto error; + } + ret->name = strdup(name); + if (ret->name == NULL) { + virReportOOMError(conn); + goto error; + } + ret->mac = strdup(mac); + if (ret->mac == NULL) { + virReportOOMError(conn); + goto error; + } + + ret->magic = VIR_INTERFACE_MAGIC; + ret->conn = conn; + + if (virHashAddEntry(conn->interfaces, name, ret) < 0) { + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("failed to add interface to connection hash table")); + goto error; + } + conn->refs++; + } + ret->refs++; + virMutexUnlock(&conn->lock); + return(ret); + + error: + virMutexUnlock(&conn->lock); + if (ret != NULL) { + VIR_FREE(ret->name); + VIR_FREE(ret->mac); + VIR_FREE(ret); + } + return(NULL); +} + +/** + * virReleaseInterface: + * @interface: the interface to release + * + * Unconditionally release all memory associated with a interface. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The interface obj must not + * be used once this method returns. + * + * It will also unreference the associated connection object, + * which may also be released if its ref count hits zero. + */ +static void +virReleaseInterface(virInterfacePtr interface) { + virConnectPtr conn = interface->conn; + DEBUG("release interface %p %s", interface, interface->name); + + /* TODO search by MAC first as they are better differenciators */ + if (virHashRemoveEntry(conn->interfaces, interface->name, NULL) < 0) + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("interface missing from connection hash table")); + + interface->magic = -1; + VIR_FREE(interface->name); + VIR_FREE(interface->mac); + VIR_FREE(interface); + + DEBUG("unref connection %p %d", conn, conn->refs); + conn->refs--; + if (conn->refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return; + } + + virMutexUnlock(&conn->lock); +} + + +/** + * virUnrefInterface: + * @interface: the interface to unreference + * + * Unreference the interface. If the use count drops to zero, the structure is + * actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefInterface(virInterfacePtr interface) { + int refs; + + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + virMutexLock(&interface->conn->lock); + DEBUG("unref interface %p %s %d", interface, interface->name, interface->refs); + interface->refs--; + refs = interface->refs; + if (refs == 0) { + virReleaseInterface(interface); + /* Already unlocked mutex */ + return (0); + } + + virMutexUnlock(&interface->conn->lock); + return (refs); +} + + /** * virGetStoragePool: * @conn: the hypervisor connection diff --git a/src/datatypes.h b/src/datatypes.h index 5956c5daea..a83777a741 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -58,6 +58,16 @@ #define VIR_IS_NETWORK(obj) ((obj) && (obj)->magic==VIR_NETWORK_MAGIC) #define VIR_IS_CONNECTED_NETWORK(obj) (VIR_IS_NETWORK(obj) && VIR_IS_CONNECT((obj)->conn)) +/** + * VIR_INTERFACE_MAGIC: + * + * magic value used to protect the API when pointers to interface structures + * are passed down by the users. + */ +#define VIR_INTERFACE_MAGIC 0xDEAD5309 +#define VIR_IS_INTERFACE(obj) ((obj) && (obj)->magic==VIR_INTERFACE_MAGIC) +#define VIR_IS_CONNECTED_INTERFACE(obj) (VIR_IS_INTERFACE(obj) && VIR_IS_CONNECT((obj)->conn)) + /** * VIR_STORAGE_POOL_MAGIC: * @@ -106,6 +116,7 @@ struct _virConnect { /* The underlying hypervisor driver and network driver. */ virDriverPtr driver; virNetworkDriverPtr networkDriver; + virInterfaceDriverPtr interfaceDriver; virStorageDriverPtr storageDriver; virDeviceMonitorPtr deviceMonitor; @@ -115,6 +126,7 @@ struct _virConnect { */ void * privateData; void * networkPrivateData; + void * interfacePrivateData; void * storagePrivateData; void * devMonPrivateData; @@ -133,6 +145,7 @@ struct _virConnect { virHashTablePtr domains; /* hash table for known domains */ virHashTablePtr networks; /* hash table for known domains */ + virHashTablePtr interfaces; /* hash table for known interfaces */ virHashTablePtr storagePools;/* hash table for known storage pools */ virHashTablePtr storageVols;/* hash table for known storage vols */ virHashTablePtr nodeDevices; /* hash table for known node devices */ @@ -166,6 +179,19 @@ struct _virNetwork { unsigned char uuid[VIR_UUID_BUFLEN]; /* the network unique identifier */ }; +/** +* _virInterface: +* +* Internal structure associated to a physical host interface +*/ +struct _virInterface { + unsigned int magic; /* specific value to check */ + int refs; /* reference count */ + virConnectPtr conn; /* pointer back to the connection */ + char *name; /* the network external name */ + char *mac; /* the interface MAC address */ +}; + /** * _virStoragePool: * @@ -225,6 +251,11 @@ virNetworkPtr virGetNetwork(virConnectPtr conn, const unsigned char *uuid); int virUnrefNetwork(virNetworkPtr network); +virInterfacePtr virGetInterface(virConnectPtr conn, + const char *name, + const char *mac); +int virUnrefInterface(virInterfacePtr interface); + virStoragePoolPtr virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid); diff --git a/src/driver.h b/src/driver.h index b8e0a04ed6..01758a9a12 100644 --- a/src/driver.h +++ b/src/driver.h @@ -488,6 +488,65 @@ struct _virNetworkDriver { virDrvNetworkSetAutostart networkSetAutostart; }; +/*-------*/ +typedef int + (*virDrvNumOfInterfaces) (virConnectPtr conn); +typedef int + (*virDrvListInterfaces) (virConnectPtr conn, + char **const names, + int maxnames); +typedef virInterfacePtr + (*virDrvInterfaceLookupByName) (virConnectPtr conn, + const char *name); +typedef virInterfacePtr + (*virDrvInterfaceLookupByMACString) (virConnectPtr conn, + const char *mac); + +typedef char * + (*virDrvInterfaceGetXMLDesc) (virInterfacePtr interface, + unsigned int flags); + +typedef virInterfacePtr + (*virDrvInterfaceDefineXML) (virConnectPtr conn, + const char *xmlDesc, + unsigned int flags); +typedef int + (*virDrvInterfaceUndefine) (virInterfacePtr interface); +typedef int + (*virDrvInterfaceCreate) (virInterfacePtr interface, + unsigned int flags); +typedef int + (*virDrvInterfaceDestroy) (virInterfacePtr interface, + unsigned int flags); + +typedef struct _virInterfaceDriver virInterfaceDriver; +typedef virInterfaceDriver *virInterfaceDriverPtr; + +/** + * _virInterfaceDriver: + * + * Structure associated to a network virtualization driver, defining the various + * entry points for it. + * + * All drivers must support the following fields/methods: + * - open + * - close + */ +struct _virInterfaceDriver { + const char *name; /* the name of the driver */ + virDrvOpen open; + virDrvClose close; + virDrvNumOfInterfaces numOfInterfaces; + virDrvListInterfaces listInterfaces; + virDrvInterfaceLookupByName interfaceLookupByName; + virDrvInterfaceLookupByMACString interfaceLookupByMACString; + virDrvInterfaceGetXMLDesc interfaceGetXMLDesc; + virDrvInterfaceDefineXML interfaceDefineXML; + virDrvInterfaceUndefine interfaceUndefine; + virDrvInterfaceCreate interfaceCreate; + virDrvInterfaceDestroy interfaceDestroy; +}; + typedef int (*virDrvConnectNumOfStoragePools) (virConnectPtr conn); @@ -724,6 +783,7 @@ struct _virDeviceMonitor { */ int virRegisterDriver(virDriverPtr); int virRegisterNetworkDriver(virNetworkDriverPtr); +int virRegisterInterfaceDriver(virInterfaceDriverPtr); int virRegisterStorageDriver(virStorageDriverPtr); int virRegisterDeviceMonitor(virDeviceMonitorPtr); #ifdef WITH_LIBVIRTD diff --git a/src/libvirt.c b/src/libvirt.c index f1f81b3ff7..cb486bbdcb 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -74,6 +74,8 @@ static virDriverPtr virDriverTab[MAX_DRIVERS]; static int virDriverTabCount = 0; static virNetworkDriverPtr virNetworkDriverTab[MAX_DRIVERS]; static int virNetworkDriverTabCount = 0; +static virInterfaceDriverPtr virInterfaceDriverTab[MAX_DRIVERS]; +static int virInterfaceDriverTabCount = 0; static virStorageDriverPtr virStorageDriverTab[MAX_DRIVERS]; static int virStorageDriverTabCount = 0; static virDeviceMonitorPtr virDeviceMonitorTab[MAX_DRIVERS]; @@ -461,6 +463,32 @@ virLibNetworkError(virNetworkPtr network, virErrorNumber error, errmsg, info, NULL, 0, 0, errmsg, info); } +/** + * virLibInterfaceError: + * @conn: the connection if available + * @error: the error number + * @info: extra information string + * + * Handle an error at the connection level + */ +static void +virLibInterfaceError(virInterfacePtr interface, virErrorNumber error, + const char *info) +{ + virConnectPtr conn = NULL; + const char *errmsg; + + if (error == VIR_ERR_OK) + return; + + errmsg = virErrorMsg(error, info); + if (error != VIR_ERR_INVALID_INTERFACE) { + conn = interface->conn; + } + virRaiseError(conn, NULL, NULL, VIR_FROM_INTERFACE, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); +} + /** * virLibStoragePoolError: * @conn: the connection if available @@ -570,6 +598,37 @@ virRegisterNetworkDriver(virNetworkDriverPtr driver) return virNetworkDriverTabCount++; } +/** + * virRegisterInterfaceDriver: + * @driver: pointer to a interface driver block + * + * Register a interface virtualization driver + * + * Returns the driver priority or -1 in case of error. + */ +int +virRegisterInterfaceDriver(virInterfaceDriverPtr driver) +{ + if (virInitialize() < 0) + return -1; + + if (driver == NULL) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + + if (virInterfaceDriverTabCount >= MAX_DRIVERS) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + + DEBUG ("registering %s as interface driver %d", + driver->name, virInterfaceDriverTabCount); + + virInterfaceDriverTab[virInterfaceDriverTabCount] = driver; + return virInterfaceDriverTabCount++; +} + /** * virRegisterStorageDriver: * @driver: pointer to a storage driver block @@ -966,6 +1025,28 @@ do_open (const char *name, } } +#if 0 + /* TODO: reactivate once we have an interface driver */ + + for (i = 0; i < virInterfaceDriverTabCount; i++) { + res = virInterfaceDriverTab[i]->open (ret, auth, flags); + DEBUG("interface driver %d %s returned %s", + i, virInterfaceDriverTab[i]->name, + res == VIR_DRV_OPEN_SUCCESS ? "SUCCESS" : + (res == VIR_DRV_OPEN_DECLINED ? "DECLINED" : + (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status"))); + if (res == VIR_DRV_OPEN_ERROR) { + if (STREQ(virInterfaceDriverTab[i]->name, "remote")) { + virLibConnWarning (NULL, VIR_WAR_NO_INTERFACE, + "Is the daemon running ?"); + } + break; + } else if (res == VIR_DRV_OPEN_SUCCESS) { + ret->interfaceDriver = virInterfaceDriverTab[i]; + break; + } + } +#endif /* Secondary driver for storage. Optional */ for (i = 0; i < virStorageDriverTabCount; i++) { @@ -1126,6 +1207,8 @@ virConnectClose(virConnectPtr conn) if (conn->networkDriver) conn->networkDriver->close (conn); + if (conn->interfaceDriver) + conn->interfaceDriver->close (conn); if (conn->storageDriver) conn->storageDriver->close (conn); if (conn->deviceMonitor) @@ -5278,6 +5361,524 @@ error: return -1; } +/** + * virInterfaceGetConnect: + * @net: pointer to a interface + * + * Provides the connection pointer associated with an interface. The + * reference counter on the connection is not increased by this + * call. + * + * WARNING: When writing libvirt bindings in other languages, do + * not use this function. Instead, store the connection and + * the interface object together. + * + * Returns the virConnectPtr or NULL in case of failure. + */ +virConnectPtr +virInterfaceGetConnect (virInterfacePtr interface) +{ + DEBUG("interface=%p", interface); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_INTERFACE (interface)) { + virLibInterfaceError (NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return NULL; + } + return interface->conn; +} + +/** + * virConnectNumOfInterfaces: + * @conn: pointer to the hypervisor connection + * + * Provides the number of interfaces on the physical host. + * + * Returns the number of interface found or -1 in case of error + */ +int +virConnectNumOfInterfaces(virConnectPtr conn) +{ + DEBUG("conn=%p", conn); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if (conn->interfaceDriver && conn->interfaceDriver->numOfInterfaces) { + int ret; + ret = conn->interfaceDriver->numOfInterfaces (conn); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return -1; +} + +/** + * virConnectListInterfaces: + * @conn: pointer to the hypervisor connection + * @names: array to collect the list of names of interfaces + * @maxnames: size of @names + * + * Collect the list of physical host interfaces, and store their names in @names + * + * Returns the number of interfaces found or -1 in case of error + */ +int +virConnectListInterfaces(virConnectPtr conn, char **const names, int maxnames) +{ + DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if ((names == NULL) || (maxnames < 0)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->interfaceDriver && conn->interfaceDriver->listInterfaces) { + int ret; + ret = conn->interfaceDriver->listInterfaces (conn, names, maxnames); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return -1; +} + +/** + * virInterfaceLookupByName: + * @conn: pointer to the hypervisor connection + * @name: name for the interface + * + * Try to lookup an interface on the given hypervisor based on its name. + * + * Returns a new interface object or NULL in case of failure. If the + * interface cannot be found, then VIR_ERR_NO_INTERFACE error is raised. + */ +virInterfacePtr +virInterfaceLookupByName(virConnectPtr conn, const char *name) +{ + DEBUG("conn=%p, name=%s", conn, name); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (name == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->interfaceDriver && conn->interfaceDriver->interfaceLookupByName) { + virInterfacePtr ret; + ret = conn->interfaceDriver->interfaceLookupByName (conn, name); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; +} + +/** + * virInterfaceLookupByMACString: + * @conn: pointer to the hypervisor connection + * @macstr: the MAC for the interface (null-terminated ASCII format) + * + * Try to lookup an interface on the given hypervisor based on its MAC. + * + * Returns a new interface object or NULL in case of failure. If the + * interface cannot be found, then VIR_ERR_NO_INTERFACE error is raised. + */ +virInterfacePtr +virInterfaceLookupByMACString(virConnectPtr conn, const char *macstr) +{ + DEBUG("conn=%p, macstr=%s", conn, macstr); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (macstr == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->interfaceDriver && conn->interfaceDriver->interfaceLookupByMACString) { + virInterfacePtr ret; + ret = conn->interfaceDriver->interfaceLookupByMACString (conn, macstr); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; +} + +/** + * virInterfaceGetName: + * @interface: a interface object + * + * Get the public name for that interface + * + * Returns a pointer to the name or NULL, the string need not be deallocated + * its lifetime will be the same as the interface object. + */ +const char * +virInterfaceGetName(virInterfacePtr interface) +{ + DEBUG("interface=%p", interface); + + virResetLastError(); + + if (!VIR_IS_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (NULL); + } + return (interface->name); +} + +/** + * virInterfaceGetMACString: + * @interface: a interface object + * + * Get the MAC for a interface as string. For more information about + * MAC see RFC4122. + * + * Returns a pointer to the MAC address (in null-terminated ASCII + * format) or NULL, the string need not be deallocated its lifetime + * will be the same as the interface object. + */ +const char * +virInterfaceGetMACString(virInterfacePtr interface) +{ + DEBUG("interface=%p", interface); + + virResetLastError(); + + if (!VIR_IS_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (NULL); + } + return (interface->mac); +} + +/** + * virInterfaceGetXMLDesc: + * @interface: a interface object + * @flags: and OR'ed set of extraction flags, not used yet + * + * Provide an XML description of the interface. The description may be reused + * later to recreate the interface with virInterfaceCreateXML(). + * + * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error. + * the caller must free() the returned value. + */ +char * +virInterfaceGetXMLDesc(virInterfacePtr interface, unsigned int flags) +{ + virConnectPtr conn; + DEBUG("interface=%p, flags=%d", interface, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (NULL); + } + if (flags != 0) { + virLibInterfaceError(interface, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + conn = interface->conn; + + if (conn->interfaceDriver && conn->interfaceDriver->interfaceGetXMLDesc) { + char *ret; + ret = conn->interfaceDriver->interfaceGetXMLDesc (interface, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(interface->conn); + return NULL; +} + +/** + * virInterfaceDefineXML: + * @conn: pointer to the hypervisor connection + * @xml: the XML description for the interface, preferably in UTF-8 + * @flags: and OR'ed set of extraction flags, not used yet + * + * Define an interface (or modify existing interface configuration) + * + * Returns NULL in case of error, a pointer to the interface otherwise + */ +virInterfacePtr +virInterfaceDefineXML(virConnectPtr conn, const char *xml, unsigned int flags) +{ + DEBUG("conn=%p, xml=%s, flags=%d", conn, xml, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (conn->flags & VIR_CONNECT_RO) { + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + if (xml == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->interfaceDriver && conn->interfaceDriver->interfaceDefineXML) { + virInterfacePtr ret; + ret = conn->interfaceDriver->interfaceDefineXML (conn, xml, flags); + if (!ret) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(conn); + return NULL; +} + +/** + * virInterfaceUndefine: + * @interface: pointer to a defined interface + * + * Undefine an interface, ie remove it from the config. + * This does not free the associated virInterfacePtr object. + * + * Returns 0 in case of success, -1 in case of error + */ +int +virInterfaceUndefine(virInterfacePtr interface) { + virConnectPtr conn; + DEBUG("interface=%p", interface); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (-1); + } + conn = interface->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibInterfaceError(interface, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->interfaceDriver && conn->interfaceDriver->interfaceUndefine) { + int ret; + ret = conn->interfaceDriver->interfaceUndefine (interface); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(interface->conn); + return -1; +} + +/** + * virInterfaceCreate: + * @interface: pointer to a defined interface + * @flags: and OR'ed set of extraction flags, not used yet + * + * Activate an interface (ie call "ifup") + * + * Returns 0 in case of success, -1 in case of error + */ +int +virInterfaceCreate(virInterfacePtr interface, unsigned int flags) +{ + virConnectPtr conn; + DEBUG("interface=%p, flags=%d", interface, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (-1); + } + conn = interface->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibInterfaceError(interface, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->interfaceDriver && conn->interfaceDriver->interfaceCreate) { + int ret; + ret = conn->interfaceDriver->interfaceCreate (interface, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(interface->conn); + return -1; +} + +/** + * virInterfaceDestroy: + * @interface: an interface object + * @flags: and OR'ed set of extraction flags, not used yet + * + * deactivate an interface (ie call "ifdown") + * This does not remove the interface from the config, and + * does not free the associated virInterfacePtr object. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virInterfaceDestroy(virInterfacePtr interface, unsigned int flags) +{ + virConnectPtr conn; + DEBUG("interface=%p, flags=%d", interface, flags); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (-1); + } + + conn = interface->conn; + if (conn->flags & VIR_CONNECT_RO) { + virLibInterfaceError(interface, VIR_ERR_OPERATION_DENIED, __FUNCTION__); + goto error; + } + + if (conn->interfaceDriver && conn->interfaceDriver->interfaceDestroy) { + int ret; + ret = conn->interfaceDriver->interfaceDestroy (interface, flags); + if (ret < 0) + goto error; + return ret; + } + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(interface->conn); + return -1; +} + +/** + * virInterfaceRef: + * @interface: the interface to hold a reference on + * + * Increment the reference count on the interface. For each + * additional call to this method, there shall be a corresponding + * call to virInterfaceFree to release the reference count, once + * the caller no longer needs the reference to this object. + * + * This method is typically useful for applications where multiple + * threads are using a connection, and it is required that the + * connection remain open until all threads have finished using + * it. ie, each new thread using a interface would increment + * the reference count. + * + * Returns 0 in case of success, -1 in case of failure. + */ +int +virInterfaceRef(virInterfacePtr interface) +{ + if ((!VIR_IS_CONNECTED_INTERFACE(interface))) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + virMutexLock(&interface->conn->lock); + DEBUG("interface=%p refs=%d", interface, interface->refs); + interface->refs++; + virMutexUnlock(&interface->conn->lock); + return 0; +} + +/** + * virInterfaceFree: + * @interface: a interface object + * + * Free the interface object. The interface itself is unaltered. + * The data structure is freed and should not be used thereafter. + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virInterfaceFree(virInterfacePtr interface) +{ + DEBUG("interface=%p", interface); + + virResetLastError(); + + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (-1); + } + if (virUnrefInterface(interface) < 0) + return (-1); + return(0); +} + /** * virStoragePoolGetConnect: diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ce6386968e..c3ceccf2bf 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -43,6 +43,7 @@ virConfWriteMem; # datatypes.h virGetDomain; +virGetInterface; virGetNetwork; virGetStoragePool; virGetStorageVol; diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 0ea130ff95..85a26d40de 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -268,5 +268,19 @@ LIBVIRT_0.6.3 { LIBVIRT_0.6.4 { global: + virInterfaceGetConnect; + virConnectNumOfInterfaces; + virConnectListInterfaces; + virInterfaceLookupByName; + virInterfaceLookupByMACString; + virInterfaceGetName; + virInterfaceGetMACString; + virInterfaceGetXMLDesc; + virInterfaceRef; + virInterfaceFree; + virInterfaceDefineXML; + virInterfaceUndefine; + virInterfaceCreate; + virInterfaceDestroy; virStorageVolCreateXMLFrom; } LIBVIRT_0.6.3; diff --git a/src/remote_internal.c b/src/remote_internal.c index 542f4adaf8..48c35fad4c 100644 --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -1,3 +1,4 @@ + /* * remote_internal.c: driver to provide access to libvirtd running * on a remote machine @@ -211,11 +212,13 @@ static void errorf (virConnectPtr conn, virErrorNumber code, static void server_error (virConnectPtr conn, remote_error *err); static virDomainPtr get_nonnull_domain (virConnectPtr conn, remote_nonnull_domain domain); static virNetworkPtr get_nonnull_network (virConnectPtr conn, remote_nonnull_network network); +static virInterfacePtr get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface interface); static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool); static virStorageVolPtr get_nonnull_storage_vol (virConnectPtr conn, remote_nonnull_storage_vol vol); static virNodeDevicePtr get_nonnull_node_device (virConnectPtr conn, remote_nonnull_node_device dev); static void make_nonnull_domain (remote_nonnull_domain *dom_dst, virDomainPtr dom_src); static void make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src); +static void make_nonnull_interface (remote_nonnull_interface *interface_dst, virInterfacePtr interface_src); static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr vol_src); static void make_nonnull_storage_vol (remote_nonnull_storage_vol *vol_dst, virStorageVolPtr vol_src); void remoteDomainEventFired(int watch, int fd, int event, void *data); @@ -3672,6 +3675,325 @@ done: +/*----------------------------------------------------------------------*/ + +static virDrvOpenStatus +remoteInterfaceOpen (virConnectPtr conn, + virConnectAuthPtr auth, + int flags) +{ + if (inside_daemon) + return VIR_DRV_OPEN_DECLINED; + + if (conn && + conn->driver && + STREQ (conn->driver->name, "remote")) { + struct private_data *priv; + + /* If we're here, the remote driver is already + * in use due to a) a QEMU uri, or b) a remote + * URI. So we can re-use existing connection + */ + priv = conn->privateData; + remoteDriverLock(priv); + priv->localUses++; + conn->interfacePrivateData = priv; + remoteDriverUnlock(priv); + return VIR_DRV_OPEN_SUCCESS; + } else { + /* Using a non-remote driver, so we need to open a + * new connection for interface APIs, forcing it to + * use the UNIX transport. This handles Xen driver + * which doesn't have its own impl of the interface APIs. + */ + struct private_data *priv; + int ret; + ret = remoteOpenSecondaryDriver(conn, + auth, + flags, + &priv); + if (ret == VIR_DRV_OPEN_SUCCESS) + conn->interfacePrivateData = priv; + return ret; + } +} + +static int +remoteInterfaceClose (virConnectPtr conn) +{ + int rv = 0; + struct private_data *priv = conn->interfacePrivateData; + + remoteDriverLock(priv); + priv->localUses--; + if (!priv->localUses) { + rv = doRemoteClose(conn, priv); + conn->interfacePrivateData = NULL; + remoteDriverUnlock(priv); + virMutexDestroy(&priv->lock); + VIR_FREE(priv); + } + if (priv) + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteNumOfInterfaces (virConnectPtr conn) +{ + int rv = -1; + remote_num_of_interfaces_ret ret; + struct private_data *priv = conn->interfacePrivateData; + + remoteDriverLock(priv); + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_NUM_OF_INTERFACES, + (xdrproc_t) xdr_void, (char *) NULL, + (xdrproc_t) xdr_remote_num_of_interfaces_ret, (char *) &ret) == -1) + goto done; + + rv = ret.num; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteListInterfaces (virConnectPtr conn, char **const names, int maxnames) +{ + int rv = -1; + int i; + remote_list_interfaces_args args; + remote_list_interfaces_ret ret; + struct private_data *priv = conn->interfacePrivateData; + + remoteDriverLock(priv); + + if (maxnames > REMOTE_INTERFACE_NAME_LIST_MAX) { + errorf (conn, VIR_ERR_RPC, + _("too many remote interfaces: %d > %d"), + maxnames, REMOTE_INTERFACE_NAME_LIST_MAX); + goto done; + } + args.maxnames = maxnames; + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_LIST_INTERFACES, + (xdrproc_t) xdr_remote_list_interfaces_args, (char *) &args, + (xdrproc_t) xdr_remote_list_interfaces_ret, (char *) &ret) == -1) + goto done; + + if (ret.names.names_len > maxnames) { + errorf (conn, VIR_ERR_RPC, + _("too many remote interfaces: %d > %d"), + ret.names.names_len, maxnames); + goto cleanup; + } + + /* This call is caller-frees (although that isn't clear from + * the documentation). However xdr_free will free up both the + * names and the list of pointers, so we have to strdup the + * names here. + */ + for (i = 0; i < ret.names.names_len; ++i) + names[i] = strdup (ret.names.names_val[i]); + + rv = ret.names.names_len; + +cleanup: + xdr_free ((xdrproc_t) xdr_remote_list_interfaces_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virInterfacePtr +remoteInterfaceLookupByName (virConnectPtr conn, + const char *name) +{ + virInterfacePtr interface = NULL; + remote_interface_lookup_by_name_args args; + remote_interface_lookup_by_name_ret ret; + struct private_data *priv = conn->interfacePrivateData; + + remoteDriverLock(priv); + + args.name = (char *) name; + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME, + (xdrproc_t) xdr_remote_interface_lookup_by_name_args, (char *) &args, + (xdrproc_t) xdr_remote_interface_lookup_by_name_ret, (char *) &ret) == -1) + goto done; + + interface = get_nonnull_interface (conn, ret.interface); + xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_name_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return interface; +} + +static virInterfacePtr +remoteInterfaceLookupByMACString (virConnectPtr conn, + const char *mac) +{ + virInterfacePtr interface = NULL; + remote_interface_lookup_by_mac_string_args args; + remote_interface_lookup_by_mac_string_ret ret; + struct private_data *priv = conn->interfacePrivateData; + + remoteDriverLock(priv); + + args.mac = (char *) mac; + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING, + (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_args, (char *) &args, + (xdrproc_t) xdr_remote_interface_lookup_by_mac_string_ret, (char *) &ret) == -1) + goto done; + + interface = get_nonnull_interface (conn, ret.interface); + xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_mac_string_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return interface; +} + +static char * +remoteInterfaceGetXMLDesc (virInterfacePtr interface, + unsigned int flags) +{ + char *rv = NULL; + remote_interface_get_xml_desc_args args; + remote_interface_get_xml_desc_ret ret; + struct private_data *priv = interface->conn->interfacePrivateData; + + remoteDriverLock(priv); + + make_nonnull_interface (&args.interface, interface); + args.flags = flags; + + memset (&ret, 0, sizeof ret); + if (call (interface->conn, priv, 0, REMOTE_PROC_INTERFACE_GET_XML_DESC, + (xdrproc_t) xdr_remote_interface_get_xml_desc_args, (char *) &args, + (xdrproc_t) xdr_remote_interface_get_xml_desc_ret, (char *) &ret) == -1) + goto done; + + /* Caller frees. */ + rv = ret.xml; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static virInterfacePtr +remoteInterfaceDefineXML (virConnectPtr conn, + const char *xmlDesc, + unsigned int flags) +{ + virInterfacePtr interface = NULL; + remote_interface_define_xml_args args; + remote_interface_define_xml_ret ret; + struct private_data *priv = conn->interfacePrivateData; + + remoteDriverLock(priv); + + args.xml = (char *) xmlDesc; + args.flags = flags; + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_DEFINE_XML, + (xdrproc_t) xdr_remote_interface_define_xml_args, (char *) &args, + (xdrproc_t) xdr_remote_interface_define_xml_ret, (char *) &ret) == -1) + goto done; + + interface = get_nonnull_interface (conn, ret.interface); + xdr_free ((xdrproc_t) &xdr_remote_interface_define_xml_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return interface; +} + +static int +remoteInterfaceUndefine (virInterfacePtr interface) +{ + int rv = -1; + remote_interface_undefine_args args; + struct private_data *priv = interface->conn->interfacePrivateData; + + remoteDriverLock(priv); + + make_nonnull_interface (&args.interface, interface); + + if (call (interface->conn, priv, 0, REMOTE_PROC_INTERFACE_UNDEFINE, + (xdrproc_t) xdr_remote_interface_undefine_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteInterfaceCreate (virInterfacePtr interface, + unsigned int flags) +{ + int rv = -1; + remote_interface_create_args args; + struct private_data *priv = interface->conn->interfacePrivateData; + + remoteDriverLock(priv); + + make_nonnull_interface (&args.interface, interface); + args.flags = flags; + + if (call (interface->conn, priv, 0, REMOTE_PROC_INTERFACE_CREATE, + (xdrproc_t) xdr_remote_interface_create_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + +static int +remoteInterfaceDestroy (virInterfacePtr interface, + unsigned int flags) +{ + int rv = -1; + remote_interface_destroy_args args; + struct private_data *priv = interface->conn->interfacePrivateData; + + remoteDriverLock(priv); + + make_nonnull_interface (&args.interface, interface); + args.flags = flags; + + if (call (interface->conn, priv, 0, REMOTE_PROC_INTERFACE_DESTROY, + (xdrproc_t) xdr_remote_interface_destroy_args, (char *) &args, + (xdrproc_t) xdr_void, (char *) NULL) == -1) + goto done; + + rv = 0; + +done: + remoteDriverUnlock(priv); + return rv; +} + /*----------------------------------------------------------------------*/ static virDrvOpenStatus @@ -6871,6 +7193,12 @@ get_nonnull_network (virConnectPtr conn, remote_nonnull_network network) return virGetNetwork (conn, network.name, BAD_CAST network.uuid); } +static virInterfacePtr +get_nonnull_interface (virConnectPtr conn, remote_nonnull_interface interface) +{ + return virGetInterface (conn, interface.name, interface.mac); +} + static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool) { @@ -6905,6 +7233,14 @@ make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src) memcpy (net_dst->uuid, net_src->uuid, VIR_UUID_BUFLEN); } +static void +make_nonnull_interface (remote_nonnull_interface *interface_dst, + virInterfacePtr interface_src) +{ + interface_dst->name = interface_src->name; + interface_dst->mac = interface_src->mac; +} + static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src) { @@ -7016,6 +7352,21 @@ static virNetworkDriver network_driver = { .networkSetAutostart = remoteNetworkSetAutostart, }; +static virInterfaceDriver interface_driver = { + .name = "remote", + .open = remoteInterfaceOpen, + .close = remoteInterfaceClose, + .numOfInterfaces = remoteNumOfInterfaces, + .listInterfaces = remoteListInterfaces, + .interfaceLookupByName = remoteInterfaceLookupByName, + .interfaceLookupByMACString = remoteInterfaceLookupByMACString, + .interfaceGetXMLDesc = remoteInterfaceGetXMLDesc, + .interfaceDefineXML = remoteInterfaceDefineXML, + .interfaceUndefine = remoteInterfaceUndefine, + .interfaceCreate = remoteInterfaceCreate, + .interfaceDestroy = remoteInterfaceDestroy, +}; + static virStorageDriver storage_driver = { .name = "remote", .open = remoteStorageOpen, @@ -7088,6 +7439,7 @@ remoteRegister (void) { if (virRegisterDriver (&driver) == -1) return -1; if (virRegisterNetworkDriver (&network_driver) == -1) return -1; + if (virRegisterInterfaceDriver (&interface_driver) == -1) return -1; if (virRegisterStorageDriver (&storage_driver) == -1) return -1; if (virRegisterDeviceMonitor (&dev_monitor) == -1) return -1; #ifdef WITH_LIBVIRTD diff --git a/src/virterror.c b/src/virterror.c index e12608d4ee..3af65447f0 100644 --- a/src/virterror.c +++ b/src/virterror.c @@ -157,6 +157,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { case VIR_FROM_VBOX: dom = "VBOX "; break; + case VIR_FROM_INTERFACE: + dom = "Interface "; + break; } return(dom); } @@ -1024,6 +1027,24 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("Requested operation is not valid: %s"); break; + case VIR_WAR_NO_INTERFACE: + if (info == NULL) + errmsg = _("Failed to find the interface"); + else + errmsg = _("Failed to find the interface: %s"); + break; + case VIR_ERR_NO_INTERFACE: + if (info == NULL) + errmsg = _("Interface not found"); + else + errmsg = _("Interface not found: %s"); + break; + case VIR_ERR_INVALID_INTERFACE: + if (info == NULL) + errmsg = _("invalid interface pointer in"); + else + errmsg = _("invalid interface pointer in %s"); + break; } return (errmsg); }