On Tue, May 19, 2009 at 12:51:24PM -0400, Laine Stump wrote: > From: Laine Stump <laine@xxxxxxxxxx> > > --- > include/libvirt/virterror.h | 4 + > src/datatypes.h | 25 ++ > src/driver.h | 60 +++++ > src/libvirt.c | 607 +++++++++++++++++++++++++++++++++++++++++++ > src/virterror.c | 21 ++ > 5 files changed, 717 insertions(+), 0 deletions(-) > > diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h > index 4677ebc..3613ac2 100644 > --- a/include/libvirt/virterror.h > +++ b/include/libvirt/virterror.h > @@ -63,6 +63,7 @@ typedef enum { > VIR_FROM_XEN_INOTIFY, /* Error from xen inotify layer */ > VIR_FROM_SECURITY, /* Error from security framework */ > VIR_FROM_VBOX, /* Error from VirtualBox driver */ > + VIR_FROM_INTERFACE, /* Error when operating on an interface */ > } virErrorDomain; > > > @@ -158,6 +159,9 @@ typedef enum { > VIR_ERR_NO_NODE_DEVICE,/* node device not found */ > VIR_ERR_NO_SECURITY_MODEL, /* security model not found */ > VIR_ERR_OPERATION_INVALID, /* operation is not applicable at this time */ > + VIR_WAR_NO_INTERFACE, /* failed to start interface driver */ > + VIR_ERR_NO_INTERFACE, /* interface driver not running */ > + VIR_ERR_INVALID_INTERFACE, /* invalid interface object */ > } virErrorNumber; > > /** > diff --git a/src/datatypes.h b/src/datatypes.h > index 5956c5d..756e0a5 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 */ > + char *mac; /* the interface MAC address */ > +}; > + > +/** > * _virStoragePool: > * > * Internal structure associated to a storage pool > diff --git a/src/driver.h b/src/driver.h > index b8e0a04..01758a9 100644 > --- a/src/driver.h > +++ b/src/driver.h > @@ -488,6 +488,65 @@ struct _virNetworkDriver { > virDrvNetworkSetAutostart networkSetAutostart; > }; > > +/*-------*/ > +typedef int > + (*virDrvNumOfInterfaces) (virConnectPtr conn); > +typedef int > + (*virDrvListInterfaces) (virConnectPtr conn, > + char **const names, > + int maxnames); > +typedef virInterfacePtr > + (*virDrvInterfaceLookupByName) (virConnectPtr conn, > + const char *name); > +typedef virInterfacePtr > + (*virDrvInterfaceLookupByMACString) (virConnectPtr conn, > + const char *mac); > + > +typedef char * > + (*virDrvInterfaceGetXMLDesc) (virInterfacePtr interface, > + unsigned int flags); > + > +typedef virInterfacePtr > + (*virDrvInterfaceDefineXML) (virConnectPtr conn, > + const char *xmlDesc, > + unsigned int flags); > +typedef int > + (*virDrvInterfaceUndefine) (virInterfacePtr interface); > +typedef int > + (*virDrvInterfaceCreate) (virInterfacePtr interface, > + unsigned int flags); > +typedef int > + (*virDrvInterfaceDestroy) (virInterfacePtr interface, > + unsigned int flags); > + > +typedef struct _virInterfaceDriver virInterfaceDriver; > +typedef virInterfaceDriver *virInterfaceDriverPtr; > + > +/** > + * _virInterfaceDriver: > + * > + * Structure associated to a network virtualization driver, defining the various > + * entry points for it. > + * > + * All drivers must support the following fields/methods: > + * - open > + * - close > + */ > +struct _virInterfaceDriver { > + const char *name; /* the name of the driver */ > + virDrvOpen open; > + virDrvClose close; > + virDrvNumOfInterfaces numOfInterfaces; > + virDrvListInterfaces listInterfaces; > + virDrvInterfaceLookupByName interfaceLookupByName; > + virDrvInterfaceLookupByMACString interfaceLookupByMACString; > + virDrvInterfaceGetXMLDesc interfaceGetXMLDesc; > + virDrvInterfaceDefineXML interfaceDefineXML; > + virDrvInterfaceUndefine interfaceUndefine; > + virDrvInterfaceCreate interfaceCreate; > + virDrvInterfaceDestroy interfaceDestroy; > +}; > + > > typedef int > (*virDrvConnectNumOfStoragePools) (virConnectPtr conn); > @@ -724,6 +783,7 @@ struct _virDeviceMonitor { > */ > int virRegisterDriver(virDriverPtr); > int virRegisterNetworkDriver(virNetworkDriverPtr); > +int virRegisterInterfaceDriver(virInterfaceDriverPtr); > int virRegisterStorageDriver(virStorageDriverPtr); > int virRegisterDeviceMonitor(virDeviceMonitorPtr); > #ifdef WITH_LIBVIRTD > diff --git a/src/libvirt.c b/src/libvirt.c > index f1f81b3..f63a47b 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,534 @@ error: > return -1; > } > > +/** > + * virInterfaceGetConnect: > + * @net: pointer to a interface > + * > + * Provides the connection pointer associated with an interface. The > + * reference counter on the connection is not increased by this > + * call. > + * > + * WARNING: When writing libvirt bindings in other languages, do > + * not use this function. Instead, store the connection and > + * the interface object together. > + * > + * Returns the virConnectPtr or NULL in case of failure. > + */ > +virConnectPtr > +virInterfaceGetConnect (virInterfacePtr interface) > +{ > + DEBUG("interface=%p", interface); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECTED_INTERFACE (interface)) { > + virLibInterfaceError (NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); > + return NULL; > + } > + return interface->conn; > +} > + > +/** > + * virConnectNumOfInterfaces: > + * @conn: pointer to the hypervisor connection > + * > + * Provides the number of interfaces on the physical host. > + * > + * Returns the number of interface found or -1 in case of error > + */ > +int > +virConnectNumOfInterfaces(virConnectPtr conn) > +{ > + DEBUG("conn=%p", conn); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECT(conn)) { > + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); > + return (-1); > + } > + > + if (conn->interfaceDriver && conn->interfaceDriver->numOfInterfaces) { > + int ret; > + ret = conn->interfaceDriver->numOfInterfaces (conn); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(conn); > + return -1; > +} > + > +/** > + * virConnectListInterfaces: > + * @conn: pointer to the hypervisor connection > + * @names: array to collect the list of names of interfaces > + * @maxnames: size of @names > + * > + * Collect the list of physical host interfaces, and store their names in @names > + * > + * Returns the number of interfaces found or -1 in case of error > + */ > +int > +virConnectListInterfaces(virConnectPtr conn, char **const names, int maxnames) > +{ > + DEBUG("conn=%p, names=%p, maxnames=%d", conn, names, maxnames); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECT(conn)) { > + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); > + return (-1); > + } > + > + if ((names == NULL) || (maxnames < 0)) { > + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); > + goto error; > + } > + > + if (conn->interfaceDriver && conn->interfaceDriver->listInterfaces) { > + int ret; > + ret = conn->interfaceDriver->listInterfaces (conn, names, maxnames); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(conn); > + return -1; > +} > + > +/** > + * virInterfaceLookupByName: > + * @conn: pointer to the hypervisor connection > + * @name: name for the interface > + * > + * Try to lookup an interface on the given hypervisor based on its name. > + * > + * Returns a new interface object or NULL in case of failure. If the > + * interface cannot be found, then VIR_ERR_NO_INTERFACE error is raised. > + */ > +virInterfacePtr > +virInterfaceLookupByName(virConnectPtr conn, const char *name) > +{ > + DEBUG("conn=%p, name=%s", conn, name); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECT(conn)) { > + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); > + return (NULL); > + } > + if (name == NULL) { > + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); > + goto error; > + } > + > + if (conn->interfaceDriver && conn->interfaceDriver->interfaceLookupByName) { > + virInterfacePtr ret; > + ret = conn->interfaceDriver->interfaceLookupByName (conn, name); > + if (!ret) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(conn); > + return NULL; > +} > + > +/** > + * virInterfaceLookupByMACString: > + * @conn: pointer to the hypervisor connection > + * @macstr: the MAC for the interface (null-terminated ASCII format) > + * > + * Try to lookup an interface on the given hypervisor based on its MAC. > + * > + * Returns a new interface object or NULL in case of failure. If the > + * interface cannot be found, then VIR_ERR_NO_INTERFACE error is raised. > + */ > +virInterfacePtr > +virInterfaceLookupByMACString(virConnectPtr conn, const char *macstr) > +{ > + DEBUG("conn=%p, macstr=%s", conn, macstr); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECT(conn)) { > + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); > + return (NULL); > + } > + if (macstr == NULL) { > + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); > + goto error; > + } > + > + if (conn->interfaceDriver && conn->interfaceDriver->interfaceLookupByMACString) { > + virInterfacePtr ret; > + ret = conn->interfaceDriver->interfaceLookupByMACString (conn, macstr); > + if (!ret) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(conn); > + return NULL; > +} > + > +/** > + * virInterfaceGetName: > + * @interface: a interface object > + * > + * Get the public name for that interface > + * > + * Returns a pointer to the name or NULL, the string need not be deallocated > + * its lifetime will be the same as the interface object. > + */ > +const char * > +virInterfaceGetName(virInterfacePtr interface) > +{ > + DEBUG("interface=%p", interface); > + > + virResetLastError(); > + > + if (!VIR_IS_INTERFACE(interface)) { > + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); > + return (NULL); > + } > + return (interface->name); > +} > + > +/** > + * virInterfaceGetMACString: > + * @interface: a interface object > + * > + * Get the MAC for a interface as string. For more information about > + * MAC see RFC4122. > + * > + * Returns a pointer to the MAC address (in null-terminated ASCII > + * format) or NULL, the string need not be deallocated its lifetime > + * will be the same as the interface object. > + */ > +const char * > +virInterfaceGetMACString(virInterfacePtr interface) > +{ > + DEBUG("interface=%p", interface); > + > + virResetLastError(); > + > + if (!VIR_IS_INTERFACE(interface)) { > + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); > + return (NULL); > + } > + return (interface->mac); > +} > + > +/** > + * virInterfaceGetXMLDesc: > + * @interface: a interface object > + * @flags: and OR'ed set of extraction flags, not used yet > + * > + * Provide an XML description of the interface. The description may be reused > + * later to recreate the interface with virInterfaceCreateXML(). > + * > + * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error. > + * the caller must free() the returned value. > + */ > +char * > +virInterfaceGetXMLDesc(virInterfacePtr interface, unsigned int flags) > +{ > + virConnectPtr conn; > + DEBUG("interface=%p, flags=%d", interface, flags); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { > + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); > + return (NULL); > + } > + if (flags != 0) { > + virLibInterfaceError(interface, VIR_ERR_INVALID_ARG, __FUNCTION__); > + goto error; > + } > + > + conn = interface->conn; > + > + if (conn->interfaceDriver && conn->interfaceDriver->interfaceGetXMLDesc) { > + char *ret; > + ret = conn->interfaceDriver->interfaceGetXMLDesc (interface, flags); > + if (!ret) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(interface->conn); > + return NULL; > +} > + > +/** > + * virInterfaceDefineXML: > + * @conn: pointer to the hypervisor connection > + * @xml: the XML description for the interface, preferably in UTF-8 > + * @flags: and OR'ed set of extraction flags, not used yet > + * > + * Define an interface (or modify existing interface configuration) > + * > + * Returns NULL in case of error, a pointer to the interface otherwise > + */ > +virInterfacePtr > +virInterfaceDefineXML(virConnectPtr conn, const char *xml, unsigned int flags) > +{ > + DEBUG("conn=%p, xml=%s, flags=%d", conn, xml, flags); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECT(conn)) { > + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); > + return (NULL); > + } > + if (conn->flags & VIR_CONNECT_RO) { > + virLibConnError(conn, VIR_ERR_OPERATION_DENIED, __FUNCTION__); > + goto error; > + } > + if (xml == NULL) { > + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); > + goto error; > + } > + > + if (conn->interfaceDriver && conn->interfaceDriver->interfaceDefineXML) { > + virInterfacePtr ret; > + ret = conn->interfaceDriver->interfaceDefineXML (conn, xml, flags); > + if (!ret) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(conn); > + return NULL; > +} > + > +/** > + * virInterfaceUndefine: > + * @interface: pointer to a defined interface > + * > + * Undefine an interface, ie remove it from the config. > + * This does not free the associated virInterfacePtr object. > + * > + * Returns 0 in case of success, -1 in case of error > + */ > +int > +virInterfaceUndefine(virInterfacePtr interface) { > + virConnectPtr conn; > + DEBUG("interface=%p", interface); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { > + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); > + return (-1); > + } > + conn = interface->conn; > + if (conn->flags & VIR_CONNECT_RO) { > + virLibInterfaceError(interface, VIR_ERR_OPERATION_DENIED, __FUNCTION__); > + goto error; > + } > + > + if (conn->interfaceDriver && conn->interfaceDriver->interfaceUndefine) { > + int ret; > + ret = conn->interfaceDriver->interfaceUndefine (interface); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(interface->conn); > + return -1; > +} > + > +/** > + * virInterfaceCreate: > + * @interface: pointer to a defined interface > + * @flags: and OR'ed set of extraction flags, not used yet > + * > + * Activate an interface (ie call "ifup") > + * > + * Returns 0 in case of success, -1 in case of error > + */ > +int > +virInterfaceCreate(virInterfacePtr interface, unsigned int flags) > +{ > + virConnectPtr conn; > + DEBUG("interface=%p, flags=%d", interface, flags); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { > + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); > + return (-1); > + } > + conn = interface->conn; > + if (conn->flags & VIR_CONNECT_RO) { > + virLibInterfaceError(interface, VIR_ERR_OPERATION_DENIED, __FUNCTION__); > + goto error; > + } > + > + if (conn->interfaceDriver && conn->interfaceDriver->interfaceCreate) { > + int ret; > + ret = conn->interfaceDriver->interfaceCreate (interface, flags); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(interface->conn); > + return -1; > +} > + > +/** > + * virInterfaceDestroy: > + * @interface: an interface object > + * @flags: and OR'ed set of extraction flags, not used yet > + * > + * deactivate an interface (ie call "ifdown") > + * This does not remove the interface from the config, and > + * does not free the associated virInterfacePtr object. > + * > + * Returns 0 in case of success and -1 in case of failure. > + */ > +int > +virInterfaceDestroy(virInterfacePtr interface, unsigned int flags) > +{ > + virConnectPtr conn; > + DEBUG("interface=%p, flags=%d", interface, flags); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { > + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); > + return (-1); > + } > + > + conn = interface->conn; > + if (conn->flags & VIR_CONNECT_RO) { > + virLibInterfaceError(interface, VIR_ERR_OPERATION_DENIED, __FUNCTION__); > + goto error; > + } > + > + if (conn->interfaceDriver && conn->interfaceDriver->interfaceDestroy) { > + int ret; > + ret = conn->interfaceDriver->interfaceDestroy (interface, flags); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + /* Copy to connection error object for back compatability */ > + virSetConnError(interface->conn); > + return -1; > +} > + > +/** > + * virInterfaceRef: > + * @interface: the interface to hold a reference on > + * > + * Increment the reference count on the interface. For each > + * additional call to this method, there shall be a corresponding > + * call to virInterfaceFree to release the reference count, once > + * the caller no longer needs the reference to this object. > + * > + * This method is typically useful for applications where multiple > + * threads are using a connection, and it is required that the > + * connection remain open until all threads have finished using > + * it. ie, each new thread using a interface would increment > + * the reference count. > + * > + * Returns 0 in case of success, -1 in case of failure. > + */ > +int > +virInterfaceRef(virInterfacePtr interface) > +{ > + if ((!VIR_IS_CONNECTED_INTERFACE(interface))) { > + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); > + return(-1); > + } > + virMutexLock(&interface->conn->lock); > + DEBUG("interface=%p refs=%d", interface, interface->refs); > + interface->refs++; > + virMutexUnlock(&interface->conn->lock); > + return 0; > +} > + > +/** > + * virInterfaceFree: > + * @interface: a interface object > + * > + * Free the interface object. The interface itself is unaltered. > + * The data structure is freed and should not be used thereafter. > + * > + * Returns 0 in case of success and -1 in case of failure. > + */ > +int > +virInterfaceFree(virInterfacePtr interface) > +{ > + DEBUG("interface=%p", interface); > + > + virResetLastError(); > + > + if (!VIR_IS_CONNECTED_INTERFACE(interface)) { > + virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__); > + return (-1); > + } > +#if 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/virterror.c b/src/virterror.c > index e12608d..3af6544 100644 > --- a/src/virterror.c > +++ b/src/virterror.c > @@ -157,6 +157,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { > case VIR_FROM_VBOX: > dom = "VBOX "; > break; > + case VIR_FROM_INTERFACE: > + dom = "Interface "; > + break; > } > return(dom); > } > @@ -1024,6 +1027,24 @@ virErrorMsg(virErrorNumber error, const char *info) > else > errmsg = _("Requested operation is not valid: %s"); > break; > + case VIR_WAR_NO_INTERFACE: > + if (info == NULL) > + errmsg = _("Failed to find the interface"); > + else > + errmsg = _("Failed to find the interface: %s"); > + break; > + case VIR_ERR_NO_INTERFACE: > + if (info == NULL) > + errmsg = _("Interface not found"); > + else > + errmsg = _("Interface not found: %s"); > + break; > + case VIR_ERR_INVALID_INTERFACE: > + if (info == NULL) > + errmsg = _("invalid interface pointer in"); > + else > + errmsg = _("invalid interface pointer in %s"); > + break; > } > return (errmsg); > } > -- ACK, looks fine now 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 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list