[libvirt] [PATCH v2 1/8] hellolibvirt: Update hellolibvirt example

Dave Allan dallan at redhat.com
Thu Feb 21 01:05:29 UTC 2013


On Wed, Feb 20, 2013 at 12:38:38PM -0500, John Ferlan wrote:
> 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 at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list




More information about the libvir-list mailing list