[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol
From: |
Luiz Capitulino |
Subject: |
Re: [Qemu-devel] [PATCH 2/2] QMP: add server mode to QEMUMonitorProtocol |
Date: |
Wed, 25 May 2011 18:16:07 -0300 |
On Wed, 25 May 2011 19:48:01 +0100
Stefan Hajnoczi <address@hidden> 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 <address@hidden>
> ---
> 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):
> """