qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: aliguori@linux.vnet.ibm.com, ryanh@us.ibm.com,
	agl@linux.vnet.ibm.com, mdroth@linux.vnet.ibm.com,
	abeekhof@redhat.com
Subject: [Qemu-devel] [RFC][PATCH 06/10] virtagent: add agent_viewfile command
Date: Fri, 22 Oct 2010 13:46:01 -0500	[thread overview]
Message-ID: <1287773165-24855-7-git-send-email-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <1287773165-24855-1-git-send-email-mdroth@linux.vnet.ibm.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
potentially confusing "viewfile" as opposed to "getfile".

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 hmp-commands.hx |   16 +++++++++
 qmp-commands.hx |   33 ++++++++++++++++++
 virtagent.c     |  102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 virtagent.h     |    4 ++
 4 files changed, 155 insertions(+), 0 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 81999aa..e9a7f4a 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1211,6 +1211,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 2234bef..8059d00 100644
--- a/virtagent.c
+++ b/virtagent.c
@@ -94,3 +94,105 @@ 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)
+{
+    RPCRequest *rpc_data = opaque;
+    xmlrpc_value *resp = NULL;
+    char *file_contents = NULL;
+    int file_size, ret;
+    xmlrpc_env env;
+    QDict *qdict = qdict_new();
+
+    if (rpc_data->resp_xml == NULL) {
+        monitor_printf(rpc_data->mon, "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:
+    qemu_free(rpc_data->resp_xml);
+    xmlrpc_DECREF(resp);
+out_no_resp:
+    rpc_data->mon_cb(rpc_data->mon_data, QOBJECT(qdict));
+    qemu_free(rpc_data);
+}
+
+/*
+ * 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;
+    RPCRequest *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(RPCRequest));
+    rpc_data->cb = do_agent_viewfile_cb;
+    rpc_data->mon = mon;
+    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 abdb32a..d027eac 100644
--- a/virtagent.h
+++ b/virtagent.h
@@ -22,4 +22,8 @@
 #define HOST_AGENT_PATH_CLIENT "/tmp/virtagent-host-client.sock"
 #define VA_MAX_CHUNK_SIZE 4096 /* max bytes at a time for get/send file */
 
+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

  parent reply	other threads:[~2010-10-22 18:46 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-22 18:45 [Qemu-devel] [RFC][PATCH 00/10] virtagent: host/guest RPC communication agent Michael Roth
2010-10-22 18:45 ` [Qemu-devel] [RFC][PATCH 01/10] virtagent: add common rpc transport defs Michael Roth
2010-10-25 21:39   ` Anthony Liguori
2010-10-25 21:54     ` malc
2010-10-25 22:02       ` Anthony Liguori
2010-10-25 22:32         ` malc
2010-10-22 18:45 ` [Qemu-devel] [RFC][PATCH 02/10] virtagent: base definitions for host/guest RPC daemon Michael Roth
2010-10-22 18:45 ` [Qemu-devel] [RFC][PATCH 03/10] virtagent: qemu-vp, integrate virtagent daemon Michael Roth
2010-10-22 18:45 ` [Qemu-devel] [RFC][PATCH 04/10] virtagent: base RPC client definitions Michael Roth
2010-10-22 18:46 ` [Qemu-devel] [RFC][PATCH 05/10] virtagent: add getfile RPC Michael Roth
2010-10-22 18:46 ` Michael Roth [this message]
2010-10-22 18:46 ` [Qemu-devel] [RFC][PATCH 07/10] virtagent: add getdmesg RPC Michael Roth
2010-10-25 21:42   ` Anthony Liguori
2010-10-22 18:46 ` [Qemu-devel] [RFC][PATCH 08/10] virtagent: add agent_viewdmesg command Michael Roth
2010-10-22 18:46 ` [Qemu-devel] [RFC][PATCH 09/10] virtagent: Makefile/configure changes to build virtagent bits Michael Roth
2010-10-22 18:46 ` [Qemu-devel] [RFC][PATCH 10/10] virtproxy: add compat defs for linking against vl.c Michael Roth
2010-10-23 11:31 ` [Qemu-devel] Re: [RFC][PATCH 00/10] virtagent: host/guest RPC communication agent Andrew Beekhof
2010-10-23 14:41   ` Michael Roth
2010-10-25  9:46     ` Andrew Beekhof
2010-10-25 10:30 ` Andrew Beekhof
2010-10-25 17:06   ` Michael Roth
2010-10-26  7:14     ` Andrew Beekhof
2010-10-25 21:28   ` Anthony Liguori
2010-10-26  7:27     ` Andrew Beekhof

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1287773165-24855-7-git-send-email-mdroth@linux.vnet.ibm.com \
    --to=mdroth@linux.vnet.ibm.com \
    --cc=abeekhof@redhat.com \
    --cc=agl@linux.vnet.ibm.com \
    --cc=aliguori@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=ryanh@us.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).