All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API
@ 2018-05-25 16:33 Kevin Wolf
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value Kevin Wolf
                   ` (15 more replies)
  0 siblings, 16 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This changes the x-blockdev-create QMP command so that it doesn't block
the monitor and the main loop any more, but starts a background job that
performs the image creation.

The basic job as implemented here is all that is necessary to make image
creation asynchronous and to provide a QMP interface that can be marked
stable, but it still lacks a few features that jobs usually provide: The
job will ignore pause commands and it doesn't publish progress yet (so
both current-progress and total-progress stay at 0). These features can
be added later without breaking compatibility.

At the end of the series, the interface is declared stable and the x-
prefix is removed.

Kevin Wolf (14):
  vdi: Fix vdi_co_do_create() return value
  vhdx: Fix vhdx_co_create() return value
  job: Add error message for failing jobs
  block/create: Make x-blockdev-create a job
  qemu-iotests: Add VM.get_qmp_events_filtered()
  qemu-iotests: Add VM.qmp_log()
  qemu-iotests: Add iotests.img_info_log()
  qemu-iotests: Rewrite 206 for blockdev-create job
  qemu-iotests: Rewrite 207 for blockdev-create job
  qemu-iotests: Rewrite 210 for blockdev-create job
  qemu-iotests: Rewrite 211 for blockdev-create job
  qemu-iotests: Rewrite 212 for blockdev-create job
  qemu-iotests: Rewrite 213 for blockdev-create job
  block/create: Mark blockdev-create stable

 qapi/block-core.json          |  18 +-
 qapi/job.json                 |   4 +-
 include/qemu/job.h            |   7 +-
 block/backup.c                |   2 +-
 block/commit.c                |   2 +-
 block/create.c                |  61 ++--
 block/mirror.c                |   2 +-
 block/stream.c                |   2 +-
 block/vdi.c                   |   1 +
 block/vhdx.c                  |   2 +-
 job-qmp.c                     |   9 +-
 job.c                         |  15 +-
 tests/qemu-iotests/206        | 705 +++++++++++++++++-------------------------
 tests/qemu-iotests/206.out    | 241 +++++++++------
 tests/qemu-iotests/207        | 435 ++++++++++++--------------
 tests/qemu-iotests/207.out    |  89 +++---
 tests/qemu-iotests/210        | 393 ++++++++++-------------
 tests/qemu-iotests/210.out    | 189 +++++++----
 tests/qemu-iotests/211        | 384 ++++++++++-------------
 tests/qemu-iotests/211.out    | 123 ++++----
 tests/qemu-iotests/212        | 483 +++++++++++------------------
 tests/qemu-iotests/212.out    | 181 +++++++----
 tests/qemu-iotests/213        | 520 ++++++++++++-------------------
 tests/qemu-iotests/213.out    | 198 +++++++-----
 tests/qemu-iotests/iotests.py |  74 +++++
 25 files changed, 1955 insertions(+), 2185 deletions(-)

-- 
2.13.6

^ permalink raw reply	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 10:38   ` Max Reitz
  2018-05-29 14:45   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 02/14] vhdx: Fix vhdx_co_create() " Kevin Wolf
                   ` (14 subsequent siblings)
  15 siblings, 2 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

.bdrv_co_create() is supposed to return 0 on success, but vdi could
return a positive value instead. Fix this.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vdi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/block/vdi.c b/block/vdi.c
index 96a22b8e83..668af0a828 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -865,6 +865,7 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
         }
     }
 
+    ret = 0;
 exit:
     blk_unref(blk);
     bdrv_unref(bs_file);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 02/14] vhdx: Fix vhdx_co_create() return value
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 10:40   ` Max Reitz
  2018-05-29 14:44   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 03/14] job: Add error message for failing jobs Kevin Wolf
                   ` (13 subsequent siblings)
  15 siblings, 2 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

.bdrv_co_create() is supposed to return 0 on success, but vhdx could
return a positive value instead. Fix this.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block/vhdx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/vhdx.c b/block/vhdx.c
index 0b1e21c750..b1ba121bb6 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -1951,7 +1951,7 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
         goto delete_and_exit;
     }
 
-
+    ret = 0;
 delete_and_exit:
     blk_unref(blk);
     bdrv_unref(bs);
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 03/14] job: Add error message for failing jobs
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value Kevin Wolf
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 02/14] vhdx: Fix vhdx_co_create() " Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 11:01   ` Max Reitz
  2018-05-29 14:43   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 04/14] block/create: Make x-blockdev-create a job Kevin Wolf
                   ` (12 subsequent siblings)
  15 siblings, 2 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

So far we relied on job->ret and strerror() to produce an error message
for failed jobs. Not surprisingly, this tends to result in completely
useless messages.

This adds a Job.error field that can contain an error string for a
failing job, and a parameter to job_completed() that sets the field. As
a default, if NULL is passed, we continue to use strerror(job->ret).

All existing callers are changed to pass NULL. They can be improved in
separate patches.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 include/qemu/job.h |  7 ++++++-
 block/backup.c     |  2 +-
 block/commit.c     |  2 +-
 block/mirror.c     |  2 +-
 block/stream.c     |  2 +-
 job-qmp.c          |  9 ++-------
 job.c              | 15 +++++++++++++--
 7 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/include/qemu/job.h b/include/qemu/job.h
index 8c8badf75e..b2e1dd00b9 100644
--- a/include/qemu/job.h
+++ b/include/qemu/job.h
@@ -124,6 +124,9 @@ typedef struct Job {
     /** Estimated progress_current value at the completion of the job */
     int64_t progress_total;
 
+    /** Error string for a failed job (NULL if job->ret == 0) */
+    char *error;
+
     /** ret code passed to job_completed. */
     int ret;
 
@@ -466,13 +469,15 @@ void job_transition_to_ready(Job *job);
 /**
  * @job: The job being completed.
  * @ret: The status code.
+ * @error: The error message for a failing job (only with @ret < 0). If @ret is
+ *         negative, but NULL is given for @error, strerror() is used.
  *
  * Marks @job as completed. If @ret is non-zero, the job transaction it is part
  * of is aborted. If @ret is zero, the job moves into the WAITING state. If it
  * is the last job to complete in its transaction, all jobs in the transaction
  * move from WAITING to PENDING.
  */
-void job_completed(Job *job, int ret);
+void job_completed(Job *job, int ret, Error *error);
 
 /** Asynchronously complete the specified @job. */
 void job_complete(Job *job, Error **errp);
diff --git a/block/backup.c b/block/backup.c
index 4e228e959b..5661435675 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -321,7 +321,7 @@ static void backup_complete(Job *job, void *opaque)
 {
     BackupCompleteData *data = opaque;
 
-    job_completed(job, data->ret);
+    job_completed(job, data->ret, NULL);
     g_free(data);
 }
 
diff --git a/block/commit.c b/block/commit.c
index 620666161b..e1814d9693 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -117,7 +117,7 @@ static void commit_complete(Job *job, void *opaque)
      * bdrv_set_backing_hd() to fail. */
     block_job_remove_all_bdrv(bjob);
 
-    job_completed(job, ret);
+    job_completed(job, ret, NULL);
     g_free(data);
 
     /* If bdrv_drop_intermediate() didn't already do that, remove the commit
diff --git a/block/mirror.c b/block/mirror.c
index dcb66ec3be..435268bbbf 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -581,7 +581,7 @@ static void mirror_exit(Job *job, void *opaque)
     blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
     blk_insert_bs(bjob->blk, mirror_top_bs, &error_abort);
 
-    job_completed(job, data->ret);
+    job_completed(job, data->ret, NULL);
 
     g_free(data);
     bdrv_drained_end(src);
diff --git a/block/stream.c b/block/stream.c
index a5d6e0cf8a..9264b68a1e 100644
--- a/block/stream.c
+++ b/block/stream.c
@@ -93,7 +93,7 @@ out:
     }
 
     g_free(s->backing_file_str);
-    job_completed(job, data->ret);
+    job_completed(job, data->ret, NULL);
     g_free(data);
 }
 
diff --git a/job-qmp.c b/job-qmp.c
index 7f38f63336..410775df61 100644
--- a/job-qmp.c
+++ b/job-qmp.c
@@ -136,14 +136,9 @@ void qmp_job_dismiss(const char *id, Error **errp)
 static JobInfo *job_query_single(Job *job, Error **errp)
 {
     JobInfo *info;
-    const char *errmsg = NULL;
 
     assert(!job_is_internal(job));
 
-    if (job->ret < 0) {
-        errmsg = strerror(-job->ret);
-    }
-
     info = g_new(JobInfo, 1);
     *info = (JobInfo) {
         .id                 = g_strdup(job->id),
@@ -151,8 +146,8 @@ static JobInfo *job_query_single(Job *job, Error **errp)
         .status             = job->status,
         .current_progress   = job->progress_current,
         .total_progress     = job->progress_total,
-        .has_error          = !!errmsg,
-        .error              = g_strdup(errmsg),
+        .has_error          = !!job->error,
+        .error              = g_strdup(job->error),
     };
 
     return info;
diff --git a/job.c b/job.c
index f026661b0f..fc39eaaa5e 100644
--- a/job.c
+++ b/job.c
@@ -369,6 +369,7 @@ void job_unref(Job *job)
 
         QLIST_REMOVE(job, job_list);
 
+        g_free(job->error);
         g_free(job->id);
         g_free(job);
     }
@@ -661,6 +662,9 @@ static void job_update_rc(Job *job)
     }
     if (job->ret) {
         job_state_transition(job, JOB_STATUS_ABORTING);
+        if (!job->error) {
+            job->error = g_strdup(strerror(-job->ret));
+        }
     }
 }
 
@@ -855,10 +859,17 @@ static void job_completed_txn_success(Job *job)
     }
 }
 
-void job_completed(Job *job, int ret)
+void job_completed(Job *job, int ret, Error *error)
 {
     assert(job && job->txn && !job_is_completed(job));
+
     job->ret = ret;
+    if (error) {
+        assert(job->ret < 0);
+        job->error = g_strdup(error_get_pretty(error));
+        error_free(error);
+    }
+
     job_update_rc(job);
     trace_job_completed(job, ret, job->ret);
     if (job->ret) {
@@ -876,7 +887,7 @@ void job_cancel(Job *job, bool force)
     }
     job_cancel_async(job, force);
     if (!job_started(job)) {
-        job_completed(job, -ECANCELED);
+        job_completed(job, -ECANCELED, NULL);
     } else if (job->deferred_to_main_loop) {
         job_completed_txn_abort(job);
     } else {
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 04/14] block/create: Make x-blockdev-create a job
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (2 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 03/14] job: Add error message for failing jobs Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 11:38   ` Max Reitz
  2018-05-29 15:27   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 05/14] qemu-iotests: Add VM.get_qmp_events_filtered() Kevin Wolf
                   ` (11 subsequent siblings)
  15 siblings, 2 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This changes the x-blockdev-create QMP command so that it doesn't block
the monitor and the main loop any more, but starts a background job that
performs the image creation.

The basic job as implemented here is all that is necessary to make image
creation asynchronous and to provide a QMP interface that can be marked
stable, but it still lacks a few features that jobs usually provide: The
job will ignore pause commands and it doesn't publish progress yet (so
both current-progress and total-progress stay at 0). These features can
be added later without breaking compatibility.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json     | 14 +++++++----
 qapi/job.json            |  4 +++-
 block/create.c           | 61 ++++++++++++++++++++++++++++++++----------------
 tests/qemu-iotests/group | 14 ++++++-----
 4 files changed, 61 insertions(+), 32 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 7dfa77a05c..1ed3a82373 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -4013,14 +4013,18 @@
 ##
 # @x-blockdev-create:
 #
-# Create an image format on a given node.
-# TODO Replace with something asynchronous (block job?)
+# Starts a job to create an image format on a given node. The job is
+# automatically finalized, but a manual job-dismiss is required.
 #
-# Since: 2.12
+# @job-id:          Identifier for the newly created job.
+#
+# @options:         Options for the image creation.
+#
+# Since: 3.0
 ##
 { 'command': 'x-blockdev-create',
-  'data': 'BlockdevCreateOptions',
-  'boxed': true }
+  'data': { 'job-id': 'str',
+            'options': 'BlockdevCreateOptions' } }
 
 ##
 # @blockdev-open-tray:
diff --git a/qapi/job.json b/qapi/job.json
index 970124de76..69c1970a58 100644
--- a/qapi/job.json
+++ b/qapi/job.json
@@ -17,10 +17,12 @@
 #
 # @backup: drive backup job type, see "drive-backup"
 #
+# @create: image creation job type, see "x-blockdev-create" (since 3.0)
+#
 # Since: 1.7
 ##
 { 'enum': 'JobType',
-  'data': ['commit', 'stream', 'mirror', 'backup'] }
+  'data': ['commit', 'stream', 'mirror', 'backup', 'create'] }
 
 ##
 # @JobStatus:
diff --git a/block/create.c b/block/create.c
index 8bd8a03719..87fdab3b72 100644
--- a/block/create.c
+++ b/block/create.c
@@ -24,28 +24,49 @@
 
 #include "qemu/osdep.h"
 #include "block/block_int.h"
+#include "qemu/job.h"
 #include "qapi/qapi-commands-block-core.h"
+#include "qapi/qapi-visit-block-core.h"
+#include "qapi/clone-visitor.h"
 #include "qapi/error.h"
 
-typedef struct BlockdevCreateCo {
+typedef struct BlockdevCreateJob {
+    Job common;
     BlockDriver *drv;
     BlockdevCreateOptions *opts;
     int ret;
-    Error **errp;
-} BlockdevCreateCo;
+    Error *err;
+} BlockdevCreateJob;
 
-static void coroutine_fn bdrv_co_create_co_entry(void *opaque)
+static void blockdev_create_complete(Job *job, void *opaque)
 {
-    BlockdevCreateCo *cco = opaque;
-    cco->ret = cco->drv->bdrv_co_create(cco->opts, cco->errp);
+    BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common);
+
+    job_completed(job, s->ret, s->err);
 }
 
-void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)
+static void coroutine_fn blockdev_create_run(void *opaque)
 {
+    BlockdevCreateJob *s = opaque;
+
+    s->ret = s->drv->bdrv_co_create(s->opts, &s->err);
+
+    qapi_free_BlockdevCreateOptions(s->opts);
+    job_defer_to_main_loop(&s->common, blockdev_create_complete, NULL);
+}
+
+static const JobDriver blockdev_create_job_driver = {
+    .instance_size = sizeof(BlockdevCreateJob),
+    .job_type      = JOB_TYPE_CREATE,
+    .start         = blockdev_create_run,
+};
+
+void qmp_x_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
+                           Error **errp)
+{
+    BlockdevCreateJob *s;
     const char *fmt = BlockdevDriver_str(options->driver);
     BlockDriver *drv = bdrv_find_format(fmt);
-    Coroutine *co;
-    BlockdevCreateCo cco;
 
     /* If the driver is in the schema, we know that it exists. But it may not
      * be whitelisted. */
@@ -61,16 +82,16 @@ void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)
         return;
     }
 
-    cco = (BlockdevCreateCo) {
-        .drv = drv,
-        .opts = options,
-        .ret = -EINPROGRESS,
-        .errp = errp,
-    };
-
-    co = qemu_coroutine_create(bdrv_co_create_co_entry, &cco);
-    qemu_coroutine_enter(co);
-    while (cco.ret == -EINPROGRESS) {
-        aio_poll(qemu_get_aio_context(), true);
+    /* Create the block job */
+    s = job_create(job_id, &blockdev_create_job_driver, NULL,
+                   qemu_get_aio_context(), JOB_DEFAULT | JOB_MANUAL_DISMISS,
+                   NULL, NULL, errp);
+    if (!s) {
+        return;
     }
+
+    s->drv = drv,
+    s->opts = QAPI_CLONE(BlockdevCreateOptions, options),
+
+    job_start(&s->common);
 }
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 93f93d71ba..22b0082db3 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -204,14 +204,16 @@
 203 rw auto migration
 204 rw auto quick
 205 rw auto quick
-206 rw auto
-207 rw auto
+# TODO The following commented out tests need to be reworked to work
+# with the x-blockdev-create job
+#206 rw auto
+#207 rw auto
 208 rw auto quick
 209 rw auto quick
-210 rw auto
-211 rw auto quick
-212 rw auto quick
-213 rw auto quick
+#210 rw auto
+#211 rw auto quick
+#212 rw auto quick
+#213 rw auto quick
 214 rw auto
 215 rw auto quick
 216 rw auto quick
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 05/14] qemu-iotests: Add VM.get_qmp_events_filtered()
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (3 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 04/14] block/create: Make x-blockdev-create a job Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 11:41   ` Max Reitz
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log() Kevin Wolf
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This adds a helper function that returns a list of QMP events that are
already filtered through filter_qmp_event().

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/iotests.py | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 28159d837a..17aa7c88dc 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -383,6 +383,11 @@ class VM(qtest.QEMUQtestMachine):
             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
 
 
 index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log()
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (4 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 05/14] qemu-iotests: Add VM.get_qmp_events_filtered() Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 11:48   ` Max Reitz
  2018-05-29 18:31   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 07/14] qemu-iotests: Add iotests.img_info_log() Kevin Wolf
                   ` (9 subsequent siblings)
  15 siblings, 2 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This adds a helper function that logs both the QMP request and the
received response before returning it.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/iotests.py | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 17aa7c88dc..319d898172 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -206,6 +206,10 @@ 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/')
+
 def log(msg, filters=[]):
     for flt in filters:
         msg = flt(msg)
@@ -389,6 +393,13 @@ class VM(qtest.QEMUQtestMachine):
             result.append(filter_qmp_event(ev))
         return result
 
+    def qmp_log(self, cmd, **kwargs):
+        logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
+        log(filter_testfiles(logmsg))
+        result = self.qmp(cmd, **kwargs)
+        log(result)
+        return result
+
 
 index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
 
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 07/14] qemu-iotests: Add iotests.img_info_log()
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (5 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log() Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 11:56   ` Max Reitz
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 08/14] qemu-iotests: Rewrite 206 for blockdev-create job Kevin Wolf
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This adds a filter function to postprocess 'qemu-img info' input
(similar to what _img_info does), and an img_info_log() function that
calls 'qemu-img info' and logs the filtered output.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/iotests.py | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 319d898172..20ce5a0cf0 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -109,6 +109,10 @@ 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):
+    output = qemu_img_pipe('info', '-f', imgfmt, filename)
+    log(filter_img_info(output, filename))
+
 def qemu_io(*args):
     '''Run qemu-io and return the stdout data'''
     args = qemu_io_args + list(args)
@@ -210,6 +214,18 @@ def filter_testfiles(msg):
     prefix = os.path.join(test_dir, "%s-" % (os.getpid()))
     return msg.replace(prefix, 'TEST_DIR/')
 
+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_DIR/t.IMGFMT') \
+                   .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)
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 08/14] qemu-iotests: Rewrite 206 for blockdev-create job
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (6 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 07/14] qemu-iotests: Add iotests.img_info_log() Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 12:27   ` Max Reitz
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 " Kevin Wolf
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This rewrites the test case 206 to work with the new x-blockdev-create
job rather than the old synchronous version of the command.

All of the test cases stay the same as before, but in order to be able
to implement proper job handling, the test case is rewritten in Python.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/206        | 705 +++++++++++++++++-------------------------
 tests/qemu-iotests/206.out    | 241 +++++++++------
 tests/qemu-iotests/group      |   2 +-
 tests/qemu-iotests/iotests.py |  15 +
 4 files changed, 448 insertions(+), 515 deletions(-)

diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
index 0a18b2b19a..9a305302d1 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,288 @@
 # 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('x-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()
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 1234  })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 18446744073709551104 })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 9223372036854775808 })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 9223372036854775296})
+    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()
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 67108864,
+                          'cluster-size': 1234 })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 67108864,
+                          'cluster-size': 128 })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 67108864,
+                          'cluster-size': 4194304 })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 67108864,
+                          'cluster-size': 0 })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 281474976710656,
+                          'cluster-size': 512 })
+    vm.shutdown()
+
+    #
+    # Invalid refcount width
+    #
+    iotests.log("=== Invalid refcount width ===")
+
+    vm.launch()
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 67108864,
+                          'refcount-bits': 128 })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 67108864,
+                          'refcount-bits': 0 })
+    blockdev_create(vm, { 'driver': imgfmt,
+                          'file': 'node0',
+                          'size': 67108864,
+                          'refcount-bits': 7 })
+    vm.shutdown()
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
index 042342ae9d..45367270e8 100644
--- a/tests/qemu-iotests/206.out
+++ b/tests/qemu-iotests/206.out
@@ -1,15 +1,16 @@
-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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}
+{u'return': {}}
+{'execute': 'x-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
 file format: IMGFMT
@@ -23,13 +24,15 @@ 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 file format: IMGFMT
@@ -43,13 +46,15 @@ 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 file format: IMGFMT
@@ -63,13 +68,15 @@ 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'backing-file': 'TEST_DIR/t.qcow2.base', 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 file format: IMGFMT
@@ -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': 'x-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/t.qcow2'}, 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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/group b/tests/qemu-iotests/group
index 22b0082db3..be157e7679 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -204,9 +204,9 @@
 203 rw auto migration
 204 rw auto quick
 205 rw auto quick
+206 rw auto
 # TODO The following commented out tests need to be reworked to work
 # with the x-blockdev-create job
-#206 rw auto
 #207 rw auto
 208 rw auto quick
 209 rw auto quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 20ce5a0cf0..f0f4ef32f0 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -416,6 +416,21 @@ class VM(qtest.QEMUQtestMachine):
         log(result)
         return result
 
+    def run_job(self, job):
+        while True:
+            for ev in self.get_qmp_events_filtered(wait=True):
+                if ev['event'] == 'JOB_STATUS_CHANGE':
+                    if ev['data']['status'] == 'aborting':
+                        result = self.qmp('query-jobs')
+                        for j in result['return']:
+                            log('Job failed: %s' % (j.get('error', None)))
+                    elif ev['data']['status'] == 'concluded':
+                        self.qmp_log('job-dismiss', id=job)
+                    elif ev['data']['status'] == 'null':
+                        return
+                else:
+                    iotests.log(ev)
+
 
 index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
 
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 for blockdev-create job
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (7 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 08/14] qemu-iotests: Rewrite 206 for blockdev-create job Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 12:44   ` Max Reitz
                     ` (2 more replies)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 10/14] qemu-iotests: Rewrite 210 " Kevin Wolf
                   ` (6 subsequent siblings)
  15 siblings, 3 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This rewrites the test case 207 to work with the new x-blockdev-create
job rather than the old synchronous version of the command.

Most of the test cases stay the same as before (the exception being some
improved 'size' options that allow distinguishing which command created
the image), but in order to be able to implement proper job handling,
the test case is rewritten in Python.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/207        | 435 +++++++++++++++++++-----------------------
 tests/qemu-iotests/207.out    |  89 +++++----
 tests/qemu-iotests/group      |   6 +-
 tests/qemu-iotests/iotests.py |  23 ++-
 4 files changed, 264 insertions(+), 289 deletions(-)

diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
index f5c77852d1..91c1f7e811 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,193 @@
 # 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
+
+iotests.verify_image_format(supported_fmts=['raw'])
+iotests.verify_protocol(supported=['ssh'])
+
+def blockdev_create(vm, options):
+    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
+
+    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..299650872c 100644
--- a/tests/qemu-iotests/207.out
+++ b/tests/qemu-iotests/207.out
@@ -1,62 +1,64 @@
-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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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"}}
 file format: IMGFMT
 virtual size: 4.0M (4194304 bytes)
 
+
 image: TEST_DIR/t.IMGFMT
 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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"}}
 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}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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_DIR/t.IMGFMT"}}
 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}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'f3386a5742ddc4a04244118e59a1f92b', '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_DIR/t.IMGFMT"}}
 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}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'c6142e54650531177fa3d88ac52501ae00ccff69', '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_DIR/t.IMGFMT"}}
 file format: IMGFMT
@@ -64,12 +66,15 @@ 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': 'x-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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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/group b/tests/qemu-iotests/group
index be157e7679..8a84bf057d 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -205,11 +205,11 @@
 204 rw auto quick
 205 rw auto quick
 206 rw auto
-# TODO The following commented out tests need to be reworked to work
-# with the x-blockdev-create job
-#207 rw auto
+207 rw auto
 208 rw auto quick
 209 rw auto quick
+# TODO The following commented out tests need to be reworked to work
+# with the x-blockdev-create job
 #210 rw auto
 #211 rw auto quick
 #212 rw auto quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index f0f4ef32f0..e945caa6bb 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -109,9 +109,11 @@ 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):
+def img_info_log(filename, filter_path=None):
     output = qemu_img_pipe('info', '-f', imgfmt, filename)
-    log(filter_img_info(output, filename))
+    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'''
@@ -301,6 +303,13 @@ def file_path(*names):
 
     return paths[0] if len(paths) == 1 else paths
 
+def remote_filename(path):
+    if imgproto == 'file':
+        return imgproto
+    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'''
@@ -595,6 +604,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)
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 10/14] qemu-iotests: Rewrite 210 for blockdev-create job
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (8 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 " Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 13:02   ` Max Reitz
  2018-05-29 18:23   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 11/14] qemu-iotests: Rewrite 211 " Kevin Wolf
                   ` (5 subsequent siblings)
  15 siblings, 2 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This rewrites the test case 210 to work with the new x-blockdev-create
job rather than the old synchronous version of the command.

All of the test cases stay the same as before, but in order to be able
to implement proper job handling, the test case is rewritten in Python.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/210        | 393 ++++++++++++++++++------------------------
 tests/qemu-iotests/210.out    | 189 ++++++++++++++------
 tests/qemu-iotests/group      |   2 +-
 tests/qemu-iotests/iotests.py |  12 +-
 4 files changed, 310 insertions(+), 286 deletions(-)

diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
index e607c0d296..ff4fddea56 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('x-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..116218ae4e 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}
+{u'return': {}}
+{'execute': 'x-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"}
 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-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/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"}
 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': 'x-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': 'x-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"}
 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': 'x-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': 'x-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': {}}
 
-=== Resize image with invalid sizes ===
+{'execute': 'x-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': {}}
 
-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}}
+=== Resize image with invalid sizes ===
 
+{'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_DIR/t.IMGFMT"}, "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/group b/tests/qemu-iotests/group
index 8a84bf057d..a1d04ce367 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -208,9 +208,9 @@
 207 rw auto
 208 rw auto quick
 209 rw auto quick
+210 rw auto
 # TODO The following commented out tests need to be reworked to work
 # with the x-blockdev-create job
-#210 rw auto
 #211 rw auto quick
 #212 rw auto quick
 #213 rw auto quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index e945caa6bb..6499a9e6fe 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -109,8 +109,16 @@ 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):
-    output = qemu_img_pipe('info', '-f', imgfmt, filename)
+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))
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 11/14] qemu-iotests: Rewrite 211 for blockdev-create job
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (9 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 10/14] qemu-iotests: Rewrite 210 " Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 13:12   ` Max Reitz
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 12/14] qemu-iotests: Rewrite 212 " Kevin Wolf
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This rewrites the test case 211 to work with the new x-blockdev-create
job rather than the old synchronous version of the command.

All of the test cases stay the same as before, but in order to be able
to implement proper job handling, the test case is rewritten in Python.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/211     | 384 ++++++++++++++++++---------------------------
 tests/qemu-iotests/211.out | 123 ++++++++-------
 tests/qemu-iotests/group   |   2 +-
 3 files changed, 227 insertions(+), 282 deletions(-)

diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
index 1edec26517..2fd89cfb32 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,157 @@
 # 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('x-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.filter_testfiles(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.filter_testfiles(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.filter_testfiles(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..31ef74db4c 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
+{u'return': {}}
+{'execute': 'x-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
 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 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': 'x-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': 'x-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
 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': 'x-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
 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': 'x-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': 'x-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': 'x-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/group b/tests/qemu-iotests/group
index a1d04ce367..4182bccccc 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -209,9 +209,9 @@
 208 rw auto quick
 209 rw auto quick
 210 rw auto
+211 rw auto quick
 # TODO The following commented out tests need to be reworked to work
 # with the x-blockdev-create job
-#211 rw auto quick
 #212 rw auto quick
 #213 rw auto quick
 214 rw auto
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 12/14] qemu-iotests: Rewrite 212 for blockdev-create job
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (10 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 11/14] qemu-iotests: Rewrite 211 " Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 13:21   ` Max Reitz
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 13/14] qemu-iotests: Rewrite 213 " Kevin Wolf
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This rewrites the test case 212 to work with the new x-blockdev-create
job rather than the old synchronous version of the command.

All of the test cases stay the same as before, but in order to be able
to implement proper job handling, the test case is rewritten in Python.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/212     | 483 +++++++++++++++++----------------------------
 tests/qemu-iotests/212.out | 181 ++++++++++-------
 tests/qemu-iotests/group   |   2 +-
 3 files changed, 290 insertions(+), 376 deletions(-)

diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
index e5a1ba77ce..5ac4947b82 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('x-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)
+
+    #
+    # 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..25c5c46027 100644
--- a/tests/qemu-iotests/212.out
+++ b/tests/qemu-iotests/212.out
@@ -1,15 +1,16 @@
-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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
+{u'return': {}}
+{'execute': 'x-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
 file format: IMGFMT
@@ -17,13 +18,15 @@ 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 file format: IMGFMT
@@ -31,13 +34,15 @@ 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 file format: IMGFMT
@@ -45,22 +50,18 @@ 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': 'x-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': 'x-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
 file format: IMGFMT
@@ -68,12 +69,10 @@ 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': 'x-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
 file format: IMGFMT
@@ -81,31 +80,77 @@ 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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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/group b/tests/qemu-iotests/group
index 4182bccccc..c843f0c177 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -210,9 +210,9 @@
 209 rw auto quick
 210 rw auto
 211 rw auto quick
+212 rw auto quick
 # TODO The following commented out tests need to be reworked to work
 # with the x-blockdev-create job
-#212 rw auto quick
 #213 rw auto quick
 214 rw auto
 215 rw auto quick
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 13/14] qemu-iotests: Rewrite 213 for blockdev-create job
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (11 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 12/14] qemu-iotests: Rewrite 212 " Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 13:27   ` Max Reitz
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 14/14] block/create: Mark blockdev-create stable Kevin Wolf
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

This rewrites the test case 213 to work with the new x-blockdev-create
job rather than the old synchronous version of the command.

All of the test cases stay the same as before, but in order to be able
to implement proper job handling, the test case is rewritten in Python.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/qemu-iotests/213     | 520 +++++++++++++++++----------------------------
 tests/qemu-iotests/213.out | 198 ++++++++++-------
 tests/qemu-iotests/group   |   4 +-
 3 files changed, 314 insertions(+), 408 deletions(-)

diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
index 3a00a0f6d6..fe4017edc7 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('x-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)
+
+    #
+    # 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..2b83e5df97 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
+{u'return': {}}
+{'execute': 'x-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
 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': True, 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': False, 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
 
 image: TEST_DIR/t.IMGFMT
 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': 'x-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': 'x-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
 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': 'x-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
 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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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': 'x-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/group b/tests/qemu-iotests/group
index c843f0c177..93f93d71ba 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -211,9 +211,7 @@
 210 rw auto
 211 rw auto quick
 212 rw auto quick
-# TODO The following commented out tests need to be reworked to work
-# with the x-blockdev-create job
-#213 rw auto quick
+213 rw auto quick
 214 rw auto
 215 rw auto quick
 216 rw auto quick
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* [Qemu-devel] [PATCH 14/14] block/create: Mark blockdev-create stable
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (12 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 13/14] qemu-iotests: Rewrite 213 " Kevin Wolf
@ 2018-05-25 16:33 ` Kevin Wolf
  2018-05-29 13:30   ` Max Reitz
  2018-05-29 18:25   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2018-05-25 16:52 ` [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API no-reply
  2018-05-25 18:13 ` Eric Blake
  15 siblings, 2 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-25 16:33 UTC (permalink / raw)
  To: qemu-block; +Cc: kwolf, mreitz, jsnow, eblake, pkrempa, qemu-devel

We're ready to declare the blockdev-create job stable. This renames the
corresponding QMP command from x-blockdev-create to blockdev-create.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 qapi/block-core.json       |  4 ++--
 qapi/job.json              |  2 +-
 block/create.c             |  4 ++--
 tests/qemu-iotests/206     |  2 +-
 tests/qemu-iotests/206.out | 54 +++++++++++++++++++++++-----------------------
 tests/qemu-iotests/207     |  2 +-
 tests/qemu-iotests/207.out | 18 ++++++++--------
 tests/qemu-iotests/210     |  2 +-
 tests/qemu-iotests/210.out | 18 ++++++++--------
 tests/qemu-iotests/211     |  2 +-
 tests/qemu-iotests/211.out | 24 ++++++++++-----------
 tests/qemu-iotests/212     |  2 +-
 tests/qemu-iotests/212.out | 42 ++++++++++++++++++------------------
 tests/qemu-iotests/213     |  2 +-
 tests/qemu-iotests/213.out | 44 ++++++++++++++++++-------------------
 15 files changed, 111 insertions(+), 111 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 1ed3a82373..015e5ac12b 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -4011,7 +4011,7 @@
   } }
 
 ##
-# @x-blockdev-create:
+# @blockdev-create:
 #
 # Starts a job to create an image format on a given node. The job is
 # automatically finalized, but a manual job-dismiss is required.
@@ -4022,7 +4022,7 @@
 #
 # Since: 3.0
 ##
-{ 'command': 'x-blockdev-create',
+{ 'command': 'blockdev-create',
   'data': { 'job-id': 'str',
             'options': 'BlockdevCreateOptions' } }
 
diff --git a/qapi/job.json b/qapi/job.json
index 69c1970a58..17d10037c4 100644
--- a/qapi/job.json
+++ b/qapi/job.json
@@ -17,7 +17,7 @@
 #
 # @backup: drive backup job type, see "drive-backup"
 #
-# @create: image creation job type, see "x-blockdev-create" (since 3.0)
+# @create: image creation job type, see "blockdev-create" (since 3.0)
 #
 # Since: 1.7
 ##
diff --git a/block/create.c b/block/create.c
index 87fdab3b72..21728acca0 100644
--- a/block/create.c
+++ b/block/create.c
@@ -61,8 +61,8 @@ static const JobDriver blockdev_create_job_driver = {
     .start         = blockdev_create_run,
 };
 
-void qmp_x_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
-                           Error **errp)
+void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
+                         Error **errp)
 {
     BlockdevCreateJob *s;
     const char *fmt = BlockdevDriver_str(options->driver);
diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
index 9a305302d1..334410d6a7 100755
--- a/tests/qemu-iotests/206
+++ b/tests/qemu-iotests/206
@@ -26,7 +26,7 @@ from iotests import imgfmt
 iotests.verify_image_format(supported_fmts=['qcow2'])
 
 def blockdev_create(vm, options):
-    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
+    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
 
     if 'return' in result:
         assert result['return'] == {}
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
index 45367270e8..8b403ea08f 100644
--- a/tests/qemu-iotests/206.out
+++ b/tests/qemu-iotests/206.out
@@ -1,13 +1,13 @@
 === Successful image creation (defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
 {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}
 {u'return': {}}
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -24,12 +24,12 @@ Format specific information:
 
 === Successful image creation (inline blockdev-add, explicit defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -46,12 +46,12 @@ Format specific information:
 
 === Successful image creation (v3 non-default options) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -68,12 +68,12 @@ Format specific information:
 
 === Successful image creation (v2 non-default options) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'backing-file': 'TEST_DIR/t.qcow2.base', 'size': 33554432}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'backing-file': 'TEST_DIR/t.qcow2.base', 'size': 33554432}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -90,7 +90,7 @@ Format specific information:
 
 === Successful image creation (encrypted) ===
 
-{'execute': 'x-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/t.qcow2'}, 'size': 33554432}}}
+{'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/t.qcow2'}, 'size': 33554432}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -144,111 +144,111 @@ Format specific information:
 
 === Invalid BlockdevRef ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': "this doesn't exist", 'size': 33554432}}}
+{'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 ===
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 1234}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 18446744073709551104L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775808L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775296}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'version': 'v1', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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'"}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'lazy-refcounts': True, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 8, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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 ===
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'full', 'driver': 'qcow2', 'backing-file': '/dev/null', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'backing-fmt': 'qcow2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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 ===
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4194304, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'qcow2', 'file': 'node0', 'size': 281474976710656}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 7, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{'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'}}
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
index 91c1f7e811..0d7680599f 100755
--- a/tests/qemu-iotests/207
+++ b/tests/qemu-iotests/207
@@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['raw'])
 iotests.verify_protocol(supported=['ssh'])
 
 def blockdev_create(vm, options):
-    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
+    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
 
     if 'return' in result:
         assert result['return'] == {}
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
index 299650872c..92a7fa1b01 100644
--- a/tests/qemu-iotests/207.out
+++ b/tests/qemu-iotests/207.out
@@ -1,6 +1,6 @@
 === Successful image creation (defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -16,7 +16,7 @@ virtual size: 4.0M (4194304 bytes)
 
 === Test host-key-check options ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': {}}
@@ -25,7 +25,7 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
 file format: IMGFMT
 virtual size: 8.0M (8388608 bytes)
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'mode': 'known_hosts'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': {}}
@@ -34,13 +34,13 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
 file format: IMGFMT
 virtual size: 4.0M (4194304 bytes)
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'wrong', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'f3386a5742ddc4a04244118e59a1f92b', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'f3386a5742ddc4a04244118e59a1f92b', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -49,13 +49,13 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
 file format: IMGFMT
 virtual size: 8.0M (8388608 bytes)
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'wrong', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'c6142e54650531177fa3d88ac52501ae00ccff69', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'c6142e54650531177fa3d88ac52501ae00ccff69', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -66,13 +66,13 @@ virtual size: 4.0M (4194304 bytes)
 
 === Invalid path and user ===
 
-{'execute': 'x-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}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'mode': 'none'}, 'user': 'invalid user', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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'}}
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
index ff4fddea56..d142841e2b 100755
--- a/tests/qemu-iotests/210
+++ b/tests/qemu-iotests/210
@@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['luks'])
 iotests.verify_protocol(supported=['file'])
 
 def blockdev_create(vm, options):
-    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
+    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
 
     if 'return' in result:
         assert result['return'] == {}
diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out
index 116218ae4e..ffdf8b4ce9 100644
--- a/tests/qemu-iotests/210.out
+++ b/tests/qemu-iotests/210.out
@@ -1,13 +1,13 @@
 === Successful image creation (defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
 {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}
 {u'return': {}}
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'imgfile', 'size': 134217728}}}
+{'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': {}}
@@ -54,12 +54,12 @@ Format specific information:
 
 === Successful image creation (with non-default options) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-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/t.luks'}, 'iter-time': 10, 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'driver': 'luks', 'size': 67108864}}}
+{'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/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': {}}
@@ -106,7 +106,7 @@ Format specific information:
 
 === Invalid BlockdevRef ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'luks', 'file': "this doesn't exist", 'size': 67108864}}}
+{'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'}}
@@ -114,7 +114,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
 
 === Zero size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'node0', 'size': 0}}}
+{'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': {}}
@@ -161,19 +161,19 @@ Format specific information:
 
 === Invalid sizes ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 18446744073709551104L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775808L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775296}}}
+{'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'}}
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
index 2fd89cfb32..05215776ce 100755
--- a/tests/qemu-iotests/211
+++ b/tests/qemu-iotests/211
@@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['vdi'])
 iotests.verify_protocol(supported=['file'])
 
 def blockdev_create(vm, options):
-    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
+    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
 
     if 'return' in result:
         assert result['return'] == {}
diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out
index 31ef74db4c..b43fb73f50 100644
--- a/tests/qemu-iotests/211.out
+++ b/tests/qemu-iotests/211.out
@@ -1,13 +1,13 @@
 === Successful image creation (defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
 {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
 {u'return': {}}
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -21,12 +21,12 @@ cluster_size: 1048576
 
 === Successful image creation (explicit defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -40,12 +40,12 @@ cluster_size: 1048576
 
 === Successful image creation (with non-default options) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -60,7 +60,7 @@ cluster_size: 1048576
 
 === Invalid BlockdevRef ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': "this doesn't exist", 'size': 33554432}}}
+{'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'}}
@@ -68,7 +68,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
 
 === Zero size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -80,7 +80,7 @@ cluster_size: 1048576
 
 === Maximum size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -92,19 +92,19 @@ cluster_size: 1048576
 
 === Invalid sizes ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 18446744073709551104L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 9223372036854775808L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203585}}}
+{'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'}}
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
index 5ac4947b82..d22dde12ad 100755
--- a/tests/qemu-iotests/212
+++ b/tests/qemu-iotests/212
@@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['parallels'])
 iotests.verify_protocol(supported=['file'])
 
 def blockdev_create(vm, options):
-    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
+    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
 
     if 'return' in result:
         assert result['return'] == {}
diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out
index 25c5c46027..4230ef929c 100644
--- a/tests/qemu-iotests/212.out
+++ b/tests/qemu-iotests/212.out
@@ -1,13 +1,13 @@
 === Successful image creation (defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
 {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
 {u'return': {}}
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -18,12 +18,12 @@ virtual size: 128M (134217728 bytes)
 
 === Successful image creation (explicit defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -34,12 +34,12 @@ virtual size: 64M (67108864 bytes)
 
 === Successful image creation (with non-default options) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -50,7 +50,7 @@ virtual size: 32M (33554432 bytes)
 
 === Invalid BlockdevRef ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': "this doesn't exist", 'size': 33554432}}}
+{'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'}}
@@ -58,7 +58,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
 
 === Zero size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -69,7 +69,7 @@ virtual size: 0 (0 bytes)
 
 === Maximum size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -80,31 +80,31 @@ virtual size: 4096T (4503599627369984 bytes)
 
 === Invalid sizes ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 1234}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 18446744073709551104L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775808L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775296}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627370497}}}
+{'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'}}
@@ -112,43 +112,43 @@ Job failed: Image size is too large for this cluster size
 
 === Invalid cluster size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4294967296, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 9223372036854775808L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 18446744073709551104L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'parallels', 'file': 'node0', 'size': 281474976710656}}}
+{'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'}}
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
index fe4017edc7..ccc27e4b2c 100755
--- a/tests/qemu-iotests/213
+++ b/tests/qemu-iotests/213
@@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['vhdx'])
 iotests.verify_protocol(supported=['file'])
 
 def blockdev_create(vm, options):
-    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
+    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
 
     if 'return' in result:
         assert result['return'] == {}
diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out
index 2b83e5df97..36a225f423 100644
--- a/tests/qemu-iotests/213.out
+++ b/tests/qemu-iotests/213.out
@@ -1,13 +1,13 @@
 === Successful image creation (defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
 {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
 {u'return': {}}
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -19,12 +19,12 @@ cluster_size: 8388608
 
 === Successful image creation (explicit defaults) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': True, 'size': 67108864}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': True, 'size': 67108864}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -36,12 +36,12 @@ cluster_size: 8388608
 
 === Successful image creation (with non-default options) ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': False, 'size': 33554432}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': False, 'size': 33554432}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -53,7 +53,7 @@ cluster_size: 268435456
 
 === Invalid BlockdevRef ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}}
+{'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'}}
@@ -61,7 +61,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
 
 === Zero size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -73,7 +73,7 @@ cluster_size: 8388608
 
 === Maximum size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}}
 {u'return': {}}
 {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
 {u'return': {}}
@@ -85,25 +85,25 @@ cluster_size: 67108864
 
 === Invalid sizes ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775808L}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775296}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177665}}}
+{'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'}}
@@ -111,31 +111,31 @@ Job failed: Image size too large; max of 64TB
 
 === Invalid block size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 128, 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 3145728, 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 536870912, 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 0, 'file': 'node0', 'size': 67108864}}}
+{'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'}}
@@ -143,25 +143,25 @@ Job failed: Block size must be a multiple of 1 MB
 
 === Invalid log size ===
 
-{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 4294967296, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
+{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 0, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
+{'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'}}
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (13 preceding siblings ...)
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 14/14] block/create: Mark blockdev-create stable Kevin Wolf
@ 2018-05-25 16:52 ` no-reply
  2018-05-25 18:13 ` Eric Blake
  15 siblings, 0 replies; 48+ messages in thread
From: no-reply @ 2018-05-25 16:52 UTC (permalink / raw)
  To: kwolf; +Cc: famz, qemu-block, pkrempa, jsnow, qemu-devel, mreitz

Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20180525163327.23097-1-kwolf@redhat.com
Subject: [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 t [tag update]            patchew/20180425183223.580566-1-eblake@redhat.com -> patchew/20180425183223.580566-1-eblake@redhat.com
 t [tag update]            patchew/20180501142222.19154-1-kbastian@mail.uni-paderborn.de -> patchew/20180501142222.19154-1-kbastian@mail.uni-paderborn.de
 * [new tag]               patchew/20180525163327.23097-1-kwolf@redhat.com -> patchew/20180525163327.23097-1-kwolf@redhat.com
Switched to a new branch 'test'
7c537677c5 block/create: Mark blockdev-create stable
2e27092a14 qemu-iotests: Rewrite 213 for blockdev-create job
d6251d43f0 qemu-iotests: Rewrite 212 for blockdev-create job
d6bc0f4894 qemu-iotests: Rewrite 211 for blockdev-create job
5b0814d1e4 qemu-iotests: Rewrite 210 for blockdev-create job
03bf59b254 qemu-iotests: Rewrite 207 for blockdev-create job
f602a6610b qemu-iotests: Rewrite 206 for blockdev-create job
a9d8a5c88e qemu-iotests: Add iotests.img_info_log()
eb9248b0ec qemu-iotests: Add VM.qmp_log()
7c9e5e8154 qemu-iotests: Add VM.get_qmp_events_filtered()
711b0d9ad8 block/create: Make x-blockdev-create a job
bc7cfcbd4b job: Add error message for failing jobs
3efdd6905e vhdx: Fix vhdx_co_create() return value
0a3f99ead0 vdi: Fix vdi_co_do_create() return value

=== OUTPUT BEGIN ===
Checking PATCH 1/14: vdi: Fix vdi_co_do_create() return value...
Checking PATCH 2/14: vhdx: Fix vhdx_co_create() return value...
Checking PATCH 3/14: job: Add error message for failing jobs...
Checking PATCH 4/14: block/create: Make x-blockdev-create a job...
Checking PATCH 5/14: qemu-iotests: Add VM.get_qmp_events_filtered()...
Checking PATCH 6/14: qemu-iotests: Add VM.qmp_log()...
Checking PATCH 7/14: qemu-iotests: Add iotests.img_info_log()...
ERROR: line over 90 characters
#40: FILE: tests/qemu-iotests/iotests.py:225:
+        line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)

total: 1 errors, 0 warnings, 28 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 8/14: qemu-iotests: Rewrite 206 for blockdev-create job...
Checking PATCH 9/14: qemu-iotests: Rewrite 207 for blockdev-create job...
Checking PATCH 10/14: qemu-iotests: Rewrite 210 for blockdev-create job...
Checking PATCH 11/14: qemu-iotests: Rewrite 211 for blockdev-create job...
Checking PATCH 12/14: qemu-iotests: Rewrite 212 for blockdev-create job...
Checking PATCH 13/14: qemu-iotests: Rewrite 213 for blockdev-create job...
Checking PATCH 14/14: block/create: Mark blockdev-create stable...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API
  2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
                   ` (14 preceding siblings ...)
  2018-05-25 16:52 ` [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API no-reply
@ 2018-05-25 18:13 ` Eric Blake
  2018-05-28  8:42   ` Kevin Wolf
  15 siblings, 1 reply; 48+ messages in thread
From: Eric Blake @ 2018-05-25 18:13 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: mreitz, jsnow, pkrempa, qemu-devel

On 05/25/2018 11:33 AM, Kevin Wolf wrote:
> This changes the x-blockdev-create QMP command so that it doesn't block
> the monitor and the main loop any more, but starts a background job that
> performs the image creation.
> 
> The basic job as implemented here is all that is necessary to make image
> creation asynchronous and to provide a QMP interface that can be marked
> stable, but it still lacks a few features that jobs usually provide: The
> job will ignore pause commands and it doesn't publish progress yet (so
> both current-progress and total-progress stay at 0). These features can
> be added later without breaking compatibility.

Can we at least have total-progress start at 1, and current-progress 
move from 0 to 1 at completion?  Seeing a 0/1 => 1/1 transition is 
better than a divide-by-zero 0/0 ratio throughout the entire job; and 
libvirt doesn't want to add any more special-casing of 0/0 than it 
already has (where it wants to treat that as "job not yet started" 
rather than the more usual sense that if total==current the job is 
hopefully complete).

> 
> At the end of the series, the interface is declared stable and the x-
> prefix is removed.
> 
> Kevin Wolf (14):
>    vdi: Fix vdi_co_do_create() return value
>    vhdx: Fix vhdx_co_create() return value
>    job: Add error message for failing jobs
>    block/create: Make x-blockdev-create a job
>    qemu-iotests: Add VM.get_qmp_events_filtered()
>    qemu-iotests: Add VM.qmp_log()
>    qemu-iotests: Add iotests.img_info_log()
>    qemu-iotests: Rewrite 206 for blockdev-create job
>    qemu-iotests: Rewrite 207 for blockdev-create job
>    qemu-iotests: Rewrite 210 for blockdev-create job
>    qemu-iotests: Rewrite 211 for blockdev-create job
>    qemu-iotests: Rewrite 212 for blockdev-create job
>    qemu-iotests: Rewrite 213 for blockdev-create job
>    block/create: Mark blockdev-create stable

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API
  2018-05-25 18:13 ` Eric Blake
@ 2018-05-28  8:42   ` Kevin Wolf
  0 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-28  8:42 UTC (permalink / raw)
  To: Eric Blake; +Cc: qemu-block, mreitz, jsnow, pkrempa, qemu-devel

Am 25.05.2018 um 20:13 hat Eric Blake geschrieben:
> On 05/25/2018 11:33 AM, Kevin Wolf wrote:
> > This changes the x-blockdev-create QMP command so that it doesn't block
> > the monitor and the main loop any more, but starts a background job that
> > performs the image creation.
> > 
> > The basic job as implemented here is all that is necessary to make image
> > creation asynchronous and to provide a QMP interface that can be marked
> > stable, but it still lacks a few features that jobs usually provide: The
> > job will ignore pause commands and it doesn't publish progress yet (so
> > both current-progress and total-progress stay at 0). These features can
> > be added later without breaking compatibility.
> 
> Can we at least have total-progress start at 1, and current-progress move
> from 0 to 1 at completion?  Seeing a 0/1 => 1/1 transition is better than a
> divide-by-zero 0/0 ratio throughout the entire job; and libvirt doesn't want
> to add any more special-casing of 0/0 than it already has (where it wants to
> treat that as "job not yet started" rather than the more usual sense that if
> total==current the job is hopefully complete).

Sure, I can do that.

Kevin

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value Kevin Wolf
@ 2018-05-29 10:38   ` Max Reitz
  2018-05-29 14:45   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 10:38 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 321 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> .bdrv_co_create() is supposed to return 0 on success, but vdi could
> return a positive value instead. Fix this.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  block/vdi.c | 1 +
>  1 file changed, 1 insertion(+)

Reviewed-by: Max Reitz <mreitz@redhat.com>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 02/14] vhdx: Fix vhdx_co_create() return value
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 02/14] vhdx: Fix vhdx_co_create() " Kevin Wolf
@ 2018-05-29 10:40   ` Max Reitz
  2018-05-29 14:44   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 10:40 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 339 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> .bdrv_co_create() is supposed to return 0 on success, but vhdx could
> return a positive value instead. Fix this.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  block/vhdx.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Max Reitz <mreitz@redhat.com>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 03/14] job: Add error message for failing jobs
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 03/14] job: Add error message for failing jobs Kevin Wolf
@ 2018-05-29 11:01   ` Max Reitz
  2018-05-29 14:43   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 11:01 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 3020 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> So far we relied on job->ret and strerror() to produce an error message
> for failed jobs. Not surprisingly, this tends to result in completely
> useless messages.
> 
> This adds a Job.error field that can contain an error string for a
> failing job, and a parameter to job_completed() that sets the field. As
> a default, if NULL is passed, we continue to use strerror(job->ret).
> 
> All existing callers are changed to pass NULL. They can be improved in
> separate patches.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  include/qemu/job.h |  7 ++++++-
>  block/backup.c     |  2 +-
>  block/commit.c     |  2 +-
>  block/mirror.c     |  2 +-
>  block/stream.c     |  2 +-
>  job-qmp.c          |  9 ++-------
>  job.c              | 15 +++++++++++++--
>  7 files changed, 25 insertions(+), 14 deletions(-)

There are some tests that call job_completed().  Those should be updated
as well.

> diff --git a/include/qemu/job.h b/include/qemu/job.h
> index 8c8badf75e..b2e1dd00b9 100644
> --- a/include/qemu/job.h
> +++ b/include/qemu/job.h
> @@ -124,6 +124,9 @@ typedef struct Job {
>      /** Estimated progress_current value at the completion of the job */
>      int64_t progress_total;
>  
> +    /** Error string for a failed job (NULL if job->ret == 0) */
> +    char *error;
> +

I think we should bind this directly to job->ret, i.e. this is NULL if
and only if job->ret == 0.  (Just because more constraints tend to make
things nicer.  And also because if you don't, then qmp_job_dismiss()
cannot assume that job->error is set on error, which would be a change
in behavior.)

>      /** ret code passed to job_completed. */
>      int ret;
> 
[...]

> diff --git a/job.c b/job.c
> index f026661b0f..fc39eaaa5e 100644
> --- a/job.c
> +++ b/job.c

job_prepare() (called by job_do_finalize() through job_txn_apply()) may
set job->ret.  If it does set it to a negative value, job_do_finalize()
will call job_completed_txn_abort(), which will eventually invoke
job_finalize_single(), which then runs job_update_rc() on the job.  This
is a bit too much code between setting job->ret and job->error for my
taste, I'd rather set job->error much sooner (e.g. by calling
job_update_rc() directly in job_prepare(), which I don't think would
change anything).

But if you think that this is just fine, then OK, because I don't think
the user can do QMP queries in between (it would still break the iff
relationship between job->ret and job->error, which I find desirable).

[...]

> @@ -661,6 +662,9 @@ static void job_update_rc(Job *job)
>      }
>      if (job->ret) {
>          job_state_transition(job, JOB_STATUS_ABORTING);
> +        if (!job->error) {
> +            job->error = g_strdup(strerror(-job->ret));
> +        }

If we do use an iff relationship between job->ret and job->error, this
should probably be inserted before job_state_transition().

Max

>      }
>  }


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 04/14] block/create: Make x-blockdev-create a job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 04/14] block/create: Make x-blockdev-create a job Kevin Wolf
@ 2018-05-29 11:38   ` Max Reitz
  2018-05-29 15:27   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 11:38 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 5007 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This changes the x-blockdev-create QMP command so that it doesn't block
> the monitor and the main loop any more, but starts a background job that
> performs the image creation.
> 
> The basic job as implemented here is all that is necessary to make image
> creation asynchronous and to provide a QMP interface that can be marked
> stable, but it still lacks a few features that jobs usually provide: The
> job will ignore pause commands and it doesn't publish progress yet (so
> both current-progress and total-progress stay at 0). These features can
> be added later without breaking compatibility.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  qapi/block-core.json     | 14 +++++++----
>  qapi/job.json            |  4 +++-
>  block/create.c           | 61 ++++++++++++++++++++++++++++++++----------------
>  tests/qemu-iotests/group | 14 ++++++-----
>  4 files changed, 61 insertions(+), 32 deletions(-)

[...]

> diff --git a/block/create.c b/block/create.c
> index 8bd8a03719..87fdab3b72 100644
> --- a/block/create.c
> +++ b/block/create.c
> @@ -24,28 +24,49 @@
>  
>  #include "qemu/osdep.h"
>  #include "block/block_int.h"
> +#include "qemu/job.h"
>  #include "qapi/qapi-commands-block-core.h"
> +#include "qapi/qapi-visit-block-core.h"
> +#include "qapi/clone-visitor.h"
>  #include "qapi/error.h"
>  
> -typedef struct BlockdevCreateCo {
> +typedef struct BlockdevCreateJob {
> +    Job common;
>      BlockDriver *drv;
>      BlockdevCreateOptions *opts;
>      int ret;
> -    Error **errp;
> -} BlockdevCreateCo;
> +    Error *err;
> +} BlockdevCreateJob;
>  
> -static void coroutine_fn bdrv_co_create_co_entry(void *opaque)
> +static void blockdev_create_complete(Job *job, void *opaque)
>  {
> -    BlockdevCreateCo *cco = opaque;
> -    cco->ret = cco->drv->bdrv_co_create(cco->opts, cco->errp);
> +    BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common);
> +
> +    job_completed(job, s->ret, s->err);
>  }
>  
> -void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)
> +static void coroutine_fn blockdev_create_run(void *opaque)
>  {
> +    BlockdevCreateJob *s = opaque;
> +
> +    s->ret = s->drv->bdrv_co_create(s->opts, &s->err);
> +
> +    qapi_free_BlockdevCreateOptions(s->opts);
> +    job_defer_to_main_loop(&s->common, blockdev_create_complete, NULL);

Better be safe than sorry, but probably not strictly necessary
considering the job is always run in the main loop anyway (more on that
below, though).

> +}
> +
> +static const JobDriver blockdev_create_job_driver = {
> +    .instance_size = sizeof(BlockdevCreateJob),
> +    .job_type      = JOB_TYPE_CREATE,
> +    .start         = blockdev_create_run,
> +};
> +
> +void qmp_x_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
> +                           Error **errp)
> +{
> +    BlockdevCreateJob *s;
>      const char *fmt = BlockdevDriver_str(options->driver);
>      BlockDriver *drv = bdrv_find_format(fmt);
> -    Coroutine *co;
> -    BlockdevCreateCo cco;
>  
>      /* If the driver is in the schema, we know that it exists. But it may not
>       * be whitelisted. */
> @@ -61,16 +82,16 @@ void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)

Minor note: The comment above this if () block reads:

    /* Call callback if it exists */

Which is now no longer really what is happening.  It just checks whether
the block driver supports blockdev-create.

>          return;
>      }
>  
> -    cco = (BlockdevCreateCo) {
> -        .drv = drv,
> -        .opts = options,
> -        .ret = -EINPROGRESS,
> -        .errp = errp,
> -    };
> -
> -    co = qemu_coroutine_create(bdrv_co_create_co_entry, &cco);
> -    qemu_coroutine_enter(co);
> -    while (cco.ret == -EINPROGRESS) {
> -        aio_poll(qemu_get_aio_context(), true);
> +    /* Create the block job */
> +    s = job_create(job_id, &blockdev_create_job_driver, NULL,
> +                   qemu_get_aio_context(), JOB_DEFAULT | JOB_MANUAL_DISMISS,

Hmmm...  The old code already used the main AIO context, but is that
correct?  When you create a qcow2 node on top of a file node, shouldn't
you use the AIO context of the file node?

I see that figuring out the correct context generically may be difficult
to impossible, so OK, maybe we should just run image creation in the
main context for now.  But then, qcow2 (and other formats) should at
least take a lock on their file's context, which they don't seem to do.

So I suppose I can give a

Reviewed-by: Max Reitz <mreitz@redhat.com>

for this patch, but I think some block drivers need some locking.

Max
	
> +                   NULL, NULL, errp);
> +    if (!s) {
> +        return;
>      }
> +
> +    s->drv = drv,
> +    s->opts = QAPI_CLONE(BlockdevCreateOptions, options),
> +
> +    job_start(&s->common);
>  }


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 05/14] qemu-iotests: Add VM.get_qmp_events_filtered()
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 05/14] qemu-iotests: Add VM.get_qmp_events_filtered() Kevin Wolf
@ 2018-05-29 11:41   ` Max Reitz
  0 siblings, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 11:41 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 349 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This adds a helper function that returns a list of QMP events that are
> already filtered through filter_qmp_event().
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/iotests.py | 5 +++++
>  1 file changed, 5 insertions(+)

Reviewed-by: Max Reitz <mreitz@redhat.com>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log()
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log() Kevin Wolf
@ 2018-05-29 11:48   ` Max Reitz
  2018-05-29 12:12     ` Kevin Wolf
  2018-05-29 18:31   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  1 sibling, 1 reply; 48+ messages in thread
From: Max Reitz @ 2018-05-29 11:48 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1558 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This adds a helper function that logs both the QMP request and the
> received response before returning it.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/iotests.py | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index 17aa7c88dc..319d898172 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -206,6 +206,10 @@ 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/')

I'd prefer 'TEST_DIR/PID-' (just because).

But if you really like just 'TEST_DIR/'...  Then OK.

> +
>  def log(msg, filters=[]):
>      for flt in filters:
>          msg = flt(msg)
> @@ -389,6 +393,13 @@ class VM(qtest.QEMUQtestMachine):
>              result.append(filter_qmp_event(ev))
>          return result
>  
> +    def qmp_log(self, cmd, **kwargs):
> +        logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
> +        log(filter_testfiles(logmsg))
> +        result = self.qmp(cmd, **kwargs)
> +        log(result)

I think we should apply the testfiles filter here, too (error messages
may contain file names, after all).

Max

> +        return result
> +
>  
>  index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
>  
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 07/14] qemu-iotests: Add iotests.img_info_log()
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 07/14] qemu-iotests: Add iotests.img_info_log() Kevin Wolf
@ 2018-05-29 11:56   ` Max Reitz
  0 siblings, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 11:56 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1972 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This adds a filter function to postprocess 'qemu-img info' input
> (similar to what _img_info does), and an img_info_log() function that
> calls 'qemu-img info' and logs the filtered output.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/iotests.py | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index 319d898172..20ce5a0cf0 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -109,6 +109,10 @@ 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):
> +    output = qemu_img_pipe('info', '-f', imgfmt, filename)
> +    log(filter_img_info(output, filename))
> +
>  def qemu_io(*args):
>      '''Run qemu-io and return the stdout data'''
>      args = qemu_io_args + list(args)
> @@ -210,6 +214,18 @@ def filter_testfiles(msg):
>      prefix = os.path.join(test_dir, "%s-" % (os.getpid()))
>      return msg.replace(prefix, 'TEST_DIR/')
>  
> +def filter_img_info(output, filename):
> +    lines = []
> +    for line in output.split('\n'):
> +        if 'disk size' in line or 'actual size' in line:

Wouldn't that be 'actual-size' (because I presume this is for JSON output)?

> +            continue
> +        line = line.replace(filename, 'TEST_DIR/t.IMGFMT') \

Why not just 'TEST_IMG'?

Max

> +                   .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)
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log()
  2018-05-29 11:48   ` Max Reitz
@ 2018-05-29 12:12     ` Kevin Wolf
  2018-05-29 12:15       ` Max Reitz
  0 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2018-05-29 12:12 UTC (permalink / raw)
  To: Max Reitz; +Cc: qemu-block, jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2020 bytes --]

Am 29.05.2018 um 13:48 hat Max Reitz geschrieben:
> On 2018-05-25 18:33, Kevin Wolf wrote:
> > This adds a helper function that logs both the QMP request and the
> > received response before returning it.
> > 
> > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > ---
> >  tests/qemu-iotests/iotests.py | 11 +++++++++++
> >  1 file changed, 11 insertions(+)
> > 
> > diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> > index 17aa7c88dc..319d898172 100644
> > --- a/tests/qemu-iotests/iotests.py
> > +++ b/tests/qemu-iotests/iotests.py
> > @@ -206,6 +206,10 @@ 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/')
> 
> I'd prefer 'TEST_DIR/PID-' (just because).
> 
> But if you really like just 'TEST_DIR/'...  Then OK.

I preferred that because it leaves the output unchanged from the old
bash tests, which made reviewing the results easier. Maybe that's a too
temporary advantage to be of any use in the future, though, so we could
change it afterwards...

> > +
> >  def log(msg, filters=[]):
> >      for flt in filters:
> >          msg = flt(msg)
> > @@ -389,6 +393,13 @@ class VM(qtest.QEMUQtestMachine):
> >              result.append(filter_qmp_event(ev))
> >          return result
> >  
> > +    def qmp_log(self, cmd, **kwargs):
> > +        logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
> > +        log(filter_testfiles(logmsg))
> > +        result = self.qmp(cmd, **kwargs)
> > +        log(result)
> 
> I think we should apply the testfiles filter here, too (error messages
> may contain file names, after all).

Didn't happen in the test outputs of this series, and filter_testfiles()
processes strings whereas result is a dict, so it would be more
complicated than just adding a function call.

Kevin

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log()
  2018-05-29 12:12     ` Kevin Wolf
@ 2018-05-29 12:15       ` Max Reitz
  2018-05-29 12:39         ` Kevin Wolf
  0 siblings, 1 reply; 48+ messages in thread
From: Max Reitz @ 2018-05-29 12:15 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2381 bytes --]

On 2018-05-29 14:12, Kevin Wolf wrote:
> Am 29.05.2018 um 13:48 hat Max Reitz geschrieben:
>> On 2018-05-25 18:33, Kevin Wolf wrote:
>>> This adds a helper function that logs both the QMP request and the
>>> received response before returning it.
>>>
>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
>>> ---
>>>  tests/qemu-iotests/iotests.py | 11 +++++++++++
>>>  1 file changed, 11 insertions(+)
>>>
>>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
>>> index 17aa7c88dc..319d898172 100644
>>> --- a/tests/qemu-iotests/iotests.py
>>> +++ b/tests/qemu-iotests/iotests.py
>>> @@ -206,6 +206,10 @@ 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/')
>>
>> I'd prefer 'TEST_DIR/PID-' (just because).
>>
>> But if you really like just 'TEST_DIR/'...  Then OK.
> 
> I preferred that because it leaves the output unchanged from the old
> bash tests, which made reviewing the results easier. Maybe that's a too
> temporary advantage to be of any use in the future, though, so we could
> change it afterwards...

It doesn't really make reviewing the patches easier, though, because the
hardest part of course is the change of the test itself and not the
change of the result. :-)

(And some file name changes really are on the easy side.)

>>> +
>>>  def log(msg, filters=[]):
>>>      for flt in filters:
>>>          msg = flt(msg)
>>> @@ -389,6 +393,13 @@ class VM(qtest.QEMUQtestMachine):
>>>              result.append(filter_qmp_event(ev))
>>>          return result
>>>  
>>> +    def qmp_log(self, cmd, **kwargs):
>>> +        logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
>>> +        log(filter_testfiles(logmsg))
>>> +        result = self.qmp(cmd, **kwargs)
>>> +        log(result)
>>
>> I think we should apply the testfiles filter here, too (error messages
>> may contain file names, after all).
> 
> Didn't happen in the test outputs of this series, and filter_testfiles()
> processes strings whereas result is a dict, so it would be more
> complicated than just adding a function call.

You mean it would be "log(filter_testfiles('%s' % result)))"?

Max


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 08/14] qemu-iotests: Rewrite 206 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 08/14] qemu-iotests: Rewrite 206 for blockdev-create job Kevin Wolf
@ 2018-05-29 12:27   ` Max Reitz
  2018-05-29 18:49     ` Kevin Wolf
  0 siblings, 1 reply; 48+ messages in thread
From: Max Reitz @ 2018-05-29 12:27 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 6317 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This rewrites the test case 206 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> All of the test cases stay the same as before, but in order to be able
> to implement proper job handling, the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/206        | 705 +++++++++++++++++-------------------------
>  tests/qemu-iotests/206.out    | 241 +++++++++------
>  tests/qemu-iotests/group      |   2 +-
>  tests/qemu-iotests/iotests.py |  15 +
>  4 files changed, 448 insertions(+), 515 deletions(-)
> 
> diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
> index 0a18b2b19a..9a305302d1 100755
> --- a/tests/qemu-iotests/206
> +++ b/tests/qemu-iotests/206

[...]

> +import iotests
> +from iotests import imgfmt
> +
> +iotests.verify_image_format(supported_fmts=['qcow2'])
> +
> +def blockdev_create(vm, options):
> +    result = vm.qmp_log('x-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"')

I don't know how subprocess.Popen() works, but are you sure you aren't
encrypting with '"foo"' now?  (i.e. literally that key, including quotes)

> +
> +    #
> +    # Successful image creation (defaults)
> +    #
> +    iotests.log("=== Successful image creation (defaults) ===")

OK, the comment makes sense for visual separation.  But so would leaving
three empty lines.  *cough*

> +    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 (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,

Change from the bash version: backing_path does not exist here.  Not
sure if that was intentional.

> +                          'backing-fmt': 'qcow2',
> +                          'version': 'v2',
> +                          'cluster-size': 512 })
> +    vm.shutdown()
> +
> +    iotests.img_info_log(disk_path)

[...]

> +    #
> +    # 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()
> +    blockdev_create(vm, { 'driver': imgfmt,
> +                          'file': 'node0',
> +                          'size': 1234  })
> +    blockdev_create(vm, { 'driver': imgfmt,
> +                          'file': 'node0',
> +                          'size': 18446744073709551104 })
> +    blockdev_create(vm, { 'driver': imgfmt,
> +                          'file': 'node0',
> +                          'size': 9223372036854775808 })
> +    blockdev_create(vm, { 'driver': imgfmt,
> +                          'file': 'node0',
> +                          'size': 9223372036854775296})

Missing space before the closing fancy bracket, critical!

[...]

> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index 20ce5a0cf0..f0f4ef32f0 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -416,6 +416,21 @@ class VM(qtest.QEMUQtestMachine):
>          log(result)
>          return result
>  
> +    def run_job(self, job):

Is there any reason this function did not get its own patch?

Also, this is a function specifically for jobs that need a manual
dismiss but have auto-finalize.  That should be noted somewhere (ideally
in the function's name, but spontaneously I don't know how).

> +        while True:
> +            for ev in self.get_qmp_events_filtered(wait=True):
> +                if ev['event'] == 'JOB_STATUS_CHANGE':
> +                    if ev['data']['status'] == 'aborting':
> +                        result = self.qmp('query-jobs')
> +                        for j in result['return']:
> +                            log('Job failed: %s' % (j.get('error', None)))

I can understand that you didn't want to use just result['return'][0],
but if you do iterate, you should probably emit the job ID as well.

Max

> +                    elif ev['data']['status'] == 'concluded':
> +                        self.qmp_log('job-dismiss', id=job)
> +                    elif ev['data']['status'] == 'null':
> +                        return
> +                else:
> +                    iotests.log(ev)
> +
>  
>  index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log()
  2018-05-29 12:15       ` Max Reitz
@ 2018-05-29 12:39         ` Kevin Wolf
  2018-05-29 12:41           ` Max Reitz
  0 siblings, 1 reply; 48+ messages in thread
From: Kevin Wolf @ 2018-05-29 12:39 UTC (permalink / raw)
  To: Max Reitz; +Cc: qemu-block, jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2828 bytes --]

Am 29.05.2018 um 14:15 hat Max Reitz geschrieben:
> On 2018-05-29 14:12, Kevin Wolf wrote:
> > Am 29.05.2018 um 13:48 hat Max Reitz geschrieben:
> >> On 2018-05-25 18:33, Kevin Wolf wrote:
> >>> This adds a helper function that logs both the QMP request and the
> >>> received response before returning it.
> >>>
> >>> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> >>> ---
> >>>  tests/qemu-iotests/iotests.py | 11 +++++++++++
> >>>  1 file changed, 11 insertions(+)
> >>>
> >>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> >>> index 17aa7c88dc..319d898172 100644
> >>> --- a/tests/qemu-iotests/iotests.py
> >>> +++ b/tests/qemu-iotests/iotests.py
> >>> @@ -206,6 +206,10 @@ 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/')
> >>
> >> I'd prefer 'TEST_DIR/PID-' (just because).
> >>
> >> But if you really like just 'TEST_DIR/'...  Then OK.
> > 
> > I preferred that because it leaves the output unchanged from the old
> > bash tests, which made reviewing the results easier. Maybe that's a too
> > temporary advantage to be of any use in the future, though, so we could
> > change it afterwards...
> 
> It doesn't really make reviewing the patches easier, though, because the
> hardest part of course is the change of the test itself and not the
> change of the result. :-)
> 
> (And some file name changes really are on the easy side.)

If you think so... For me the main reason to convert the test files was
to see whether the job actually does the same thing as the old
synchronous command did.

> >>> +
> >>>  def log(msg, filters=[]):
> >>>      for flt in filters:
> >>>          msg = flt(msg)
> >>> @@ -389,6 +393,13 @@ class VM(qtest.QEMUQtestMachine):
> >>>              result.append(filter_qmp_event(ev))
> >>>          return result
> >>>  
> >>> +    def qmp_log(self, cmd, **kwargs):
> >>> +        logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
> >>> +        log(filter_testfiles(logmsg))
> >>> +        result = self.qmp(cmd, **kwargs)
> >>> +        log(result)
> >>
> >> I think we should apply the testfiles filter here, too (error messages
> >> may contain file names, after all).
> > 
> > Didn't happen in the test outputs of this series, and filter_testfiles()
> > processes strings whereas result is a dict, so it would be more
> > complicated than just adding a function call.
> 
> You mean it would be "log(filter_testfiles('%s' % result)))"?

Ah, you mean just for logging? Yes, we can do that. I thought you meant
returning a filtered result as well.

Kevin

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log()
  2018-05-29 12:39         ` Kevin Wolf
@ 2018-05-29 12:41           ` Max Reitz
  0 siblings, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 12:41 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 3078 bytes --]

On 2018-05-29 14:39, Kevin Wolf wrote:
> Am 29.05.2018 um 14:15 hat Max Reitz geschrieben:
>> On 2018-05-29 14:12, Kevin Wolf wrote:
>>> Am 29.05.2018 um 13:48 hat Max Reitz geschrieben:
>>>> On 2018-05-25 18:33, Kevin Wolf wrote:
>>>>> This adds a helper function that logs both the QMP request and the
>>>>> received response before returning it.
>>>>>
>>>>> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
>>>>> ---
>>>>>  tests/qemu-iotests/iotests.py | 11 +++++++++++
>>>>>  1 file changed, 11 insertions(+)
>>>>>
>>>>> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
>>>>> index 17aa7c88dc..319d898172 100644
>>>>> --- a/tests/qemu-iotests/iotests.py
>>>>> +++ b/tests/qemu-iotests/iotests.py
>>>>> @@ -206,6 +206,10 @@ 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/')
>>>>
>>>> I'd prefer 'TEST_DIR/PID-' (just because).
>>>>
>>>> But if you really like just 'TEST_DIR/'...  Then OK.
>>>
>>> I preferred that because it leaves the output unchanged from the old
>>> bash tests, which made reviewing the results easier. Maybe that's a too
>>> temporary advantage to be of any use in the future, though, so we could
>>> change it afterwards...
>>
>> It doesn't really make reviewing the patches easier, though, because the
>> hardest part of course is the change of the test itself and not the
>> change of the result. :-)
>>
>> (And some file name changes really are on the easy side.)
> 
> If you think so... For me the main reason to convert the test files was
> to see whether the job actually does the same thing as the old
> synchronous command did.

Sure, but kompare is rather good at highlighting changes in a single
line, so I can quickly verify them as benign. :-)

>>>>> +
>>>>>  def log(msg, filters=[]):
>>>>>      for flt in filters:
>>>>>          msg = flt(msg)
>>>>> @@ -389,6 +393,13 @@ class VM(qtest.QEMUQtestMachine):
>>>>>              result.append(filter_qmp_event(ev))
>>>>>          return result
>>>>>  
>>>>> +    def qmp_log(self, cmd, **kwargs):
>>>>> +        logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
>>>>> +        log(filter_testfiles(logmsg))
>>>>> +        result = self.qmp(cmd, **kwargs)
>>>>> +        log(result)
>>>>
>>>> I think we should apply the testfiles filter here, too (error messages
>>>> may contain file names, after all).
>>>
>>> Didn't happen in the test outputs of this series, and filter_testfiles()
>>> processes strings whereas result is a dict, so it would be more
>>> complicated than just adding a function call.
>>
>> You mean it would be "log(filter_testfiles('%s' % result)))"?
> 
> Ah, you mean just for logging? Yes, we can do that. I thought you meant
> returning a filtered result as well.

Oh, no.  At least I can't think of a reason why we'd want that.

Max


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 " Kevin Wolf
@ 2018-05-29 12:44   ` Max Reitz
  2018-05-29 12:47   ` Max Reitz
  2018-05-29 17:52   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2 siblings, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 12:44 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 5868 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This rewrites the test case 207 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> Most of the test cases stay the same as before (the exception being some
> improved 'size' options that allow distinguishing which command created
> the image), but in order to be able to implement proper job handling,
> the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/207        | 435 +++++++++++++++++++-----------------------
>  tests/qemu-iotests/207.out    |  89 +++++----
>  tests/qemu-iotests/group      |   6 +-
>  tests/qemu-iotests/iotests.py |  23 ++-
>  4 files changed, 264 insertions(+), 289 deletions(-)
> 
> diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
> index f5c77852d1..91c1f7e811 100755
> --- a/tests/qemu-iotests/207
> +++ b/tests/qemu-iotests/207

[...]

> +    #
> +    # Test host-key-check options
> +    #
> +    iotests.log("=== Test host-key-check options ===")
> +    iotests.log("")

[...]

> +    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 })

Technically a change from before where it was 8M, but not a change I'm
opposed to.

[...]

> +    #
> +    # 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 })

Technical changes again (the previous test didn't have host-key-check),
but these are good changes.

[...]

> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index f0f4ef32f0..e945caa6bb 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -109,9 +109,11 @@ 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):
> +def img_info_log(filename, filter_path=None):
>      output = qemu_img_pipe('info', '-f', imgfmt, filename)
> -    log(filter_img_info(output, filename))
> +    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'''
> @@ -301,6 +303,13 @@ def file_path(*names):
>  
>      return paths[0] if len(paths) == 1 else paths
>  
> +def remote_filename(path):

I don't really understand why you have two patches in this series to add
functions to iotests.py, but then you keep on adding more functions in
other patches on the side.

> +    if imgproto == 'file':
> +        return imgproto

Shouldn't this be path?

With that fixed:

Reviewed-by: Max Reitz <mreitz@redhat.com>

> +    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'''
> @@ -595,6 +604,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)
> 



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 " Kevin Wolf
  2018-05-29 12:44   ` Max Reitz
@ 2018-05-29 12:47   ` Max Reitz
  2018-05-29 17:52   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  2 siblings, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 12:47 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1429 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This rewrites the test case 207 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> Most of the test cases stay the same as before (the exception being some
> improved 'size' options that allow distinguishing which command created
> the image), but in order to be able to implement proper job handling,
> the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/207        | 435 +++++++++++++++++++-----------------------
>  tests/qemu-iotests/207.out    |  89 +++++----
>  tests/qemu-iotests/group      |   6 +-
>  tests/qemu-iotests/iotests.py |  23 ++-
>  4 files changed, 264 insertions(+), 289 deletions(-)

[...]

> diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
> index 417deee970..299650872c 100644
> --- a/tests/qemu-iotests/207.out
> +++ b/tests/qemu-iotests/207.out

[...]

> +{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'f3386a5742ddc4a04244118e59a1f92b', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}

On second thought...  That hash shouldn't be here.  Well, my R-b stands
if you change it to 314620f24e31d6074e573b80887ace53. ;-)

Max


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 10/14] qemu-iotests: Rewrite 210 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 10/14] qemu-iotests: Rewrite 210 " Kevin Wolf
@ 2018-05-29 13:02   ` Max Reitz
  2018-05-29 18:23   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 13:02 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1893 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This rewrites the test case 210 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> All of the test cases stay the same as before, but in order to be able
> to implement proper job handling, the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/210        | 393 ++++++++++++++++++------------------------
>  tests/qemu-iotests/210.out    | 189 ++++++++++++++------
>  tests/qemu-iotests/group      |   2 +-
>  tests/qemu-iotests/iotests.py |  12 +-
>  4 files changed, 310 insertions(+), 286 deletions(-)

Reviewed-by: Max Reitz <mreitz@redhat.com>

> diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
> index e607c0d296..ff4fddea56 100755
> --- a/tests/qemu-iotests/210
> +++ b/tests/qemu-iotests/210

[...]

> +    #
> +    # 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 ]:

Maybe this would be nice in patch 8 as well.

Max

> +        blockdev_create(vm, { 'driver': imgfmt,
> +                              'file': 'node0',
> +                              'key-secret': 'keysec0',
> +                              'size': size })
> +    vm.shutdown(


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 11/14] qemu-iotests: Rewrite 211 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 11/14] qemu-iotests: Rewrite 211 " Kevin Wolf
@ 2018-05-29 13:12   ` Max Reitz
  0 siblings, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 13:12 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1414 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This rewrites the test case 211 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> All of the test cases stay the same as before, but in order to be able
> to implement proper job handling, the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/211     | 384 ++++++++++++++++++---------------------------
>  tests/qemu-iotests/211.out | 123 ++++++++-------
>  tests/qemu-iotests/group   |   2 +-
>  3 files changed, 227 insertions(+), 282 deletions(-)
> 
> diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
> index 1edec26517..2fd89cfb32 100755
> --- a/tests/qemu-iotests/211
> +++ b/tests/qemu-iotests/211

[...]
> +    iotests.img_info_log(disk_path)
> +    iotests.log(iotests.filter_testfiles(iotests.qemu_img_pipe(
> +        'map', '--output=json', disk_path)))

The _filter_qemu_img_map wasn't there to filter the filename (it isn't
present in the JSON output anyway, from what I can see), but to filter
the offset.

I don't think we really need to filter the offset here, though, because
this test is for a single specific image format with very specific
options, so it should be OK.

(The only thing is that the filter_testfiles() call seems unnecessary.)

Reviewed-by: Max Reitz <mreitz@redhat.com>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 12/14] qemu-iotests: Rewrite 212 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 12/14] qemu-iotests: Rewrite 212 " Kevin Wolf
@ 2018-05-29 13:21   ` Max Reitz
  0 siblings, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 13:21 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1469 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This rewrites the test case 212 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> All of the test cases stay the same as before, but in order to be able
> to implement proper job handling, the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/212     | 483 +++++++++++++++++----------------------------
>  tests/qemu-iotests/212.out | 181 ++++++++++-------
>  tests/qemu-iotests/group   |   2 +-
>  3 files changed, 290 insertions(+), 376 deletions(-)
> 
> diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
> index e5a1ba77ce..5ac4947b82 100755
> --- a/tests/qemu-iotests/212
> +++ b/tests/qemu-iotests/212

[...]

> +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('x-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, \

't.vdi', are you sure about that? ;-)

(You thought I wouldn't read the boiler plate anymore, didn't you?  Ha!)

With that fixed:

Reviewed-by: Max Reitz <mreitz@redhat.com>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 13/14] qemu-iotests: Rewrite 213 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 13/14] qemu-iotests: Rewrite 213 " Kevin Wolf
@ 2018-05-29 13:27   ` Max Reitz
  0 siblings, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 13:27 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1387 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> This rewrites the test case 213 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> All of the test cases stay the same as before, but in order to be able
> to implement proper job handling, the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/213     | 520 +++++++++++++++++----------------------------
>  tests/qemu-iotests/213.out | 198 ++++++++++-------
>  tests/qemu-iotests/group   |   4 +-
>  3 files changed, 314 insertions(+), 408 deletions(-)
> 
> diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
> index 3a00a0f6d6..fe4017edc7 100755
> --- a/tests/qemu-iotests/213
> +++ b/tests/qemu-iotests/213

[...]

> +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('x-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, \

Now you've just given up? :-)

Again, with that fixed:

Reviewed-by: Max Reitz <mreitz@redhat.com>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 14/14] block/create: Mark blockdev-create stable
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 14/14] block/create: Mark blockdev-create stable Kevin Wolf
@ 2018-05-29 13:30   ` Max Reitz
  2018-05-29 18:25   ` [Qemu-devel] [Qemu-block] " Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Max Reitz @ 2018-05-29 13:30 UTC (permalink / raw)
  To: Kevin Wolf, qemu-block; +Cc: jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1101 bytes --]

On 2018-05-25 18:33, Kevin Wolf wrote:
> We're ready to declare the blockdev-create job stable. This renames the
> corresponding QMP command from x-blockdev-create to blockdev-create.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  qapi/block-core.json       |  4 ++--
>  qapi/job.json              |  2 +-
>  block/create.c             |  4 ++--
>  tests/qemu-iotests/206     |  2 +-
>  tests/qemu-iotests/206.out | 54 +++++++++++++++++++++++-----------------------
>  tests/qemu-iotests/207     |  2 +-
>  tests/qemu-iotests/207.out | 18 ++++++++--------
>  tests/qemu-iotests/210     |  2 +-
>  tests/qemu-iotests/210.out | 18 ++++++++--------
>  tests/qemu-iotests/211     |  2 +-
>  tests/qemu-iotests/211.out | 24 ++++++++++-----------
>  tests/qemu-iotests/212     |  2 +-
>  tests/qemu-iotests/212.out | 42 ++++++++++++++++++------------------
>  tests/qemu-iotests/213     |  2 +-
>  tests/qemu-iotests/213.out | 44 ++++++++++++++++++-------------------
>  15 files changed, 111 insertions(+), 111 deletions(-)

Reviewed-by: Max Reitz <mreitz@redhat.com>


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 03/14] job: Add error message for failing jobs
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 03/14] job: Add error message for failing jobs Kevin Wolf
  2018-05-29 11:01   ` Max Reitz
@ 2018-05-29 14:43   ` Jeff Cody
  2018-05-29 19:54     ` Kevin Wolf
  1 sibling, 1 reply; 48+ messages in thread
From: Jeff Cody @ 2018-05-29 14:43 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel, mreitz

On Fri, May 25, 2018 at 06:33:16PM +0200, Kevin Wolf wrote:
> So far we relied on job->ret and strerror() to produce an error message
> for failed jobs. Not surprisingly, this tends to result in completely
> useless messages.
> 
> This adds a Job.error field that can contain an error string for a
> failing job, and a parameter to job_completed() that sets the field. As
> a default, if NULL is passed, we continue to use strerror(job->ret).
> 
> All existing callers are changed to pass NULL. They can be improved in
> separate patches.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  include/qemu/job.h |  7 ++++++-
>  block/backup.c     |  2 +-
>  block/commit.c     |  2 +-
>  block/mirror.c     |  2 +-
>  block/stream.c     |  2 +-
>  job-qmp.c          |  9 ++-------
>  job.c              | 15 +++++++++++++--
>  7 files changed, 25 insertions(+), 14 deletions(-)
> 
> diff --git a/include/qemu/job.h b/include/qemu/job.h
> index 8c8badf75e..b2e1dd00b9 100644
> --- a/include/qemu/job.h
> +++ b/include/qemu/job.h
> @@ -124,6 +124,9 @@ typedef struct Job {
>      /** Estimated progress_current value at the completion of the job */
>      int64_t progress_total;
>  
> +    /** Error string for a failed job (NULL if job->ret == 0) */
> +    char *error;
> +
>      /** ret code passed to job_completed. */
>      int ret;
>  
> @@ -466,13 +469,15 @@ void job_transition_to_ready(Job *job);
>  /**
>   * @job: The job being completed.
>   * @ret: The status code.
> + * @error: The error message for a failing job (only with @ret < 0). If @ret is
> + *         negative, but NULL is given for @error, strerror() is used.
>   *
>   * Marks @job as completed. If @ret is non-zero, the job transaction it is part
>   * of is aborted. If @ret is zero, the job moves into the WAITING state. If it
>   * is the last job to complete in its transaction, all jobs in the transaction
>   * move from WAITING to PENDING.
>   */
> -void job_completed(Job *job, int ret);
> +void job_completed(Job *job, int ret, Error *error);
>  
>  /** Asynchronously complete the specified @job. */
>  void job_complete(Job *job, Error **errp);
> diff --git a/block/backup.c b/block/backup.c
> index 4e228e959b..5661435675 100644
> --- a/block/backup.c
> +++ b/block/backup.c
> @@ -321,7 +321,7 @@ static void backup_complete(Job *job, void *opaque)
>  {
>      BackupCompleteData *data = opaque;
>  
> -    job_completed(job, data->ret);
> +    job_completed(job, data->ret, NULL);
>      g_free(data);
>  }
>  
> diff --git a/block/commit.c b/block/commit.c
> index 620666161b..e1814d9693 100644
> --- a/block/commit.c
> +++ b/block/commit.c
> @@ -117,7 +117,7 @@ static void commit_complete(Job *job, void *opaque)
>       * bdrv_set_backing_hd() to fail. */
>      block_job_remove_all_bdrv(bjob);
>  
> -    job_completed(job, ret);
> +    job_completed(job, ret, NULL);
>      g_free(data);
>  
>      /* If bdrv_drop_intermediate() didn't already do that, remove the commit
> diff --git a/block/mirror.c b/block/mirror.c
> index dcb66ec3be..435268bbbf 100644
> --- a/block/mirror.c
> +++ b/block/mirror.c
> @@ -581,7 +581,7 @@ static void mirror_exit(Job *job, void *opaque)
>      blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
>      blk_insert_bs(bjob->blk, mirror_top_bs, &error_abort);
>  
> -    job_completed(job, data->ret);
> +    job_completed(job, data->ret, NULL);
>  
>      g_free(data);
>      bdrv_drained_end(src);
> diff --git a/block/stream.c b/block/stream.c
> index a5d6e0cf8a..9264b68a1e 100644
> --- a/block/stream.c
> +++ b/block/stream.c
> @@ -93,7 +93,7 @@ out:
>      }
>  
>      g_free(s->backing_file_str);
> -    job_completed(job, data->ret);
> +    job_completed(job, data->ret, NULL);
>      g_free(data);
>  }
>  
> diff --git a/job-qmp.c b/job-qmp.c
> index 7f38f63336..410775df61 100644
> --- a/job-qmp.c
> +++ b/job-qmp.c
> @@ -136,14 +136,9 @@ void qmp_job_dismiss(const char *id, Error **errp)
>  static JobInfo *job_query_single(Job *job, Error **errp)
>  {
>      JobInfo *info;
> -    const char *errmsg = NULL;
>  
>      assert(!job_is_internal(job));
>  
> -    if (job->ret < 0) {
> -        errmsg = strerror(-job->ret);
> -    }
> -
>      info = g_new(JobInfo, 1);
>      *info = (JobInfo) {
>          .id                 = g_strdup(job->id),
> @@ -151,8 +146,8 @@ static JobInfo *job_query_single(Job *job, Error **errp)
>          .status             = job->status,
>          .current_progress   = job->progress_current,
>          .total_progress     = job->progress_total,
> -        .has_error          = !!errmsg,
> -        .error              = g_strdup(errmsg),
> +        .has_error          = !!job->error,
> +        .error              = g_strdup(job->error),
>      };
>  
>      return info;
> diff --git a/job.c b/job.c
> index f026661b0f..fc39eaaa5e 100644
> --- a/job.c
> +++ b/job.c
> @@ -369,6 +369,7 @@ void job_unref(Job *job)
>  
>          QLIST_REMOVE(job, job_list);
>  
> +        g_free(job->error);
>          g_free(job->id);
>          g_free(job);
>      }
> @@ -661,6 +662,9 @@ static void job_update_rc(Job *job)
>      }
>      if (job->ret) {
>          job_state_transition(job, JOB_STATUS_ABORTING);
> +        if (!job->error) {
> +            job->error = g_strdup(strerror(-job->ret));
> +        }
>      }
>  }
>  
> @@ -855,10 +859,17 @@ static void job_completed_txn_success(Job *job)
>      }
>  }
>  
> -void job_completed(Job *job, int ret)
> +void job_completed(Job *job, int ret, Error *error)
>  {
>      assert(job && job->txn && !job_is_completed(job));
> +
>      job->ret = ret;
> +    if (error) {
> +        assert(job->ret < 0);

The assert here implies that only job->ret values < 0 are valid for error.
Elsewhere, we just check for non-zero values for error (for example, [1]).
Maybe we should relax this to just assert(job->ret) here?

> +        job->error = g_strdup(error_get_pretty(error));
> +        error_free(error);
> +    }
> +
>      job_update_rc(job);
>      trace_job_completed(job, ret, job->ret);

[1]

>      if (job->ret) {
          job_completed_txn_abort(job);
      } else {
          job_completed_txn_success(job);
      }


> @@ -876,7 +887,7 @@ void job_cancel(Job *job, bool force)
>      }
>      job_cancel_async(job, force);
>      if (!job_started(job)) {
> -        job_completed(job, -ECANCELED);
> +        job_completed(job, -ECANCELED, NULL);
>      } else if (job->deferred_to_main_loop) {
>          job_completed_txn_abort(job);
>      } else {
> -- 
> 2.13.6
> 
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 02/14] vhdx: Fix vhdx_co_create() return value
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 02/14] vhdx: Fix vhdx_co_create() " Kevin Wolf
  2018-05-29 10:40   ` Max Reitz
@ 2018-05-29 14:44   ` Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Jeff Cody @ 2018-05-29 14:44 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel, mreitz

On Fri, May 25, 2018 at 06:33:15PM +0200, Kevin Wolf wrote:
> .bdrv_co_create() is supposed to return 0 on success, but vhdx could
> return a positive value instead. Fix this.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  block/vhdx.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/block/vhdx.c b/block/vhdx.c
> index 0b1e21c750..b1ba121bb6 100644
> --- a/block/vhdx.c
> +++ b/block/vhdx.c
> @@ -1951,7 +1951,7 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
>          goto delete_and_exit;
>      }
>  
> -
> +    ret = 0;
>  delete_and_exit:
>      blk_unref(blk);
>      bdrv_unref(bs);
> -- 
> 2.13.6
> 
> 

Reviewed-by: Jeff Cody <jcody@redhat.com>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value Kevin Wolf
  2018-05-29 10:38   ` Max Reitz
@ 2018-05-29 14:45   ` Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Jeff Cody @ 2018-05-29 14:45 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel, mreitz

On Fri, May 25, 2018 at 06:33:14PM +0200, Kevin Wolf wrote:
> .bdrv_co_create() is supposed to return 0 on success, but vdi could
> return a positive value instead. Fix this.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  block/vdi.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/block/vdi.c b/block/vdi.c
> index 96a22b8e83..668af0a828 100644
> --- a/block/vdi.c
> +++ b/block/vdi.c
> @@ -865,6 +865,7 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
>          }
>      }
>  
> +    ret = 0;
>  exit:
>      blk_unref(blk);
>      bdrv_unref(bs_file);
> -- 
> 2.13.6
> 
> 

Reviewed-by: Jeff Cody <jcody@redhat.com>

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 04/14] block/create: Make x-blockdev-create a job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 04/14] block/create: Make x-blockdev-create a job Kevin Wolf
  2018-05-29 11:38   ` Max Reitz
@ 2018-05-29 15:27   ` Jeff Cody
  2018-05-29 15:40     ` Kevin Wolf
  1 sibling, 1 reply; 48+ messages in thread
From: Jeff Cody @ 2018-05-29 15:27 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel, mreitz

On Fri, May 25, 2018 at 06:33:17PM +0200, Kevin Wolf wrote:
> This changes the x-blockdev-create QMP command so that it doesn't block
> the monitor and the main loop any more, but starts a background job that
> performs the image creation.
> 

This comes down to "user error", but now that the monitor and main loop are
not blocked (which is good), should we try at all to catch/prevent a
blockdev-add that is issued before a blockdev-create completion?

> The basic job as implemented here is all that is necessary to make image
> creation asynchronous and to provide a QMP interface that can be marked
> stable, but it still lacks a few features that jobs usually provide: The
> job will ignore pause commands and it doesn't publish progress yet (so
> both current-progress and total-progress stay at 0). These features can
> be added later without breaking compatibility.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  qapi/block-core.json     | 14 +++++++----
>  qapi/job.json            |  4 +++-
>  block/create.c           | 61 ++++++++++++++++++++++++++++++++----------------
>  tests/qemu-iotests/group | 14 ++++++-----
>  4 files changed, 61 insertions(+), 32 deletions(-)
> 
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 7dfa77a05c..1ed3a82373 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -4013,14 +4013,18 @@
>  ##
>  # @x-blockdev-create:
>  #
> -# Create an image format on a given node.
> -# TODO Replace with something asynchronous (block job?)
> +# Starts a job to create an image format on a given node. The job is
> +# automatically finalized, but a manual job-dismiss is required.
>  #
> -# Since: 2.12
> +# @job-id:          Identifier for the newly created job.
> +#
> +# @options:         Options for the image creation.
> +#
> +# Since: 3.0
>  ##
>  { 'command': 'x-blockdev-create',
> -  'data': 'BlockdevCreateOptions',
> -  'boxed': true }
> +  'data': { 'job-id': 'str',
> +            'options': 'BlockdevCreateOptions' } }
>  
>  ##
>  # @blockdev-open-tray:
> diff --git a/qapi/job.json b/qapi/job.json
> index 970124de76..69c1970a58 100644
> --- a/qapi/job.json
> +++ b/qapi/job.json
> @@ -17,10 +17,12 @@
>  #
>  # @backup: drive backup job type, see "drive-backup"
>  #
> +# @create: image creation job type, see "x-blockdev-create" (since 3.0)
> +#
>  # Since: 1.7
>  ##
>  { 'enum': 'JobType',
> -  'data': ['commit', 'stream', 'mirror', 'backup'] }
> +  'data': ['commit', 'stream', 'mirror', 'backup', 'create'] }
>  
>  ##
>  # @JobStatus:
> diff --git a/block/create.c b/block/create.c
> index 8bd8a03719..87fdab3b72 100644
> --- a/block/create.c
> +++ b/block/create.c
> @@ -24,28 +24,49 @@
>  
>  #include "qemu/osdep.h"
>  #include "block/block_int.h"
> +#include "qemu/job.h"
>  #include "qapi/qapi-commands-block-core.h"
> +#include "qapi/qapi-visit-block-core.h"
> +#include "qapi/clone-visitor.h"
>  #include "qapi/error.h"
>  
> -typedef struct BlockdevCreateCo {
> +typedef struct BlockdevCreateJob {
> +    Job common;
>      BlockDriver *drv;
>      BlockdevCreateOptions *opts;
>      int ret;
> -    Error **errp;
> -} BlockdevCreateCo;
> +    Error *err;
> +} BlockdevCreateJob;
>  
> -static void coroutine_fn bdrv_co_create_co_entry(void *opaque)
> +static void blockdev_create_complete(Job *job, void *opaque)
>  {
> -    BlockdevCreateCo *cco = opaque;
> -    cco->ret = cco->drv->bdrv_co_create(cco->opts, cco->errp);
> +    BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common);
> +
> +    job_completed(job, s->ret, s->err);
>  }
>  
> -void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)
> +static void coroutine_fn blockdev_create_run(void *opaque)
>  {
> +    BlockdevCreateJob *s = opaque;
> +
> +    s->ret = s->drv->bdrv_co_create(s->opts, &s->err);
> +
> +    qapi_free_BlockdevCreateOptions(s->opts);
> +    job_defer_to_main_loop(&s->common, blockdev_create_complete, NULL);
> +}
> +
> +static const JobDriver blockdev_create_job_driver = {
> +    .instance_size = sizeof(BlockdevCreateJob),
> +    .job_type      = JOB_TYPE_CREATE,
> +    .start         = blockdev_create_run,
> +};
> +
> +void qmp_x_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
> +                           Error **errp)
> +{
> +    BlockdevCreateJob *s;
>      const char *fmt = BlockdevDriver_str(options->driver);
>      BlockDriver *drv = bdrv_find_format(fmt);
> -    Coroutine *co;
> -    BlockdevCreateCo cco;
>  
>      /* If the driver is in the schema, we know that it exists. But it may not
>       * be whitelisted. */
> @@ -61,16 +82,16 @@ void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)
>          return;
>      }
>  
> -    cco = (BlockdevCreateCo) {
> -        .drv = drv,
> -        .opts = options,
> -        .ret = -EINPROGRESS,
> -        .errp = errp,
> -    };
> -
> -    co = qemu_coroutine_create(bdrv_co_create_co_entry, &cco);
> -    qemu_coroutine_enter(co);
> -    while (cco.ret == -EINPROGRESS) {
> -        aio_poll(qemu_get_aio_context(), true);
> +    /* Create the block job */
> +    s = job_create(job_id, &blockdev_create_job_driver, NULL,
> +                   qemu_get_aio_context(), JOB_DEFAULT | JOB_MANUAL_DISMISS,
> +                   NULL, NULL, errp);
> +    if (!s) {
> +        return;
>      }
> +
> +    s->drv = drv,
> +    s->opts = QAPI_CLONE(BlockdevCreateOptions, options),
> +
> +    job_start(&s->common);
>  }
> diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
> index 93f93d71ba..22b0082db3 100644
> --- a/tests/qemu-iotests/group
> +++ b/tests/qemu-iotests/group
> @@ -204,14 +204,16 @@
>  203 rw auto migration
>  204 rw auto quick
>  205 rw auto quick
> -206 rw auto
> -207 rw auto
> +# TODO The following commented out tests need to be reworked to work
> +# with the x-blockdev-create job
> +#206 rw auto
> +#207 rw auto
>  208 rw auto quick
>  209 rw auto quick
> -210 rw auto
> -211 rw auto quick
> -212 rw auto quick
> -213 rw auto quick
> +#210 rw auto
> +#211 rw auto quick
> +#212 rw auto quick
> +#213 rw auto quick
>  214 rw auto
>  215 rw auto quick
>  216 rw auto quick
> -- 
> 2.13.6
> 
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 04/14] block/create: Make x-blockdev-create a job
  2018-05-29 15:27   ` [Qemu-devel] [Qemu-block] " Jeff Cody
@ 2018-05-29 15:40     ` Kevin Wolf
  0 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-29 15:40 UTC (permalink / raw)
  To: Jeff Cody; +Cc: qemu-block, qemu-devel, mreitz

Am 29.05.2018 um 17:27 hat Jeff Cody geschrieben:
> On Fri, May 25, 2018 at 06:33:17PM +0200, Kevin Wolf wrote:
> > This changes the x-blockdev-create QMP command so that it doesn't block
> > the monitor and the main loop any more, but starts a background job that
> > performs the image creation.
> > 
> 
> This comes down to "user error", but now that the monitor and main loop are
> not blocked (which is good), should we try at all to catch/prevent a
> blockdev-add that is issued before a blockdev-create completion?

Hm, currently, the .bdrv_co_create implementations usually do this:

    blk = blk_new(BLK_PERM_WRITE | BLK_PERM_RESIZE, BLK_PERM_ALL);

I'm not sure if BLK_PERM_ALL is the best options for the shared
permissions, but anyway format drivers can't share BLK_PERM_WRITE on
their part, so I think we already do prevent this by taking the
BLK_PERM_WRITE permission.

Kevin

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 09/14] qemu-iotests: Rewrite 207 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 " Kevin Wolf
  2018-05-29 12:44   ` Max Reitz
  2018-05-29 12:47   ` Max Reitz
@ 2018-05-29 17:52   ` Jeff Cody
  2 siblings, 0 replies; 48+ messages in thread
From: Jeff Cody @ 2018-05-29 17:52 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel, mreitz

On Fri, May 25, 2018 at 06:33:22PM +0200, Kevin Wolf wrote:
> This rewrites the test case 207 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> Most of the test cases stay the same as before (the exception being some
> improved 'size' options that allow distinguishing which command created
> the image), but in order to be able to implement proper job handling,
> the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/207        | 435 +++++++++++++++++++-----------------------
>  tests/qemu-iotests/207.out    |  89 +++++----
>  tests/qemu-iotests/group      |   6 +-
>  tests/qemu-iotests/iotests.py |  23 ++-
>  4 files changed, 264 insertions(+), 289 deletions(-)
> 
> diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
> index f5c77852d1..91c1f7e811 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,193 @@
>  # 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
> +
> +iotests.verify_image_format(supported_fmts=['raw'])
> +iotests.verify_protocol(supported=['ssh'])
> +
> +def blockdev_create(vm, options):
> +    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)

This needs a 'hash' filter, to filter out the md5sum in the 'md5'
host-key-check tests.


> +
> +    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..299650872c 100644
> --- a/tests/qemu-iotests/207.out
> +++ b/tests/qemu-iotests/207.out
> @@ -1,62 +1,64 @@
> -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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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"}}
>  file format: IMGFMT
>  virtual size: 4.0M (4194304 bytes)
>  
> +
>  image: TEST_DIR/t.IMGFMT
>  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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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"}}
>  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}}
> +
> +{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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_DIR/t.IMGFMT"}}
>  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}}
> +
> +{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'f3386a5742ddc4a04244118e59a1f92b', '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_DIR/t.IMGFMT"}}
>  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}}
> +
> +{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'c6142e54650531177fa3d88ac52501ae00ccff69', '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_DIR/t.IMGFMT"}}
>  file format: IMGFMT
> @@ -64,12 +66,15 @@ 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': 'x-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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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/group b/tests/qemu-iotests/group
> index be157e7679..8a84bf057d 100644
> --- a/tests/qemu-iotests/group
> +++ b/tests/qemu-iotests/group
> @@ -205,11 +205,11 @@
>  204 rw auto quick
>  205 rw auto quick
>  206 rw auto
> -# TODO The following commented out tests need to be reworked to work
> -# with the x-blockdev-create job
> -#207 rw auto
> +207 rw auto
>  208 rw auto quick
>  209 rw auto quick
> +# TODO The following commented out tests need to be reworked to work
> +# with the x-blockdev-create job
>  #210 rw auto
>  #211 rw auto quick
>  #212 rw auto quick
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index f0f4ef32f0..e945caa6bb 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -109,9 +109,11 @@ 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):
> +def img_info_log(filename, filter_path=None):
>      output = qemu_img_pipe('info', '-f', imgfmt, filename)
> -    log(filter_img_info(output, filename))
> +    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'''
> @@ -301,6 +303,13 @@ def file_path(*names):
>  
>      return paths[0] if len(paths) == 1 else paths
>  
> +def remote_filename(path):
> +    if imgproto == 'file':
> +        return imgproto
> +    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'''
> @@ -595,6 +604,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)
> -- 
> 2.13.6
> 
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 10/14] qemu-iotests: Rewrite 210 for blockdev-create job
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 10/14] qemu-iotests: Rewrite 210 " Kevin Wolf
  2018-05-29 13:02   ` Max Reitz
@ 2018-05-29 18:23   ` Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Jeff Cody @ 2018-05-29 18:23 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel, mreitz

On Fri, May 25, 2018 at 06:33:23PM +0200, Kevin Wolf wrote:
> This rewrites the test case 210 to work with the new x-blockdev-create
> job rather than the old synchronous version of the command.
> 
> All of the test cases stay the same as before, but in order to be able
> to implement proper job handling, the test case is rewritten in Python.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Reviewed-by: Jeff Cody <jcody@redhat.com>

> ---
>  tests/qemu-iotests/210        | 393 ++++++++++++++++++------------------------
>  tests/qemu-iotests/210.out    | 189 ++++++++++++++------
>  tests/qemu-iotests/group      |   2 +-
>  tests/qemu-iotests/iotests.py |  12 +-
>  4 files changed, 310 insertions(+), 286 deletions(-)
> 
> diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
> index e607c0d296..ff4fddea56 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('x-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..116218ae4e 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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
> +{u'return': {}}
> +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
> +{u'return': {}}
> +
> +{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}
> +{u'return': {}}
> +{'execute': 'x-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"}
>  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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
> +{u'return': {}}
> +{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
> +{u'return': {}}
> +
> +{'execute': 'x-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/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"}
>  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': 'x-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': 'x-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"}
>  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': 'x-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': 'x-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': {}}
>  
> -=== Resize image with invalid sizes ===
> +{'execute': 'x-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': {}}
>  
> -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}}
> +=== Resize image with invalid sizes ===
>  
> +{'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_DIR/t.IMGFMT"}, "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/group b/tests/qemu-iotests/group
> index 8a84bf057d..a1d04ce367 100644
> --- a/tests/qemu-iotests/group
> +++ b/tests/qemu-iotests/group
> @@ -208,9 +208,9 @@
>  207 rw auto
>  208 rw auto quick
>  209 rw auto quick
> +210 rw auto
>  # TODO The following commented out tests need to be reworked to work
>  # with the x-blockdev-create job
> -#210 rw auto
>  #211 rw auto quick
>  #212 rw auto quick
>  #213 rw auto quick
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index e945caa6bb..6499a9e6fe 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -109,8 +109,16 @@ 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):
> -    output = qemu_img_pipe('info', '-f', imgfmt, filename)
> +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))
> -- 
> 2.13.6
> 
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 14/14] block/create: Mark blockdev-create stable
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 14/14] block/create: Mark blockdev-create stable Kevin Wolf
  2018-05-29 13:30   ` Max Reitz
@ 2018-05-29 18:25   ` Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Jeff Cody @ 2018-05-29 18:25 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel, mreitz

On Fri, May 25, 2018 at 06:33:27PM +0200, Kevin Wolf wrote:
> We're ready to declare the blockdev-create job stable. This renames the
> corresponding QMP command from x-blockdev-create to blockdev-create.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>

Reviewed-by: Jeff Cody <jcody@redhat.com>

> ---
>  qapi/block-core.json       |  4 ++--
>  qapi/job.json              |  2 +-
>  block/create.c             |  4 ++--
>  tests/qemu-iotests/206     |  2 +-
>  tests/qemu-iotests/206.out | 54 +++++++++++++++++++++++-----------------------
>  tests/qemu-iotests/207     |  2 +-
>  tests/qemu-iotests/207.out | 18 ++++++++--------
>  tests/qemu-iotests/210     |  2 +-
>  tests/qemu-iotests/210.out | 18 ++++++++--------
>  tests/qemu-iotests/211     |  2 +-
>  tests/qemu-iotests/211.out | 24 ++++++++++-----------
>  tests/qemu-iotests/212     |  2 +-
>  tests/qemu-iotests/212.out | 42 ++++++++++++++++++------------------
>  tests/qemu-iotests/213     |  2 +-
>  tests/qemu-iotests/213.out | 44 ++++++++++++++++++-------------------
>  15 files changed, 111 insertions(+), 111 deletions(-)
> 
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 1ed3a82373..015e5ac12b 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -4011,7 +4011,7 @@
>    } }
>  
>  ##
> -# @x-blockdev-create:
> +# @blockdev-create:
>  #
>  # Starts a job to create an image format on a given node. The job is
>  # automatically finalized, but a manual job-dismiss is required.
> @@ -4022,7 +4022,7 @@
>  #
>  # Since: 3.0
>  ##
> -{ 'command': 'x-blockdev-create',
> +{ 'command': 'blockdev-create',
>    'data': { 'job-id': 'str',
>              'options': 'BlockdevCreateOptions' } }
>  
> diff --git a/qapi/job.json b/qapi/job.json
> index 69c1970a58..17d10037c4 100644
> --- a/qapi/job.json
> +++ b/qapi/job.json
> @@ -17,7 +17,7 @@
>  #
>  # @backup: drive backup job type, see "drive-backup"
>  #
> -# @create: image creation job type, see "x-blockdev-create" (since 3.0)
> +# @create: image creation job type, see "blockdev-create" (since 3.0)
>  #
>  # Since: 1.7
>  ##
> diff --git a/block/create.c b/block/create.c
> index 87fdab3b72..21728acca0 100644
> --- a/block/create.c
> +++ b/block/create.c
> @@ -61,8 +61,8 @@ static const JobDriver blockdev_create_job_driver = {
>      .start         = blockdev_create_run,
>  };
>  
> -void qmp_x_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
> -                           Error **errp)
> +void qmp_blockdev_create(const char *job_id, BlockdevCreateOptions *options,
> +                         Error **errp)
>  {
>      BlockdevCreateJob *s;
>      const char *fmt = BlockdevDriver_str(options->driver);
> diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
> index 9a305302d1..334410d6a7 100755
> --- a/tests/qemu-iotests/206
> +++ b/tests/qemu-iotests/206
> @@ -26,7 +26,7 @@ from iotests import imgfmt
>  iotests.verify_image_format(supported_fmts=['qcow2'])
>  
>  def blockdev_create(vm, options):
> -    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
> +    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
>  
>      if 'return' in result:
>          assert result['return'] == {}
> diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
> index 45367270e8..8b403ea08f 100644
> --- a/tests/qemu-iotests/206.out
> +++ b/tests/qemu-iotests/206.out
> @@ -1,13 +1,13 @@
>  === Successful image creation (defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
>  {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}
>  {u'return': {}}
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -24,12 +24,12 @@ Format specific information:
>  
>  === Successful image creation (inline blockdev-add, explicit defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -46,12 +46,12 @@ Format specific information:
>  
>  === Successful image creation (v3 non-default options) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -68,12 +68,12 @@ Format specific information:
>  
>  === Successful image creation (v2 non-default options) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'backing-file': 'TEST_DIR/t.qcow2.base', 'size': 33554432}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.qcow2'}, 'backing-file': 'TEST_DIR/t.qcow2.base', 'size': 33554432}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -90,7 +90,7 @@ Format specific information:
>  
>  === Successful image creation (encrypted) ===
>  
> -{'execute': 'x-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/t.qcow2'}, 'size': 33554432}}}
> +{'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/t.qcow2'}, 'size': 33554432}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -144,111 +144,111 @@ Format specific information:
>  
>  === Invalid BlockdevRef ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': "this doesn't exist", 'size': 33554432}}}
> +{'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 ===
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 1234}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 18446744073709551104L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775808L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775296}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'version': 'v1', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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'"}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'lazy-refcounts': True, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 8, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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 ===
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'full', 'driver': 'qcow2', 'backing-file': '/dev/null', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'backing-fmt': 'qcow2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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 ===
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4194304, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'qcow2', 'file': 'node0', 'size': 281474976710656}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 7, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
> +{'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'}}
> diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
> index 91c1f7e811..0d7680599f 100755
> --- a/tests/qemu-iotests/207
> +++ b/tests/qemu-iotests/207
> @@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['raw'])
>  iotests.verify_protocol(supported=['ssh'])
>  
>  def blockdev_create(vm, options):
> -    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
> +    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
>  
>      if 'return' in result:
>          assert result['return'] == {}
> diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
> index 299650872c..92a7fa1b01 100644
> --- a/tests/qemu-iotests/207.out
> +++ b/tests/qemu-iotests/207.out
> @@ -1,6 +1,6 @@
>  === Successful image creation (defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -16,7 +16,7 @@ virtual size: 4.0M (4194304 bytes)
>  
>  === Test host-key-check options ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': {}}
> @@ -25,7 +25,7 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
>  file format: IMGFMT
>  virtual size: 8.0M (8388608 bytes)
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'mode': 'known_hosts'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': {}}
> @@ -34,13 +34,13 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
>  file format: IMGFMT
>  virtual size: 4.0M (4194304 bytes)
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'wrong', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'f3386a5742ddc4a04244118e59a1f92b', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'f3386a5742ddc4a04244118e59a1f92b', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -49,13 +49,13 @@ image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.po
>  file format: IMGFMT
>  virtual size: 8.0M (8388608 bytes)
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'wrong', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'c6142e54650531177fa3d88ac52501ae00ccff69', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'hash': 'c6142e54650531177fa3d88ac52501ae00ccff69', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -66,13 +66,13 @@ virtual size: 4.0M (4194304 bytes)
>  
>  === Invalid path and user ===
>  
> -{'execute': 'x-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}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/t.img', 'host-key-check': {'mode': 'none'}, 'user': 'invalid user', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/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'}}
> diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
> index ff4fddea56..d142841e2b 100755
> --- a/tests/qemu-iotests/210
> +++ b/tests/qemu-iotests/210
> @@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['luks'])
>  iotests.verify_protocol(supported=['file'])
>  
>  def blockdev_create(vm, options):
> -    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
> +    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
>  
>      if 'return' in result:
>          assert result['return'] == {}
> diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out
> index 116218ae4e..ffdf8b4ce9 100644
> --- a/tests/qemu-iotests/210.out
> +++ b/tests/qemu-iotests/210.out
> @@ -1,13 +1,13 @@
>  === Successful image creation (defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
>  {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}
>  {u'return': {}}
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'imgfile', 'size': 134217728}}}
> +{'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': {}}
> @@ -54,12 +54,12 @@ Format specific information:
>  
>  === Successful image creation (with non-default options) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.luks'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-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/t.luks'}, 'iter-time': 10, 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'driver': 'luks', 'size': 67108864}}}
> +{'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/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': {}}
> @@ -106,7 +106,7 @@ Format specific information:
>  
>  === Invalid BlockdevRef ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'luks', 'file': "this doesn't exist", 'size': 67108864}}}
> +{'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'}}
> @@ -114,7 +114,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
>  
>  === Zero size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'node0', 'size': 0}}}
> +{'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': {}}
> @@ -161,19 +161,19 @@ Format specific information:
>  
>  === Invalid sizes ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 18446744073709551104L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775808L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775296}}}
> +{'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'}}
> diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
> index 2fd89cfb32..05215776ce 100755
> --- a/tests/qemu-iotests/211
> +++ b/tests/qemu-iotests/211
> @@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['vdi'])
>  iotests.verify_protocol(supported=['file'])
>  
>  def blockdev_create(vm, options):
> -    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
> +    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
>  
>      if 'return' in result:
>          assert result['return'] == {}
> diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out
> index 31ef74db4c..b43fb73f50 100644
> --- a/tests/qemu-iotests/211.out
> +++ b/tests/qemu-iotests/211.out
> @@ -1,13 +1,13 @@
>  === Successful image creation (defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
>  {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
>  {u'return': {}}
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -21,12 +21,12 @@ cluster_size: 1048576
>  
>  === Successful image creation (explicit defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -40,12 +40,12 @@ cluster_size: 1048576
>  
>  === Successful image creation (with non-default options) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -60,7 +60,7 @@ cluster_size: 1048576
>  
>  === Invalid BlockdevRef ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': "this doesn't exist", 'size': 33554432}}}
> +{'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'}}
> @@ -68,7 +68,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
>  
>  === Zero size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -80,7 +80,7 @@ cluster_size: 1048576
>  
>  === Maximum size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -92,19 +92,19 @@ cluster_size: 1048576
>  
>  === Invalid sizes ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 18446744073709551104L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 9223372036854775808L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203585}}}
> +{'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'}}
> diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
> index 5ac4947b82..d22dde12ad 100755
> --- a/tests/qemu-iotests/212
> +++ b/tests/qemu-iotests/212
> @@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['parallels'])
>  iotests.verify_protocol(supported=['file'])
>  
>  def blockdev_create(vm, options):
> -    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
> +    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
>  
>      if 'return' in result:
>          assert result['return'] == {}
> diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out
> index 25c5c46027..4230ef929c 100644
> --- a/tests/qemu-iotests/212.out
> +++ b/tests/qemu-iotests/212.out
> @@ -1,13 +1,13 @@
>  === Successful image creation (defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
>  {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
>  {u'return': {}}
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -18,12 +18,12 @@ virtual size: 128M (134217728 bytes)
>  
>  === Successful image creation (explicit defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 67108864}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -34,12 +34,12 @@ virtual size: 64M (67108864 bytes)
>  
>  === Successful image creation (with non-default options) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'size': 33554432}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -50,7 +50,7 @@ virtual size: 32M (33554432 bytes)
>  
>  === Invalid BlockdevRef ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': "this doesn't exist", 'size': 33554432}}}
> +{'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'}}
> @@ -58,7 +58,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
>  
>  === Zero size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -69,7 +69,7 @@ virtual size: 0 (0 bytes)
>  
>  === Maximum size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -80,31 +80,31 @@ virtual size: 4096T (4503599627369984 bytes)
>  
>  === Invalid sizes ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 1234}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 18446744073709551104L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775808L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775296}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627370497}}}
> +{'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'}}
> @@ -112,43 +112,43 @@ Job failed: Image size is too large for this cluster size
>  
>  === Invalid cluster size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4294967296, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 9223372036854775808L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 18446744073709551104L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'parallels', 'file': 'node0', 'size': 281474976710656}}}
> +{'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'}}
> diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
> index fe4017edc7..ccc27e4b2c 100755
> --- a/tests/qemu-iotests/213
> +++ b/tests/qemu-iotests/213
> @@ -27,7 +27,7 @@ iotests.verify_image_format(supported_fmts=['vhdx'])
>  iotests.verify_protocol(supported=['file'])
>  
>  def blockdev_create(vm, options):
> -    result = vm.qmp_log('x-blockdev-create', job_id='job0', options=options)
> +    result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
>  
>      if 'return' in result:
>          assert result['return'] == {}
> diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out
> index 2b83e5df97..36a225f423 100644
> --- a/tests/qemu-iotests/213.out
> +++ b/tests/qemu-iotests/213.out
> @@ -1,13 +1,13 @@
>  === Successful image creation (defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
>  {'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}
>  {u'return': {}}
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -19,12 +19,12 @@ cluster_size: 8388608
>  
>  === Successful image creation (explicit defaults) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': True, 'size': 67108864}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': True, 'size': 67108864}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -36,12 +36,12 @@ cluster_size: 8388608
>  
>  === Successful image creation (with non-default options) ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': False, 'size': 33554432}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/t.vdi'}, 'block-state-zero': False, 'size': 33554432}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -53,7 +53,7 @@ cluster_size: 268435456
>  
>  === Invalid BlockdevRef ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}}
> +{'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'}}
> @@ -61,7 +61,7 @@ Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exi
>  
>  === Zero size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -73,7 +73,7 @@ cluster_size: 8388608
>  
>  === Maximum size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}}
> +{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}}
>  {u'return': {}}
>  {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
>  {u'return': {}}
> @@ -85,25 +85,25 @@ cluster_size: 67108864
>  
>  === Invalid sizes ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775808L}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775296}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177665}}}
> +{'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'}}
> @@ -111,31 +111,31 @@ Job failed: Image size too large; max of 64TB
>  
>  === Invalid block size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 128, 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 3145728, 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 536870912, 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 0, 'file': 'node0', 'size': 67108864}}}
> +{'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'}}
> @@ -143,25 +143,25 @@ Job failed: Block size must be a multiple of 1 MB
>  
>  === Invalid log size ===
>  
> -{'execute': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 4294967296, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
> +{'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': 'x-blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 0, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
> +{'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'}}
> -- 
> 2.13.6
> 
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 06/14] qemu-iotests: Add VM.qmp_log()
  2018-05-25 16:33 ` [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log() Kevin Wolf
  2018-05-29 11:48   ` Max Reitz
@ 2018-05-29 18:31   ` Jeff Cody
  1 sibling, 0 replies; 48+ messages in thread
From: Jeff Cody @ 2018-05-29 18:31 UTC (permalink / raw)
  To: Kevin Wolf; +Cc: qemu-block, qemu-devel, mreitz

On Fri, May 25, 2018 at 06:33:19PM +0200, Kevin Wolf wrote:
> This adds a helper function that logs both the QMP request and the
> received response before returning it.
> 
> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> ---
>  tests/qemu-iotests/iotests.py | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> index 17aa7c88dc..319d898172 100644
> --- a/tests/qemu-iotests/iotests.py
> +++ b/tests/qemu-iotests/iotests.py
> @@ -206,6 +206,10 @@ 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/')
> +

Either as-is, or with the suggestion by Max to add the PID to the output:

Reviewed-by: Jeff Cody <jcody@redhat.com>


>  def log(msg, filters=[]):
>      for flt in filters:
>          msg = flt(msg)
> @@ -389,6 +393,13 @@ class VM(qtest.QEMUQtestMachine):
>              result.append(filter_qmp_event(ev))
>          return result
>  
> +    def qmp_log(self, cmd, **kwargs):
> +        logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
> +        log(filter_testfiles(logmsg))
> +        result = self.qmp(cmd, **kwargs)
> +        log(result)
> +        return result
> +
>  
>  index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
>  
> -- 
> 2.13.6
> 
> 

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [PATCH 08/14] qemu-iotests: Rewrite 206 for blockdev-create job
  2018-05-29 12:27   ` Max Reitz
@ 2018-05-29 18:49     ` Kevin Wolf
  0 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-29 18:49 UTC (permalink / raw)
  To: Max Reitz; +Cc: qemu-block, jsnow, eblake, pkrempa, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 6965 bytes --]

Am 29.05.2018 um 14:27 hat Max Reitz geschrieben:
> On 2018-05-25 18:33, Kevin Wolf wrote:
> > This rewrites the test case 206 to work with the new x-blockdev-create
> > job rather than the old synchronous version of the command.
> > 
> > All of the test cases stay the same as before, but in order to be able
> > to implement proper job handling, the test case is rewritten in Python.
> > 
> > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > ---
> >  tests/qemu-iotests/206        | 705 +++++++++++++++++-------------------------
> >  tests/qemu-iotests/206.out    | 241 +++++++++------
> >  tests/qemu-iotests/group      |   2 +-
> >  tests/qemu-iotests/iotests.py |  15 +
> >  4 files changed, 448 insertions(+), 515 deletions(-)
> > 
> > diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206
> > index 0a18b2b19a..9a305302d1 100755
> > --- a/tests/qemu-iotests/206
> > +++ b/tests/qemu-iotests/206
> 
> [...]
> 
> > +import iotests
> > +from iotests import imgfmt
> > +
> > +iotests.verify_image_format(supported_fmts=['qcow2'])
> > +
> > +def blockdev_create(vm, options):
> > +    result = vm.qmp_log('x-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"')
> 
> I don't know how subprocess.Popen() works, but are you sure you aren't
> encrypting with '"foo"' now?  (i.e. literally that key, including quotes)

That's correct. Anything wrong with it?

(Okay, you're right. I did fix it in 210, but forgot it here...)

> > +
> > +    #
> > +    # Successful image creation (defaults)
> > +    #
> > +    iotests.log("=== Successful image creation (defaults) ===")
> 
> OK, the comment makes sense for visual separation.  But so would leaving
> three empty lines.  *cough*

I tried vertical spacing first, but it didn't work well for me. What
made the difference is the syntax highlighting of comments vs. code.
YMMV.

> > +    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 (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,
> 
> Change from the bash version: backing_path does not exist here.  Not
> sure if that was intentional.

No, it was not. It's actually a good test case, though. Creating an
image at backing_path would be easy enough, but maybe we should just
leave it?

> > +                          'backing-fmt': 'qcow2',
> > +                          'version': 'v2',
> > +                          'cluster-size': 512 })
> > +    vm.shutdown()
> > +
> > +    iotests.img_info_log(disk_path)
> 
> [...]
> 
> > +    #
> > +    # 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()
> > +    blockdev_create(vm, { 'driver': imgfmt,
> > +                          'file': 'node0',
> > +                          'size': 1234  })
> > +    blockdev_create(vm, { 'driver': imgfmt,
> > +                          'file': 'node0',
> > +                          'size': 18446744073709551104 })
> > +    blockdev_create(vm, { 'driver': imgfmt,
> > +                          'file': 'node0',
> > +                          'size': 9223372036854775808 })
> > +    blockdev_create(vm, { 'driver': imgfmt,
> > +                          'file': 'node0',
> > +                          'size': 9223372036854775296})
> 
> Missing space before the closing fancy bracket, critical!
> 
> [...]
> 
> > diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
> > index 20ce5a0cf0..f0f4ef32f0 100644
> > --- a/tests/qemu-iotests/iotests.py
> > +++ b/tests/qemu-iotests/iotests.py
> > @@ -416,6 +416,21 @@ class VM(qtest.QEMUQtestMachine):
> >          log(result)
> >          return result
> >  
> > +    def run_job(self, job):
> 
> Is there any reason this function did not get its own patch?
> 
> Also, this is a function specifically for jobs that need a manual
> dismiss but have auto-finalize.  That should be noted somewhere (ideally
> in the function's name, but spontaneously I don't know how).

If you want me to move it into a separate patch, maybe just make it more
reusable with parameters auto_finalize=True, auto_dismiss=false.

> > +        while True:
> > +            for ev in self.get_qmp_events_filtered(wait=True):
> > +                if ev['event'] == 'JOB_STATUS_CHANGE':
> > +                    if ev['data']['status'] == 'aborting':
> > +                        result = self.qmp('query-jobs')
> > +                        for j in result['return']:
> > +                            log('Job failed: %s' % (j.get('error', None)))
> 
> I can understand that you didn't want to use just result['return'][0],
> but if you do iterate, you should probably emit the job ID as well.

If you have multiple jobs running, it doesn't work correctly anyway. :-)

Kevin

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 48+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH 03/14] job: Add error message for failing jobs
  2018-05-29 14:43   ` [Qemu-devel] [Qemu-block] " Jeff Cody
@ 2018-05-29 19:54     ` Kevin Wolf
  0 siblings, 0 replies; 48+ messages in thread
From: Kevin Wolf @ 2018-05-29 19:54 UTC (permalink / raw)
  To: Jeff Cody; +Cc: qemu-block, qemu-devel, mreitz

Am 29.05.2018 um 16:43 hat Jeff Cody geschrieben:
> On Fri, May 25, 2018 at 06:33:16PM +0200, Kevin Wolf wrote:
> > So far we relied on job->ret and strerror() to produce an error message
> > for failed jobs. Not surprisingly, this tends to result in completely
> > useless messages.
> > 
> > This adds a Job.error field that can contain an error string for a
> > failing job, and a parameter to job_completed() that sets the field. As
> > a default, if NULL is passed, we continue to use strerror(job->ret).
> > 
> > All existing callers are changed to pass NULL. They can be improved in
> > separate patches.
> > 
> > Signed-off-by: Kevin Wolf <kwolf@redhat.com>
> > ---
> >  include/qemu/job.h |  7 ++++++-
> >  block/backup.c     |  2 +-
> >  block/commit.c     |  2 +-
> >  block/mirror.c     |  2 +-
> >  block/stream.c     |  2 +-
> >  job-qmp.c          |  9 ++-------
> >  job.c              | 15 +++++++++++++--
> >  7 files changed, 25 insertions(+), 14 deletions(-)
> > 
> > diff --git a/include/qemu/job.h b/include/qemu/job.h
> > index 8c8badf75e..b2e1dd00b9 100644
> > --- a/include/qemu/job.h
> > +++ b/include/qemu/job.h
> > @@ -124,6 +124,9 @@ typedef struct Job {
> >      /** Estimated progress_current value at the completion of the job */
> >      int64_t progress_total;
> >  
> > +    /** Error string for a failed job (NULL if job->ret == 0) */
> > +    char *error;
> > +
> >      /** ret code passed to job_completed. */
> >      int ret;
> >  
> > @@ -466,13 +469,15 @@ void job_transition_to_ready(Job *job);
> >  /**
> >   * @job: The job being completed.
> >   * @ret: The status code.
> > + * @error: The error message for a failing job (only with @ret < 0). If @ret is
> > + *         negative, but NULL is given for @error, strerror() is used.
> >   *
> >   * Marks @job as completed. If @ret is non-zero, the job transaction it is part
> >   * of is aborted. If @ret is zero, the job moves into the WAITING state. If it
> >   * is the last job to complete in its transaction, all jobs in the transaction
> >   * move from WAITING to PENDING.
> >   */
> > -void job_completed(Job *job, int ret);
> > +void job_completed(Job *job, int ret, Error *error);
> >  
> >  /** Asynchronously complete the specified @job. */
> >  void job_complete(Job *job, Error **errp);
> > diff --git a/block/backup.c b/block/backup.c
> > index 4e228e959b..5661435675 100644
> > --- a/block/backup.c
> > +++ b/block/backup.c
> > @@ -321,7 +321,7 @@ static void backup_complete(Job *job, void *opaque)
> >  {
> >      BackupCompleteData *data = opaque;
> >  
> > -    job_completed(job, data->ret);
> > +    job_completed(job, data->ret, NULL);
> >      g_free(data);
> >  }
> >  
> > diff --git a/block/commit.c b/block/commit.c
> > index 620666161b..e1814d9693 100644
> > --- a/block/commit.c
> > +++ b/block/commit.c
> > @@ -117,7 +117,7 @@ static void commit_complete(Job *job, void *opaque)
> >       * bdrv_set_backing_hd() to fail. */
> >      block_job_remove_all_bdrv(bjob);
> >  
> > -    job_completed(job, ret);
> > +    job_completed(job, ret, NULL);
> >      g_free(data);
> >  
> >      /* If bdrv_drop_intermediate() didn't already do that, remove the commit
> > diff --git a/block/mirror.c b/block/mirror.c
> > index dcb66ec3be..435268bbbf 100644
> > --- a/block/mirror.c
> > +++ b/block/mirror.c
> > @@ -581,7 +581,7 @@ static void mirror_exit(Job *job, void *opaque)
> >      blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
> >      blk_insert_bs(bjob->blk, mirror_top_bs, &error_abort);
> >  
> > -    job_completed(job, data->ret);
> > +    job_completed(job, data->ret, NULL);
> >  
> >      g_free(data);
> >      bdrv_drained_end(src);
> > diff --git a/block/stream.c b/block/stream.c
> > index a5d6e0cf8a..9264b68a1e 100644
> > --- a/block/stream.c
> > +++ b/block/stream.c
> > @@ -93,7 +93,7 @@ out:
> >      }
> >  
> >      g_free(s->backing_file_str);
> > -    job_completed(job, data->ret);
> > +    job_completed(job, data->ret, NULL);
> >      g_free(data);
> >  }
> >  
> > diff --git a/job-qmp.c b/job-qmp.c
> > index 7f38f63336..410775df61 100644
> > --- a/job-qmp.c
> > +++ b/job-qmp.c
> > @@ -136,14 +136,9 @@ void qmp_job_dismiss(const char *id, Error **errp)
> >  static JobInfo *job_query_single(Job *job, Error **errp)
> >  {
> >      JobInfo *info;
> > -    const char *errmsg = NULL;
> >  
> >      assert(!job_is_internal(job));
> >  
> > -    if (job->ret < 0) {
> > -        errmsg = strerror(-job->ret);
> > -    }
> > -
> >      info = g_new(JobInfo, 1);
> >      *info = (JobInfo) {
> >          .id                 = g_strdup(job->id),
> > @@ -151,8 +146,8 @@ static JobInfo *job_query_single(Job *job, Error **errp)
> >          .status             = job->status,
> >          .current_progress   = job->progress_current,
> >          .total_progress     = job->progress_total,
> > -        .has_error          = !!errmsg,
> > -        .error              = g_strdup(errmsg),
> > +        .has_error          = !!job->error,
> > +        .error              = g_strdup(job->error),
> >      };
> >  
> >      return info;
> > diff --git a/job.c b/job.c
> > index f026661b0f..fc39eaaa5e 100644
> > --- a/job.c
> > +++ b/job.c
> > @@ -369,6 +369,7 @@ void job_unref(Job *job)
> >  
> >          QLIST_REMOVE(job, job_list);
> >  
> > +        g_free(job->error);
> >          g_free(job->id);
> >          g_free(job);
> >      }
> > @@ -661,6 +662,9 @@ static void job_update_rc(Job *job)
> >      }
> >      if (job->ret) {
> >          job_state_transition(job, JOB_STATUS_ABORTING);
> > +        if (!job->error) {
> > +            job->error = g_strdup(strerror(-job->ret));
> > +        }
> >      }
> >  }
> >  
> > @@ -855,10 +859,17 @@ static void job_completed_txn_success(Job *job)
> >      }
> >  }
> >  
> > -void job_completed(Job *job, int ret)
> > +void job_completed(Job *job, int ret, Error *error)
> >  {
> >      assert(job && job->txn && !job_is_completed(job));
> > +
> >      job->ret = ret;
> > +    if (error) {
> > +        assert(job->ret < 0);
> 
> The assert here implies that only job->ret values < 0 are valid for error.
> Elsewhere, we just check for non-zero values for error (for example, [1]).
> Maybe we should relax this to just assert(job->ret) here?

A positive error is usually a bug. I wouldn't even be sure if it should
be considered success (e.g. someone returned the result of bdrv_pwrite()
like the two places fixed at the start of this series) or we forgot to
negate errno.

I think it's better to be strict and catch such bugs.

Kevin

^ permalink raw reply	[flat|nested] 48+ messages in thread

end of thread, other threads:[~2018-05-29 19:54 UTC | newest]

Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-25 16:33 [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API Kevin Wolf
2018-05-25 16:33 ` [Qemu-devel] [PATCH 01/14] vdi: Fix vdi_co_do_create() return value Kevin Wolf
2018-05-29 10:38   ` Max Reitz
2018-05-29 14:45   ` [Qemu-devel] [Qemu-block] " Jeff Cody
2018-05-25 16:33 ` [Qemu-devel] [PATCH 02/14] vhdx: Fix vhdx_co_create() " Kevin Wolf
2018-05-29 10:40   ` Max Reitz
2018-05-29 14:44   ` [Qemu-devel] [Qemu-block] " Jeff Cody
2018-05-25 16:33 ` [Qemu-devel] [PATCH 03/14] job: Add error message for failing jobs Kevin Wolf
2018-05-29 11:01   ` Max Reitz
2018-05-29 14:43   ` [Qemu-devel] [Qemu-block] " Jeff Cody
2018-05-29 19:54     ` Kevin Wolf
2018-05-25 16:33 ` [Qemu-devel] [PATCH 04/14] block/create: Make x-blockdev-create a job Kevin Wolf
2018-05-29 11:38   ` Max Reitz
2018-05-29 15:27   ` [Qemu-devel] [Qemu-block] " Jeff Cody
2018-05-29 15:40     ` Kevin Wolf
2018-05-25 16:33 ` [Qemu-devel] [PATCH 05/14] qemu-iotests: Add VM.get_qmp_events_filtered() Kevin Wolf
2018-05-29 11:41   ` Max Reitz
2018-05-25 16:33 ` [Qemu-devel] [PATCH 06/14] qemu-iotests: Add VM.qmp_log() Kevin Wolf
2018-05-29 11:48   ` Max Reitz
2018-05-29 12:12     ` Kevin Wolf
2018-05-29 12:15       ` Max Reitz
2018-05-29 12:39         ` Kevin Wolf
2018-05-29 12:41           ` Max Reitz
2018-05-29 18:31   ` [Qemu-devel] [Qemu-block] " Jeff Cody
2018-05-25 16:33 ` [Qemu-devel] [PATCH 07/14] qemu-iotests: Add iotests.img_info_log() Kevin Wolf
2018-05-29 11:56   ` Max Reitz
2018-05-25 16:33 ` [Qemu-devel] [PATCH 08/14] qemu-iotests: Rewrite 206 for blockdev-create job Kevin Wolf
2018-05-29 12:27   ` Max Reitz
2018-05-29 18:49     ` Kevin Wolf
2018-05-25 16:33 ` [Qemu-devel] [PATCH 09/14] qemu-iotests: Rewrite 207 " Kevin Wolf
2018-05-29 12:44   ` Max Reitz
2018-05-29 12:47   ` Max Reitz
2018-05-29 17:52   ` [Qemu-devel] [Qemu-block] " Jeff Cody
2018-05-25 16:33 ` [Qemu-devel] [PATCH 10/14] qemu-iotests: Rewrite 210 " Kevin Wolf
2018-05-29 13:02   ` Max Reitz
2018-05-29 18:23   ` [Qemu-devel] [Qemu-block] " Jeff Cody
2018-05-25 16:33 ` [Qemu-devel] [PATCH 11/14] qemu-iotests: Rewrite 211 " Kevin Wolf
2018-05-29 13:12   ` Max Reitz
2018-05-25 16:33 ` [Qemu-devel] [PATCH 12/14] qemu-iotests: Rewrite 212 " Kevin Wolf
2018-05-29 13:21   ` Max Reitz
2018-05-25 16:33 ` [Qemu-devel] [PATCH 13/14] qemu-iotests: Rewrite 213 " Kevin Wolf
2018-05-29 13:27   ` Max Reitz
2018-05-25 16:33 ` [Qemu-devel] [PATCH 14/14] block/create: Mark blockdev-create stable Kevin Wolf
2018-05-29 13:30   ` Max Reitz
2018-05-29 18:25   ` [Qemu-devel] [Qemu-block] " Jeff Cody
2018-05-25 16:52 ` [Qemu-devel] [PATCH 00/14] block: Make blockdev-create a job and stable API no-reply
2018-05-25 18:13 ` Eric Blake
2018-05-28  8:42   ` Kevin Wolf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.