提交 ab600621 编写于 作者: J John Ferlan

Add capability to fetch balloon stats

This patch will add the qemuMonitorJSONGetMemoryStats() to execute a
"guest-stats" on the balloonpath using "get-qom" replacing the former
mechanism which looked through the "query-ballon" returned data for
the fields.  The "query-balloon" code only returns 'actual' memory.
Rather than duplicating the existing code, have the JSON API use the
GetBalloonInfo API.

A check in the qemuMonitorGetMemoryStats() will be made to ensure the
balloon driver path has been set.  Since the underlying JSON code can
return data not associated with the balloon driver, we don't fail on
a failure to get the balloonpath.  Of course since we've made the check,
we can then set the ballooninit flag.  Getting the path here is primarily
due to the process reconnect path which doesn't attempt to set the
collection period.
上级 ffdf82a9
......@@ -1491,10 +1491,14 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
return -1;
}
if (mon->json)
ret = qemuMonitorJSONGetMemoryStats(mon, stats, nr_stats);
else
if (mon->json) {
ignore_value(qemuMonitorFindBalloonObjectPath(mon, mon->vm, "/"));
mon->ballooninit = true;
ret = qemuMonitorJSONGetMemoryStats(mon, mon->balloonpath,
stats, nr_stats);
} else {
ret = qemuMonitorTextGetMemoryStats(mon, stats, nr_stats);
}
return ret;
}
......
......@@ -1361,131 +1361,115 @@ cleanup:
}
/* Process the balloon driver statistics. The request and data returned
* will be as follows (although the 'child[#]' entry will differ based on
* where it's run).
*
* { "execute": "qom-get","arguments": \
* { "path": "/machine/i440fx/pci.0/child[7]","property": "guest-stats"} }
*
* {"return": {"stats": \
* {"stat-swap-out": 0,
* "stat-free-memory": 686350336,
* "stat-minor-faults": 697283,
* "stat-major-faults": 951,
* "stat-total-memory": 1019924480,
* "stat-swap-in": 0},
* "last-update": 1371221540}}
*
* A value in "stats" can be -1 indicating it's never been collected/stored.
* The 'last-update' value could be used in the future in order to determine
* rates and/or whether data has been collected since a previous cycle.
* It's currently unused.
*/
#define GET_BALLOON_STATS(FIELD, TAG, DIVISOR) \
if (virJSONValueObjectHasKey(statsdata, FIELD) && \
(got < nr_stats)) { \
if (virJSONValueObjectGetNumberUlong(statsdata, FIELD, &mem) < 0) { \
VIR_DEBUG("Failed to get '%s' value", FIELD); \
} else { \
/* Not being collected? No point in providing bad data */ \
if (mem != -1UL) { \
stats[got].tag = TAG; \
stats[got].val = mem / DIVISOR; \
got++; \
} \
} \
}
int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
char *balloonpath,
virDomainMemoryStatPtr stats,
unsigned int nr_stats)
{
int ret;
int got = 0;
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-balloon",
NULL);
virJSONValuePtr cmd = NULL;
virJSONValuePtr reply = NULL;
virJSONValuePtr data;
virJSONValuePtr statsdata;
unsigned long long mem;
int got = 0;
if (!cmd)
return -1;
ret = qemuMonitorJSONGetBalloonInfo(mon, &mem);
if (ret == 1 && (got < nr_stats)) {
stats[got].tag = VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON;
stats[got].val = mem;
got++;
}
ret = qemuMonitorJSONCommand(mon, cmd, &reply);
if (!balloonpath)
goto cleanup;
if (ret == 0) {
/* See if balloon soft-failed */
if (qemuMonitorJSONHasError(reply, "DeviceNotActive") ||
qemuMonitorJSONHasError(reply, "KVMMissingCap"))
goto cleanup;
if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
"s:path", balloonpath,
"s:property", "guest-stats",
NULL)))
goto cleanup;
/* See if any other fatal error occurred */
ret = qemuMonitorJSONCheckError(cmd, reply);
ret = qemuMonitorJSONCommand(mon, cmd, &reply);
/* Success */
if (ret == 0) {
virJSONValuePtr data;
unsigned long long mem;
if (ret == 0)
ret = qemuMonitorJSONCheckError(cmd, reply);
if (!(data = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("info balloon reply was missing return data"));
ret = -1;
goto cleanup;
}
if (ret < 0)
goto cleanup;
if (virJSONValueObjectHasKey(data, "actual") && (got < nr_stats)) {
if (virJSONValueObjectGetNumberUlong(data, "actual", &mem) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("info balloon reply was missing balloon actual"));
ret = -1;
goto cleanup;
}
stats[got].tag = VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON;
stats[got].val = (mem/1024);
got++;
}
if (!(data = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("qom-get reply was missing return data"));
goto cleanup;
}
if (virJSONValueObjectHasKey(data, "mem_swapped_in") && (got < nr_stats)) {
if (virJSONValueObjectGetNumberUlong(data, "mem_swapped_in", &mem) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("info balloon reply was missing balloon mem_swapped_in"));
ret = -1;
goto cleanup;
}
stats[got].tag = VIR_DOMAIN_MEMORY_STAT_SWAP_IN;
stats[got].val = (mem/1024);
got++;
}
if (virJSONValueObjectHasKey(data, "mem_swapped_out") && (got < nr_stats)) {
if (virJSONValueObjectGetNumberUlong(data, "mem_swapped_out", &mem) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("info balloon reply was missing balloon mem_swapped_out"));
ret = -1;
goto cleanup;
}
stats[got].tag = VIR_DOMAIN_MEMORY_STAT_SWAP_OUT;
stats[got].val = (mem/1024);
got++;
}
if (virJSONValueObjectHasKey(data, "major_page_faults") && (got < nr_stats)) {
if (virJSONValueObjectGetNumberUlong(data, "major_page_faults", &mem) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("info balloon reply was missing balloon major_page_faults"));
ret = -1;
goto cleanup;
}
stats[got].tag = VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT;
stats[got].val = mem;
got++;
}
if (virJSONValueObjectHasKey(data, "minor_page_faults") && (got < nr_stats)) {
if (virJSONValueObjectGetNumberUlong(data, "minor_page_faults", &mem) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("info balloon reply was missing balloon minor_page_faults"));
ret = -1;
goto cleanup;
}
stats[got].tag = VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT;
stats[got].val = mem;
got++;
}
if (virJSONValueObjectHasKey(data, "free_mem") && (got < nr_stats)) {
if (virJSONValueObjectGetNumberUlong(data, "free_mem", &mem) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("info balloon reply was missing balloon free_mem"));
ret = -1;
goto cleanup;
}
stats[got].tag = VIR_DOMAIN_MEMORY_STAT_UNUSED;
stats[got].val = (mem/1024);
got++;
}
if (virJSONValueObjectHasKey(data, "total_mem") && (got < nr_stats)) {
if (virJSONValueObjectGetNumberUlong(data, "total_mem", &mem) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("info balloon reply was missing balloon total_mem"));
ret = -1;
goto cleanup;
}
stats[got].tag = VIR_DOMAIN_MEMORY_STAT_AVAILABLE;
stats[got].val = (mem/1024);
got++;
}
}
if (!(statsdata = virJSONValueObjectGet(data, "stats"))) {
VIR_DEBUG("data does not include 'stats'");
goto cleanup;
}
if (got > 0)
ret = got;
GET_BALLOON_STATS("stat-swap-in",
VIR_DOMAIN_MEMORY_STAT_SWAP_IN, 1024);
GET_BALLOON_STATS("stat-swap-out",
VIR_DOMAIN_MEMORY_STAT_SWAP_OUT, 1024);
GET_BALLOON_STATS("stat-major-faults",
VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT, 1);
GET_BALLOON_STATS("stat-minor-faults",
VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT, 1);
GET_BALLOON_STATS("stat-free-memory",
VIR_DOMAIN_MEMORY_STAT_UNUSED, 1024);
GET_BALLOON_STATS("stat-total-memory",
VIR_DOMAIN_MEMORY_STAT_AVAILABLE, 1024);
cleanup:
virJSONValueFree(cmd);
virJSONValueFree(reply);
if (got > 0)
ret = got;
return ret;
}
#undef GET_BALLOON_STATS
/*
......
......@@ -59,6 +59,7 @@ int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon,
int qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
unsigned long long *currmem);
int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
char *balloonpath,
virDomainMemoryStatPtr stats,
unsigned int nr_stats);
int qemuMonitorJSONSetMemoryStatsPeriod(qemuMonitorPtr mon,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册