From: Hanna Reitz <hreitz@redhat.com>
To: John Snow <jsnow@redhat.com>, qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>, Thomas Huth <thuth@redhat.com>,
Beraldo Leal <bleal@redhat.com>,
qemu-block@nongnu.org, Cleber Rosa <crosa@redhat.com>,
Eric Blake <eblake@redhat.com>
Subject: Re: [PATCH v3 4/5] iotests: make qemu_img raise on non-zero rc by default
Date: Thu, 17 Mar 2022 11:25:24 +0100 [thread overview]
Message-ID: <e9b98326-1d20-b9fa-0756-42d0ab7f8466@redhat.com> (raw)
In-Reply-To: <20220308015728.1269649-5-jsnow@redhat.com>
On 08.03.22 02:57, John Snow wrote:
> re-write qemu_img() as a function that will by default raise a
> VerboseProcessException (extended from CalledProcessException) on
> non-zero return codes. This will produce a stack trace that will show
> the command line arguments and return code from the failed process run.
Why not qemu_img_pipe_and_status() as the central function where all
qemu-img calls go through?
It seems like this makes qemu_img() a second version of
qemu_img_pipe_and_status(), which is a bit weird.
(Or perhaps it should actually be qemu_tool_pipe_and_status() that
receives this treatment, with qemu-io functions just passing check=False
by default.)
> Users that want something more flexible (there appears to be only one)
> can use check=False and manage the return themselves. However, when the
> return code is negative, the Exception will be raised no matter what.
> This is done under the belief that there's no legitimate reason, even in
> negative tests, to see a crash from qemu-img.
>
> Signed-off-by: John Snow <jsnow@redhat.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>
> ---
> tests/qemu-iotests/257 | 8 +++--
> tests/qemu-iotests/iotests.py | 56 ++++++++++++++++++++++++++++++-----
> 2 files changed, 54 insertions(+), 10 deletions(-)
>
> diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257
> index fb5359c581..e7e7a2317e 100755
> --- a/tests/qemu-iotests/257
> +++ b/tests/qemu-iotests/257
> @@ -241,11 +241,13 @@ def compare_images(image, reference, baseimg=None, expected_match=True):
> expected_ret = 0 if expected_match else 1
> if baseimg:
> qemu_img("rebase", "-u", "-b", baseimg, '-F', iotests.imgfmt, image)
> - ret = qemu_img("compare", image, reference)
> +
> + sub = qemu_img("compare", image, reference, check=False)
> +
> log('qemu_img compare "{:s}" "{:s}" ==> {:s}, {:s}'.format(
> image, reference,
> - "Identical" if ret == 0 else "Mismatch",
> - "OK!" if ret == expected_ret else "ERROR!"),
> + "Identical" if sub.returncode == 0 else "Mismatch",
> + "OK!" if sub.returncode == expected_ret else "ERROR!"),
> filters=[iotests.filter_testfiles])
>
> def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index 508adade9e..ec4568b24a 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -37,9 +37,10 @@
>
> from contextlib import contextmanager
>
> +from qemu.aqmp.legacy import QEMUMonitorProtocol
> from qemu.machine import qtest
> from qemu.qmp import QMPMessage
> -from qemu.aqmp.legacy import QEMUMonitorProtocol
> +from qemu.utils import VerboseProcessError
>
> # Use this logger for logging messages directly from the iotests module
> logger = logging.getLogger('qemu.iotests')
> @@ -215,9 +216,49 @@ def qemu_img_pipe_and_status(*args: str) -> Tuple[str, int]:
> return qemu_tool_pipe_and_status('qemu-img', full_args,
> drop_successful_output=is_create)
>
> -def qemu_img(*args: str) -> int:
> - '''Run qemu-img and return the exit code'''
> - return qemu_img_pipe_and_status(*args)[1]
> +def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
> + ) -> subprocess.CompletedProcess[str]:
> + """
> + Run qemu_img and return the status code and console output.
> +
> + This function always prepends QEMU_IMG_OPTIONS and may further alter
> + the args for 'create' commands.
> +
> + :param args: command-line arguments to qemu-img.
> + :param check: Enforce a return code of zero.
> + :param combine_stdio: set to False to keep stdout/stderr separated.
> +
> + :raise VerboseProcessError:
> + When the return code is negative, or on any non-zero exit code
> + when 'check=True' was provided (the default). This exception has
> + 'stdout', 'stderr', and 'returncode' properties that may be
> + inspected to show greater detail. If this exception is not
> + handled, the command-line, return code, and all console output
> + will be included at the bottom of the stack trace.
> +
> + :return: a CompletedProcess. This object has args, returncode, and
> + stdout properties. If streams are not combined, it will also
> + have a stderr property.
> + """
> + full_args = qemu_img_args + qemu_img_create_prepare_args(list(args))
> +
> + subp = subprocess.run(
> + full_args,
> + stdout=subprocess.PIPE,
> + stderr=subprocess.STDOUT if combine_stdio else subprocess.PIPE,
> + universal_newlines=True,
> + check=False
> + )
> +
> + if check and subp.returncode or (subp.returncode < 0):
I wouldn’t expect these parentheses here in any other language, are they
required in Python?
> + raise VerboseProcessError(
> + subp.returncode, full_args,
> + output=subp.stdout,
> + stderr=subp.stderr,
> + )
I trust these parameters are correct, because it really sometimes seems
like Python doc doesn’t want to tell me about the arguments that
constructors take. (The only thing I found out is that `stdout` works
as an alias for `output`, so passing `output` here and reading
`self.stdout` in `VerboseProcesError` should(tm) be fine.)
Hanna
> +
> + return subp
> +
>
> def ordered_qmp(qmsg, conv_keys=True):
> # Dictionaries are not ordered prior to 3.6, therefore:
> @@ -232,7 +273,7 @@ def ordered_qmp(qmsg, conv_keys=True):
> return od
> return qmsg
>
> -def qemu_img_create(*args):
> +def qemu_img_create(*args: str) -> subprocess.CompletedProcess[str]:
> return qemu_img('create', *args)
>
> def qemu_img_measure(*args):
> @@ -467,8 +508,9 @@ def qemu_nbd_popen(*args):
>
> def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt):
> '''Return True if two image files are identical'''
> - return qemu_img('compare', '-f', fmt1,
> - '-F', fmt2, img1, img2) == 0
> + res = qemu_img('compare', '-f', fmt1,
> + '-F', fmt2, img1, img2, check=False)
> + return res.returncode == 0
>
> def create_image(name, size):
> '''Create a fully-allocated raw image with sector markers'''
next prev parent reply other threads:[~2022-03-17 10:30 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-08 1:57 [PATCH v3 0/5] iotests: add enhanced debugging info to qemu-img failures John Snow
2022-03-08 1:57 ` [PATCH v3 1/5] python/utils: add add_visual_margin() text decoration utility John Snow
2022-03-17 10:29 ` Hanna Reitz
2022-03-08 1:57 ` [PATCH v3 2/5] python/utils: add VerboseProcessError John Snow
2022-03-17 9:23 ` Hanna Reitz
2022-03-17 15:13 ` John Snow
2022-03-17 15:56 ` Hanna Reitz
2022-03-17 16:31 ` John Snow
2022-03-17 16:34 ` Hanna Reitz
2022-03-17 16:48 ` John Snow
2022-03-08 1:57 ` [PATCH v3 3/5] iotests: Remove explicit checks for qemu_img() == 0 John Snow
2022-03-08 15:15 ` Eric Blake
2022-03-08 17:04 ` John Snow
2022-03-17 10:28 ` Hanna Reitz
2022-03-08 1:57 ` [PATCH v3 4/5] iotests: make qemu_img raise on non-zero rc by default John Snow
2022-03-17 10:25 ` Hanna Reitz [this message]
2022-03-17 10:41 ` Hanna Reitz
2022-03-17 14:23 ` John Snow
2022-03-17 15:24 ` John Snow
2022-03-17 15:58 ` Hanna Reitz
2022-03-17 16:06 ` Hanna Reitz
2022-03-08 1:57 ` [PATCH v3 5/5] iotests: fortify compare_images() against crashes John Snow
2022-03-17 10:28 ` Hanna Reitz
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=e9b98326-1d20-b9fa-0756-42d0ab7f8466@redhat.com \
--to=hreitz@redhat.com \
--cc=bleal@redhat.com \
--cc=crosa@redhat.com \
--cc=eblake@redhat.com \
--cc=jsnow@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=thuth@redhat.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).