@@ -604,6 +604,55 @@ class QMPMonitor(Monitor):
return self._greeting
+ def send(self, data, timeout=20):
+ """
+ Send data to the QMP monitor and return its response.
+
+ @param data: Data to send
+ @param timeout: Time duration to wait for response
+ @return: The response received
+ @raise MonitorLockError: Raised if the lock cannot be acquired
+ @raise MonitorSendError: Raised if the command cannot be sent
+ @raise MonitorProtocolError: Raised if no response is received
+ """
+ if not self._acquire_lock(20):
+ raise MonitorLockError("Could not acquire exclusive lock to send "
+ "QMP command '%s'" % cmd)
+ try:
+ self._read_objects()
+ self._socket.sendall(data)
+ end_time = time.time() + timeout
+ while time.time() < end_time:
+ for obj in self._read_objects():
+ if isinstance(obj, dict):
+ if "return" in obj or "error" in obj:
+ return obj
+ time.sleep(0.1)
+ else:
+ raise MonitorProtocolError("Received no response (data: %s)"
+ % str(data))
+ except socket.error:
+ raise MonitorSendError("Could not send data '%s'" % str(data))
+ finally:
+ self._lock.release()
+
+
+ def send_cmd(self, command, timeout=20):
+ """
+ Send a QMP command. This is a simple wrapper to send() method that does
+ JSON formatting.
+
+ @param command: QMP command to send
+ @param timeout: Time duration to wait for response
+ @return: The response received
+ @raise MonitorLockError: Raised if the lock cannot be acquired
+ @raise MonitorSendError: Raised if the command cannot be sent
+ @raise MonitorProtocolError: Raised if no response is received
+
+ """
+ return self.send(json.dumps(command) + "\n", timeout)
+
+
# Command wrappers
# Note: all of the following functions raise exceptions in a similar manner
# to cmd() and _get_command_output().