* src/qemu/qemu_conf.h: qemud_driver data structure extension. * src/qemu/qemu_driver.c: qemu driver API extension. Signed-off-by: Hong Xiang <hxiang@xxxxxxxxxxxxxxxxxx> --- src/qemu/qemu_conf.h | 2 + src/qemu/qemu_driver.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index ff5cf23..56e9972 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -138,6 +138,8 @@ struct qemud_driver { * of guests which will be automatically killed * when the virConnectPtr is closed*/ virHashTablePtr autodestroy; + + char *managedCoreDumpDir; }; typedef struct _qemuDomainCmdlineDef qemuDomainCmdlineDef; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5e49ff4..cccfc92 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -472,6 +472,9 @@ qemudStartup(int privileged) { if (virAsprintf(&qemu_driver->autoDumpPath, "%s/lib/libvirt/qemu/dump", LOCALSTATEDIR) == -1) goto out_of_memory; + if (virAsprintf(&qemu_driver->managedCoreDumpDir, + "%s/lib/libvirt/qemu/managed-core-dump", LOCALSTATEDIR) == -1) + goto out_of_memory; } else { uid_t uid = geteuid(); char *userdir = virGetUserDirectory(uid); @@ -502,6 +505,9 @@ qemudStartup(int privileged) { goto out_of_memory; if (virAsprintf(&qemu_driver->autoDumpPath, "%s/qemu/dump", base) == -1) goto out_of_memory; + if (virAsprintf(&qemu_driver->managedCoreDumpDir, + "%s/lib/libvirt/qemu/managed-core-dump", base) == -1) + goto out_of_memory; } if (virFileMakePath(qemu_driver->stateDir) < 0) { @@ -540,6 +546,13 @@ qemudStartup(int privileged) { qemu_driver->autoDumpPath, virStrerror(errno, ebuf, sizeof ebuf)); goto error; } + if (virFileMakePath(qemu_driver->managedCoreDumpDir) < 0) { + char ebuf[1024]; + VIR_ERROR(_("Failed to create managed-core-dump dir '%s': %s"), + qemu_driver->managedCoreDumpDir, + virStrerror(errno, ebuf, sizeof ebuf)); + goto error; + } /* Configuration paths are either ~/.libvirt/qemu/... (session) or * /etc/libvirt/qemu/... (system). @@ -606,6 +619,13 @@ qemudStartup(int privileged) { qemu_driver->snapshotDir, qemu_driver->user, qemu_driver->group); goto error; } + if (chown(qemu_driver->managedCoreDumpDir, qemu_driver->user, qemu_driver->group) < 0) { + virReportSystemError(errno, + _("unable to set ownership of '%s' to %d:%d"), + qemu_driver->managedCoreDumpDir, + qemu_driver->user, qemu_driver->group); + goto error; + } } /* If hugetlbfs is present, then we need to create a sub-directory within @@ -801,6 +821,7 @@ qemudShutdown(void) { VIR_FREE(qemu_driver->hugepage_path); VIR_FREE(qemu_driver->saveImageFormat); VIR_FREE(qemu_driver->dumpImageFormat); + VIR_FREE(qemu_driver->managedCoreDumpDir); virSecurityManagerFree(qemu_driver->securityManager); @@ -2843,6 +2864,19 @@ cleanup: return ret; } +static char * +qemuDomainManagedCoreDumpPath(struct qemud_driver *driver, virDomainObjPtr vm) { + char *ret; + + if (virAsprintf(&ret, "%s/%s.core", driver->managedCoreDumpDir, + vm->def->name) < 0) { + virReportOOMError(); + return(NULL); + } + + return(ret); +} + static int doCoreDump(struct qemud_driver *driver, virDomainObjPtr vm, @@ -2928,7 +2962,7 @@ getCompressionType(struct qemud_driver *driver) return compress; } -static int qemudDomainCoreDump(virDomainPtr dom, +static int qemudDomainCoreDumpInternal(virDomainPtr dom, const char *path, unsigned int flags) { @@ -2938,6 +2972,7 @@ static int qemudDomainCoreDump(virDomainPtr dom, int resume = 0, paused = 0; int ret = -1; virDomainEventPtr event = NULL; + char * real_path = NULL; virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH | VIR_DUMP_BYPASS_CACHE | VIR_DUMP_RESET, -1); @@ -2952,6 +2987,13 @@ static int qemudDomainCoreDump(virDomainPtr dom, _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } + if (NULL == path) { + real_path = qemuDomainManagedCoreDumpPath(driver, vm); + if(NULL == real_path) + goto cleanup; + } else { + real_path = (char *)path; + } if (qemuDomainObjBeginAsyncJobWithDriver(driver, vm, QEMU_ASYNC_JOB_DUMP) < 0) @@ -2982,7 +3024,7 @@ static int qemudDomainCoreDump(virDomainPtr dom, } } - ret = doCoreDump(driver, vm, path, getCompressionType(driver), + ret = doCoreDump(driver, vm, real_path, getCompressionType(driver), (flags & VIR_DUMP_BYPASS_CACHE) != 0); if (ret < 0) goto endjob; @@ -3027,6 +3069,8 @@ endjob: } cleanup: + if(NULL == path) + VIR_FREE(real_path); if (vm) virDomainObjUnlock(vm); if (event) @@ -3035,6 +3079,130 @@ cleanup: return ret; } +static int qemudDomainCoreDump(virDomainPtr dom, + const char *path, + unsigned int flags) +{ + return qemudDomainCoreDumpInternal(dom, path, flags); +} + +static int +qemuDomainManagedCoreDump(virDomainPtr dom, unsigned int flags) +{ + return qemudDomainCoreDumpInternal(dom, NULL, flags); +} + +static int +qemuDomainHasManagedCoreDump(virDomainPtr dom, unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm = NULL; + int ret = -1; + char *name = NULL; + + virCheckFlags(0, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + name = qemuDomainManagedCoreDumpPath(driver, vm); + if (name == NULL) + goto cleanup; + + ret = virFileExists(name); + +cleanup: + VIR_FREE(name); + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + +static int +qemuDomainManagedCoreDumpRemove(virDomainPtr dom, unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm = NULL; + int ret = -1; + char *name = NULL; + + virCheckFlags(0, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain with matching uuid '%s'"), uuidstr); + goto cleanup; + } + + name = qemuDomainManagedCoreDumpPath(driver, vm); + if (name == NULL) + goto cleanup; + + ret = unlink(name); + +cleanup: + VIR_FREE(name); + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + +static int +qemuDomainManagedCoreDumpDownload(virDomainPtr dom, + virStreamPtr st, + unsigned int flags) +{ + struct qemud_driver *driver = dom->conn->privateData; + virDomainObjPtr vm; + int ret = -1; + char *name = NULL; + + virCheckFlags(0, -1); + + qemuDriverLock(driver); + vm = virDomainFindByUUID(&driver->domains, dom->uuid); + + if (!vm) { + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(dom->uuid, uuidstr); + qemuReportError(VIR_ERR_NO_DOMAIN, + _("no domain matching uuid '%s'"), uuidstr); + goto cleanup; + } + + name = qemuDomainManagedCoreDumpPath(driver, vm); + if (NULL == name) + goto cleanup; + + if (virFDStreamOpenFile(st, name, 0, 0, O_RDONLY) < 0) { + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("unable to open stream")); + goto cleanup; + } + + ret = 0; + +cleanup: + VIR_FREE(name); + if (vm) + virDomainObjUnlock(vm); + qemuDriverUnlock(driver); + return ret; +} + static char * qemuDomainScreenshot(virDomainPtr dom, virStreamPtr st, @@ -10904,6 +11072,10 @@ static virDriver qemuDriver = { .domainGetBlockJobInfo = qemuDomainGetBlockJobInfo, /* 0.9.4 */ .domainBlockJobSetSpeed = qemuDomainBlockJobSetSpeed, /* 0.9.4 */ .domainBlockPull = qemuDomainBlockPull, /* 0.9.4 */ + .domainManagedCoreDump = qemuDomainManagedCoreDump, /* 0.9.8 */ + .domainHasManagedCoreDump = qemuDomainHasManagedCoreDump, /* 0.9.8 */ + .domainManagedCoreDumpRemove = qemuDomainManagedCoreDumpRemove, /* 0.9.8 */ + .domainManagedCoreDumpDownload = qemuDomainManagedCoreDumpDownload, /* 0.9.8 */ }; -- 1.7.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list