Public API for node device enumeration (David Lively)

This commit is contained in:
Daniel P. Berrange 2008-11-21 12:19:22 +00:00
parent 2c855c1c66
commit 0793e73c02
10 changed files with 703 additions and 0 deletions

View File

@ -1,3 +1,15 @@
Fri Nov 21 12:19:14 BST 2008 Daniel P. Berrange <berrange@redhat.com>
Public API for node device enumeration
* include/libvirt/libvirt.h.in, include/libvirt/virterror.h:
New public APIs for node device enumeration
* src/datatypes.c, src/datatypes.h: Internal impl of public
data types for node devices
* src/driver.h, src/libvirt.c: Stubs for node device APIs
* src/libvirt_sym.version.in: Export new node device API
symbols
* src/virterror.c: Error codes for node device drivers
Fri Nov 21 12:03:14 BST 2008 Daniel P. Berrange <berrange@redhat.com>
Optional (disabled by default) dlopen support

View File

@ -994,6 +994,59 @@ virDomainPtr virDomainCreateLinux (virConnectPtr conn,
const char *xmlDesc,
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,
const char *cap,
unsigned int flags);
int virNodeListDevices (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);
int virNodeDeviceFree (virNodeDevicePtr dev);
/*
* Domain Event Notification
*/

View File

@ -994,6 +994,59 @@ virDomainPtr virDomainCreateLinux (virConnectPtr conn,
const char *xmlDesc,
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,
const char *cap,
unsigned int flags);
int virNodeListDevices (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);
int virNodeDeviceFree (virNodeDevicePtr dev);
/*
* Domain Event Notification
*/

View File

@ -59,6 +59,7 @@ typedef enum {
VIR_FROM_NETWORK, /* Error from network config */
VIR_FROM_DOMAIN, /* Error from domain config */
VIR_FROM_UML, /* Error at the UML driver */
VIR_FROM_NODEDEV, /* Error from node device monitor */
} virErrorDomain;
@ -149,6 +150,9 @@ typedef enum {
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;
/**

View File

@ -140,6 +140,9 @@ virGetConnect(void) {
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 @@ failed:
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 @@ virReleaseConnect(virConnectPtr conn) {
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 @@ virUnrefStorageVol(virStorageVolPtr vol) {
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);
}

View File

@ -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 @@ struct _virConnect {
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 @@ struct _virConnect {
void * privateData;
void * networkPrivateData;
void * storagePrivateData;
void * devMonPrivateData;
/* Per-connection error. */
virError err; /* the last error */
@ -118,6 +130,7 @@ struct _virConnect {
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 @@ struct _virStorageVol {
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 @@ virStorageVolPtr virGetStorageVol(virConnectPtr conn,
const char *key);
int virUnrefStorageVol(virStorageVolPtr vol);
virNodeDevicePtr virGetNodeDevice(virConnectPtr conn,
const char *name);
int virUnrefNodeDevice(virNodeDevicePtr dev);
#endif

View File

@ -635,6 +635,54 @@ struct _virStateDriver {
};
#endif
typedef struct _virDeviceMonitor virDeviceMonitor;
typedef virDeviceMonitor *virDeviceMonitorPtr;
typedef int (*virDevMonNumOfDevices)(virConnectPtr conn,
const char *cap,
unsigned int flags);
typedef int (*virDevMonListDevices)(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);
/**
* _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;
virDevMonDeviceLookupByName deviceLookupByName;
virDevMonDeviceDumpXML deviceDumpXML;
virDevMonDeviceGetParent deviceGetParent;
virDevMonDeviceNumOfCaps deviceNumOfCaps;
virDevMonDeviceListCaps deviceListCaps;
};
/*
* Registration
* TODO: also need ways to (des)activate a given driver
@ -643,6 +691,7 @@ struct _virStateDriver {
int virRegisterDriver(virDriverPtr);
int virRegisterNetworkDriver(virNetworkDriverPtr);
int virRegisterStorageDriver(virStorageDriverPtr);
int virRegisterDeviceMonitor(virDeviceMonitorPtr);
#ifdef WITH_LIBVIRTD
int virRegisterStateDriver(virStateDriverPtr);
#endif

View File

@ -70,6 +70,8 @@ static virNetworkDriverPtr virNetworkDriverTab[MAX_DRIVERS];
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;
@ -448,6 +450,32 @@ virLibStorageVolError(virStorageVolPtr vol, virErrorNumber error,
errmsg, info, NULL, 0, 0, errmsg, info);
}
/**
* 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_NODEDEV, error, VIR_ERR_ERROR,
errmsg, info, NULL, 0, 0, errmsg, info);
}
/**
* virRegisterNetworkDriver:
* @driver: pointer to a network driver block
@ -510,6 +538,34 @@ virRegisterStorageDriver(virStorageDriverPtr 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++;
}
/**
* virRegisterDriver:
* @driver: pointer to a driver block
@ -806,6 +862,33 @@ do_open (const char *name,
}
}
/* 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 @@ virConnectClose(virConnectPtr conn)
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)
@ -5374,6 +5459,257 @@ virStorageVolGetPath(virStorageVolPtr vol)
/**
* virNodeNumOfDevices:
* @conn: pointer to the hypervisor connection
* @cap: capability name
* @flags: flags (unused, pass 0)
*
* Provides the number of node devices.
*
* If the optional 'cap' argument is non-NULL, then the count
* will be restricted to devices with the specified capability
*
* Returns the number of node devices or -1 in case of error
*/
int
virNodeNumOfDevices(virConnectPtr conn, const char *cap, unsigned int flags)
{
DEBUG("conn=%p, cap=%s, flags=%d", conn, cap, 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, cap, flags);
virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
/**
* virNodeListDevices:
* @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, and store their names in @names
*
* If the optional 'cap' argument is non-NULL, then the count
* will be restricted to devices with the specified capability
*
* Returns the number of node devices found or -1 in case of error
*/
int
virNodeListDevices(virConnectPtr conn,
const char *cap,
char **const names, int maxnames,
unsigned int flags)
{
DEBUG("conn=%p, cap=%s, 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)) {
virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
return (-1);
}
if (conn->deviceMonitor && conn->deviceMonitor->listDevices)
return conn->deviceMonitor->listDevices (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;
}
/**
* 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;
}
/**
* 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
*/

View File

@ -232,6 +232,21 @@ LIBVIRT_0.5.0 {
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 .... */

View File

@ -310,6 +310,9 @@ virDefaultErrorFunc(virErrorPtr err)
case VIR_FROM_DOMAIN:
dom = "Domain Config ";
break;
case VIR_FROM_NODEDEV:
dom = "Node Device ";
break;
case VIR_FROM_UML:
dom = "UML ";
break;
@ -721,6 +724,24 @@ virErrorMsg(virErrorNumber error, const char *info)
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);
}