From: John Snow <jsnow@redhat.com>
To: Max Reitz <mreitz@redhat.com>, qemu-devel@nongnu.org
Cc: kwolf@redhat.com, famz@redhat.com, armbru@redhat.com,
vsementsov@parallels.com, stefanha@redhat.com
Subject: Re: [Qemu-devel] [PATCH v12 14/17] iotests: add simple incremental backup case
Date: Wed, 11 Feb 2015 17:02:54 -0500 [thread overview]
Message-ID: <54DBD18E.10703@redhat.com> (raw)
In-Reply-To: <54DBCC59.7060303@redhat.com>
On 02/11/2015 04:40 PM, Max Reitz wrote:
> On 2015-02-09 at 20:35, John Snow wrote:
>> Signed-off-by: John Snow <jsnow@redhat.com>
>> ---
>> tests/qemu-iotests/112 | 120
>> +++++++++++++++++++++++++++++++++++++++++-
>> tests/qemu-iotests/112.out | 4 +-
>> tests/qemu-iotests/iotests.py | 18 ++++---
>> 3 files changed, 133 insertions(+), 9 deletions(-)
>>
>> diff --git a/tests/qemu-iotests/112 b/tests/qemu-iotests/112
>> index 7985cd1..31431ad 100644
>> --- a/tests/qemu-iotests/112
>> +++ b/tests/qemu-iotests/112
>> @@ -22,18 +22,49 @@
>> import os
>> import iotests
>> +from iotests import qemu_img, qemu_io, create_image
>
> Is this really necessary? For me, it works without, too; and if it is
> necessary, shouldn't it be part of patch 13?
>
Maybe not? It's baggage from copying 056 as a template.
>> def io_write_patterns(img, patterns):
>> for pattern in patterns:
>> iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img)
>> +class Bitmap:
>> + def __init__(self, name, node):
>> + self.name = name
>> + self.node = node
>> + self.pattern = os.path.join(iotests.test_dir,
>> + '%s.backup.%%s.img' % name)
>
> Shouldn't this be %%i? %%s works for me, but I think %%i might look better.
>
It's probably more semantically appropriate, yes.
>> + self.num = 0
>> + self.backups = list()
>> +
>> + def new_target(self, num=None):
>> + if num is None:
>> + num = self.num
>> + self.num = num + 1
>> + target = self.pattern % num
>
> I hope nobody has a % in the test path...
>
Oh, good point.
> Although it does look nice, maybe just self.base =
> os.path.join(iotests.test_dir, '%s.backup.img.' % name) and target =
> self.base + str(num) is more robust (putting the '.img' at the end is a
> bonus).
>
>> + self.backups.append(target)
>> + return target
>> +
>> + def last_target(self):
>> + return self.backups[-1]
>> +
>> + def del_target(self):
>> + os.remove(self.backups.pop())
>> + self.num -= 1
>> +
>> + def __del__(self):
>> + for backup in self.backups:
>> + try:
>> + os.remove(backup)
>> + except OSError:
>> + pass
>> class TestIncrementalBackup(iotests.QMPTestCase):
>> def setUp(self):
>> self.bitmaps = list()
>> self.files = list()
>> - self.vm = iotests.VM()
>> + self.vm = iotests.VM().add_args(['-S'])
>
> Isn't -machine accel=qtest (which is specified by default) enough?
Yes, this is actually somewhat vestigial from a standalone version of
this that would tolerate an arbitrary image. I left it in because I
thought it was harmless and it served as an illustration about the
inferred timing of the commands being tested.
That said, it /can/ be removed. Its only purpose is illustrative.
>
>> self.test_img = os.path.join(iotests.test_dir, 'base.img')
>> self.full_bak = os.path.join(iotests.test_dir, 'backup.img')
>> self.foo_img = os.path.join(iotests.test_dir, 'foo.bar')
>> @@ -58,6 +89,93 @@ class TestIncrementalBackup(iotests.QMPTestCase):
>> iotests.qemu_img('create', '-f', fmt, img, size)
>> self.files.append(img)
>> +
>> + def create_full_backup(self, drive='drive0'):
>> + res = self.vm.qmp('drive-backup', device=drive,
>> + sync='full', format=iotests.imgfmt,
>> + target=self.full_bak)
>> + self.assert_qmp(res, 'return', {})
>> + self.wait_until_completed(drive)
>> + self.check_full_backup()
>> + self.files.append(self.full_bak)
>> +
>> +
>> + def check_full_backup(self):
>> + self.assertTrue(iotests.compare_images(self.test_img,
>> self.full_bak))
>> +
>> +
>> + def add_bitmap(self, name, node='drive0'):
>> + bitmap = Bitmap(name, node)
>> + self.bitmaps.append(bitmap)
>> + result = self.vm.qmp('block-dirty-bitmap-add', node=bitmap.node,
>> + name=bitmap.name)
>> + self.assert_qmp(result, 'return', {})
>> + return bitmap
>> +
>> +
>> + def create_incremental(self, bitmap=None, num=None,
>> + parent=None, parentFormat=None,
>> validate=True):
>> + if bitmap is None:
>> + bitmap = self.bitmaps[-1]
>> +
>> + # If this is the first incremental backup for a bitmap,
>> + # use the full backup as a backing image. Otherwise, use
>> + # the last incremental backup.
>> + if parent is None:
>> + if bitmap.num is 0:
>
> Why not == 0?
>
Just having a really good time in python.
I think "is" tests instances; it's like a strict equals. == is
equivalence as you and I are used to it. In this case, it winds up being
the same because python has some numerical objects cached, and any
equation that evaluates to 0 evaluates to the /same/ 0.
== is more correct, though, apparently.
>> + parent = self.full_bak
>> + else:
>> + parent = self.bitmaps[-1].last_target()
>
> Is this intentional or should this be bitmap.last_target()? In this
> patch, no caller of create_incremental() gives any parameter, so there's
> no difference.
>
Vestigial from the standalone edition. 'bitmap' should be preferred over
bitmaps[-1], yes.
>> +
>> + target = bitmap.new_target(num)
>> + self.img_create(target, iotests.imgfmt, parent=parent)
>> +
>> + result = self.vm.qmp('drive-backup', device=bitmap.node,
>> + sync='dirty-bitmap', bitmap=bitmap.name,
>> + format=iotests.imgfmt, target=target,
>> + mode='existing')
>> + self.assert_qmp(result, 'return', {})
>> +
>> + event = self.wait_until_completed(bitmap.node,
>> check_offset=validate)
>> + if validate:
>> + return self.check_incremental(target)
>> +
>> +
>> + def check_incremental(self, target=None):
>> + if target is None:
>> + target = self.bitmaps[-1].last_target()
>> + self.assertTrue(iotests.compare_images(self.test_img, target))
>> + return True
>> +
>> +
>> + def hmp_io_writes(self, drive, patterns):
>> + for pattern in patterns:
>> + self.vm.hmp_qemu_io(drive, 'write -P%s %s %s' % pattern)
>> + self.vm.hmp_qemu_io(drive, 'flush')
>> +
>> +
>> + # Create a bitmap and full backup before VM execution begins,
>> + # then create a series of incremental backups during execution.
>> + def test_incremental_simple(self):
>> + self.create_full_backup()
>> + self.add_bitmap('bitmap0', 'drive0')
>> + self.vm.hmp('c')
>
> self.vm.qmp('continue') works, too, but as I said above, I think
> accel=qtest should be enough so you may not need this at all.
>
> (I'm saying this because we all know that QMP > HMP (obviously))
>
>
> So I had some small questions which I think I want to have answers
> before giving an R-b, but the test logic looks good to me.
>
> Max
>
Explanation above covers this; a more human-focused demi-interactive
version preceded this iotest.
I'll excise it and just use comments to create the same documentation
effect.
>> + # Sanity: Create a "hollow" incremental backup
>> + self.create_incremental()
>> + # Three writes: One complete overwrite, one new segment,
>> + # and one partial overlap.
>> + self.hmp_io_writes('drive0', (('0xab', 0, 512),
>> + ('0xfe', '16M', '256k'),
>> + ('0x64', '32736k', '64k')))
>> + self.create_incremental()
>> + # Three more writes, one of each kind, like above
>> + self.hmp_io_writes('drive0', (('0x9a', 0, 512),
>> + ('0x55', '8M', '352k'),
>> + ('0x78', '15872k', '1M')))
>> + self.create_incremental()
>> + return True
>> +
>> +
>> def test_sync_dirty_bitmap_missing(self):
>> self.assert_no_active_block_jobs()
>> self.files.append(self.foo_img)
>> diff --git a/tests/qemu-iotests/112.out b/tests/qemu-iotests/112.out
>> index fbc63e6..8d7e996 100644
>> --- a/tests/qemu-iotests/112.out
>> +++ b/tests/qemu-iotests/112.out
>> @@ -1,5 +1,5 @@
>> -..
>> +...
>> ----------------------------------------------------------------------
>> -Ran 2 tests
>> +Ran 3 tests
>> OK
>> diff --git a/tests/qemu-iotests/iotests.py
>> b/tests/qemu-iotests/iotests.py
>> index 241b5ee..6bff935 100644
>> --- a/tests/qemu-iotests/iotests.py
>> +++ b/tests/qemu-iotests/iotests.py
>> @@ -88,6 +88,11 @@ class VM(object):
>> '-display', 'none', '-vga', 'none']
>> self._num_drives = 0
>> + # Add arbitrary arguments to the command-line.
>> + def add_args(self, arglist):
>> + self._args = self._args + arglist
>> + return self
>> +
>> # This can be used to add an unused monitor instance.
>> def add_monitor_telnet(self, ip, port):
>> args = 'tcp:%s:%d,server,nowait,telnet' % (ip, port)
>> @@ -109,23 +114,24 @@ class VM(object):
>> self._num_drives += 1
>> return self
>> + def hmp(self, args):
>> + return self.qmp('human-monitor-command',
>> + command_line=args)
>> +
>> def pause_drive(self, drive, event=None):
>> '''Pause drive r/w operations'''
>> if not event:
>> self.pause_drive(drive, "read_aio")
>> self.pause_drive(drive, "write_aio")
>> return
>> - self.qmp('human-monitor-command',
>> - command_line='qemu-io %s "break %s bp_%s"' %
>> (drive, event, drive))
>> + self.hmp('qemu-io %s "break %s bp_%s"' % (drive, event, drive))
>> def resume_drive(self, drive):
>> - self.qmp('human-monitor-command',
>> - command_line='qemu-io %s "remove_break bp_%s"' %
>> (drive, drive))
>> + self.hmp('qemu-io %s "remove_break bp_%s"' % (drive, drive))
>> def hmp_qemu_io(self, drive, cmd):
>> '''Write to a given drive using an HMP command'''
>> - return self.qmp('human-monitor-command',
>> - command_line='qemu-io %s "%s"' % (drive, cmd))
>> + return self.hmp('qemu-io %s "%s"' % (drive, cmd))
>> def add_fd(self, fd, fdset, opaque, opts=''):
>> '''Pass a file descriptor to the VM'''
>
next prev parent reply other threads:[~2015-02-11 22:03 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-10 1:35 [Qemu-devel] [PATCH v12 00/17] block: incremental backup series John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 01/17] qapi: Add optional field "name" to block dirty bitmap John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 02/17] qmp: Add block-dirty-bitmap-add and block-dirty-bitmap-remove John Snow
2015-02-10 21:56 ` Max Reitz
2015-02-13 22:24 ` Eric Blake
2015-02-13 22:39 ` John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 03/17] block: Introduce bdrv_dirty_bitmap_granularity() John Snow
2015-02-10 22:03 ` Max Reitz
2015-02-11 18:57 ` John Snow
2015-02-11 18:58 ` Max Reitz
2015-02-10 22:13 ` Max Reitz
2015-02-10 22:15 ` John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 04/17] hbitmap: add hbitmap_merge John Snow
2015-02-10 22:16 ` Max Reitz
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 05/17] qmp: Add block-dirty-bitmap-enable and block-dirty-bitmap-disable John Snow
2015-02-11 16:26 ` Max Reitz
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 06/17] block: Add bitmap successors John Snow
2015-02-11 16:50 ` Max Reitz
2015-02-11 16:51 ` John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 07/17] qmp: Add support of "dirty-bitmap" sync mode for drive-backup John Snow
2015-02-11 17:47 ` Max Reitz
2015-02-11 17:54 ` John Snow
2015-02-11 18:18 ` Max Reitz
2015-02-11 18:31 ` John Snow
2015-02-11 18:33 ` Max Reitz
2015-02-11 21:13 ` John Snow
2015-02-13 17:33 ` Vladimir Sementsov-Ogievskiy
2015-02-13 18:35 ` John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 08/17] qmp: add block-dirty-bitmap-clear John Snow
2015-02-11 18:28 ` Max Reitz
2015-02-11 18:36 ` John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 09/17] qapi: Add transaction support to block-dirty-bitmap operations John Snow
2015-02-11 19:07 ` Max Reitz
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 10/17] qmp: Add dirty bitmap status fields in query-block John Snow
2015-02-11 19:10 ` Max Reitz
2015-02-11 19:19 ` John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 11/17] block: add BdrvDirtyBitmap documentation John Snow
2015-02-11 19:14 ` Max Reitz
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 12/17] block: Ensure consistent bitmap function prototypes John Snow
2015-02-11 19:20 ` Max Reitz
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 13/17] iotests: add invalid input incremental backup tests John Snow
2015-02-11 20:45 ` Max Reitz
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 14/17] iotests: add simple incremental backup case John Snow
2015-02-11 21:40 ` Max Reitz
2015-02-11 22:02 ` John Snow [this message]
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 15/17] iotests: add transactional incremental backup test John Snow
2015-02-11 21:49 ` Max Reitz
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 16/17] blkdebug: fix "once" rule John Snow
2015-02-11 21:50 ` Max Reitz
2015-02-11 22:04 ` John Snow
2015-02-10 1:35 ` [Qemu-devel] [PATCH v12 17/17] iotests: add incremental backup failure recovery test John Snow
2015-02-11 22:01 ` Max Reitz
2015-02-11 22:08 ` John Snow
2015-02-11 22:11 ` Max Reitz
2015-02-10 16:32 ` [Qemu-devel] [PATCH v12 00/17] block: incremental backup series John Snow
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=54DBD18E.10703@redhat.com \
--to=jsnow@redhat.com \
--cc=armbru@redhat.com \
--cc=famz@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=vsementsov@parallels.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 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.