[libvirt] [PATCHv1 4/9] conf: Add helper for listing domains on drivers supporting virDomainObj

Peter Krempa pkrempa at redhat.com
Tue Jun 5 13:19:04 UTC 2012


This patch adds common code to list domains in fashion used by
virListAllDomains and helpers to filter this list.

This code supports filters based on data stored in the virDomainObj.
Supported filter flags:
  VIR_CONNECT_LIST_DOMAINS_ACTIVE
  VIR_CONNECT_LIST_DOMAINS_INACTIVE
  VIR_CONNECT_LIST_DOMAINS_PERSISTENT
  VIR_CONNECT_LIST_DOMAINS_TRANSIENT
  VIR_CONNECT_LIST_DOMAINS_RUNNING
  VIR_CONNECT_LIST_DOMAINS_PAUSED
  VIR_CONNECT_LIST_DOMAINS_SHUTOFF
  VIR_CONNECT_LIST_DOMAINS_OTHER
  VIR_CONNECT_LIST_DOMAINS_AUTOSTART
  VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART
  VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT
  VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT

Hypervisor specific flags have to be filtered after using this function.
This patch adds virDomainListFilter() helper function to remove elements
from the array based on a predicate.
---
New in this series.
---
 src/Makefile.am          |    6 +-
 src/conf/virdomainlist.c |  214 ++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/virdomainlist.h |   36 ++++++++
 src/libvirt_private.syms |    5 +
 4 files changed, 260 insertions(+), 1 deletions(-)
 create mode 100644 src/conf/virdomainlist.c
 create mode 100644 src/conf/virdomainlist.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 5693fb4..fd9d892 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -194,6 +194,9 @@ CPU_CONF_SOURCES =						\
 CONSOLE_CONF_SOURCES =						\
 		conf/virconsole.c conf/virconsole.h

+# Domain listing helpers
+DOMAIN_LIST_SOURCES =						\
+		conf/virdomainlist.c conf/virdomainlist.h
 CONF_SOURCES =							\
 		$(NETDEV_CONF_SOURCES)				\
 		$(DOMAIN_CONF_SOURCES)				\
@@ -206,7 +209,8 @@ CONF_SOURCES =							\
 		$(INTERFACE_CONF_SOURCES)			\
 		$(SECRET_CONF_SOURCES)				\
 		$(CPU_CONF_SOURCES)				\
-		$(CONSOLE_CONF_SOURCES)
+		$(CONSOLE_CONF_SOURCES)				\
+		$(DOMAIN_LIST_SOURCES)

 # The remote RPC driver, covering domains, storage, networks, etc
 REMOTE_DRIVER_GENERATED = \
diff --git a/src/conf/virdomainlist.c b/src/conf/virdomainlist.c
new file mode 100644
index 0000000..180b37d
--- /dev/null
+++ b/src/conf/virdomainlist.c
@@ -0,0 +1,214 @@
+/**
+ * virdomainlist.c: Helpers for listing and filtering domains.
+ *
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Peter Krempa <pkrempa at redhat.com>
+ */
+
+#include <config.h>
+
+#include "virdomainlist.h"
+
+#include "internal.h"
+#include "virhash.h"
+#include "domain_conf.h"
+#include "memory.h"
+#include "datatypes.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+struct virDomainListData {
+    virConnectPtr conn;
+    virDomainPtr *domains;
+    unsigned int flags;
+    int ndomains;
+    size_t size;
+    bool error;
+};
+
+#define MATCH(FLAG) (data->flags & (FLAG))
+static void
+virDomainListPopulate(void *payload,
+                      const void *name ATTRIBUTE_UNUSED,
+                      void *opaque)
+{
+    struct virDomainListData *data = opaque;
+    virDomainObjPtr vm = payload;
+    virDomainPtr dom;
+
+    if (data->error)
+        return;
+
+    virDomainObjLock(vm);
+    /* check if the domain matches the filter */
+
+    /* filter by active state */
+    if (MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE |
+              VIR_CONNECT_LIST_DOMAINS_INACTIVE) &&
+        !((MATCH(VIR_CONNECT_LIST_DOMAINS_ACTIVE) &&
+           virDomainObjIsActive(vm)) ||
+          (MATCH(VIR_CONNECT_LIST_DOMAINS_INACTIVE) &&
+           !virDomainObjIsActive(vm))))
+        goto cleanup;
+
+
+    /* filter by persistence */
+    if (MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT |
+              VIR_CONNECT_LIST_DOMAINS_TRANSIENT) &&
+        !((MATCH(VIR_CONNECT_LIST_DOMAINS_PERSISTENT) &&
+           vm->persistent) ||
+          (MATCH(VIR_CONNECT_LIST_DOMAINS_TRANSIENT) &&
+           !vm->persistent)))
+        goto cleanup;
+
+    /* filter by domain state */
+    if (MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING |
+              VIR_CONNECT_LIST_DOMAINS_PAUSED  |
+              VIR_CONNECT_LIST_DOMAINS_SHUTOFF |
+              VIR_CONNECT_LIST_DOMAINS_OTHER)) {
+        int st = virDomainObjGetState(vm, NULL);
+        if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_RUNNING) &&
+               st == VIR_DOMAIN_RUNNING) ||
+              (MATCH(VIR_CONNECT_LIST_DOMAINS_PAUSED) &&
+               st == VIR_DOMAIN_PAUSED) ||
+              (MATCH(VIR_CONNECT_LIST_DOMAINS_SHUTOFF) &&
+               st == VIR_DOMAIN_SHUTOFF) ||
+              (MATCH(VIR_CONNECT_LIST_DOMAINS_OTHER) &&
+               (st == VIR_DOMAIN_NOSTATE || st == VIR_DOMAIN_BLOCKED ||
+                st == VIR_DOMAIN_SHUTDOWN || st == VIR_DOMAIN_CRASHED ||
+                st == VIR_DOMAIN_PMSUSPENDED))))
+            goto cleanup;
+    }
+
+    /* managed save filter has to be driver specific */
+
+    /* filter by autostart option */
+    if (MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART |
+              VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART) &&
+        !((MATCH(VIR_CONNECT_LIST_DOMAINS_AUTOSTART) && vm->autostart) ||
+          (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART) && !vm->autostart)))
+        goto cleanup;
+
+    /* filter by snapshot existence */
+    if (MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT |
+              VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT)) {
+        int nsnapshots = virDomainSnapshotObjListNum(&vm->snapshots, 0);
+        if (!((MATCH(VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT) &&
+               nsnapshots > 0) ||
+              (MATCH(VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT) &&
+               nsnapshots <= 0)))
+            goto cleanup;
+    }
+
+    /* just count the machines */
+    if (!data->domains) {
+        data->ndomains++;
+        return;
+    }
+
+    /* add the domain to the result list */
+    if (VIR_EXPAND_N(data->domains, data->size, 1) < 0)
+        goto no_memory;
+
+    if (!(dom = virGetDomain(data->conn, vm->def->name, vm->def->uuid)))
+        goto no_memory;
+
+    dom->id = vm->def->id;
+
+    data->domains[data->ndomains++] = dom;
+
+cleanup:
+    virDomainObjUnlock(vm);
+    return;
+
+no_memory:
+    virReportOOMError();
+    data->error = true;
+    goto cleanup;
+}
+#undef MATCH
+
+int
+virDomainList(virConnectPtr conn, virHashTablePtr domobjs,
+              virDomainPtr **domains, unsigned int flags)
+{
+    int ret = -1;
+    int i;
+
+    struct virDomainListData data = { conn,  NULL, flags, 0, 0, false };
+
+    if (domains) {
+        if (VIR_ALLOC_N(data.domains, 1) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+        data.size = 1;
+    }
+
+    virHashForEach(domobjs, virDomainListPopulate, &data);
+
+    if (data.error)
+        goto cleanup;
+
+    if (data.domains) {
+        *domains = data.domains;
+        data.domains = NULL;
+    }
+
+    ret = data.ndomains;
+
+cleanup:
+    if (data.domains) {
+        for (i = 0; i < data.size; i++)
+            if (data.domains[i])
+                virDomainFree(data.domains[i]);
+        VIR_FREE(data.domains);
+    }
+
+    return ret;
+}
+
+int
+virDomainListFilter(virDomainPtr **doms,
+                    int *ndoms,
+                    virDomainListFilterFunc filter,
+                    int result)
+{
+    int i = 0;
+    int ret;
+
+    while (i < *ndoms) {
+        ret = filter((*doms)[i]);
+        if (ret < 0)
+            return -1;
+
+        if (ret == result) {
+            virDomainFree((*doms)[i]);
+            if (i != --*ndoms)
+                memmove(&(*doms)[i], &(*doms)[i+1], sizeof(*doms) * (*ndoms - i));
+
+            if (VIR_REALLOC_N(*doms, *ndoms) < 0) {
+                ; /* not fatal */
+            }
+            continue;
+        }
+        i++;
+    }
+    return 0;
+}
diff --git a/src/conf/virdomainlist.h b/src/conf/virdomainlist.h
new file mode 100644
index 0000000..80fe4f8
--- /dev/null
+++ b/src/conf/virdomainlist.h
@@ -0,0 +1,36 @@
+/**
+ * virdomainlist.h: Helpers for listing and filtering domains.
+ *
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Peter Krempa <pkrempa at redhat.com>
+ */
+#ifndef __VIR_DOMAIN_LIST_H__
+# define __VIR_DOMAIN_LIST_H__
+
+# include "internal.h"
+# include "virhash.h"
+
+typedef int (*virDomainListFilterFunc)(virDomainPtr dom);
+
+int virDomainListFilter(virDomainPtr **doms, int *ndoms,
+                        virDomainListFilterFunc filter, int result);
+
+int virDomainList(virConnectPtr conn, virHashTablePtr domobjs,
+                  virDomainPtr **domains, unsigned int flags);
+
+#endif /* __VIR_DOMAIN_LIST_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fdf2186..eacdf3a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1237,6 +1237,11 @@ virConsoleOpen;
 virDBusGetSystemBus;


+# virdomainlist.h
+virDomainList;
+virDomainListFilter;
+
+
 # virfile.h
 virFileClose;
 virFileDirectFdFlag;
-- 
1.7.3.4




More information about the libvir-list mailing list