From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=32815 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PeowV-0006xP-2f for qemu-devel@nongnu.org; Mon, 17 Jan 2011 08:16:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PeowS-0006FI-6N for qemu-devel@nongnu.org; Mon, 17 Jan 2011 08:16:18 -0500 Received: from e6.ny.us.ibm.com ([32.97.182.146]:51973) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PeowS-0006FC-3I for qemu-devel@nongnu.org; Mon, 17 Jan 2011 08:16:16 -0500 Received: from d01dlp01.pok.ibm.com (d01dlp01.pok.ibm.com [9.56.224.56]) by e6.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p0HD1cRn000681 for ; Mon, 17 Jan 2011 08:01:46 -0500 Received: from d01relay01.pok.ibm.com (d01relay01.pok.ibm.com [9.56.227.233]) by d01dlp01.pok.ibm.com (Postfix) with ESMTP id 6C51A728051 for ; Mon, 17 Jan 2011 08:16:15 -0500 (EST) Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by d01relay01.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p0HDGFSn397694 for ; Mon, 17 Jan 2011 08:16:15 -0500 Received: from d01av04.pok.ibm.com (loopback [127.0.0.1]) by d01av04.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p0HDGEtL030573 for ; Mon, 17 Jan 2011 08:16:14 -0500 From: Michael Roth Date: Mon, 17 Jan 2011 07:15:03 -0600 Message-Id: <1295270117-24760-10-git-send-email-mdroth@linux.vnet.ibm.com> In-Reply-To: <1295270117-24760-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1295270117-24760-1-git-send-email-mdroth@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC][PATCH v6 09/23] virtagent: add agent_viewfile qmp/hmp command List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: agl@linux.vnet.ibm.com, stefanha@linux.vnet.ibm.com, Jes.Sorensen@redhat.com, marcel.mittelstaedt@de.ibm.com, mdroth@linux.vnet.ibm.com, markus_mueller@de.ibm.com, aliguori@linux.vnet.ibm.com, ryanh@us.ibm.com, abeekhof@redhat.com Utilize the getfile RPC to provide a means to view text files in the guest. Getfile can handle binary files as well but we don't advertise that here due to the special handling requiring to store it and provide it back to the user (base64 encoding it for instance). Hence the otherwise confusing "viewfile" as opposed to "getfile". Signed-off-by: Michael Roth --- hmp-commands.hx | 16 +++++++++ monitor.c | 1 + qmp-commands.hx | 33 +++++++++++++++++++ virtagent.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ virtagent.h | 3 ++ 5 files changed, 149 insertions(+), 0 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 1cea572..a3e5e27 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1328,6 +1328,22 @@ show available trace events and their state ETEXI #endif + { + .name = "agent_viewfile", + .args_type = "filepath:s", + .params = "filepath", + .help = "Echo a file from the guest filesystem", + .user_print = do_agent_viewfile_print, + .mhandler.cmd_async = do_agent_viewfile, + .flags = MONITOR_CMD_ASYNC, + }, + +STEXI +@item agent_viewfile @var{filepath} +@findex agent_viewfile +Echo the file identified by @var{filepath} on the guest filesystem +ETEXI + STEXI @end table ETEXI diff --git a/monitor.c b/monitor.c index f258000..cd015aa 100644 --- a/monitor.c +++ b/monitor.c @@ -57,6 +57,7 @@ #include "json-parser.h" #include "osdep.h" #include "exec-all.h" +#include "virtagent.h" #ifdef CONFIG_SIMPLE_TRACE #include "trace.h" #endif diff --git a/qmp-commands.hx b/qmp-commands.hx index 56c4d8b..9dca7b9 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -795,6 +795,39 @@ Example: EQMP { + .name = "agent_viewfile", + .args_type = "filepath:s", + .params = "filepath", + .help = "Echo a file from the guest filesystem", + .user_print = monitor_user_noop, + .mhandler.cmd_async = do_agent_viewfile, + .flags = MONITOR_CMD_ASYNC, + }, + +STEXI +@item agent_viewfile @var{filepath} +@findex agent_viewfile +Echo the file identified by @var{filepath} on the guest filesystem +ETEXI +SQMP +agent_viewfile +-------- + +Echo the file identified by @var{filepath} from the guest filesystem. + +Arguments: + +- "filepath": Full guest path of the desired file + +Example: + +-> { "execute": "agent_viewfile", + "arguments": { "filepath": "/sys/kernel/kexec_loaded" } } +<- { "return": { "contents": "0" } } + +EQMP + + { .name = "qmp_capabilities", .args_type = "", .params = "", diff --git a/virtagent.c b/virtagent.c index 00eccb5..cd5caf1 100644 --- a/virtagent.c +++ b/virtagent.c @@ -156,3 +156,99 @@ out_free: out: return ret; } + +/* QMP/HMP RPC client functions */ + +void do_agent_viewfile_print(Monitor *mon, const QObject *data) +{ + QDict *qdict; + const char *contents = NULL; + int i; + + qdict = qobject_to_qdict(data); + if (!qdict_haskey(qdict, "contents")) { + return; + } + + contents = qdict_get_str(qdict, "contents"); + if (contents != NULL) { + /* monitor_printf truncates so do it in chunks. also, file_contents + * may not be null-termed at proper location so explicitly calc + * last chunk sizes */ + for (i = 0; i < strlen(contents); i += 1024) { + monitor_printf(mon, "%.1024s", contents + i); + } + } + monitor_printf(mon, "\n"); +} + +static void do_agent_viewfile_cb(const char *resp_data, + size_t resp_data_len, + MonitorCompletion *mon_cb, + void *mon_data) +{ + xmlrpc_value *resp = NULL; + char *file_contents = NULL; + size_t file_size; + int ret; + xmlrpc_env env; + QDict *qdict = qdict_new(); + + if (resp_data == NULL) { + LOG("error handling RPC request"); + goto out_no_resp; + } + + xmlrpc_env_init(&env); + resp = xmlrpc_parse_response(&env, resp_data, resp_data_len); + if (va_rpc_has_error(&env)) { + ret = -1; + goto out_no_resp; + } + + xmlrpc_parse_value(&env, resp, "6", &file_contents, &file_size); + if (va_rpc_has_error(&env)) { + ret = -1; + goto out; + } + + if (file_contents != NULL) { + qdict_put(qdict, "contents", + qstring_from_substr(file_contents, 0, file_size-1)); + } + +out: + xmlrpc_DECREF(resp); +out_no_resp: + if (mon_cb) { + mon_cb(mon_data, QOBJECT(qdict)); + } + qobject_decref(QOBJECT(qdict)); +} + +/* + * do_agent_viewfile(): View a text file in the guest + */ +int do_agent_viewfile(Monitor *mon, const QDict *mon_params, + MonitorCompletion cb, void *opaque) +{ + xmlrpc_env env; + xmlrpc_value *params; + const char *filepath; + int ret; + + filepath = qdict_get_str(mon_params, "filepath"); + xmlrpc_env_init(&env); + params = xmlrpc_build_value(&env, "(s)", filepath); + if (va_rpc_has_error(&env)) { + return -1; + } + + ret = va_do_rpc(&env, "va.getfile", params, do_agent_viewfile_cb, cb, + opaque); + if (ret) { + qerror_report(QERR_VA_FAILED, ret, strerror(ret)); + } + xmlrpc_DECREF(params); + return ret; +} diff --git a/virtagent.h b/virtagent.h index 3e4d4fb..1bd7595 100644 --- a/virtagent.h +++ b/virtagent.h @@ -30,5 +30,8 @@ typedef struct VAClientData { int va_client_init(VAClientData *client_data); int va_client_close(void); +void do_agent_viewfile_print(Monitor *mon, const QObject *qobject); +int do_agent_viewfile(Monitor *mon, const QDict *mon_params, + MonitorCompletion cb, void *opaque); #endif /* VIRTAGENT_H */ -- 1.7.0.4