Message ID | 1429314609-29776-20-git-send-email-jsnow@redhat.com |
---|---|
State | New |
Headers | show |
On Fri, Apr 17, 2015 at 07:50:07PM -0400, John Snow wrote: > Signed-off-by: John Snow <jsnow@redhat.com> > Reviewed-by: Max Reitz <mreitz@redhat.com> > --- > tests/qemu-iotests/124 | 174 +++++++++++++++++++++++++++++++++++++++++++-- > tests/qemu-iotests/124.out | 4 +- > 2 files changed, 172 insertions(+), 6 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Am 18.04.2015 um 01:50 hat John Snow geschrieben: > Signed-off-by: John Snow <jsnow@redhat.com> > Reviewed-by: Max Reitz <mreitz@redhat.com> > --- > tests/qemu-iotests/124 | 174 +++++++++++++++++++++++++++++++++++++++++++-- > tests/qemu-iotests/124.out | 4 +- > 2 files changed, 172 insertions(+), 6 deletions(-) > > diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124 > index 85675ec..5c3b434 100644 > --- a/tests/qemu-iotests/124 > +++ b/tests/qemu-iotests/124 > @@ -29,6 +29,51 @@ def io_write_patterns(img, patterns): > iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img) > > > +def try_remove(img): > + try: > + os.remove(img) > + except OSError: > + pass > + > + > +class Bitmap: > + def __init__(self, name, drive): > + self.name = name > + self.drive = drive > + self.num = 0 > + self.backups = list() > + > + def base_target(self): > + return (self.drive['backup'], None) > + > + def new_target(self, num=None): > + if num is None: > + num = self.num > + self.num = num + 1 > + base = os.path.join(iotests.test_dir, > + "%s.%s." % (self.drive['id'], self.name)) > + suff = "%i.%s" % (num, self.drive['fmt']) > + target = base + "inc" + suff > + reference = base + "ref" + suff > + self.backups.append((target, reference)) > + return (target, reference) > + > + def last_target(self): > + if self.backups: > + return self.backups[-1] > + return self.base_target() > + > + def del_target(self): > + for image in self.backups.pop(): > + try_remove(image) > + self.num -= 1 > + > + def cleanup(self): > + for backup in self.backups: > + for image in backup: > + try_remove(image) > + > + > class TestIncrementalBackup(iotests.QMPTestCase): > def setUp(self): > self.bitmaps = list() > @@ -73,6 +118,128 @@ class TestIncrementalBackup(iotests.QMPTestCase): > iotests.qemu_img('create', '-f', fmt, img, size) > self.files.append(img) > > + > + def do_qmp_backup(self, error='Input/output error', **kwargs): > + res = self.vm.qmp('drive-backup', **kwargs) > + self.assert_qmp(res, 'return', {}) > + > + event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED", > + match={'data': {'device': kwargs['device']}}) > + self.assertIsNotNone(event) RHEL 6 doesn't have self.assertIsNotNone(), so 124 fails there now. Can you send a follow-up patch to fix this? Kevin
On 05/22/2015 11:02 AM, Kevin Wolf wrote: > Am 18.04.2015 um 01:50 hat John Snow geschrieben: >> Signed-off-by: John Snow <jsnow@redhat.com> >> Reviewed-by: Max Reitz <mreitz@redhat.com> >> --- >> tests/qemu-iotests/124 | 174 +++++++++++++++++++++++++++++++++++++++++++-- >> tests/qemu-iotests/124.out | 4 +- >> 2 files changed, 172 insertions(+), 6 deletions(-) >> >> diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124 >> index 85675ec..5c3b434 100644 >> --- a/tests/qemu-iotests/124 >> +++ b/tests/qemu-iotests/124 >> @@ -29,6 +29,51 @@ def io_write_patterns(img, patterns): >> iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img) >> >> >> +def try_remove(img): >> + try: >> + os.remove(img) >> + except OSError: >> + pass >> + >> + >> +class Bitmap: >> + def __init__(self, name, drive): >> + self.name = name >> + self.drive = drive >> + self.num = 0 >> + self.backups = list() >> + >> + def base_target(self): >> + return (self.drive['backup'], None) >> + >> + def new_target(self, num=None): >> + if num is None: >> + num = self.num >> + self.num = num + 1 >> + base = os.path.join(iotests.test_dir, >> + "%s.%s." % (self.drive['id'], self.name)) >> + suff = "%i.%s" % (num, self.drive['fmt']) >> + target = base + "inc" + suff >> + reference = base + "ref" + suff >> + self.backups.append((target, reference)) >> + return (target, reference) >> + >> + def last_target(self): >> + if self.backups: >> + return self.backups[-1] >> + return self.base_target() >> + >> + def del_target(self): >> + for image in self.backups.pop(): >> + try_remove(image) >> + self.num -= 1 >> + >> + def cleanup(self): >> + for backup in self.backups: >> + for image in backup: >> + try_remove(image) >> + >> + >> class TestIncrementalBackup(iotests.QMPTestCase): >> def setUp(self): >> self.bitmaps = list() >> @@ -73,6 +118,128 @@ class TestIncrementalBackup(iotests.QMPTestCase): >> iotests.qemu_img('create', '-f', fmt, img, size) >> self.files.append(img) >> >> + >> + def do_qmp_backup(self, error='Input/output error', **kwargs): >> + res = self.vm.qmp('drive-backup', **kwargs) >> + self.assert_qmp(res, 'return', {}) >> + >> + event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED", >> + match={'data': {'device': kwargs['device']}}) >> + self.assertIsNotNone(event) > > RHEL 6 doesn't have self.assertIsNotNone(), so 124 fails there now. Can > you send a follow-up patch to fix this? > > Kevin > What's the minimum version requirement for RHEL6, for future information? --js
Am 22.05.2015 um 17:29 hat John Snow geschrieben: > > > On 05/22/2015 11:02 AM, Kevin Wolf wrote: > > Am 18.04.2015 um 01:50 hat John Snow geschrieben: > >> Signed-off-by: John Snow <jsnow@redhat.com> > >> Reviewed-by: Max Reitz <mreitz@redhat.com> > >> --- > >> tests/qemu-iotests/124 | 174 +++++++++++++++++++++++++++++++++++++++++++-- > >> tests/qemu-iotests/124.out | 4 +- > >> 2 files changed, 172 insertions(+), 6 deletions(-) > >> > >> diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124 > >> index 85675ec..5c3b434 100644 > >> --- a/tests/qemu-iotests/124 > >> +++ b/tests/qemu-iotests/124 > >> @@ -29,6 +29,51 @@ def io_write_patterns(img, patterns): > >> iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img) > >> > >> > >> +def try_remove(img): > >> + try: > >> + os.remove(img) > >> + except OSError: > >> + pass > >> + > >> + > >> +class Bitmap: > >> + def __init__(self, name, drive): > >> + self.name = name > >> + self.drive = drive > >> + self.num = 0 > >> + self.backups = list() > >> + > >> + def base_target(self): > >> + return (self.drive['backup'], None) > >> + > >> + def new_target(self, num=None): > >> + if num is None: > >> + num = self.num > >> + self.num = num + 1 > >> + base = os.path.join(iotests.test_dir, > >> + "%s.%s." % (self.drive['id'], self.name)) > >> + suff = "%i.%s" % (num, self.drive['fmt']) > >> + target = base + "inc" + suff > >> + reference = base + "ref" + suff > >> + self.backups.append((target, reference)) > >> + return (target, reference) > >> + > >> + def last_target(self): > >> + if self.backups: > >> + return self.backups[-1] > >> + return self.base_target() > >> + > >> + def del_target(self): > >> + for image in self.backups.pop(): > >> + try_remove(image) > >> + self.num -= 1 > >> + > >> + def cleanup(self): > >> + for backup in self.backups: > >> + for image in backup: > >> + try_remove(image) > >> + > >> + > >> class TestIncrementalBackup(iotests.QMPTestCase): > >> def setUp(self): > >> self.bitmaps = list() > >> @@ -73,6 +118,128 @@ class TestIncrementalBackup(iotests.QMPTestCase): > >> iotests.qemu_img('create', '-f', fmt, img, size) > >> self.files.append(img) > >> > >> + > >> + def do_qmp_backup(self, error='Input/output error', **kwargs): > >> + res = self.vm.qmp('drive-backup', **kwargs) > >> + self.assert_qmp(res, 'return', {}) > >> + > >> + event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED", > >> + match={'data': {'device': kwargs['device']}}) > >> + self.assertIsNotNone(event) > > > > RHEL 6 doesn't have self.assertIsNotNone(), so 124 fails there now. Can > > you send a follow-up patch to fix this? > > > > Kevin > > > > What's the minimum version requirement for RHEL6, for future information? $ python --version Python 2.6.5 Kevin
diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124 index 85675ec..5c3b434 100644 --- a/tests/qemu-iotests/124 +++ b/tests/qemu-iotests/124 @@ -29,6 +29,51 @@ def io_write_patterns(img, patterns): iotests.qemu_io('-c', 'write -P%s %s %s' % pattern, img) +def try_remove(img): + try: + os.remove(img) + except OSError: + pass + + +class Bitmap: + def __init__(self, name, drive): + self.name = name + self.drive = drive + self.num = 0 + self.backups = list() + + def base_target(self): + return (self.drive['backup'], None) + + def new_target(self, num=None): + if num is None: + num = self.num + self.num = num + 1 + base = os.path.join(iotests.test_dir, + "%s.%s." % (self.drive['id'], self.name)) + suff = "%i.%s" % (num, self.drive['fmt']) + target = base + "inc" + suff + reference = base + "ref" + suff + self.backups.append((target, reference)) + return (target, reference) + + def last_target(self): + if self.backups: + return self.backups[-1] + return self.base_target() + + def del_target(self): + for image in self.backups.pop(): + try_remove(image) + self.num -= 1 + + def cleanup(self): + for backup in self.backups: + for image in backup: + try_remove(image) + + class TestIncrementalBackup(iotests.QMPTestCase): def setUp(self): self.bitmaps = list() @@ -73,6 +118,128 @@ class TestIncrementalBackup(iotests.QMPTestCase): iotests.qemu_img('create', '-f', fmt, img, size) self.files.append(img) + + def do_qmp_backup(self, error='Input/output error', **kwargs): + res = self.vm.qmp('drive-backup', **kwargs) + self.assert_qmp(res, 'return', {}) + + event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED", + match={'data': {'device': kwargs['device']}}) + self.assertIsNotNone(event) + + try: + failure = self.dictpath(event, 'data/error') + except AssertionError: + # Backup succeeded. + self.assert_qmp(event, 'data/offset', event['data']['len']) + return True + else: + # Backup failed. + self.assert_qmp(event, 'data/error', error) + return False + + + def create_anchor_backup(self, drive=None): + if drive is None: + drive = self.drives[-1] + res = self.do_qmp_backup(device=drive['id'], sync='full', + format=drive['fmt'], target=drive['backup']) + self.assertTrue(res) + self.files.append(drive['backup']) + return drive['backup'] + + + def make_reference_backup(self, bitmap=None): + if bitmap is None: + bitmap = self.bitmaps[-1] + _, reference = bitmap.last_target() + res = self.do_qmp_backup(device=bitmap.drive['id'], sync='full', + format=bitmap.drive['fmt'], target=reference) + self.assertTrue(res) + + + def add_bitmap(self, name, drive): + bitmap = Bitmap(name, drive) + self.bitmaps.append(bitmap) + result = self.vm.qmp('block-dirty-bitmap-add', node=drive['id'], + name=bitmap.name) + self.assert_qmp(result, 'return', {}) + return bitmap + + + def prepare_backup(self, bitmap=None, parent=None): + if bitmap is None: + bitmap = self.bitmaps[-1] + if parent is None: + parent, _ = bitmap.last_target() + + target, _ = bitmap.new_target() + self.img_create(target, bitmap.drive['fmt'], parent=parent) + return target + + + def create_incremental(self, bitmap=None, parent=None, + parentFormat=None, validate=True): + if bitmap is None: + bitmap = self.bitmaps[-1] + if parent is None: + parent, _ = bitmap.last_target() + + target = self.prepare_backup(bitmap, parent) + res = self.do_qmp_backup(device=bitmap.drive['id'], + sync='dirty-bitmap', bitmap=bitmap.name, + format=bitmap.drive['fmt'], target=target, + mode='existing') + if not res: + bitmap.del_target(); + self.assertFalse(validate) + else: + self.make_reference_backup(bitmap) + return res + + + def check_backups(self): + for bitmap in self.bitmaps: + for incremental, reference in bitmap.backups: + self.assertTrue(iotests.compare_images(incremental, reference)) + last = bitmap.last_target()[0] + self.assertTrue(iotests.compare_images(last, bitmap.drive['file'])) + + + 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') + + + def test_incremental_simple(self): + ''' + Test: Create and verify three incremental backups. + + Create a bitmap and a full backup before VM execution begins, + then create a series of three incremental backups "during execution," + i.e.; after IO requests begin modifying the drive. + ''' + self.create_anchor_backup() + self.add_bitmap('bitmap0', self.drives[0]) + + # 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(self.drives[0]['id'], (('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(self.drives[0]['id'], (('0x9a', 0, 512), + ('0x55', '8M', '352k'), + ('0x78', '15872k', '1M'))) + self.create_incremental() + self.vm.shutdown() + self.check_backups() + + def test_sync_dirty_bitmap_missing(self): self.assert_no_active_block_jobs() self.files.append(self.err_img) @@ -93,11 +260,10 @@ class TestIncrementalBackup(iotests.QMPTestCase): def tearDown(self): self.vm.shutdown() + for bitmap in self.bitmaps: + bitmap.cleanup() for filename in self.files: - try: - os.remove(filename) - except OSError: - pass + try_remove(filename) if __name__ == '__main__': diff --git a/tests/qemu-iotests/124.out b/tests/qemu-iotests/124.out index fbc63e6..8d7e996 100644 --- a/tests/qemu-iotests/124.out +++ b/tests/qemu-iotests/124.out @@ -1,5 +1,5 @@ -.. +... ---------------------------------------------------------------------- -Ran 2 tests +Ran 3 tests OK