[libvirt] PATCH: 1/7: Public API

Daniel P. Berrange berrange at redhat.com
Thu Nov 20 17:51:39 UTC 2008


This patch contains the public API for node devices. Changes since last
post are

 - Remove the ByCap methods - the main list method now takes an optionally
   NULL, cap arguent. This simplified virsh usage later too which is nice

 - Change VIR_FROM_DEVMONITOR to VIR_FROM_NODEDEV to match rest of public
   naming scheme

 - Remove unused NodeDeviceCreate/Destroy methods. We can re-add them
   when we need them

Daniel

diff -r 2e1f852dff74 include/libvirt/libvirt.h
--- a/include/libvirt/libvirt.h	Wed Nov 19 18:00:40 2008 +0000
+++ b/include/libvirt/libvirt.h	Thu Nov 20 17:43:17 2008 +0000
@@ -995,6 +995,59 @@
                                                  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 -r 2e1f852dff74 include/libvirt/libvirt.h.in
--- a/include/libvirt/libvirt.h.in	Wed Nov 19 18:00:40 2008 +0000
+++ b/include/libvirt/libvirt.h.in	Thu Nov 20 17:43:17 2008 +0000
@@ -995,6 +995,59 @@
                                                  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 -r 2e1f852dff74 include/libvirt/virterror.h
--- a/include/libvirt/virterror.h	Wed Nov 19 18:00:40 2008 +0000
+++ b/include/libvirt/virterror.h	Thu Nov 20 17:43:17 2008 +0000
@@ -59,6 +59,7 @@
     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 @@
     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 2e1f852dff74 src/datatypes.c
--- a/src/datatypes.c	Wed Nov 19 18:00:40 2008 +0000
+++ b/src/datatypes.c	Thu Nov 20 17:43:17 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 2e1f852dff74 src/datatypes.h
--- a/src/datatypes.h	Wed Nov 19 18:00:40 2008 +0000
+++ b/src/datatypes.h	Thu Nov 20 17:43:17 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 2e1f852dff74 src/driver.h
--- a/src/driver.h	Wed Nov 19 18:00:40 2008 +0000
+++ b/src/driver.h	Thu Nov 20 17:43:17 2008 +0000
@@ -635,6 +635,54 @@
 };
 #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 @@
 int virRegisterDriver(virDriverPtr);
 int virRegisterNetworkDriver(virNetworkDriverPtr);
 int virRegisterStorageDriver(virStorageDriverPtr);
+int virRegisterDeviceMonitor(virDeviceMonitorPtr);
 #ifdef WITH_LIBVIRTD
 int virRegisterStateDriver(virStateDriverPtr);
 #endif
diff -r 2e1f852dff74 src/libvirt.c
--- a/src/libvirt.c	Wed Nov 19 18:00:40 2008 +0000
+++ b/src/libvirt.c	Thu Nov 20 17:43:17 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_NODEDEV, 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)
@@ -5374,6 +5459,257 @@
 
 
 
+
+/**
+ * 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 -r 2e1f852dff74 src/libvirt_sym.version.in
--- a/src/libvirt_sym.version.in	Wed Nov 19 18:00:40 2008 +0000
+++ b/src/libvirt_sym.version.in	Thu Nov 20 17:43:17 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 2e1f852dff74 src/virterror.c
--- a/src/virterror.c	Wed Nov 19 18:00:40 2008 +0000
+++ b/src/virterror.c	Thu Nov 20 17:43:17 2008 +0000
@@ -309,6 +309,9 @@
             break;
         case VIR_FROM_DOMAIN:
             dom = "Domain Config ";
+            break;
+        case VIR_FROM_NODEDEV:
+            dom = "Node Device ";
             break;
         case VIR_FROM_UML:
             dom = "UML ";
@@ -721,6 +724,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 :|




More information about the libvir-list mailing list