[PATCH 07/26] hypervisor: move support for auto-shutdown out of QEMU driver

Daniel P. Berrangé posted 26 patches 1 week, 5 days ago
[PATCH 07/26] hypervisor: move support for auto-shutdown out of QEMU driver
Posted by Daniel P. Berrangé 1 week, 5 days ago
This is a move of the code that currently exists in the QEMU
driver, into the common layer that can be used by multiple
drivers.

The code currently supports performing managed save of all
running guests, ignoring any failures.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 src/hypervisor/domain_driver.c | 48 ++++++++++++++++++++++++++++++++++
 src/hypervisor/domain_driver.h |  8 +++++-
 src/libvirt_private.syms       |  1 +
 src/qemu/qemu_driver.c         | 47 ++++-----------------------------
 4 files changed, 61 insertions(+), 43 deletions(-)

diff --git a/src/hypervisor/domain_driver.c b/src/hypervisor/domain_driver.c
index 44c8fad4d5..949e3d01f1 100644
--- a/src/hypervisor/domain_driver.c
+++ b/src/hypervisor/domain_driver.c
@@ -706,3 +706,51 @@ void virDomainDriverAutoStart(virDomainObjList *domains,
 
     virDomainObjListForEach(domains, false, virDomainDriverAutoStartOne, &state);
 }
+
+
+void
+virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg)
+{
+    g_autoptr(virConnect) conn = NULL;
+    int numDomains = 0;
+    size_t i;
+    int state;
+    virDomainPtr *domains = NULL;
+    g_autofree unsigned int *flags = NULL;
+
+    if (!(conn = virConnectOpen(cfg->uri)))
+        goto cleanup;
+
+    if ((numDomains = virConnectListAllDomains(conn,
+                                               &domains,
+                                               VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0)
+        goto cleanup;
+
+    flags = g_new0(unsigned int, numDomains);
+
+    /* First we pause all VMs to make them stop dirtying
+       pages, etc. We remember if any VMs were paused so
+       we can restore that on resume. */
+    for (i = 0; i < numDomains; i++) {
+        flags[i] = VIR_DOMAIN_SAVE_RUNNING;
+        if (virDomainGetState(domains[i], &state, NULL, 0) == 0) {
+            if (state == VIR_DOMAIN_PAUSED)
+                flags[i] = VIR_DOMAIN_SAVE_PAUSED;
+        }
+        virDomainSuspend(domains[i]);
+    }
+
+    /* Then we save the VMs to disk */
+    for (i = 0; i < numDomains; i++)
+        if (virDomainManagedSave(domains[i], flags[i]) < 0)
+            VIR_WARN("Unable to perform managed save of '%s': %s",
+                     virDomainGetName(domains[i]),
+                     virGetLastErrorMessage());
+
+ cleanup:
+    if (domains) {
+        for (i = 0; i < numDomains; i++)
+            virObjectUnref(domains[i]);
+        VIR_FREE(domains);
+    }
+}
diff --git a/src/hypervisor/domain_driver.h b/src/hypervisor/domain_driver.h
index d695e26f90..d1588ea712 100644
--- a/src/hypervisor/domain_driver.h
+++ b/src/hypervisor/domain_driver.h
@@ -81,7 +81,7 @@ typedef void (*virDomainDriverAutoStartCallback)(virDomainObj *vm,
                                                  void *opaque);
 
 typedef struct _virDomainDriverAutoStartConfig {
-    char *stateDir;
+    const char *stateDir;
     virDomainDriverAutoStartCallback callback;
     void *opaque;
     int delayMS; /* milliseconds between starting each guest */
@@ -89,3 +89,9 @@ typedef struct _virDomainDriverAutoStartConfig {
 
 void virDomainDriverAutoStart(virDomainObjList *domains,
                               virDomainDriverAutoStartConfig *cfg);
+
+typedef struct _virDomainDriverAutoShutdownConfig {
+    const char *uri;
+} virDomainDriverAutoShutdownConfig;
+
+void virDomainDriverAutoShutdown(virDomainDriverAutoShutdownConfig *cfg);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d90b15e215..781bb566d2 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1640,6 +1640,7 @@ virDomainCgroupSetupVcpuBW;
 
 # hypervisor/domain_driver.h
 virDomainDriverAddIOThreadCheck;
+virDomainDriverAutoShutdown;
 virDomainDriverAutoStart;
 virDomainDriverDelIOThreadCheck;
 virDomainDriverGenerateMachineName;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f689dadc0a..8c16566ce8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -944,51 +944,14 @@ qemuStateReload(void)
 static int
 qemuStateStop(void)
 {
-    int ret = -1;
-    g_autoptr(virConnect) conn = NULL;
-    int numDomains = 0;
-    size_t i;
-    int state;
-    virDomainPtr *domains = NULL;
-    g_autofree unsigned int *flags = NULL;
     g_autoptr(virQEMUDriverConfig) cfg = virQEMUDriverGetConfig(qemu_driver);
+    virDomainDriverAutoShutdownConfig ascfg = {
+        .uri = cfg->uri,
+    };
 
-    if (!(conn = virConnectOpen(cfg->uri)))
-        goto cleanup;
-
-    if ((numDomains = virConnectListAllDomains(conn,
-                                               &domains,
-                                               VIR_CONNECT_LIST_DOMAINS_ACTIVE)) < 0)
-        goto cleanup;
-
-    flags = g_new0(unsigned int, numDomains);
-
-    /* First we pause all VMs to make them stop dirtying
-       pages, etc. We remember if any VMs were paused so
-       we can restore that on resume. */
-    for (i = 0; i < numDomains; i++) {
-        flags[i] = VIR_DOMAIN_SAVE_RUNNING;
-        if (virDomainGetState(domains[i], &state, NULL, 0) == 0) {
-            if (state == VIR_DOMAIN_PAUSED)
-                flags[i] = VIR_DOMAIN_SAVE_PAUSED;
-        }
-        virDomainSuspend(domains[i]);
-    }
-
-    ret = 0;
-    /* Then we save the VMs to disk */
-    for (i = 0; i < numDomains; i++)
-        if (virDomainManagedSave(domains[i], flags[i]) < 0)
-            ret = -1;
-
- cleanup:
-    if (domains) {
-        for (i = 0; i < numDomains; i++)
-            virObjectUnref(domains[i]);
-        VIR_FREE(domains);
-    }
+    virDomainDriverAutoShutdown(&ascfg);
 
-    return ret;
+    return 0;
 }
 
 
-- 
2.47.1