From patchwork Thu Nov 11 01:37:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 70746 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 757E5B7117 for ; Thu, 11 Nov 2010 12:47:23 +1100 (EST) Received: from localhost ([127.0.0.1]:37359 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PGMFq-0005GI-Ay for incoming@patchwork.ozlabs.org; Wed, 10 Nov 2010 20:47:10 -0500 Received: from [140.186.70.92] (port=56526 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PGM7E-0007jt-9d for qemu-devel@nongnu.org; Wed, 10 Nov 2010 20:39:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PGM6q-0008Uu-Rr for qemu-devel@nongnu.org; Wed, 10 Nov 2010 20:38:14 -0500 Received: from e3.ny.us.ibm.com ([32.97.182.143]:41589) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PGM6q-0008UN-NS for qemu-devel@nongnu.org; Wed, 10 Nov 2010 20:37:52 -0500 Received: from d01relay01.pok.ibm.com (d01relay01.pok.ibm.com [9.56.227.233]) by e3.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id oAB1KXOp001894 for ; Wed, 10 Nov 2010 20:20:33 -0500 Received: from d01av01.pok.ibm.com (d01av01.pok.ibm.com [9.56.224.215]) by d01relay01.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id oAB1bqXm349202 for ; Wed, 10 Nov 2010 20:37:52 -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 oAB1bpdg010414 for ; Wed, 10 Nov 2010 20:37:52 -0500 Received: from localhost.localdomain (sig-9-65-242-217.mts.ibm.com [9.65.242.217]) by d01av01.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id oAB1bY19009666; Wed, 10 Nov 2010 20:37:51 -0500 From: Michael Roth To: qemu-devel@nongnu.org Date: Wed, 10 Nov 2010 19:37:25 -0600 Message-Id: <1289439450-23556-7-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1289439450-23556-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1289439450-23556-1-git-send-email-mdroth@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: agl@linux.vnet.ibm.com, abeekhof@redhat.com, mdroth@linux.vnet.ibm.com, aliguori@linux.vnet.ibm.com, ryanh@us.ibm.com, amit.shah@redhat.com Subject: [Qemu-devel] [RFC][PATCH v3 06/11] virtagent: add agent_viewfile 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 potentially confusing "viewfile" as opposed to "getfile". Signed-off-by: Michael Roth --- hmp-commands.hx | 16 +++++++++ qmp-commands.hx | 33 ++++++++++++++++++ virtagent.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ virtagent.h | 3 ++ 4 files changed, 152 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/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 cfd279f..2e496f9 100644 --- a/virtagent.c +++ b/virtagent.c @@ -143,3 +143,103 @@ out_callxml: out: return ret; } + +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(void *opaque) +{ + VARPCData *rpc_data = opaque; + xmlrpc_value *resp = NULL; + char *file_contents = NULL; + size_t file_size; + int ret; + xmlrpc_env env; + QDict *qdict = qdict_new(); + + if (rpc_data->status != VA_RPC_STATUS_OK) { + LOG("error handling RPC request"); + goto out_no_resp; + } + + xmlrpc_env_init(&env); + resp = xmlrpc_parse_response(&env, rpc_data->resp_xml, + rpc_data->resp_xml_len); + if (rpc_has_error(&env)) { + ret = -1; + goto out_no_resp; + } + + xmlrpc_parse_value(&env, resp, "6", &file_contents, &file_size); + if (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: + rpc_data->mon_cb(rpc_data->mon_data, 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; + VARPCData *rpc_data; + const char *filepath; + int ret; + + filepath = qdict_get_str(mon_params, "filepath"); + xmlrpc_env_init(&env); + params = xmlrpc_build_value(&env, "(s)", filepath); + if (rpc_has_error(&env)) { + return -1; + } + + rpc_data = qemu_mallocz(sizeof(VARPCData)); + rpc_data->cb = do_agent_viewfile_cb; + rpc_data->mon_cb = cb; + rpc_data->mon_data = opaque; + + ret = rpc_execute(&env, "getfile", params, rpc_data); + if (ret == -EREMOTE) { + monitor_printf(mon, "RPC Failed (%i): %s\n", env.fault_code, + env.fault_string); + return -1; + } else if (ret == -1) { + monitor_printf(mon, "RPC communication error\n"); + return -1; + } + + return 0; +} diff --git a/virtagent.h b/virtagent.h index 53efa29..63d77c2 100644 --- a/virtagent.h +++ b/virtagent.h @@ -23,5 +23,8 @@ #define VA_MAX_CHUNK_SIZE 4096 /* max bytes at a time for get/send file */ int va_client_init(VPDriver *vp_drv, bool is_host); +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 */