From: Ishani Chugh <chugh.ishani@research.iiit.ac.in>
To: qemu-devel@nongnu.org
Cc: stefanha@redhat.com, jsnow@redhat.com,
Ishani Chugh <chugh.ishani@research.iiit.ac.in>
Subject: [Qemu-devel] [PATCH] Python3 Support for qmp.py
Date: Sat, 1 Jul 2017 00:39:41 +0530 [thread overview]
Message-ID: <1498849781-12776-1-git-send-email-chugh.ishani@research.iiit.ac.in> (raw)
This patch intends to make qmp.py compatible with both python2 and python3.
Signed-off-by: Ishani Chugh <chugh.ishani@research.iiit.ac.in>
---
scripts/qmp/qmp.py | 66 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 43 insertions(+), 23 deletions(-)
diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py
index 62d3651..9926c36 100644
--- a/scripts/qmp/qmp.py
+++ b/scripts/qmp/qmp.py
@@ -13,18 +13,23 @@ import errno
import socket
import sys
+
class QMPError(Exception):
pass
+
class QMPConnectError(QMPError):
pass
+
class QMPCapabilitiesError(QMPError):
pass
+
class QMPTimeoutError(QMPError):
pass
+
class QEMUMonitorProtocol:
def __init__(self, address, server=False, debug=False):
"""
@@ -42,6 +47,7 @@ class QEMUMonitorProtocol:
self.__address = address
self._debug = debug
self.__sock = self.__get_sock()
+ self.data = b""
if server:
self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.__sock.bind(self.__address)
@@ -56,23 +62,35 @@ class QEMUMonitorProtocol:
def __negotiate_capabilities(self):
greeting = self.__json_read()
- if greeting is None or not greeting.has_key('QMP'):
+ if greeting is None or 'QMP' not in greeting:
raise QMPConnectError
- # Greeting seems ok, negotiate capabilities
resp = self.cmd('qmp_capabilities')
if "return" in resp:
return greeting
raise QMPCapabilitiesError
+ def __sock_readline(self):
+ while True:
+ ch = self.__sock.recv(1)
+ if ch is None:
+ if self.data:
+ raise ValueError('socket closed mid-line')
+ return None
+ self.data += ch
+ if ch == b'\n':
+ line = self.data.decode('utf-8')
+ self.data = b""
+ return line
+
def __json_read(self, only_event=False):
while True:
- data = self.__sockfile.readline()
+ data = self.__sock_readline()
if not data:
return
resp = json.loads(data)
if 'event' in resp:
if self._debug:
- print >>sys.stderr, "QMP:<<< %s" % resp
+ print("QMP:<<< %s" % resp)
self.__events.append(resp)
if not only_event:
continue
@@ -87,18 +105,18 @@ class QEMUMonitorProtocol:
@param wait (bool): block until an event is available.
@param wait (float): If wait is a float, treat it as a timeout value.
- @raise QMPTimeoutError: If a timeout float is provided and the timeout
- period elapses.
- @raise QMPConnectError: If wait is True but no events could be retrieved
- or if some other error occurred.
+ @raise QMPTimeoutError: If a timeout float is provided and the
+ timeout period elapses.
+ @raise QMPConnectError: If wait is True but no events could be
+ retrieved or if some other error occurred.
"""
# Check for new events regardless and pull them into the cache:
self.__sock.setblocking(0)
try:
- self.__json_read()
+ test = self.__json_read()
except socket.error as err:
- if err[0] == errno.EAGAIN:
+ if err.errno == errno.EAGAIN:
# No data available
pass
self.__sock.setblocking(1)
@@ -128,7 +146,7 @@ class QEMUMonitorProtocol:
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock.connect(self.__address)
- self.__sockfile = self.__sock.makefile()
+ self.__sockfile = self.__sock.makefile('rb')
if negotiate:
return self.__negotiate_capabilities()
@@ -143,7 +161,7 @@ class QEMUMonitorProtocol:
"""
self.__sock.settimeout(15)
self.__sock, _ = self.__sock.accept()
- self.__sockfile = self.__sock.makefile()
+ self.__sockfile = self.__sock.makefile('rb')
return self.__negotiate_capabilities()
def cmd_obj(self, qmp_cmd):
@@ -155,16 +173,17 @@ class QEMUMonitorProtocol:
been closed
"""
if self._debug:
- print >>sys.stderr, "QMP:>>> %s" % qmp_cmd
+ print("QMP:>>> %s" % qmp_cmd)
try:
- self.__sock.sendall(json.dumps(qmp_cmd))
+ command = json.dumps(qmp_cmd)
+ self.__sock.sendall(command.encode('UTF-8'))
except socket.error as err:
- if err[0] == errno.EPIPE:
+ if err.errno == errno.EPIPE:
return
- raise socket.error(err)
+ raise
resp = self.__json_read()
if self._debug:
- print >>sys.stderr, "QMP:<<< %s" % resp
+ print("QMP:<<< %s" % resp)
return resp
def cmd(self, name, args=None, id=None):
@@ -175,7 +194,7 @@ class QEMUMonitorProtocol:
@param args: command arguments (dict)
@param id: command id (dict, list, string or int)
"""
- qmp_cmd = { 'execute': name }
+ qmp_cmd = {'execute': name}
if args:
qmp_cmd['arguments'] = args
if id:
@@ -184,7 +203,7 @@ class QEMUMonitorProtocol:
def command(self, cmd, **kwds):
ret = self.cmd(cmd, kwds)
- if ret.has_key('error'):
+ if 'error' in ret:
raise Exception(ret['error']['desc'])
return ret['return']
@@ -197,8 +216,8 @@ class QEMUMonitorProtocol:
@raise QMPTimeoutError: If a timeout float is provided and the timeout
period elapses.
- @raise QMPConnectError: If wait is True but no events could be retrieved
- or if some other error occurred.
+ @raise QMPConnectError: If wait is True but no events could be
+ retrieved or if some other error occurred.
@return The first available QMP event, or None.
"""
@@ -217,8 +236,8 @@ class QEMUMonitorProtocol:
@raise QMPTimeoutError: If a timeout float is provided and the timeout
period elapses.
- @raise QMPConnectError: If wait is True but no events could be retrieved
- or if some other error occurred.
+ @raise QMPConnectError: If wait is True but no events could be
+ retrieved or if some other error occurred.
@return The list of available QMP events.
"""
@@ -245,3 +264,4 @@ class QEMUMonitorProtocol:
def is_scm_available(self):
return self.__sock.family == socket.AF_UNIX
+
--
2.7.4
next reply other threads:[~2017-06-30 19:10 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-30 19:09 Ishani Chugh [this message]
2017-07-03 8:50 ` [Qemu-devel] [PATCH] Python3 Support for qmp.py Stefan Hajnoczi
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=1498849781-12776-1-git-send-email-chugh.ishani@research.iiit.ac.in \
--to=chugh.ishani@research.iiit.ac.in \
--cc=jsnow@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.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).