diff options
Diffstat (limited to 'tests/qemu-iotests')
41 files changed, 2897 insertions, 2262 deletions
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index 640a6dfd10..1dbc2ddc49 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -304,8 +304,7 @@ class TestParallelOps(iotests.QMPTestCase): result = self.vm.qmp('block-stream', device='node5', base=self.imgs[3], job_id='stream-node6') self.assert_qmp(result, 'error/class', 'GenericError') - event = self.vm.get_qmp_event(wait=True) - self.assertEqual(event['event'], 'BLOCK_JOB_READY') + event = self.vm.event_wait(name='BLOCK_JOB_READY') self.assert_qmp(event, 'data/device', 'commit-drive0') self.assert_qmp(event, 'data/type', 'commit') self.assert_qmp_absent(event, 'data/error') @@ -565,6 +564,8 @@ class TestEIO(TestErrors): self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE) self.assert_qmp(event, 'data/len', self.image_len) completed = True + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') self.assert_no_active_block_jobs() self.vm.shutdown() @@ -596,6 +597,8 @@ class TestEIO(TestErrors): self.assert_qmp(event, 'data/offset', self.image_len) self.assert_qmp(event, 'data/len', self.image_len) completed = True + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') self.assert_no_active_block_jobs() self.vm.shutdown() @@ -637,6 +640,8 @@ class TestEIO(TestErrors): self.assert_qmp(event, 'data/offset', self.image_len) self.assert_qmp(event, 'data/len', self.image_len) completed = True + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') self.assert_no_active_block_jobs() self.vm.shutdown() @@ -663,6 +668,8 @@ class TestEIO(TestErrors): self.assert_qmp(event, 'data/offset', self.STREAM_BUFFER_SIZE) self.assert_qmp(event, 'data/len', self.image_len) completed = True + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') self.assert_no_active_block_jobs() self.vm.shutdown() @@ -722,6 +729,8 @@ class TestENOSPC(TestErrors): self.assert_qmp(event, 'data/offset', self.image_len) self.assert_qmp(event, 'data/len', self.image_len) completed = True + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') self.assert_no_active_block_jobs() self.vm.shutdown() @@ -751,7 +760,9 @@ class TestStreamStop(iotests.QMPTestCase): time.sleep(0.1) events = self.vm.get_qmp_events(wait=False) - self.assertEqual(events, [], 'unexpected QMP event: %s' % events) + for e in events: + self.assert_qmp(e, 'event', 'JOB_STATUS_CHANGE') + self.assert_qmp(e, 'data/id', 'drive0') self.cancel_and_wait(resume=True) diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040 index 90b5b4f2ad..1beb5e6dab 100755 --- a/tests/qemu-iotests/040 +++ b/tests/qemu-iotests/040 @@ -162,6 +162,8 @@ class TestSingleDrive(ImageCommitTestCase): elif event['event'] == 'BLOCK_JOB_CANCELLED': self.assert_qmp(event, 'data/device', 'drive0') cancelled = True + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') else: self.fail("Unexpected event %s" % (event['event'])) diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041 index a860a31e9a..c20ac7da87 100755 --- a/tests/qemu-iotests/041 +++ b/tests/qemu-iotests/041 @@ -445,6 +445,8 @@ new_state = "1" self.assert_qmp(event, 'data/device', 'drive0') self.assert_qmp(event, 'data/error', 'Input/output error') completed = True + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') self.assert_no_active_block_jobs() self.vm.shutdown() @@ -457,6 +459,10 @@ new_state = "1" self.assert_qmp(result, 'return', {}) event = self.vm.get_qmp_event(wait=True) + while event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') + 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') @@ -478,6 +484,10 @@ new_state = "1" self.assert_qmp(result, 'return', {}) event = self.vm.get_qmp_event(wait=True) + while event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') + 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') @@ -608,7 +618,7 @@ new_state = "1" on_target_error='ignore') self.assert_qmp(result, 'return', {}) - event = self.vm.get_qmp_event(wait=True) + event = self.vm.event_wait(name='BLOCK_JOB_ERROR') self.assertEquals(event['event'], 'BLOCK_JOB_ERROR') self.assert_qmp(event, 'data/device', 'drive0') self.assert_qmp(event, 'data/operation', 'write') @@ -784,7 +794,12 @@ class TestGranularity(iotests.QMPTestCase): sync='full', target=target_img, mode='absolute-paths', granularity=8192) self.assert_qmp(result, 'return', {}) + event = self.vm.get_qmp_event(wait=60.0) + while event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', 'drive0') + event = self.vm.get_qmp_event(wait=60.0) + # Failures will manifest as COMPLETED/ERROR. self.assert_qmp(event, 'event', 'BLOCK_JOB_READY') self.complete_and_wait(drive='drive0', wait_ready=False) @@ -1015,9 +1030,9 @@ class TestOrphanedSource(iotests.QMPTestCase): 'read-only': 'on' } self.vm = iotests.VM() - self.vm.add_blockdev(self.qmp_to_opts(blk0)) - self.vm.add_blockdev(self.qmp_to_opts(blk1)) - self.vm.add_blockdev(self.qmp_to_opts(blk2)) + self.vm.add_blockdev(self.vm.qmp_to_opts(blk0)) + self.vm.add_blockdev(self.vm.qmp_to_opts(blk1)) + self.vm.add_blockdev(self.vm.qmp_to_opts(blk2)) self.vm.launch() def tearDown(self): diff --git a/tests/qemu-iotests/086 b/tests/qemu-iotests/086 index cd4494a660..84e3835071 100755 --- a/tests/qemu-iotests/086 +++ b/tests/qemu-iotests/086 @@ -38,7 +38,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 . ./common.filter _supported_fmt qcow2 raw -_supported_proto file nfs +_supported_proto file _supported_os Linux function run_qemu_img() diff --git a/tests/qemu-iotests/094.out b/tests/qemu-iotests/094.out index f52baffe70..665b630b08 100644 --- a/tests/qemu-iotests/094.out +++ b/tests/qemu-iotests/094.out @@ -2,10 +2,17 @@ QA output created by 094 Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/source.IMGFMT', fmt=IMGFMT size=67108864 {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} *** done diff --git a/tests/qemu-iotests/095 b/tests/qemu-iotests/095 index 030adb22e1..72ecc22e1b 100755 --- a/tests/qemu-iotests/095 +++ b/tests/qemu-iotests/095 @@ -72,7 +72,7 @@ _send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return" _send_qemu_cmd $h "{ 'execute': 'block-commit', 'arguments': { 'device': 'test', - 'top': '"${TEST_IMG}.snp1"' } }" "BLOCK_JOB_COMPLETED" + 'top': '"${TEST_IMG}.snp1"' } }" '"status": "null"' _cleanup_qemu diff --git a/tests/qemu-iotests/095.out b/tests/qemu-iotests/095.out index 73875cab40..8c093dfff3 100644 --- a/tests/qemu-iotests/095.out +++ b/tests/qemu-iotests/095.out @@ -11,8 +11,14 @@ virtual size: 5.0M (5242880 bytes) === Running QEMU Live Commit Test === {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "test"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "test"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "test"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "test"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "test", "len": 104857600, "offset": 104857600, "speed": 0, "type": "commit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "test"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "test"}} === Base image info after commit and resize === image: TEST_DIR/t.IMGFMT.base diff --git a/tests/qemu-iotests/109 b/tests/qemu-iotests/109 index d70b574d88..acbd079136 100755 --- a/tests/qemu-iotests/109 +++ b/tests/qemu-iotests/109 @@ -64,7 +64,7 @@ function run_qemu() _send_qemu_cmd $QEMU_HANDLE '' "$qmp_event" if test "$qmp_event" = BLOCK_JOB_ERROR; then - _send_qemu_cmd $QEMU_HANDLE '' "BLOCK_JOB_COMPLETED" + _send_qemu_cmd $QEMU_HANDLE '' '"status": "null"' fi _send_qemu_cmd $QEMU_HANDLE '{"execute":"query-block-jobs"}' "return" _send_qemu_cmd $QEMU_HANDLE '{"execute":"quit"}' "return" diff --git a/tests/qemu-iotests/109.out b/tests/qemu-iotests/109.out index 8a9b93672b..ad0ee6fb48 100644 --- a/tests/qemu-iotests/109.out +++ b/tests/qemu-iotests/109.out @@ -6,23 +6,35 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -32,23 +44,35 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 512, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 197120, "offset": 197120, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 197120, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -58,23 +82,35 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 262144, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -84,23 +120,35 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 1024, "offset": 1024, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 1024, "offset": 1024, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -110,23 +158,35 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 65536, "offset": 65536, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -136,23 +196,35 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -161,23 +233,35 @@ Images are identical. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2560, "offset": 2560, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2560, "offset": 2560, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -186,23 +270,35 @@ Images are identical. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 31457280, "offset": 31457280, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 31457280, "offset": 31457280, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -211,23 +307,35 @@ Images are identical. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 327680, "offset": 327680, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 327680, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -236,23 +344,35 @@ Images are identical. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": LEN, "offset": OFFSET, "speed": 0, "type": "mirror", "error": "Operation not permitted"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} {"return": []} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 2048, "offset": 2048, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 2048, "offset": 2048, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. @@ -261,23 +381,37 @@ Images are identical. Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 {"return": {}} WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw. -Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. -Specify the 'raw' format explicitly to remove the restrictions. + Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted. + Specify the 'raw' format explicitly to remove the restrictions. +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "src"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} {"return": [{"auto-finalize": true, "io-status": "ok", "device": "src", "auto-dismiss": true, "busy": false, "len": 512, "offset": 512, "status": "ready", "paused": false, "speed": 0, "ready": true, "type": "mirror"}]} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "src"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 512, "offset": 512, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "src"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "src"}} Warning: Image size mismatch! Images are identical. *** done diff --git a/tests/qemu-iotests/124 b/tests/qemu-iotests/124 index 8e76e62f93..3ea4ac53f5 100755 --- a/tests/qemu-iotests/124 +++ b/tests/qemu-iotests/124 @@ -151,10 +151,17 @@ class TestIncrementalBackupBase(iotests.QMPTestCase): return self.wait_qmp_backup(kwargs['device'], error) + def ignore_job_status_change_events(self): + while True: + e = self.vm.event_wait(name="JOB_STATUS_CHANGE") + if e['data']['status'] == 'null': + break + def wait_qmp_backup(self, device, error='Input/output error'): event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED", match={'data': {'device': device}}) self.assertNotEqual(event, None) + self.ignore_job_status_change_events() try: failure = self.dictpath(event, 'data/error') @@ -172,6 +179,7 @@ class TestIncrementalBackupBase(iotests.QMPTestCase): event = self.vm.event_wait(name='BLOCK_JOB_CANCELLED', match={'data': {'device': device}}) self.assertNotEqual(event, None) + self.ignore_job_status_change_events() def create_anchor_backup(self, drive=None): diff --git a/tests/qemu-iotests/126.out b/tests/qemu-iotests/126.out index 50d73080fa..17d03d5248 100644 --- a/tests/qemu-iotests/126.out +++ b/tests/qemu-iotests/126.out @@ -3,7 +3,7 @@ QA output created by 126 === Testing plain files === Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 -Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'file:TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 === Testing relative backing filename resolution === diff --git a/tests/qemu-iotests/127.out b/tests/qemu-iotests/127.out index 543d075005..83b522d4c2 100644 --- a/tests/qemu-iotests/127.out +++ b/tests/qemu-iotests/127.out @@ -5,10 +5,17 @@ Formatting 'TEST_DIR/t.IMGFMT.overlay1', fmt=IMGFMT size=65536 backing_file=TEST wrote 42/42 bytes at offset 0 42 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "mirror"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "mirror"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "mirror", "len": 65536, "offset": 65536, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "mirror"}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} *** done diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141 index 2f9d7b9bc2..4246d387a1 100755 --- a/tests/qemu-iotests/141 +++ b/tests/qemu-iotests/141 @@ -107,7 +107,7 @@ test_blockjob \ 'format': '$IMGFMT', 'sync': 'none'}}" \ 'return' \ - 'BLOCK_JOB_CANCELLED' + '"status": "null"' echo echo '=== Testing drive-mirror ===' @@ -124,7 +124,7 @@ test_blockjob \ 'format': '$IMGFMT', 'sync': 'none'}}" \ 'BLOCK_JOB_READY' \ - 'BLOCK_JOB_COMPLETED' + '"status": "null"' echo echo '=== Testing active block-commit ===' @@ -138,7 +138,7 @@ test_blockjob \ "{'execute': 'block-commit', 'arguments': {'job-id': 'job0', 'device': 'drv0'}}" \ 'BLOCK_JOB_READY' \ - 'BLOCK_JOB_COMPLETED' + '"status": "null"' echo echo '=== Testing non-active block-commit ===' @@ -157,7 +157,7 @@ test_blockjob \ 'top': '$TEST_DIR/m.$IMGFMT', 'speed': 1}}" \ 'return' \ - 'BLOCK_JOB_CANCELLED' + '"status": "null"' echo echo '=== Testing block-stream ===' @@ -170,8 +170,7 @@ echo $QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io # With some data to stream (and @speed set to 1), block-stream will not complete -# until we send the block-job-cancel command. Therefore, no event other than -# BLOCK_JOB_CANCELLED will be emitted. +# until we send the block-job-cancel command. test_blockjob \ "{'execute': 'block-stream', @@ -179,7 +178,7 @@ test_blockjob \ 'device': 'drv0', 'speed': 1}}" \ 'return' \ - 'BLOCK_JOB_CANCELLED' + '"status": "null"' _cleanup_qemu diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out index 82e763b68d..f252c86875 100644 --- a/tests/qemu-iotests/141.out +++ b/tests/qemu-iotests/141.out @@ -8,31 +8,50 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m. {"return": {}} Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} {"return": {}} {"error": {"class": "GenericError", "desc": "Node drv0 is in use"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} {"return": {}} === Testing drive-mirror === {"return": {}} Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}} {"return": {}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} {"return": {}} === Testing active block-commit === {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} {"return": {}} {"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} {"return": {}} === Testing non-active block-commit === @@ -40,10 +59,15 @@ Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t. wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} {"return": {}} {"error": {"class": "GenericError", "desc": "Node drv0 is in use"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} {"return": {}} === Testing block-stream === @@ -51,9 +75,14 @@ wrote 1048576/1048576 bytes at offset 0 wrote 1048576/1048576 bytes at offset 0 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}} {"return": {}} {"error": {"class": "GenericError", "desc": "Node drv0 is in use"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}} {"return": {}} *** done diff --git a/tests/qemu-iotests/144 b/tests/qemu-iotests/144 index 00de3c33cf..4b915718cd 100755 --- a/tests/qemu-iotests/144 +++ b/tests/qemu-iotests/144 @@ -93,7 +93,7 @@ _send_qemu_cmd $h "{ 'execute': 'block-job-complete', 'arguments': { 'device': 'virtio0' } - }" "COMPLETED" + }" '"status": "null"' echo echo === Performing Live Snapshot 2 === diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out index 014b2817ee..55299201e4 100644 --- a/tests/qemu-iotests/144.out +++ b/tests/qemu-iotests/144.out @@ -12,10 +12,17 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/ === Performing block-commit on active layer === +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} {"return": {}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "virtio0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "virtio0"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "virtio0"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "virtio0"}} === Performing Live Snapshot 2 === diff --git a/tests/qemu-iotests/155 b/tests/qemu-iotests/155 index 42dae04c83..63a5b5e2c0 100755 --- a/tests/qemu-iotests/155 +++ b/tests/qemu-iotests/155 @@ -63,7 +63,7 @@ class BaseClass(iotests.QMPTestCase): 'driver': iotests.imgfmt, 'file': {'driver': 'file', 'filename': source_img}} - self.vm.add_blockdev(self.qmp_to_opts(blockdev)) + self.vm.add_blockdev(self.vm.qmp_to_opts(blockdev)) self.vm.add_device('virtio-blk,id=qdev0,drive=source') self.vm.launch() diff --git a/tests/qemu-iotests/156 b/tests/qemu-iotests/156 index e75dc4d743..0a9a09802e 100755 --- a/tests/qemu-iotests/156 +++ b/tests/qemu-iotests/156 @@ -119,7 +119,7 @@ _send_qemu_cmd $QEMU_HANDLE \ _send_qemu_cmd $QEMU_HANDLE \ '' \ - 'BLOCK_JOB_COMPLETED' + '"status": "null"' # Remove the source images rm -f "$TEST_IMG{,.backing,.overlay}" diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out index f96a564c1d..34c057b626 100644 --- a/tests/qemu-iotests/156.out +++ b/tests/qemu-iotests/156.out @@ -12,13 +12,20 @@ wrote 131072/131072 bytes at offset 131072 128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} Formatting 'TEST_DIR/t.IMGFMT.target.overlay', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT.target +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "source"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "source"}} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "source"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "source", "len": 131072, "offset": 131072, "speed": 0, "type": "mirror"}} wrote 65536/65536 bytes at offset 196608 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) {"return": ""} {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "source"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "source"}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "source", "len": 196608, "offset": 196608, "speed": 0, "type": "mirror"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "source"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "source"}} read 65536/65536 bytes at offset 0 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) diff --git a/tests/qemu-iotests/185 b/tests/qemu-iotests/185 index 9a2d317414..7dcfdeac60 100755 --- a/tests/qemu-iotests/185 +++ b/tests/qemu-iotests/185 @@ -27,8 +27,6 @@ echo "QA output created by $seq" here=`pwd` status=1 # failure is the default! -MIG_SOCKET="${TEST_DIR}/migrate" - _cleanup() { rm -f "${TEST_IMG}.mid" @@ -118,8 +116,10 @@ _send_qemu_cmd $h \ # If we don't sleep here 'quit' command races with disk I/O sleep 0.5 +# Ignore the JOB_STATUS_CHANGE events while shutting down the VM. Depending on +# the timing, jobs may or may not transition through a paused state. _send_qemu_cmd $h "{ 'execute': 'quit' }" "return" -wait=1 _cleanup_qemu +wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' echo echo === Start active commit job and exit qemu === @@ -141,7 +141,7 @@ _send_qemu_cmd $h \ sleep 0.5 _send_qemu_cmd $h "{ 'execute': 'quit' }" "return" -wait=1 _cleanup_qemu +wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' echo echo === Start mirror job and exit qemu === @@ -166,7 +166,7 @@ _send_qemu_cmd $h \ sleep 0.5 _send_qemu_cmd $h "{ 'execute': 'quit' }" "return" -wait=1 _cleanup_qemu +wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' echo echo === Start backup job and exit qemu === @@ -190,7 +190,7 @@ _send_qemu_cmd $h \ sleep 0.5 _send_qemu_cmd $h "{ 'execute': 'quit' }" "return" -wait=1 _cleanup_qemu +wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' echo echo === Start streaming job and exit qemu === @@ -211,7 +211,7 @@ _send_qemu_cmd $h \ sleep 0.5 _send_qemu_cmd $h "{ 'execute': 'quit' }" "return" -wait=1 _cleanup_qemu +wait=1 _cleanup_qemu | grep -v 'JOB_STATUS_CHANGE' _check_test_img diff --git a/tests/qemu-iotests/185.out b/tests/qemu-iotests/185.out index 57eaf8d699..4e0ca0dffa 100644 --- a/tests/qemu-iotests/185.out +++ b/tests/qemu-iotests/185.out @@ -17,6 +17,8 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q === Start commit job and exit qemu === +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} @@ -25,6 +27,8 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q === Start active commit job and exit qemu === {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} @@ -34,6 +38,8 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 backing_file=TEST_DIR/t.q {"return": {}} Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} @@ -43,6 +49,8 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l {"return": {}} Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16 +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} @@ -51,6 +59,8 @@ Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=67108864 cluster_size=65536 l === Start streaming job and exit qemu === {"return": {}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "disk"}} +{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "disk"}} {"return": {}} {"return": {}} {"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} diff --git a/tests/qemu-iotests/191 b/tests/qemu-iotests/191 index dfad6555e4..d6860e72f7 100755 --- a/tests/qemu-iotests/191 +++ b/tests/qemu-iotests/191 @@ -27,8 +27,6 @@ echo "QA output created by $seq" here=`pwd` status=1 # failure is the default! -MIG_SOCKET="${TEST_DIR}/migrate" - _cleanup() { rm -f "${TEST_IMG}.mid" @@ -83,7 +81,7 @@ _send_qemu_cmd $h \ 'device': 'top', 'base':'$TEST_IMG.base', 'top': '$TEST_IMG.mid' } }" \ - "BLOCK_JOB_COMPLETED" + '"status": "null"' _send_qemu_cmd $h "" "^}" echo @@ -131,7 +129,7 @@ _send_qemu_cmd $h \ 'device': 'top', 'base':'$TEST_IMG.base', 'top': '$TEST_IMG.mid' } }" \ - "BLOCK_JOB_COMPLETED" + '"status": "null"' _send_qemu_cmd $h "" "^}" echo diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out index 190c5f049a..31a0c7d4c4 100644 --- a/tests/qemu-iotests/191.out +++ b/tests/qemu-iotests/191.out @@ -16,6 +16,28 @@ wrote 65536/65536 bytes at offset 1048576 === Perform commit job === { + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "created", + "id": "commit0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "running", + "id": "commit0" + } +} +{ "return": { } } @@ -24,6 +46,28 @@ wrote 65536/65536 bytes at offset 1048576 "seconds": TIMESTAMP, "microseconds": TIMESTAMP }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "waiting", + "id": "commit0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "pending", + "id": "commit0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, "event": "BLOCK_JOB_COMPLETED", "data": { "device": "commit0", @@ -33,6 +77,28 @@ wrote 65536/65536 bytes at offset 1048576 "type": "commit" } } +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "concluded", + "id": "commit0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "null", + "id": "commit0" + } +} === Check that both top and top2 point to base now === @@ -356,6 +422,28 @@ wrote 65536/65536 bytes at offset 1048576 === Perform commit job === { + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "created", + "id": "commit0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "running", + "id": "commit0" + } +} +{ "return": { } } @@ -364,6 +452,28 @@ wrote 65536/65536 bytes at offset 1048576 "seconds": TIMESTAMP, "microseconds": TIMESTAMP }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "waiting", + "id": "commit0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "pending", + "id": "commit0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, "event": "BLOCK_JOB_COMPLETED", "data": { "device": "commit0", @@ -373,6 +483,28 @@ wrote 65536/65536 bytes at offset 1048576 "type": "commit" } } +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "concluded", + "id": "commit0" + } +} +{ + "timestamp": { + "seconds": TIMESTAMP, + "microseconds": TIMESTAMP + }, + "event": "JOB_STATUS_CHANGE", + "data": { + "status": "null", + "id": "commit0" + } +} === Check that both top and top2 point to base now === diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206 index 0a18b2b19a..128c334c7c 100755 --- a/tests/qemu-iotests/206 +++ b/tests/qemu-iotests/206 @@ -1,9 +1,11 @@ -#!/bin/bash +#!/usr/bin/env python # # Test qcow2 and file image creation # # Copyright (C) 2018 Red Hat, Inc. # +# Creator/Owner: Kevin Wolf <kwolf@redhat.com> +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -18,419 +20,263 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -# creator -owner=kwolf@redhat.com - -seq=`basename $0` -echo "QA output created by $seq" - -here=`pwd` -status=1 # failure is the default! - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter - -_supported_fmt qcow2 -_supported_proto file -_supported_os Linux - -function do_run_qemu() -{ - echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" - echo -} - -function run_qemu() -{ - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ - | _filter_qemu | _filter_imgfmt \ - | _filter_actual_image_size -} - -echo -echo "=== Successful image creation (defaults) ===" -echo - -size=$((128 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "blockdev-add", - "arguments": { - "driver": "file", - "node-name": "imgfile", - "filename": "$TEST_IMG" - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "imgfile", - "size": $size - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific - -echo -echo "=== Successful image creation (inline blockdev-add, explicit defaults) ===" -echo - -# Choose a different size to show that we got a new image -size=$((64 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0, - "preallocation": "off", - "nocow": false - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "version": "v3", - "cluster-size": 65536, - "preallocation": "off", - "lazy-refcounts": false, - "refcount-bits": 16 - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific - -echo -echo "=== Successful image creation (v3 non-default options) ===" -echo - -# Choose a different size to show that we got a new image -size=$((32 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0, - "preallocation": "falloc", - "nocow": true - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "version": "v3", - "cluster-size": 2097152, - "preallocation": "metadata", - "lazy-refcounts": true, - "refcount-bits": 1 - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific - -echo -echo "=== Successful image creation (v2 non-default options) ===" -echo - -mv $TEST_IMG $TEST_IMG.base - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "backing-file": "$TEST_IMG.base", - "backing-fmt": "qcow2", - "version": "v2", - "cluster-size": 512 - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific - -echo -echo "=== Successful image creation (encrypted) ===" -echo - -run_qemu -object secret,id=keysec0,data="foo" <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "encrypt": { - "format": "luks", - "key-secret": "keysec0", - "cipher-alg": "twofish-128", - "cipher-mode": "ctr", - "ivgen-alg": "plain64", - "ivgen-hash-alg": "md5", - "hash-alg": "sha1", - "iter-time": 10 - } - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Invalid BlockdevRef ===" -echo - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "this doesn't exist", - "size": $size - } -} -{ "execute": "quit" } -EOF - - -echo -echo "=== Invalid sizes ===" -echo - -# TODO Negative image sizes aren't handled correctly, but this is a problem -# with QAPI's implementation of the 'size' type and affects other commands as -# well. Once this is fixed, we may want to add a test case here. - -# 1. Misaligned image size -# 2. 2^64 - 512 -# 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this) -# 4. 2^63 - 512 (generally valid, but qcow2 can't handle images this size) - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 1234 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 18446744073709551104 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 9223372036854775808 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 9223372036854775296 - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Invalid version ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "version": "v1" - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "version": "v2", - "lazy-refcounts": true - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "version": "v2", - "refcount-bits": 8 - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Invalid backing file options ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "backing-file": "/dev/null", - "preallocation": "full" - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "backing-fmt": "$IMGFMT" - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Invalid cluster size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 1234 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 128 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 4194304 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 281474976710656, - "cluster-size": 512 - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Invalid refcount width ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "refcount-bits": 128 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "refcount-bits": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "refcount-bits": 7 - } -} -{ "execute": "quit" } -EOF - -# success, all done -echo "*** done" -rm -f $seq.full -status=0 +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=['qcow2']) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.qcow2') as disk_path, \ + iotests.FilePath('t.qcow2.base') as backing_path, \ + iotests.VM() as vm: + + vm.add_object('secret,id=keysec0,data=foo') + + # + # Successful image creation (defaults) + # + iotests.log("=== Successful image creation (defaults) ===") + iotests.log("") + + size = 128 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.qmp_log('blockdev-add', driver='file', filename=disk_path, + node_name='imgfile') + + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (inline blockdev-add, explicit defaults) + # + iotests.log("=== Successful image creation (inline blockdev-add, explicit defaults) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0, + 'preallocation': 'off', + 'nocow': False }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'version': 'v3', + 'cluster-size': 65536, + 'preallocation': 'off', + 'lazy-refcounts': False, + 'refcount-bits': 16 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (v3 non-default options) + # + iotests.log("=== Successful image creation (v3 non-default options) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 32 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0, + 'preallocation': 'falloc', + 'nocow': True }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'version': 'v3', + 'cluster-size': 2097152, + 'preallocation': 'metadata', + 'lazy-refcounts': True, + 'refcount-bits': 1 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (v2 non-default options) + # + iotests.log("=== Successful image creation (v2 non-default options) ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'backing-file': backing_path, + 'backing-fmt': 'qcow2', + 'version': 'v2', + 'cluster-size': 512 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (encrypted) + # + iotests.log("=== Successful image creation (encrypted) ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'encrypt': { + 'format': 'luks', + 'key-secret': 'keysec0', + 'cipher-alg': 'twofish-128', + 'cipher-mode': 'ctr', + 'ivgen-alg': 'plain64', + 'ivgen-hash-alg': 'md5', + 'hash-alg': 'sha1', + 'iter-time': 10, + }}) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid BlockdevRef + # + iotests.log("=== Invalid BlockdevRef ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) + vm.shutdown() + + # + # Invalid sizes + # + iotests.log("=== Invalid sizes ===") + + # TODO Negative image sizes aren't handled correctly, but this is a problem + # with QAPI's implementation of the 'size' type and affects other commands + # as well. Once this is fixed, we may want to add a test case here. + # + # 1. Misaligned image size + # 2. 2^64 - 512 + # 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this) + # 4. 2^63 - 512 (generally valid, but qcow2 can't handle images this size) + + vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) + + vm.launch() + for size in [ 1234, 18446744073709551104, 9223372036854775808, + 9223372036854775296 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size }) + vm.shutdown() + + # + # Invalid version + # + iotests.log("=== Invalid version ===") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'version': 'v1' }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'version': 'v2', + 'lazy-refcounts': True }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'version': 'v2', + 'refcount-bits': 8 }) + vm.shutdown() + + # + # Invalid backing file options + # + iotests.log("=== Invalid backing file options ===") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'backing-file': '/dev/null', + 'preallocation': 'full' }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'backing-fmt': imgfmt }) + vm.shutdown() + + # + # Invalid cluster size + # + iotests.log("=== Invalid cluster size ===") + + vm.launch() + for csize in [ 1234, 128, 4194304, 0 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'cluster-size': csize }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 281474976710656, + 'cluster-size': 512 }) + vm.shutdown() + + # + # Invalid refcount width + # + iotests.log("=== Invalid refcount width ===") + + vm.launch() + for refcount_bits in [ 128, 0, 7 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'refcount-bits': refcount_bits }) + vm.shutdown() diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out index 042342ae9d..789eebe57b 100644 --- a/tests/qemu-iotests/206.out +++ b/tests/qemu-iotests/206.out @@ -1,17 +1,18 @@ -QA output created by 206 - === Successful image creation (defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}} +{u'return': {}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 128M (134217728 bytes) cluster_size: 65536 @@ -23,15 +24,17 @@ Format specific information: === Successful image creation (inline blockdev-add, explicit defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: TEST_IMG file format: IMGFMT virtual size: 64M (67108864 bytes) cluster_size: 65536 @@ -43,15 +46,17 @@ Format specific information: === Successful image creation (v3 non-default options) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 32M (33554432 bytes) cluster_size: 2097152 @@ -63,19 +68,21 @@ Format specific information: === Successful image creation (v2 non-default options) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'backing-file': 'TEST_DIR/PID-t.qcow2.base', 'size': 33554432}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: TEST_IMG file format: IMGFMT virtual size: 32M (33554432 bytes) cluster_size: 512 -backing file: TEST_DIR/t.IMGFMT.base +backing file: TEST_IMG.base backing file format: IMGFMT Format specific information: compat: 0.10 @@ -83,16 +90,16 @@ Format specific information: === Successful image creation (encrypted) === -Testing: -object secret,id=keysec0,data=foo -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'encrypt': {'key-secret': 'keysec0', 'iter-time': 10, 'cipher-mode': 'ctr', 'ivgen-hash-alg': 'md5', 'cipher-alg': 'twofish-128', 'format': 'luks', 'ivgen-alg': 'plain64', 'hash-alg': 'sha1'}, 'driver': 'qcow2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'size': 33554432}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 32M (33554432 bytes) +encrypted: yes +cluster_size: 65536 Format specific information: compat: 1.1 lazy refcounts: false @@ -101,13 +108,13 @@ Format specific information: ivgen alg: plain64 hash alg: sha1 cipher alg: twofish-128 - uuid: 00000000-0000-0000-0000-000000000000 + uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX format: luks cipher mode: ctr slots: [0]: active: true - iters: 1024 + iters: XXX key offset: 4096 stripes: 4000 [1]: @@ -132,78 +139,118 @@ Format specific information: active: false key offset: 462848 payload offset: 528384 - master key iters: 1024 + master key iters: XXX corrupt: false === Invalid BlockdevRef === -Testing: -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': "this doesn't exist", 'size': 33554432}}} +{u'return': {}} +Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Invalid sizes === - -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Image size must be a multiple of 512 bytes"}} -{"error": {"class": "GenericError", "desc": "Could not resize image: Image size cannot be negative"}} -{"error": {"class": "GenericError", "desc": "Could not resize image: Image size cannot be negative"}} -{"error": {"class": "GenericError", "desc": "Could not resize image: Failed to grow the L1 table: File too large"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 1234}}} +{u'return': {}} +Job failed: Image size must be a multiple of 512 bytes +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 18446744073709551104L}}} +{u'return': {}} +Job failed: Could not resize image: Image size cannot be negative +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775808L}}} +{u'return': {}} +Job failed: Could not resize image: Image size cannot be negative +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775296}}} +{u'return': {}} +Job failed: Could not resize image: Failed to grow the L1 table: File too large +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Invalid version === +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'version': 'v1', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter 'v1'"}} -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}} -{"error": {"class": "GenericError", "desc": "Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)"}} -{"error": {"class": "GenericError", "desc": "Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'lazy-refcounts': True, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater) +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 8, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater) +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Invalid backing file options === - -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Backing file and preallocation cannot be used at the same time"}} -{"error": {"class": "GenericError", "desc": "Backing format cannot be used without backing file"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'full', 'driver': 'qcow2', 'backing-file': '/dev/null', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Backing file and preallocation cannot be used at the same time +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'backing-fmt': 'qcow2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Backing format cannot be used without backing file +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Invalid cluster size === - -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}} -{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}} -{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}} -{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}} -{"error": {"class": "GenericError", "desc": "Could not resize image: Failed to grow the L1 table: File too large"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size must be a power of two between 512 and 2048k +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size must be a power of two between 512 and 2048k +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4194304, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size must be a power of two between 512 and 2048k +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size must be a power of two between 512 and 2048k +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'qcow2', 'file': 'node0', 'size': 281474976710656}}} +{u'return': {}} +Job failed: Could not resize image: Failed to grow the L1 table: File too large +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Invalid refcount width === +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Refcount width must be a power of two and may not exceed 64 bits +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Refcount width must be a power of two and may not exceed 64 bits +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 7, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Refcount width must be a power of two and may not exceed 64 bits +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}} -{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}} -{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - -*** done diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 index f5c77852d1..444ae233ae 100755 --- a/tests/qemu-iotests/207 +++ b/tests/qemu-iotests/207 @@ -1,9 +1,11 @@ -#!/bin/bash +#!/usr/bin/env python # # Test ssh image creation # # Copyright (C) 2018 Red Hat, Inc. # +# Creator/Owner: Kevin Wolf <kwolf@redhat.com> +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -18,244 +20,198 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -# creator -owner=kwolf@redhat.com - -seq=`basename $0` -echo "QA output created by $seq" - -here=`pwd` -status=1 # failure is the default! - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter - -_supported_fmt raw -_supported_proto ssh -_supported_os Linux - -function do_run_qemu() -{ - echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" - echo -} - -function run_qemu() -{ - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ - | _filter_qemu | _filter_imgfmt \ - | _filter_actual_image_size -} - -echo -echo "=== Successful image creation (defaults) ===" -echo - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "$TEST_IMG_FILE", - "server": { - "host": "127.0.0.1", - "port": "22" - } - }, - "size": 4194304 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info -echo -TEST_IMG=$TEST_IMG_FILE _img_info | _filter_img_info - -echo -echo "=== Test host-key-check options ===" -echo - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "$TEST_IMG_FILE", - "server": { - "host": "127.0.0.1", - "port": "22" - }, - "host-key-check": { - "mode": "none" - } - }, - "size": 8388608 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "$TEST_IMG_FILE", - "server": { - "host": "127.0.0.1", - "port": "22" - }, - "host-key-check": { - "mode": "known_hosts" - } - }, - "size": 4194304 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - - -key=$(ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | - cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "$TEST_IMG_FILE", - "server": { - "host": "127.0.0.1", - "port": "22" - }, - "host-key-check": { - "mode": "hash", - "type": "md5", - "hash": "wrong" - } - }, - "size": 8388608 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "$TEST_IMG_FILE", - "server": { - "host": "127.0.0.1", - "port": "22" - }, - "host-key-check": { - "mode": "hash", - "type": "md5", - "hash": "$key" - } - }, - "size": 8388608 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - - -key=$(ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | - cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "$TEST_IMG_FILE", - "server": { - "host": "127.0.0.1", - "port": "22" - }, - "host-key-check": { - "mode": "hash", - "type": "sha1", - "hash": "wrong" - } - }, - "size": 4194304 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "$TEST_IMG_FILE", - "server": { - "host": "127.0.0.1", - "port": "22" - }, - "host-key-check": { - "mode": "hash", - "type": "sha1", - "hash": "$key" - } - }, - "size": 4194304 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -echo -echo "=== Invalid path and user ===" -echo - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "/this/is/not/an/existing/path", - "server": { - "host": "127.0.0.1", - "port": "22" - } - }, - "size": 4194304 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "ssh", - "location": { - "path": "$TEST_IMG_FILE", - "user": "invalid user", - "server": { - "host": "127.0.0.1", - "port": "22" - } - }, - "size": 4194304 - } -} -{ "execute": "quit" } -EOF - -# success, all done -echo "*** done" -rm -f $seq.full -status=0 +import iotests +import subprocess +import re + +iotests.verify_image_format(supported_fmts=['raw']) +iotests.verify_protocol(supported=['ssh']) + +def filter_hash(msg): + return re.sub("'hash': '[0-9a-f]+'", "'hash': HASH", msg) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options, + filters=[iotests.filter_testfiles, filter_hash]) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.img') as disk_path, \ + iotests.VM() as vm: + + remote_path = iotests.remote_filename(disk_path) + + # + # Successful image creation (defaults) + # + iotests.log("=== Successful image creation (defaults) ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, + 'server': { + 'host': '127.0.0.1', + 'port': '22' + } + }, + 'size': 4194304 }) + vm.shutdown() + + iotests.img_info_log(remote_path, filter_path=disk_path) + iotests.log("") + iotests.img_info_log(disk_path) + + # + # Test host-key-check options + # + iotests.log("=== Test host-key-check options ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, + 'server': { + 'host': '127.0.0.1', + 'port': '22' + }, + 'host-key-check': { + 'mode': 'none' + } + }, + 'size': 8388608 }) + vm.shutdown() + + iotests.img_info_log(remote_path, filter_path=disk_path) + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, + 'server': { + 'host': '127.0.0.1', + 'port': '22' + }, + 'host-key-check': { + 'mode': 'known_hosts' + } + }, + 'size': 4194304 }) + vm.shutdown() + + iotests.img_info_log(remote_path, filter_path=disk_path) + + md5_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + + 'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1', + shell=True).rstrip() + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, + 'server': { + 'host': '127.0.0.1', + 'port': '22' + }, + 'host-key-check': { + 'mode': 'hash', + 'type': 'md5', + 'hash': 'wrong', + } + }, + 'size': 2097152 }) + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, + 'server': { + 'host': '127.0.0.1', + 'port': '22' + }, + 'host-key-check': { + 'mode': 'hash', + 'type': 'md5', + 'hash': md5_key, + } + }, + 'size': 8388608 }) + vm.shutdown() + + iotests.img_info_log(remote_path, filter_path=disk_path) + + sha1_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + + 'cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1', + shell=True).rstrip() + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, + 'server': { + 'host': '127.0.0.1', + 'port': '22' + }, + 'host-key-check': { + 'mode': 'hash', + 'type': 'sha1', + 'hash': 'wrong', + } + }, + 'size': 2097152 }) + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, + 'server': { + 'host': '127.0.0.1', + 'port': '22' + }, + 'host-key-check': { + 'mode': 'hash', + 'type': 'sha1', + 'hash': sha1_key, + } + }, + 'size': 4194304 }) + vm.shutdown() + + iotests.img_info_log(remote_path, filter_path=disk_path) + + # + # Invalid path and user + # + iotests.log("=== Invalid path and user ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': '/this/is/not/an/existing/path', + 'server': { + 'host': '127.0.0.1', + 'port': '22' + }, + 'host-key-check': { + 'mode': 'none' + } + }, + 'size': 4194304 }) + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, + 'user': 'invalid user', + 'server': { + 'host': '127.0.0.1', + 'port': '22' + }, + 'host-key-check': { + 'mode': 'none' + } + }, + 'size': 4194304 }) + vm.shutdown() diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out index 417deee970..078b7e63cb 100644 --- a/tests/qemu-iotests/207.out +++ b/tests/qemu-iotests/207.out @@ -1,75 +1,80 @@ -QA output created by 207 - === Successful image creation (defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}} +image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT virtual size: 4.0M (4194304 bytes) -image: TEST_DIR/t.IMGFMT + +image: TEST_IMG file format: IMGFMT virtual size: 4.0M (4194304 bytes) === Test host-key-check options === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}} +image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT virtual size: 8.0M (8388608 bytes) -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - -image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'known_hosts'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT virtual size: 4.0M (4194304 bytes) -Testing: -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "remote host key does not match host_key_check 'wrong'"}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - -image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}} +{u'return': {}} +Job failed: remote host key does not match host_key_check 'wrong' +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT virtual size: 8.0M (8388608 bytes) -Testing: -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "remote host key does not match host_key_check 'wrong'"}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - -image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}} +{u'return': {}} +Job failed: remote host key does not match host_key_check 'wrong' +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} file format: IMGFMT virtual size: 4.0M (4194304 bytes) === Invalid path and user === -Testing: -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)"}} -{"error": {"class": "GenericError", "desc": "failed to authenticate using publickey authentication and the identities held by your ssh-agent"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': '/this/is/not/an/existing/path', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +{u'return': {}} +Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31) +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'user': 'invalid user', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +{u'return': {}} +Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -*** done diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210 index e607c0d296..d142841e2b 100755 --- a/tests/qemu-iotests/210 +++ b/tests/qemu-iotests/210 @@ -1,9 +1,11 @@ -#!/bin/bash +#!/usr/bin/env python # # Test luks and file image creation # # Copyright (C) 2018 Red Hat, Inc. # +# Creator/Owner: Kevin Wolf <kwolf@redhat.com> +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -18,230 +20,165 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -# creator -owner=kwolf@redhat.com - -seq=`basename $0` -echo "QA output created by $seq" - -here=`pwd` -status=1 # failure is the default! - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter - -_supported_fmt luks -_supported_proto file -_supported_os Linux - -function do_run_qemu() -{ - echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" - echo -} - -function run_qemu() -{ - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ - | _filter_qemu | _filter_imgfmt \ - | _filter_actual_image_size -} - -echo -echo "=== Successful image creation (defaults) ===" -echo - -size=$((128 * 1024 * 1024)) - -run_qemu -object secret,id=keysec0,data="foo" <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG_FILE", - "size": 0 - } -} -{ "execute": "blockdev-add", - "arguments": { - "driver": "file", - "node-name": "imgfile", - "filename": "$TEST_IMG_FILE" - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "imgfile", - "key-secret": "keysec0", - "size": $size, - "iter-time": 10 - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Successful image creation (with non-default options) ===" -echo - -# Choose a different size to show that we got a new image -size=$((64 * 1024 * 1024)) - -run_qemu -object secret,id=keysec0,data="foo" <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG_FILE", - "size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG_FILE" - }, - "size": $size, - "key-secret": "keysec0", - "cipher-alg": "twofish-128", - "cipher-mode": "ctr", - "ivgen-alg": "plain64", - "ivgen-hash-alg": "md5", - "hash-alg": "sha1", - "iter-time": 10 - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Invalid BlockdevRef ===" -echo - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "this doesn't exist", - "size": $size - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Zero size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \ - -object secret,id=keysec0,data="foo" <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "key-secret": "keysec0", - "size": 0, - "iter-time": 10 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - - -echo -echo "=== Invalid sizes ===" -echo - -# TODO Negative image sizes aren't handled correctly, but this is a problem -# with QAPI's implementation of the 'size' type and affects other commands as -# well. Once this is fixed, we may want to add a test case here. - -# 1. 2^64 - 512 -# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) -# 3. 2^63 - 512 (generally valid, but with the crypto header the file will -# exceed 63 bits) - -run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \ - -object secret,id=keysec0,data="foo" <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "key-secret": "keysec0", - "size": 18446744073709551104 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "key-secret": "keysec0", - "size": 9223372036854775808 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "key-secret": "keysec0", - "size": 9223372036854775296 - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Resize image with invalid sizes ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \ - -blockdev driver=luks,file=node0,key-secret=keysec0,node-name=node1 \ - -object secret,id=keysec0,data="foo" <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "block_resize", - "arguments": { - "node-name": "node1", - "size": 9223372036854775296 - } -} -{ "execute": "block_resize", - "arguments": { - "node-name": "node1", - "size": 9223372036854775808 - } -} -{ "execute": "block_resize", - "arguments": { - "node-name": "node1", - "size": 18446744073709551104 - } -} -{ "execute": "block_resize", - "arguments": { - "node-name": "node1", - "size": -9223372036854775808 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -# success, all done -echo "*** done" -rm -f $seq.full -status=0 +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=['luks']) +iotests.verify_protocol(supported=['file']) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.luks') as disk_path, \ + iotests.VM() as vm: + + vm.add_object('secret,id=keysec0,data=foo') + + # + # Successful image creation (defaults) + # + iotests.log("=== Successful image creation (defaults) ===") + iotests.log("") + + size = 128 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.qmp_log('blockdev-add', driver='file', filename=disk_path, + node_name='imgfile') + + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'imgfile', + 'key-secret': 'keysec0', + 'size': size, + 'iter-time': 10 }) + vm.shutdown() + + # TODO Proper support for images to be used with imgopts and/or protocols + iotests.img_info_log( + 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path), + filter_path=disk_path, + extra_args=['--object', 'secret,id=keysec0,data=foo'], + imgopts=True) + + # + # Successful image creation (with non-default options) + # + iotests.log("=== Successful image creation (with non-default options) ===") + iotests.log("") + + size = 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'key-secret': 'keysec0', + 'cipher-alg': 'twofish-128', + 'cipher-mode': 'ctr', + 'ivgen-alg': 'plain64', + 'ivgen-hash-alg': 'md5', + 'hash-alg': 'sha1', + 'iter-time': 10 }) + vm.shutdown() + + # TODO Proper support for images to be used with imgopts and/or protocols + iotests.img_info_log( + 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path), + filter_path=disk_path, + extra_args=['--object', 'secret,id=keysec0,data=foo'], + imgopts=True) + + # + # Invalid BlockdevRef + # + iotests.log("=== Invalid BlockdevRef ===") + iotests.log("") + + size = 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) + vm.shutdown() + + # + # Zero size + # + iotests.log("=== Zero size ===") + iotests.log("") + + vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'key-secret': 'keysec0', + 'size': 0, + 'iter-time': 10 }) + vm.shutdown() + + # TODO Proper support for images to be used with imgopts and/or protocols + iotests.img_info_log( + 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path), + filter_path=disk_path, + extra_args=['--object', 'secret,id=keysec0,data=foo'], + imgopts=True) + + # + # Invalid sizes + # + + # TODO Negative image sizes aren't handled correctly, but this is a problem + # with QAPI's implementation of the 'size' type and affects other commands as + # well. Once this is fixed, we may want to add a test case here. + + # 1. 2^64 - 512 + # 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) + # 3. 2^63 - 512 (generally valid, but with the crypto header the file will + # exceed 63 bits) + iotests.log("=== Invalid sizes ===") + iotests.log("") + + vm.launch() + for size in [ 18446744073709551104, 9223372036854775808, 9223372036854775296 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'key-secret': 'keysec0', + 'size': size }) + vm.shutdown() + + # + # Resize image with invalid sizes + # + iotests.log("=== Resize image with invalid sizes ===") + iotests.log("") + + vm.add_blockdev('driver=luks,file=node0,key-secret=keysec0,node-name=node1') + vm.launch() + vm.qmp_log('block_resize', node_name='node1', size=9223372036854775296) + vm.qmp_log('block_resize', node_name='node1', size=9223372036854775808) + vm.qmp_log('block_resize', node_name='node1', size=18446744073709551104) + vm.qmp_log('block_resize', node_name='node1', size=-9223372036854775808) + vm.shutdown() + + # TODO Proper support for images to be used with imgopts and/or protocols + iotests.img_info_log( + 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path), + filter_path=disk_path, + extra_args=['--object', 'secret,id=keysec0,data=foo'], + imgopts=True) diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out index 8198f8c829..078ba544a1 100644 --- a/tests/qemu-iotests/210.out +++ b/tests/qemu-iotests/210.out @@ -1,29 +1,31 @@ -QA output created by 210 - === Successful image creation (defaults) === -Testing: -object secret,id=keysec0,data=foo -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}} +{u'return': {}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'imgfile', 'size': 134217728}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"} +image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT virtual size: 128M (134217728 bytes) +encrypted: yes Format specific information: ivgen alg: plain64 hash alg: sha256 cipher alg: aes-256 - uuid: 00000000-0000-0000-0000-000000000000 + uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX cipher mode: xts slots: [0]: active: true - iters: 1024 + iters: XXX key offset: 4096 stripes: 4000 [1]: @@ -48,31 +50,34 @@ Format specific information: active: false key offset: 1810432 payload offset: 2068480 - master key iters: 1024 + master key iters: XXX === Successful image creation (with non-default options) === -Testing: -object secret,id=keysec0,data=foo -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'hash-alg': 'sha1', 'cipher-mode': 'ctr', 'cipher-alg': 'twofish-128', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}, 'iter-time': 10, 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'driver': 'luks', 'size': 67108864}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"} +image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT virtual size: 64M (67108864 bytes) +encrypted: yes Format specific information: ivgen alg: plain64 hash alg: sha1 cipher alg: twofish-128 - uuid: 00000000-0000-0000-0000-000000000000 + uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX cipher mode: ctr slots: [0]: active: true - iters: 1024 + iters: XXX key offset: 4096 stripes: 4000 [1]: @@ -97,56 +102,130 @@ Format specific information: active: false key offset: 462848 payload offset: 528384 - master key iters: 1024 + master key iters: XXX === Invalid BlockdevRef === -Testing: -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'luks', 'file': "this doesn't exist", 'size': 67108864}}} +{u'return': {}} +Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Zero size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -object secret,id=keysec0,data=foo -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'node0', 'size': 0}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"} +image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT virtual size: 0 (0 bytes) +encrypted: yes +Format specific information: + ivgen alg: plain64 + hash alg: sha256 + cipher alg: aes-256 + uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + cipher mode: xts + slots: + [0]: + active: true + iters: XXX + key offset: 4096 + stripes: 4000 + [1]: + active: false + key offset: 262144 + [2]: + active: false + key offset: 520192 + [3]: + active: false + key offset: 778240 + [4]: + active: false + key offset: 1036288 + [5]: + active: false + key offset: 1294336 + [6]: + active: false + key offset: 1552384 + [7]: + active: false + key offset: 1810432 + payload offset: 2068480 + master key iters: XXX === Invalid sizes === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -object secret,id=keysec0,data=foo -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} -{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} -{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 18446744073709551104L}}} +{u'return': {}} +Job failed: The requested file size is too large +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775808L}}} +{u'return': {}} +Job failed: The requested file size is too large +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775296}}} +{u'return': {}} +Job failed: The requested file size is too large +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Resize image with invalid sizes === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -blockdev driver=IMGFMT,file=node0,key-secret=keysec0,node-name=node1 -object secret,id=keysec0,data=foo -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} -{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} -{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} -{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - -image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"} +{'execute': 'block_resize', 'arguments': {'size': 9223372036854775296, 'node_name': 'node1'}} +{u'error': {u'class': u'GenericError', u'desc': u'The requested file size is too large'}} +{'execute': 'block_resize', 'arguments': {'size': 9223372036854775808L, 'node_name': 'node1'}} +{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}} +{'execute': 'block_resize', 'arguments': {'size': 18446744073709551104L, 'node_name': 'node1'}} +{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}} +{'execute': 'block_resize', 'arguments': {'size': -9223372036854775808, 'node_name': 'node1'}} +{u'error': {u'class': u'GenericError', u'desc': u"Parameter 'size' expects a >0 size"}} +image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} file format: IMGFMT virtual size: 0 (0 bytes) -*** done +encrypted: yes +Format specific information: + ivgen alg: plain64 + hash alg: sha256 + cipher alg: aes-256 + uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + cipher mode: xts + slots: + [0]: + active: true + iters: XXX + key offset: 4096 + stripes: 4000 + [1]: + active: false + key offset: 262144 + [2]: + active: false + key offset: 520192 + [3]: + active: false + key offset: 778240 + [4]: + active: false + key offset: 1036288 + [5]: + active: false + key offset: 1294336 + [6]: + active: false + key offset: 1552384 + [7]: + active: false + key offset: 1810432 + payload offset: 2068480 + master key iters: XXX + diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211 index 1edec26517..7b7985db6c 100755 --- a/tests/qemu-iotests/211 +++ b/tests/qemu-iotests/211 @@ -1,9 +1,11 @@ -#!/bin/bash +#!/usr/bin/env python # # Test VDI and file image creation # # Copyright (C) 2018 Red Hat, Inc. # +# Creator/Owner: Kevin Wolf <kwolf@redhat.com> +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -18,229 +20,154 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -# creator -owner=kwolf@redhat.com - -seq=`basename $0` -echo "QA output created by $seq" - -here=`pwd` -status=1 # failure is the default! - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter - -_supported_fmt vdi -_supported_proto file -_supported_os Linux - -function do_run_qemu() -{ - echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" - echo -} - -function run_qemu() -{ - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ - | _filter_qemu | _filter_imgfmt \ - | _filter_actual_image_size -} - -echo -echo "=== Successful image creation (defaults) ===" -echo - -size=$((128 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "blockdev-add", - "arguments": { - "driver": "file", - "node-name": "imgfile", - "filename": "$TEST_IMG" - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "imgfile", - "size": $size - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific -$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map - -echo -echo "=== Successful image creation (explicit defaults) ===" -echo - -# Choose a different size to show that we got a new image -size=$((64 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "preallocation": "off" - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific -$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map - -echo -echo "=== Successful image creation (with non-default options) ===" -echo - -# Choose a different size to show that we got a new image -size=$((32 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "preallocation": "metadata" - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific -$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map - -echo -echo "=== Invalid BlockdevRef ===" -echo - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "this doesn't exist", - "size": $size - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Zero size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 0 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -echo -echo "=== Maximum size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 562949819203584 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -echo -echo "=== Invalid sizes ===" -echo - -# TODO Negative image sizes aren't handled correctly, but this is a problem -# with QAPI's implementation of the 'size' type and affects other commands as -# well. Once this is fixed, we may want to add a test case here. - -# 1. 2^64 - 512 -# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) -# 3. 0x1fffff8000001 (one byte more than maximum image size for VDI) - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 18446744073709551104 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 9223372036854775808 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 562949819203585 - } -} -{ "execute": "quit" } -EOF - -# success, all done -echo "*** done" -rm -f $seq.full -status=0 +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=['vdi']) +iotests.verify_protocol(supported=['file']) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.vdi') as disk_path, \ + iotests.VM() as vm: + + # + # Successful image creation (defaults) + # + iotests.log("=== Successful image creation (defaults) ===") + iotests.log("") + + size = 128 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.qmp_log('blockdev-add', driver='file', filename=disk_path, + node_name='imgfile') + + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) + vm.shutdown() + + iotests.img_info_log(disk_path) + iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path)) + + # + # Successful image creation (explicit defaults) + # + iotests.log("=== Successful image creation (explicit defaults) ===") + iotests.log("") + + size = 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'preallocation': 'off' }) + vm.shutdown() + + iotests.img_info_log(disk_path) + iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path)) + + # + # Successful image creation (with non-default options) + # + iotests.log("=== Successful image creation (with non-default options) ===") + iotests.log("") + + size = 32 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'preallocation': 'metadata' }) + vm.shutdown() + + iotests.img_info_log(disk_path) + iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path)) + + # + # Invalid BlockdevRef + # + iotests.log("=== Invalid BlockdevRef ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) + vm.shutdown() + + # + # Zero size + # + iotests.log("=== Zero size ===") + iotests.log("") + + vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 0 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Maximum size + # + iotests.log("=== Maximum size ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 562949819203584 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid sizes + # + + # TODO Negative image sizes aren't handled correctly, but this is a problem + # with QAPI's implementation of the 'size' type and affects other commands + # as well. Once this is fixed, we may want to add a test case here. + + # 1. 2^64 - 512 + # 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) + # 3. 0x1fffff8000001 (one byte more than maximum image size for VDI) + + iotests.log("=== Invalid sizes ===") + iotests.log("") + + vm.launch() + for size in [ 18446744073709551104, 9223372036854775808, 562949819203585 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size }) + vm.shutdown() diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out index 3247bbaa64..6feaea3978 100644 --- a/tests/qemu-iotests/211.out +++ b/tests/qemu-iotests/211.out @@ -1,97 +1,112 @@ -QA output created by 211 - === Successful image creation (defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}} +{u'return': {}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 128M (134217728 bytes) +cluster_size: 1048576 + [{ "start": 0, "length": 134217728, "depth": 0, "zero": true, "data": false}] === Successful image creation (explicit defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 67108864}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: TEST_IMG file format: IMGFMT virtual size: 64M (67108864 bytes) +cluster_size: 1048576 + [{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}] === Successful image creation (with non-default options) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 33554432}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: TEST_IMG file format: IMGFMT virtual size: 32M (33554432 bytes) -[{ "start": 0, "length": 3072, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, -{ "start": 3072, "length": 33551360, "depth": 0, "zero": true, "data": true, "offset": OFFSET}] +cluster_size: 1048576 -=== Invalid BlockdevRef === +[{ "start": 0, "length": 3072, "depth": 0, "zero": false, "data": true, "offset": 1024}, +{ "start": 3072, "length": 33551360, "depth": 0, "zero": true, "data": true, "offset": 4096}] -Testing: -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +=== Invalid BlockdevRef === +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': "this doesn't exist", 'size': 33554432}}} +{u'return': {}} +Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Zero size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 0 (0 bytes) +cluster_size: 1048576 === Maximum size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 512T (562949819203584 bytes) +cluster_size: 1048576 === Invalid sizes === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)"}} -{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000)"}} -{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000)"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 18446744073709551104L}}} +{u'return': {}} +Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000) +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 9223372036854775808L}}} +{u'return': {}} +Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000) +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203585}}} +{u'return': {}} +Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000) +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -*** done diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212 index e5a1ba77ce..95c8810d83 100755 --- a/tests/qemu-iotests/212 +++ b/tests/qemu-iotests/212 @@ -1,9 +1,11 @@ -#!/bin/bash +#!/usr/bin/env python # # Test parallels and file image creation # # Copyright (C) 2018 Red Hat, Inc. # +# Creator/Owner: Kevin Wolf <kwolf@redhat.com> +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -18,309 +20,176 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -# creator -owner=kwolf@redhat.com - -seq=`basename $0` -echo "QA output created by $seq" - -here=`pwd` -status=1 # failure is the default! - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter - -_supported_fmt parallels -_supported_proto file -_supported_os Linux - -function do_run_qemu() -{ - echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" - echo -} - -function run_qemu() -{ - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ - | _filter_qemu | _filter_imgfmt \ - | _filter_actual_image_size -} - -echo -echo "=== Successful image creation (defaults) ===" -echo - -size=$((128 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "blockdev-add", - "arguments": { - "driver": "file", - "node-name": "imgfile", - "filename": "$TEST_IMG" - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "imgfile", - "size": $size - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Successful image creation (explicit defaults) ===" -echo - -# Choose a different size to show that we got a new image -size=$((64 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "cluster-size": 1048576 - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Successful image creation (with non-default options) ===" -echo - -# Choose a different size to show that we got a new image -size=$((32 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "cluster-size": 65536 - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Invalid BlockdevRef ===" -echo - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "this doesn't exist", - "size": $size - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Zero size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 0 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -echo -echo "=== Maximum size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 4503599627369984 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -echo -echo "=== Invalid sizes ===" -echo - -# TODO Negative image sizes aren't handled correctly, but this is a problem -# with QAPI's implementation of the 'size' type and affects other commands as -# well. Once this is fixed, we may want to add a test case here. - -# 1. Misaligned image size -# 2. 2^64 - 512 -# 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this) -# 4. 2^63 - 512 (generally valid, but with the image header the file will -# exceed 63 bits) -# 5. 2^52 (512 bytes more than maximum image size) - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 1234 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 18446744073709551104 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 9223372036854775808 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 9223372036854775296 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 4503599627370497 - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Invalid cluster size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 1234 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 128 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 4294967296 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 9223372036854775808 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 18446744073709551104 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "cluster-size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 281474976710656, - "cluster-size": 512 - } -} -{ "execute": "quit" } -EOF - - -# success, all done -echo "*** done" -rm -f $seq.full -status=0 +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=['parallels']) +iotests.verify_protocol(supported=['file']) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.parallels') as disk_path, \ + iotests.VM() as vm: + + # + # Successful image creation (defaults) + # + iotests.log("=== Successful image creation (defaults) ===") + iotests.log("") + + size = 128 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.qmp_log('blockdev-add', driver='file', filename=disk_path, + node_name='imgfile') + + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (explicit defaults) + # + iotests.log("=== Successful image creation (explicit defaults) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'cluster-size': 1048576 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (with non-default options) + # + iotests.log("=== Successful image creation (with non-default options) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 32 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'cluster-size': 65536 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid BlockdevRef + # + iotests.log("=== Invalid BlockdevRef ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) + vm.shutdown() + + # + # Zero size + # + iotests.log("=== Zero size ===") + iotests.log("") + + vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 0 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Maximum size + # + iotests.log("=== Maximum size ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 4503599627369984}) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid sizes + # + + # TODO Negative image sizes aren't handled correctly, but this is a problem + # with QAPI's implementation of the 'size' type and affects other commands + # as well. Once this is fixed, we may want to add a test case here. + + # 1. Misaligned image size + # 2. 2^64 - 512 + # 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this) + # 4. 2^63 - 512 (generally valid, but with the image header the file will + # exceed 63 bits) + # 5. 2^52 (512 bytes more than maximum image size) + + iotests.log("=== Invalid sizes ===") + iotests.log("") + + vm.launch() + for size in [ 1234, 18446744073709551104, 9223372036854775808, + 9223372036854775296, 4503599627370497 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size }) + vm.shutdown() + + # + # Invalid cluster size + # + iotests.log("=== Invalid cluster size ===") + iotests.log("") + + vm.launch() + for csize in [ 1234, 128, 4294967296, 9223372036854775808, + 18446744073709551104, 0 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'cluster-size': csize }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 281474976710656, + 'cluster-size': 512 }) + vm.shutdown() diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out index 587de6fad0..9150da7a2c 100644 --- a/tests/qemu-iotests/212.out +++ b/tests/qemu-iotests/212.out @@ -1,111 +1,156 @@ -QA output created by 212 - === Successful image creation (defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}} +{u'return': {}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 128M (134217728 bytes) === Successful image creation (explicit defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 67108864}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: TEST_IMG file format: IMGFMT virtual size: 64M (67108864 bytes) === Successful image creation (with non-default options) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 33554432}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 32M (33554432 bytes) === Invalid BlockdevRef === -Testing: -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': "this doesn't exist", 'size': 33554432}}} +{u'return': {}} +Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Zero size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 0 (0 bytes) === Maximum size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 4096T (4503599627369984 bytes) === Invalid sizes === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Image size must be a multiple of 512 bytes"}} -{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} -{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} -{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} -{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 1234}}} +{u'return': {}} +Job failed: Image size must be a multiple of 512 bytes +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 18446744073709551104L}}} +{u'return': {}} +Job failed: Image size is too large for this cluster size +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775808L}}} +{u'return': {}} +Job failed: Image size is too large for this cluster size +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775296}}} +{u'return': {}} +Job failed: Image size is too large for this cluster size +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627370497}}} +{u'return': {}} +Job failed: Image size is too large for this cluster size +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Invalid cluster size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Cluster size must be a multiple of 512 bytes"}} -{"error": {"class": "GenericError", "desc": "Cluster size must be a multiple of 512 bytes"}} -{"error": {"class": "GenericError", "desc": "Cluster size is too large"}} -{"error": {"class": "GenericError", "desc": "Cluster size is too large"}} -{"error": {"class": "GenericError", "desc": "Cluster size is too large"}} -{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} -{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - -*** done +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size must be a multiple of 512 bytes +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size must be a multiple of 512 bytes +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4294967296, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size is too large +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 9223372036854775808L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size is too large +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 18446744073709551104L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Cluster size is too large +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Image size is too large for this cluster size +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'parallels', 'file': 'node0', 'size': 281474976710656}}} +{u'return': {}} +Job failed: Image size is too large for this cluster size +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213 index 3a00a0f6d6..4054439e3c 100755 --- a/tests/qemu-iotests/213 +++ b/tests/qemu-iotests/213 @@ -1,9 +1,11 @@ -#!/bin/bash +#!/usr/bin/env python # # Test vhdx and file image creation # # Copyright (C) 2018 Red Hat, Inc. # +# Creator/Owner: Kevin Wolf <kwolf@redhat.com> +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -18,332 +20,190 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -# creator -owner=kwolf@redhat.com - -seq=`basename $0` -echo "QA output created by $seq" - -here=`pwd` -status=1 # failure is the default! - -# get standard environment, filters and checks -. ./common.rc -. ./common.filter - -_supported_fmt vhdx -_supported_proto file -_supported_os Linux - -function do_run_qemu() -{ - echo Testing: "$@" - $QEMU -nographic -qmp stdio -serial none "$@" - echo -} - -function run_qemu() -{ - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ - | _filter_qemu | _filter_imgfmt \ - | _filter_actual_image_size -} - -echo -echo "=== Successful image creation (defaults) ===" -echo - -size=$((128 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "blockdev-add", - "arguments": { - "driver": "file", - "node-name": "imgfile", - "filename": "$TEST_IMG" - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "imgfile", - "size": $size - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Successful image creation (explicit defaults) ===" -echo - -# Choose a different size to show that we got a new image -size=$((64 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "log-size": 1048576, - "block-size": 8388608, - "subformat": "dynamic", - "block-state-zero": true - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Successful image creation (with non-default options) ===" -echo - -# Choose a different size to show that we got a new image -size=$((32 * 1024 * 1024)) - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "file", - "filename": "$TEST_IMG", - "size": 0 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": { - "driver": "file", - "filename": "$TEST_IMG" - }, - "size": $size, - "log-size": 8388608, - "block-size": 268435456, - "subformat": "fixed", - "block-state-zero": false - } -} -{ "execute": "quit" } -EOF - -_img_info --format-specific | _filter_img_info --format-specific - -echo -echo "=== Invalid BlockdevRef ===" -echo - -run_qemu <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "this doesn't exist", - "size": $size - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Zero size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 0 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -echo -echo "=== Maximum size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 70368744177664 - } -} -{ "execute": "quit" } -EOF - -_img_info | _filter_img_info - -echo -echo "=== Invalid sizes ===" -echo - -# TODO Negative image sizes aren't handled correctly, but this is a problem -# with QAPI's implementation of the 'size' type and affects other commands as -# well. Once this is fixed, we may want to add a test case here. - -# 1. 2^64 - 512 -# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) -# 3. 2^63 - 512 (generally valid, but with the image header the file will -# exceed 63 bits) -# 4. 2^46 + 1 (one byte more than maximum image size) - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 18446744073709551104 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 9223372036854775808 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 9223372036854775296 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 70368744177665 - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Invalid block size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "block-size": 1234567 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "block-size": 128 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "block-size": 3145728 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "block-size": 536870912 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "block-size": 0 - } -} -{ "execute": "quit" } -EOF - -echo -echo "=== Invalid log size ===" -echo - -run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF -{ "execute": "qmp_capabilities" } -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "log-size": 1234567 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "log-size": 128 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "log-size": 4294967296 - } -} -{ "execute": "x-blockdev-create", - "arguments": { - "driver": "$IMGFMT", - "file": "node0", - "size": 67108864, - "log-size": 0 - } -} -{ "execute": "quit" } -EOF - - -# success, all done -echo "*** done" -rm -f $seq.full -status=0 +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=['vhdx']) +iotests.verify_protocol(supported=['file']) + +def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options) + + if 'return' in result: + assert result['return'] == {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.vhdx') as disk_path, \ + iotests.VM() as vm: + + # + # Successful image creation (defaults) + # + iotests.log("=== Successful image creation (defaults) ===") + iotests.log("") + + size = 128 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.qmp_log('blockdev-add', driver='file', filename=disk_path, + node_name='imgfile') + + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (explicit defaults) + # + iotests.log("=== Successful image creation (explicit defaults) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'log-size': 1048576, + 'block-size': 8388608, + 'subformat': 'dynamic', + 'block-state-zero': True }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (with non-default options) + # + iotests.log("=== Successful image creation (with non-default options) ===") + iotests.log("") + + # Choose a different size to show that we got a new image + size = 32 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'log-size': 8388608, + 'block-size': 268435456, + 'subformat': 'fixed', + 'block-state-zero': False }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid BlockdevRef + # + iotests.log("=== Invalid BlockdevRef ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) + vm.shutdown() + + # + # Zero size + # + iotests.log("=== Zero size ===") + iotests.log("") + + vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path)) + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 0 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Maximum size + # + iotests.log("=== Maximum size ===") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 70368744177664 }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid sizes + # + + # TODO Negative image sizes aren't handled correctly, but this is a problem + # with QAPI's implementation of the 'size' type and affects other commands + # as well. Once this is fixed, we may want to add a test case here. + + # 1. 2^64 - 512 + # 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) + # 3. 2^63 - 512 (generally valid, but with the image header the file will + # exceed 63 bits) + # 4. 2^46 + 1 (one byte more than maximum image size) + + iotests.log("=== Invalid sizes ===") + iotests.log("") + + vm.launch() + for size in [ 18446744073709551104, 9223372036854775808, + 9223372036854775296, 70368744177665 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size }) + vm.shutdown() + + # + # Invalid block size + # + iotests.log("=== Invalid block size ===") + iotests.log("") + + vm.launch() + for bsize in [ 1234567, 128, 3145728, 536870912, 0 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'block-size': bsize }) + vm.shutdown() + + # + # Invalid log size + # + iotests.log("=== Invalid log size ===") + iotests.log("") + + vm.launch() + for lsize in [ 1234567, 128, 4294967296, 0 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 67108864, + 'log-size': lsize }) + vm.shutdown() diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out index 8e8fc29cbc..e1dcd47201 100644 --- a/tests/qemu-iotests/213.out +++ b/tests/qemu-iotests/213.out @@ -1,121 +1,169 @@ -QA output created by 213 - === Successful image creation (defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}} +{u'return': {}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 128M (134217728 bytes) +cluster_size: 8388608 === Successful image creation (explicit defaults) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': True, 'size': 67108864}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +image: TEST_IMG file format: IMGFMT virtual size: 64M (67108864 bytes) +cluster_size: 8388608 === Successful image creation (with non-default options) === -Testing: -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': False, 'size': 33554432}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 32M (33554432 bytes) +cluster_size: 268435456 === Invalid BlockdevRef === -Testing: -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}} +{u'return': {}} +Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Zero size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 0 (0 bytes) +cluster_size: 8388608 === Maximum size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"return": {}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}} +{u'return': {}} +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} -image: TEST_DIR/t.IMGFMT +image: TEST_IMG file format: IMGFMT virtual size: 64T (70368744177664 bytes) +cluster_size: 67108864 === Invalid sizes === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}} -{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}} -{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}} -{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}} +{u'return': {}} +Job failed: Image size too large; max of 64TB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775808L}}} +{u'return': {}} +Job failed: Image size too large; max of 64TB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775296}}} +{u'return': {}} +Job failed: Image size too large; max of 64TB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177665}}} +{u'return': {}} +Job failed: Image size too large; max of 64TB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Invalid block size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}} -{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}} -{"error": {"class": "GenericError", "desc": "Block size must be a power of two"}} -{"error": {"class": "GenericError", "desc": "Block size must not exceed 268435456"}} -{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Block size must be a multiple of 1 MB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 128, 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Block size must be a multiple of 1 MB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 3145728, 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Block size must be a power of two +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 536870912, 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Block size must not exceed 268435456 +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 0, 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Block size must be a multiple of 1 MB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} === Invalid log size === -Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -QMP_VERSION -{"return": {}} -{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}} -{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}} -{"error": {"class": "GenericError", "desc": "Log size must be smaller than 4 GB"}} -{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}} -{"return": {}} -{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} - -*** done +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Log size must be a multiple of 1 MB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Log size must be a multiple of 1 MB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 4294967296, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Log size must be smaller than 4 GB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 0, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +{u'return': {}} +Job failed: Log size must be a multiple of 1 MB +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +{u'return': {}} + diff --git a/tests/qemu-iotests/219 b/tests/qemu-iotests/219 new file mode 100755 index 0000000000..898a26eef0 --- /dev/null +++ b/tests/qemu-iotests/219 @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +# Creator/Owner: Kevin Wolf <kwolf@redhat.com> +# +# Check using the job-* QMP commands with block jobs + +import iotests + +iotests.verify_image_format(supported_fmts=['qcow2']) + +def pause_wait(vm, job_id): + with iotests.Timeout(3, "Timeout waiting for job to pause"): + while True: + result = vm.qmp('query-jobs') + for job in result['return']: + if job['id'] == job_id and job['status'] in ['paused', 'standby']: + return job + +# Test that block-job-pause/resume and job-pause/resume can be mixed +def test_pause_resume(vm): + for pause_cmd, pause_arg in [('block-job-pause', 'device'), + ('job-pause', 'id')]: + for resume_cmd, resume_arg in [('block-job-resume', 'device'), + ('job-resume', 'id')]: + iotests.log('=== Testing %s/%s ===' % (pause_cmd, resume_cmd)) + + iotests.log(vm.qmp(pause_cmd, **{pause_arg: 'job0'})) + pause_wait(vm, 'job0') + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + iotests.log(vm.qmp('query-jobs')) + + iotests.log(vm.qmp(resume_cmd, **{resume_arg: 'job0'})) + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + iotests.log(vm.qmp('query-jobs')) + +def test_job_lifecycle(vm, job, job_args, has_ready=False): + iotests.log('') + iotests.log('') + iotests.log('Starting block job: %s (auto-finalize: %s; auto-dismiss: %s)' % + (job, + job_args.get('auto-finalize', True), + job_args.get('auto-dismiss', True))) + iotests.log(vm.qmp(job, job_id='job0', **job_args)) + + # Depending on the storage, the first request may or may not have completed + # yet, so filter out the progress. Later query-job calls don't need the + # filtering because the progress is made deterministic by the block job + # speed + result = vm.qmp('query-jobs') + for j in result['return']: + del j['current-progress'] + iotests.log(result) + + # undefined -> created -> running + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + + # RUNNING state: + # pause/resume should work, complete/finalize/dismiss should error out + iotests.log('') + iotests.log('Pause/resume in RUNNING') + test_pause_resume(vm) + + iotests.log(vm.qmp('job-complete', id='job0')) + iotests.log(vm.qmp('job-finalize', id='job0')) + iotests.log(vm.qmp('job-dismiss', id='job0')) + + iotests.log(vm.qmp('block-job-complete', device='job0')) + iotests.log(vm.qmp('block-job-finalize', id='job0')) + iotests.log(vm.qmp('block-job-dismiss', id='job0')) + + # Let the job complete (or transition to READY if it supports that) + iotests.log(vm.qmp('block-job-set-speed', device='job0', speed=0)) + if has_ready: + iotests.log('') + iotests.log('Waiting for READY state...') + vm.event_wait('BLOCK_JOB_READY') + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + iotests.log(vm.qmp('query-jobs')) + + # READY state: + # pause/resume/complete should work, finalize/dismiss should error out + iotests.log('') + iotests.log('Pause/resume in READY') + test_pause_resume(vm) + + iotests.log(vm.qmp('job-finalize', id='job0')) + iotests.log(vm.qmp('job-dismiss', id='job0')) + + iotests.log(vm.qmp('block-job-finalize', id='job0')) + iotests.log(vm.qmp('block-job-dismiss', id='job0')) + + # Transition to WAITING + iotests.log(vm.qmp('job-complete', id='job0')) + + # Move to WAITING and PENDING state + iotests.log('') + iotests.log('Waiting for PENDING state...') + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + + if not job_args.get('auto-finalize', True): + # PENDING state: + # finalize should work, pause/complete/dismiss should error out + iotests.log(vm.qmp('query-jobs')) + + iotests.log(vm.qmp('job-pause', id='job0')) + iotests.log(vm.qmp('job-complete', id='job0')) + iotests.log(vm.qmp('job-dismiss', id='job0')) + + iotests.log(vm.qmp('block-job-pause', device='job0')) + iotests.log(vm.qmp('block-job-complete', device='job0')) + iotests.log(vm.qmp('block-job-dismiss', id='job0')) + + # Transition to CONCLUDED + iotests.log(vm.qmp('job-finalize', id='job0')) + + + # Move to CONCLUDED state + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + + if not job_args.get('auto-dismiss', True): + # CONCLUDED state: + # dismiss should work, pause/complete/finalize should error out + iotests.log(vm.qmp('query-jobs')) + + iotests.log(vm.qmp('job-pause', id='job0')) + iotests.log(vm.qmp('job-complete', id='job0')) + iotests.log(vm.qmp('job-finalize', id='job0')) + + iotests.log(vm.qmp('block-job-pause', device='job0')) + iotests.log(vm.qmp('block-job-complete', device='job0')) + iotests.log(vm.qmp('block-job-finalize', id='job0')) + + # Transition to NULL + iotests.log(vm.qmp('job-dismiss', id='job0')) + + # Move to NULL state + iotests.log(iotests.filter_qmp_event(vm.event_wait('JOB_STATUS_CHANGE'))) + iotests.log(vm.qmp('query-jobs')) + + +with iotests.FilePath('disk.img') as disk_path, \ + iotests.FilePath('copy.img') as copy_path, \ + iotests.VM() as vm: + + img_size = '4M' + iotests.qemu_img_create('-f', iotests.imgfmt, disk_path, img_size) + iotests.qemu_io('-c', 'write 0 %s' % (img_size), + '-f', iotests.imgfmt, disk_path) + + iotests.log('Launching VM...') + vm.add_blockdev(vm.qmp_to_opts({ + 'driver': iotests.imgfmt, + 'node-name': 'drive0-node', + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + })) + vm.launch() + + # In order to keep things deterministic (especially progress in query-job, + # but related to this also automatic state transitions like job + # completion), but still get pause points often enough to avoid making this + # test very slow, it's important to have the right ratio between speed and + # buf_size. + # + # For backup, buf_size is hard-coded to the source image cluster size (64k), + # so we'll pick the same for mirror. The slice time, i.e. the granularity + # of the rate limiting is 100ms. With a speed of 256k per second, we can + # get four pause points per second. This gives us 250ms per iteration, + # which should be enough to stay deterministic. + + test_job_lifecycle(vm, 'drive-mirror', has_ready=True, job_args={ + 'device': 'drive0-node', + 'target': copy_path, + 'sync': 'full', + 'speed': 262144, + 'buf_size': 65536, + }) + + for auto_finalize in [True, False]: + for auto_dismiss in [True, False]: + test_job_lifecycle(vm, 'drive-backup', job_args={ + 'device': 'drive0-node', + 'target': copy_path, + 'sync': 'full', + 'speed': 262144, + 'auto-finalize': auto_finalize, + 'auto-dismiss': auto_dismiss, + }) + + vm.shutdown() diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out new file mode 100644 index 0000000000..346801b655 --- /dev/null +++ b/tests/qemu-iotests/219.out @@ -0,0 +1,327 @@ +Launching VM... + + +Starting block job: drive-mirror (auto-finalize: True; auto-dismiss: True) +{u'return': {}} +{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} + +Pause/resume in RUNNING +=== Testing block-job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +=== Testing block-job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +=== Testing job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +=== Testing job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'return': {}} + +Waiting for READY state... +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} + +Pause/resume in READY +=== Testing block-job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +=== Testing block-job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +=== Testing job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +=== Testing job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} +{u'return': {}} + +Waiting for PENDING state... +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': []} + + +Starting block job: drive-backup (auto-finalize: True; auto-dismiss: True) +{u'return': {}} +{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} + +Pause/resume in RUNNING +=== Testing block-job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing block-job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'return': {}} + +Waiting for PENDING state... +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': []} + + +Starting block job: drive-backup (auto-finalize: True; auto-dismiss: False) +{u'return': {}} +{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} + +Pause/resume in RUNNING +=== Testing block-job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing block-job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'return': {}} + +Waiting for PENDING state... +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'concluded', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': []} + + +Starting block job: drive-backup (auto-finalize: False; auto-dismiss: True) +{u'return': {}} +{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} + +Pause/resume in RUNNING +=== Testing block-job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing block-job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'return': {}} + +Waiting for PENDING state... +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'pending', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': []} + + +Starting block job: drive-backup (auto-finalize: False; auto-dismiss: False) +{u'return': {}} +{u'return': [{u'status': u'running', u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} + +Pause/resume in RUNNING +=== Testing block-job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing block-job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing job-pause/block-job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +=== Testing job-pause/job-resume === +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +{u'return': {}} + +Waiting for PENDING state... +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'pending', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': [{u'status': u'concluded', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +{u'return': {}} +{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +{u'return': []} diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index c5f4bcf578..f08ee55046 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -119,7 +119,8 @@ _filter_actual_image_size() # replace driver-specific options in the "Formatting..." line _filter_img_create() { - sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ -e "s#$TEST_DIR#TEST_DIR#g" \ -e "s#$IMGFMT#IMGFMT#g" \ -e 's#nbd:127.0.0.1:10810#TEST_DIR/t.IMGFMT#g' \ @@ -154,7 +155,8 @@ _filter_img_info() discard=0 regex_json_spec_start='^ *"format-specific": \{' - sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ -e "s#$TEST_DIR#TEST_DIR#g" \ -e "s#$IMGFMT#IMGFMT#g" \ -e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \ diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 9a65a11026..d054cb97fc 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -147,8 +147,9 @@ else TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" elif [ "$IMGPROTO" = "nfs" ]; then - TEST_DIR="nfs://127.0.0.1/$TEST_DIR" - TEST_IMG=$TEST_DIR/t.$IMGFMT + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + REMOTE_TEST_DIR="nfs://127.0.0.1$TEST_DIR" + TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" elif [ "$IMGPROTO" = "vxhs" ]; then TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT" @@ -173,6 +174,10 @@ if [ ! -d "$TEST_DIR" ]; then exit 1 fi +if [ -z "$REMOTE_TEST_DIR" ]; then + REMOTE_TEST_DIR="$TEST_DIR" +fi + if [ ! -d "$SAMPLE_IMG_DIR" ]; then echo "common.config: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory" exit 1 @@ -333,7 +338,8 @@ _img_info() discard=0 regex_json_spec_start='^ *"format-specific": \{' $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \ - sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ -e "s#$TEST_DIR#TEST_DIR#g" \ -e "s#$IMGFMT#IMGFMT#g" \ -e "/^disk size:/ D" \ diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index cc8cd8cc8e..93f93d71ba 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -97,7 +97,7 @@ 088 rw auto quick 089 rw auto quick 090 rw auto quick -091 rw auto +091 rw auto migration 092 rw auto quick 093 auto 094 rw auto quick @@ -169,7 +169,7 @@ 162 auto quick 163 rw auto 165 rw auto quick -169 rw auto quick +169 rw auto quick migration 170 rw auto quick 171 rw auto quick 172 auto @@ -194,14 +194,14 @@ 192 rw auto quick 194 rw auto migration quick 195 rw auto quick -196 rw auto quick +196 rw auto quick migration 197 rw auto quick 198 rw auto -199 rw auto +199 rw auto migration 200 rw auto 201 rw auto migration 202 rw auto quick -203 rw auto +203 rw auto migration 204 rw auto quick 205 rw auto quick 206 rw auto @@ -216,3 +216,4 @@ 215 rw auto quick 216 rw auto quick 218 rw auto quick +219 rw auto diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index b25d48a91b..fdbdd8b300 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -109,6 +109,20 @@ def qemu_img_pipe(*args): sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) return subp.communicate()[0] +def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]): + args = [ 'info' ] + if imgopts: + args.append('--image-opts') + else: + args += [ '-f', imgfmt ] + args += extra_args + args.append(filename) + + output = qemu_img_pipe(*args) + if not filter_path: + filter_path = filename + log(filter_img_info(output, filter_path)) + def qemu_io(*args): '''Run qemu-io and return the stdout data''' args = qemu_io_args + list(args) @@ -206,6 +220,22 @@ def filter_qmp_event(event): event['timestamp']['microseconds'] = 'USECS' return event +def filter_testfiles(msg): + prefix = os.path.join(test_dir, "%s-" % (os.getpid())) + return msg.replace(prefix, 'TEST_DIR/PID-') + +def filter_img_info(output, filename): + lines = [] + for line in output.split('\n'): + if 'disk size' in line or 'actual-size' in line: + continue + line = line.replace(filename, 'TEST_IMG') \ + .replace(imgfmt, 'IMGFMT') + line = re.sub('iters: [0-9]+', 'iters: XXX', line) + line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line) + lines.append(line) + return '\n'.join(lines) + def log(msg, filters=[]): for flt in filters: msg = flt(msg) @@ -281,6 +311,13 @@ def file_path(*names): return paths[0] if len(paths) == 1 else paths +def remote_filename(path): + if imgproto == 'file': + return path + elif imgproto == 'ssh': + return "ssh://127.0.0.1%s" % (path) + else: + raise Exception("Protocol %s not supported" % (imgproto)) class VM(qtest.QEMUQtestMachine): '''A QEMU VM''' @@ -363,6 +400,58 @@ class VM(qtest.QEMUQtestMachine): return self.qmp('human-monitor-command', command_line='qemu-io %s "%s"' % (drive, cmd)) + def flatten_qmp_object(self, obj, output=None, basestr=''): + if output is None: + output = dict() + if isinstance(obj, list): + for i in range(len(obj)): + self.flatten_qmp_object(obj[i], output, basestr + str(i) + '.') + elif isinstance(obj, dict): + for key in obj: + self.flatten_qmp_object(obj[key], output, basestr + key + '.') + else: + output[basestr[:-1]] = obj # Strip trailing '.' + return output + + def qmp_to_opts(self, obj): + obj = self.flatten_qmp_object(obj) + output_list = list() + for key in obj: + output_list += [key + '=' + obj[key]] + return ','.join(output_list) + + def get_qmp_events_filtered(self, wait=True): + result = [] + for ev in self.get_qmp_events(wait=wait): + result.append(filter_qmp_event(ev)) + return result + + def qmp_log(self, cmd, filters=[filter_testfiles], **kwargs): + logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs) + log(logmsg, filters) + result = self.qmp(cmd, **kwargs) + log(str(result), filters) + return result + + def run_job(self, job, auto_finalize=True, auto_dismiss=False): + while True: + for ev in self.get_qmp_events_filtered(wait=True): + if ev['event'] == 'JOB_STATUS_CHANGE': + status = ev['data']['status'] + if status == 'aborting': + result = self.qmp('query-jobs') + for j in result['return']: + if j['id'] == job: + log('Job failed: %s' % (j['error'])) + elif status == 'pending' and not auto_finalize: + self.qmp_log('job-finalize', id=job) + elif status == 'concluded' and not auto_dismiss: + self.qmp_log('job-dismiss', id=job) + elif status == 'null': + return + else: + iotests.log(ev) + index_re = re.compile(r'([^\[]+)\[([^\]]+)\]') @@ -390,26 +479,6 @@ class QMPTestCase(unittest.TestCase): self.fail('invalid index "%s" in path "%s" in "%s"' % (idx, path, str(d))) return d - def flatten_qmp_object(self, obj, output=None, basestr=''): - if output is None: - output = dict() - if isinstance(obj, list): - for i in range(len(obj)): - self.flatten_qmp_object(obj[i], output, basestr + str(i) + '.') - elif isinstance(obj, dict): - for key in obj: - self.flatten_qmp_object(obj[key], output, basestr + key + '.') - else: - output[basestr[:-1]] = obj # Strip trailing '.' - return output - - def qmp_to_opts(self, obj): - obj = self.flatten_qmp_object(obj) - output_list = list() - for key in obj: - output_list += [key + '=' + obj[key]] - return ','.join(output_list) - def assert_qmp_absent(self, d, path): try: result = self.dictpath(d, path) @@ -444,8 +513,8 @@ class QMPTestCase(unittest.TestCase): '''Asserts that the given filename is a json: filename and that its content is equal to the given reference object''' self.assertEqual(json_filename[:5], 'json:') - self.assertEqual(self.flatten_qmp_object(json.loads(json_filename[5:])), - self.flatten_qmp_object(reference)) + self.assertEqual(self.vm.flatten_qmp_object(json.loads(json_filename[5:])), + self.vm.flatten_qmp_object(reference)) def cancel_and_wait(self, drive='drive0', force=False, resume=False): '''Cancel a block job and wait for it to finish, returning the event''' @@ -464,6 +533,9 @@ class QMPTestCase(unittest.TestCase): self.assert_qmp(event, 'data/device', drive) result = event cancelled = True + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', drive) + self.assert_no_active_block_jobs() return result @@ -479,6 +551,8 @@ class QMPTestCase(unittest.TestCase): self.assert_qmp(event, 'data/offset', event['data']['len']) self.assert_no_active_block_jobs() return event + elif event['event'] == 'JOB_STATUS_CHANGE': + self.assert_qmp(event, 'data/id', drive) def wait_ready(self, drive='drive0'): '''Wait until a block job BLOCK_JOB_READY event''' @@ -542,6 +616,16 @@ def verify_image_format(supported_fmts=[], unsupported_fmts=[]): if not_sup or (imgfmt in unsupported_fmts): notrun('not suitable for this image format: %s' % imgfmt) +def verify_protocol(supported=[], unsupported=[]): + assert not (supported and unsupported) + + if 'generic' in supported: + return + + not_sup = supported and (imgproto not in supported) + if not_sup or (imgproto in unsupported): + notrun('not suitable for this protocol: %s' % imgproto) + def verify_platform(supported_oses=['linux']): if True not in [sys.platform.startswith(x) for x in supported_oses]: notrun('not suitable for this OS: %s' % sys.platform) |