mirror of https://gitee.com/openkylin/qemu.git
qemu-iotests: add testcases for mirroring on-source-error/on-target-error
The new options are tested with blkdebug on both the source and the target. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
9eb80eadd4
commit
9dfa9f5930
|
@ -292,6 +292,259 @@ class TestMirrorNoBacking(ImageMirroringTestCase):
|
|||
self.assertTrue(self.compare_images(test_img, target_img),
|
||||
'target image does not match source after mirroring')
|
||||
|
||||
class TestReadErrors(ImageMirroringTestCase):
|
||||
image_len = 2 * 1024 * 1024 # MB
|
||||
|
||||
# this should be a multiple of twice the default granularity
|
||||
# so that we hit this offset first in state 1
|
||||
MIRROR_GRANULARITY = 1024 * 1024
|
||||
|
||||
def create_blkdebug_file(self, name, event, errno):
|
||||
file = open(name, 'w')
|
||||
file.write('''
|
||||
[inject-error]
|
||||
state = "1"
|
||||
event = "%s"
|
||||
errno = "%d"
|
||||
immediately = "off"
|
||||
once = "on"
|
||||
sector = "%d"
|
||||
|
||||
[set-state]
|
||||
state = "1"
|
||||
event = "%s"
|
||||
new_state = "2"
|
||||
|
||||
[set-state]
|
||||
state = "2"
|
||||
event = "%s"
|
||||
new_state = "1"
|
||||
''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event))
|
||||
file.close()
|
||||
|
||||
def setUp(self):
|
||||
self.blkdebug_file = backing_img + ".blkdebug"
|
||||
self.create_image(backing_img, TestReadErrors.image_len)
|
||||
self.create_blkdebug_file(self.blkdebug_file, "read_aio", 5)
|
||||
qemu_img('create', '-f', iotests.imgfmt,
|
||||
'-o', 'backing_file=blkdebug:%s:%s,backing_fmt=raw'
|
||||
% (self.blkdebug_file, backing_img),
|
||||
test_img)
|
||||
self.vm = iotests.VM().add_drive(test_img)
|
||||
self.vm.launch()
|
||||
|
||||
def tearDown(self):
|
||||
self.vm.shutdown()
|
||||
os.remove(test_img)
|
||||
os.remove(backing_img)
|
||||
os.remove(self.blkdebug_file)
|
||||
|
||||
def test_report_read(self):
|
||||
self.assert_no_active_mirrors()
|
||||
|
||||
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
|
||||
target=target_img)
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
completed = False
|
||||
error = False
|
||||
while not completed:
|
||||
for event in self.vm.get_qmp_events(wait=True):
|
||||
if event['event'] == 'BLOCK_JOB_ERROR':
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'read')
|
||||
error = True
|
||||
elif event['event'] == 'BLOCK_JOB_READY':
|
||||
self.assertTrue(False, 'job completed unexpectedly')
|
||||
elif event['event'] == 'BLOCK_JOB_COMPLETED':
|
||||
self.assertTrue(error, 'job completed unexpectedly')
|
||||
self.assert_qmp(event, 'data/type', 'mirror')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/error', 'Input/output error')
|
||||
self.assert_qmp(event, 'data/len', self.image_len)
|
||||
completed = True
|
||||
|
||||
self.assert_no_active_mirrors()
|
||||
self.vm.shutdown()
|
||||
|
||||
def test_ignore_read(self):
|
||||
self.assert_no_active_mirrors()
|
||||
|
||||
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
|
||||
target=target_img, on_source_error='ignore')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
event = self.vm.get_qmp_event(wait=True)
|
||||
self.assertEquals(event['event'], 'BLOCK_JOB_ERROR')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'read')
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
self.assert_qmp(result, 'return[0]/paused', False)
|
||||
self.complete_and_wait()
|
||||
self.vm.shutdown()
|
||||
|
||||
def test_stop_read(self):
|
||||
self.assert_no_active_mirrors()
|
||||
|
||||
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
|
||||
target=target_img, on_source_error='stop')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
error = False
|
||||
ready = False
|
||||
while not ready:
|
||||
for event in self.vm.get_qmp_events(wait=True):
|
||||
if event['event'] == 'BLOCK_JOB_ERROR':
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'read')
|
||||
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
self.assert_qmp(result, 'return[0]/paused', True)
|
||||
self.assert_qmp(result, 'return[0]/io-status', 'failed')
|
||||
|
||||
result = self.vm.qmp('block-job-resume', device='drive0')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
error = True
|
||||
elif event['event'] == 'BLOCK_JOB_READY':
|
||||
self.assertTrue(error, 'job completed unexpectedly')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
ready = True
|
||||
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
self.assert_qmp(result, 'return[0]/paused', False)
|
||||
self.assert_qmp(result, 'return[0]/io-status', 'ok')
|
||||
|
||||
self.complete_and_wait(wait_ready=False)
|
||||
self.assert_no_active_mirrors()
|
||||
self.vm.shutdown()
|
||||
|
||||
class TestWriteErrors(ImageMirroringTestCase):
|
||||
image_len = 2 * 1024 * 1024 # MB
|
||||
|
||||
# this should be a multiple of twice the default granularity
|
||||
# so that we hit this offset first in state 1
|
||||
MIRROR_GRANULARITY = 1024 * 1024
|
||||
|
||||
def create_blkdebug_file(self, name, event, errno):
|
||||
file = open(name, 'w')
|
||||
file.write('''
|
||||
[inject-error]
|
||||
state = "1"
|
||||
event = "%s"
|
||||
errno = "%d"
|
||||
immediately = "off"
|
||||
once = "on"
|
||||
sector = "%d"
|
||||
|
||||
[set-state]
|
||||
state = "1"
|
||||
event = "%s"
|
||||
new_state = "2"
|
||||
|
||||
[set-state]
|
||||
state = "2"
|
||||
event = "%s"
|
||||
new_state = "1"
|
||||
''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event))
|
||||
file.close()
|
||||
|
||||
def setUp(self):
|
||||
self.blkdebug_file = target_img + ".blkdebug"
|
||||
self.create_image(backing_img, TestWriteErrors.image_len)
|
||||
self.create_blkdebug_file(self.blkdebug_file, "write_aio", 5)
|
||||
qemu_img('create', '-f', iotests.imgfmt, '-obacking_file=%s' %(backing_img), test_img)
|
||||
self.vm = iotests.VM().add_drive(test_img)
|
||||
self.target_img = 'blkdebug:%s:%s' % (self.blkdebug_file, target_img)
|
||||
qemu_img('create', '-f', iotests.imgfmt, '-osize=%d' %(TestWriteErrors.image_len), target_img)
|
||||
self.vm.launch()
|
||||
|
||||
def tearDown(self):
|
||||
self.vm.shutdown()
|
||||
os.remove(test_img)
|
||||
os.remove(backing_img)
|
||||
os.remove(self.blkdebug_file)
|
||||
|
||||
def test_report_write(self):
|
||||
self.assert_no_active_mirrors()
|
||||
|
||||
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
|
||||
mode='existing', target=self.target_img)
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
completed = False
|
||||
error = False
|
||||
while not completed:
|
||||
for event in self.vm.get_qmp_events(wait=True):
|
||||
if event['event'] == 'BLOCK_JOB_ERROR':
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'write')
|
||||
error = True
|
||||
elif event['event'] == 'BLOCK_JOB_READY':
|
||||
self.assertTrue(False, 'job completed unexpectedly')
|
||||
elif event['event'] == 'BLOCK_JOB_COMPLETED':
|
||||
self.assertTrue(error, 'job completed unexpectedly')
|
||||
self.assert_qmp(event, 'data/type', 'mirror')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/error', 'Input/output error')
|
||||
self.assert_qmp(event, 'data/len', self.image_len)
|
||||
completed = True
|
||||
|
||||
self.assert_no_active_mirrors()
|
||||
self.vm.shutdown()
|
||||
|
||||
def test_ignore_write(self):
|
||||
self.assert_no_active_mirrors()
|
||||
|
||||
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
|
||||
mode='existing', target=self.target_img,
|
||||
on_target_error='ignore')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
event = self.vm.get_qmp_event(wait=True)
|
||||
self.assertEquals(event['event'], 'BLOCK_JOB_ERROR')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'write')
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
self.assert_qmp(result, 'return[0]/paused', False)
|
||||
self.complete_and_wait()
|
||||
self.vm.shutdown()
|
||||
|
||||
def test_stop_write(self):
|
||||
self.assert_no_active_mirrors()
|
||||
|
||||
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
|
||||
mode='existing', target=self.target_img,
|
||||
on_target_error='stop')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
error = False
|
||||
ready = False
|
||||
while not ready:
|
||||
for event in self.vm.get_qmp_events(wait=True):
|
||||
if event['event'] == 'BLOCK_JOB_ERROR':
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
self.assert_qmp(event, 'data/operation', 'write')
|
||||
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
self.assert_qmp(result, 'return[0]/paused', True)
|
||||
self.assert_qmp(result, 'return[0]/io-status', 'failed')
|
||||
|
||||
result = self.vm.qmp('block-job-resume', device='drive0')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
result = self.vm.qmp('query-block-jobs')
|
||||
self.assert_qmp(result, 'return[0]/paused', False)
|
||||
self.assert_qmp(result, 'return[0]/io-status', 'ok')
|
||||
error = True
|
||||
elif event['event'] == 'BLOCK_JOB_READY':
|
||||
self.assertTrue(error, 'job completed unexpectedly')
|
||||
self.assert_qmp(event, 'data/device', 'drive0')
|
||||
ready = True
|
||||
|
||||
self.complete_and_wait(wait_ready=False)
|
||||
self.assert_no_active_mirrors()
|
||||
self.vm.shutdown()
|
||||
|
||||
class TestSetSpeed(ImageMirroringTestCase):
|
||||
image_len = 80 * 1024 * 1024 # MB
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
............
|
||||
..................
|
||||
----------------------------------------------------------------------
|
||||
Ran 12 tests
|
||||
Ran 18 tests
|
||||
|
||||
OK
|
||||
|
|
|
@ -106,6 +106,10 @@ def qmp(self, cmd, **args):
|
|||
|
||||
return self._qmp.cmd(cmd, args=qmp_args)
|
||||
|
||||
def get_qmp_event(self, wait=False):
|
||||
'''Poll for one queued QMP events and return it'''
|
||||
return self._qmp.pull_event(wait=wait)
|
||||
|
||||
def get_qmp_events(self, wait=False):
|
||||
'''Poll for queued QMP events and return a list of dicts'''
|
||||
events = self._qmp.get_events(wait=wait)
|
||||
|
|
Loading…
Reference in New Issue