summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2008-11-21 12:19:22 +0000
committerDaniel P. Berrange <berrange@redhat.com>2008-11-21 12:19:22 +0000
commit0793e73c025ba79f9825e975053ea77808228074 (patch)
tree529cfa90909ed8b2bc36b3a739fb35aaf0a351d3
parentOptional dlopen support for drivers (diff)
downloadlibvirt-0793e73c025ba79f9825e975053ea77808228074.tar.gz
libvirt-0793e73c025ba79f9825e975053ea77808228074.tar.bz2
libvirt-0793e73c025ba79f9825e975053ea77808228074.zip
Public API for node device enumeration (David Lively)
-rw-r--r--ChangeLog12
-rw-r--r--include/libvirt/libvirt.h53
-rw-r--r--include/libvirt/libvirt.h.in53
-rw-r--r--include/libvirt/virterror.h4
-rw-r--r--src/datatypes.c130
-rw-r--r--src/datatypes.h30
-rw-r--r--src/driver.h49
-rw-r--r--src/libvirt.c336
-rw-r--r--src/libvirt_sym.version.in15
-rw-r--r--src/virterror.c21
10 files changed, 703 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 236e9655f..3ded42eda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index 469c870c1..729e59474 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -995,6 +995,59 @@ virDomainPtr virDomainCreateLinux (virConnectPtr conn,
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
*/
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 5bdc67710..fc322e6b0 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -995,6 +995,59 @@ virDomainPtr virDomainCreateLinux (virConnectPtr conn,
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
*/
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index 868f1a3b3..870ebbc17 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -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;
/**
diff --git a/src/datatypes.c b/src/datatypes.c
index 560154b86..3911a2dfd 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -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);
+}
diff --git a/src/datatypes.h b/src/datatypes.h
index f06f41f63..e61b178f3 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -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
diff --git a/src/driver.h b/src/driver.h
index 2382ac90d..5fd3843f0 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -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
diff --git a/src/libvirt.c b/src/libvirt.c
index 31e698745..32dc3cc2c 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -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;
@@ -449,6 +451,32 @@ virLibStorageVolError(virStorageVolPtr vol, virErrorNumber error,
}
/**
+ * 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
*
@@ -511,6 +539,34 @@ virRegisterStorageDriver(virStorageDriverPtr driver)
}
/**
+ * 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
*/
diff --git a/src/libvirt_sym.version.in b/src/libvirt_sym.version.in
index 943eb9ae8..d0920f498 100644
--- a/src/libvirt_sym.version.in
+++ b/src/libvirt_sym.version.in
@@ -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 .... */
diff --git a/src/virterror.c b/src/virterror.c
index 46a7d1542..0723db88f 100644
--- a/src/virterror.c
+++ b/src/virterror.c
@@ -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);
}