Update the code to be more in line with how code looks elsewhere in
libvirt. Allow listing of domains, networks, storage pools, and
network interfaces.
I like the changes to make the style more in line with the rest of the
codebase, however, I really think that this example code should be
about a minimal use of the API to list a few domains and that's all,
so I'm not in favor of extending it to list other kinds of objects. I
think people can find the details of how to do that kind of thing in
the API docs.
Dave
Update the function prototypes in libvirt.c to include a message
about
the client needing to free() returned name fields. Fix the all domains
example flags values.
---
examples/hellolibvirt/hellolibvirt.c | 131 ++++++++++++++++++++++-------------
src/libvirt.c | 21 +++---
2 files changed, 91 insertions(+), 61 deletions(-)
diff --git a/examples/hellolibvirt/hellolibvirt.c b/examples/hellolibvirt/hellolibvirt.c
index 234637e..85e5ae6 100644
--- a/examples/hellolibvirt/hellolibvirt.c
+++ b/examples/hellolibvirt/hellolibvirt.c
@@ -15,7 +15,7 @@ showError(virConnectPtr conn)
virErrorPtr err;
err = malloc(sizeof(*err));
- if (NULL == err) {
+ if (!err) {
printf("Could not allocate memory for error data\n");
goto out;
}
@@ -56,14 +56,14 @@ showHypervisorInfo(virConnectPtr conn)
* to fail if, for example, there is no connection to a
* hypervisor, so check what it returns. */
hvType = virConnectGetType(conn);
- if (NULL == hvType) {
+ if (!hvType) {
ret = 1;
printf("Failed to get hypervisor type\n");
showError(conn);
goto out;
}
- if (0 != virConnectGetVersion(conn, &hvVer)) {
+ if (virConnectGetVersion(conn, &hvVer) < 0) {
ret = 1;
printf("Failed to get hypervisor version\n");
showError(conn);
@@ -85,73 +85,101 @@ out:
return ret;
}
+/* Turn off the message in order to compile here
+ *
+ * The virConnectListAll*(), vir*IsActive(), vir*GetName(), and vir*Free()
+ * functions require specific types which aren't possible to provide in
+ * this tabular manner.
+ */
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+typedef struct _objectTable objectTable;
+struct _objectTable {
+ const char *objName;
+ int (*activeFcn)(virConnectPtr);
+ int (*inactiveFcn)(virConnectPtr);
+ int (*allFcn)();
+ int (*isActiveFcn)();
+ const char *(*nameFcn)();
+ int (*freeFcn)();
+ unsigned int flags;
+};
+
+objectTable fcnTable[] = {
+ {"domains",
+ virConnectNumOfDomains, virConnectNumOfDefinedDomains,
+ virConnectListAllDomains, virDomainIsActive,
+ virDomainGetName, virDomainFree,
+ VIR_CONNECT_LIST_DOMAINS_ACTIVE |
+ VIR_CONNECT_LIST_DOMAINS_INACTIVE},
+ {"networks",
+ virConnectNumOfNetworks, virConnectNumOfDefinedNetworks,
+ virConnectListAllNetworks, virNetworkIsActive,
+ virNetworkGetName, virNetworkFree,
+ VIR_CONNECT_LIST_NETWORKS_ACTIVE |
+ VIR_CONNECT_LIST_NETWORKS_INACTIVE},
+ {"storage pools",
+ virConnectNumOfStoragePools, virConnectNumOfDefinedStoragePools,
+ virConnectListAllStoragePools, virStoragePoolIsActive,
+ virStoragePoolGetName, virStoragePoolFree,
+ VIR_CONNECT_LIST_STORAGE_POOLS_ACTIVE |
+ VIR_CONNECT_LIST_STORAGE_POOLS_INACTIVE},
+ {"interfaces",
+ virConnectNumOfInterfaces, virConnectNumOfDefinedInterfaces,
+ virConnectListAllInterfaces, virInterfaceIsActive,
+ virInterfaceGetName, virInterfaceFree,
+ VIR_CONNECT_LIST_INTERFACES_ACTIVE |
+ VIR_CONNECT_LIST_INTERFACES_INACTIVE},
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0}
+};
static int
-showDomains(virConnectPtr conn)
+showObject(virConnectPtr conn, objectTable entry)
{
- int ret = 0, i, numNames, numInactiveDomains, numActiveDomains;
- char **nameList = NULL;
+ int ret = 0, numActive, numInactive, numObjects, i;
+ void **objects = NULL;
- numActiveDomains = virConnectNumOfDomains(conn);
- if (-1 == numActiveDomains) {
+ if ((numActive = (*entry.activeFcn)(conn)) < 0) {
ret = 1;
- printf("Failed to get number of active domains\n");
+ printf("Failed to get number of active %s\n", entry.objName);
showError(conn);
goto out;
}
- numInactiveDomains = virConnectNumOfDefinedDomains(conn);
- if (-1 == numInactiveDomains) {
+ if ((numInactive = (*entry.inactiveFcn)(conn)) < 0) {
ret = 1;
- printf("Failed to get number of inactive domains\n");
+ printf("Failed to get number of inactive %s\n", entry.objName);
showError(conn);
goto out;
}
- printf("There are %d active and %d inactive domains\n",
- numActiveDomains, numInactiveDomains);
+ printf("There are %d active and %d inactive %s:\n",
+ numActive, numInactive, entry.objName);
- nameList = malloc(sizeof(*nameList) * numInactiveDomains);
-
- if (NULL == nameList) {
+ if ((numObjects = (*entry.allFcn)(conn, &objects, entry.flags)) < 0) {
ret = 1;
- printf("Could not allocate memory for list of inactive domains\n");
- goto out;
- }
-
- numNames = virConnectListDefinedDomains(conn,
- nameList,
- numInactiveDomains);
-
- if (-1 == numNames) {
- ret = 1;
- printf("Could not get list of defined domains from hypervisor\n");
+ printf("Failed to get all %s\n", entry.objName);
showError(conn);
goto out;
}
-
- if (numNames > 0) {
- printf("Inactive domains:\n");
- }
-
- for (i = 0 ; i < numNames ; i++) {
- printf(" %s\n", *(nameList + i));
- /* The API documentation doesn't say so, but the names
- * returned by virConnectListDefinedDomains are strdup'd and
- * must be freed here. */
- free(*(nameList + i));
+ for (i = 0; i < numObjects; i++) {
+ int active = (*entry.isActiveFcn)(objects[i]);
+ /* Sure the name could be longer, but for a quick example this works */
+ printf("\t%8s (%s)\n",
+ (*entry.nameFcn)(objects[i]),
+ (active == 1 ? "active" : "non-active"));
+
+ /* We have to free the entry */
+ (*entry.freeFcn)(objects[i]);
}
-
+ free(objects);
out:
- free(nameList);
return ret;
}
-
int
main(int argc, char *argv[])
{
- int ret = 0;
+ int ret = 0, i;
virConnectPtr conn;
char *uri;
@@ -163,7 +191,7 @@ main(int argc, char *argv[])
* except, possibly, the URI of the hypervisor. */
conn = virConnectOpenAuth(uri, virConnectAuthPtrDefault, 0);
- if (NULL == conn) {
+ if (!conn) {
ret = 1;
printf("No connection to hypervisor\n");
showError(conn);
@@ -171,7 +199,7 @@ main(int argc, char *argv[])
}
uri = virConnectGetURI(conn);
- if (NULL == uri) {
+ if (!uri) {
ret = 1;
printf("Failed to get URI for hypervisor connection\n");
showError(conn);
@@ -181,18 +209,21 @@ main(int argc, char *argv[])
printf("Connected to hypervisor at \"%s\"\n", uri);
free(uri);
- if (0 != showHypervisorInfo(conn)) {
+ if (showHypervisorInfo(conn) < 0) {
ret = 1;
goto disconnect;
}
- if (0 != showDomains(conn)) {
- ret = 1;
- goto disconnect;
+ i = 0;
+ while (fcnTable[i].objName) {
+ ret = showObject(conn, fcnTable[i]);
+ if (ret != 0)
+ goto disconnect;
+ i++;
}
disconnect:
- if (0 != virConnectClose(conn)) {
+ if (virConnectClose(conn) < 0) {
printf("Failed to disconnect from hypervisor\n");
showError(conn);
ret = 1;
diff --git a/src/libvirt.c b/src/libvirt.c
index 1e78500..e717f16 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -8304,19 +8304,18 @@ error:
* VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT, for filtering based on whether
* a domain has snapshots.
*
- * Returns the number of domains found or -1 and sets domains to NULL in case
- * of error. On success, the array stored into @doms is guaranteed to have an
+ * Returns the number of domains found or -1 and sets domains to NULL in case of
+ * error. On success, the array stored into @domains is guaranteed to have an
* extra allocated element set to NULL but not included in the return count, to
* make iteration easier. The caller is responsible for calling virDomainFree()
- * on each array element, then calling free() on @doms.
+ * on each array element, then calling free() on @domains.
*
* Example of usage:
* virDomainPtr *domains;
- * virDomainPtr dom;
* int i;
* int ret;
- * unsigned int flags = VIR_CONNECT_LIST_RUNNING |
- * VIR_CONNECT_LIST_PERSISTENT;
+ * unsigned int flags = VIR_CONNECT_LIST_DOMAINS_RUNNING |
+ * VIR_CONNECT_LIST_DOMAINS_PERSISTENT;
*
* ret = virConnectListAllDomains(conn, &domains, flags);
* if (ret < 0)
@@ -10226,7 +10225,7 @@ error:
* this command is inherently racy; a network can be started between a call
* to virConnectNumOfNetworks() and this call; you are only guaranteed that
* all currently active networks were listed if the return is less than
- * @maxnames.
+ * @maxnames. The client must call free() on each returned name.
*/
int
virConnectListNetworks(virConnectPtr conn, char **const names, int maxnames)
@@ -11208,7 +11207,7 @@ error:
* this command is inherently racy; a interface can be started between a call
* to virConnectNumOfInterfaces() and this call; you are only guaranteed that
* all currently active interfaces were listed if the return is less than
- * @maxnames.
+ * @maxnames. The client must call free() on each returned name.
*/
int
virConnectListInterfaces(virConnectPtr conn, char **const names, int maxnames)
@@ -12076,7 +12075,7 @@ error:
* this command is inherently racy; a pool can be started between a call to
* virConnectNumOfStoragePools() and this call; you are only guaranteed
* that all currently active pools were listed if the return is less than
- * @maxnames.
+ * @maxnames. The client must call free() on each returned name.
*/
int
virConnectListStoragePools(virConnectPtr conn,
@@ -18285,7 +18284,7 @@ error:
* the results, see virDomainListAllSnapshots().
*
* Returns the number of domain snapshots found or -1 in case of error.
- * The caller is responsible for freeing each member of the array.
+ * The caller is responsible to call free() for each member of the array.
*/
int
virDomainSnapshotListNames(virDomainPtr domain, char **names, int nameslen,
@@ -18534,7 +18533,7 @@ error:
* the results, see virDomainSnapshotListAllChildren().
*
* Returns the number of domain snapshots found or -1 in case of error.
- * The caller is responsible for freeing each member of the array.
+ * The caller is responsible to call free() for each member of the array.
*/
int
virDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot,
--
1.7.11.7
--
libvir-list mailing list
libvir-list(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list