This patch contains the public API additions.
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index 3624367..c888943 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -993,6 +993,76 @@ char * virStorageVolGetPath (virStorageVolPtr vol); 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, + 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); + + #ifdef __cplusplus } #endif diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 8e24708..020b8dc 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -58,6 +58,7 @@ typedef enum { VIR_FROM_STORAGE, /* Error from storage driver */ VIR_FROM_NETWORK, /* Error from network config */ VIR_FROM_DOMAIN, /* Error from domain config */ + VIR_FROM_NODE, /* Error from node driver */ } virErrorDomain; @@ -148,6 +149,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/libvirt.c b/src/libvirt.c index ca2675a..5cef752 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -73,6 +73,8 @@ static virNetworkDriverPtr virNetworkDriverTab[MAX_DRIVERS]; static int virNetworkDriverTabCount = 0; static virStorageDriverPtr virStorageDriverTab[MAX_DRIVERS]; static int virStorageDriverTabCount = 0; +static virNodeDriverPtr virNodeDriverTab[MAX_DRIVERS]; +static int virNodeDriverTabCount = 0; #ifdef WITH_LIBVIRTD static virStateDriverPtr virStateDriverTab[MAX_DRIVERS]; static int virStateDriverTabCount = 0; @@ -299,6 +301,12 @@ virInitialize(void) #ifdef WITH_NETWORK if (networkRegister() == -1) return -1; #endif +#ifdef HAVE_HAL + if (halNodeRegister() == -1) return -1; +#endif +#ifdef HAVE_DEVKIT + if (devkitNodeRegister() == -1) return -1; +#endif if (storageRegister() == -1) return -1; #endif #ifdef WITH_REMOTE @@ -457,6 +465,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_NODE, error, VIR_ERR_ERROR, + errmsg, info, NULL, 0, 0, errmsg, info); +} + +/** * virRegisterNetworkDriver: * @driver: pointer to a network driver block * @@ -513,6 +547,34 @@ virRegisterStorageDriver(virStorageDriverPtr driver) } /** + * virRegisterNodeDriver: + * @driver: pointer to a node driver block + * + * Register a node driver + * + * Returns the driver priority or -1 in case of error. + */ +int +virRegisterNodeDriver(virNodeDriverPtr driver) +{ + if (virInitialize() < 0) + return -1; + + if (driver == NULL) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + + if (virNodeDriverTabCount >= MAX_DRIVERS) { + virLibConnError(NULL, VIR_ERR_INVALID_ARG, __FUNCTION__); + return(-1); + } + + virNodeDriverTab[virNodeDriverTabCount] = driver; + return virNodeDriverTabCount++; +} + +/** * virRegisterDriver: * @driver: pointer to a driver block * @@ -846,6 +908,33 @@ do_open (const char *name, } } + /* Node driver (optional) */ + for (i = 0; i < virNodeDriverTabCount; i++) { + res = virNodeDriverTab[i]->open (ret, uri, auth, flags); + DEBUG("node driver %d %s returned %s", + i, virNodeDriverTab[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(virNodeDriverTab[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?", + virNodeDriverTab[i]->name) > 0) { + virLibConnWarning (NULL, VIR_WAR_NO_NODE, msg); + VIR_FREE(msg); + } + } + break; + } else if (res == VIR_DRV_OPEN_SUCCESS) { + ret->nodeDriver = virNodeDriverTab[i]; + break; + } + } + xmlFreeURI (uri); return ret; @@ -966,6 +1055,8 @@ virConnectClose(virConnectPtr conn) conn->networkDriver->close (conn); if (conn->storageDriver) conn->storageDriver->close (conn); + if (conn->nodeDriver) + conn->nodeDriver->close (conn); conn->driver->close (conn); if (virUnrefConnect(conn) < 0) @@ -5307,6 +5398,382 @@ virStorageVolGetPath(virStorageVolPtr vol) +/** + * 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->nodeDriver && conn->nodeDriver->numOfDevices) + return conn->nodeDriver->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->nodeDriver && conn->nodeDriver->listDevices) + return conn->nodeDriver->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->nodeDriver && conn->nodeDriver->numOfDevicesByCap) + return conn->nodeDriver->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->nodeDriver && conn->nodeDriver->listDevicesByCap) + return conn->nodeDriver->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->nodeDriver && conn->nodeDriver->deviceLookupByName) + return conn->nodeDriver->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->nodeDriver && conn->nodeDriver->deviceCreate) + return conn->nodeDriver->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->nodeDriver && dev->conn->nodeDriver->deviceDumpXML) + return dev->conn->nodeDriver->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->nodeDriver && dev->conn->nodeDriver->deviceDestroy) + return dev->conn->nodeDriver->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->nodeDriver && dev->conn->nodeDriver->deviceGetParent) + return dev->conn->nodeDriver->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->nodeDriver && dev->conn->nodeDriver->deviceNumOfCaps) + return dev->conn->nodeDriver->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->nodeDriver && dev->conn->nodeDriver->deviceListCaps) + return dev->conn->nodeDriver->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); +} + + /* Not for public use. Combines the elements of a virStringList * into a single string. */ diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version index 3cc4505..47c2a9f 100644 --- a/src/libvirt_sym.version +++ b/src/libvirt_sym.version @@ -147,6 +147,20 @@ virStorageVolGetXMLDesc; virStorageVolGetPath; + virNodeNumOfDevices; + virNodeListDevices; + virNodeNumOfDevicesByCap; + virNodeListDevicesByCap; + virNodeDeviceLookupByName; + virNodeDeviceFree; + virNodeDeviceGetXMLDesc; + virNodeDeviceCreate; + virNodeDeviceDestroy; + virNodeDeviceGetName; + virNodeDeviceGetParent; + virNodeDeviceNumOfCaps; + virNodeDeviceListCaps; + /* Symbols with __ are private only for use by the libvirtd daemon. They are not part of stable ABI @@ -166,6 +180,7 @@ __virGetNetwork; __virGetStoragePool; __virGetStorageVol; + __virGetNodeDevice; __virEventRegisterImpl; diff --git a/src/virterror.c b/src/virterror.c index 21c7339..c9c5bf0 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_NODE: + dom = "Node Driver "; + break; } if ((err->dom != NULL) && (err->code != VIR_ERR_INVALID_DOMAIN)) { @@ -719,6 +722,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); }
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list