All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough
@ 2010-11-16 19:19 Luiz Capitulino
  2010-11-16 19:19 ` [Qemu-devel] [PATCH 1/3] qemu-char: Introduce Memory driver Luiz Capitulino
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Luiz Capitulino @ 2010-11-16 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, armbru, avi

Simple example:

-> { "execute": "human-monitor-command", "arguments": { "command-line": "print /i 10+25" } }
<- { "return": "35\r\n" }

Please, check individual patches for details. Also note that this series
depends on the script improvements one.

Also, Markus suggestion of having an assert() in qemu_chr_close() have not
been added this series because I don't know what to assert(). But that's an
incremental change anyway and should prevent this series from being merged.

changelog
---------

v3 -> v4

- Simplify qemu_chr_mem_to_qs() (as per Markus review)
- Fix qmp-shell not to cache bad CPU index values

v2 -> v3

- Renamed command name to human-monitor-command
- Fixed buggy error reporting when cpu-index is invalid
- Make qemu_chr_mem_to_qs() return a string when outbuf is empty
- Introduced qemu_chr_mem_osize() along with some cleanups

v1 -> v2

- A number of small cleanups and clarifications

Thanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 1/3] qemu-char: Introduce Memory driver
  2010-11-16 19:19 [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
@ 2010-11-16 19:19 ` Luiz Capitulino
  2010-11-16 19:19 ` [Qemu-devel] [PATCH 2/3] QMP: Introduce Human Monitor passthrough command Luiz Capitulino
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Luiz Capitulino @ 2010-11-16 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, armbru, avi

This driver handles in-memory chardev operations. That's, all writes
to this driver are stored in an internal buffer and it doesn't talk
to the external world in any way.

Right now it's very simple: it supports only writes. But it can be
easily extended to support more operations.

This is going to be used by the monitor's "HMP passthrough via QMP"
feature, which needs to run monitor handlers without a backing
device.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qemu-char.c |   64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-char.h |    7 ++++++
 2 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 88997f9..edc9ad6 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2275,6 +2275,70 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     return NULL;
 }
 
+/***********************************************************/
+/* Memory chardev */
+typedef struct {
+    size_t outbuf_size;
+    size_t outbuf_capacity;
+    uint8_t *outbuf;
+} MemoryDriver;
+
+static int mem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    MemoryDriver *d = chr->opaque;
+
+    /* TODO: the QString implementation has the same code, we should
+     * introduce a generic way to do this in cutils.c */
+    if (d->outbuf_capacity < d->outbuf_size + len) {
+        /* grow outbuf */
+        d->outbuf_capacity += len;
+        d->outbuf_capacity *= 2;
+        d->outbuf = qemu_realloc(d->outbuf, d->outbuf_capacity);
+    }
+
+    memcpy(d->outbuf + d->outbuf_size, buf, len);
+    d->outbuf_size += len;
+
+    return len;
+}
+
+void qemu_chr_init_mem(CharDriverState *chr)
+{
+    MemoryDriver *d;
+
+    d = qemu_malloc(sizeof(*d));
+    d->outbuf_size = 0;
+    d->outbuf_capacity = 4096;
+    d->outbuf = qemu_mallocz(d->outbuf_capacity);
+
+    memset(chr, 0, sizeof(*chr));
+    chr->opaque = d;
+    chr->chr_write = mem_chr_write;
+}
+
+QString *qemu_chr_mem_to_qs(CharDriverState *chr)
+{
+    MemoryDriver *d = chr->opaque;
+    return qstring_from_substr((char *) d->outbuf, 0, d->outbuf_size - 1);
+}
+
+/* NOTE: this driver can not be closed with qemu_chr_close()! */
+void qemu_chr_close_mem(CharDriverState *chr)
+{
+    MemoryDriver *d = chr->opaque;
+
+    qemu_free(d->outbuf);
+    qemu_free(chr->opaque);
+    chr->opaque = NULL;
+    chr->chr_write = NULL;
+}
+
+size_t qemu_chr_mem_osize(const CharDriverState *chr)
+{
+    const MemoryDriver *d = chr->opaque;
+    return d->outbuf_size;
+}
+
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
 {
     char host[65], port[33], width[8], height[8];
diff --git a/qemu-char.h b/qemu-char.h
index 18ad12b..e6ee6c4 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -6,6 +6,7 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "qobject.h"
+#include "qstring.h"
 
 /* character device */
 
@@ -100,6 +101,12 @@ CharDriverState *qemu_chr_open_eventfd(int eventfd);
 
 extern int term_escape_char;
 
+/* memory chardev */
+void qemu_chr_init_mem(CharDriverState *chr);
+void qemu_chr_close_mem(CharDriverState *chr);
+QString *qemu_chr_mem_to_qs(CharDriverState *chr);
+size_t qemu_chr_mem_osize(const CharDriverState *chr);
+
 /* async I/O support */
 
 int qemu_set_fd_handler2(int fd,
-- 
1.7.3.2.168.gd6b63

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 2/3] QMP: Introduce Human Monitor passthrough command
  2010-11-16 19:19 [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
  2010-11-16 19:19 ` [Qemu-devel] [PATCH 1/3] qemu-char: Introduce Memory driver Luiz Capitulino
@ 2010-11-16 19:19 ` Luiz Capitulino
  2010-11-16 19:19 ` [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode Luiz Capitulino
  2010-11-17 10:27 ` [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Markus Armbruster
  3 siblings, 0 replies; 10+ messages in thread
From: Luiz Capitulino @ 2010-11-16 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, armbru, avi

This command allows QMP clients to execute HMP commands.

Please, check the documentation added to the qmp-commands.hx file
for additional details about the interface and its limitations.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 monitor.c       |   38 ++++++++++++++++++++++++++++++++++++++
 qmp-commands.hx |   45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/monitor.c b/monitor.c
index 8cee35d..ec31eac 100644
--- a/monitor.c
+++ b/monitor.c
@@ -491,6 +491,44 @@ static int do_qmp_capabilities(Monitor *mon, const QDict *params,
     return 0;
 }
 
+static int mon_set_cpu(int cpu_index);
+static void handle_user_command(Monitor *mon, const char *cmdline);
+
+static int do_hmp_passthrough(Monitor *mon, const QDict *params,
+                              QObject **ret_data)
+{
+    int ret = 0;
+    Monitor *old_mon, hmp;
+    CharDriverState mchar;
+
+    memset(&hmp, 0, sizeof(hmp));
+    qemu_chr_init_mem(&mchar);
+    hmp.chr = &mchar;
+
+    old_mon = cur_mon;
+    cur_mon = &hmp;
+
+    if (qdict_haskey(params, "cpu-index")) {
+        ret = mon_set_cpu(qdict_get_int(params, "cpu-index"));
+        if (ret < 0) {
+            cur_mon = old_mon;
+            qerror_report(QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number");
+            goto out;
+        }
+    }
+
+    handle_user_command(&hmp, qdict_get_str(params, "command-line"));
+    cur_mon = old_mon;
+
+    if (qemu_chr_mem_osize(hmp.chr) > 0) {
+        *ret_data = QOBJECT(qemu_chr_mem_to_qs(hmp.chr));
+    }
+
+out:
+    qemu_chr_close_mem(hmp.chr);
+    return ret;
+}
+
 static int compare_cmd(const char *name, const char *list)
 {
     const char *p, *pstart;
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 793cf1c..e5f157f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -761,6 +761,51 @@ Example:
 
 Note: This command must be issued before issuing any other command.
 
+EQMP
+
+    {
+        .name       = "human-monitor-command",
+        .args_type  = "command-line:s,cpu-index:i?",
+        .params     = "",
+        .help       = "",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_hmp_passthrough,
+    },
+
+SQMP
+human-monitor-command
+---------------------
+
+Execute a Human Monitor command.
+
+Arguments: 
+
+- command-line: the command name and its arguments, just like the
+                Human Monitor's shell (json-string)
+- cpu-index: select the CPU number to be used by commands which access CPU
+             data, like 'info registers'. The Monitor selects CPU 0 if this
+             argument is not provided (json-int, optional)
+
+Example:
+
+-> { "execute": "human-monitor-command", "arguments": { "command-line": "info kvm" } }
+<- { "return": "kvm support: enabled\r\n" }
+
+Notes:
+
+(1) The Human Monitor is NOT an stable interface, this means that command
+    names, arguments and responses can change or be removed at ANY time.
+    Applications that rely on long term stability guarantees should NOT
+    use this command
+
+(2) Limitations:
+
+    o This command is stateless, this means that commands that depend
+      on state information (such as getfd) might not work
+
+    o Commands that prompt the user for data (eg. 'cont' when the block
+      device is encrypted) don't currently work
+
 3. Query Commands
 =================
 
-- 
1.7.3.2.168.gd6b63

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode
  2010-11-16 19:19 [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
  2010-11-16 19:19 ` [Qemu-devel] [PATCH 1/3] qemu-char: Introduce Memory driver Luiz Capitulino
  2010-11-16 19:19 ` [Qemu-devel] [PATCH 2/3] QMP: Introduce Human Monitor passthrough command Luiz Capitulino
@ 2010-11-16 19:19 ` Luiz Capitulino
  2010-11-17 10:27 ` [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Markus Armbruster
  3 siblings, 0 replies; 10+ messages in thread
From: Luiz Capitulino @ 2010-11-16 19:19 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, armbru, avi

In which qmp-shell will exclusively use the HMP passthrough feature,
this is useful for testing.

Example:

    # ./qmp-shell -H qmp-sock
    Welcome to the HMP shell!
    Connected to QEMU 0.13.50

    (QEMU) info network
    VLAN 0 devices:
      user.0: net=10.0.2.0, restricted=n
        e1000.0: model=e1000,macaddr=52:54:00:12:34:56
        Devices not on any VLAN:
    (QEMU)

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 QMP/qmp-shell |   79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 78 insertions(+), 1 deletions(-)

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index 1fb7e76..42dabc8 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -145,6 +145,76 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         else:
             return self._execute_cmd(cmdline)
 
+class HMPShell(QMPShell):
+    def __init__(self, address):
+        QMPShell.__init__(self, address)
+        self.__cpu_index = 0
+
+    def __cmd_completion(self):
+        for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
+            if cmd and cmd[0] != '[' and cmd[0] != '\t':
+                name = cmd.split()[0] # drop help text
+                if name == 'info':
+                    continue
+                if name.find('|') != -1:
+                    # Command in the form 'foobar|f' or 'f|foobar', take the
+                    # full name
+                    opt = name.split('|')
+                    if len(opt[0]) == 1:
+                        name = opt[1]
+                    else:
+                        name = opt[0]
+                self._completer.append(name)
+                self._completer.append('help ' + name) # help completion
+
+    def __info_completion(self):
+        for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
+            if cmd:
+                self._completer.append('info ' + cmd.split()[1])
+
+    def __other_completion(self):
+        # special cases
+        self._completer.append('help info')
+
+    def _fill_completion(self):
+        self.__cmd_completion()
+        self.__info_completion()
+        self.__other_completion()
+
+    def __cmd_passthrough(self, cmdline, cpu_index = 0):
+        return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments':
+                              { 'command-line': cmdline,
+                                'cpu-index': cpu_index } })
+
+    def _execute_cmd(self, cmdline):
+        if cmdline.split()[0] == "cpu":
+            # trap the cpu command, it requires special setting
+            try:
+                idx = int(cmdline.split()[1])
+                if not 'return' in self.__cmd_passthrough('info version', idx):
+                    print 'bad CPU index'
+                    return True
+                self.__cpu_index = idx
+            except ValueError:
+                print 'cpu command takes an integer argument'
+                return True
+        resp = self.__cmd_passthrough(cmdline, self.__cpu_index)
+        if resp is None:
+            print 'Disconnected'
+            return False
+        assert 'return' in resp or 'error' in resp
+        if 'return' in resp:
+            # Success
+            if len(resp['return']) > 0:
+                print resp['return'],
+        else:
+            # Error
+            print '%s: %s' % (resp['error']['class'], resp['error']['desc'])
+        return True
+
+    def show_banner(self):
+        QMPShell.show_banner(self, msg='Welcome to the HMP shell!')
+
 def die(msg):
     sys.stderr.write('ERROR: %s\n' % msg)
     sys.exit(1)
@@ -156,9 +226,16 @@ def fail_cmdline(option=None):
     sys.exit(1)
 
 def main():
+    addr = ''
     try:
         if len(sys.argv) == 2:
             qemu = QMPShell(sys.argv[1])
+            addr = sys.argv[1]
+        elif len(sys.argv) == 3:
+            if sys.argv[1] != '-H':
+                fail_cmdline(sys.argv[1])
+            qemu = HMPShell(sys.argv[2])
+            addr = sys.argv[2]
         else:
                 fail_cmdline()
     except QMPShellBadPort:
@@ -171,7 +248,7 @@ def main():
     except qmp.QMPCapabilitiesError:
         die('Could not negotiate capabilities')
     except qemu.error:
-        die('Could not connect to %s' % sys.argv[1])
+        die('Could not connect to %s' % addr)
 
     qemu.show_banner()
     while qemu.read_exec_command('(QEMU) '):
-- 
1.7.3.2.168.gd6b63

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough
  2010-11-16 19:19 [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
                   ` (2 preceding siblings ...)
  2010-11-16 19:19 ` [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode Luiz Capitulino
@ 2010-11-17 10:27 ` Markus Armbruster
  2010-11-17 12:39   ` Luiz Capitulino
  3 siblings, 1 reply; 10+ messages in thread
From: Markus Armbruster @ 2010-11-17 10:27 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: aliguori, qemu-devel, avi

Luiz Capitulino <lcapitulino@redhat.com> writes:

> Simple example:
>
> -> { "execute": "human-monitor-command", "arguments": { "command-line": "print /i 10+25" } }
> <- { "return": "35\r\n" }
>
> Please, check individual patches for details. Also note that this series
> depends on the script improvements one.
>
> Also, Markus suggestion of having an assert() in qemu_chr_close() have not
> been added this series because I don't know what to assert(). But that's an
> incremental change anyway and should prevent this series from being merged.

We talked about it when we discussed v2.  While it shouldn't be hard,
it's not required, and I don't want to delay this series any further.

Same for documenting or fixing qobject_to_json() for embedded '\0'.

ACK series

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough
  2010-11-17 10:27 ` [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Markus Armbruster
@ 2010-11-17 12:39   ` Luiz Capitulino
  0 siblings, 0 replies; 10+ messages in thread
From: Luiz Capitulino @ 2010-11-17 12:39 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: aliguori, qemu-devel, avi

On Wed, 17 Nov 2010 11:27:31 +0100
Markus Armbruster <armbru@redhat.com> wrote:

> Luiz Capitulino <lcapitulino@redhat.com> writes:
> 
> > Simple example:
> >
> > -> { "execute": "human-monitor-command", "arguments": { "command-line": "print /i 10+25" } }
> > <- { "return": "35\r\n" }
> >
> > Please, check individual patches for details. Also note that this series
> > depends on the script improvements one.
> >
> > Also, Markus suggestion of having an assert() in qemu_chr_close() have not
> > been added this series because I don't know what to assert(). But that's an
> > incremental change anyway and should prevent this series from being merged.
> 
> We talked about it when we discussed v2.  While it shouldn't be hard,
> it's not required, and I don't want to delay this series any further.
> 
> Same for documenting or fixing qobject_to_json() for embedded '\0'.
> 
> ACK series

Thanks for reviewing it, Markus.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode
  2010-11-11 19:31 [Qemu-devel] [PATCH v3 " Luiz Capitulino
@ 2010-11-11 19:31 ` Luiz Capitulino
  0 siblings, 0 replies; 10+ messages in thread
From: Luiz Capitulino @ 2010-11-11 19:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, armbru, avi

In which qmp-shell will exclusively use the HMP passthrough feature,
this is useful for testing.

Example:

    # ./qmp-shell -H qmp-sock
    Welcome to the HMP shell!
    Connected to QEMU 0.13.50

    (QEMU) info network
    VLAN 0 devices:
      user.0: net=10.0.2.0, restricted=n
        e1000.0: model=e1000,macaddr=52:54:00:12:34:56
        Devices not on any VLAN:
    (QEMU)

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 QMP/qmp-shell |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 74 insertions(+), 1 deletions(-)

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index 1fb7e76..5135590 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -145,6 +145,72 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         else:
             return self._execute_cmd(cmdline)
 
+class HMPShell(QMPShell):
+    def __init__(self, address):
+        QMPShell.__init__(self, address)
+        self.__cpu_index = 0
+
+    def __cmd_completion(self):
+        for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
+            if cmd and cmd[0] != '[' and cmd[0] != '\t':
+                name = cmd.split()[0] # drop help text
+                if name == 'info':
+                    continue
+                if name.find('|') != -1:
+                    # Command in the form 'foobar|f' or 'f|foobar', take the
+                    # full name
+                    opt = name.split('|')
+                    if len(opt[0]) == 1:
+                        name = opt[1]
+                    else:
+                        name = opt[0]
+                self._completer.append(name)
+                self._completer.append('help ' + name) # help completion
+
+    def __info_completion(self):
+        for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
+            if cmd:
+                self._completer.append('info ' + cmd.split()[1])
+
+    def __other_completion(self):
+        # special cases
+        self._completer.append('help info')
+
+    def _fill_completion(self):
+        self.__cmd_completion()
+        self.__info_completion()
+        self.__other_completion()
+
+    def __cmd_passthrough(self, cmdline):
+        return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments':
+                              { 'command-line': cmdline,
+                                'cpu-index': self.__cpu_index } })
+
+    def _execute_cmd(self, cmdline):
+        if cmdline.split()[0] == "cpu":
+            # trap the cpu command, it requires special setting
+            try:
+                self.__cpu_index = int(cmdline.split()[1])
+            except ValueError:
+                print 'cpu command takes an integer argument'
+                return True
+        resp = self.__cmd_passthrough(cmdline)
+        if resp is None:
+            print 'Disconnected'
+            return False
+        assert 'return' in resp or 'error' in resp
+        if 'return' in resp:
+            # Success
+            if len(resp['return']) > 0:
+                print resp['return'],
+        else:
+            # Error
+            print '%s: %s' % (resp['error']['class'], resp['error']['desc'])
+        return True
+
+    def show_banner(self):
+        QMPShell.show_banner(self, msg='Welcome to the HMP shell!')
+
 def die(msg):
     sys.stderr.write('ERROR: %s\n' % msg)
     sys.exit(1)
@@ -156,9 +222,16 @@ def fail_cmdline(option=None):
     sys.exit(1)
 
 def main():
+    addr = ''
     try:
         if len(sys.argv) == 2:
             qemu = QMPShell(sys.argv[1])
+            addr = sys.argv[1]
+        elif len(sys.argv) == 3:
+            if sys.argv[1] != '-H':
+                fail_cmdline(sys.argv[1])
+            qemu = HMPShell(sys.argv[2])
+            addr = sys.argv[2]
         else:
                 fail_cmdline()
     except QMPShellBadPort:
@@ -171,7 +244,7 @@ def main():
     except qmp.QMPCapabilitiesError:
         die('Could not negotiate capabilities')
     except qemu.error:
-        die('Could not connect to %s' % sys.argv[1])
+        die('Could not connect to %s' % addr)
 
     qemu.show_banner()
     while qemu.read_exec_command('(QEMU) '):
-- 
1.7.3.2.164.g6f10c

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode
  2010-11-10 18:59 [Qemu-devel] [PATCH v2 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
@ 2010-11-10 18:59 ` Luiz Capitulino
  0 siblings, 0 replies; 10+ messages in thread
From: Luiz Capitulino @ 2010-11-10 18:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, armbru

In which qmp-shell will exclusively use the HMP passthrough feature,
this is useful for testing.

Example:

    # ./qmp-shell -H qmp-sock
    Welcome to the HMP shell!
    Connected to QEMU 0.13.50

    (QEMU) info network
    VLAN 0 devices:
      user.0: net=10.0.2.0, restricted=n
        e1000.0: model=e1000,macaddr=52:54:00:12:34:56
        Devices not on any VLAN:
    (QEMU)

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 QMP/qmp-shell |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 74 insertions(+), 1 deletions(-)

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index 1fb7e76..ce0d259 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -145,6 +145,72 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         else:
             return self._execute_cmd(cmdline)
 
+class HMPShell(QMPShell):
+    def __init__(self, address):
+        QMPShell.__init__(self, address)
+        self.__cpu_index = 0
+
+    def __cmd_completion(self):
+        for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
+            if cmd and cmd[0] != '[' and cmd[0] != '\t':
+                name = cmd.split()[0] # drop help text
+                if name == 'info':
+                    continue
+                if name.find('|') != -1:
+                    # Command in the form 'foobar|f' or 'f|foobar', take the
+                    # full name
+                    opt = name.split('|')
+                    if len(opt[0]) == 1:
+                        name = opt[1]
+                    else:
+                        name = opt[0]
+                self._completer.append(name)
+                self._completer.append('help ' + name) # help completion
+
+    def __info_completion(self):
+        for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
+            if cmd:
+                self._completer.append('info ' + cmd.split()[1])
+
+    def __other_completion(self):
+        # special cases
+        self._completer.append('help info')
+
+    def _fill_completion(self):
+        self.__cmd_completion()
+        self.__info_completion()
+        self.__other_completion()
+
+    def __cmd_passthrough(self, cmdline):
+        return self.cmd_obj({ 'execute': 'hmp_passthrough', 'arguments':
+                              { 'command-line': cmdline,
+                                'cpu-index': self.__cpu_index } })
+
+    def _execute_cmd(self, cmdline):
+        if cmdline.split()[0] == "cpu":
+            # trap the cpu command, it requires special setting
+            try:
+                self.__cpu_index = int(cmdline.split()[1])
+            except ValueError:
+                print 'cpu command takes an integer argument'
+                return True
+        resp = self.__cmd_passthrough(cmdline)
+        if resp is None:
+            print 'Disconnected'
+            return False
+        assert 'return' in resp or 'error' in resp
+        if 'return' in resp:
+            # Success
+            if len(resp['return']) > 0:
+                print resp['return'],
+        else:
+            # Error
+            print '%s: %s' % (resp['error']['class'], resp['error']['desc'])
+        return True
+
+    def show_banner(self):
+        QMPShell.show_banner(self, msg='Welcome to the HMP shell!')
+
 def die(msg):
     sys.stderr.write('ERROR: %s\n' % msg)
     sys.exit(1)
@@ -156,9 +222,16 @@ def fail_cmdline(option=None):
     sys.exit(1)
 
 def main():
+    addr = ''
     try:
         if len(sys.argv) == 2:
             qemu = QMPShell(sys.argv[1])
+            addr = sys.argv[1]
+        elif len(sys.argv) == 3:
+            if sys.argv[1] != '-H':
+                fail_cmdline(sys.argv[1])
+            qemu = HMPShell(sys.argv[2])
+            addr = sys.argv[2]
         else:
                 fail_cmdline()
     except QMPShellBadPort:
@@ -171,7 +244,7 @@ def main():
     except qmp.QMPCapabilitiesError:
         die('Could not negotiate capabilities')
     except qemu.error:
-        die('Could not connect to %s' % sys.argv[1])
+        die('Could not connect to %s' % addr)
 
     qemu.show_banner()
     while qemu.read_exec_command('(QEMU) '):
-- 
1.7.3.2.164.g6f10c

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode
  2010-10-29 14:28 ` [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode Luiz Capitulino
@ 2010-11-10 13:22   ` Markus Armbruster
  0 siblings, 0 replies; 10+ messages in thread
From: Markus Armbruster @ 2010-11-10 13:22 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: aliguori, qemu-devel

Luiz Capitulino <lcapitulino@redhat.com> writes:

> In which qmp-shell will exclusively use the HMP passthrough feature,
> this is useful for testing.
>
> Example:
>

If you respin anyway, consider inserting something like "$ qmp-shell -H
..." here, to point to the new -H.

>     (QEMU) info network
>     VLAN 0 devices:
>       user.0: net=10.0.2.0, restricted=n
>         e1000.0: model=e1000,macaddr=52:54:00:12:34:56
>         Devices not on any VLAN:
>     (QEMU)
[...]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode
  2010-10-29 14:28 [Qemu-devel] [PATCH v1 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
@ 2010-10-29 14:28 ` Luiz Capitulino
  2010-11-10 13:22   ` Markus Armbruster
  0 siblings, 1 reply; 10+ messages in thread
From: Luiz Capitulino @ 2010-10-29 14:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, armbru

In which qmp-shell will exclusively use the HMP passthrough feature,
this is useful for testing.

Example:

    (QEMU) info network
    VLAN 0 devices:
      user.0: net=10.0.2.0, restricted=n
        e1000.0: model=e1000,macaddr=52:54:00:12:34:56
        Devices not on any VLAN:
    (QEMU)

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 QMP/qmp-shell |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 70 insertions(+), 0 deletions(-)

diff --git a/QMP/qmp-shell b/QMP/qmp-shell
index 1fb7e76..8eb5b3e 100755
--- a/QMP/qmp-shell
+++ b/QMP/qmp-shell
@@ -145,6 +145,72 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         else:
             return self._execute_cmd(cmdline)
 
+class HMPShell(QMPShell):
+    def __init__(self, address):
+        QMPShell.__init__(self, address)
+        self.__cpu_index = 0
+
+    def __cmd_completion(self):
+        for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
+            if cmd and cmd[0] != '[' and cmd[0] != '\t':
+                name = cmd.split()[0] # drop help text
+                if name == 'info':
+                    continue
+                if name.find('|') != -1:
+                    # Command in the form 'foobar|f' or 'f|foobar', take the
+                    # full name
+                    opt = name.split('|')
+                    if len(opt[0]) == 1:
+                        name = opt[1]
+                    else:
+                        name = opt[0]
+                self._completer.append(name)
+                self._completer.append('help ' + name) # help completion
+
+    def __info_completion(self):
+        for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
+            if cmd:
+                self._completer.append('info ' + cmd.split()[1])
+
+    def __other_completion(self):
+        # special cases
+        self._completer.append('help info')
+
+    def _fill_completion(self):
+        self.__cmd_completion()
+        self.__info_completion()
+        self.__other_completion()
+
+    def __cmd_passthrough(self, cmdline):
+        return self.cmd_obj({ 'execute': 'hmp_passthrough', 'arguments':
+                              { 'command-line': cmdline,
+                                'cpu-index': self.__cpu_index } })
+
+    def _execute_cmd(self, cmdline):
+        if cmdline.split()[0] == "cpu":
+            # trap the cpu command, it requires special setting
+            try:
+                self.__cpu_index = int(cmdline.split()[1])
+            except ValueError:
+                print 'cpu command takes an integer argument'
+                return True
+        resp = self.__cmd_passthrough(cmdline)
+        if resp is None:
+            print 'Disconnected'
+            return False
+        assert 'return' in resp or 'error' in resp
+        if 'return' in resp:
+            # Success
+            if len(resp['return']) > 0:
+                print resp['return'],
+        else:
+            # Error
+            print '%s: %s' % (resp['error']['class'], resp['error']['desc'])
+        return True
+
+    def show_banner(self):
+        QMPShell.show_banner(self, msg='Welcome to the HMP shell!')
+
 def die(msg):
     sys.stderr.write('ERROR: %s\n' % msg)
     sys.exit(1)
@@ -159,6 +225,10 @@ def main():
     try:
         if len(sys.argv) == 2:
             qemu = QMPShell(sys.argv[1])
+        elif len(sys.argv) == 3:
+            if sys.argv[1] != '-H':
+                fail_cmdline(sys.argv[1])
+            qemu = HMPShell(sys.argv[2])
         else:
                 fail_cmdline()
     except QMPShellBadPort:
-- 
1.7.3.2.145.g7ebee

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-11-17 12:39 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-16 19:19 [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
2010-11-16 19:19 ` [Qemu-devel] [PATCH 1/3] qemu-char: Introduce Memory driver Luiz Capitulino
2010-11-16 19:19 ` [Qemu-devel] [PATCH 2/3] QMP: Introduce Human Monitor passthrough command Luiz Capitulino
2010-11-16 19:19 ` [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode Luiz Capitulino
2010-11-17 10:27 ` [Qemu-devel] [PATCH v4 0/3]: QMP: Human Monitor passthrough Markus Armbruster
2010-11-17 12:39   ` Luiz Capitulino
  -- strict thread matches above, loose matches on Subject: below --
2010-11-11 19:31 [Qemu-devel] [PATCH v3 " Luiz Capitulino
2010-11-11 19:31 ` [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode Luiz Capitulino
2010-11-10 18:59 [Qemu-devel] [PATCH v2 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
2010-11-10 18:59 ` [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode Luiz Capitulino
2010-10-29 14:28 [Qemu-devel] [PATCH v1 0/3]: QMP: Human Monitor passthrough Luiz Capitulino
2010-10-29 14:28 ` [Qemu-devel] [PATCH 3/3] QMP/qmp-shell: Introduce HMP mode Luiz Capitulino
2010-11-10 13:22   ` Markus Armbruster

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.