[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libvir] [PATCH 7/7] Add KVM restore support using migration.



Signed-off-by: Jim Paris <jim jtan com>
---
 src/qemu_driver.c |  106 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 50ab702..c6de8a0 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -2047,10 +2047,108 @@ static int qemudDomainSave(virDomainPtr dom,
 
 
 static int qemudDomainRestore(virConnectPtr conn,
-                       const char *path ATTRIBUTE_UNUSED) {
-    /*struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;*/
-    qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "restore is not supported");
-    return -1;
+                       const char *path) {
+    struct qemud_driver *driver = (struct qemud_driver *)conn->privateData;
+    struct qemud_vm_def *def;
+    struct qemud_vm *vm;
+    int fd;
+    char *xml;
+    struct qemud_save_header header;
+
+    /* Verify the header and read the XML */
+    if ((fd = open(path, O_RDONLY)) < 0) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "cannot read domain image");
+        return -1;
+    }
+
+    if (read(fd, &header, sizeof(header)) != sizeof(header)) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "failed to read qemu header");
+        close(fd);
+        return -1;
+    }
+    
+    if (memcmp(header.magic, QEMUD_SAVE_MAGIC, sizeof(header.magic)) != 0) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "image magic is incorrect");
+        close(fd);
+        return -1;
+    }
+
+    if ((xml = (char *)malloc(header.xml_len + 1)) == NULL) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "out of memory");
+        close(fd);
+        return -1;
+    }
+
+    if (read(fd, xml, header.xml_len) != header.xml_len) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "failed to read XML");
+        close(fd);
+        free(xml);
+        return -1;
+    }
+    xml[header.xml_len] = '\0';
+
+    /* Create a domain from this XML */
+    if (!(def = qemudParseVMDef(conn, driver, xml, NULL))) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "failed to parse XML");
+        close(fd);
+        free(xml);
+        return -1;
+    }
+    free(xml);
+
+    /* Ensure the name and UUID don't already exist in an active VM */
+    vm = qemudFindVMByUUID(driver, def->uuid);
+    if (!vm) vm = qemudFindVMByName(driver, def->name);
+    if (vm && qemudIsActiveVM(vm)) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "domain to restore is already active");
+        close(fd);
+        return -1;
+    }
+    
+    if (!(vm = qemudAssignVMDef(conn, driver, def))) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "failed to assign new VM");
+        qemudFreeVMDef(def);
+        close(fd);
+        return -1;
+    }
+
+    /* Set the migration source and start it up. */
+    snprintf(vm->migrateFrom, sizeof(vm->migrateFrom), "stdio");
+    vm->stdinFd = fd;
+   
+    if (qemudStartVMDaemon(conn, driver, vm) < 0) {
+        qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                         "failed to start VM");
+        if (!vm->configFile[0])
+            qemudRemoveInactiveVM(driver, vm);
+        close(fd);
+        return -1;
+    }
+    close(fd);
+    vm->migrateFrom[0] = '\0';
+    vm->stdinFd = 0;
+
+    /* If it was running before, resume it now. */
+    if (header.was_running) {
+        char *info;
+        if (qemudMonitorCommand(driver, vm, "cont\n", &info) < 0) {
+            qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, 
+                             "failed to resume domain");
+            return -1;
+        }
+        free(info);
+        vm->state = VIR_DOMAIN_RUNNING;
+    }
+
+    return 0;
 }
 
 
-- 
1.5.3.rc4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]