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 :|