32
34
result = self.vm.qmp('query-block-jobs')
33
35
self.assert_qmp(result, 'return', [])
37
def cancel_and_wait(self, drive='drive0'):
38
'''Cancel a block job and wait for it to finish'''
39
result = self.vm.qmp('block-job-cancel', device=drive)
40
self.assert_qmp(result, 'return', {})
44
for event in self.vm.get_qmp_events(wait=True):
45
if event['event'] == 'BLOCK_JOB_CANCELLED':
46
self.assert_qmp(event, 'data/type', 'stream')
47
self.assert_qmp(event, 'data/device', drive)
50
self.assert_no_active_streams()
52
def create_image(self, name, size):
53
file = open(name, 'w')
56
sector = struct.pack('>l504xl', i / 512, i / 512)
35
62
class TestSingleDrive(ImageStreamingTestCase):
36
63
image_len = 1 * 1024 * 1024 # MB
39
qemu_img('create', backing_img, str(TestSingleDrive.image_len))
40
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
66
self.create_image(backing_img, TestSingleDrive.image_len)
67
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
68
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
41
69
self.vm = iotests.VM().add_drive(test_img)
44
72
def tearDown(self):
46
74
os.remove(test_img)
47
76
os.remove(backing_img)
49
78
def test_stream(self):
50
79
self.assert_no_active_streams()
52
result = self.vm.qmp('block_stream', device='drive0')
53
self.assert_qmp(result, 'return', {})
57
for event in self.vm.get_qmp_events(wait=True):
58
if event['event'] == 'BLOCK_JOB_COMPLETED':
59
self.assert_qmp(event, 'data/type', 'stream')
60
self.assert_qmp(event, 'data/device', 'drive0')
61
self.assert_qmp(event, 'data/offset', self.image_len)
62
self.assert_qmp(event, 'data/len', self.image_len)
65
self.assert_no_active_streams()
67
self.assertFalse('sectors not allocated' in qemu_io('-c', 'map', test_img),
68
'image file not fully populated after streaming')
81
result = self.vm.qmp('block-stream', device='drive0')
82
self.assert_qmp(result, 'return', {})
86
for event in self.vm.get_qmp_events(wait=True):
87
if event['event'] == 'BLOCK_JOB_COMPLETED':
88
self.assert_qmp(event, 'data/type', 'stream')
89
self.assert_qmp(event, 'data/device', 'drive0')
90
self.assert_qmp(event, 'data/offset', self.image_len)
91
self.assert_qmp(event, 'data/len', self.image_len)
94
self.assert_no_active_streams()
97
self.assertEqual(qemu_io('-c', 'map', backing_img),
98
qemu_io('-c', 'map', test_img),
99
'image file map does not match backing file after streaming')
101
def test_stream_partial(self):
102
self.assert_no_active_streams()
104
result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
105
self.assert_qmp(result, 'return', {})
109
for event in self.vm.get_qmp_events(wait=True):
110
if event['event'] == 'BLOCK_JOB_COMPLETED':
111
self.assert_qmp(event, 'data/type', 'stream')
112
self.assert_qmp(event, 'data/device', 'drive0')
113
self.assert_qmp(event, 'data/offset', self.image_len)
114
self.assert_qmp(event, 'data/len', self.image_len)
117
self.assert_no_active_streams()
120
self.assertEqual(qemu_io('-c', 'map', mid_img),
121
qemu_io('-c', 'map', test_img),
122
'image file map does not match backing file after streaming')
70
124
def test_device_not_found(self):
71
result = self.vm.qmp('block_stream', device='nonexistent')
125
result = self.vm.qmp('block-stream', device='nonexistent')
72
126
self.assert_qmp(result, 'error/class', 'DeviceNotFound')
74
128
class TestStreamStop(ImageStreamingTestCase):
91
145
self.assert_no_active_streams()
93
result = self.vm.qmp('block_stream', device='drive0')
147
result = self.vm.qmp('block-stream', device='drive0')
94
148
self.assert_qmp(result, 'return', {})
97
151
events = self.vm.get_qmp_events(wait=False)
98
152
self.assertEqual(events, [], 'unexpected QMP event: %s' % events)
100
self.vm.qmp('block_job_cancel', device='drive0')
101
self.assert_qmp(result, 'return', {})
105
for event in self.vm.get_qmp_events(wait=True):
106
if event['event'] == 'BLOCK_JOB_CANCELLED':
107
self.assert_qmp(event, 'data/type', 'stream')
108
self.assert_qmp(event, 'data/device', 'drive0')
111
self.assert_no_active_streams()
113
# This is a short performance test which is not run by default.
114
# Invoke "IMGFMT=qed ./030 TestSetSpeed.perf_test_set_speed"
154
self.cancel_and_wait()
115
156
class TestSetSpeed(ImageStreamingTestCase):
116
157
image_len = 80 * 1024 * 1024 # MB
148
191
self.assert_no_active_streams()
193
def test_set_speed(self):
194
self.assert_no_active_streams()
196
result = self.vm.qmp('block-stream', device='drive0')
197
self.assert_qmp(result, 'return', {})
200
result = self.vm.qmp('query-block-jobs')
201
self.assert_qmp(result, 'return[0]/device', 'drive0')
202
self.assert_qmp(result, 'return[0]/speed', 0)
204
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
205
self.assert_qmp(result, 'return', {})
207
# Ensure the speed we set was accepted
208
result = self.vm.qmp('query-block-jobs')
209
self.assert_qmp(result, 'return[0]/device', 'drive0')
210
self.assert_qmp(result, 'return[0]/speed', 8 * 1024 * 1024)
212
self.cancel_and_wait()
214
# Check setting speed in block-stream works
215
result = self.vm.qmp('block-stream', device='drive0', speed=4 * 1024 * 1024)
216
self.assert_qmp(result, 'return', {})
218
result = self.vm.qmp('query-block-jobs')
219
self.assert_qmp(result, 'return[0]/device', 'drive0')
220
self.assert_qmp(result, 'return[0]/speed', 4 * 1024 * 1024)
222
self.cancel_and_wait()
224
def test_set_speed_invalid(self):
225
self.assert_no_active_streams()
227
result = self.vm.qmp('block-stream', device='drive0', speed=-1)
228
self.assert_qmp(result, 'error/class', 'InvalidParameter')
229
self.assert_qmp(result, 'error/data/name', 'speed')
231
self.assert_no_active_streams()
233
result = self.vm.qmp('block-stream', device='drive0')
234
self.assert_qmp(result, 'return', {})
236
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
237
self.assert_qmp(result, 'error/class', 'InvalidParameter')
238
self.assert_qmp(result, 'error/data/name', 'speed')
240
self.cancel_and_wait()
150
242
if __name__ == '__main__':
151
243
iotests.main(supported_fmts=['qcow2', 'qed'])