[libvirt] [PATCH 5/5] qemu: Implement virDomainRename

Tomas Meszaros exo at tty.sk
Wed Aug 5 11:59:11 UTC 2015


Currently supports only renaming inactive domains without snapshots.

Signed-off-by: Tomas Meszaros <exo at tty.sk>
---
 src/qemu/qemu_driver.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 172 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b9278f8..3ff04fe 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19835,6 +19835,177 @@ qemuDomainSetUserPassword(virDomainPtr dom,
 }
 
 
+static int qemuDomainRename(virDomainPtr dom,
+                            const char *new_name)
+{
+    virQEMUDriverPtr driver = dom->conn->privateData;
+    virQEMUDriverConfigPtr cfg = NULL;
+    virDomainObjPtr vm;
+    virObjectEventPtr event = NULL;
+    int ret = -1;
+    int logfile = -1;
+    size_t i;
+    char ebuf[1024];
+    char *timestamp;
+    char *rename_log_msg = NULL;
+    char *new_dom_name = NULL;
+    char *old_dom_name = NULL;
+    char *old_dom_cfg_file = NULL;
+    char *new_guest_path = NULL;
+    char *old_guest_path = NULL;
+    virDomainChrDefPtr agent = NULL;
+
+    if (VIR_STRDUP(new_dom_name, new_name) < 0)
+        goto cleanup;
+
+    if (!(vm = qemuDomObjFromDomain(dom)))
+        goto cleanup;
+
+    if (virDomainRenameEnsureACL(dom->conn, vm->def) < 0)
+        goto cleanup;
+
+    cfg = virQEMUDriverGetConfig(driver);
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (virDomainObjIsActive(vm)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("cannot rename active domain"));
+        goto endjob;
+    }
+
+    if (!vm->persistent) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("cannot rename a transient domain"));
+        goto endjob;
+    }
+
+    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_SHUTOFF) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       "%s", _("domain has to be shutoff before renaming"));
+        goto endjob;
+    }
+
+    if (virDomainSnapshotObjListNum(vm->snapshots, NULL, 0) > 0) {
+        virReportError(VIR_ERR_OPERATION_INVALID,
+                       "%s", _("cannot rename domain with snapshots"));
+        goto endjob;
+    }
+
+    if (virAsprintf(&rename_log_msg, ": domain %s has been renamed to %s\n",
+                    vm->def->name, new_name) < 0) {
+        goto endjob;
+    }
+
+    if (!(old_dom_cfg_file = virDomainConfigFile(cfg->configDir,
+                                                 vm->def->name))) {
+        goto endjob;
+    }
+
+    if (virDomainObjListRenameAddNew(driver->domains, vm, new_name) < 0)
+        goto endjob;
+
+    if ((logfile = qemuDomainCreateLog(driver, vm, true)) < 0)
+        goto rollback;
+
+    /* Switch name in domain definition. */
+    old_dom_name = vm->def->name;
+    vm->def->name = new_dom_name;
+    new_dom_name = NULL;
+
+    /* Change guest agent path. */
+    for (i = 0; i < vm->def->nchannels; i++) {
+        virDomainChrDefPtr channel = vm->def->channels[i];
+        if (channel->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
+            channel->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
+            channel->source.data.file.path &&
+            channel->target.name) {
+
+            if (virAsprintf(&new_guest_path, "%s/%s.%s",
+                            cfg->channelTargetDir,
+                            new_name, channel->target.name) < 0)
+                goto rollback;
+
+            old_guest_path = channel->source.data.file.path;
+            channel->source.data.file.path = new_guest_path;
+            new_guest_path = NULL;
+            agent = channel;
+            break;
+        }
+    }
+
+
+    if (virDomainSaveConfig(cfg->configDir, vm->def) < 0)
+        goto rollback;
+
+    if (virFileExists(old_dom_cfg_file) &&
+        unlink(old_dom_cfg_file) < 0) {
+        virReportSystemError(errno,
+                             _("cannot remove old domain config file %s"),
+                             old_dom_cfg_file);
+        goto rollback;
+    }
+
+    /* Remove old domain name from table. */
+    virDomainObjListRenameRemove(driver->domains, old_dom_name);
+
+    event = virDomainEventLifecycleNewFromObj(vm,
+                                              VIR_DOMAIN_EVENT_DEFINED,
+                                              VIR_DOMAIN_EVENT_DEFINED_RENAMED);
+
+    /* Write message to the log. */
+    if ((timestamp = virTimeStringNow()) != NULL) {
+        if (safewrite(logfile, timestamp, strlen(timestamp)) < 0 ||
+            safewrite(logfile, rename_log_msg,
+                      strlen(rename_log_msg)) < 0) {
+            VIR_WARN("Unable to write timestamp to logfile: %s",
+                     virStrerror(errno, ebuf, sizeof(ebuf)));
+        }
+        VIR_FREE(timestamp);
+    }
+
+    /* Success, domain has been renamed. */
+    ret = 0;
+
+ endjob:
+    qemuDomainObjEndJob(driver, vm);
+
+ cleanup:
+    if (VIR_CLOSE(logfile) < 0) {
+        VIR_WARN("Unable to close logfile: %s",
+                 virStrerror(errno, ebuf, sizeof(ebuf)));
+    }
+    virDomainObjEndAPI(&vm);
+    VIR_FREE(old_dom_cfg_file);
+    VIR_FREE(old_dom_name);
+    VIR_FREE(new_dom_name);
+    VIR_FREE(rename_log_msg);
+    VIR_FREE(new_guest_path);
+    VIR_FREE(old_guest_path);
+    if (event)
+        qemuDomainEventQueue(driver, event);
+    virObjectUnref(cfg);
+    return ret;
+
+
+ rollback:
+    if (old_dom_name) {
+        new_dom_name = vm->def->name;
+        vm->def->name = old_dom_name;
+        old_dom_name = NULL;
+    }
+
+    if (agent) {
+        new_guest_path = agent->source.data.file.path;
+        agent->source.data.file.path = old_guest_path;
+        old_guest_path = NULL;
+    }
+
+    virDomainObjListRenameRemove(driver->domains, new_name);
+    goto endjob;
+}
+
 static virHypervisorDriver qemuHypervisorDriver = {
     .name = QEMU_DRIVER_NAME,
     .connectOpen = qemuConnectOpen, /* 0.2.0 */
@@ -20042,6 +20213,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainGetFSInfo = qemuDomainGetFSInfo, /* 1.2.11 */
     .domainInterfaceAddresses = qemuDomainInterfaceAddresses, /* 1.2.14 */
     .domainSetUserPassword = qemuDomainSetUserPassword, /* 1.2.16 */
+    .domainRename = qemuDomainRename, /* 1.2.19 */
 };
 
 
-- 
2.1.0




More information about the libvir-list mailing list