[libvirt] [PATCH 0/5] Interface Config public APIs and remote stubs

These 5 patches contain the public virInterface*() API definition, the local plumbing, and the RPC glue. The test driver and real driver are still TBI, but having this in will allow other people to work on related stuff. Other things still needed: python/java bindings cli commands in virsh I'm sure lots of other things I don't know about yet. Note that I have added a couple things to the API that I previously didn't realize were needed (virInterfaceRef and virInterfaceFree - I had figured the client side would just pass around a cookie, not actually have storage associated with it).

From: Laine Stump <laine@redhat.com> --- include/libvirt/libvirt.h | 84 ++++++++++++++++++++++++++++++++++++++++++ include/libvirt/libvirt.h.in | 84 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 0 deletions(-) diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index 30f559d..91af6fd 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -854,6 +854,90 @@ 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; + +/* + * Get connection from interface. + */ +virConnectPtr virInterfaceGetConnect (virInterfacePtr interface); + +/* + * List defined interfaces + */ +int virConnectNumOfInterfaces (virConnectPtr conn); +int virConnectListInterfaces (virConnectPtr conn, + char **const names, + int maxnames); + +/* + * Lookup interface by name or MAC address + */ +virInterfacePtr virInterfaceLookupByName (virConnectPtr conn, + const char *name); +virInterfacePtr virInterfaceLookupByMAC (virConnectPtr conn, + const unsigned char *mac); +virInterfacePtr virInterfaceLookupByMACString (virConnectPtr conn, + const char *mac); + +/* + * Interface information + */ +const char* virInterfaceGetName (virInterfacePtr interface); +int virInterfaceGetMAC (virInterfacePtr interface, + unsigned char *mac); +int virInterfaceGetMACString (virInterfacePtr interface, + char *mac); + +char * virInterfaceGetXMLDesc (virInterfacePtr interface, + int flags); +/* + * Define interface (or modify existing interface configuration) + */ +virInterfacePtr virInterfaceDefineXML (virConnectPtr conn, + const char *xmlDesc, + int flags); + +/* + * Delete interface + */ +int virInterfaceUndefine (virInterfacePtr interface); + +/* + * Activate interface (ie call "ifup") + */ +int virInterfaceCreate (virInterfacePtr interface, + int flags); + +/* + * De-activate interface (call "ifdown") + */ +int virInterfaceDestroy (virInterfacePtr interface, + int flags); + +/* + * interface object memory management - you must call + * virInterfaceFree() once for each call to virInterfaceRef, or any + * API function that returns a virInterfacePtr. + */ +int virInterfaceRef (virInterfacePtr interface); +int virInterfaceFree (virInterfacePtr interface); /** * virStoragePool: diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 2f7076f..cee3d94 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -854,6 +854,90 @@ 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; + +/* + * Get connection from interface. + */ +virConnectPtr virInterfaceGetConnect (virInterfacePtr interface); + +/* + * List defined interfaces + */ +int virConnectNumOfInterfaces (virConnectPtr conn); +int virConnectListInterfaces (virConnectPtr conn, + char **const names, + int maxnames); + +/* + * Lookup interface by name or MAC address + */ +virInterfacePtr virInterfaceLookupByName (virConnectPtr conn, + const char *name); +virInterfacePtr virInterfaceLookupByMAC (virConnectPtr conn, + const unsigned char *mac); +virInterfacePtr virInterfaceLookupByMACString (virConnectPtr conn, + const char *mac); + +/* + * Interface information + */ +const char* virInterfaceGetName (virInterfacePtr interface); +int virInterfaceGetMAC (virInterfacePtr interface, + unsigned char *mac); +int virInterfaceGetMACString (virInterfacePtr interface, + char *mac); + +char * virInterfaceGetXMLDesc (virInterfacePtr interface, + int flags); +/* + * Define interface (or modify existing interface configuration) + */ +virInterfacePtr virInterfaceDefineXML (virConnectPtr conn, + const char *xmlDesc, + int flags); + +/* + * Delete interface + */ +int virInterfaceUndefine (virInterfacePtr interface); + +/* + * Activate interface (ie call "ifup") + */ +int virInterfaceCreate (virInterfacePtr interface, + int flags); + +/* + * De-activate interface (call "ifdown") + */ +int virInterfaceDestroy (virInterfacePtr interface, + int flags); + +/* + * interface object memory management - you must call + * virInterfaceFree() once for each call to virInterfaceRef, or any + * API function that returns a virInterfacePtr. + */ +int virInterfaceRef (virInterfacePtr interface); +int virInterfaceFree (virInterfacePtr interface); /** * virStoragePool: -- 1.6.0.6

On Fri, May 08, 2009 at 01:52:23PM -0400, Laine Stump wrote:
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 2f7076f..cee3d94 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -854,6 +854,90 @@ 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; + +/* + * Get connection from interface. + */ +virConnectPtr virInterfaceGetConnect (virInterfacePtr interface); + +/* + * List defined interfaces + */ +int virConnectNumOfInterfaces (virConnectPtr conn); +int virConnectListInterfaces (virConnectPtr conn, + char **const names, + int maxnames); + +/* + * Lookup interface by name or MAC address + */ +virInterfacePtr virInterfaceLookupByName (virConnectPtr conn, + const char *name); +virInterfacePtr virInterfaceLookupByMAC (virConnectPtr conn, + const unsigned char *mac); +virInterfacePtr virInterfaceLookupByMACString (virConnectPtr conn, + const char *mac); + +/* + * Interface information + */ +const char* virInterfaceGetName (virInterfacePtr interface); +int virInterfaceGetMAC (virInterfacePtr interface, + unsigned char *mac); +int virInterfaceGetMACString (virInterfacePtr interface, + char *mac); + +char * virInterfaceGetXMLDesc (virInterfacePtr interface, + int flags); +/* + * Define interface (or modify existing interface configuration) + */ +virInterfacePtr virInterfaceDefineXML (virConnectPtr conn, + const char *xmlDesc, + int flags); + +/* + * Delete interface + */ +int virInterfaceUndefine (virInterfacePtr interface); + +/* + * Activate interface (ie call "ifup") + */ +int virInterfaceCreate (virInterfacePtr interface, + int flags); + +/* + * De-activate interface (call "ifdown") + */ +int virInterfaceDestroy (virInterfacePtr interface, + int flags); + +/* + * interface object memory management - you must call + * virInterfaceFree() once for each call to virInterfaceRef, or any + * API function that returns a virInterfacePtr. + */ +int virInterfaceRef (virInterfacePtr interface); +int virInterfaceFree (virInterfacePtr interface);
/** * virStoragePool:
ACK, looks OK to me. BTW, there's no need for the comments in the header, as the src/libvirt.c file contains formal docs for each API that are then put in website & in generated API docs Regards Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Fri, May 08, 2009 at 01:52:23PM -0400, Laine Stump wrote:
From: Laine Stump <laine@redhat.com>
--- include/libvirt/libvirt.h | 84 ++++++++++++++++++++++++++++++++++++++++++ include/libvirt/libvirt.h.in | 84 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 0 deletions(-)
+ +char * virInterfaceGetXMLDesc (virInterfacePtr interface, + int flags); +virInterfacePtr virInterfaceDefineXML (virConnectPtr conn, + const char *xmlDesc, + int flags); +int virInterfaceCreate (virInterfacePtr interface, + int flags); +int virInterfaceDestroy (virInterfacePtr interface, + int flags);
Oh, one very minor point - can you change these to 'unsigned int', since that's what we now prefer to use for flags (yes, some existing APIs are bad in this respect) Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

From: Laine Stump <laine@redhat.com> --- include/libvirt/libvirt.h | 18 ++ include/libvirt/libvirt.h.in | 18 ++ include/libvirt/virterror.h | 4 + src/datatypes.h | 25 ++ src/driver.h | 60 ++++ src/libvirt.c | 695 ++++++++++++++++++++++++++++++++++++++++++ src/util.h | 2 - src/virterror.c | 21 ++ 8 files changed, 841 insertions(+), 2 deletions(-) diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index 91af6fd..b0d93a2 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -433,6 +433,24 @@ extern virConnectAuthPtr virConnectAuthPtrDefault; #define VIR_UUID_STRING_BUFLEN (36+1) +/** + * VIR_MAC_BUFLEN: + * + * This macro provides the length of the buffer required + * for an interface MAC address + */ + +#define VIR_MAC_BUFLEN (6) + +/** + * VIR_MAC_STRING_BUFLEN: + * + * This macro provides the length of the buffer required + * for virInterfaceGetMACString() + */ + +#define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3) + /* library versioning */ /** diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index cee3d94..fbaf212 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -433,6 +433,24 @@ extern virConnectAuthPtr virConnectAuthPtrDefault; #define VIR_UUID_STRING_BUFLEN (36+1) +/** + * VIR_MAC_BUFLEN: + * + * This macro provides the length of the buffer required + * for an interface MAC address + */ + +#define VIR_MAC_BUFLEN (6) + +/** + * VIR_MAC_STRING_BUFLEN: + * + * This macro provides the length of the buffer required + * for virInterfaceGetMACString() + */ + +#define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3) + /* library versioning */ /** diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index faf3f61..766cbad 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; @@ -157,6 +158,9 @@ typedef enum { VIR_ERR_INVALID_NODE_DEVICE,/* invalid node device object */ VIR_ERR_NO_NODE_DEVICE,/* node device not found */ VIR_ERR_NO_SECURITY_MODEL, /* security model not found */ + 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/src/datatypes.h b/src/datatypes.h index 5956c5d..deac9df 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -59,6 +59,16 @@ #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: * * magic value used to protect the API when pointers to storage pool structures @@ -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; @@ -167,6 +179,19 @@ struct _virNetwork { }; /** +* _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 */ + unsigned char mac[VIR_MAC_BUFLEN]; /* the interface MAC address */ +}; + +/** * _virStoragePool: * * Internal structure associated to a storage pool diff --git a/src/driver.h b/src/driver.h index c357b76..30905c0 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 + (*virDrvInterfaceLookupByMAC) (virConnectPtr conn, + const unsigned char *mac); + +typedef char * + (*virDrvInterfaceGetXMLDesc) (virInterfacePtr interface, + int flags); + +typedef virInterfacePtr + (*virDrvInterfaceDefineXML) (virConnectPtr conn, + const char *xmlDesc, + int flags); +typedef int + (*virDrvInterfaceUndefine) (virInterfacePtr interface); +typedef int + (*virDrvInterfaceCreate) (virInterfacePtr interface, + int flags); +typedef int + (*virDrvInterfaceDestroy) (virInterfacePtr interface, + 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; + virDrvInterfaceLookupByMAC interfaceLookupByMAC; + virDrvInterfaceGetXMLDesc interfaceGetXMLDesc; + virDrvInterfaceDefineXML interfaceDefineXML; + virDrvInterfaceUndefine interfaceUndefine; + virDrvInterfaceCreate interfaceCreate; + virDrvInterfaceDestroy interfaceDestroy; +}; + typedef int (*virDrvConnectNumOfStoragePools) (virConnectPtr conn); @@ -718,6 +777,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 ded18a7..4bd85a7 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]; @@ -462,6 +464,32 @@ virLibNetworkError(virNetworkPtr network, virErrorNumber error, } /** + * 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 * @error: the error number @@ -571,6 +599,37 @@ virRegisterNetworkDriver(virNetworkDriverPtr driver) } /** + * 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,24 @@ do_open (const char *name, } } + 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; + } + } /* Secondary driver for storage. Optional */ for (i = 0; i < virStorageDriverTabCount; i++) { @@ -1126,6 +1203,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 +5357,622 @@ 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; +} + +/** + * virInterfaceLookupByMAC: + * @conn: pointer to the hypervisor connection + * @mac: the raw MAC for the interface + * + * 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 +virInterfaceLookupByMAC(virConnectPtr conn, const unsigned char *mac) +{ + DEBUG("conn=%p, mac=%02X:%02X:%02X:%02X:%02X:%02X", conn, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + virResetLastError(); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (NULL); + } + if (mac == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (conn->interfaceDriver && conn->interfaceDriver->interfaceLookupByMAC){ + virInterfacePtr ret; + ret = conn->interfaceDriver->interfaceLookupByMAC (conn, mac); + 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 string MAC for the interface + * + * 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) +{ + unsigned char mac[VIR_MAC_BUFLEN]; + int ret; + 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; + } + + ret = virParseMacAddr (macstr, mac); + if (ret == -1) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + return virInterfaceLookupByMAC(conn, &mac[0]); + +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); +} + +/** + * virInterfaceGetMAC: + * @interface: a interface object + * @mac: pointer to a VIR_MAC_BUFLEN bytes array + * + * Get the MAC for a interface + * + * Returns -1 in case of error, 0 in case of success + */ +int +virInterfaceGetMAC(virInterfacePtr interface, unsigned char *mac) +{ + DEBUG("interface=%p, mac=%p", interface, mac); + + virResetLastError(); + + if (!VIR_IS_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (-1); + } + if (mac == NULL) { + virLibInterfaceError(interface, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + memcpy(mac, &interface->mac[0], VIR_MAC_BUFLEN); + + return (0); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(interface->conn); + return -1; +} + +/** + * virInterfaceGetMACString: + * @interface: a interface object + * @buf: pointer to a VIR_MAC_STRING_BUFLEN bytes array + * + * Get the MAC for a interface as string. For more information about + * MAC see RFC4122. + * + * Returns -1 in case of error, 0 in case of success + */ +int +virInterfaceGetMACString(virInterfacePtr interface, char *buf) +{ + unsigned char mac[VIR_MAC_BUFLEN]; + DEBUG("interface=%p, buf=%p", interface, buf); + + virResetLastError(); + + if (!VIR_IS_INTERFACE(interface)) { + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); + return (-1); + } + if (buf == NULL) { + virLibInterfaceError(interface, VIR_ERR_INVALID_ARG, __FUNCTION__); + goto error; + } + + if (virInterfaceGetMAC(interface, &mac[0])) + return (-1); + + virFormatMacAddr(mac, buf); + return (0); + +error: + /* Copy to connection error object for back compatability */ + virSetConnError(interface->conn); + return -1; +} + +/** + * 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 relaunch 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, 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 + * + * 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, 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 + * + * 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 + * + * Activate an interface (ie call "ifup") + * + * Returns 0 in case of success, -1 in case of error + */ +int +virInterfaceCreate(virInterfacePtr interface, 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 + * + * Destroy the interface object. The running instance is shutdown if not down + * already and all resources used by it are given back to the hypervisor. This + * does not free the associated virInterfacePtr object. + * This function may require privileged access + * + * Returns 0 in case of success and -1 in case of failure. + */ +int +virInterfaceDestroy(virInterfacePtr interface, 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 running instance is kept alive. + * 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 0 + /* + * FIXME: This needs to be uncommented when the stubs are replaced + * with actual functionality. + */ + + if (virUnrefInterface(interface) < 0) + return (-1); +#else + interface->refs--; +#endif + + return(0); +} + /** * virStoragePoolGetConnect: diff --git a/src/util.h b/src/util.h index 4bed077..2bb45bf 100644 --- a/src/util.h +++ b/src/util.h @@ -146,9 +146,7 @@ int virParseNumber(const char **str); int virAsprintf(char **strp, const char *fmt, ...) ATTRIBUTE_FORMAT(printf, 2, 3); -#define VIR_MAC_BUFLEN 6 #define VIR_MAC_PREFIX_BUFLEN 3 -#define VIR_MAC_STRING_BUFLEN VIR_MAC_BUFLEN * 3 int virParseMacAddr(const char* str, unsigned char *addr); diff --git a/src/virterror.c b/src/virterror.c index c9db91f..0f4a9eb 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); } @@ -1018,6 +1021,24 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("Security model not found: %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); } -- 1.6.0.6

On Fri, May 08, 2009 at 01:52:24PM -0400, Laine Stump wrote:
From: Laine Stump <laine@redhat.com>
--- include/libvirt/libvirt.h | 18 ++ include/libvirt/libvirt.h.in | 18 ++ include/libvirt/virterror.h | 4 + src/datatypes.h | 25 ++ src/driver.h | 60 ++++ src/libvirt.c | 695 ++++++++++++++++++++++++++++++++++++++++++ src/util.h | 2 - src/virterror.c | 21 ++ 8 files changed, 841 insertions(+), 2 deletions(-)
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index 91af6fd..b0d93a2 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -433,6 +433,24 @@ extern virConnectAuthPtr virConnectAuthPtrDefault;
#define VIR_UUID_STRING_BUFLEN (36+1)
+/** + * VIR_MAC_BUFLEN: + * + * This macro provides the length of the buffer required + * for an interface MAC address + */ + +#define VIR_MAC_BUFLEN (6) + +/** + * VIR_MAC_STRING_BUFLEN: + * + * This macro provides the length of the buffer required + * for virInterfaceGetMACString() + */ + +#define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3) +
Since this is now in our public API, I'm wondering whether we shouldn't make the buflen longer. 6 bytes is fine with wired ethernet, but I'm not sure its sufficient for all network device types in general. eg, my wmaster0 device has a rather longer hardware address wmaster0 Link encap:UNSPEC HWaddr 00-13-02-B9-F9-D3-F4-1F-00-00-00-00-00-00-00-00 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b) Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On 05/11/2009 06:35 AM, Daniel P. Berrange wrote:
On Fri, May 08, 2009 at 01:52:24PM -0400, Laine Stump wrote:
From: Laine Stump <laine@redhat.com>
--- include/libvirt/libvirt.h | 18 ++ include/libvirt/libvirt.h.in | 18 ++ include/libvirt/virterror.h | 4 + src/datatypes.h | 25 ++ src/driver.h | 60 ++++ src/libvirt.c | 695 ++++++++++++++++++++++++++++++++++++++++++ src/util.h | 2 - src/virterror.c | 21 ++ 8 files changed, 841 insertions(+), 2 deletions(-)
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index 91af6fd..b0d93a2 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -433,6 +433,24 @@ extern virConnectAuthPtr virConnectAuthPtrDefault;
#define VIR_UUID_STRING_BUFLEN (36+1)
+/** + * VIR_MAC_BUFLEN: + * + * This macro provides the length of the buffer required + * for an interface MAC address + */ + +#define VIR_MAC_BUFLEN (6) + +/** + * VIR_MAC_STRING_BUFLEN: + * + * This macro provides the length of the buffer required + * for virInterfaceGetMACString() + */ + +#define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3) +
Since this is now in our public API, I'm wondering whether we shouldn't make the buflen longer. 6 bytes is fine with wired ethernet, but I'm not sure its sufficient for all network device types in general.
eg, my wmaster0 device has a rather longer hardware address
wmaster0 Link encap:UNSPEC HWaddr 00-13-02-B9-F9-D3-F4-1F-00-00-00-00-00-00-00-00 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Yes, tun interfaces too. Since this is binary data rather than a null-terminated string, we need to decide among the following three choices: 1) have a fixed length (how long? is 16 bytes long enough?) and zero-fill the shorter ones. 2) Add a macLen arg to any API function that uses mac address (this will need to be a return arg in some cases too) 3) Only provide the versions of the functions that accept/use ASCII mac address args. Also, this has ramifications on other code outside virInterface* using VIR_MAC_BUFLEN, so there will probably need to be a patch separate from this series that grows VIR_MAC_BUFLEN and fixes that other code accordingly Any opinion on how to proceed?

On Mon, May 11, 2009 at 03:29:42PM -0400, Laine Stump wrote:
On 05/11/2009 06:35 AM, Daniel P. Berrange wrote:
On Fri, May 08, 2009 at 01:52:24PM -0400, Laine Stump wrote:
From: Laine Stump <laine@redhat.com>
--- include/libvirt/libvirt.h | 18 ++ include/libvirt/libvirt.h.in | 18 ++ include/libvirt/virterror.h | 4 + src/datatypes.h | 25 ++ src/driver.h | 60 ++++ src/libvirt.c | 695 ++++++++++++++++++++++++++++++++++++++++++ src/util.h | 2 - src/virterror.c | 21 ++ 8 files changed, 841 insertions(+), 2 deletions(-)
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h index 91af6fd..b0d93a2 100644 --- a/include/libvirt/libvirt.h +++ b/include/libvirt/libvirt.h @@ -433,6 +433,24 @@ extern virConnectAuthPtr virConnectAuthPtrDefault; #define VIR_UUID_STRING_BUFLEN (36+1) +/** + * VIR_MAC_BUFLEN: + * + * This macro provides the length of the buffer required + * for an interface MAC address + */ + +#define VIR_MAC_BUFLEN (6) + +/** + * VIR_MAC_STRING_BUFLEN: + * + * This macro provides the length of the buffer required + * for virInterfaceGetMACString() + */ + +#define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3) +
Since this is now in our public API, I'm wondering whether we shouldn't make the buflen longer. 6 bytes is fine with wired ethernet, but I'm not sure its sufficient for all network device types in general.
eg, my wmaster0 device has a rather longer hardware address
wmaster0 Link encap:UNSPEC HWaddr 00-13-02-B9-F9-D3-F4-1F-00-00-00-00-00-00-00-00 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
Yes, tun interfaces too. Since this is binary data rather than a null-terminated string, we need to decide among the following three choices:
1) have a fixed length (how long? is 16 bytes long enough?) and zero-fill the shorter ones.
2) Add a macLen arg to any API function that uses mac address (this will need to be a return arg in some cases too)
3) Only provide the versions of the functions that accept/use ASCII mac address args.
IMHO, I would play safe at this point and pick 3) First it's sufficient, from the ASCII version people can usually derive the binary one if they really need it, but mostly I think people asked for those interfaces at the libvirt level because they wanted the ability to not mess with the low level stuff, so we should focuse on the high level. And if this proves unsufficient we can stil add new APIs based on the people feedback.
Also, this has ramifications on other code outside virInterface* using VIR_MAC_BUFLEN, so there will probably need to be a patch separate from this series that grows VIR_MAC_BUFLEN and fixes that other code accordingly
Any opinion on how to proceed?
I would go for 3) but keep the 2 macros internally either in the internals.h file or in a network header and try to make sure we use them everywhere :-) 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/

On Wed, May 13, 2009 at 11:46:58AM +0200, Daniel Veillard wrote:
On Mon, May 11, 2009 at 03:29:42PM -0400, Laine Stump wrote:
Yes, tun interfaces too. Since this is binary data rather than a null-terminated string, we need to decide among the following three choices:
1) have a fixed length (how long? is 16 bytes long enough?) and zero-fill the shorter ones.
2) Add a macLen arg to any API function that uses mac address (this will need to be a return arg in some cases too)
3) Only provide the versions of the functions that accept/use ASCII mac address args.
IMHO, I would play safe at this point and pick 3) First it's sufficient, from the ASCII version people can usually derive the binary one if they really need it, but mostly I think people asked for those interfaces at the libvirt level because they wanted the ability to not mess with the low level stuff, so we should focuse on the high level. And if this proves unsufficient we can stil add new APIs based on the people feedback.
Ok, so we just need to get rid of the constants in the public header file, and remove these APis virInterfacePtr virInterfaceLookupByMAC (virConnectPtr conn, const unsigned char *mac); int virInterfaceGetMAC (virInterfacePtr interface, unsigned char *mac); and change the remote_protocol.x file to use 'remote_nonnull_string' instead of the fixed length mac addr on the wire. And in the virInterfacePtr struct in src/datatypes.c also use the null terminated string, instead of fixed byte array. Regards, Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Wed, May 13, 2009 at 10:57:13AM +0100, Daniel P. Berrange wrote:
On Wed, May 13, 2009 at 11:46:58AM +0200, Daniel Veillard wrote:
On Mon, May 11, 2009 at 03:29:42PM -0400, Laine Stump wrote:
Yes, tun interfaces too. Since this is binary data rather than a null-terminated string, we need to decide among the following three choices:
1) have a fixed length (how long? is 16 bytes long enough?) and zero-fill the shorter ones.
2) Add a macLen arg to any API function that uses mac address (this will need to be a return arg in some cases too)
3) Only provide the versions of the functions that accept/use ASCII mac address args.
IMHO, I would play safe at this point and pick 3) First it's sufficient, from the ASCII version people can usually derive the binary one if they really need it, but mostly I think people asked for those interfaces at the libvirt level because they wanted the ability to not mess with the low level stuff, so we should focuse on the high level. And if this proves unsufficient we can stil add new APIs based on the people feedback.
Ok, so we just need to get rid of the constants in the public header file, and remove these APis
virInterfacePtr virInterfaceLookupByMAC (virConnectPtr conn, const unsigned char *mac);
int virInterfaceGetMAC (virInterfacePtr interface, unsigned char *mac);
and change the remote_protocol.x file to use 'remote_nonnull_string' instead of the fixed length mac addr on the wire.
And in the virInterfacePtr struct in src/datatypes.c also use the null terminated string, instead of fixed byte array.
Yes I think that's the simpler, and doesn't prevent adding something to that intent later if the need arise. 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/

On 05/13/2009 07:29 AM, Daniel Veillard wrote:
On Wed, May 13, 2009 at 10:57:13AM +0100, Daniel P. Berrange wrote:
On Wed, May 13, 2009 at 11:46:58AM +0200, Daniel Veillard wrote:
On Mon, May 11, 2009 at 03:29:42PM -0400, Laine Stump wrote:
Yes, tun interfaces too. Since this is binary data rather than a null-terminated string, we need to decide among the following three choices:
1) have a fixed length (how long? is 16 bytes long enough?) and zero-fill the shorter ones.
2) Add a macLen arg to any API function that uses mac address (this will need to be a return arg in some cases too)
3) Only provide the versions of the functions that accept/use ASCII mac address args.
IMHO, I would play safe at this point and pick 3) First it's sufficient, from the ASCII version people can usually derive the binary one if they really need it, but mostly I think people asked for those interfaces at the libvirt level because they wanted the ability to not mess with the low level stuff, so we should focuse on the high level. And if this proves unsufficient we can stil add new APIs based on the people feedback.
Ok, so we just need to get rid of the constants in the public header file, and remove these APis
virInterfacePtr virInterfaceLookupByMAC (virConnectPtr conn, const unsigned char *mac);
int virInterfaceGetMAC (virInterfacePtr interface, unsigned char *mac);
and change the remote_protocol.x file to use 'remote_nonnull_string' instead of the fixed length mac addr on the wire.
And in the virInterfacePtr struct in src/datatypes.c also use the null terminated string, instead of fixed byte array.
Yes I think that's the simpler, and doesn't prevent adding something to that intent later if the need arise.
Another advantage of this is that it can be done independent of fixing other uses of mac address in the code. I'm starting on this right now. (After a morning delay for a kindergarten presentation on Turkey, and another delay for a train of realtors traipsing through our house)

--- 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 | 50 +++++ qemud/remote_protocol.c | 156 ++++++++++++++++ qemud/remote_protocol.h | 127 +++++++++++++ qemud/remote_protocol.x | 90 +++++++++- src/datatypes.c | 154 ++++++++++++++++ src/datatypes.h | 6 + src/libvirt.c | 10 - src/remote_internal.c | 351 ++++++++++++++++++++++++++++++++++++ 12 files changed, 1245 insertions(+), 11 deletions(-) diff --git a/qemud/remote.c b/qemud/remote.c index 8d24a3a..6dfd83a 100644 --- a/qemud/remote.c +++ b/qemud/remote.c @@ -60,10 +60,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); @@ -2559,6 +2561,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 +remoteDispatchInterfaceLookupByMac (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + virConnectPtr conn, + remote_error *rerr, + remote_interface_lookup_by_mac_args *args, + remote_interface_lookup_by_mac_ret *ret) +{ + virInterfacePtr interface; + + interface = virInterfaceLookupByMAC (conn, (unsigned char *) 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, @@ -4527,6 +4748,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, BAD_CAST interface.mac); +} + static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool) { @@ -4558,6 +4785,14 @@ make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src) } static void +make_nonnull_interface (remote_nonnull_interface *interface_dst, + virInterfacePtr interface_src) +{ + interface_dst->name = strdup (interface_src->name); + memcpy (interface_dst->mac, interface_src->mac, VIR_MAC_BUFLEN); +} + +static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src) { pool_dst->name = strdup (pool_src->name); diff --git a/qemud/remote_dispatch_args.h b/qemud/remote_dispatch_args.h index 58eccf5..2297a48 100644 --- a/qemud/remote_dispatch_args.h +++ b/qemud/remote_dispatch_args.h @@ -105,3 +105,11 @@ remote_domain_get_security_label_args val_remote_domain_get_security_label_args; 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_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_args val_remote_interface_lookup_by_mac_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 96dcb2a..80044c1 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 remoteDispatchInterfaceLookupByMac( + struct qemud_server *server, + struct qemud_client *client, + virConnectPtr conn, + remote_error *err, + remote_interface_lookup_by_mac_args *args, + remote_interface_lookup_by_mac_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 3325c8b..1c5380a 100644 --- a/qemud/remote_dispatch_ret.h +++ b/qemud/remote_dispatch_ret.h @@ -89,3 +89,9 @@ remote_domain_get_security_label_ret val_remote_domain_get_security_label_ret; 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_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_ret val_remote_interface_lookup_by_mac_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 ac7f9b9..68e67e5 100644 --- a/qemud/remote_dispatch_table.h +++ b/qemud/remote_dispatch_table.h @@ -627,3 +627,53 @@ .args_filter = (xdrproc_t) xdr_remote_node_device_destroy_args, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* (unused) => 125 */ + .fn = NULL, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_void, +}, +{ /* 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, +}, +{ /* InterfaceLookupByMac => 129 */ + .fn = (dispatch_fn) remoteDispatchInterfaceLookupByMac, + .args_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_args, + .ret_filter = (xdrproc_t) xdr_remote_interface_lookup_by_mac_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 af3c792..578857d 100644 --- a/qemud/remote_protocol.c +++ b/qemud/remote_protocol.c @@ -36,6 +36,15 @@ xdr_remote_uuid (XDR *xdrs, remote_uuid objp) } bool_t +xdr_remote_mac (XDR *xdrs, remote_mac objp) +{ + + if (!xdr_opaque (xdrs, objp, VIR_MAC_BUFLEN)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_nonnull_domain (XDR *xdrs, remote_nonnull_domain *objp) { @@ -60,6 +69,17 @@ xdr_remote_nonnull_network (XDR *xdrs, remote_nonnull_network *objp) } 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_mac (xdrs, objp->mac)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_nonnull_storage_pool (XDR *xdrs, remote_nonnull_storage_pool *objp) { @@ -1478,6 +1498,142 @@ xdr_remote_network_set_autostart_args (XDR *xdrs, remote_network_set_autostart_a } 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_args (XDR *xdrs, remote_interface_lookup_by_mac_args *objp) +{ + + if (!xdr_remote_mac (xdrs, objp->mac)) + return FALSE; + return TRUE; +} + +bool_t +xdr_remote_interface_lookup_by_mac_ret (XDR *xdrs, remote_interface_lookup_by_mac_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_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_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_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_int (xdrs, &objp->flags)) + return FALSE; + return TRUE; +} + +bool_t xdr_remote_auth_list_ret (XDR *xdrs, remote_auth_list_ret *objp) { char **objp_cpp0 = (char **) (void *) &objp->types.types_val; diff --git a/qemud/remote_protocol.h b/qemud/remote_protocol.h index 9d67e58..7201720 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 @@ -44,6 +45,8 @@ typedef remote_nonnull_string *remote_string; typedef char remote_uuid[VIR_UUID_BUFLEN]; +typedef char remote_mac[VIR_MAC_BUFLEN]; + struct remote_nonnull_domain { remote_nonnull_string name; remote_uuid uuid; @@ -57,6 +60,12 @@ struct remote_nonnull_network { }; typedef struct remote_nonnull_network remote_nonnull_network; +struct remote_nonnull_interface { + remote_nonnull_string name; + remote_mac mac; +}; +typedef struct remote_nonnull_interface remote_nonnull_interface; + struct remote_nonnull_storage_pool { remote_nonnull_string name; remote_uuid uuid; @@ -822,6 +831,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_args { + remote_mac mac; +}; +typedef struct remote_interface_lookup_by_mac_args remote_interface_lookup_by_mac_args; + +struct remote_interface_lookup_by_mac_ret { + remote_nonnull_interface interface; +}; +typedef struct remote_interface_lookup_by_mac_ret remote_interface_lookup_by_mac_ret; + +struct remote_interface_get_xml_desc_args { + remote_nonnull_interface interface; + 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; + 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; + int flags; +}; +typedef struct remote_interface_create_args remote_interface_create_args; + +struct remote_interface_destroy_args { + remote_nonnull_interface interface; + int flags; +}; +typedef struct remote_interface_destroy_args remote_interface_destroy_args; + struct remote_auth_list_ret { struct { u_int types_len; @@ -1415,6 +1501,15 @@ enum remote_procedure { REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122, REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123, REMOTE_PROC_NODE_DEVICE_DESTROY = 124, + REMOTE_PROC_NUM_OF_INTERFACES = 126, + REMOTE_PROC_LIST_INTERFACES = 127, + REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, + REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC = 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; @@ -1448,8 +1543,10 @@ typedef struct remote_message_header remote_message_header; extern bool_t xdr_remote_nonnull_string (XDR *, remote_nonnull_string*); extern bool_t xdr_remote_string (XDR *, remote_string*); extern bool_t xdr_remote_uuid (XDR *, remote_uuid); +extern bool_t xdr_remote_mac (XDR *, remote_mac); 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*); @@ -1573,6 +1670,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_args (XDR *, remote_interface_lookup_by_mac_args*); +extern bool_t xdr_remote_interface_lookup_by_mac_ret (XDR *, remote_interface_lookup_by_mac_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*); @@ -1662,8 +1773,10 @@ extern bool_t xdr_remote_message_header (XDR *, remote_message_header*); extern bool_t xdr_remote_nonnull_string (); extern bool_t xdr_remote_string (); extern bool_t xdr_remote_uuid (); +extern bool_t xdr_remote_mac (); 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 (); @@ -1787,6 +1900,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_args (); +extern bool_t xdr_remote_interface_lookup_by_mac_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 2c79949..6abc908 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; @@ -133,6 +136,9 @@ const REMOTE_SECURITY_DOI_MAX = VIR_SECURITY_DOI_BUFLEN; /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; +/* MAC. VIR_MAC_BUFLEN definition comes from libvirt.h */ +typedef opaque remote_mac[VIR_MAC_BUFLEN]; + /* A domain which may not be NULL. */ struct remote_nonnull_domain { remote_nonnull_string name; @@ -146,6 +152,12 @@ struct remote_nonnull_network { remote_uuid uuid; }; +/* An interface which may not be NULL. */ +struct remote_nonnull_interface { + remote_nonnull_string name; + remote_mac mac; +}; + /* A storage pool which may not be NULL. */ struct remote_nonnull_storage_pool { remote_nonnull_string name; @@ -770,6 +782,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<REMOTE_INTERFACE_NAME_LIST_MAX>; +}; + +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_args { + remote_mac mac; +}; + +struct remote_interface_lookup_by_mac_ret { + remote_nonnull_interface interface; +}; + +struct remote_interface_get_xml_desc_args { + remote_nonnull_interface interface; + int flags; +}; + +struct remote_interface_get_xml_desc_ret { + remote_nonnull_string xml; +}; + +struct remote_interface_define_xml_args { + remote_nonnull_string xml; + 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; + int flags; +}; + +struct remote_interface_destroy_args { + remote_nonnull_interface interface; + int flags; +}; + + +/* Auth calls: */ + struct remote_auth_list_ret { remote_auth_type types<REMOTE_AUTH_TYPE_LIST_MAX>; }; @@ -1286,7 +1363,18 @@ enum remote_procedure { REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122, REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123, - REMOTE_PROC_NODE_DEVICE_DESTROY = 124 + REMOTE_PROC_NODE_DEVICE_DESTROY = 124, + + REMOTE_PROC_NUM_OF_INTERFACES = 126, + REMOTE_PROC_LIST_INTERFACES = 127, + REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, + REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC = 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/datatypes.c b/src/datatypes.c index b1013f2..8593e2b 100644 --- a/src/datatypes.c +++ b/src/datatypes.c @@ -67,6 +67,20 @@ virNetworkFreeName(virNetworkPtr network, const char *name ATTRIBUTE_UNUSED) } /** + * 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) @@ -488,6 +510,138 @@ 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 unsigned 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->magic = VIR_INTERFACE_MAGIC; + ret->conn = conn; + if (mac != NULL) + memcpy(&(ret->mac[0]), mac, VIR_MAC_BUFLEN); + + 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); + } + 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); + + 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 * @name: pointer to the storage pool name diff --git a/src/datatypes.h b/src/datatypes.h index deac9df..e56755b 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -145,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 */ @@ -250,6 +251,11 @@ virNetworkPtr virGetNetwork(virConnectPtr conn, const unsigned char *uuid); int virUnrefNetwork(virNetworkPtr network); +virInterfacePtr virGetInterface(virConnectPtr conn, + const char *name, + const unsigned char *mac); +int virUnrefInterface(virInterfacePtr interface); + virStoragePoolPtr virGetStoragePool(virConnectPtr conn, const char *name, const unsigned char *uuid); diff --git a/src/libvirt.c b/src/libvirt.c index 4bd85a7..15f107a 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -5958,18 +5958,8 @@ virInterfaceFree(virInterfacePtr interface) virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); return (-1); } -#if 0 - /* - * FIXME: This needs to be uncommented when the stubs are replaced - * with actual functionality. - */ - if (virUnrefInterface(interface) < 0) return (-1); -#else - interface->refs--; -#endif - return(0); } diff --git a/src/remote_internal.c b/src/remote_internal.c index 24226e5..6bc2b9c 100644 --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -211,11 +211,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); @@ -3684,6 +3686,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 +remoteInterfaceLookupByMAC (virConnectPtr conn, + const unsigned char *mac) +{ + virInterfacePtr interface = NULL; + remote_interface_lookup_by_mac_args args; + remote_interface_lookup_by_mac_ret ret; + struct private_data *priv = conn->interfacePrivateData; + + remoteDriverLock(priv); + + memcpy (args.mac, mac, VIR_MAC_BUFLEN); + + memset (&ret, 0, sizeof ret); + if (call (conn, priv, 0, REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC, + (xdrproc_t) xdr_remote_interface_lookup_by_mac_args, (char *) &args, + (xdrproc_t) xdr_remote_interface_lookup_by_mac_ret, (char *) &ret) == -1) + goto done; + + interface = get_nonnull_interface (conn, ret.interface); + xdr_free ((xdrproc_t) &xdr_remote_interface_lookup_by_mac_ret, (char *) &ret); + +done: + remoteDriverUnlock(priv); + return interface; +} + +static char * +remoteInterfaceGetXMLDesc (virInterfacePtr interface, + 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, + 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, + 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, + 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 remoteStorageOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags) @@ -6851,6 +7172,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, BAD_CAST interface.mac); +} + static virStoragePoolPtr get_nonnull_storage_pool (virConnectPtr conn, remote_nonnull_storage_pool pool) { @@ -6886,6 +7213,14 @@ make_nonnull_network (remote_nonnull_network *net_dst, virNetworkPtr net_src) } static void +make_nonnull_interface (remote_nonnull_interface *interface_dst, + virInterfacePtr interface_src) +{ + interface_dst->name = interface_src->name; + memcpy (interface_dst->mac, interface_src->mac, VIR_MAC_BUFLEN); +} + +static void make_nonnull_storage_pool (remote_nonnull_storage_pool *pool_dst, virStoragePoolPtr pool_src) { pool_dst->name = pool_src->name; @@ -6996,6 +7331,21 @@ static virNetworkDriver network_driver = { .networkSetAutostart = remoteNetworkSetAutostart, }; +static virInterfaceDriver interface_driver = { + .name = "remote", + .open = remoteInterfaceOpen, + .close = remoteInterfaceClose, + .numOfInterfaces = remoteNumOfInterfaces, + .listInterfaces = remoteListInterfaces, + .interfaceLookupByName = remoteInterfaceLookupByName, + .interfaceLookupByMAC = remoteInterfaceLookupByMAC, + .interfaceGetXMLDesc = remoteInterfaceGetXMLDesc, + .interfaceDefineXML = remoteInterfaceDefineXML, + .interfaceUndefine = remoteInterfaceUndefine, + .interfaceCreate = remoteInterfaceCreate, + .interfaceDestroy = remoteInterfaceDestroy, +}; + static virStorageDriver storage_driver = { .name = "remote", .open = remoteStorageOpen, @@ -7067,6 +7417,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 -- 1.6.0.6

On Fri, May 08, 2009 at 01:52:25PM -0400, Laine Stump wrote:
--- 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 | 50 +++++ qemud/remote_protocol.c | 156 ++++++++++++++++ qemud/remote_protocol.h | 127 +++++++++++++ qemud/remote_protocol.x | 90 +++++++++- src/datatypes.c | 154 ++++++++++++++++ src/datatypes.h | 6 + src/libvirt.c | 10 - src/remote_internal.c | 351 ++++++++++++++++++++++++++++++++++++ 12 files changed, 1245 insertions(+), 11 deletions(-)
ACK, this all looks fine. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

--- src/libvirt_public.syms | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b8f9128..cd369cb 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -264,4 +264,24 @@ LIBVIRT_0.6.3 { virNodeDeviceDestroy; } LIBVIRT_0.6.1; +LIBVIRT_0.6.4 { + global: + virInterfaceGetConnect; + virConnectNumOfInterfaces; + virConnectListInterfaces; + virInterfaceLookupByName; + virInterfaceLookupByMAC; + virInterfaceLookupByMACString; + virInterfaceGetName; + virInterfaceGetMAC; + virInterfaceGetMACString; + virInterfaceGetXMLDesc; + virInterfaceRef; + virInterfaceFree; + virInterfaceDefineXML; + virInterfaceUndefine; + virInterfaceCreate; + virInterfaceDestroy; + +} LIBVIRT_0.6.3; # .... define new API here using predicted next version number .... -- 1.6.0.6

On Fri, May 08, 2009 at 01:52:26PM -0400, Laine Stump wrote:
--- src/libvirt_public.syms | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index b8f9128..cd369cb 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -264,4 +264,24 @@ LIBVIRT_0.6.3 { virNodeDeviceDestroy; } LIBVIRT_0.6.1;
+LIBVIRT_0.6.4 { + global: + virInterfaceGetConnect; + virConnectNumOfInterfaces; + virConnectListInterfaces; + virInterfaceLookupByName; + virInterfaceLookupByMAC; + virInterfaceLookupByMACString; + virInterfaceGetName; + virInterfaceGetMAC; + virInterfaceGetMACString; + virInterfaceGetXMLDesc; + virInterfaceRef; + virInterfaceFree; + virInterfaceDefineXML; + virInterfaceUndefine; + virInterfaceCreate; + virInterfaceDestroy; + +} LIBVIRT_0.6.3; # .... define new API here using predicted next version number .... --
ACK, standard stuff. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

From: Laine Stump <laine@redhat.com> --- configure.in | 35 ++++++++++++++++++++++++++++++++--- src/Makefile.am | 5 +++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 1cdb64c..4ce4342 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 @@ -789,9 +790,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]) @@ -1376,6 +1399,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([]) @@ -1443,6 +1467,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/src/Makefile.am b/src/Makefile.am index fd692b4..7d7ef74 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -351,6 +351,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 -- 1.6.0.6

On Fri, May 08, 2009 at 01:52:27PM -0400, Laine Stump wrote:
From: Laine Stump <laine@redhat.com>
--- configure.in | 35 ++++++++++++++++++++++++++++++++--- src/Makefile.am | 5 +++++ 2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/configure.in b/configure.in index 1cdb64c..4ce4342 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 @@ -789,9 +790,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]) @@ -1376,6 +1399,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([]) @@ -1443,6 +1467,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/src/Makefile.am b/src/Makefile.am index fd692b4..7d7ef74 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -351,6 +351,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
ACK, looks good to me. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

On Fri, May 08, 2009 at 01:52:22PM -0400, Laine Stump wrote:
These 5 patches contain the public virInterface*() API definition, the local plumbing, and the RPC glue. The test driver and real driver are still TBI, but having this in will allow other people to work on related stuff.
Okay, this is all good to commit IMHO except for the raw network address problem, Could you generate a patch subset, dropping the second one and the non-ascii interfaces, using the unsigned int flags, and I guess we can apply this safely, then we can separately discuss extending the API for raw addresses (or not/delay them).
Other things still needed:
python/java bindings
For example the raw API adresses may not be a very good match for python bindings, one more reason IMHO to avoid the duplication.
cli commands in virsh
Yes especially if we can provide relatively high level ones, not limit ourselves to command taking an XML in, I guess this can go a long way to help where current users are getting stuck. 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/
participants (3)
-
Daniel P. Berrange
-
Daniel Veillard
-
Laine Stump