qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15
@ 2017-09-15 23:37 Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 01/15] qemu.py: Pylint/style fixes Eduardo Habkost
                   ` (15 more replies)
  0 siblings, 16 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

I have been queueing some patches for Python modules and scripts,
recently, and submitted a MAINTAINERS patch to include Cleber and
me as maintainers.

However, I don't want to delay this pull request to avoid
conflicts if people send additional patches for those scripts, so
I'm sending this pull request before the MAINTAINERS patch is
applied.

The following changes since commit 5faf2d376af3cb4eb92da44c2580e08d39832caa:

  Merge remote-tracking branch 'remotes/huth/tags/check-20170915' into staging (2017-09-15 20:29:44 +0100)

are available in the git repository at:

  git://github.com/ehabkost/qemu.git tags/python-next-pull-request

for you to fetch changes up to b92a0011b1220aff549ae82c6104014d25e339ef:

  qemu.py: include debug information on launch error (2017-09-15 20:12:00 -0300)

----------------------------------------------------------------
Python queue, 2017-09-15

----------------------------------------------------------------

Amador Pahim (5):
  qemu.py: fix is_running() return before first launch()
  qemu.py: avoid writing to stdout/stderr
  qemu.py: use os.path.null instead of /dev/null
  qemu.py: improve message on negative exit code
  qemu.py: include debug information on launch error

Lukáš Doktor (10):
  qemu.py: Pylint/style fixes
  qemu|qtest: Avoid dangerous arguments
  qemu.py: Use iteritems rather than keys()
  qemu.py: Simplify QMP key-conversion
  qemu.py: Use custom exceptions rather than Exception
  qmp.py: Couple of pylint/style fixes
  qmp.py: Use object-based class for QEMUMonitorProtocol
  qmp.py: Avoid "has_key" usage
  qmp.py: Avoid overriding a builtin object
  qtest.py: Few pylint/style fixes

 scripts/qemu.py       | 145 +++++++++++++++++++++++++++++++++++++++-----------
 scripts/qmp/qmp.py    |  49 ++++++++++-------
 scripts/qtest.py      |  13 +++--
 scripts/qmp/qmp-shell |   4 +-
 4 files changed, 151 insertions(+), 60 deletions(-)

-- 
2.13.5

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

* [Qemu-devel] [PULL 01/15] qemu.py: Pylint/style fixes
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 02/15] qemu|qtest: Avoid dangerous arguments Eduardo Habkost
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

No actual code changes, just several pylint/style fixes and docstring
clarifications.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20170818142613.32394-2-ldoktor@redhat.com>
Reviewed-by: Cleber Rosa <crosa@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 73 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 55 insertions(+), 18 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index 4d8ee10943..b45e691538 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -30,8 +30,22 @@ class QEMUMachine(object):
         # vm is guaranteed to be shut down here
     '''
 
-    def __init__(self, binary, args=[], wrapper=[], name=None, test_dir="/var/tmp",
-                 monitor_address=None, socket_scm_helper=None, debug=False):
+    def __init__(self, binary, args=[], wrapper=[], name=None,
+                 test_dir="/var/tmp", monitor_address=None,
+                 socket_scm_helper=None, debug=False):
+        '''
+        Initialize a QEMUMachine
+
+        @param binary: path to the qemu binary
+        @param args: list of extra arguments
+        @param wrapper: list of arguments used as prefix to qemu binary
+        @param name: prefix for socket and log file names (default: qemu-PID)
+        @param test_dir: where to create socket and log file
+        @param monitor_address: address for QMP monitor
+        @param socket_scm_helper: helper program, required for send_fd_scm()"
+        @param debug: enable debug mode
+        @note: Qemu process is not started until launch() is used.
+        '''
         if name is None:
             name = "qemu-%d" % os.getpid()
         if monitor_address is None:
@@ -40,12 +54,13 @@ class QEMUMachine(object):
         self._qemu_log_path = os.path.join(test_dir, name + ".log")
         self._popen = None
         self._binary = binary
-        self._args = list(args) # Force copy args in case we modify them
+        self._args = list(args)     # Force copy args in case we modify them
         self._wrapper = wrapper
         self._events = []
         self._iolog = None
         self._socket_scm_helper = socket_scm_helper
         self._debug = debug
+        self._qmp = None
 
     def __enter__(self):
         return self
@@ -78,16 +93,16 @@ class QEMUMachine(object):
         if self._socket_scm_helper is None:
             print >>sys.stderr, "No path to socket_scm_helper set"
             return -1
-        if os.path.exists(self._socket_scm_helper) == False:
+        if not os.path.exists(self._socket_scm_helper):
             print >>sys.stderr, "%s does not exist" % self._socket_scm_helper
             return -1
         fd_param = ["%s" % self._socket_scm_helper,
                     "%d" % self._qmp.get_sock_fd(),
                     "%s" % fd_file_path]
         devnull = open('/dev/null', 'rb')
-        p = subprocess.Popen(fd_param, stdin=devnull, stdout=sys.stdout,
-                             stderr=sys.stderr)
-        return p.wait()
+        proc = subprocess.Popen(fd_param, stdin=devnull, stdout=sys.stdout,
+                                stderr=sys.stderr)
+        return proc.wait()
 
     @staticmethod
     def _remove_if_exists(path):
@@ -113,8 +128,8 @@ class QEMUMachine(object):
         return self._popen.pid
 
     def _load_io_log(self):
-        with open(self._qemu_log_path, "r") as fh:
-            self._iolog = fh.read()
+        with open(self._qemu_log_path, "r") as iolog:
+            self._iolog = iolog.read()
 
     def _base_args(self):
         if isinstance(self._monitor_address, tuple):
@@ -128,7 +143,8 @@ class QEMUMachine(object):
                 '-display', 'none', '-vga', 'none']
 
     def _pre_launch(self):
-        self._qmp = qmp.qmp.QEMUMonitorProtocol(self._monitor_address, server=True,
+        self._qmp = qmp.qmp.QEMUMonitorProtocol(self._monitor_address,
+                                                server=True,
                                                 debug=self._debug)
 
     def _post_launch(self):
@@ -145,9 +161,11 @@ class QEMUMachine(object):
         qemulog = open(self._qemu_log_path, 'wb')
         try:
             self._pre_launch()
-            args = self._wrapper + [self._binary] + self._base_args() + self._args
+            args = (self._wrapper + [self._binary] + self._base_args() +
+                    self._args)
             self._popen = subprocess.Popen(args, stdin=devnull, stdout=qemulog,
-                                           stderr=subprocess.STDOUT, shell=False)
+                                           stderr=subprocess.STDOUT,
+                                           shell=False)
             self._post_launch()
         except:
             if self.is_running():
@@ -168,23 +186,30 @@ class QEMUMachine(object):
 
             exitcode = self._popen.wait()
             if exitcode < 0:
-                sys.stderr.write('qemu received signal %i: %s\n' % (-exitcode, ' '.join(self._args)))
+                sys.stderr.write('qemu received signal %i: %s\n'
+                                 % (-exitcode, ' '.join(self._args)))
             self._load_io_log()
             self._post_shutdown()
 
     underscore_to_dash = string.maketrans('_', '-')
+
     def qmp(self, cmd, conv_keys=True, **args):
-        '''Invoke a QMP command and return the result dict'''
+        '''Invoke a QMP command and return the response dict'''
         qmp_args = dict()
-        for k in args.keys():
+        for key in args.keys():
             if conv_keys:
-                qmp_args[k.translate(self.underscore_to_dash)] = args[k]
+                qmp_args[key.translate(self.underscore_to_dash)] = args[key]
             else:
-                qmp_args[k] = args[k]
+                qmp_args[key] = args[key]
 
         return self._qmp.cmd(cmd, args=qmp_args)
 
     def command(self, cmd, conv_keys=True, **args):
+        '''
+        Invoke a QMP command.
+        On success return the response dict.
+        On failure raise an exception.
+        '''
         reply = self.qmp(cmd, conv_keys, **args)
         if reply is None:
             raise Exception("Monitor is closed")
@@ -207,7 +232,15 @@ class QEMUMachine(object):
         return events
 
     def event_wait(self, name, timeout=60.0, match=None):
-        # Test if 'match' is a recursive subset of 'event'
+        '''
+        Wait for specified timeout on named event in QMP; optionally filter
+        results by match.
+
+        The 'match' is checked to be a recursive subset of the 'event'; skips
+        branch processing on match's value None
+           {"foo": {"bar": 1}} matches {"foo": None}
+           {"foo": {"bar": 1}} does not matches {"foo": {"baz": None}}
+        '''
         def event_match(event, match=None):
             if match is None:
                 return True
@@ -240,4 +273,8 @@ class QEMUMachine(object):
         return None
 
     def get_log(self):
+        '''
+        After self.shutdown or failed qemu execution, this returns the output
+        of the qemu process.
+        '''
         return self._iolog
-- 
2.13.5

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

* [Qemu-devel] [PULL 02/15] qemu|qtest: Avoid dangerous arguments
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 01/15] qemu.py: Pylint/style fixes Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 03/15] qemu.py: Use iteritems rather than keys() Eduardo Habkost
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

The list object is mutable in python and potentially might modify other
object's arguments when used as default argument. Reproducer:

    >>> vm1 = QEMUMachine("qemu")
    >>> vm2 = QEMUMachine("qemu")
    >>> vm1._wrapper.append("foo")
    >>> print vm2._wrapper
    ['foo']

In this case the `args` is actually copied so it would be safe to keep
it, but it's not a good practice to keep it. The same issue applies in
inherited qtest module.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-Id: <20170818142613.32394-3-ldoktor@redhat.com>
Reviewed-by: Cleber Rosa <crosa@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py  | 6 +++++-
 scripts/qtest.py | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index b45e691538..afd98a290e 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -30,7 +30,7 @@ class QEMUMachine(object):
         # vm is guaranteed to be shut down here
     '''
 
-    def __init__(self, binary, args=[], wrapper=[], name=None,
+    def __init__(self, binary, args=None, wrapper=None, name=None,
                  test_dir="/var/tmp", monitor_address=None,
                  socket_scm_helper=None, debug=False):
         '''
@@ -46,6 +46,10 @@ class QEMUMachine(object):
         @param debug: enable debug mode
         @note: Qemu process is not started until launch() is used.
         '''
+        if args is None:
+            args = []
+        if wrapper is None:
+            wrapper = []
         if name is None:
             name = "qemu-%d" % os.getpid()
         if monitor_address is None:
diff --git a/scripts/qtest.py b/scripts/qtest.py
index d5aecb5f49..ab183c0635 100644
--- a/scripts/qtest.py
+++ b/scripts/qtest.py
@@ -79,7 +79,7 @@ class QEMUQtestProtocol(object):
 class QEMUQtestMachine(qemu.QEMUMachine):
     '''A QEMU VM'''
 
-    def __init__(self, binary, args=[], name=None, test_dir="/var/tmp",
+    def __init__(self, binary, args=None, name=None, test_dir="/var/tmp",
                  socket_scm_helper=None):
         if name is None:
             name = "qemu-%d" % os.getpid()
-- 
2.13.5

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

* [Qemu-devel] [PULL 03/15] qemu.py: Use iteritems rather than keys()
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 01/15] qemu.py: Pylint/style fixes Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 02/15] qemu|qtest: Avoid dangerous arguments Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 04/15] qemu.py: Simplify QMP key-conversion Eduardo Habkost
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

Let's avoid creating an in-memory list of keys and query for each value
and use `iteritems` which is an iterator of key-value pairs.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170818142613.32394-4-ldoktor@redhat.com>
Reviewed-by: Cleber Rosa <crosa@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index afd98a290e..d8c169b31e 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -200,11 +200,11 @@ class QEMUMachine(object):
     def qmp(self, cmd, conv_keys=True, **args):
         '''Invoke a QMP command and return the response dict'''
         qmp_args = dict()
-        for key in args.keys():
+        for key, value in args.iteritems():
             if conv_keys:
-                qmp_args[key.translate(self.underscore_to_dash)] = args[key]
+                qmp_args[key.translate(self.underscore_to_dash)] = value
             else:
-                qmp_args[key] = args[key]
+                qmp_args[key] = value
 
         return self._qmp.cmd(cmd, args=qmp_args)
 
-- 
2.13.5

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

* [Qemu-devel] [PULL 04/15] qemu.py: Simplify QMP key-conversion
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (2 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 03/15] qemu.py: Use iteritems rather than keys() Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 05/15] qemu.py: Use custom exceptions rather than Exception Eduardo Habkost
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

The QMP key conversion consist of '_'s to be replaced with '-'s, which
can easily be done by a single `str.replace` method which is faster and
does not require `string` module import.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20170818142613.32394-5-ldoktor@redhat.com>
Reviewed-by: Cleber Rosa <crosa@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index d8c169b31e..bde8da8fe7 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -13,7 +13,6 @@
 #
 
 import errno
-import string
 import os
 import sys
 import subprocess
@@ -195,14 +194,12 @@ class QEMUMachine(object):
             self._load_io_log()
             self._post_shutdown()
 
-    underscore_to_dash = string.maketrans('_', '-')
-
     def qmp(self, cmd, conv_keys=True, **args):
         '''Invoke a QMP command and return the response dict'''
         qmp_args = dict()
         for key, value in args.iteritems():
             if conv_keys:
-                qmp_args[key.translate(self.underscore_to_dash)] = value
+                qmp_args[key.replace('_', '-')] = value
             else:
                 qmp_args[key] = value
 
-- 
2.13.5

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

* [Qemu-devel] [PULL 05/15] qemu.py: Use custom exceptions rather than Exception
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (3 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 04/15] qemu.py: Simplify QMP key-conversion Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 06/15] qmp.py: Couple of pylint/style fixes Eduardo Habkost
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

The naked Exception should not be widely used. It makes sense to be a
bit more specific and use better-suited custom exceptions. As a benefit
we can store the full reply in the exception in case someone needs it
when catching the exception.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20170818142613.32394-6-ldoktor@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index bde8da8fe7..7c6802609a 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -19,6 +19,19 @@ import subprocess
 import qmp.qmp
 
 
+class MonitorResponseError(qmp.qmp.QMPError):
+    '''
+    Represents erroneous QMP monitor reply
+    '''
+    def __init__(self, reply):
+        try:
+            desc = reply["error"]["desc"]
+        except KeyError:
+            desc = reply
+        super(MonitorResponseError, self).__init__(desc)
+        self.reply = reply
+
+
 class QEMUMachine(object):
     '''A QEMU VM
 
@@ -213,9 +226,9 @@ class QEMUMachine(object):
         '''
         reply = self.qmp(cmd, conv_keys, **args)
         if reply is None:
-            raise Exception("Monitor is closed")
+            raise qmp.qmp.QMPError("Monitor is closed")
         if "error" in reply:
-            raise Exception(reply["error"]["desc"])
+            raise MonitorResponseError(reply)
         return reply["return"]
 
     def get_qmp_event(self, wait=False):
-- 
2.13.5

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

* [Qemu-devel] [PULL 06/15] qmp.py: Couple of pylint/style fixes
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (4 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 05/15] qemu.py: Use custom exceptions rather than Exception Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 07/15] qmp.py: Use object-based class for QEMUMonitorProtocol Eduardo Habkost
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

No actual code changes, just initializing attributes earlier to avoid
AttributeError on early introspection, a few pylint/style fixes and
docstring clarifications.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170818142613.32394-7-ldoktor@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qmp/qmp.py | 37 ++++++++++++++++++++++++-------------
 1 file changed, 24 insertions(+), 13 deletions(-)

diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py
index 62d3651967..782d1ac5df 100644
--- a/scripts/qmp/qmp.py
+++ b/scripts/qmp/qmp.py
@@ -13,19 +13,30 @@ import errno
 import socket
 import sys
 
+
 class QMPError(Exception):
     pass
 
+
 class QMPConnectError(QMPError):
     pass
 
+
 class QMPCapabilitiesError(QMPError):
     pass
 
+
 class QMPTimeoutError(QMPError):
     pass
 
+
 class QEMUMonitorProtocol:
+
+    #: Socket's error class
+    error = socket.error
+    #: Socket's timeout
+    timeout = socket.timeout
+
     def __init__(self, address, server=False, debug=False):
         """
         Create a QEMUMonitorProtocol class.
@@ -42,6 +53,7 @@ class QEMUMonitorProtocol:
         self.__address = address
         self._debug = debug
         self.__sock = self.__get_sock()
+        self.__sockfile = None
         if server:
             self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
             self.__sock.bind(self.__address)
@@ -56,7 +68,7 @@ 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')
@@ -78,8 +90,6 @@ class QEMUMonitorProtocol:
                     continue
             return resp
 
-    error = socket.error
-
     def __get_events(self, wait=False):
         """
         Check for new events in the stream and cache them in __events.
@@ -89,8 +99,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.
         """
 
         # Check for new events regardless and pull them into the cache:
@@ -175,7 +185,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:
@@ -183,6 +193,9 @@ class QEMUMonitorProtocol:
         return self.cmd_obj(qmp_cmd)
 
     def command(self, cmd, **kwds):
+        """
+        Build and send a QMP command to the monitor, report errors if any
+        """
         ret = self.cmd(cmd, kwds)
         if ret.has_key('error'):
             raise Exception(ret['error']['desc'])
@@ -190,15 +203,15 @@ class QEMUMonitorProtocol:
 
     def pull_event(self, wait=False):
         """
-        Get and delete the first available QMP event.
+        Pulls a single event.
 
         @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 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 +230,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.
         """
@@ -235,8 +248,6 @@ class QEMUMonitorProtocol:
         self.__sock.close()
         self.__sockfile.close()
 
-    timeout = socket.timeout
-
     def settimeout(self, timeout):
         self.__sock.settimeout(timeout)
 
-- 
2.13.5

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

* [Qemu-devel] [PULL 07/15] qmp.py: Use object-based class for QEMUMonitorProtocol
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (5 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 06/15] qmp.py: Couple of pylint/style fixes Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 08/15] qmp.py: Avoid "has_key" usage Eduardo Habkost
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

There is no need to define QEMUMonitorProtocol as old-style class.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20170818142613.32394-8-ldoktor@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qmp/qmp.py    | 2 +-
 scripts/qmp/qmp-shell | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py
index 782d1ac5df..95ff5cc39a 100644
--- a/scripts/qmp/qmp.py
+++ b/scripts/qmp/qmp.py
@@ -30,7 +30,7 @@ class QMPTimeoutError(QMPError):
     pass
 
 
-class QEMUMonitorProtocol:
+class QEMUMonitorProtocol(object):
 
     #: Socket's error class
     error = socket.error
diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell
index 860ffb27f2..be449de621 100755
--- a/scripts/qmp/qmp-shell
+++ b/scripts/qmp/qmp-shell
@@ -106,7 +106,7 @@ class FuzzyJSON(ast.NodeTransformer):
 #       _execute_cmd()). Let's design a better one.
 class QMPShell(qmp.QEMUMonitorProtocol):
     def __init__(self, address, pretty=False):
-        qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
+        super(QMPShell, self).__init__(self.__get_address(address))
         self._greeting = None
         self._completer = None
         self._pretty = pretty
@@ -281,7 +281,7 @@ class QMPShell(qmp.QEMUMonitorProtocol):
         return True
 
     def connect(self, negotiate):
-        self._greeting = qmp.QEMUMonitorProtocol.connect(self, negotiate)
+        self._greeting = super(QMPShell, self).connect(negotiate)
         self.__completer_setup()
 
     def show_banner(self, msg='Welcome to the QMP low-level shell!'):
-- 
2.13.5

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

* [Qemu-devel] [PULL 08/15] qmp.py: Avoid "has_key" usage
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (6 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 07/15] qmp.py: Use object-based class for QEMUMonitorProtocol Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 09/15] qmp.py: Avoid overriding a builtin object Eduardo Habkost
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

The "has_key" is deprecated in favor of "__in__" operator.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170818142613.32394-9-ldoktor@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qmp/qmp.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py
index 95ff5cc39a..f2f5a9b296 100644
--- a/scripts/qmp/qmp.py
+++ b/scripts/qmp/qmp.py
@@ -197,7 +197,7 @@ class QEMUMonitorProtocol(object):
         Build and send a QMP command to the monitor, report errors if any
         """
         ret = self.cmd(cmd, kwds)
-        if ret.has_key('error'):
+        if "error" in ret:
             raise Exception(ret['error']['desc'])
         return ret['return']
 
-- 
2.13.5

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

* [Qemu-devel] [PULL 09/15] qmp.py: Avoid overriding a builtin object
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (7 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 08/15] qmp.py: Avoid "has_key" usage Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 10/15] qtest.py: Few pylint/style fixes Eduardo Habkost
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

The "id" is a builtin method to get object's identity and should not be
overridden. This might bring some issues in case someone was directly
calling "cmd(..., id=id)" but I haven't found such usage on brief search
for "cmd\(.*id=".

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20170818142613.32394-10-ldoktor@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qmp/qmp.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/scripts/qmp/qmp.py b/scripts/qmp/qmp.py
index f2f5a9b296..ef12e8a1a0 100644
--- a/scripts/qmp/qmp.py
+++ b/scripts/qmp/qmp.py
@@ -177,19 +177,19 @@ class QEMUMonitorProtocol(object):
             print >>sys.stderr, "QMP:<<< %s" % resp
         return resp
 
-    def cmd(self, name, args=None, id=None):
+    def cmd(self, name, args=None, cmd_id=None):
         """
         Build a QMP command and send it to the QMP Monitor.
 
         @param name: command name (string)
         @param args: command arguments (dict)
-        @param id: command id (dict, list, string or int)
+        @param cmd_id: command id (dict, list, string or int)
         """
         qmp_cmd = {'execute': name}
         if args:
             qmp_cmd['arguments'] = args
-        if id:
-            qmp_cmd['id'] = id
+        if cmd_id:
+            qmp_cmd['id'] = cmd_id
         return self.cmd_obj(qmp_cmd)
 
     def command(self, cmd, **kwds):
-- 
2.13.5

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

* [Qemu-devel] [PULL 10/15] qtest.py: Few pylint/style fixes
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (8 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 09/15] qmp.py: Avoid overriding a builtin object Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 11/15] qemu.py: fix is_running() return before first launch() Eduardo Habkost
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Lukáš Doktor <ldoktor@redhat.com>

No actual code changes, just few pylint/style fixes.

Signed-off-by: Lukáš Doktor <ldoktor@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
Message-Id: <20170818142613.32394-11-ldoktor@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qtest.py | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/scripts/qtest.py b/scripts/qtest.py
index ab183c0635..df0daf26ca 100644
--- a/scripts/qtest.py
+++ b/scripts/qtest.py
@@ -11,14 +11,11 @@
 # Based on qmp.py.
 #
 
-import errno
 import socket
-import string
 import os
-import subprocess
-import qmp.qmp
 import qemu
 
+
 class QEMUQtestProtocol(object):
     def __init__(self, address, server=False):
         """
@@ -83,8 +80,10 @@ class QEMUQtestMachine(qemu.QEMUMachine):
                  socket_scm_helper=None):
         if name is None:
             name = "qemu-%d" % os.getpid()
-        super(QEMUQtestMachine, self).__init__(binary, args, name=name, test_dir=test_dir,
-                                               socket_scm_helper=socket_scm_helper)
+        super(QEMUQtestMachine,
+              self).__init__(binary, args, name=name, test_dir=test_dir,
+                             socket_scm_helper=socket_scm_helper)
+        self._qtest = None
         self._qtest_path = os.path.join(test_dir, name + "-qtest.sock")
 
     def _base_args(self):
-- 
2.13.5

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

* [Qemu-devel] [PULL 11/15] qemu.py: fix is_running() return before first launch()
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (9 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 10/15] qtest.py: Few pylint/style fixes Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 12/15] qemu.py: avoid writing to stdout/stderr Eduardo Habkost
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Amador Pahim <apahim@redhat.com>

is_running() returns None when called before the first time we
call launch():

    >>> import qemu
    >>> vm = qemu.QEMUMachine('qemu-system-x86_64')
    >>> vm.is_running()
    >>>

It should return False instead. This patch fixes that.

For consistence, this patch removes the parenthesis from the
second clause as it's not really needed.

Signed-off-by: Amador Pahim <apahim@redhat.com>
Message-Id: <20170901112829.2571-2-apahim@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index 7c6802609a..f80b008f7f 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -131,7 +131,7 @@ class QEMUMachine(object):
             raise
 
     def is_running(self):
-        return self._popen and (self._popen.returncode is None)
+        return self._popen is not None and self._popen.returncode is None
 
     def exitcode(self):
         if self._popen is None:
-- 
2.13.5

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

* [Qemu-devel] [PULL 12/15] qemu.py: avoid writing to stdout/stderr
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (10 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 11/15] qemu.py: fix is_running() return before first launch() Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 13/15] qemu.py: use os.path.null instead of /dev/null Eduardo Habkost
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Amador Pahim <apahim@redhat.com>

This module should not write directly to stdout/stderr. Instead, it
should either raise exceptions or just log the messages and let the
callers handle them and decide what to do. For example, scripts could
choose to send the log messages stderr or/and write them to a file if
verbose or debugging mode is enabled.

This patch replaces the writes to stderr by an exception in the
send_fd_scm() when _socket_scm_helper is not set or not present. In the
same method, the subprocess Popen will now redirect the stdout/stderr to
logging.debug instead of writing to system stderr. As consequence, since
the Popen.communicate() is now used (in order to get the stdout), the
further call to wait() became redundant and was replaced by
Popen.returncode.

The shutdown() message on negative exit code will now be logged
to logging.warn instead of written to system stderr.

Signed-off-by: Amador Pahim <apahim@redhat.com>
Message-Id: <20170901112829.2571-3-apahim@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index f80b008f7f..8d3d24dd2b 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -13,12 +13,22 @@
 #
 
 import errno
+import logging
 import os
 import sys
 import subprocess
 import qmp.qmp
 
 
+LOG = logging.getLogger(__name__)
+
+
+class QEMUMachineError(Exception):
+    """
+    Exception called when an error in QEMUMachine happens.
+    """
+
+
 class MonitorResponseError(qmp.qmp.QMPError):
     '''
     Represents erroneous QMP monitor reply
@@ -107,18 +117,21 @@ class QEMUMachine(object):
         # In iotest.py, the qmp should always use unix socket.
         assert self._qmp.is_scm_available()
         if self._socket_scm_helper is None:
-            print >>sys.stderr, "No path to socket_scm_helper set"
-            return -1
+            raise QEMUMachineError("No path to socket_scm_helper set")
         if not os.path.exists(self._socket_scm_helper):
-            print >>sys.stderr, "%s does not exist" % self._socket_scm_helper
-            return -1
+            raise QEMUMachineError("%s does not exist" %
+                                   self._socket_scm_helper)
         fd_param = ["%s" % self._socket_scm_helper,
                     "%d" % self._qmp.get_sock_fd(),
                     "%s" % fd_file_path]
         devnull = open('/dev/null', 'rb')
-        proc = subprocess.Popen(fd_param, stdin=devnull, stdout=sys.stdout,
-                                stderr=sys.stderr)
-        return proc.wait()
+        proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE,
+                                stderr=subprocess.STDOUT)
+        output = proc.communicate()[0]
+        if output:
+            LOG.debug(output)
+
+        return proc.returncode
 
     @staticmethod
     def _remove_if_exists(path):
@@ -202,8 +215,8 @@ class QEMUMachine(object):
 
             exitcode = self._popen.wait()
             if exitcode < 0:
-                sys.stderr.write('qemu received signal %i: %s\n'
-                                 % (-exitcode, ' '.join(self._args)))
+                LOG.warn('qemu received signal %i: %s', -exitcode,
+                          ' '.join(self._args))
             self._load_io_log()
             self._post_shutdown()
 
-- 
2.13.5

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

* [Qemu-devel] [PULL 13/15] qemu.py: use os.path.null instead of /dev/null
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (11 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 12/15] qemu.py: avoid writing to stdout/stderr Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-15 23:37 ` [Qemu-devel] [PULL 14/15] qemu.py: improve message on negative exit code Eduardo Habkost
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Amador Pahim <apahim@redhat.com>

For increased portability, let's use os.path.devnull.

Signed-off-by: Amador Pahim <apahim@redhat.com>
Message-Id: <20170901112829.2571-4-apahim@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index 8d3d24dd2b..c9bcaafe41 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -124,7 +124,7 @@ class QEMUMachine(object):
         fd_param = ["%s" % self._socket_scm_helper,
                     "%d" % self._qmp.get_sock_fd(),
                     "%s" % fd_file_path]
-        devnull = open('/dev/null', 'rb')
+        devnull = open(os.path.devnull, 'rb')
         proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
         output = proc.communicate()[0]
@@ -186,7 +186,7 @@ class QEMUMachine(object):
 
     def launch(self):
         '''Launch the VM and establish a QMP connection'''
-        devnull = open('/dev/null', 'rb')
+        devnull = open(os.path.devnull, 'rb')
         qemulog = open(self._qemu_log_path, 'wb')
         try:
             self._pre_launch()
-- 
2.13.5

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

* [Qemu-devel] [PULL 14/15] qemu.py: improve message on negative exit code
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (12 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 13/15] qemu.py: use os.path.null instead of /dev/null Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-18  9:44   ` Daniel P. Berrange
  2017-09-15 23:37 ` [Qemu-devel] [PULL 15/15] qemu.py: include debug information on launch error Eduardo Habkost
  2017-09-16 14:25 ` [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Peter Maydell
  15 siblings, 1 reply; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Amador Pahim <apahim@redhat.com>

The current message shows 'self._args', which contains only part of the
options used in the Qemu command line.

This patch makes the qemu full args list an instance variable and then
uses it in the negative exit code message.

Message was moved outside the 'if is_running' block to make sure it will
be logged if the VM finishes before the call to shutdown().

Signed-off-by: Amador Pahim <apahim@redhat.com>
Message-Id: <20170901112829.2571-5-apahim@redhat.com>
[ehabkost: removed superfluous parenthesis]
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index c9bcaafe41..9440261ac3 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -87,6 +87,7 @@ class QEMUMachine(object):
         self._socket_scm_helper = socket_scm_helper
         self._debug = debug
         self._qmp = None
+        self._qemu_full_args = None
 
     def __enter__(self):
         return self
@@ -186,13 +187,16 @@ class QEMUMachine(object):
 
     def launch(self):
         '''Launch the VM and establish a QMP connection'''
+        self._qemu_full_args = None
         devnull = open(os.path.devnull, 'rb')
         qemulog = open(self._qemu_log_path, 'wb')
         try:
             self._pre_launch()
-            args = (self._wrapper + [self._binary] + self._base_args() +
-                    self._args)
-            self._popen = subprocess.Popen(args, stdin=devnull, stdout=qemulog,
+            self._qemu_full_args = self._wrapper + [self._binary] +
+                                    self._base_args() + self._args
+            self._popen = subprocess.Popen(self._qemu_full_args,
+                                           stdin=devnull,
+                                           stdout=qemulog,
                                            stderr=subprocess.STDOUT,
                                            shell=False)
             self._post_launch()
@@ -212,14 +216,20 @@ class QEMUMachine(object):
                 self._qmp.close()
             except:
                 self._popen.kill()
+            self._popen.wait()
 
-            exitcode = self._popen.wait()
-            if exitcode < 0:
-                LOG.warn('qemu received signal %i: %s', -exitcode,
-                          ' '.join(self._args))
             self._load_io_log()
             self._post_shutdown()
 
+        exitcode = self.exitcode()
+        if exitcode is not None and exitcode < 0:
+            msg = 'qemu received signal %i: %s'
+            if self._qemu_full_args:
+                command = ' '.join(self._qemu_full_args)
+            else:
+                command = ''
+            LOG.warn(msg, exitcode, command)
+
     def qmp(self, cmd, conv_keys=True, **args):
         '''Invoke a QMP command and return the response dict'''
         qmp_args = dict()
-- 
2.13.5

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

* [Qemu-devel] [PULL 15/15] qemu.py: include debug information on launch error
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (13 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 14/15] qemu.py: improve message on negative exit code Eduardo Habkost
@ 2017-09-15 23:37 ` Eduardo Habkost
  2017-09-16 14:25 ` [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Peter Maydell
  15 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-15 23:37 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Lukáš Doktor, Stefan Hajnoczi, Amador Pahim

From: Amador Pahim <apahim@redhat.com>

When launching a VM, if an exception happens and the VM is not
initiated, it might be useful to see the qemu command line and
the qemu command output.

This patch creates that message. Notice that self._iolog needs to be
cleaned up in the beginning of the launch() to make sure we will not
expose the qemu log from a previous launch if the current one fails.

Signed-off-by: Amador Pahim <apahim@redhat.com>
Message-Id: <20170901112829.2571-6-apahim@redhat.com>
Reviewed-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 scripts/qemu.py | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/scripts/qemu.py b/scripts/qemu.py
index 9440261ac3..8c67595ec8 100644
--- a/scripts/qemu.py
+++ b/scripts/qemu.py
@@ -187,6 +187,7 @@ class QEMUMachine(object):
 
     def launch(self):
         '''Launch the VM and establish a QMP connection'''
+        self._iolog = None
         self._qemu_full_args = None
         devnull = open(os.path.devnull, 'rb')
         qemulog = open(self._qemu_log_path, 'wb')
@@ -206,6 +207,12 @@ class QEMUMachine(object):
                 self._popen.wait()
             self._load_io_log()
             self._post_shutdown()
+
+            LOG.debug('Error launching VM')
+            if self._qemu_full_args:
+                LOG.debug('Command: %r', ' '.join(self._qemu_full_args))
+            if self._iolog:
+                LOG.debug('Output: %r', self._iolog)
             raise
 
     def shutdown(self):
-- 
2.13.5

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

* Re: [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15
  2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
                   ` (14 preceding siblings ...)
  2017-09-15 23:37 ` [Qemu-devel] [PULL 15/15] qemu.py: include debug information on launch error Eduardo Habkost
@ 2017-09-16 14:25 ` Peter Maydell
  15 siblings, 0 replies; 19+ messages in thread
From: Peter Maydell @ 2017-09-16 14:25 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: QEMU Developers, Lukáš Doktor, Stefan Hajnoczi,
	Amador Pahim

On 16 September 2017 at 00:37, Eduardo Habkost <ehabkost@redhat.com> wrote:
> I have been queueing some patches for Python modules and scripts,
> recently, and submitted a MAINTAINERS patch to include Cleber and
> me as maintainers.
>
> However, I don't want to delay this pull request to avoid
> conflicts if people send additional patches for those scripts, so
> I'm sending this pull request before the MAINTAINERS patch is
> applied.
>
> The following changes since commit 5faf2d376af3cb4eb92da44c2580e08d39832caa:
>
>   Merge remote-tracking branch 'remotes/huth/tags/check-20170915' into staging (2017-09-15 20:29:44 +0100)
>
> are available in the git repository at:
>
>   git://github.com/ehabkost/qemu.git tags/python-next-pull-request
>
> for you to fetch changes up to b92a0011b1220aff549ae82c6104014d25e339ef:
>
>   qemu.py: include debug information on launch error (2017-09-15 20:12:00 -0300)
>
> ----------------------------------------------------------------
> Python queue, 2017-09-15
>

Applied, thanks.

-- PMM

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

* Re: [Qemu-devel] [PULL 14/15] qemu.py: improve message on negative exit code
  2017-09-15 23:37 ` [Qemu-devel] [PULL 14/15] qemu.py: improve message on negative exit code Eduardo Habkost
@ 2017-09-18  9:44   ` Daniel P. Berrange
  2017-09-18 11:46     ` Eduardo Habkost
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2017-09-18  9:44 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Peter Maydell, qemu-devel, Lukáš Doktor, Amador Pahim,
	Stefan Hajnoczi

On Fri, Sep 15, 2017 at 08:37:38PM -0300, Eduardo Habkost wrote:
> From: Amador Pahim <apahim@redhat.com>
> 
> The current message shows 'self._args', which contains only part of the
> options used in the Qemu command line.
> 
> This patch makes the qemu full args list an instance variable and then
> uses it in the negative exit code message.
> 
> Message was moved outside the 'if is_running' block to make sure it will
> be logged if the VM finishes before the call to shutdown().
> 
> Signed-off-by: Amador Pahim <apahim@redhat.com>
> Message-Id: <20170901112829.2571-5-apahim@redhat.com>
> [ehabkost: removed superfluous parenthesis]
> Reviewed-by: Fam Zheng <famz@redhat.com>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
>  scripts/qemu.py | 24 +++++++++++++++++-------
>  1 file changed, 17 insertions(+), 7 deletions(-)
> 
> diff --git a/scripts/qemu.py b/scripts/qemu.py
> index c9bcaafe41..9440261ac3 100644
> --- a/scripts/qemu.py
> +++ b/scripts/qemu.py
> @@ -87,6 +87,7 @@ class QEMUMachine(object):
>          self._socket_scm_helper = socket_scm_helper
>          self._debug = debug
>          self._qmp = None
> +        self._qemu_full_args = None
>  
>      def __enter__(self):
>          return self
> @@ -186,13 +187,16 @@ class QEMUMachine(object):
>  
>      def launch(self):
>          '''Launch the VM and establish a QMP connection'''
> +        self._qemu_full_args = None
>          devnull = open(os.path.devnull, 'rb')
>          qemulog = open(self._qemu_log_path, 'wb')
>          try:
>              self._pre_launch()
> -            args = (self._wrapper + [self._binary] + self._base_args() +
> -                    self._args)
> -            self._popen = subprocess.Popen(args, stdin=devnull, stdout=qemulog,
> +            self._qemu_full_args = self._wrapper + [self._binary] +
> +                                    self._base_args() + self._args

FYI, this change causes a syntax error because you need either the ()
brackets, or an explicit \ continuation. Unfortunately this wasn't
caught by Peter's merge tests, since this code is only execised by
the qemu iotests which aren't run from a 'make check'.

If someone has cycles, it would be great to write some unit tests
directly targetting the qemu.py and qmp.py code, so that we get test
coverage of it independantly of the iotest execution.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

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

* Re: [Qemu-devel] [PULL 14/15] qemu.py: improve message on negative exit code
  2017-09-18  9:44   ` Daniel P. Berrange
@ 2017-09-18 11:46     ` Eduardo Habkost
  0 siblings, 0 replies; 19+ messages in thread
From: Eduardo Habkost @ 2017-09-18 11:46 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: Peter Maydell, qemu-devel, Lukáš Doktor, Amador Pahim,
	Stefan Hajnoczi

On Mon, Sep 18, 2017 at 10:44:00AM +0100, Daniel P. Berrange wrote:
> On Fri, Sep 15, 2017 at 08:37:38PM -0300, Eduardo Habkost wrote:
> > From: Amador Pahim <apahim@redhat.com>
> > 
> > The current message shows 'self._args', which contains only part of the
> > options used in the Qemu command line.
> > 
> > This patch makes the qemu full args list an instance variable and then
> > uses it in the negative exit code message.
> > 
> > Message was moved outside the 'if is_running' block to make sure it will
> > be logged if the VM finishes before the call to shutdown().
> > 
> > Signed-off-by: Amador Pahim <apahim@redhat.com>
> > Message-Id: <20170901112829.2571-5-apahim@redhat.com>
> > [ehabkost: removed superfluous parenthesis]
> > Reviewed-by: Fam Zheng <famz@redhat.com>
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> >  scripts/qemu.py | 24 +++++++++++++++++-------
> >  1 file changed, 17 insertions(+), 7 deletions(-)
> > 
> > diff --git a/scripts/qemu.py b/scripts/qemu.py
> > index c9bcaafe41..9440261ac3 100644
> > --- a/scripts/qemu.py
> > +++ b/scripts/qemu.py
> > @@ -87,6 +87,7 @@ class QEMUMachine(object):
> >          self._socket_scm_helper = socket_scm_helper
> >          self._debug = debug
> >          self._qmp = None
> > +        self._qemu_full_args = None
> >  
> >      def __enter__(self):
> >          return self
> > @@ -186,13 +187,16 @@ class QEMUMachine(object):
> >  
> >      def launch(self):
> >          '''Launch the VM and establish a QMP connection'''
> > +        self._qemu_full_args = None
> >          devnull = open(os.path.devnull, 'rb')
> >          qemulog = open(self._qemu_log_path, 'wb')
> >          try:
> >              self._pre_launch()
> > -            args = (self._wrapper + [self._binary] + self._base_args() +
> > -                    self._args)
> > -            self._popen = subprocess.Popen(args, stdin=devnull, stdout=qemulog,
> > +            self._qemu_full_args = self._wrapper + [self._binary] +
> > +                                    self._base_args() + self._args
> 
> FYI, this change causes a syntax error because you need either the ()
> brackets, or an explicit \ continuation. Unfortunately this wasn't
> caught by Peter's merge tests, since this code is only execised by
> the qemu iotests which aren't run from a 'make check'.
> 
> If someone has cycles, it would be great to write some unit tests
> directly targetting the qemu.py and qmp.py code, so that we get test
> coverage of it independantly of the iotest execution.

Oops, sorry!  I thought "make check" was exercising that code
path.

-- 
Eduardo

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

end of thread, other threads:[~2017-09-18 11:46 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-15 23:37 [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 01/15] qemu.py: Pylint/style fixes Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 02/15] qemu|qtest: Avoid dangerous arguments Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 03/15] qemu.py: Use iteritems rather than keys() Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 04/15] qemu.py: Simplify QMP key-conversion Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 05/15] qemu.py: Use custom exceptions rather than Exception Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 06/15] qmp.py: Couple of pylint/style fixes Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 07/15] qmp.py: Use object-based class for QEMUMonitorProtocol Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 08/15] qmp.py: Avoid "has_key" usage Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 09/15] qmp.py: Avoid overriding a builtin object Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 10/15] qtest.py: Few pylint/style fixes Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 11/15] qemu.py: fix is_running() return before first launch() Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 12/15] qemu.py: avoid writing to stdout/stderr Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 13/15] qemu.py: use os.path.null instead of /dev/null Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 14/15] qemu.py: improve message on negative exit code Eduardo Habkost
2017-09-18  9:44   ` Daniel P. Berrange
2017-09-18 11:46     ` Eduardo Habkost
2017-09-15 23:37 ` [Qemu-devel] [PULL 15/15] qemu.py: include debug information on launch error Eduardo Habkost
2017-09-16 14:25 ` [Qemu-devel] [PULL 00/15] Python queue, 2017-09-15 Peter Maydell

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).