]> xenbits.xensource.com Git - libvirt.git/commitdiff
Public API for node device enumeration (David Lively)
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 21 Nov 2008 12:19:22 +0000 (12:19 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Fri, 21 Nov 2008 12:19:22 +0000 (12:19 +0000)
ChangeLog
include/libvirt/libvirt.h
include/libvirt/libvirt.h.in
include/libvirt/virterror.h
src/datatypes.c
src/datatypes.h
src/driver.h
src/libvirt.c
src/libvirt_sym.version.in
src/virterror.c

index 236e9655f5836e95d7aeca42ab1fb184697e5005..3ded42eda15f1dbaff0c1892667ae68f0438bb25 100644 (file)
--- 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
index 469c870c113d929f0b578406ba6a888cc341be4b..729e59474e1cc244b3912f8706986807aea7d6be 100644 (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
  */
index 5bdc67710c53ebeefd1cf38d5b79a41a7dd600c9..fc322e6b0f0a94690112c62970af50150595d6a2 100644 (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
  */
index 868f1a3b32287a47450593960df82c89e9ccedaa..870ebbc17d0102c335cabe5b848a1918fdbf7083 100644 (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;
 
 /**
index 560154b86ab07e26f5b7aca20d1f1e9cd01ed649..3911a2dfdafc0c4292a9753682e28b201d658b04 100644 (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);
+}
index f06f41f6397d4d507f609fc15571ebeff08de0ef..e61b178f3a3d4d6ab5766edfd4c14b38f0bc51f8 100644 (file)
 #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
index 2382ac90d6ce5f5843a047904327adabb7f066dd..5fd3843f055fc96561950ec691cb39bef442617c 100644 (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
index 31e698745044a02a6bcc7d4384517e8b6ed1c30e..32dc3cc2c36f0a7084b2b62c9e6990b14c3cd53a 100644 (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
  */
index 943eb9ae8ec460841c5f73be8cbbe1bbd9b3e023..d0920f498774fc331426a2094729c7f422ebacf0 100644 (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 .... */
index 46a7d15426c0c081e3c151e3f86ee41d7cdedcef..0723db88f5abd6b2c20dee24eedd5985389260b7 100644 (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);
 }