* [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option
@ 2011-05-25 18:48 Stefan Hajnoczi
2011-05-25 18:48 ` [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol Stefan Hajnoczi
2011-05-25 21:15 ` [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option Luiz Capitulino
0 siblings, 2 replies; 7+ messages in thread
From: Stefan Hajnoczi @ 2011-05-25 18:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Stefan Hajnoczi, Luiz Capitulino
The get_events() function polls for new QMP events and then returns. It
can be useful to wait for the next QMP event so add the boolean 'wait'
keyword argument.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
QMP/qmp.py | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/QMP/qmp.py b/QMP/qmp.py
index 14ce8b0..2565508 100644
--- a/QMP/qmp.py
+++ b/QMP/qmp.py
@@ -43,7 +43,7 @@ class QEMUMonitorProtocol:
family = socket.AF_UNIX
return socket.socket(family, socket.SOCK_STREAM)
- def __json_read(self):
+ def __json_read(self, only_event=False):
while True:
data = self.__sockfile.readline()
if not data:
@@ -51,7 +51,8 @@ class QEMUMonitorProtocol:
resp = json.loads(data)
if 'event' in resp:
self.__events.append(resp)
- continue
+ if not only_event:
+ continue
return resp
error = socket.error
@@ -106,9 +107,11 @@ class QEMUMonitorProtocol:
qmp_cmd['id'] = id
return self.cmd_obj(qmp_cmd)
- def get_events(self):
+ def get_events(self, wait=False):
"""
Get a list of available QMP events.
+
+ @param wait: block until an event is available (bool)
"""
self.__sock.setblocking(0)
try:
@@ -118,6 +121,8 @@ class QEMUMonitorProtocol:
# No data available
pass
self.__sock.setblocking(1)
+ if not self.__events and wait:
+ self.__json_read(only_event=True)
return self.__events
def clear_events(self):
--
1.7.4.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol
2011-05-25 18:48 [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option Stefan Hajnoczi
@ 2011-05-25 18:48 ` Stefan Hajnoczi
2011-05-25 21:16 ` Luiz Capitulino
2011-05-25 21:15 ` [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option Luiz Capitulino
1 sibling, 1 reply; 7+ messages in thread
From: Stefan Hajnoczi @ 2011-05-25 18:48 UTC (permalink / raw)
To: qemu-devel; +Cc: Stefan Hajnoczi, Luiz Capitulino
QEMU supports socket chardevs that establish connections like a server
or a client. The QEMUMonitorProtocol class only supports connecting as
a client. It is not possible to connect race-free when launching QEMU
since trying to connect before QEMU has bound and is listening on the
socket results in failure.
Add the QEMUMonitorProtocol(server=True) argument to bind and listen on
the socket. The QEMU process can then be launched and connects to the
already existing QMP socket without a race condition:
qmp = qmp.QEMUMonitorProtocol(monitor_path, server=True)
popen = subprocess.Popen(args)
qmp.accept()
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
QMP/qmp.py | 43 ++++++++++++++++++++++++++++++++-----------
1 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/QMP/qmp.py b/QMP/qmp.py
index 2565508..c7dbea0 100644
--- a/QMP/qmp.py
+++ b/QMP/qmp.py
@@ -22,19 +22,24 @@ class QMPCapabilitiesError(QMPError):
pass
class QEMUMonitorProtocol:
- def __init__(self, address):
+ def __init__(self, address, server=False):
"""
Create a QEMUMonitorProtocol class.
@param address: QEMU address, can be either a unix socket path (string)
or a tuple in the form ( address, port ) for a TCP
connection
- @note No connection is established, this is done by the connect() method
+ @param server: server mode listens on the socket (bool)
+ @raise socket.error on socket connection errors
+ @note No connection is established, this is done by the connect() or
+ accept() methods
"""
self.__events = []
self.__address = address
self.__sock = self.__get_sock()
- self.__sockfile = self.__sock.makefile()
+ if server:
+ self.__sock.bind(self.__address)
+ self.__sock.listen(1)
def __get_sock(self):
if isinstance(self.__address, tuple):
@@ -43,6 +48,17 @@ class QEMUMonitorProtocol:
family = socket.AF_UNIX
return socket.socket(family, socket.SOCK_STREAM)
+ def __negotiate_capabilities(self):
+ self.__sockfile = self.__sock.makefile()
+ greeting = self.__json_read()
+ if greeting is None or not greeting.has_key('QMP'):
+ raise QMPConnectError
+ # Greeting seems ok, negotiate capabilities
+ resp = self.cmd('qmp_capabilities')
+ if "return" in resp:
+ return greeting
+ raise QMPCapabilitiesError
+
def __json_read(self, only_event=False):
while True:
data = self.__sockfile.readline()
@@ -67,14 +83,19 @@ class QEMUMonitorProtocol:
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock.connect(self.__address)
- greeting = self.__json_read()
- if greeting is None or not greeting.has_key('QMP'):
- raise QMPConnectError
- # Greeting seems ok, negotiate capabilities
- resp = self.cmd('qmp_capabilities')
- if "return" in resp:
- return greeting
- raise QMPCapabilitiesError
+ return self.__negotiate_capabilities()
+
+ def accept(self):
+ """
+ Await connection from QMP Monitor and perform capabilities negotiation.
+
+ @return QMP greeting dict
+ @raise socket.error on socket connection errors
+ @raise QMPConnectError if the greeting is not received
+ @raise QMPCapabilitiesError if fails to negotiate capabilities
+ """
+ self.__sock, _ = self.__sock.accept()
+ return self.__negotiate_capabilities()
def cmd_obj(self, qmp_cmd):
"""
--
1.7.4.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option
2011-05-25 18:48 [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option Stefan Hajnoczi
2011-05-25 18:48 ` [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol Stefan Hajnoczi
@ 2011-05-25 21:15 ` Luiz Capitulino
2011-05-26 8:03 ` Stefan Hajnoczi
1 sibling, 1 reply; 7+ messages in thread
From: Luiz Capitulino @ 2011-05-25 21:15 UTC (permalink / raw)
To: Stefan Hajnoczi; +Cc: qemu-devel
On Wed, 25 May 2011 19:48:00 +0100
Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> wrote:
> The get_events() function polls for new QMP events and then returns. It
> can be useful to wait for the next QMP event so add the boolean 'wait'
> keyword argument.
>
> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> ---
> QMP/qmp.py | 11 ++++++++---
> 1 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/QMP/qmp.py b/QMP/qmp.py
> index 14ce8b0..2565508 100644
> --- a/QMP/qmp.py
> +++ b/QMP/qmp.py
> @@ -43,7 +43,7 @@ class QEMUMonitorProtocol:
> family = socket.AF_UNIX
> return socket.socket(family, socket.SOCK_STREAM)
>
> - def __json_read(self):
> + def __json_read(self, only_event=False):
> while True:
> data = self.__sockfile.readline()
> if not data:
> @@ -51,7 +51,8 @@ class QEMUMonitorProtocol:
> resp = json.loads(data)
> if 'event' in resp:
> self.__events.append(resp)
> - continue
> + if not only_event:
> + continue
> return resp
>
> error = socket.error
> @@ -106,9 +107,11 @@ class QEMUMonitorProtocol:
> qmp_cmd['id'] = id
> return self.cmd_obj(qmp_cmd)
>
> - def get_events(self):
> + def get_events(self, wait=False):
> """
> Get a list of available QMP events.
> +
> + @param wait: block until an event is available (bool)
> """
> self.__sock.setblocking(0)
> try:
> @@ -118,6 +121,8 @@ class QEMUMonitorProtocol:
> # No data available
> pass
> self.__sock.setblocking(1)
> + if not self.__events and wait:
> + self.__json_read(only_event=True)
> return self.__events
Maybe this is better (untested):
def get_events(self, wait=False):
"""
Get a list of available QMP events.
@param wait: block until an event is available (bool)
"""
if not wait:
self.__sock.setblocking(0)
try:
self.__json_read(only_event=wait)
except socket.error, err:
if err[0] == errno.EAGAIN:
# No data available
pass
if not wait:
self.__sock.setblocking(1)
return self.__events
>
> def clear_events(self):
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol
2011-05-25 18:48 ` [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol Stefan Hajnoczi
@ 2011-05-25 21:16 ` Luiz Capitulino
2011-05-26 8:16 ` Stefan Hajnoczi
0 siblings, 1 reply; 7+ messages in thread
From: Luiz Capitulino @ 2011-05-25 21:16 UTC (permalink / raw)
To: Stefan Hajnoczi; +Cc: qemu-devel
On Wed, 25 May 2011 19:48:01 +0100
Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> wrote:
> QEMU supports socket chardevs that establish connections like a server
> or a client. The QEMUMonitorProtocol class only supports connecting as
> a client. It is not possible to connect race-free when launching QEMU
> since trying to connect before QEMU has bound and is listening on the
> socket results in failure.
>
> Add the QEMUMonitorProtocol(server=True) argument to bind and listen on
> the socket. The QEMU process can then be launched and connects to the
> already existing QMP socket without a race condition:
>
> qmp = qmp.QEMUMonitorProtocol(monitor_path, server=True)
> popen = subprocess.Popen(args)
> qmp.accept()
Would be cool to get the demo shell doing this (not a required for the
initial merge, of course).
>
> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> ---
> QMP/qmp.py | 43 ++++++++++++++++++++++++++++++++-----------
> 1 files changed, 32 insertions(+), 11 deletions(-)
>
> diff --git a/QMP/qmp.py b/QMP/qmp.py
> index 2565508..c7dbea0 100644
> --- a/QMP/qmp.py
> +++ b/QMP/qmp.py
> @@ -22,19 +22,24 @@ class QMPCapabilitiesError(QMPError):
> pass
>
> class QEMUMonitorProtocol:
> - def __init__(self, address):
> + def __init__(self, address, server=False):
> """
> Create a QEMUMonitorProtocol class.
>
> @param address: QEMU address, can be either a unix socket path (string)
> or a tuple in the form ( address, port ) for a TCP
> connection
> - @note No connection is established, this is done by the connect() method
> + @param server: server mode listens on the socket (bool)
> + @raise socket.error on socket connection errors
> + @note No connection is established, this is done by the connect() or
> + accept() methods
> """
> self.__events = []
> self.__address = address
> self.__sock = self.__get_sock()
> - self.__sockfile = self.__sock.makefile()
> + if server:
> + self.__sock.bind(self.__address)
> + self.__sock.listen(1)
>
> def __get_sock(self):
> if isinstance(self.__address, tuple):
> @@ -43,6 +48,17 @@ class QEMUMonitorProtocol:
> family = socket.AF_UNIX
> return socket.socket(family, socket.SOCK_STREAM)
>
> + def __negotiate_capabilities(self):
> + self.__sockfile = self.__sock.makefile()
> + greeting = self.__json_read()
> + if greeting is None or not greeting.has_key('QMP'):
> + raise QMPConnectError
> + # Greeting seems ok, negotiate capabilities
> + resp = self.cmd('qmp_capabilities')
> + if "return" in resp:
> + return greeting
> + raise QMPCapabilitiesError
> +
> def __json_read(self, only_event=False):
> while True:
> data = self.__sockfile.readline()
> @@ -67,14 +83,19 @@ class QEMUMonitorProtocol:
> @raise QMPCapabilitiesError if fails to negotiate capabilities
> """
> self.__sock.connect(self.__address)
> - greeting = self.__json_read()
> - if greeting is None or not greeting.has_key('QMP'):
> - raise QMPConnectError
> - # Greeting seems ok, negotiate capabilities
> - resp = self.cmd('qmp_capabilities')
> - if "return" in resp:
> - return greeting
> - raise QMPCapabilitiesError
> + return self.__negotiate_capabilities()
> +
> + def accept(self):
> + """
> + Await connection from QMP Monitor and perform capabilities negotiation.
> +
> + @return QMP greeting dict
> + @raise socket.error on socket connection errors
> + @raise QMPConnectError if the greeting is not received
> + @raise QMPCapabilitiesError if fails to negotiate capabilities
> + """
> + self.__sock, _ = self.__sock.accept()
> + return self.__negotiate_capabilities()
>
> def cmd_obj(self, qmp_cmd):
> """
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option
2011-05-25 21:15 ` [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option Luiz Capitulino
@ 2011-05-26 8:03 ` Stefan Hajnoczi
2011-05-26 12:47 ` Luiz Capitulino
0 siblings, 1 reply; 7+ messages in thread
From: Stefan Hajnoczi @ 2011-05-26 8:03 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: Stefan Hajnoczi, qemu-devel
On Wed, May 25, 2011 at 10:15 PM, Luiz Capitulino
<lcapitulino@redhat.com> wrote:
> On Wed, 25 May 2011 19:48:00 +0100
> Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> wrote:
>
>> The get_events() function polls for new QMP events and then returns. It
>> can be useful to wait for the next QMP event so add the boolean 'wait'
>> keyword argument.
>>
>> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
>> ---
>> QMP/qmp.py | 11 ++++++++---
>> 1 files changed, 8 insertions(+), 3 deletions(-)
>>
>> diff --git a/QMP/qmp.py b/QMP/qmp.py
>> index 14ce8b0..2565508 100644
>> --- a/QMP/qmp.py
>> +++ b/QMP/qmp.py
>> @@ -43,7 +43,7 @@ class QEMUMonitorProtocol:
>> family = socket.AF_UNIX
>> return socket.socket(family, socket.SOCK_STREAM)
>>
>> - def __json_read(self):
>> + def __json_read(self, only_event=False):
>> while True:
>> data = self.__sockfile.readline()
>> if not data:
>> @@ -51,7 +51,8 @@ class QEMUMonitorProtocol:
>> resp = json.loads(data)
>> if 'event' in resp:
>> self.__events.append(resp)
>> - continue
>> + if not only_event:
>> + continue
>> return resp
>>
>> error = socket.error
>> @@ -106,9 +107,11 @@ class QEMUMonitorProtocol:
>> qmp_cmd['id'] = id
>> return self.cmd_obj(qmp_cmd)
>>
>> - def get_events(self):
>> + def get_events(self, wait=False):
>> """
>> Get a list of available QMP events.
>> +
>> + @param wait: block until an event is available (bool)
>> """
>> self.__sock.setblocking(0)
>> try:
>> @@ -118,6 +121,8 @@ class QEMUMonitorProtocol:
>> # No data available
>> pass
>> self.__sock.setblocking(1)
>> + if not self.__events and wait:
>> + self.__json_read(only_event=True)
>> return self.__events
>
> Maybe this is better (untested):
I've tested it because that's how I implemented it first too :).
However, I don't want to block until the QMP monitor sends the next
event when there is already a received event pending.
The patch I posted polls for new events first, then only blocks if
there are no events available.
Stefan
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol
2011-05-25 21:16 ` Luiz Capitulino
@ 2011-05-26 8:16 ` Stefan Hajnoczi
0 siblings, 0 replies; 7+ messages in thread
From: Stefan Hajnoczi @ 2011-05-26 8:16 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: qemu-devel, Stefan Hajnoczi
The test-stream.py script performs several automated tests of the image
streaming QMP interface, including exercising both the incremental and
background streaming modes.
This should probably be ported to KVM-Autotest rather than reinventing
the wheel.
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
---
This is an example of how I am using qmp.py, especially the new
QEMUMonitorProtocol(server=True) and QEMUMonitorProtocol.get_events(wait=True)
arguments.
I am not submitting this for merge. Like the commit message says, this should
probably be ported to KVM-Autotest because it duplicates basic QEMU testing
infrastructure.
test-stream.py | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 145 insertions(+), 0 deletions(-)
create mode 100644 test-stream.py
diff --git a/test-stream.py b/test-stream.py
new file mode 100644
index 0000000..eb9d9d6
--- /dev/null
+++ b/test-stream.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+import unittest
+import subprocess
+import re
+import os
+import sys; sys.path.append('QMP/')
+import qmp
+
+def qemu_img(*args):
+ devnull = open('/dev/null', 'r+')
+ return subprocess.call(['./qemu-img'] + list(args), stdin=devnull, stdout=devnull)
+
+class VM(object):
+ def __init__(self):
+ self._monitor_path = '/tmp/qemu-mon.%d' % os.getpid()
+ self._qemu_log_path = '/tmp/qemu-log.%d' % os.getpid()
+ self._args = ['x86_64-softmmu/qemu-system-x86_64',
+ '-chardev', 'socket,id=mon,path=' + self._monitor_path,
+ '-mon', 'chardev=mon,mode=control',
+ '-nographic']
+ self._num_drives = 0
+
+ def add_drive(self, path):
+ self._args.append('-drive')
+ self._args.append('if=virtio,cache=none,file=%s,id=drive%d' % (path, self._num_drives))
+ self._num_drives += 1
+ return self
+
+ def launch(self):
+ devnull = open('/dev/null', 'rb')
+ qemulog = open(self._qemu_log_path, 'wb')
+ self._qmp = qmp.QEMUMonitorProtocol(self._monitor_path, server=True)
+ self._popen = subprocess.Popen(self._args, stdin=devnull, stdout=qemulog,
+ stderr=subprocess.STDOUT)
+ self._qmp.accept()
+
+ def shutdown(self):
+ self._qmp.cmd('quit')
+ self._popen.wait()
+ os.remove(self._monitor_path)
+ os.remove(self._qemu_log_path)
+
+ def qmp(self, cmd, **args):
+ return self._qmp.cmd(cmd, args=args)
+
+ def get_qmp_events(self, wait=False):
+ events = self._qmp.get_events(wait=wait)
+ self._qmp.clear_events()
+ return events
+
+index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
+
+class QMPTestCase(unittest.TestCase):
+ def dictpath(self, d, path):
+ """Traverse a path in a nested dict"""
+ for component in path.split('/'):
+ m = index_re.match(component)
+ if m:
+ component, idx = m.groups()
+ idx = int(idx)
+
+ if not isinstance(d, dict) or component not in d:
+ self.fail('failed path traversal for "%s" in "%s"' % (path, str(d)))
+ d = d[component]
+
+ if m:
+ if not isinstance(d, list):
+ self.fail('path component "%s" in "%s" is not a list in "%s"' % (component, path, str(d)))
+ try:
+ d = d[idx]
+ except IndexError:
+ self.fail('invalid index "%s" in path "%s" in "%s"' % (idx, path, str(d)))
+ return d
+
+ def assert_qmp(self, d, path, value):
+ result = self.dictpath(d, path)
+ self.assertEqual(result, value, 'values not equal "%s" and "%s"' % (str(result), str(value)))
+
+ def assert_no_active_streams(self):
+ result = self.vm.qmp('query-block-stream')
+ self.assert_qmp(result, 'return', [])
+
+class TestSingleDrive(QMPTestCase):
+ image_len = 1 * 1024 * 1024
+
+ def setUp(self):
+ qemu_img('create', 'backing.img', str(TestSingleDrive.image_len))
+ qemu_img('create', '-f', 'qed', '-o', 'backing_file=backing.img,copy_on_read=on', 'test.qed')
+ self.vm = VM().add_drive('test.qed')
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove('test.qed')
+ os.remove('backing.img')
+
+ def test_stream_incremental(self):
+ self.assert_no_active_streams()
+
+ completed = False
+ while not completed:
+ result = self.vm.qmp('block_stream', device='drive0')
+ self.assert_qmp(result, 'return/device', 'drive0')
+ self.assert_qmp(result, 'return/len', self.image_len)
+
+ for event in self.vm.get_qmp_events():
+ if event['event'] == 'BLOCK_STREAM_COMPLETED':
+ self.assert_qmp(event, 'data/device', 'drive0')
+ self.assert_qmp(event, 'data/offset', self.image_len)
+ self.assert_qmp(event, 'data/len', self.image_len)
+ completed = True
+
+ # Compare result against query-block-stream output
+ if not completed:
+ query = self.vm.qmp('query-block-stream')
+ self.assert_qmp(query, 'return[0]/device', 'drive0')
+ self.assert_qmp(query, 'return[0]/offset',
+ self.dictpath(result, 'return/offset'))
+ self.assert_qmp(query, 'return[0]/len', self.image_len)
+
+ self.assert_no_active_streams()
+
+ def test_stream_all(self):
+ self.assert_no_active_streams()
+
+ result = self.vm.qmp('block_stream', device='drive0', all=True)
+ self.assert_qmp(result, 'return', {})
+
+ completed = False
+ while not completed:
+ for event in self.vm.get_qmp_events(wait=True):
+ if event['event'] == 'BLOCK_STREAM_COMPLETED':
+ self.assert_qmp(event, 'data/device', 'drive0')
+ self.assert_qmp(event, 'data/offset', self.image_len)
+ self.assert_qmp(event, 'data/len', self.image_len)
+ completed = True
+
+ self.assert_no_active_streams()
+
+ def test_device_not_found(self):
+ result = self.vm.qmp('block_stream', device='nonexistent')
+ self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+
+if __name__ == '__main__':
+ unittest.main()
--
1.7.4.4
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option
2011-05-26 8:03 ` Stefan Hajnoczi
@ 2011-05-26 12:47 ` Luiz Capitulino
0 siblings, 0 replies; 7+ messages in thread
From: Luiz Capitulino @ 2011-05-26 12:47 UTC (permalink / raw)
To: Stefan Hajnoczi; +Cc: Stefan Hajnoczi, qemu-devel
On Thu, 26 May 2011 09:03:49 +0100
Stefan Hajnoczi <stefanha@gmail.com> wrote:
> On Wed, May 25, 2011 at 10:15 PM, Luiz Capitulino
> <lcapitulino@redhat.com> wrote:
> > On Wed, 25 May 2011 19:48:00 +0100
> > Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> wrote:
> >
> >> The get_events() function polls for new QMP events and then returns. It
> >> can be useful to wait for the next QMP event so add the boolean 'wait'
> >> keyword argument.
> >>
> >> Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
> >> ---
> >> QMP/qmp.py | 11 ++++++++---
> >> 1 files changed, 8 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/QMP/qmp.py b/QMP/qmp.py
> >> index 14ce8b0..2565508 100644
> >> --- a/QMP/qmp.py
> >> +++ b/QMP/qmp.py
> >> @@ -43,7 +43,7 @@ class QEMUMonitorProtocol:
> >> family = socket.AF_UNIX
> >> return socket.socket(family, socket.SOCK_STREAM)
> >>
> >> - def __json_read(self):
> >> + def __json_read(self, only_event=False):
> >> while True:
> >> data = self.__sockfile.readline()
> >> if not data:
> >> @@ -51,7 +51,8 @@ class QEMUMonitorProtocol:
> >> resp = json.loads(data)
> >> if 'event' in resp:
> >> self.__events.append(resp)
> >> - continue
> >> + if not only_event:
> >> + continue
> >> return resp
> >>
> >> error = socket.error
> >> @@ -106,9 +107,11 @@ class QEMUMonitorProtocol:
> >> qmp_cmd['id'] = id
> >> return self.cmd_obj(qmp_cmd)
> >>
> >> - def get_events(self):
> >> + def get_events(self, wait=False):
> >> """
> >> Get a list of available QMP events.
> >> +
> >> + @param wait: block until an event is available (bool)
> >> """
> >> self.__sock.setblocking(0)
> >> try:
> >> @@ -118,6 +121,8 @@ class QEMUMonitorProtocol:
> >> # No data available
> >> pass
> >> self.__sock.setblocking(1)
> >> + if not self.__events and wait:
> >> + self.__json_read(only_event=True)
> >> return self.__events
> >
> > Maybe this is better (untested):
>
> I've tested it because that's how I implemented it first too :).
> However, I don't want to block until the QMP monitor sends the next
> event when there is already a received event pending.
>
> The patch I posted polls for new events first, then only blocks if
> there are no events available.
Ok, pushed both patches to the QMP queue.
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-05-26 12:48 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-25 18:48 [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option Stefan Hajnoczi
2011-05-25 18:48 ` [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol Stefan Hajnoczi
2011-05-25 21:16 ` Luiz Capitulino
2011-05-26 8:16 ` Stefan Hajnoczi
2011-05-25 21:15 ` [Qemu-devel] [PATCH 1/2] QMP: add get_events(wait=True) option Luiz Capitulino
2011-05-26 8:03 ` Stefan Hajnoczi
2011-05-26 12:47 ` Luiz Capitulino
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).