Currently supports only renaming inactive domains without snapshots. Signed-off-by: Tomas Meszaros <exo@xxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list