@@ -70,7 +70,9 @@ class ImageCommitTestCase(iotests.QMPTestCase):
70
70
self .wait_for_complete ()
71
71
72
72
class TestSingleDrive (ImageCommitTestCase ):
73
- image_len = 1 * 1024 * 1024
73
+ # Need some space after the copied data so that throttling is effective in
74
+ # tests that use it rather than just completing the job immediately
75
+ image_len = 2 * 1024 * 1024
74
76
test_len = 1 * 1024 * 256
75
77
76
78
def setUp (self ):
@@ -79,7 +81,9 @@ class TestSingleDrive(ImageCommitTestCase):
79
81
qemu_img ('create' , '-f' , iotests .imgfmt , '-o' , 'backing_file=%s' % mid_img , test_img )
80
82
qemu_io ('-f' , 'raw' , '-c' , 'write -P 0xab 0 524288' , backing_img )
81
83
qemu_io ('-f' , iotests .imgfmt , '-c' , 'write -P 0xef 524288 524288' , mid_img )
82
- self .vm = iotests .VM ().add_drive (test_img )
84
+ self .vm = iotests .VM ().add_drive (test_img , interface = "none" )
85
+ self .vm .add_device ("virtio-scsi-pci" )
86
+ self .vm .add_device ("scsi-hd,id=scsi0,drive=drive0" )
83
87
self .vm .launch ()
84
88
85
89
def tearDown (self ):
@@ -131,6 +135,33 @@ class TestSingleDrive(ImageCommitTestCase):
131
135
self .assert_qmp (result , 'error/class' , 'GenericError' )
132
136
self .assert_qmp (result , 'error/desc' , 'Base \' %s\' not found' % mid_img )
133
137
138
+ # When the job is running on a BB that is automatically deleted on hot
139
+ # unplug, the job is cancelled when the device disappears
140
+ def test_hot_unplug (self ):
141
+ if self .image_len == 0 :
142
+ return
143
+
144
+ self .assert_no_active_block_jobs ()
145
+ result = self .vm .qmp ('block-commit' , device = 'drive0' , top = mid_img ,
146
+ base = backing_img , speed = (self .image_len / 4 ))
147
+ self .assert_qmp (result , 'return' , {})
148
+ result = self .vm .qmp ('device_del' , id = 'scsi0' )
149
+ self .assert_qmp (result , 'return' , {})
150
+
151
+ cancelled = False
152
+ deleted = False
153
+ while not cancelled or not deleted :
154
+ for event in self .vm .get_qmp_events (wait = True ):
155
+ if event ['event' ] == 'DEVICE_DELETED' :
156
+ self .assert_qmp (event , 'data/device' , 'scsi0' )
157
+ deleted = True
158
+ elif event ['event' ] == 'BLOCK_JOB_CANCELLED' :
159
+ self .assert_qmp (event , 'data/device' , 'drive0' )
160
+ cancelled = True
161
+ else :
162
+ self .fail ("Unexpected event %s" % (event ['event' ]))
163
+
164
+ self .assert_no_active_block_jobs ()
134
165
135
166
class TestRelativePaths (ImageCommitTestCase ):
136
167
image_len = 1 * 1024 * 1024
0 commit comments