From 1f1a0ca63c5492c7d41a0cdbd452a2743f314ebc Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Fri, 8 May 2009 10:11:14 +0000 Subject: [PATCH] Improve name & UUID uniqueness checking in QEMU driver (cherry picked from commit 54ebbde1e18ec831ff2fddb44ec27ed5dde7874a) Fedora-patch: libvirt-0.6.2-qemu-name-uniqueness.patch --- src/qemu_driver.c | 103 ++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/qemu_driver.c b/src/qemu_driver.c index 8473616..dfd19c5 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -2174,22 +2174,37 @@ static virDomainPtr qemudDomainCreate(virConnectPtr conn, const char *xml, if (virSecurityDriverVerify(conn, def) < 0) goto cleanup; - vm = virDomainFindByName(&driver->domains, def->name); - if (vm) { - qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, - _("domain '%s' is already defined"), - def->name); - goto cleanup; - } + /* See if a VM with matching UUID already exists */ vm = virDomainFindByUUID(&driver->domains, def->uuid); if (vm) { - char uuidstr[VIR_UUID_STRING_BUFLEN]; + /* UUID matches, but if names don't match, refuse it */ + if (STRNEQ(vm->def->name, def->name)) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, uuidstr); + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("domain '%s' is already defined with uuid %s"), + vm->def->name, uuidstr); + goto cleanup; + } - virUUIDFormat(def->uuid, uuidstr); - qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, - _("domain with uuid '%s' is already defined"), - uuidstr); - goto cleanup; + /* UUID & name match, but if VM is already active, refuse it */ + if (virDomainIsActive(vm)) { + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("domain is already active as '%s'"), vm->def->name); + goto cleanup; + } + virDomainObjUnlock(vm); + } else { + /* UUID does not match, but if a name matches, refuse it */ + vm = virDomainFindByName(&driver->domains, def->name); + if (vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, uuidstr); + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("domain '%s' is already defined with uuid %s"), + def->name, uuidstr); + goto cleanup; + } } if (!(vm = virDomainAssignDef(conn, @@ -2368,6 +2383,11 @@ static int qemudDomainDestroy(virDomainPtr dom) { _("no domain with matching id %d"), dom->id); goto cleanup; } + if (!virDomainIsActive(vm)) { + qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, + "%s", _("domain is not running")); + goto cleanup; + } qemudShutdownVMDaemon(dom->conn, driver, vm); event = virDomainEventNewFromObj(vm, @@ -3272,17 +3292,36 @@ static int qemudDomainRestore(virConnectPtr conn, goto cleanup; } - /* Ensure the name and UUID don't already exist in an active VM */ + /* See if a VM with matching UUID already exists */ vm = virDomainFindByUUID(&driver->domains, def->uuid); - if (!vm) - vm = virDomainFindByName(&driver->domains, def->name); if (vm) { + /* UUID matches, but if names don't match, refuse it */ + if (STRNEQ(vm->def->name, def->name)) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, uuidstr); + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("domain '%s' is already defined with uuid %s"), + vm->def->name, uuidstr); + goto cleanup; + } + + /* UUID & name match, but if VM is already active, refuse it */ if (virDomainIsActive(vm)) { qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, _("domain is already active as '%s'"), vm->def->name); goto cleanup; - } else { - virDomainObjUnlock(vm); + } + virDomainObjUnlock(vm); + } else { + /* UUID does not match, but if a name matches, refuse it */ + vm = virDomainFindByName(&driver->domains, def->name); + if (vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, uuidstr); + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("domain '%s' is already defined with uuid %s"), + def->name, uuidstr); + goto cleanup; } } @@ -3470,18 +3509,41 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { if (virSecurityDriverVerify(conn, def) < 0) goto cleanup; - vm = virDomainFindByName(&driver->domains, def->name); + /* See if a VM with matching UUID already exists */ + vm = virDomainFindByUUID(&driver->domains, def->uuid); if (vm) { + /* UUID matches, but if names don't match, refuse it */ + if (STRNEQ(vm->def->name, def->name)) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, uuidstr); + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("domain '%s' is already defined with uuid %s"), + vm->def->name, uuidstr); + goto cleanup; + } + + /* UUID & name match */ virDomainObjUnlock(vm); newVM = 0; + } else { + /* UUID does not match, but if a name matches, refuse it */ + vm = virDomainFindByName(&driver->domains, def->name); + if (vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(vm->def->uuid, uuidstr); + qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, + _("domain '%s' is already defined with uuid %s"), + def->name, uuidstr); + goto cleanup; + } } if (!(vm = virDomainAssignDef(conn, &driver->domains, def))) { - virDomainDefFree(def); goto cleanup; } + def = NULL; vm->persistent = 1; if (virDomainSaveConfig(conn, @@ -3503,6 +3565,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) { if (dom) dom->id = vm->def->id; cleanup: + virDomainDefFree(def); if (vm) virDomainObjUnlock(vm); if (event) -- 1.6.2.5