qemu-iotests/199: better catch postcopy time
The test aims to test _postcopy_ migration, and wants to do some write operations during postcopy time. Test considers migrate status=complete event on source as start of postcopy. This is completely wrong, completion is completion of the whole migration process. Let's instead consider destination start as start of postcopy, and use RESUME event for it. Next, as migration finish, let's use migration status=complete event on target, as such method is closer to what libvirt or another user will do, than tracking number of dirty-bitmaps. Finally, add a possibility to dump events for debug. And if set debug to True, we see, that actual postcopy period is very small relatively to the whole test duration time (~0.2 seconds to >40 seconds for me). This means, that test is very inefficient in what it supposed to do. Let's improve it in following commits. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Reviewed-by: Andrey Shinkevich <andrey.shinkevich@virtuozzo.com> Tested-by: Eric Blake <eblake@redhat.com> Message-Id: <20200727194236.19551-4-vsementsov@virtuozzo.com> Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
f3f483ac63
commit
09feea6cf5
|
@ -20,17 +20,43 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import iotests
|
import iotests
|
||||||
import time
|
|
||||||
from iotests import qemu_img
|
from iotests import qemu_img
|
||||||
|
|
||||||
|
debug = False
|
||||||
|
|
||||||
disk_a = os.path.join(iotests.test_dir, 'disk_a')
|
disk_a = os.path.join(iotests.test_dir, 'disk_a')
|
||||||
disk_b = os.path.join(iotests.test_dir, 'disk_b')
|
disk_b = os.path.join(iotests.test_dir, 'disk_b')
|
||||||
size = '256G'
|
size = '256G'
|
||||||
fifo = os.path.join(iotests.test_dir, 'mig_fifo')
|
fifo = os.path.join(iotests.test_dir, 'mig_fifo')
|
||||||
|
|
||||||
|
|
||||||
|
def event_seconds(event):
|
||||||
|
return event['timestamp']['seconds'] + \
|
||||||
|
event['timestamp']['microseconds'] / 1000000.0
|
||||||
|
|
||||||
|
|
||||||
|
def event_dist(e1, e2):
|
||||||
|
return event_seconds(e2) - event_seconds(e1)
|
||||||
|
|
||||||
|
|
||||||
class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase):
|
class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
if debug:
|
||||||
|
self.vm_a_events += self.vm_a.get_qmp_events()
|
||||||
|
self.vm_b_events += self.vm_b.get_qmp_events()
|
||||||
|
for e in self.vm_a_events:
|
||||||
|
e['vm'] = 'SRC'
|
||||||
|
for e in self.vm_b_events:
|
||||||
|
e['vm'] = 'DST'
|
||||||
|
events = (self.vm_a_events + self.vm_b_events)
|
||||||
|
events = [(e['timestamp']['seconds'],
|
||||||
|
e['timestamp']['microseconds'],
|
||||||
|
e['vm'],
|
||||||
|
e['event'],
|
||||||
|
e.get('data', '')) for e in events]
|
||||||
|
for e in sorted(events):
|
||||||
|
print('{}.{:06} {} {} {}'.format(*e))
|
||||||
|
|
||||||
self.vm_a.shutdown()
|
self.vm_a.shutdown()
|
||||||
self.vm_b.shutdown()
|
self.vm_b.shutdown()
|
||||||
os.remove(disk_a)
|
os.remove(disk_a)
|
||||||
|
@ -47,6 +73,10 @@ class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase):
|
||||||
self.vm_a.launch()
|
self.vm_a.launch()
|
||||||
self.vm_b.launch()
|
self.vm_b.launch()
|
||||||
|
|
||||||
|
# collect received events for debug
|
||||||
|
self.vm_a_events = []
|
||||||
|
self.vm_b_events = []
|
||||||
|
|
||||||
def test_postcopy(self):
|
def test_postcopy(self):
|
||||||
write_size = 0x40000000
|
write_size = 0x40000000
|
||||||
granularity = 512
|
granularity = 512
|
||||||
|
@ -77,15 +107,13 @@ class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase):
|
||||||
self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk))
|
self.vm_a.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk))
|
||||||
s += 0x10000
|
s += 0x10000
|
||||||
|
|
||||||
bitmaps_cap = {'capability': 'dirty-bitmaps', 'state': True}
|
caps = [{'capability': 'dirty-bitmaps', 'state': True},
|
||||||
events_cap = {'capability': 'events', 'state': True}
|
{'capability': 'events', 'state': True}]
|
||||||
|
|
||||||
result = self.vm_a.qmp('migrate-set-capabilities',
|
result = self.vm_a.qmp('migrate-set-capabilities', capabilities=caps)
|
||||||
capabilities=[bitmaps_cap, events_cap])
|
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
result = self.vm_b.qmp('migrate-set-capabilities',
|
result = self.vm_b.qmp('migrate-set-capabilities', capabilities=caps)
|
||||||
capabilities=[bitmaps_cap])
|
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
result = self.vm_a.qmp('migrate', uri='exec:cat>' + fifo)
|
result = self.vm_a.qmp('migrate', uri='exec:cat>' + fifo)
|
||||||
|
@ -94,24 +122,38 @@ class TestDirtyBitmapPostcopyMigration(iotests.QMPTestCase):
|
||||||
result = self.vm_a.qmp('migrate-start-postcopy')
|
result = self.vm_a.qmp('migrate-start-postcopy')
|
||||||
self.assert_qmp(result, 'return', {})
|
self.assert_qmp(result, 'return', {})
|
||||||
|
|
||||||
while True:
|
event_resume = self.vm_b.event_wait('RESUME')
|
||||||
event = self.vm_a.event_wait('MIGRATION')
|
self.vm_b_events.append(event_resume)
|
||||||
if event['data']['status'] == 'completed':
|
|
||||||
break
|
|
||||||
|
|
||||||
s = 0x8000
|
s = 0x8000
|
||||||
while s < write_size:
|
while s < write_size:
|
||||||
self.vm_b.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk))
|
self.vm_b.hmp_qemu_io('drive0', 'write %d %d' % (s, chunk))
|
||||||
s += 0x10000
|
s += 0x10000
|
||||||
|
|
||||||
result = self.vm_b.qmp('query-block')
|
match = {'data': {'status': 'completed'}}
|
||||||
while len(result['return'][0]['dirty-bitmaps']) > 1:
|
event_complete = self.vm_b.event_wait('MIGRATION', match=match)
|
||||||
time.sleep(2)
|
self.vm_b_events.append(event_complete)
|
||||||
result = self.vm_b.qmp('query-block')
|
|
||||||
|
|
||||||
|
# take queued event, should already been happened
|
||||||
|
event_stop = self.vm_a.event_wait('STOP')
|
||||||
|
self.vm_a_events.append(event_stop)
|
||||||
|
|
||||||
|
downtime = event_dist(event_stop, event_resume)
|
||||||
|
postcopy_time = event_dist(event_resume, event_complete)
|
||||||
|
|
||||||
|
# TODO: assert downtime * 10 < postcopy_time
|
||||||
|
if debug:
|
||||||
|
print('downtime:', downtime)
|
||||||
|
print('postcopy_time:', postcopy_time)
|
||||||
|
|
||||||
|
# Assert that bitmap migration is finished (check that successor bitmap
|
||||||
|
# is removed)
|
||||||
|
result = self.vm_b.qmp('query-block')
|
||||||
|
assert len(result['return'][0]['dirty-bitmaps']) == 1
|
||||||
|
|
||||||
|
# Check content of migrated (and updated by new writes) bitmap
|
||||||
result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256',
|
result = self.vm_b.qmp('x-debug-block-dirty-bitmap-sha256',
|
||||||
node='drive0', name='bitmap')
|
node='drive0', name='bitmap')
|
||||||
|
|
||||||
self.assert_qmp(result, 'return/sha256', sha256)
|
self.assert_qmp(result, 'return/sha256', sha256)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue