From patchwork Fri Dec 3 18:03:09 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 74175 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id DBB8E1007D6 for ; Sat, 4 Dec 2010 05:08:15 +1100 (EST) Received: from localhost ([127.0.0.1]:51674 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1POa3H-0002sR-UK for incoming@patchwork.ozlabs.org; Fri, 03 Dec 2010 13:08:12 -0500 Received: from [140.186.70.92] (port=44504 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1POZzJ-00023c-MQ for qemu-devel@nongnu.org; Fri, 03 Dec 2010 13:04:07 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1POZzF-0003Dv-Vk for qemu-devel@nongnu.org; Fri, 03 Dec 2010 13:04:05 -0500 Received: from e1.ny.us.ibm.com ([32.97.182.141]:36018) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1POZzF-0003Dn-SM for qemu-devel@nongnu.org; Fri, 03 Dec 2010 13:04:01 -0500 Received: from d01dlp01.pok.ibm.com (d01dlp01.pok.ibm.com [9.56.224.56]) by e1.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id oB3HtvUB014979 for ; Fri, 3 Dec 2010 12:55:58 -0500 Received: from d01relay07.pok.ibm.com (d01relay07.pok.ibm.com [9.56.227.147]) by d01dlp01.pok.ibm.com (Postfix) with ESMTP id 40675728042 for ; Fri, 3 Dec 2010 13:04:01 -0500 (EST) Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by d01relay07.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id oB3I3wwx2232464 for ; Fri, 3 Dec 2010 13:03:59 -0500 Received: from d01av01.pok.ibm.com (loopback [127.0.0.1]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id oB3I3vZ8013496 for ; Fri, 3 Dec 2010 13:03:58 -0500 Received: from localhost.localdomain (sig-9-65-101-53.mts.ibm.com [9.65.101.53]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id oB3I3S9f011647; Fri, 3 Dec 2010 13:03:56 -0500 From: Michael Roth To: qemu-devel@nongnu.org Date: Fri, 3 Dec 2010 12:03:09 -0600 Message-Id: <1291399402-20366-9-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1291399402-20366-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1291399402-20366-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Content-Scanned: Fidelis XPS MAILER X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: agl@linux.vnet.ibm.com, stefanha@linux.vnet.ibm.com, Jes.Sorensen@redhat.com, mdroth@linux.vnet.ibm.com, aliguori@linux.vnet.ibm.com, ryanh@us.ibm.com, abeekhof@redhat.com Subject: [Qemu-devel] [RFC][PATCH v5 08/21] virtagent: add agent_viewfile qmp/hmp command X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 e5585ba..423c752 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1212,6 +1212,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 8cee35d..145895d 100644 --- a/monitor.c +++ b/monitor.c @@ -56,6 +56,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 793cf1c..efa2137 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -738,6 +738,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 34d8545..4a4dc8a 100644 --- a/virtagent.c +++ b/virtagent.c @@ -139,3 +139,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 af36b6a..5960616 100644 --- a/virtagent.h +++ b/virtagent.h @@ -28,5 +28,8 @@ typedef struct VAClientData { } VAClientData; int va_client_init(VAClientData *client_data); +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 */