All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Kevin Wolf" <kwolf@redhat.com>,
	"Michael Roth" <michael.roth@amd.com>,
	"John Snow" <jsnow@redhat.com>, "Hanna Reitz" <hreitz@redhat.com>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	"Cleber Rosa" <crosa@redhat.com>,
	qemu-block@nongnu.org, "Markus Armbruster" <armbru@redhat.com>,
	"Adam Dorsey" <adam.dorsey@twosixtech.com>,
	"Adam Dorsey" <adam@dorseys.email>,
	"Daniel P. Berrangé" <berrange@redhat.com>
Subject: [PULL 08/19] python: backport 'feat: allow setting read buffer limit'
Date: Tue, 16 Sep 2025 12:23:53 -0400	[thread overview]
Message-ID: <20250916162404.9195-9-jsnow@redhat.com> (raw)
In-Reply-To: <20250916162404.9195-1-jsnow@redhat.com>

From: Adam Dorsey <adam.dorsey@twosixtech.com>

Expose the limit parameter of the underlying StreamReader and StreamWriter
instances.

This is helpful for the use case of transferring files in and out of a VM
via the QEMU guest agent's guest-file-open, guest-file-read, guest-file-write,
and guest-file-close methods, as it allows pushing the buffer size up to the
guest agent's limit of 48MB per transfer.

Signed-off-by: Adam Dorsey <adam@dorseys.email>
cherry picked from commit python-qemu-qmp@9ba6a698344eb3b570fa4864e906c54042824cd6
cherry picked from commit python-qemu-qmp@e4d0d3f835d82283ee0e48438d1b154e18303491
[Squashed in linter fixups. --js]
Signed-off-by: John Snow <jsnow@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 python/qemu/qmp/protocol.py   | 25 ++++++++++++++++---------
 python/qemu/qmp/qmp_client.py | 18 ++++++++++++++----
 2 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/python/qemu/qmp/protocol.py b/python/qemu/qmp/protocol.py
index 958aeca08ac..3d5eb553aad 100644
--- a/python/qemu/qmp/protocol.py
+++ b/python/qemu/qmp/protocol.py
@@ -53,6 +53,9 @@
 UnixAddrT = str
 SocketAddrT = Union[UnixAddrT, InternetAddrT]
 
+# Maximum allowable size of read buffer, default
+_DEFAULT_READBUFLEN = 64 * 1024
+
 
 class Runstate(Enum):
     """Protocol session runstate."""
@@ -202,22 +205,26 @@ class AsyncProtocol(Generic[T]):
         will log to 'qemu.qmp.protocol', but each individual connection
         can be given its own logger by giving it a name; messages will
         then log to 'qemu.qmp.protocol.${name}'.
+    :param readbuflen:
+        The maximum read buffer length of the underlying StreamReader
+        instance.
     """
     # pylint: disable=too-many-instance-attributes
 
     #: Logger object for debugging messages from this connection.
     logger = logging.getLogger(__name__)
 
-    # Maximum allowable size of read buffer
-    _limit = 64 * 1024
-
     # -------------------------
     # Section: Public interface
     # -------------------------
 
-    def __init__(self, name: Optional[str] = None) -> None:
+    def __init__(
+        self, name: Optional[str] = None,
+        readbuflen: int = _DEFAULT_READBUFLEN
+    ) -> None:
         self._name: Optional[str]
         self.name = name
+        self.readbuflen = readbuflen
 
         # stream I/O
         self._reader: Optional[StreamReader] = None
@@ -574,7 +581,7 @@ async def _do_start_server(self, address: SocketAddrT,
                 port=address[1],
                 ssl=ssl,
                 backlog=1,
-                limit=self._limit,
+                limit=self.readbuflen,
             )
         else:
             coro = asyncio.start_unix_server(
@@ -582,7 +589,7 @@ async def _do_start_server(self, address: SocketAddrT,
                 path=address,
                 ssl=ssl,
                 backlog=1,
-                limit=self._limit,
+                limit=self.readbuflen,
             )
 
         # Allow runstate watchers to witness 'CONNECTING' state; some
@@ -637,7 +644,7 @@ async def _do_connect(self, address: Union[SocketAddrT, socket.socket],
                               "fd=%d, family=%r, type=%r",
                               address.fileno(), address.family, address.type)
             connect = asyncio.open_connection(
-                limit=self._limit,
+                limit=self.readbuflen,
                 ssl=ssl,
                 sock=address,
             )
@@ -647,14 +654,14 @@ async def _do_connect(self, address: Union[SocketAddrT, socket.socket],
                 address[0],
                 address[1],
                 ssl=ssl,
-                limit=self._limit,
+                limit=self.readbuflen,
             )
         else:
             self.logger.debug("Connecting to file://%s ...", address)
             connect = asyncio.open_unix_connection(
                 path=address,
                 ssl=ssl,
-                limit=self._limit,
+                limit=self.readbuflen,
             )
 
         self._reader, self._writer = await connect
diff --git a/python/qemu/qmp/qmp_client.py b/python/qemu/qmp/qmp_client.py
index a87fb565ab5..d826331b6d5 100644
--- a/python/qemu/qmp/qmp_client.py
+++ b/python/qemu/qmp/qmp_client.py
@@ -170,6 +170,12 @@ class QMPClient(AsyncProtocol[Message], Events):
 
     :param name: Optional nickname for the connection, used for logging.
 
+    :param readbuflen:
+        The maximum buffer length for reads and writes to and from the QMP
+        server, in bytes. Default is 10MB. If `QMPClient` is used to
+        connect to a guest agent to transfer files via ``guest-file-read``/
+        ``guest-file-write``, increasing this value may be required.
+
     Basic script-style usage looks like this::
 
       qmp = QMPClient('my_virtual_machine_name')
@@ -203,14 +209,18 @@ async def run(self, address='/tmp/qemu.socket'):
     #: Logger object used for debugging messages.
     logger = logging.getLogger(__name__)
 
-    # Read buffer limit; 10MB like libvirt default
-    _limit = 10 * 1024 * 1024
+    # Read buffer default limit; 10MB like libvirt default
+    _readbuflen = 10 * 1024 * 1024
 
     # Type alias for pending execute() result items
     _PendingT = Union[Message, ExecInterruptedError]
 
-    def __init__(self, name: Optional[str] = None) -> None:
-        super().__init__(name)
+    def __init__(
+        self,
+        name: Optional[str] = None,
+        readbuflen: int = _readbuflen
+    ) -> None:
+        super().__init__(name, readbuflen)
         Events.__init__(self)
 
         #: Whether or not to await a greeting after establishing a connection.
-- 
2.51.0



  parent reply	other threads:[~2025-09-16 16:27 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-16 16:23 [PULL 00/19] Python patches John Snow
2025-09-16 16:23 ` [PULL 01/19] python: backport 'Change error classes to have better repr methods' John Snow
2025-09-16 16:23 ` [PULL 02/19] python: backport 'EventListener: add __repr__ method' John Snow
2025-09-16 16:23 ` [PULL 03/19] python: backport 'kick event queue on legacy event_pull()' John Snow
2025-09-16 16:23 ` [PULL 04/19] python: backport 'protocol: adjust logging name when changing client name' John Snow
2025-10-15  7:11   ` Thomas Huth
2025-10-22  0:37     ` John Snow
2025-09-16 16:23 ` [PULL 05/19] python: backport 'drop Python3.6 workarounds' John Snow
2025-09-16 16:23 ` [PULL 06/19] python: backport 'Use @asynciocontextmanager' John Snow
2025-09-16 16:23 ` [PULL 07/19] python: backport 'qmp-shell: add common_parser()' John Snow
2025-09-16 16:23 ` John Snow [this message]
2025-09-16 16:23 ` [PULL 09/19] python: backport 'make require() preserve async-ness' John Snow
2025-09-16 16:23 ` [PULL 10/19] python: backport 'qmp-shell-wrap: handle missing binary gracefully' John Snow
2025-09-16 16:23 ` [PULL 11/19] python: backport 'qmp-tui: Do not crash if optional dependencies are not met' John Snow
2025-09-16 16:23 ` [PULL 12/19] python: backport 'Remove deprecated get_event_loop calls' John Snow
2025-09-16 16:23 ` [PULL 13/19] python: backport 'avoid creating additional event loops per thread' John Snow
2025-09-16 16:23 ` [PULL 14/19] python: synchronize qemu.qmp documentation John Snow
2025-09-16 16:24 ` [PULL 15/19] iotests: drop compat for old version context manager John Snow
2025-09-16 16:24 ` [PULL 16/19] python: ensure QEMUQtestProtocol closes its socket John Snow
2025-09-16 16:24 ` [PULL 17/19] iotests/147: ensure temporary sockets are closed before exiting John Snow
2025-09-16 16:24 ` [PULL 18/19] iotests/151: ensure subprocesses are cleaned up John Snow
2025-09-16 16:24 ` [PULL 19/19] iotests/check: always enable all python warnings John Snow
2025-09-16 18:20 ` [PULL 00/19] Python patches John Snow
2025-09-16 19:22 ` Richard Henderson

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=20250916162404.9195-9-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=adam.dorsey@twosixtech.com \
    --cc=adam@dorseys.email \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=crosa@redhat.com \
    --cc=hreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=michael.roth@amd.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.