summaryrefslogtreecommitdiffstats
path: root/python/qemu
Commit message (Collapse)AuthorAgeFilesLines
* python/aqmp: add socket bind step to legacy.pyJohn Snow2022-02-022-3/+41
| | | | | | | | | | | | | | | | | | | | | | | | The synchronous QMP library would bind to the server address during __init__(). The new library delays this to the accept() call, because binding occurs inside of the call to start_[unix_]server(), which is an async method -- so it cannot happen during __init__ anymore. Python 3.7+ adds the ability to create the server (and thus the bind() call) and begin the active listening in separate steps, but we don't have that functionality in 3.6, our current minimum. Therefore ... Add a temporary workaround that allows the synchronous version of the client to bind the socket in advance, guaranteeing that there will be a UNIX socket in the filesystem ready for the QEMU client to connect to without a race condition. (Yes, it's a bit ugly. Fixing it more nicely will have to wait until our minimum Python version is 3.7+.) Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 20220201041134.1237016-5-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/machine: raise VMLaunchFailure exception from launch()John Snow2022-02-021-6/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | This allows us to pack in some extra information about the failure, which guarantees that if the caller did not *intentionally* cause a failure (by capturing this Exception), some pretty good clues will be printed at the bottom of the traceback information. This will help make failures in the event of a non-negative return code more obvious when they go unhandled; the current behavior in _post_shutdown() is to print a warning message only in the event of signal-based terminations (for negative return codes). (Note: In Python, catching BaseException instead of Exception catches a broader array of Exception events, including SystemExit and KeyboardInterrupt. We do not want to "wrap" such exceptions as a VMLaunchFailure, because that will 'downgrade' the exception from a BaseException to a regular Exception. We do, however, want to perform cleanup in either case, so catch on the broadest scope and wrap-and-re-raise only in the more targeted scope.) Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 20220201041134.1237016-3-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Fix negotiation with pre-"oob" QEMUJohn Snow2022-02-021-2/+2
| | | | | | | | | | | | QEMU versions prior to the "oob" capability *also* can't accept the "enable" keyword argument at all. Fix the handshake process with older QEMU versions. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 20220201041134.1237016-2-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python: move qmp-shell under the AQMP packageJohn Snow2022-01-211-0/+0
| | | | | | Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Beraldo Leal <bleal@redhat.com>
* python: move qmp utilities to python/qemu/utilsJohn Snow2022-01-214-0/+0
| | | | | | | | | | | | | In order to upload a QMP package to PyPI, I want to remove any scripts that I am not 100% confident I want to support upstream, beyond our castle walls. Move most of our QMP utilities into the utils package so we can split them out from the PyPI upload. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Beraldo Leal <bleal@redhat.com>
* python/qmp: switch qmp-shell to AQMPJohn Snow2022-01-212-14/+20
| | | | | | | | We have a replacement for async QMP, but it doesn't have feature parity yet. For now, then, port the old tool onto the new backend. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
* python/qmp: switch qom tools to AQMPJohn Snow2022-01-213-8/+11
| | | | | | Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Beraldo Leal <bleal@redhat.com>
* python/qmp: switch qemu-ga-client to AQMPJohn Snow2022-01-211-11/+11
| | | | | | | | | | | Async QMP always raises a "ConnectError" on any connection error which houses the cause in a second exception. We can check if this root cause was python's ConnectionError to determine a fairly similar condition to the original error check here. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Beraldo Leal <bleal@redhat.com>
* python/qemu-ga-client: don't use deprecated CLI syntax in usage commentJohn Snow2022-01-211-1/+1
| | | | | | | | | Cleanup related to commit ccd3b3b8112b670f, "qemu-option: warn for short-form boolean options". Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
* python/aqmp: rename AQMPError to QMPErrorJohn Snow2022-01-216-21/+21
| | | | | | | | | This is in preparation for renaming qemu.aqmp to qemu.qmp. I should have done this from this from the very beginning, but it's a convenient time to make sure this churn is taken care of. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
* python/aqmp: add SocketAddrT to package rootJohn Snow2022-01-211-1/+9
| | | | | | | | It's a commonly needed definition, it can be re-exported by the root. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Beraldo Leal <bleal@redhat.com>
* python/aqmp: copy type definitions from qmpJohn Snow2022-01-212-8/+30
| | | | | | | | | | Copy the remaining type definitions from QMP into the qemu.aqmp.legacy module. Now, users that require the legacy interface don't need to import anything else but qemu.aqmp.legacy wrapper. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Beraldo Leal <bleal@redhat.com>
* python/aqmp: handle asyncio.TimeoutError on execute()John Snow2022-01-211-2/+6
| | | | | | | | | | This exception can be injected into any await statement. If we are canceled via timeout, we want to clear the pending execution record on our way out. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Beraldo Leal <bleal@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
* python/aqmp: add __del__ method to legacy interfaceJohn Snow2022-01-211-0/+18
| | | | | | | | | | | | | | | | | | | | | | | asyncio can complain *very* loudly if you forget to back out of things gracefully before the garbage collector starts destroying objects that contain live references to asyncio Tasks. The usual fix is just to remember to call aqmp.disconnect(), but for the sake of the legacy wrapper and quick, one-off scripts where a graceful shutdown is not necessarily of paramount imporance, add a courtesy cleanup that will trigger prior to seeing screenfuls of confusing asyncio tracebacks. Note that we can't *always* save you from yourself; depending on when the GC runs, you might just seriously be out of luck. The best we can do in this case is to gently remind you to clean up after yourself. (Still much better than multiple pages of incomprehensible python warnings for the crime of forgetting to put your toys away.) Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Beraldo Leal <bleal@redhat.com>
* python/aqmp: fix docstring typoJohn Snow2022-01-211-1/+1
| | | | | | Reported-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Beraldo Leal <bleal@redhat.com>
* python: update type hints for mypy 0.930John Snow2022-01-111-5/+1Star
| | | | | | | | | | | | | | | Mypy 0.930, released Dec 22, changes the way argparse objects are considered. Crafting a definition that works under Python 3.6 and an older mypy alongside newer versions simultaneously is ... difficult, so... eh. Stub it out with an 'Any' definition to get the CI moving again. Oh well. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Beraldo Leal <bleal@redhat.com> Message-id: 20220110191349.1841027-4-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* Python/aqmp: fix type definitions for mypy 0.920John Snow2022-01-111-2/+3
| | | | | | | | | | | | | | | | 0.920 (Released 2021-12-15) is not entirely happy with the way that I was defining _FutureT: qemu/aqmp/protocol.py:601: error: Item "object" of the upper bound "Optional[Future[Any]]" of type variable "_FutureT" has no attribute "done" Update it with something a little mechanically simpler that works better across a wider array of mypy versions. Signed-off-by: John Snow <jsnow@redhat.com> Message-id: 20220110191349.1841027-3-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: use absolute import statementJohn Snow2022-01-111-1/+2
| | | | | | | | | | | | | | | pylint's dependency astroid appears to have bugs in 2.9.1 and 2.9.2 (Dec 31 and Jan 3) that appear to erroneously expect the qemu namespace to have an __init__.py file. astroid 2.9.3 (Jan 9) avoids that problem, but appears to not understand a relative import within a namespace package. Update the relative import - it was worth changing anyway, because these packages will eventually be packaged and distributed separately. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Beraldo Leal <bleal@redhat.com> Message-id: 20220110191349.1841027-2-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: fix send_fd_scm for python 3.6.xJohn Snow2021-11-231-3/+6
| | | | | | | | | | | | | 3.6 doesn't play keepaway with the socket object, so we don't need to go fishing for it on this version. In fact, so long as 'sendmsg' is still available, it's probably preferable to just use that method and only go fishing for forbidden details when we absolutely have to. Reported-by: Thomas Huth <thuth@redhat.com> Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Willian Rampazzo <willianr@redhat.com> Message-id: 20211118204620.1897674-8-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/machine: handle "fast" QEMU terminationsJohn Snow2021-11-231-7/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | In the case that the QEMU process actually launches -- but then dies so quickly that we can't establish a QMP connection to it -- QEMUMachine currently calls _post_shutdown() assuming that it never launched the VM process. This isn't true, though: it "merely" may have failed to establish a QMP connection and the process is in the middle of its own exit path. If we don't wait for the subprocess, the caller may get a bogus `None` return for .exitcode(). This behavior was observed from device-crash-test; after the switch to Async QMP, the timings were changed such that it was now seemingly possible to witness the failure of "vm.launch()" *prior* to the exitcode becoming available. The semantic of the `_launched` property is changed in this patch. Instead of representing the condition "launch() executed successfully", it will now represent "has forked a child process successfully". This way, wait() when called in the exit path won't become a no-op. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Willian Rampazzo <willianr@redhat.com> Message-id: 20211118204620.1897674-6-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/machine: move more variable initializations to _pre_launchJohn Snow2021-11-231-8/+8
| | | | | | | | | No need to clear them only to set them later. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Willian Rampazzo <willianr@redhat.com> Message-id: 20211118204620.1897674-5-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/machine: add instance disambiguator to default nicknameJohn Snow2021-11-231-1/+1
| | | | | | | | | | | | | | | | | | | If you create two instances of QEMUMachine(), they'll both create the same nickname by default -- which is not that helpful. Luckily, they'll both create unique temporary directories ... but due to user configuration, they may share logging and sockfile directories, meaning two instances can collide. The Python logging will also be quite confusing, with no differentiation between the two instances. Add an instance disambiguator (The memory address of the instance) to the default nickname to foolproof this in all cases. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Willian Rampazzo <willianr@redhat.com> Message-id: 20211118204620.1897674-4-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/machine: remove _remove_monitor_sockfile propertyJohn Snow2021-11-231-4/+1Star
| | | | | | | | | | | It doesn't matter if it was the user or the class itself that specified where the sockfile should be created; the fact is that if we are using a sockfile here, we created it and we can clean it up. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Willian Rampazzo <willianr@redhat.com> Message-id: 20211118204620.1897674-3-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/machine: add @sock_dir propertyJohn Snow2021-11-231-4/+13
| | | | | | | | | | | | | Analogous to temp_dir and log_dir, add a sock_dir property that defaults to @temp_dir -- instead of base_temp_dir -- when the user hasn't overridden the sock dir value in the initializer. This gives us a much more unique directory to put sockfiles in by default. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Willian Rampazzo <willianr@redhat.com> Message-id: 20211118204620.1897674-2-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: fix ConnectError string methodJohn Snow2021-11-161-1/+5
| | | | | | | | | | | | | | | | | | | | When ConnectError is used to wrap an Exception that was initialized without an error message, we are treated to a traceback with a rubbish line like this: ... ConnectError: Failed to establish session: Correct this to use the name of an exception as a fallback message: ... ConnectError: Failed to establish session: EOFError Better! Signed-off-by: John Snow <jsnow@redhat.com> Reported-by: Thomas Huth <thuth@redhat.com> Tested-by: Thomas Huth <thuth@redhat.com> Message-id: 20211111143719.2162525-3-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Fix disconnect during capabilities negotiationJohn Snow2021-11-161-5/+13
| | | | | | | | | | | | | | | | | | | | | | | If we receive ConnectionResetError (ECONNRESET) while attempting to perform capabilities negotiation -- prior to the establishment of the async reader/writer tasks -- the disconnect function is not aware that we are in an error pathway. As a result, when attempting to close the StreamWriter, we'll see the same ConnectionResetError that caused us to initiate a disconnect in the first place, which will cause the disconnect task itself to fail, which emits a CRITICAL logging event. I still don't know if there's a smarter way to check to see if an exception received at this point is "the same" exception as the one that caused the initial disconnect, but for now the problem can be avoided by improving the error pathway detection in the exit path. Reported-by: Thomas Huth <thuth@redhat.com> Signed-off-by: John Snow <jsnow@redhat.com> Tested-by: Thomas Huth <thuth@redhat.com> Message-id: 20211111143719.2162525-2-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* tests/acceptance: rename tests acceptance to tests avocadoWillian Rampazzo2021-11-083-3/+3
| | | | | | | | | | | | | | | | | | | In the discussion about renaming the `tests/acceptance` [1], the conclusion was that the folders inside `tests` are related to the framework running the tests and not directly related to the type of the tests. This changes the folder to `tests/avocado` and adjusts the MAKEFILE, the CI related files and the documentation. [1] https://lists.gnu.org/archive/html/qemu-devel/2021-05/msg06553.html Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Willian Rampazzo <willianr@redhat.com> Message-Id: <20211105155354.154864-3-willianr@redhat.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
* python, iotests: replace qmp with aqmpJohn Snow2021-11-011-1/+6
| | | | | | | | | | | | | | | | Swap out the synchronous QEMUMonitorProtocol from qemu.qmp with the sync wrapper from qemu.aqmp instead. Add an escape hatch in the form of the environment variable QEMU_PYTHON_LEGACY_QMP which allows you to cajole QEMUMachine into using the old implementation, proving that both implementations work concurrently. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Message-id: 20211026175612.4127598-9-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Create sync QMP wrapper for iotestsJohn Snow2021-11-011-0/+138
| | | | | | | | | | | | | | | This is a wrapper around the async QMPClient that mimics the old, synchronous QEMUMonitorProtocol class. It is designed to be interchangeable with the old implementation. It does not, however, attempt to mimic Exception compatibility. Signed-off-by: John Snow <jsnow@redhat.com> Acked-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Message-id: 20211026175612.4127598-8-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Remove scary messageJohn Snow2021-11-011-12/+0Star
| | | | | | | | | | | | | The scary message interferes with the iotests output. Coincidentally, if iotests works by removing this, then it's good evidence that we don't really need to scare people away from using it. Signed-off-by: John Snow <jsnow@redhat.com> Acked-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Message-id: 20211026175612.4127598-4-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/machine: Handle QMP errors on close more meticulouslyJohn Snow2021-11-011-6/+42
| | | | | | | | | | | | | | | | | | | | | | | To use the AQMP backend, Machine just needs to be a little more diligent about what happens when closing a QMP connection. The operation is no longer a freebie in the async world; it may return errors encountered in the async bottom half on incoming message receipt, etc. (AQMP's disconnect, ultimately, serves as the quiescence point where all async contexts are gathered together, and any final errors reported at that point.) Because async QMP continues to check for messages asynchronously, it's almost certainly likely that the loop will have exited due to EOF after issuing the last 'quit' command. That error will ultimately be bubbled up when attempting to close the QMP connection. The manager class here then is free to discard it -- if it was expected. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 20211026175612.4127598-3-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/machine: remove has_quit argumentJohn Snow2021-11-011-15/+19
| | | | | | | | | | | | | | | | | | | | | If we spy on the QMP commands instead, we don't need callers to remember to pass it. Seems like a fair trade-off. The one slightly weird bit is overloading this instance variable for wait(), where we use it to mean "don't issue the qmp 'quit' command". This means that wait() will "fail" if the QEMU process does not terminate of its own accord. In most cases, we probably did already actually issue quit -- some iotests do this -- but in some others, we may be waiting for QEMU to terminate for some other reason, such as a test wherein we tell the guest (directly) to shut down. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Kevin Wolf <kwolf@redhat.com> Message-id: 20211026175612.4127598-2-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python, iotests: remove socket_scm_helperJohn Snow2021-10-122-5/+0Star
| | | | | | | | | | It's not used anymore, now. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 20210923004938.3999963-11-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/qmp: add send_fd_scm directly to QEMUMonitorProtocolJohn Snow2021-10-122-47/+18Star
| | | | | | | | | | | | | | | | | It turns out you can do this directly from Python ... and because of this, you don't need to worry about setting the inheritability of the fds or spawning another process. Doing this is helpful because it allows QEMUMonitorProtocol to keep its file descriptor and socket object as private implementation details. /that/ is helpful in turn because it allows me to write a compatible, alternative implementation. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 20210923004938.3999963-10-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/qmp: clear events on get_events() callJohn Snow2021-10-123-4/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | All callers in the tree *already* clear the events after a call to get_events(). Do it automatically instead and update callsites to remove the manual clear call. These semantics are quite a bit easier to emulate with async QMP, and nobody appears to be abusing some emergent properties of what happens if you decide not to clear them, so let's dial down to the dumber, simpler thing. Specifically: callers of clear() right after a call to get_events() are more likely expressing their desire to not see any events they just retrieved, whereas callers of clear_events() not in relation to a recent call to pull_event/get_events are likely expressing their desire to simply drop *all* pending events straight onto the floor. In the sync world, this is safe enough; in the async world it's nearly impossible to promise that nothing happens between getting and clearing the events. Making the retrieval also clear the queue is vastly simpler. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 20210923004938.3999963-9-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Disable logging messages by defaultJohn Snow2021-10-121-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | AQMP is a library, and ideally it should not print error diagnostics unless a user opts into seeing them. By default, Python will print all WARNING, ERROR or CRITICAL messages to screen if no logging configuration has been created by a client application. In AQMP's case, ERROR logging statements are used to report additional detail about runtime failures that will also eventually be reported to the client library via an Exception, so these messages should not be rendered by default. (Why bother to have them at all, then? In async contexts, there may be multiple Exceptions and we are only able to report one of them back to the client application. It is not reasonably easy to predict ahead of time if one or more of these Exceptions will be squelched. Therefore, it's useful to log intermediate failures to help make sense of the ultimate, resulting failure.) Add a NullHandler that will suppress these messages until a client application opts into logging via logging.basicConfig or similar. Note that upon calling basicConfig(), this handler will *not* suppress these messages from being displayed by the client's configuration. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 20210923004938.3999963-8-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Reduce severity of EOFError-caused loop terminationsJohn Snow2021-10-121-2/+5
| | | | | | | | | | | | | | When we encounter an EOFError, we don't know if it's an "error" in the perspective of the user of the library yet. Therefore, we should not log it as an error. Reduce the severity of this logging message to "INFO" to indicate that it's something that we expect to occur during the normal operation of the library. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 20210923004938.3999963-7-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Add dict conversion method to Greeting objectJohn Snow2021-10-121-0/+13
| | | | | | | | | | | The iotests interface expects to return the greeting as a dict; AQMP offers it as a rich object. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 20210923004938.3999963-6-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: add send_fd_scmJohn Snow2021-10-121-0/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add an implementation for send_fd_scm to the async QMP implementation. Like socket_scm_helper mentions, a non-empty payload is required for QEMU to process the ancillary data. A space is most useful because it does not disturb the parsing of subsequent JSON objects. A note on "voiding the warranty": Python 3.11 removes support for calling sendmsg directly from a transport's socket. There is no other interface for doing this, our use case is, I suspect, "quite unique". As far as I can tell, this is safe to do -- send_fd_scm is a synchronous function and we can be guaranteed that the async coroutines will *not* be running when it is invoked. In testing, it works correctly. I investigated quite thoroughly the possibility of creating my own asyncio Transport (The class that ultimately manages the raw socket object) so that I could manage the socket myself, but this is so wildly invasive and unportable I scrapped the idea. It would involve a lot of copy-pasting of various python utilities and classes just to re-create the same infrastructure, and for extremely little benefit. Nah. Just boldly void the warranty instead, while I try to follow up on https://bugs.python.org/issue43232 Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-id: 20210923004938.3999963-5-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Return cleared events from EventListener.clear()John Snow2021-10-121-2/+7
| | | | | | | | | | | | | | | | This serves two purposes: (1) It is now possible to discern whether or not clear() removed any event(s) from the queue with absolute certainty, and (2) It is now very easy to get a List of all pending events in one chunk, which is useful for the sync bridge. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 20210923004938.3999963-4-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: add .empty() method to EventListenerJohn Snow2021-10-121-0/+6
| | | | | | | | | | | | | Synchronous clients may want to know if they're about to block waiting for an event or not. A method such as this is necessary to implement a compatible interface for the old QEMUMonitorProtocol using the new async internals. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 20210923004938.3999963-3-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: add greeting property to QMPClientJohn Snow2021-10-121-0/+5
| | | | | | | | | | | Expose the greeting as a read-only property of QMPClient so it can be retrieved at-will. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Hanna Reitz <hreitz@redhat.com> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Message-id: 20210923004938.3999963-2-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp-tui: Add syntax highlightingG S Niteesh Babu2021-09-271-2/+34
| | | | | | | | | | | | | | | Add syntax highlighting for the incoming and outgoing QMP messages. This is achieved using the pygments module which was added in a previous commit. The current implementation is a really simple one which doesn't allow for any configuration. In future this has to be improved to allow for easier theme config using an external config of some sort. Signed-off-by: G S Niteesh Babu <niteesh.gs@gmail.com> Message-Id: <20210823220746.28295-6-niteesh.gs@gmail.com> Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp-tui: Add AQMP TUIG S Niteesh Babu2021-09-271-0/+620
| | | | | | | | | | | | | | | | Added AQMP TUI. Implements the follwing basic features: 1) Command transmission/reception. 2) Shows events asynchronously. 3) Shows server status in the bottom status bar. 4) Automatic retries on disconnects and error conditions. Also added type annotations and necessary pylint/mypy configurations. Signed-off-by: G S Niteesh Babu <niteesh.gs@gmail.com> Message-Id: <20210823220746.28295-3-niteesh.gs@gmail.com> Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: add scary messageJohn Snow2021-09-271-0/+14
| | | | | | | | | Add a warning whenever AQMP is used to steer people gently away from using it for the time-being. Signed-off-by: John Snow <jsnow@redhat.com> Message-id: 20210915162955.333025-24-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: add asyncio_run compatibility wrapperJohn Snow2021-09-271-0/+19
| | | | | | | | | | As a convenience. It isn't used by the library itself, but it is used by the test suite. It will also come in handy for users of the library still on Python 3.6. Signed-off-by: John Snow <jsnow@redhat.com> Message-id: 20210915162955.333025-23-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: add _raw() execution interfaceJohn Snow2021-09-271-0/+51
| | | | | | | | | | | | | | This is added in anticipation of wanting it for a synchronous wrapper for the iotest interface. Normally, execute() and execute_msg() both raise QMP errors in the form of Python exceptions. Many iotests expect the entire reply as-is. To reduce churn there, add a private execution interface that will ease transition churn. However, I do not wish to encourage its use, so it will remain a private interface. Signed-off-by: John Snow <jsnow@redhat.com> Message-id: 20210915162955.333025-22-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: add execute() interfacesJohn Snow2021-09-272-8/+198
| | | | | | | | | | | | | | | | Add execute() and execute_msg(). _execute() is split into _issue() and _reply() halves so that hypothetical subclasses of QMP that want to support different execution paradigms can do so. I anticipate a synchronous interface may have need of separating the send/reply phases. However, I do not wish to expose that interface here and want to actively discourage it, so they remain private interfaces. Signed-off-by: John Snow <jsnow@redhat.com> Message-id: 20210915162955.333025-21-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: Add message routing to QMP protocolJohn Snow2021-09-271-2/+120
| | | | | | | | | | Add the ability to handle and route messages in qmp_protocol.py. The interface for actually sending anything still isn't added until next commit. Signed-off-by: John Snow <jsnow@redhat.com> Message-id: 20210915162955.333025-20-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>
* python/aqmp: add QMP protocol supportJohn Snow2021-09-272-0/+266
| | | | | | | | | | | The star of our show! Add most of the QMP protocol, sans support for actually executing commands. No problem, that happens in the next several commits. Signed-off-by: John Snow <jsnow@redhat.com> Message-id: 20210915162955.333025-18-jsnow@redhat.com Signed-off-by: John Snow <jsnow@redhat.com>