summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/qemu-iotests/0304
-rwxr-xr-xtests/qemu-iotests/0495
-rw-r--r--tests/qemu-iotests/049.out5
-rwxr-xr-xtests/qemu-iotests/0511
-rwxr-xr-xtests/qemu-iotests/206232
-rwxr-xr-xtests/qemu-iotests/2078
-rwxr-xr-xtests/qemu-iotests/21081
-rwxr-xr-xtests/qemu-iotests/21112
-rwxr-xr-xtests/qemu-iotests/212101
-rwxr-xr-xtests/qemu-iotests/213113
-rwxr-xr-xtests/qemu-iotests/237139
-rwxr-xr-xtests/qemu-iotests/25510
-rwxr-xr-xtests/qemu-iotests/26669
-rw-r--r--tests/qemu-iotests/266.out14
-rwxr-xr-xtests/qemu-iotests/2671
-rwxr-xr-xtests/qemu-iotests/2733
-rw-r--r--tests/qemu-iotests/273.out27
-rwxr-xr-xtests/qemu-iotests/27957
-rw-r--r--tests/qemu-iotests/279.out35
-rwxr-xr-xtests/qemu-iotests/28083
-rw-r--r--tests/qemu-iotests/280.out50
-rw-r--r--tests/qemu-iotests/common.rc3
-rw-r--r--tests/qemu-iotests/group2
-rw-r--r--tests/qemu-iotests/iotests.py25
24 files changed, 627 insertions, 453 deletions
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index f3766f2a81..be35bde06f 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -943,7 +943,7 @@ class TestSetSpeed(iotests.QMPTestCase):
         self.assert_no_active_block_jobs()
 
         result = self.vm.qmp('block-stream', device='drive0', speed=-1)
-        self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'")
+        self.assert_qmp(result, 'error/desc', "Parameter 'speed' expects a non-negative value")
 
         self.assert_no_active_block_jobs()
 
@@ -952,7 +952,7 @@ class TestSetSpeed(iotests.QMPTestCase):
         self.assert_qmp(result, 'return', {})
 
         result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1)
-        self.assert_qmp(result, 'error/desc', "Invalid parameter 'speed'")
+        self.assert_qmp(result, 'error/desc', "Parameter 'speed' expects a non-negative value")
 
         self.cancel_and_wait(resume=True)
 
diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049
index c100d30ed0..051a1c79e0 100755
--- a/tests/qemu-iotests/049
+++ b/tests/qemu-iotests/049
@@ -78,6 +78,11 @@ for s in $sizes; do
     test_qemu_img create -f $IMGFMT -o size=$s "$TEST_IMG"
 done
 
+echo "== 4. Specify size twice (-o and traditional parameter) =="
+echo
+
+test_qemu_img create -f $IMGFMT -o size=10M "$TEST_IMG" 20M
+
 echo "== Check correct interpretation of suffixes for cluster size =="
 echo
 sizes="1024 1024b 1k 1K 1M "
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index 6b505408dd..affa55b341 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -121,6 +121,11 @@ qemu-img: TEST_DIR/t.qcow2: Parameter 'size' expects a non-negative number below
 Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta-
 and exabytes, respectively.
 
+== 4. Specify size twice (-o and traditional parameter) ==
+
+qemu-img create -f qcow2 -o size=10M TEST_DIR/t.qcow2 20M
+qemu-img: TEST_DIR/t.qcow2: The image size must be specified only once
+
 == Check correct interpretation of suffixes for cluster size ==
 
 qemu-img create -f qcow2 -o cluster_size=1024 TEST_DIR/t.qcow2 64M
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 53bcdbc911..a13bce2fd0 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -41,6 +41,7 @@ _supported_proto file
 # A compat=0.10 image is created in this test which does not support anything
 # other than refcount_bits=16
 _unsupported_imgopts 'refcount_bits=\([^1]\|.\([^6]\|$\)\)'
+_require_drivers nbd
 
 do_run_qemu()
 {
diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
index 5bb738bf23..9f16a7df8d 100755
--- a/tests/qemu-iotests/206
+++ b/tests/qemu-iotests/206
@@ -25,16 +25,6 @@ from iotests import imgfmt
 
 iotests.verify_image_format(supported_fmts=['qcow2'])
 
-def blockdev_create(vm, options):
-    result = vm.qmp_log('blockdev-create',
-                        filters=[iotests.filter_qmp_testfiles],
-                        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:
@@ -50,18 +40,18 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     size = 128 * 1024 * 1024
 
     vm.launch()
-    blockdev_create(vm, { 'driver': 'file',
-                          'filename': disk_path,
-                          'size': 0 })
+    vm.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
 
     vm.qmp_log('blockdev-add',
                filters=[iotests.filter_qmp_testfiles],
                driver='file', filename=disk_path,
                node_name='imgfile')
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'imgfile',
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'imgfile',
+                         'size': size })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -76,23 +66,23 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     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.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0,
+                         'preallocation': 'off',
+                         'nocow': False })
+
+    vm.blockdev_create({ '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)
@@ -107,23 +97,23 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     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.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0,
+                         'preallocation': 'falloc',
+                         'nocow': True })
+
+    vm.blockdev_create({ '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)
@@ -135,20 +125,20 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     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.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
+
+    vm.blockdev_create({ '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)
@@ -160,22 +150,22 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     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.blockdev_create({ '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)
@@ -187,9 +177,9 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': "this doesn't exist",
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': "this doesn't exist",
+                         'size': size })
     vm.shutdown()
 
     #
@@ -211,9 +201,9 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     vm.launch()
     for size in [ 1234, 18446744073709551104, 9223372036854775808,
                   9223372036854775296 ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'size': size })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': size })
     vm.shutdown()
 
     #
@@ -222,20 +212,20 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     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.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 67108864,
+                         'version': 'v1' })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 67108864,
+                         'version': 'v2',
+                         'lazy-refcounts': True })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 67108864,
+                         'version': 'v2',
+                         'refcount-bits': 8 })
     vm.shutdown()
 
     #
@@ -244,15 +234,15 @@ with iotests.FilePath('t.qcow2') as disk_path, \
     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.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 67108864,
+                         'backing-file': '/dev/null',
+                         'preallocation': 'full' })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 67108864,
+                         'backing-fmt': imgfmt })
     vm.shutdown()
 
     #
@@ -262,14 +252,14 @@ with iotests.FilePath('t.qcow2') as disk_path, \
 
     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.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': 67108864,
+                             'cluster-size': csize })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 281474976710656,
+                         'cluster-size': 512 })
     vm.shutdown()
 
     #
@@ -279,8 +269,8 @@ with iotests.FilePath('t.qcow2') as disk_path, \
 
     vm.launch()
     for refcount_bits in [ 128, 0, 7 ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'size': 67108864,
-                              'refcount-bits': refcount_bits })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': 67108864,
+                             'refcount-bits': refcount_bits })
     vm.shutdown()
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
index ec8c1d06f0..812ab34e47 100755
--- a/tests/qemu-iotests/207
+++ b/tests/qemu-iotests/207
@@ -35,13 +35,7 @@ def filter_hash(qmsg):
     return iotests.filter_qmp(qmsg, _filter)
 
 def blockdev_create(vm, options):
-    result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
-                        filters=[iotests.filter_qmp_testfiles, filter_hash])
-
-    if 'return' in result:
-        assert result['return'] == {}
-        vm.run_job('job0')
-    iotests.log("")
+    vm.blockdev_create(options, filters=[iotests.filter_qmp_testfiles, filter_hash])
 
 with iotests.FilePath('t.img') as disk_path, \
      iotests.VM() as vm:
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
index 565e3b7b9b..4ca0fe26ef 100755
--- a/tests/qemu-iotests/210
+++ b/tests/qemu-iotests/210
@@ -26,15 +26,6 @@ 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,
-                        filters=[iotests.filter_qmp_testfiles])
-
-    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:
 
@@ -49,18 +40,18 @@ with iotests.FilePath('t.luks') as disk_path, \
     size = 128 * 1024 * 1024
 
     vm.launch()
-    blockdev_create(vm, { 'driver': 'file',
-                          'filename': disk_path,
-                          'size': 0 })
+    vm.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
 
     vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
                node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'imgfile',
-                          'key-secret': 'keysec0',
-                          'size': size,
-                          'iter-time': 10 })
+    vm.blockdev_create({ '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
@@ -79,22 +70,22 @@ with iotests.FilePath('t.luks') as disk_path, \
     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.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
+    vm.blockdev_create({ '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
@@ -113,9 +104,9 @@ with iotests.FilePath('t.luks') as disk_path, \
     size = 64 * 1024 * 1024
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': "this doesn't exist",
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': "this doesn't exist",
+                         'size': size })
     vm.shutdown()
 
     #
@@ -126,11 +117,11 @@ with iotests.FilePath('t.luks') as disk_path, \
 
     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.blockdev_create({ '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
@@ -157,10 +148,10 @@ with iotests.FilePath('t.luks') as disk_path, \
 
     vm.launch()
     for size in [ 18446744073709551104, 9223372036854775808, 9223372036854775296 ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'key-secret': 'keysec0',
-                              'size': size })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'key-secret': 'keysec0',
+                             'size': size })
     vm.shutdown()
 
     #
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
index 6afc894f76..8834ebfe85 100755
--- a/tests/qemu-iotests/211
+++ b/tests/qemu-iotests/211
@@ -27,15 +27,9 @@ 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,
-                        filters=[iotests.filter_qmp_testfiles])
-
-    if 'return' in result:
-        assert result['return'] == {}
-        error = vm.run_job('job0')
-        if error and 'Could not allocate bmap' in error:
-            iotests.notrun('Insufficient memory')
-    iotests.log("")
+    error = vm.blockdev_create(options)
+    if error and 'Could not allocate bmap' in error:
+        iotests.notrun('Insufficient memory')
 
 with iotests.FilePath('t.vdi') as disk_path, \
      iotests.VM() as vm:
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
index 42b74f208b..8f3ccc7b15 100755
--- a/tests/qemu-iotests/212
+++ b/tests/qemu-iotests/212
@@ -26,15 +26,6 @@ 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,
-                        filters=[iotests.filter_qmp_testfiles])
-
-    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:
 
@@ -47,16 +38,16 @@ with iotests.FilePath('t.parallels') as disk_path, \
     size = 128 * 1024 * 1024
 
     vm.launch()
-    blockdev_create(vm, { 'driver': 'file',
-                          'filename': disk_path,
-                          'size': 0 })
+    vm.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
 
     vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
                node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'imgfile',
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'imgfile',
+                         'size': size })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -71,16 +62,16 @@ with iotests.FilePath('t.parallels') as disk_path, \
     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.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': {
+                             'driver': 'file',
+                             'filename': disk_path,
+                         },
+                         'size': size,
+                         'cluster-size': 1048576 })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -95,16 +86,16 @@ with iotests.FilePath('t.parallels') as disk_path, \
     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.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': {
+                             'driver': 'file',
+                             'filename': disk_path,
+                         },
+                         'size': size,
+                         'cluster-size': 65536 })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -116,9 +107,9 @@ with iotests.FilePath('t.parallels') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': "this doesn't exist",
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': "this doesn't exist",
+                         'size': size })
     vm.shutdown()
 
     #
@@ -129,9 +120,9 @@ with iotests.FilePath('t.parallels') as disk_path, \
 
     vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'node0',
-                          'size': 0 })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 0 })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -143,9 +134,9 @@ with iotests.FilePath('t.parallels') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'node0',
-                          'size': 4503599627369984})
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 4503599627369984})
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -171,9 +162,9 @@ with iotests.FilePath('t.parallels') as disk_path, \
     vm.launch()
     for size in [ 1234, 18446744073709551104, 9223372036854775808,
                   9223372036854775296, 4503599627370497 ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'size': size })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': size })
     vm.shutdown()
 
     #
@@ -185,12 +176,12 @@ with iotests.FilePath('t.parallels') as disk_path, \
     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.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': 67108864,
+                             'cluster-size': csize })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 281474976710656,
+                         'cluster-size': 512 })
     vm.shutdown()
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
index 5604f3cebb..3fc8dc6eaa 100755
--- a/tests/qemu-iotests/213
+++ b/tests/qemu-iotests/213
@@ -26,15 +26,6 @@ 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,
-                        filters=[iotests.filter_qmp_testfiles])
-
-    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:
 
@@ -47,16 +38,16 @@ with iotests.FilePath('t.vhdx') as disk_path, \
     size = 128 * 1024 * 1024
 
     vm.launch()
-    blockdev_create(vm, { 'driver': 'file',
-                          'filename': disk_path,
-                          'size': 0 })
+    vm.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
 
     vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
                node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'imgfile',
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'imgfile',
+                         'size': size })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -71,19 +62,19 @@ with iotests.FilePath('t.vhdx') as disk_path, \
     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.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
+    vm.blockdev_create({ '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)
@@ -98,19 +89,19 @@ with iotests.FilePath('t.vhdx') as disk_path, \
     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.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
+    vm.blockdev_create({ '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)
@@ -122,9 +113,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': "this doesn't exist",
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': "this doesn't exist",
+                         'size': size })
     vm.shutdown()
 
     #
@@ -135,9 +126,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \
 
     vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'node0',
-                          'size': 0 })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 0 })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -149,9 +140,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'node0',
-                          'size': 70368744177664 })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 70368744177664 })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -176,9 +167,9 @@ with iotests.FilePath('t.vhdx') as disk_path, \
     vm.launch()
     for size in [ 18446744073709551104, 9223372036854775808,
                   9223372036854775296, 70368744177665 ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'size': size })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': size })
     vm.shutdown()
 
     #
@@ -189,10 +180,10 @@ with iotests.FilePath('t.vhdx') as disk_path, \
 
     vm.launch()
     for bsize in [ 1234567, 128, 3145728, 536870912, 0 ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'size': 67108864,
-                              'block-size': bsize })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': 67108864,
+                             'block-size': bsize })
     vm.shutdown()
 
     #
@@ -203,8 +194,8 @@ with iotests.FilePath('t.vhdx') as disk_path, \
 
     vm.launch()
     for lsize in [ 1234567, 128, 4294967296, 0 ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'size': 67108864,
-                              'log-size': lsize })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': 67108864,
+                             'log-size': lsize })
     vm.shutdown()
diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237
index 06897f8c87..a2242a4736 100755
--- a/tests/qemu-iotests/237
+++ b/tests/qemu-iotests/237
@@ -26,15 +26,6 @@ from iotests import imgfmt
 
 iotests.verify_image_format(supported_fmts=['vmdk'])
 
-def blockdev_create(vm, options):
-    result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
-                        filters=[iotests.filter_qmp_testfiles])
-
-    if 'return' in result:
-        assert result['return'] == {}
-        vm.run_job('job0')
-    iotests.log("")
-
 with iotests.FilePath('t.vmdk') as disk_path, \
      iotests.FilePath('t.vmdk.1') as extent1_path, \
      iotests.FilePath('t.vmdk.2') as extent2_path, \
@@ -50,16 +41,16 @@ with iotests.FilePath('t.vmdk') as disk_path, \
     size = 5 * 1024 * 1024 * 1024
 
     vm.launch()
-    blockdev_create(vm, { 'driver': 'file',
-                          'filename': disk_path,
-                          'size': 0 })
+    vm.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
 
     vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
                node_name='imgfile', filters=[iotests.filter_qmp_testfiles])
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'imgfile',
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'imgfile',
+                         'size': size })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -74,21 +65,21 @@ with iotests.FilePath('t.vmdk') as disk_path, \
     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,
-                          'extents': [],
-                          'subformat': 'monolithicSparse',
-                          'adapter-type': 'ide',
-                          'hwversion': '4',
-                          'zeroed-grain': False })
+    vm.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
+
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': {
+                             'driver': 'file',
+                             'filename': disk_path,
+                         },
+                         'size': size,
+                         'extents': [],
+                         'subformat': 'monolithicSparse',
+                         'adapter-type': 'ide',
+                         'hwversion': '4',
+                         'zeroed-grain': False })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -103,20 +94,20 @@ with iotests.FilePath('t.vmdk') as disk_path, \
     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,
-                          'extents': [],
-                          'subformat': 'monolithicSparse',
-                          'adapter-type': 'buslogic',
-                          'zeroed-grain': True })
+    vm.blockdev_create({ 'driver': 'file',
+                         'filename': disk_path,
+                         'size': 0 })
+
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': {
+                             'driver': 'file',
+                             'filename': disk_path,
+                         },
+                         'size': size,
+                         'extents': [],
+                         'subformat': 'monolithicSparse',
+                         'adapter-type': 'buslogic',
+                         'zeroed-grain': True })
     vm.shutdown()
 
     iotests.img_info_log(disk_path)
@@ -128,9 +119,9 @@ with iotests.FilePath('t.vmdk') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': "this doesn't exist",
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': "this doesn't exist",
+                         'size': size })
     vm.shutdown()
 
     #
@@ -148,10 +139,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \
 
     vm.launch()
     for adapter_type in [ 'ide', 'buslogic', 'lsilogic', 'legacyESX' ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'size': size,
-                              'adapter-type': adapter_type })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': size,
+                             'adapter-type': adapter_type })
     vm.shutdown()
 
     # Invalid
@@ -160,10 +151,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \
 
     vm.launch()
     for adapter_type in [ 'foo', 'IDE', 'legacyesx', 1 ]:
-        blockdev_create(vm, { 'driver': imgfmt,
-                              'file': 'node0',
-                              'size': size,
-                              'adapter-type': adapter_type })
+        vm.blockdev_create({ 'driver': imgfmt,
+                             'file': 'node0',
+                             'size': size,
+                             'adapter-type': adapter_type })
     vm.shutdown()
 
     #
@@ -185,10 +176,10 @@ with iotests.FilePath('t.vmdk') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'node0',
-                          'size': size,
-                          'subformat': 'monolithicFlat' })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': size,
+                         'subformat': 'monolithicFlat' })
     vm.shutdown()
 
     # Correct extent
@@ -196,11 +187,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'node0',
-                          'size': size,
-                          'subformat': 'monolithicFlat',
-                          'extents': ['ext1'] })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': size,
+                         'subformat': 'monolithicFlat',
+                         'extents': ['ext1'] })
     vm.shutdown()
 
     # Extra extent
@@ -208,11 +199,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \
     iotests.log("")
 
     vm.launch()
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'node0',
-                          'size': 512,
-                          'subformat': 'monolithicFlat',
-                          'extents': ['ext1', 'ext2', 'ext3'] })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'node0',
+                         'size': 512,
+                         'subformat': 'monolithicFlat',
+                         'extents': ['ext1', 'ext2', 'ext3'] })
     vm.shutdown()
 
     # Split formats
@@ -228,11 +219,11 @@ with iotests.FilePath('t.vmdk') as disk_path, \
             extents = [ "ext%d" % (i) for i in range(1, num_extents + 1) ]
 
             vm.launch()
-            blockdev_create(vm, { 'driver': imgfmt,
-                                  'file': 'node0',
-                                  'size': size,
-                                  'subformat': subfmt,
-                                  'extents': extents })
+            vm.blockdev_create({ 'driver': imgfmt,
+                                 'file': 'node0',
+                                 'size': size,
+                                 'subformat': subfmt,
+                                 'extents': extents })
             vm.shutdown()
 
             iotests.img_info_log(disk_path)
diff --git a/tests/qemu-iotests/255 b/tests/qemu-iotests/255
index 3632d507d0..0ba03d9e61 100755
--- a/tests/qemu-iotests/255
+++ b/tests/qemu-iotests/255
@@ -25,16 +25,6 @@ from iotests import imgfmt
 
 iotests.verify_image_format(supported_fmts=['qcow2'])
 
-def blockdev_create(vm, options):
-    result = vm.qmp_log('blockdev-create',
-                        filters=[iotests.filter_qmp_testfiles],
-                        job_id='job0', options=options)
-
-    if 'return' in result:
-        assert result['return'] == {}
-        vm.run_job('job0')
-    iotests.log("")
-
 iotests.log('Finishing a commit job with background reads')
 iotests.log('============================================')
 iotests.log('')
diff --git a/tests/qemu-iotests/266 b/tests/qemu-iotests/266
index 5b35cd67e4..c353cf88ee 100755
--- a/tests/qemu-iotests/266
+++ b/tests/qemu-iotests/266
@@ -22,15 +22,6 @@ import iotests
 from iotests import imgfmt
 
 
-def blockdev_create(vm, options):
-    result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
-                        filters=[iotests.filter_qmp_testfiles])
-
-    if 'return' in result:
-        assert result['return'] == {}
-        vm.run_job('job0')
-
-
 # Successful image creation (defaults)
 def implicit_defaults(vm, file_path):
     iotests.log("=== Successful image creation (defaults) ===")
@@ -40,9 +31,9 @@ def implicit_defaults(vm, file_path):
     # (Close to 64 MB)
     size = 8 * 964 * 17 * 512
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'protocol-node',
-                          'size': size })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'protocol-node',
+                         'size': size })
 
 
 # Successful image creation (explicit defaults)
@@ -54,11 +45,11 @@ def explicit_defaults(vm, file_path):
     # (Close to 128 MB)
     size = 16 * 964 * 17 * 512
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'protocol-node',
-                          'size': size,
-                          'subformat': 'dynamic',
-                          'force-size': False })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'protocol-node',
+                         'size': size,
+                         'subformat': 'dynamic',
+                         'force-size': False })
 
 
 # Successful image creation (non-default options)
@@ -69,11 +60,11 @@ def non_defaults(vm, file_path):
     # Not representable in CHS (fine with force-size=True)
     size = 1048576
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'protocol-node',
-                          'size': size,
-                          'subformat': 'fixed',
-                          'force-size': True })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'protocol-node',
+                         'size': size,
+                         'subformat': 'fixed',
+                         'force-size': True })
 
 
 # Size not representable in CHS with force-size=False
@@ -84,10 +75,10 @@ def non_chs_size_without_force(vm, file_path):
     # Not representable in CHS (will not work with force-size=False)
     size = 1048576
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'protocol-node',
-                          'size': size,
-                          'force-size': False })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'protocol-node',
+                         'size': size,
+                         'force-size': False })
 
 
 # Zero size
@@ -95,9 +86,9 @@ def zero_size(vm, file_path):
     iotests.log("=== Zero size===")
     iotests.log("")
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'protocol-node',
-                          'size': 0 })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'protocol-node',
+                         'size': 0 })
 
 
 # Maximum CHS size
@@ -105,9 +96,9 @@ def maximum_chs_size(vm, file_path):
     iotests.log("=== Maximum CHS size===")
     iotests.log("")
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'protocol-node',
-                          'size': 16 * 65535 * 255 * 512 })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'protocol-node',
+                         'size': 16 * 65535 * 255 * 512 })
 
 
 # Actual maximum size
@@ -115,10 +106,10 @@ def maximum_size(vm, file_path):
     iotests.log("=== Actual maximum size===")
     iotests.log("")
 
-    blockdev_create(vm, { 'driver': imgfmt,
-                          'file': 'protocol-node',
-                          'size': 0xff000000 * 512,
-                          'force-size': True })
+    vm.blockdev_create({ 'driver': imgfmt,
+                         'file': 'protocol-node',
+                         'size': 0xff000000 * 512,
+                         'force-size': True })
 
 
 def main():
@@ -132,9 +123,9 @@ def main():
             vm.launch()
 
             iotests.log('--- Creating empty file ---')
-            blockdev_create(vm, { 'driver': 'file',
-                                  'filename': file_path,
-                                  'size': 0 })
+            vm.blockdev_create({ 'driver': 'file',
+                                 'filename': file_path,
+                                 'size': 0 })
 
             vm.qmp_log('blockdev-add', driver='file', filename=file_path,
                        node_name='protocol-node',
diff --git a/tests/qemu-iotests/266.out b/tests/qemu-iotests/266.out
index b11953e81f..5a7d7d01aa 100644
--- a/tests/qemu-iotests/266.out
+++ b/tests/qemu-iotests/266.out
@@ -3,6 +3,7 @@
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
+
 {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
 {"return": {}}
 
@@ -13,6 +14,7 @@
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
+
 image: TEST_IMG
 file format: IMGFMT
 virtual size: 64 MiB (67125248 bytes)
@@ -23,6 +25,7 @@ cluster_size: 2097152
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
+
 {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
 {"return": {}}
 
@@ -33,6 +36,7 @@ cluster_size: 2097152
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
+
 image: TEST_IMG
 file format: IMGFMT
 virtual size: 128 MiB (134250496 bytes)
@@ -43,6 +47,7 @@ cluster_size: 2097152
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
+
 {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
 {"return": {}}
 
@@ -53,6 +58,7 @@ cluster_size: 2097152
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
+
 image: TEST_IMG
 file format: IMGFMT
 virtual size: 1 MiB (1048576 bytes)
@@ -62,6 +68,7 @@ virtual size: 1 MiB (1048576 bytes)
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
+
 {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
 {"return": {}}
 
@@ -73,6 +80,7 @@ Job failed: The requested image size cannot be represented in CHS geometry
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
+
 qemu-img: Could not open 'TEST_IMG': File too small for a VHD header
 
 --- Creating empty file ---
@@ -80,6 +88,7 @@ qemu-img: Could not open 'TEST_IMG': File too small for a VHD header
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
+
 {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
 {"return": {}}
 
@@ -90,6 +99,7 @@ qemu-img: Could not open 'TEST_IMG': File too small for a VHD header
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
+
 image: TEST_IMG
 file format: IMGFMT
 virtual size: 0 B (0 bytes)
@@ -100,6 +110,7 @@ cluster_size: 2097152
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
+
 {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
 {"return": {}}
 
@@ -110,6 +121,7 @@ cluster_size: 2097152
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
+
 image: TEST_IMG
 file format: IMGFMT
 virtual size: 127 GiB (136899993600 bytes)
@@ -120,6 +132,7 @@ cluster_size: 2097152
 {"return": {}}
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
+
 {"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vpc", "node-name": "protocol-node"}}
 {"return": {}}
 
@@ -130,6 +143,7 @@ cluster_size: 2097152
 {"execute": "job-dismiss", "arguments": {"id": "job0"}}
 {"return": {}}
 
+
 image: TEST_IMG
 file format: IMGFMT
 virtual size: 1.99 TiB (2190433320960 bytes)
diff --git a/tests/qemu-iotests/267 b/tests/qemu-iotests/267
index 170e173c0a..b823668e29 100755
--- a/tests/qemu-iotests/267
+++ b/tests/qemu-iotests/267
@@ -40,6 +40,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
 _supported_fmt qcow2
 _supported_proto file
 _supported_os Linux
+_require_drivers copy-on-read
 
 # Internal snapshots are (currently) impossible with refcount_bits=1
 _unsupported_imgopts 'refcount_bits=1[^0-9]'
diff --git a/tests/qemu-iotests/273 b/tests/qemu-iotests/273
index 98a672516d..d598c47d9b 100755
--- a/tests/qemu-iotests/273
+++ b/tests/qemu-iotests/273
@@ -48,7 +48,8 @@ do_run_qemu()
 run_qemu()
 {
     do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp |
-        _filter_generated_node_ids | _filter_imgfmt | _filter_actual_image_size
+        _filter_generated_node_ids | _filter_imgfmt |
+        _filter_actual_image_size | _filter_img_info
 }
 
 TEST_IMG="$TEST_IMG.base" _make_test_img 64M
diff --git a/tests/qemu-iotests/273.out b/tests/qemu-iotests/273.out
index c410fee5c4..684b8d6f77 100644
--- a/tests/qemu-iotests/273.out
+++ b/tests/qemu-iotests/273.out
@@ -38,15 +38,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
                     "cluster-size": 65536,
                     "format": "IMGFMT",
                     "actual-size": SIZE,
-                    "format-specific": {
-                        "type": "IMGFMT",
-                        "data": {
-                            "compat": "1.1",
-                            "lazy-refcounts": false,
-                            "refcount-bits": 16,
-                            "corrupt": false
-                        }
-                    },
                     "full-backing-filename": "TEST_DIR/t.IMGFMT.base",
                     "backing-filename": "TEST_DIR/t.IMGFMT.base",
                     "dirty-flag": false
@@ -57,15 +48,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
                 "cluster-size": 65536,
                 "format": "IMGFMT",
                 "actual-size": SIZE,
-                "format-specific": {
-                    "type": "IMGFMT",
-                    "data": {
-                        "compat": "1.1",
-                        "lazy-refcounts": false,
-                        "refcount-bits": 16,
-                        "corrupt": false
-                    }
-                },
                 "full-backing-filename": "TEST_DIR/t.IMGFMT.mid",
                 "backing-filename": "TEST_DIR/t.IMGFMT.mid",
                 "dirty-flag": false
@@ -136,15 +118,6 @@ Testing: -blockdev file,node-name=base,filename=TEST_DIR/t.IMGFMT.base -blockdev
                 "cluster-size": 65536,
                 "format": "IMGFMT",
                 "actual-size": SIZE,
-                "format-specific": {
-                    "type": "IMGFMT",
-                    "data": {
-                        "compat": "1.1",
-                        "lazy-refcounts": false,
-                        "refcount-bits": 16,
-                        "corrupt": false
-                    }
-                },
                 "full-backing-filename": "TEST_DIR/t.IMGFMT.base",
                 "backing-filename": "TEST_DIR/t.IMGFMT.base",
                 "dirty-flag": false
diff --git a/tests/qemu-iotests/279 b/tests/qemu-iotests/279
new file mode 100755
index 0000000000..6682376808
--- /dev/null
+++ b/tests/qemu-iotests/279
@@ -0,0 +1,57 @@
+#!/usr/bin/env bash
+#
+# Test qemu-img --backing-chain --image-opts
+#
+# Copyright (C) 2019 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/>.
+#
+
+seq=$(basename "$0")
+echo "QA output created by $seq"
+
+status=1	# failure is the default!
+
+_cleanup()
+{
+    _cleanup_test_img
+    rm -f "$TEST_IMG.mid"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# Backing files are required...
+_supported_fmt qcow qcow2 vmdk qed
+_supported_proto file
+_supported_os Linux
+
+TEST_IMG="$TEST_IMG.base" _make_test_img 64M
+TEST_IMG="$TEST_IMG.mid" _make_test_img -b "$TEST_IMG.base"
+_make_test_img -b "$TEST_IMG.mid"
+
+echo
+echo '== qemu-img info --backing-chain =='
+_img_info --backing-chain | _filter_img_info
+
+echo
+echo '== qemu-img info --backing-chain --image-opts =='
+TEST_IMG="driver=qcow2,file.driver=file,file.filename=$TEST_IMG" _img_info --backing-chain --image-opts | _filter_img_info
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/279.out b/tests/qemu-iotests/279.out
new file mode 100644
index 0000000000..f4dc6c69cb
--- /dev/null
+++ b/tests/qemu-iotests/279.out
@@ -0,0 +1,35 @@
+QA output created by 279
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT.mid', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.mid
+
+== qemu-img info --backing-chain ==
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+backing file: TEST_DIR/t.IMGFMT.mid
+
+image: TEST_DIR/t.IMGFMT.mid
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+backing file: TEST_DIR/t.IMGFMT.base
+
+image: TEST_DIR/t.IMGFMT.base
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+
+== qemu-img info --backing-chain --image-opts ==
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+backing file: TEST_DIR/t.IMGFMT.mid
+
+image: TEST_DIR/t.IMGFMT.mid
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+backing file: TEST_DIR/t.IMGFMT.base
+
+image: TEST_DIR/t.IMGFMT.base
+file format: IMGFMT
+virtual size: 64 MiB (67108864 bytes)
+*** done
diff --git a/tests/qemu-iotests/280 b/tests/qemu-iotests/280
new file mode 100755
index 0000000000..0b1fa8e1d8
--- /dev/null
+++ b/tests/qemu-iotests/280
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 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>
+#
+# Test migration to file for taking an external snapshot with VM state.
+
+import iotests
+import os
+
+iotests.verify_image_format(supported_fmts=['qcow2'])
+iotests.verify_protocol(supported=['file'])
+iotests.verify_platform(['linux'])
+
+with iotests.FilePath('base') as base_path , \
+     iotests.FilePath('top') as top_path, \
+     iotests.VM() as vm:
+
+    iotests.qemu_img_log('create', '-f', iotests.imgfmt, base_path, '64M')
+
+    iotests.log('=== Launch VM ===')
+    vm.add_object('iothread,id=iothread0')
+    vm.add_blockdev('file,filename=%s,node-name=base-file' % (base_path))
+    vm.add_blockdev('%s,file=base-file,node-name=base-fmt' % (iotests.imgfmt))
+    vm.add_device('virtio-blk,drive=base-fmt,iothread=iothread0,id=vda')
+    vm.launch()
+
+    vm.enable_migration_events('VM')
+
+    iotests.log('\n=== Migrate to file ===')
+    vm.qmp_log('migrate', uri='exec:cat > /dev/null')
+
+    with iotests.Timeout(3, 'Migration does not complete'):
+        vm.wait_migration()
+
+    iotests.log('\nVM is now stopped:')
+    iotests.log(vm.qmp('query-migrate')['return']['status'])
+    vm.qmp_log('query-status')
+
+    iotests.log('\n=== Create a snapshot of the disk image ===')
+    vm.blockdev_create({
+        'driver': 'file',
+        'filename': top_path,
+        'size': 0,
+    })
+    vm.qmp_log('blockdev-add', node_name='top-file',
+               driver='file', filename=top_path,
+               filters=[iotests.filter_qmp_testfiles])
+
+    vm.blockdev_create({
+        'driver': iotests.imgfmt,
+        'file': 'top-file',
+        'size': 1024 * 1024,
+    })
+    vm.qmp_log('blockdev-add', node_name='top-fmt',
+               driver=iotests.imgfmt, file='top-file')
+
+    vm.qmp_log('blockdev-snapshot', node='base-fmt', overlay='top-fmt')
+
+    iotests.log('\n=== Resume the VM and simulate a write request ===')
+    vm.qmp_log('cont')
+    iotests.log(vm.hmp_qemu_io('-d vda/virtio-backend', 'write 4k 4k'))
+
+    iotests.log('\n=== Commit it to the backing file ===')
+    result = vm.qmp_log('block-commit', job_id='job0', auto_dismiss=False,
+                        device='top-fmt', top_node='top-fmt',
+                        filters=[iotests.filter_qmp_testfiles])
+    if 'return' in result:
+        vm.run_job('job0')
diff --git a/tests/qemu-iotests/280.out b/tests/qemu-iotests/280.out
new file mode 100644
index 0000000000..5d382faaa8
--- /dev/null
+++ b/tests/qemu-iotests/280.out
@@ -0,0 +1,50 @@
+Formatting 'TEST_DIR/PID-base', fmt=qcow2 size=67108864 cluster_size=65536 lazy_refcounts=off refcount_bits=16
+
+=== Launch VM ===
+Enabling migration QMP events on VM...
+{"return": {}}
+
+=== Migrate to file ===
+{"execute": "migrate", "arguments": {"uri": "exec:cat > /dev/null"}}
+{"return": {}}
+{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+
+VM is now stopped:
+completed
+{"execute": "query-status", "arguments": {}}
+{"return": {"running": false, "singlestep": false, "status": "postmigrate"}}
+
+=== Create a snapshot of the disk image ===
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-top", "size": 0}}}
+{"return": {}}
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
+{"return": {}}
+
+{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-top", "node-name": "top-file"}}
+{"return": {}}
+{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "file": "top-file", "size": 1048576}}}
+{"return": {}}
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
+{"return": {}}
+
+{"execute": "blockdev-add", "arguments": {"driver": "qcow2", "file": "top-file", "node-name": "top-fmt"}}
+{"return": {}}
+{"execute": "blockdev-snapshot", "arguments": {"node": "base-fmt", "overlay": "top-fmt"}}
+{"return": {}}
+
+=== Resume the VM and simulate a write request ===
+{"execute": "cont", "arguments": {}}
+{"return": {}}
+{"return": ""}
+
+=== Commit it to the backing file ===
+{"execute": "block-commit", "arguments": {"auto-dismiss": false, "device": "top-fmt", "job-id": "job0", "top-node": "top-fmt"}}
+{"return": {}}
+{"execute": "job-complete", "arguments": {"id": "job0"}}
+{"return": {}}
+{"data": {"device": "job0", "len": 65536, "offset": 65536, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"data": {"device": "job0", "len": 65536, "offset": 65536, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "job-dismiss", "arguments": {"id": "job0"}}
+{"return": {}}
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 6f0582c79a..555c453911 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -217,7 +217,8 @@ if [ "$IMGOPTSSYNTAX" = "true" ]; then
         TEST_IMG="$DRIVER,file.filename=$TEST_DIR/t.$IMGFMT"
     elif [ "$IMGPROTO" = "nbd" ]; then
         TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
-        TEST_IMG="$DRIVER,file.driver=nbd,file.type=unix,file.path=$SOCKDIR/nbd"
+        TEST_IMG="$DRIVER,file.driver=nbd,file.type=unix"
+        TEST_IMG="$TEST_IMG,file.path=$SOCK_DIR/nbd"
     elif [ "$IMGPROTO" = "ssh" ]; then
         TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT
         TEST_IMG="$DRIVER,file.driver=ssh,file.host=127.0.0.1,file.path=$TEST_IMG_FILE"
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 6b10a6a762..cb2b789e44 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -286,3 +286,5 @@
 272 rw
 273 backing quick
 277 rw quick
+279 rw backing quick
+280 rw migration quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index df0708923d..8739ec6613 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -162,6 +162,11 @@ def qemu_io(*args):
         sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args)))
     return subp.communicate()[0]
 
+def qemu_io_log(*args):
+    result = qemu_io(*args)
+    log(result, filters=[filter_testfiles, filter_qemu_io])
+    return result
+
 def qemu_io_silent(*args):
     '''Run qemu-io and return the exit code, suppressing stdout'''
     args = qemu_io_args + list(args)
@@ -604,7 +609,7 @@ class VM(qtest.QEMUQtestMachine):
         ]
         error = None
         while True:
-            ev = filter_qmp_event(self.events_wait(events))
+            ev = filter_qmp_event(self.events_wait(events, timeout=wait))
             if ev['event'] != 'JOB_STATUS_CHANGE':
                 if use_log:
                     log(ev)
@@ -617,6 +622,8 @@ class VM(qtest.QEMUQtestMachine):
                         error = j['error']
                         if use_log:
                             log('Job failed: %s' % (j['error']))
+            elif status == 'ready':
+                self.qmp_log('job-complete', id=job)
             elif status == 'pending' and not auto_finalize:
                 if pre_finalize:
                     pre_finalize()
@@ -636,6 +643,22 @@ class VM(qtest.QEMUQtestMachine):
             elif status == 'null':
                 return error
 
+    # Returns None on success, and an error string on failure
+    def blockdev_create(self, options, job_id='job0', filters=None):
+        if filters is None:
+            filters = [filter_qmp_testfiles]
+        result = self.qmp_log('blockdev-create', filters=filters,
+                              job_id=job_id, options=options)
+
+        if 'return' in result:
+            assert result['return'] == {}
+            job_result = self.run_job(job_id)
+        else:
+            job_result = result['error']
+
+        log("")
+        return job_result
+
     def enable_migration_events(self, name):
         log('Enabling migration QMP events on %s...' % name)
         log(self.qmp('migrate-set-capabilities', capabilities=[