This patch is the public API parts of the node device enumeration code. No changes since David's last submission of this, except for some Makefile tweaks Daniel diff -r 78738f80cf4c include/libvirt/libvirt.h --- a/include/libvirt/libvirt.h Wed Nov 12 21:05:32 2008 +0000 +++ b/include/libvirt/libvirt.h Wed Nov 12 21:11:46 2008 +0000 @@ -995,6 +995,74 @@ unsigned int flags); /* + * Host device enumeration + */ + +/** + * virNodeDevice: + * + * A virNodeDevice contains a node (host) device details. + */ + +typedef struct _virNodeDevice virNodeDevice; + +/** + * virNodeDevicePtr: + * + * A virNodeDevicePtr is a pointer to a virNodeDevice structure. Get + * one via virNodeDeviceLookupByKey, virNodeDeviceLookupByName, or + * virNodeDeviceCreate. Be sure to Call virNodeDeviceFree when done + * using a virNodeDevicePtr obtained from any of the above functions to + * avoid leaking memory. + */ + +typedef virNodeDevice *virNodeDevicePtr; + + +int virNodeNumOfDevices (virConnectPtr conn, + unsigned int flags); + +int virNodeListDevices (virConnectPtr conn, + char **const names, + int maxnames, + unsigned int flags); + +int virNodeNumOfDevicesByCap (virConnectPtr conn, + const char *cap, + unsigned int flags); + +int virNodeListDevicesByCap (virConnectPtr conn, + const char *cap, + char **const names, + int maxnames, + unsigned int flags); + +virNodeDevicePtr virNodeDeviceLookupByName (virConnectPtr conn, + const char *name); + +const char * virNodeDeviceGetName (virNodeDevicePtr dev); + +const char * virNodeDeviceGetParent (virNodeDevicePtr dev); + +int virNodeDeviceNumOfCaps (virNodeDevicePtr dev); + +int virNodeDeviceListCaps (virNodeDevicePtr dev, + char **const names, + int maxnames); + +char * virNodeDeviceGetXMLDesc (virNodeDevicePtr dev, + unsigned int flags); + +virNodeDevicePtr virNodeDeviceCreate (virConnectPtr conn, + const char *xml, + unsigned int flags); + +int virNodeDeviceDestroy (virNodeDevicePtr dev, + unsigned int flags); + +int virNodeDeviceFree (virNodeDevicePtr dev); + +/* * Domain Event Notification */ diff -r 78738f80cf4c include/libvirt/libvirt.h.in --- a/include/libvirt/libvirt.h.in Wed Nov 12 21:05:32 2008 +0000 +++ b/include/libvirt/libvirt.h.in Wed Nov 12 21:11:46 2008 +0000 @@ -995,6 +995,74 @@ unsigned int flags); /* + * Host device enumeration + */ + +/** + * virNodeDevice: + * + * A virNodeDevice contains a node (host) device details. + */ + +typedef struct _virNodeDevice virNodeDevice; + +/** + * virNodeDevicePtr: + * + * A virNodeDevicePtr is a pointer to a virNodeDevice structure. Get + * one via virNodeDeviceLookupByKey, virNodeDeviceLookupByName, or + * virNodeDeviceCreate. Be sure to Call virNodeDeviceFree when done + * using a virNodeDevicePtr obtained from any of the above functions to + * avoid leaking memory. + */ + +typedef virNodeDevice *virNodeDevicePtr; + + +int virNodeNumOfDevices (virConnectPtr conn, + unsigned int flags); + +int virNodeListDevices (virConnectPtr conn, + char **const names, + int maxnames, + unsigned int flags); + +int virNodeNumOfDevicesByCap (virConnectPtr conn, + const char *cap, + unsigned int flags); + +int virNodeListDevicesByCap (virConnectPtr conn, + const char *cap, + char **const names, + int maxnames, + unsigned int flags); + +virNodeDevicePtr virNodeDeviceLookupByName (virConnectPtr conn, + const char *name); + +const char * virNodeDeviceGetName (virNodeDevicePtr dev); + +const char * virNodeDeviceGetParent (virNodeDevicePtr dev); + +int virNodeDeviceNumOfCaps (virNodeDevicePtr dev); + +int virNodeDeviceListCaps (virNodeDevicePtr dev, + char **const names, + int maxnames); + +char * virNodeDeviceGetXMLDesc (virNodeDevicePtr dev, + unsigned int flags); + +virNodeDevicePtr virNodeDeviceCreate (virConnectPtr conn, + const char *xml, + unsigned int flags); + +int virNodeDeviceDestroy (virNodeDevicePtr dev, + unsigned int flags); + +int virNodeDeviceFree (virNodeDevicePtr dev); + +/* * Domain Event Notification */ diff -r 78738f80cf4c include/libvirt/virterror.h --- a/include/libvirt/virterror.h Wed Nov 12 21:05:32 2008 +0000 +++ b/include/libvirt/virterror.h Wed Nov 12 21:11:46 2008 +0000 @@ -58,6 +58,7 @@ VIR_FROM_STORAGE, /* Error from storage driver */ VIR_FROM_NETWORK, /* Error from network config */ VIR_FROM_DOMAIN, /* Error from domain config */ + VIR_FROM_DEVMONITOR,/* Error from node device monitor */ } virErrorDomain; @@ -148,6 +149,9 @@ VIR_WAR_NO_STORAGE, /* failed to start storage */ VIR_ERR_NO_STORAGE_POOL, /* storage pool not found */ VIR_ERR_NO_STORAGE_VOL, /* storage pool not found */ + VIR_WAR_NO_NODE, /* failed to start node driver */ + VIR_ERR_INVALID_NODE_DEVICE,/* invalid node device object */ + VIR_ERR_NO_NODE_DEVICE,/* node device not found */ } virErrorNumber; /** diff -r 78738f80cf4c src/datatypes.c --- a/src/datatypes.c Wed Nov 12 21:05:32 2008 +0000 +++ b/src/datatypes.c Wed Nov 12 21:11:46 2008 +0000 @@ -140,6 +140,9 @@ ret->storageVols = virHashCreate(20); if (ret->storageVols == NULL) goto failed; + ret->nodeDevices = virHashCreate(256); + if (ret->nodeDevices == NULL) + goto failed; pthread_mutex_init(&ret->lock, NULL); @@ -156,6 +159,8 @@ virHashFree(ret->storagePools, (virHashDeallocator) virStoragePoolFreeName); if (ret->storageVols != NULL) virHashFree(ret->storageVols, (virHashDeallocator) virStorageVolFreeName); + if (ret->nodeDevices != NULL) + virHashFree(ret->nodeDevices, (virHashDeallocator) virNodeDeviceFree); pthread_mutex_destroy(&ret->lock); VIR_FREE(ret); @@ -183,6 +188,8 @@ virHashFree(conn->storagePools, (virHashDeallocator) virStoragePoolFreeName); if (conn->storageVols != NULL) virHashFree(conn->storageVols, (virHashDeallocator) virStorageVolFreeName); + if (conn->nodeDevices != NULL) + virHashFree(conn->nodeDevices, (virHashDeallocator) virNodeDeviceFree); virResetError(&conn->err); if (virLastErr.conn == conn) @@ -771,3 +778,126 @@ pthread_mutex_unlock(&vol->conn->lock); return (refs); } + + +/** + * virGetNodeDevice: + * @conn: the hypervisor connection + * @name: device name (unique on node) + * + * Lookup if the device 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 + * virFreeNodeDevice() is needed to not leak data. + * + * Returns a pointer to the node device, or NULL in case of failure + */ +virNodeDevicePtr +virGetNodeDevice(virConnectPtr conn, const char *name) +{ + virNodeDevicePtr ret = NULL; + + if ((!VIR_IS_CONNECT(conn)) || (name == NULL)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(NULL); + } + pthread_mutex_lock(&conn->lock); + + ret = (virNodeDevicePtr) virHashLookup(conn->nodeDevices, name); + if (ret == NULL) { + if (VIR_ALLOC(ret) < 0) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("allocating node dev")); + goto error; + } + ret->magic = VIR_NODE_DEVICE_MAGIC; + ret->conn = conn; + ret->name = strdup(name); + if (ret->name == NULL) { + virLibConnError(conn, VIR_ERR_NO_MEMORY, _("copying node dev name")); + goto error; + } + + if (virHashAddEntry(conn->nodeDevices, name, ret) < 0) { + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("failed to add node dev to conn hash table")); + goto error; + } + conn->refs++; + } + ret->refs++; + pthread_mutex_unlock(&conn->lock); + return(ret); + +error: + pthread_mutex_unlock(&conn->lock); + if (ret != NULL) { + VIR_FREE(ret->name); + VIR_FREE(ret); + } + return(NULL); +} + + +/** + * virReleaseNodeDevice: + * @dev: the dev to release + * + * Unconditionally release all memory associated with a dev. + * The conn.lock mutex must be held prior to calling this, and will + * be released prior to this returning. The dev 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 +virReleaseNodeDevice(virNodeDevicePtr dev) { + virConnectPtr conn = dev->conn; + DEBUG("release dev %p %s", dev, dev->name); + + if (virHashRemoveEntry(conn->nodeDevices, dev->name, NULL) < 0) + virLibConnError(conn, VIR_ERR_INTERNAL_ERROR, + _("dev missing from connection hash table")); + + dev->magic = -1; + VIR_FREE(dev->name); + VIR_FREE(dev); + + DEBUG("unref connection %p %d", conn, conn->refs); + conn->refs--; + if (conn->refs == 0) { + virReleaseConnect(conn); + /* Already unlocked mutex */ + return; + } + + pthread_mutex_unlock(&conn->lock); +} + + +/** + * virUnrefNodeDevice: + * @dev: the dev to unreference + * + * Unreference the dev. If the use count drops to zero, the structure is + * actually freed. + * + * Returns the reference count or -1 in case of failure. + */ +int +virUnrefNodeDevice(virNodeDevicePtr dev) { + int refs; + + pthread_mutex_lock(&dev->conn->lock); + DEBUG("unref dev %p %s %d", dev, dev->name, dev->refs); + dev->refs--; + refs = dev->refs; + if (refs == 0) { + virReleaseNodeDevice(dev); + /* Already unlocked mutex */ + return (0); + } + + pthread_mutex_unlock(&dev->conn->lock); + return (refs); +} diff -r 78738f80cf4c src/datatypes.h --- a/src/datatypes.h Wed Nov 12 21:05:32 2008 +0000 +++ b/src/datatypes.h Wed Nov 12 21:11:46 2008 +0000 @@ -78,6 +78,16 @@ #define VIR_IS_STORAGE_VOL(obj) ((obj) && (obj)->magic==VIR_STORAGE_VOL_MAGIC) #define VIR_IS_CONNECTED_STORAGE_VOL(obj) (VIR_IS_STORAGE_VOL(obj) && VIR_IS_CONNECT((obj)->conn)) +/** + * VIR_NODE_DEVICE_MAGIC: + * + * magic value used to protect the API when pointers to storage vol structures + * are passed down by the users. + */ +#define VIR_NODE_DEVICE_MAGIC 0xDEAD5679 +#define VIR_IS_NODE_DEVICE(obj) ((obj) && (obj)->magic==VIR_NODE_DEVICE_MAGIC) +#define VIR_IS_CONNECTED_NODE_DEVICE(obj) (VIR_IS_NODE_DEVICE(obj) && VIR_IS_CONNECT((obj)->conn)) + /** * _virConnect: @@ -93,6 +103,7 @@ virDriverPtr driver; virNetworkDriverPtr networkDriver; virStorageDriverPtr storageDriver; + virDeviceMonitorPtr deviceMonitor; /* Private data pointer which can be used by driver and * network driver as they wish. @@ -101,6 +112,7 @@ void * privateData; void * networkPrivateData; void * storagePrivateData; + void * devMonPrivateData; /* Per-connection error. */ virError err; /* the last error */ @@ -118,6 +130,7 @@ virHashTablePtr networks; /* hash table for known domains */ virHashTablePtr storagePools;/* hash table for known storage pools */ virHashTablePtr storageVols;/* hash table for known storage vols */ + virHashTablePtr nodeDevices; /* hash table for known node devices */ int refs; /* reference count */ }; @@ -176,6 +189,19 @@ char key[PATH_MAX]; /* unique key for storage vol */ }; +/** + * _virNodeDevice: + * + * Internal structure associated with a node device + */ +struct _virNodeDevice { + unsigned int magic; /* specific value to check */ + int refs; /* reference count */ + virConnectPtr conn; /* pointer back to the connection */ + char *name; /* device name (unique on node) */ +}; + + /************************************************************************ * * * API for domain/connections (de)allocations and lookups * @@ -203,4 +229,8 @@ const char *key); int virUnrefStorageVol(virStorageVolPtr vol); +virNodeDevicePtr virGetNodeDevice(virConnectPtr conn, + const char *name); +int virUnrefNodeDevice(virNodeDevicePtr dev); + #endif diff -r 78738f80cf4c src/driver.h --- a/src/driver.h Wed Nov 12 21:05:32 2008 +0000 +++ b/src/driver.h Wed Nov 12 21:11:46 2008 +0000 @@ -604,6 +604,73 @@ }; #endif + +typedef struct _virDeviceMonitor virDeviceMonitor; +typedef virDeviceMonitor *virDeviceMonitorPtr; + +typedef int (*virDevMonNumOfDevices)(virConnectPtr conn, + unsigned int flags); + +typedef int (*virDevMonListDevices)(virConnectPtr conn, + char **const names, + int maxnames, + unsigned int flags); + +typedef int (*virDevMonNumOfDevicesByCap)(virConnectPtr conn, + const char *cap, + unsigned int flags); + +typedef int (*virDevMonListDevicesByCap)(virConnectPtr conn, + const char *cap, + char **const names, + int maxnames, + unsigned int flags); + +typedef virNodeDevicePtr (*virDevMonDeviceLookupByName)(virConnectPtr conn, + const char *name); + +typedef char * (*virDevMonDeviceDumpXML)(virNodeDevicePtr dev, + unsigned int flags); + +typedef char * (*virDevMonDeviceGetParent)(virNodeDevicePtr dev); + +typedef int (*virDevMonDeviceNumOfCaps)(virNodeDevicePtr dev); + +typedef int (*virDevMonDeviceListCaps)(virNodeDevicePtr dev, + char **const names, + int maxnames); + +typedef virNodeDevicePtr (*virDevMonDeviceCreate)(virConnectPtr conn, + const char *xml, + unsigned int flags); + +typedef int (*virDevMonDeviceDestroy)(virNodeDevicePtr dev, + unsigned int flags); + +/** + * _virDeviceMonitor: + * + * Structure associated with monitoring the devices + * on a virtualized node. + * + */ +struct _virDeviceMonitor { + const char * name; /* the name of the driver */ + virDrvOpen open; + virDrvClose close; + virDevMonNumOfDevices numOfDevices; + virDevMonListDevices listDevices; + virDevMonNumOfDevicesByCap numOfDevicesByCap; + virDevMonListDevicesByCap listDevicesByCap; + virDevMonDeviceLookupByName deviceLookupByName; + virDevMonDeviceDumpXML deviceDumpXML; + virDevMonDeviceGetParent deviceGetParent; + virDevMonDeviceNumOfCaps deviceNumOfCaps; + virDevMonDeviceListCaps deviceListCaps; + virDevMonDeviceCreate deviceCreate; + virDevMonDeviceDestroy deviceDestroy; +}; + /* * Registration * TODO: also need ways to (des)activate a given driver @@ -612,6 +679,7 @@ int virRegisterDriver(virDriverPtr); int virRegisterNetworkDriver(virNetworkDriverPtr); int virRegisterStorageDriver(virStorageDriverPtr); +int virRegisterDeviceMonitor(virDeviceMonitorPtr); #ifdef WITH_LIBVIRTD int virRegisterStateDriver(virStateDriverPtr); #endif diff -r 78738f80cf4c src/libvirt.c --- a/src/libvirt.c Wed Nov 12 21:05:32 2008 +0000 +++ b/src/libvirt.c Wed Nov 12 21:11:46 2008 +0000 @@ -70,6 +70,8 @@ static int virNetworkDriverTabCount = 0; static virStorageDriverPtr virStorageDriverTab[MAX_DRIVERS]; static int virStorageDriverTabCount = 0; +static virDeviceMonitorPtr virDeviceMonitorTab[MAX_DRIVERS]; +static int virDeviceMonitorTabCount = 0; #ifdef WITH_LIBVIRTD static virStateDriverPtr virStateDriverTab[MAX_DRIVERS]; static int virStateDriverTabCount = 0; @@ -449,6 +451,32 @@ } /** + * virLibNodeDeviceError: + * @dev: the device if available + * @error: the error number + * @info: extra information string + * + * Handle an error at the node device level + */ +static void +virLibNodeDeviceError(virNodeDevicePtr dev, 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_NODE_DEVICE) + conn = dev->conn; + + virRaiseError(conn, NULL, NULL, VIR_FROM_DEVMONITOR, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); +} + +/** * virRegisterNetworkDriver: * @driver: pointer to a network driver block * @@ -508,6 +536,34 @@ virStorageDriverTab[virStorageDriverTabCount] = driver; return virStorageDriverTabCount++; +} + +/** + * virRegisterDeviceMonitor: + * @driver: pointer to a device monitor block + * + * Register a device monitor + * + * Returns the driver priority or -1 in case of error. + */ +int +virRegisterDeviceMonitor(virDeviceMonitorPtr driver) +{ + if (virInitialize() < 0) + return -1; + + if (driver == NULL) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + + if (virDeviceMonitorTabCount >= MAX_DRIVERS) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + + virDeviceMonitorTab[virDeviceMonitorTabCount] = driver; + return virDeviceMonitorTabCount++; } /** @@ -806,6 +862,33 @@ } } + /* Node driver (optional) */ + for (i = 0; i < virDeviceMonitorTabCount; i++) { + res = virDeviceMonitorTab[i]->open (ret, auth, flags); + DEBUG("node driver %d %s returned %s", + i, virDeviceMonitorTab[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(virDeviceMonitorTab[i]->name, "remote")) { + virLibConnWarning (NULL, VIR_WAR_NO_NODE, + "Is the libvirtd daemon running ?"); + } else { + char *msg; + if (asprintf(&msg, "Is the %s daemon running?", + virDeviceMonitorTab[i]->name) > 0) { + virLibConnWarning (NULL, VIR_WAR_NO_NODE, msg); + VIR_FREE(msg); + } + } + break; + } else if (res == VIR_DRV_OPEN_SUCCESS) { + ret->deviceMonitor = virDeviceMonitorTab[i]; + break; + } + } + return ret; failed: @@ -923,6 +1006,8 @@ conn->networkDriver->close (conn); if (conn->storageDriver) conn->storageDriver->close (conn); + if (conn->deviceMonitor) + conn->deviceMonitor->close (conn); conn->driver->close (conn); if (virUnrefConnect(conn) < 0) @@ -5263,6 +5348,383 @@ + +/** + * virNodeNumOfDevices: + * @conn: pointer to the hypervisor connection + * @flags: flags (unused, pass 0) + * + * Provides the number of node devices. + * + * Returns the number of node devices or -1 in case of error + */ +int +virNodeNumOfDevices(virConnectPtr conn, unsigned int flags) +{ + DEBUG("conn=%p, flags=%d", conn, flags); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + if (flags != 0) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return (-1); + } + + if (conn->deviceMonitor && conn->deviceMonitor->numOfDevices) + return conn->deviceMonitor->numOfDevices (conn, flags); + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + + +/** + * virNodeListDevices: + * @conn: pointer to the hypervisor connection + * @names: array to collect the list of node device names + * @maxnames: size of @names + * @flags: flags (unused, pass 0) + * + * Collect the list of node devices, and store their names in @names + * + * Returns the number of node devices found or -1 in case of error + */ +int +virNodeListDevices(virConnectPtr conn, char **const names, int maxnames, + unsigned int flags) +{ + DEBUG("conn=%p, names=%p, maxnames=%d, flags=%d", + conn, names, maxnames, flags); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + if ((flags != 0) || (names == NULL) || (maxnames < 0)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return (-1); + } + + if (conn->deviceMonitor && conn->deviceMonitor->listDevices) + return conn->deviceMonitor->listDevices (conn, names, maxnames, flags); + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +/** + * virNodeNumOfDevicesByCap: + * @conn: pointer to the hypervisor connection + * @cap: capability name + * @flags: flags (unused, pass 0) + * + * Provides the number of node devices with the given capability. + * + * Returns the number of node devices with the capability or -1 in case of error + */ +int +virNodeNumOfDevicesByCap(virConnectPtr conn, const char *cap, + unsigned int flags) +{ + DEBUG("conn=%p, cap=%p, flags=%d", conn, cap, flags); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if ((flags != 0) || (cap == NULL)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return (-1); + } + + if (conn->deviceMonitor && conn->deviceMonitor->numOfDevicesByCap) + return conn->deviceMonitor->numOfDevicesByCap (conn, cap, flags); + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + + +/** + * virNodeListDevicesByCap: + * @conn: pointer to the hypervisor connection + * @cap: capability name + * @names: array to collect the list of node device names + * @maxnames: size of @names + * @flags: flags (unused, pass 0) + * + * Collect the list of node devices with the given capability, and store + * their names in @names + * + * Returns the number of node devices found with the capability or -1 in case of error + */ +int +virNodeListDevicesByCap(virConnectPtr conn, const char *cap, + char **const names, int maxnames, + unsigned int flags) +{ + DEBUG("conn=%p, cap=%p, names=%p, maxnames=%d, flags=%d", + conn, cap, names, maxnames, flags); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return (-1); + } + + if ((flags != 0) || (names == NULL) || (maxnames < 0) || (cap == NULL)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return (-1); + } + + if (conn->deviceMonitor && conn->deviceMonitor->listDevicesByCap) + return conn->deviceMonitor->listDevicesByCap (conn, cap, names, maxnames, flags); + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + + +/** + * virNodeDeviceLookupByName: + * @conn: pointer to the hypervisor connection + * @name: unique device name + * + * Lookup a node device by its name. + * + * Returns a virNodeDevicePtr if found, NULL otherwise. + */ +virNodeDevicePtr virNodeDeviceLookupByName(virConnectPtr conn, const char *name) +{ + DEBUG("conn=%p, name=%p", conn, name); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return NULL; + } + + if (name == NULL) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } + + if (conn->deviceMonitor && conn->deviceMonitor->deviceLookupByName) + return conn->deviceMonitor->deviceLookupByName (conn, name); + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return NULL; +} + + +/** + * virNodeDeviceCreate: + * @conn: pointer to the hypervisor connection + * @xml: XML description for new device + * @flags: flags (unused, pass 0) + * + * Creates a new node device, as described by the XML. + * [Need to describe what kinds of devices can be created this way] + * + * Returns a pointer to the new device, or NULL for error. + */ +virNodeDevicePtr virNodeDeviceCreate(virConnectPtr conn, const char *xml, + unsigned int flags) +{ + DEBUG("conn=%p, xml=%p, flags=%d", conn, xml, flags); + + if (!VIR_IS_CONNECT(conn)) { + virLibConnError(NULL, VIR_ERR_INVALID_CONN, __FUNCTION__); + return NULL; + } + + if ((flags != 0) || (xml == NULL)) { + virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return NULL; + } + + if (conn->deviceMonitor && conn->deviceMonitor->deviceCreate) + return conn->deviceMonitor->deviceCreate (conn, xml, flags); + + virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return NULL; +} + +/** + * virNodeDeviceGetXMLDesc: + * @dev: pointer to the node device + * @flags: flags for XML generation (unused, pass 0) + * + * Fetch an XML document describing all aspects of + * the device. + * + * Return the XML document, or NULL on error + */ +char *virNodeDeviceGetXMLDesc(virNodeDevicePtr dev, unsigned int flags) +{ + DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { + virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); + return NULL; + } + + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceDumpXML) + return dev->conn->deviceMonitor->deviceDumpXML (dev, flags); + + virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return NULL; +} + + +/** + * virNodeDeviceDestroy: + * @dev: pointer to the created device + * @flags: flags (unused, pass 0) + * + * Removes a device created by virNodeDeviceCreate. + * + * Returns 0 for success, <0 for failure. + */ +int virNodeDeviceDestroy(virNodeDevicePtr dev, unsigned int flags) +{ + DEBUG("dev=%p, conn=%p, flags=%d", dev, dev ? dev->conn : NULL, flags); + + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { + virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); + return (-1); + } + + if (flags != 0) { + virLibConnError(dev->conn, VIR_ERR_INVALID_ARG, __FUNCTION__); + return -1; + } + + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceDestroy) + return dev->conn->deviceMonitor->deviceDestroy (dev, flags); + + virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + + +/** + * virNodeDeviceGetName: + * @dev: the device + * + * Returns the device name. + */ +const char *virNodeDeviceGetName(virNodeDevicePtr dev) +{ + DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { + virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); + return NULL; + } + + return dev->name; +} + +/** + * virNodeDeviceGetParent: + * @dev: the device + * + * Returns the name of the device's parent, or NULL if the + * device has no parent. + */ +const char *virNodeDeviceGetParent(virNodeDevicePtr dev) +{ + DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { + virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); + return NULL; + } + + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceGetParent) + return dev->conn->deviceMonitor->deviceGetParent (dev); + + virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return NULL; +} + +/** + * virNodeDeviceNumOfCaps: + * @dev: the device + * + * Returns the number of capabilities supported by the device. + */ +int virNodeDeviceNumOfCaps(virNodeDevicePtr dev) +{ + DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { + virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); + return -1; + } + + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceNumOfCaps) + return dev->conn->deviceMonitor->deviceNumOfCaps (dev); + + virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + +/** + * virNodeDeviceListCaps: + * @dev: the device + * @names: array to collect the list of capability names + * @maxnames: size of @names + * + * Lists the names of the capabilities supported by the device. + * + * Returns the number of capability names listed in @names. + */ +int virNodeDeviceListCaps(virNodeDevicePtr dev, + char **const names, + int maxnames) +{ + DEBUG("dev=%p, conn=%p, names=%p, maxnames=%d", + dev, dev ? dev->conn : NULL, names, maxnames); + + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { + virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); + return -1; + } + + if (dev->conn->deviceMonitor && dev->conn->deviceMonitor->deviceListCaps) + return dev->conn->deviceMonitor->deviceListCaps (dev, names, maxnames); + + virLibConnError (dev->conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); + return -1; +} + + +/** + * virNodeDeviceFree: + * @dev: pointer to the node device + * + * Drops a reference to the node device, freeing it if + * this was the last reference. + * + * Returns the 0 for success, -1 for error. + */ +int virNodeDeviceFree(virNodeDevicePtr dev) +{ + DEBUG("dev=%p, conn=%p", dev, dev ? dev->conn : NULL); + + if (!VIR_IS_CONNECTED_NODE_DEVICE(dev)) { + virLibNodeDeviceError(NULL, VIR_ERR_INVALID_NODE_DEVICE, __FUNCTION__); + return (-1); + } + if (virUnrefNodeDevice(dev) < 0) + return (-1); + return(0); +} + + /* * Domain Event Notification */ diff -r 78738f80cf4c src/libvirt_sym.version.in --- a/src/libvirt_sym.version.in Wed Nov 12 21:05:32 2008 +0000 +++ b/src/libvirt_sym.version.in Wed Nov 12 21:11:46 2008 +0000 @@ -232,6 +232,21 @@ virEventRegisterImpl; virConnectDomainEventRegister; virConnectDomainEventDeregister; + + virNodeNumOfDevices; + virNodeListDevices; + virNodeNumOfDevicesByCap; + virNodeListDevicesByCap; + virNodeDeviceLookupByName; + virNodeDeviceFree; + virNodeDeviceGetXMLDesc; + virNodeDeviceCreate; + virNodeDeviceDestroy; + virNodeDeviceGetName; + virNodeDeviceGetParent; + virNodeDeviceNumOfCaps; + virNodeDeviceListCaps; + } LIBVIRT_0.4.5; /* .... define new API here using predicted next version number .... */ diff -r 78738f80cf4c src/virterror.c --- a/src/virterror.c Wed Nov 12 21:05:32 2008 +0000 +++ b/src/virterror.c Wed Nov 12 21:11:46 2008 +0000 @@ -309,6 +309,9 @@ break; case VIR_FROM_DOMAIN: dom = "Domain Config "; + break; + case VIR_FROM_DEVMONITOR: + dom = "Device Monitor "; break; } @@ -719,6 +722,24 @@ else errmsg = _("Failed to find a storage driver: %s"); break; + case VIR_WAR_NO_NODE: + if (info == NULL) + errmsg = _("Failed to find a node driver"); + else + errmsg = _("Failed to find a node driver: %s"); + break; + case VIR_ERR_INVALID_NODE_DEVICE: + if (info == NULL) + errmsg = _("invalid node device pointer"); + else + errmsg = _("invalid node device pointer in %s"); + break; + case VIR_ERR_NO_NODE_DEVICE: + if (info == NULL) + errmsg = _("Node device not found"); + else + errmsg = _("Node device not found: %s"); + break; } return (errmsg); } -- |: 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