- kvm-blkdebug-Add-delay-ns-option.patch [RHEL-121686] - kvm-block-Add-blk_co_start-end_request-and-BDRV_REQ_NO_Q.patch [RHEL-121686] - kvm-block-Add-flags-parameter-to-blk_-_pdiscard.patch [RHEL-121686] - kvm-ide-Minimal-fix-for-deadlock-between-TRIM-and-drain.patch [RHEL-121686] - kvm-ide-Clean-up-ide_trim_co_entry-to-be-idiomatic-corou.patch [RHEL-121686] - kvm-ide-test-Factor-out-wait_dma_completion.patch [RHEL-121686] - kvm-ide-test-Test-reset-during-TRIM.patch [RHEL-121686] - kvm-block-graph-lock-fix-missed-wakeup-in-bdrv_graph_co_.patch [RHEL-186384] - kvm-block-curl-fix-curl-internal-handles-handling.patch [RHEL-186384] - kvm-block-curl.c-Use-explicit-long-constants-in-curl_eas.patch [RHEL-186384] - kvm-block-curl.c-Fix-CURLOPT_VERBOSE-parameter-type.patch [RHEL-186384] - kvm-block-curl-fix-concurrent-completion-handling.patch [RHEL-186384] - kvm-block-curl-free-s-password-in-cleanup-paths.patch [RHEL-186384] - kvm-nvme-Kick-and-check-completions-in-BDS-context.patch [RHEL-186384] - kvm-nvme-Note-in-which-AioContext-some-functions-run.patch [RHEL-186384] - kvm-block-remove-detached-header-option-from-opts-after-.patch [RHEL-186384] - kvm-block-fix-luks-amend-when-run-in-coroutine.patch [RHEL-186384] - kvm-qed-Don-t-try-to-flush-during-incoming-migration.patch [RHEL-186384] - kvm-block-vmdk-fix-OOB-read-in-vmdk_read_extent.patch [RHEL-186384] - kvm-block-throttle-groups-fix-deadlock-with-iolimits-and.patch [RHEL-186384] - kvm-throttle-group-Fix-race-condition-in-throttle_group_.patch [RHEL-186384] - kvm-qemu-img-Fix-amend-option-parse-error-handling.patch [RHEL-186384] - kvm-qemu-img-rebase-don-t-exceed-IO_BUF_SIZE-in-one-oper.patch [RHEL-186384] - kvm-python-backport-drop-Python3.6-workarounds.patch [RHEL-186384] - kvm-python-backport-Remove-deprecated-get_event_loop-cal.patch [RHEL-186384] - kvm-python-backport-avoid-creating-additional-event-loop.patch [RHEL-186384] - kvm-iotests-147-ensure-temporary-sockets-are-closed-befo.patch [RHEL-186384] - kvm-iotests-151-ensure-subprocesses-are-cleaned-up.patch [RHEL-186384] - kvm-tests-qemu-iotest-fix-iotest-024-with-qed-images.patch [RHEL-186384] - kvm-tests-qemu-iotests-Fix-check-for-existing-file-in-_r.patch [RHEL-186384] - kvm-async-access-bottom-half-flags-with-qatomic_read.patch [RHEL-186384] - kvm-block-linux-aio-bound-ioq_submit-recursion-depth.patch [RHEL-186384] - kvm-block-io-fallback-to-bounce-buffer-if-BLKZEROOUT-is-.patch [RHEL-186384] - kvm-file-posix-populate-pwrite_zeroes_alignment.patch [RHEL-186384] - kvm-block-use-pwrite_zeroes_alignment-when-writing-first.patch [RHEL-186384] - kvm-iotests-add-Linux-loop-device-image-creation-test.patch [RHEL-186384] - kvm-virtio-Fix-crash-when-sriov-pf-is-set-for-non-PCI-Ex.patch [RHEL-186384] - kvm-virtio-scsi-pass-the-same-cdb_size-to-virtio_scsi_po.patch [RHEL-186384] - kvm-hw-scsi-avoid-deadlock-upon-TMF-request-cancelling-w.patch [RHEL-186384] - kvm-virtio-blk-fix-zone-report-buffer-out-of-memory-CVE-.patch [RHEL-186384] - kvm-ide-Fix-potential-assertion-failure-on-VM-stop-for-P.patch [RHEL-186384] - kvm-block-Create-DEFAULT_BLOCK_CONF-macro.patch [RHEL-186384] - kvm-block-Add-more-defaults-to-DEFAULT_BLOCK_CONF.patch [RHEL-186384] - kvm-block-mirror-check-range-when-setting-zero-bitmap-fo.patch [RHEL-186384] - kvm-iotests-test-active-mirror-with-unaligned-small-writ.patch [RHEL-186384] - kvm-block-mirror-fix-assertion-failure-upon-duplicate-co.patch [RHEL-186384] - kvm-commit-Drain-nodes-across-all-of-bdrv_commit.patch [RHEL-186384] - kvm-qemu-io-Add-aio_discard-command.patch [RHEL-186384] - kvm-qcow2-Fix-corruption-on-discard-during-write-with-CO.patch [RHEL-186384] - kvm-iotests-046-Test-that-discard-write_zeroes-wait-for-.patch [RHEL-186384] - kvm-qcow2-Fix-data-loss-on-zero-write-with-detect-zeroes.patch [RHEL-186384] - kvm-block-Fix-crash-after-setting-latency-historygram-wi.patch [RHEL-186384] - Resolves: RHEL-121686 (qemu-kvm hung during drain after double pause) - Resolves: RHEL-186384 (virt-storage: Backport stable branch fixes)
301 lines
10 KiB
Diff
301 lines
10 KiB
Diff
From 5de86fbbb5f6c0353bd2668c0424da28bf786264 Mon Sep 17 00:00:00 2001
|
|
From: John Snow <jsnow@redhat.com>
|
|
Date: Tue, 6 Jun 2023 13:19:11 -0400
|
|
Subject: [PATCH 24/52] python: backport 'drop Python3.6 workarounds'
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
RH-MergeRequest: 504: virt-storage: Backport stable branch fixes
|
|
RH-Jira: RHEL-186384
|
|
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
RH-Commit: [17/45] 65ffd438927850c395611deb3821d01b71d3c2c1 (kmwolf/centos-qemu-kvm)
|
|
|
|
Now that the minimum version is 3.7, drop some of the 3.6-specific hacks
|
|
we've been carrying. A single remaining compatibility hack concerning
|
|
3.6's lack of @asynccontextmanager is addressed in the following commit.
|
|
|
|
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
cherry picked from commit python-qemu-qmp@3e8e34e594cfc6b707e6f67959166acde4b421b8
|
|
Signed-off-by: John Snow <jsnow@redhat.com>
|
|
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
|
(cherry picked from commit f9d2e0a3bd7ba2a693a892881f91cf53fa90cc71)
|
|
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
---
|
|
python/qemu/qmp/protocol.py | 13 ++---
|
|
python/qemu/qmp/qmp_tui.py | 8 +--
|
|
python/qemu/qmp/util.py | 107 ++----------------------------------
|
|
python/tests/protocol.py | 8 +--
|
|
4 files changed, 17 insertions(+), 119 deletions(-)
|
|
|
|
diff --git a/python/qemu/qmp/protocol.py b/python/qemu/qmp/protocol.py
|
|
index a4ffdfad51..4aff0ea423 100644
|
|
--- a/python/qemu/qmp/protocol.py
|
|
+++ b/python/qemu/qmp/protocol.py
|
|
@@ -36,13 +36,10 @@
|
|
from .error import QMPError
|
|
from .util import (
|
|
bottom_half,
|
|
- create_task,
|
|
exception_summary,
|
|
flush,
|
|
- is_closing,
|
|
pretty_traceback,
|
|
upper_half,
|
|
- wait_closed,
|
|
)
|
|
|
|
|
|
@@ -663,8 +660,8 @@ async def _establish_session(self) -> None:
|
|
reader_coro = self._bh_loop_forever(self._bh_recv_message, 'Reader')
|
|
writer_coro = self._bh_loop_forever(self._bh_send_message, 'Writer')
|
|
|
|
- self._reader_task = create_task(reader_coro)
|
|
- self._writer_task = create_task(writer_coro)
|
|
+ self._reader_task = asyncio.create_task(reader_coro)
|
|
+ self._writer_task = asyncio.create_task(writer_coro)
|
|
|
|
self._bh_tasks = asyncio.gather(
|
|
self._reader_task,
|
|
@@ -689,7 +686,7 @@ def _schedule_disconnect(self) -> None:
|
|
if not self._dc_task:
|
|
self._set_state(Runstate.DISCONNECTING)
|
|
self.logger.debug("Scheduling disconnect.")
|
|
- self._dc_task = create_task(self._bh_disconnect())
|
|
+ self._dc_task = asyncio.create_task(self._bh_disconnect())
|
|
|
|
@upper_half
|
|
async def _wait_disconnect(self) -> None:
|
|
@@ -825,13 +822,13 @@ async def _bh_close_stream(self, error_pathway: bool = False) -> None:
|
|
if not self._writer:
|
|
return
|
|
|
|
- if not is_closing(self._writer):
|
|
+ if not self._writer.is_closing():
|
|
self.logger.debug("Closing StreamWriter.")
|
|
self._writer.close()
|
|
|
|
self.logger.debug("Waiting for StreamWriter to close ...")
|
|
try:
|
|
- await wait_closed(self._writer)
|
|
+ await self._writer.wait_closed()
|
|
except Exception: # pylint: disable=broad-except
|
|
# It's hard to tell if the Stream is already closed or
|
|
# not. Even if one of the tasks has failed, it may have
|
|
diff --git a/python/qemu/qmp/qmp_tui.py b/python/qemu/qmp/qmp_tui.py
|
|
index 2d9ebbd20b..562be008d5 100644
|
|
--- a/python/qemu/qmp/qmp_tui.py
|
|
+++ b/python/qemu/qmp/qmp_tui.py
|
|
@@ -40,7 +40,7 @@
|
|
from .message import DeserializationError, Message, UnexpectedTypeError
|
|
from .protocol import ConnectError, Runstate
|
|
from .qmp_client import ExecInterruptedError, QMPClient
|
|
-from .util import create_task, pretty_traceback
|
|
+from .util import pretty_traceback
|
|
|
|
|
|
# The name of the signal that is used to update the history list
|
|
@@ -225,7 +225,7 @@ def cb_send_to_server(self, raw_msg: str) -> None:
|
|
"""
|
|
try:
|
|
msg = Message(bytes(raw_msg, encoding='utf-8'))
|
|
- create_task(self._send_to_server(msg))
|
|
+ asyncio.create_task(self._send_to_server(msg))
|
|
except (DeserializationError, UnexpectedTypeError) as err:
|
|
raw_msg = format_json(raw_msg)
|
|
logging.info('Invalid message: %s', err.error_message)
|
|
@@ -246,7 +246,7 @@ def kill_app(self) -> None:
|
|
Initiates killing of app. A bridge between asynchronous and synchronous
|
|
code.
|
|
"""
|
|
- create_task(self._kill_app())
|
|
+ asyncio.create_task(self._kill_app())
|
|
|
|
async def _kill_app(self) -> None:
|
|
"""
|
|
@@ -393,7 +393,7 @@ def run(self, debug: bool = False) -> None:
|
|
handle_mouse=True,
|
|
event_loop=event_loop)
|
|
|
|
- create_task(self.manage_connection(), self.aloop)
|
|
+ self.aloop.create_task(self.manage_connection())
|
|
try:
|
|
main_loop.run()
|
|
except Exception as err:
|
|
diff --git a/python/qemu/qmp/util.py b/python/qemu/qmp/util.py
|
|
index ca6225e9cd..0b3e781373 100644
|
|
--- a/python/qemu/qmp/util.py
|
|
+++ b/python/qemu/qmp/util.py
|
|
@@ -1,25 +1,15 @@
|
|
"""
|
|
Miscellaneous Utilities
|
|
|
|
-This module provides asyncio utilities and compatibility wrappers for
|
|
-Python 3.6 to provide some features that otherwise become available in
|
|
-Python 3.7+.
|
|
-
|
|
-Various logging and debugging utilities are also provided, such as
|
|
-`exception_summary()` and `pretty_traceback()`, used primarily for
|
|
-adding information into the logging stream.
|
|
+This module provides asyncio and various logging and debugging
|
|
+utilities, such as `exception_summary()` and `pretty_traceback()`, used
|
|
+primarily for adding information into the logging stream.
|
|
"""
|
|
|
|
import asyncio
|
|
import sys
|
|
import traceback
|
|
-from typing import (
|
|
- Any,
|
|
- Coroutine,
|
|
- Optional,
|
|
- TypeVar,
|
|
- cast,
|
|
-)
|
|
+from typing import TypeVar, cast
|
|
|
|
|
|
T = TypeVar('T')
|
|
@@ -79,95 +69,6 @@ def bottom_half(func: T) -> T:
|
|
return func
|
|
|
|
|
|
-# -------------------------------
|
|
-# Section: Compatibility Wrappers
|
|
-# -------------------------------
|
|
-
|
|
-
|
|
-def create_task(coro: Coroutine[Any, Any, T],
|
|
- loop: Optional[asyncio.AbstractEventLoop] = None
|
|
- ) -> 'asyncio.Future[T]':
|
|
- """
|
|
- Python 3.6-compatible `asyncio.create_task` wrapper.
|
|
-
|
|
- :param coro: The coroutine to execute in a task.
|
|
- :param loop: Optionally, the loop to create the task in.
|
|
-
|
|
- :return: An `asyncio.Future` object.
|
|
- """
|
|
- if sys.version_info >= (3, 7):
|
|
- if loop is not None:
|
|
- return loop.create_task(coro)
|
|
- return asyncio.create_task(coro) # pylint: disable=no-member
|
|
-
|
|
- # Python 3.6:
|
|
- return asyncio.ensure_future(coro, loop=loop)
|
|
-
|
|
-
|
|
-def is_closing(writer: asyncio.StreamWriter) -> bool:
|
|
- """
|
|
- Python 3.6-compatible `asyncio.StreamWriter.is_closing` wrapper.
|
|
-
|
|
- :param writer: The `asyncio.StreamWriter` object.
|
|
- :return: `True` if the writer is closing, or closed.
|
|
- """
|
|
- if sys.version_info >= (3, 7):
|
|
- return writer.is_closing()
|
|
-
|
|
- # Python 3.6:
|
|
- transport = writer.transport
|
|
- assert isinstance(transport, asyncio.WriteTransport)
|
|
- return transport.is_closing()
|
|
-
|
|
-
|
|
-async def wait_closed(writer: asyncio.StreamWriter) -> None:
|
|
- """
|
|
- Python 3.6-compatible `asyncio.StreamWriter.wait_closed` wrapper.
|
|
-
|
|
- :param writer: The `asyncio.StreamWriter` to wait on.
|
|
- """
|
|
- if sys.version_info >= (3, 7):
|
|
- await writer.wait_closed()
|
|
- return
|
|
-
|
|
- # Python 3.6
|
|
- transport = writer.transport
|
|
- assert isinstance(transport, asyncio.WriteTransport)
|
|
-
|
|
- while not transport.is_closing():
|
|
- await asyncio.sleep(0)
|
|
-
|
|
- # This is an ugly workaround, but it's the best I can come up with.
|
|
- sock = transport.get_extra_info('socket')
|
|
-
|
|
- if sock is None:
|
|
- # Our transport doesn't have a socket? ...
|
|
- # Nothing we can reasonably do.
|
|
- return
|
|
-
|
|
- while sock.fileno() != -1:
|
|
- await asyncio.sleep(0)
|
|
-
|
|
-
|
|
-def asyncio_run(coro: Coroutine[Any, Any, T], *, debug: bool = False) -> T:
|
|
- """
|
|
- Python 3.6-compatible `asyncio.run` wrapper.
|
|
-
|
|
- :param coro: A coroutine to execute now.
|
|
- :return: The return value from the coroutine.
|
|
- """
|
|
- if sys.version_info >= (3, 7):
|
|
- return asyncio.run(coro, debug=debug)
|
|
-
|
|
- # Python 3.6
|
|
- loop = asyncio.get_event_loop()
|
|
- loop.set_debug(debug)
|
|
- ret = loop.run_until_complete(coro)
|
|
- loop.close()
|
|
-
|
|
- return ret
|
|
-
|
|
-
|
|
# ----------------------------
|
|
# Section: Logging & Debugging
|
|
# ----------------------------
|
|
diff --git a/python/tests/protocol.py b/python/tests/protocol.py
|
|
index 56c4d441f9..c254c77b17 100644
|
|
--- a/python/tests/protocol.py
|
|
+++ b/python/tests/protocol.py
|
|
@@ -8,7 +8,6 @@
|
|
|
|
from qemu.qmp import ConnectError, Runstate
|
|
from qemu.qmp.protocol import AsyncProtocol, StateError
|
|
-from qemu.qmp.util import asyncio_run, create_task
|
|
|
|
|
|
class NullProtocol(AsyncProtocol[None]):
|
|
@@ -124,7 +123,7 @@ async def _runner():
|
|
if allow_cancellation:
|
|
return
|
|
raise
|
|
- return create_task(_runner())
|
|
+ return asyncio.create_task(_runner())
|
|
|
|
|
|
@contextmanager
|
|
@@ -271,7 +270,7 @@ async def _watcher():
|
|
msg=f"Expected state '{state.name}'",
|
|
)
|
|
|
|
- self.runstate_watcher = create_task(_watcher())
|
|
+ self.runstate_watcher = asyncio.create_task(_watcher())
|
|
# Kick the loop and force the task to block on the event.
|
|
await asyncio.sleep(0)
|
|
|
|
@@ -589,7 +588,8 @@ async def _asyncTearDown(self):
|
|
async def testSmoke(self):
|
|
with TemporaryDirectory(suffix='.qmp') as tmpdir:
|
|
sock = os.path.join(tmpdir, type(self.proto).__name__ + ".sock")
|
|
- server_task = create_task(self.server.start_server_and_accept(sock))
|
|
+ server_task = asyncio.create_task(
|
|
+ self.server.start_server_and_accept(sock))
|
|
|
|
# give the server a chance to start listening [...]
|
|
await asyncio.sleep(0)
|
|
--
|
|
2.52.0
|
|
|