* 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(a)linux.vnet.ibm.com>
---
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