aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-05-31 09:40:19 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-05-31 09:40:19 +0100
commitfe817a8a0d4a2face895f692a7e061f0c98412b9 (patch)
tree55a28d5f5ba6aa569edb27a2efe91ff3852a5695
parentb5725385d17c876a12aa176a4a436d32d34ed06d (diff)
parent3fb588a0f2c006122c34e1960a15c87ae2b927eb (diff)
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches: - Add blockdev-create job - qcow2: Silence Coverity false positive # gpg: Signature made Wed 30 May 2018 16:55:31 BST # gpg: using RSA key 7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: block/create: Mark blockdev-create stable qemu-iotests: Rewrite 213 for blockdev-create job qemu-iotests: Rewrite 212 for blockdev-create job qemu-iotests: Rewrite 211 for blockdev-create job qemu-iotests: Rewrite 210 for blockdev-create job qemu-iotests: Rewrite 207 for blockdev-create job qemu-iotests: Rewrite 206 for blockdev-create job qemu-iotests: iotests.py helper for non-file protocols qemu-iotests: Add VM.run_job() qemu-iotests: Add iotests.img_info_log() qemu-iotests: Add VM.qmp_log() qemu-iotests: Add VM.get_qmp_events_filtered() block/create: Make x-blockdev-create a job job: Add error message for failing jobs vhdx: Fix vhdx_co_create() return value vdi: Fix vdi_co_do_create() return value qcow2: Fix Coverity warning when calculating the refcount cache size Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--block/backup.c2
-rw-r--r--block/commit.c2
-rw-r--r--block/create.c67
-rw-r--r--block/mirror.c2
-rw-r--r--block/qcow2.c5
-rw-r--r--block/stream.c2
-rw-r--r--block/vdi.c1
-rw-r--r--block/vhdx.c2
-rw-r--r--include/qemu/job.h7
-rw-r--r--job-qmp.c9
-rw-r--r--job.c16
-rw-r--r--qapi/block-core.json18
-rw-r--r--qapi/job.json4
-rwxr-xr-xtests/qemu-iotests/206680
-rw-r--r--tests/qemu-iotests/206.out253
-rwxr-xr-xtests/qemu-iotests/207440
-rw-r--r--tests/qemu-iotests/207.out107
-rwxr-xr-xtests/qemu-iotests/210393
-rw-r--r--tests/qemu-iotests/210.out197
-rwxr-xr-xtests/qemu-iotests/211381
-rw-r--r--tests/qemu-iotests/211.out133
-rwxr-xr-xtests/qemu-iotests/212483
-rw-r--r--tests/qemu-iotests/212.out191
-rwxr-xr-xtests/qemu-iotests/213520
-rw-r--r--tests/qemu-iotests/213.out208
-rw-r--r--tests/qemu-iotests/iotests.py78
-rw-r--r--tests/test-bdrv-drain.c2
-rw-r--r--tests/test-blockjob-txn.c2
-rw-r--r--tests/test-blockjob.c2
29 files changed, 1981 insertions, 2226 deletions
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/create.c b/block/create.c
index 8bd8a03719..915cd41bcc 100644
--- a/block/create.c
+++ b/block/create.c
@@ -24,28 +24,51 @@
#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;
+
+ job_progress_set_remaining(&s->common, 1);
+ s->ret = s->drv->bdrv_co_create(s->opts, &s->err);
+ job_progress_update(&s->common, 1);
+
+ 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_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. */
@@ -55,22 +78,24 @@ void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)
return;
}
- /* Call callback if it exists */
+ /* Error out if the driver doesn't support .bdrv_co_create */
if (!drv->bdrv_co_create) {
error_setg(errp, "Driver does not support 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 */
+ /* TODO Running in the main context. Block drivers need to error out or add
+ * locking when they use a BDS in a different AioContext. */
+ 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/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/qcow2.c b/block/qcow2.c
index 6d532470a8..a007dc4246 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -768,6 +768,7 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
BDRVQcow2State *s = bs->opaque;
uint64_t combined_cache_size;
bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set;
+ int min_refcount_cache = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
combined_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_CACHE_SIZE);
l2_cache_size_set = qemu_opt_get(opts, QCOW2_OPT_L2_CACHE_SIZE);
@@ -804,8 +805,6 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
} else {
uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE;
uint64_t max_l2_cache = virtual_disk_size / (s->cluster_size / 8);
- uint64_t min_refcount_cache =
- (uint64_t) MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
/* Assign as much memory as possible to the L2 cache, and
* use the remainder for the refcount cache */
@@ -825,7 +824,7 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
* s->cluster_size);
}
if (!refcount_cache_size_set) {
- *refcount_cache_size = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size;
+ *refcount_cache_size = min_refcount_cache;
}
}
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/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);
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);
diff --git a/include/qemu/job.h b/include/qemu/job.h
index 8c8badf75e..1d820530fa 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, and only 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/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..84e140238b 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);
}
@@ -660,6 +661,9 @@ static void job_update_rc(Job *job)
job->ret = -ECANCELED;
}
if (job->ret) {
+ if (!job->error) {
+ job->error = g_strdup(strerror(-job->ret));
+ }
job_state_transition(job, JOB_STATUS_ABORTING);
}
}
@@ -782,6 +786,7 @@ static int job_prepare(Job *job)
{
if (job->ret == 0 && job->driver->prepare) {
job->ret = job->driver->prepare(job);
+ job_update_rc(job);
}
return job->ret;
}
@@ -855,10 +860,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 +888,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 {
diff --git a/qapi/block-core.json b/qapi/block-core.json
index ad66ad6f80..4b1de474a9 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -4011,16 +4011,20 @@
} }
##
-# @x-blockdev-create:
+# @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 }
+{ 'command': 'blockdev-create',
+ 'data': { 'job-id': 'str',
+ 'options': 'BlockdevCreateOptions' } }
##
# @blockdev-open-tray:
diff --git a/qapi/job.json b/qapi/job.json
index 970124de76..17d10037c4 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 "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/tests/qemu-iotests/206 b/tests/qemu-iotests/206
index 0a18b2b19a..128c334c7c 100755
--- a/tests/qemu-iotests/206
+++ b/tests/qemu-iotests/206
@@ -1,9 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env python
#
# Test qcow2 and file image creation
#
# Copyright (C) 2018 Red Hat, Inc.
#
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -18,419 +20,263 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# creator
-owner=kwolf@redhat.com
-
-seq=`basename $0`
-echo "QA output created by $seq"
-
-here=`pwd`
-status=1 # failure is the default!
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-
-_supported_fmt qcow2
-_supported_proto file
-_supported_os Linux
-
-function do_run_qemu()
-{
- echo Testing: "$@"
- $QEMU -nographic -qmp stdio -serial none "$@"
- echo
-}
-
-function run_qemu()
-{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
- | _filter_qemu | _filter_imgfmt \
- | _filter_actual_image_size
-}
-
-echo
-echo "=== Successful image creation (defaults) ==="
-echo
-
-size=$((128 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "blockdev-add",
- "arguments": {
- "driver": "file",
- "node-name": "imgfile",
- "filename": "$TEST_IMG"
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "imgfile",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific
-
-echo
-echo "=== Successful image creation (inline blockdev-add, explicit defaults) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((64 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0,
- "preallocation": "off",
- "nocow": false
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "version": "v3",
- "cluster-size": 65536,
- "preallocation": "off",
- "lazy-refcounts": false,
- "refcount-bits": 16
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific
-
-echo
-echo "=== Successful image creation (v3 non-default options) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((32 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0,
- "preallocation": "falloc",
- "nocow": true
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "version": "v3",
- "cluster-size": 2097152,
- "preallocation": "metadata",
- "lazy-refcounts": true,
- "refcount-bits": 1
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific
-
-echo
-echo "=== Successful image creation (v2 non-default options) ==="
-echo
-
-mv $TEST_IMG $TEST_IMG.base
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "backing-file": "$TEST_IMG.base",
- "backing-fmt": "qcow2",
- "version": "v2",
- "cluster-size": 512
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific
-
-echo
-echo "=== Successful image creation (encrypted) ==="
-echo
-
-run_qemu -object secret,id=keysec0,data="foo" <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "encrypt": {
- "format": "luks",
- "key-secret": "keysec0",
- "cipher-alg": "twofish-128",
- "cipher-mode": "ctr",
- "ivgen-alg": "plain64",
- "ivgen-hash-alg": "md5",
- "hash-alg": "sha1",
- "iter-time": 10
- }
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Invalid BlockdevRef ==="
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "this doesn't exist",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-
-echo
-echo "=== Invalid sizes ==="
-echo
-
-# TODO Negative image sizes aren't handled correctly, but this is a problem
-# with QAPI's implementation of the 'size' type and affects other commands as
-# well. Once this is fixed, we may want to add a test case here.
-
-# 1. Misaligned image size
-# 2. 2^64 - 512
-# 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
-# 4. 2^63 - 512 (generally valid, but qcow2 can't handle images this size)
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 1234
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 18446744073709551104
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 9223372036854775808
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 9223372036854775296
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Invalid version ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "version": "v1"
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "version": "v2",
- "lazy-refcounts": true
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "version": "v2",
- "refcount-bits": 8
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Invalid backing file options ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "backing-file": "/dev/null",
- "preallocation": "full"
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "backing-fmt": "$IMGFMT"
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Invalid cluster size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 1234
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 128
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 4194304
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 281474976710656,
- "cluster-size": 512
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Invalid refcount width ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "refcount-bits": 128
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "refcount-bits": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "refcount-bits": 7
- }
-}
-{ "execute": "quit" }
-EOF
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
+import iotests
+from iotests import imgfmt
+
+iotests.verify_image_format(supported_fmts=['qcow2'])
+
+def blockdev_create(vm, options):
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+
+ if 'return' in result:
+ assert result['return'] == {}
+ vm.run_job('job0')
+ iotests.log("")
+
+with iotests.FilePath('t.qcow2') as disk_path, \
+ iotests.FilePath('t.qcow2.base') as backing_path, \
+ iotests.VM() as vm:
+
+ vm.add_object('secret,id=keysec0,data=foo')
+
+ #
+ # Successful image creation (defaults)
+ #
+ iotests.log("=== Successful image creation (defaults) ===")
+ iotests.log("")
+
+ size = 128 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
+ node_name='imgfile')
+
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'size': size })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Successful image creation (inline blockdev-add, explicit defaults)
+ #
+ iotests.log("=== Successful image creation (inline blockdev-add, explicit defaults) ===")
+ iotests.log("")
+
+ # Choose a different size to show that we got a new image
+ size = 64 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0,
+ 'preallocation': 'off',
+ 'nocow': False })
+
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'version': 'v3',
+ 'cluster-size': 65536,
+ 'preallocation': 'off',
+ 'lazy-refcounts': False,
+ 'refcount-bits': 16 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Successful image creation (v3 non-default options)
+ #
+ iotests.log("=== Successful image creation (v3 non-default options) ===")
+ iotests.log("")
+
+ # Choose a different size to show that we got a new image
+ size = 32 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0,
+ 'preallocation': 'falloc',
+ 'nocow': True })
+
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'version': 'v3',
+ 'cluster-size': 2097152,
+ 'preallocation': 'metadata',
+ 'lazy-refcounts': True,
+ 'refcount-bits': 1 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Successful image creation (v2 non-default options)
+ #
+ iotests.log("=== Successful image creation (v2 non-default options) ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'backing-file': backing_path,
+ 'backing-fmt': 'qcow2',
+ 'version': 'v2',
+ 'cluster-size': 512 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Successful image creation (encrypted)
+ #
+ iotests.log("=== Successful image creation (encrypted) ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'encrypt': {
+ 'format': 'luks',
+ 'key-secret': 'keysec0',
+ 'cipher-alg': 'twofish-128',
+ 'cipher-mode': 'ctr',
+ 'ivgen-alg': 'plain64',
+ 'ivgen-hash-alg': 'md5',
+ 'hash-alg': 'sha1',
+ 'iter-time': 10,
+ }})
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Invalid BlockdevRef
+ #
+ iotests.log("=== Invalid BlockdevRef ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Invalid sizes
+ #
+ iotests.log("=== Invalid sizes ===")
+
+ # TODO Negative image sizes aren't handled correctly, but this is a problem
+ # with QAPI's implementation of the 'size' type and affects other commands
+ # as well. Once this is fixed, we may want to add a test case here.
+ #
+ # 1. Misaligned image size
+ # 2. 2^64 - 512
+ # 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
+ # 4. 2^63 - 512 (generally valid, but qcow2 can't handle images this size)
+
+ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
+
+ vm.launch()
+ for size in [ 1234, 18446744073709551104, 9223372036854775808,
+ 9223372036854775296 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Invalid version
+ #
+ iotests.log("=== Invalid version ===")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'version': 'v1' })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'version': 'v2',
+ 'lazy-refcounts': True })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'version': 'v2',
+ 'refcount-bits': 8 })
+ vm.shutdown()
+
+ #
+ # Invalid backing file options
+ #
+ iotests.log("=== Invalid backing file options ===")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'backing-file': '/dev/null',
+ 'preallocation': 'full' })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'backing-fmt': imgfmt })
+ vm.shutdown()
+
+ #
+ # Invalid cluster size
+ #
+ iotests.log("=== Invalid cluster size ===")
+
+ vm.launch()
+ for csize in [ 1234, 128, 4194304, 0 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'cluster-size': csize })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 281474976710656,
+ 'cluster-size': 512 })
+ vm.shutdown()
+
+ #
+ # Invalid refcount width
+ #
+ iotests.log("=== Invalid refcount width ===")
+
+ vm.launch()
+ for refcount_bits in [ 128, 0, 7 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'refcount-bits': refcount_bits })
+ vm.shutdown()
diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out
index 042342ae9d..789eebe57b 100644
--- a/tests/qemu-iotests/206.out
+++ b/tests/qemu-iotests/206.out
@@ -1,17 +1,18 @@
-QA output created by 206
-
=== Successful image creation (defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}
+{u'return': {}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 128M (134217728 bytes)
cluster_size: 65536
@@ -23,15 +24,17 @@ Format specific information:
=== Successful image creation (inline blockdev-add, explicit defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: TEST_IMG
file format: IMGFMT
virtual size: 64M (67108864 bytes)
cluster_size: 65536
@@ -43,15 +46,17 @@ Format specific information:
=== Successful image creation (v3 non-default options) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 32M (33554432 bytes)
cluster_size: 2097152
@@ -63,19 +68,21 @@ Format specific information:
=== Successful image creation (v2 non-default options) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'backing-file': 'TEST_DIR/PID-t.qcow2.base', 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: TEST_IMG
file format: IMGFMT
virtual size: 32M (33554432 bytes)
cluster_size: 512
-backing file: TEST_DIR/t.IMGFMT.base
+backing file: TEST_IMG.base
backing file format: IMGFMT
Format specific information:
compat: 0.10
@@ -83,16 +90,16 @@ Format specific information:
=== Successful image creation (encrypted) ===
-Testing: -object secret,id=keysec0,data=foo
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'encrypt': {'key-secret': 'keysec0', 'iter-time': 10, 'cipher-mode': 'ctr', 'ivgen-hash-alg': 'md5', 'cipher-alg': 'twofish-128', 'format': 'luks', 'ivgen-alg': 'plain64', 'hash-alg': 'sha1'}, 'driver': 'qcow2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 32M (33554432 bytes)
+encrypted: yes
+cluster_size: 65536
Format specific information:
compat: 1.1
lazy refcounts: false
@@ -101,13 +108,13 @@ Format specific information:
ivgen alg: plain64
hash alg: sha1
cipher alg: twofish-128
- uuid: 00000000-0000-0000-0000-000000000000
+ uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
format: luks
cipher mode: ctr
slots:
[0]:
active: true
- iters: 1024
+ iters: XXX
key offset: 4096
stripes: 4000
[1]:
@@ -132,78 +139,118 @@ Format specific information:
active: false
key offset: 462848
payload offset: 528384
- master key iters: 1024
+ master key iters: XXX
corrupt: false
=== Invalid BlockdevRef ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': "this doesn't exist", 'size': 33554432}}}
+{u'return': {}}
+Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Invalid sizes ===
-
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Image size must be a multiple of 512 bytes"}}
-{"error": {"class": "GenericError", "desc": "Could not resize image: Image size cannot be negative"}}
-{"error": {"class": "GenericError", "desc": "Could not resize image: Image size cannot be negative"}}
-{"error": {"class": "GenericError", "desc": "Could not resize image: Failed to grow the L1 table: File too large"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 1234}}}
+{u'return': {}}
+Job failed: Image size must be a multiple of 512 bytes
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 18446744073709551104L}}}
+{u'return': {}}
+Job failed: Could not resize image: Image size cannot be negative
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775808L}}}
+{u'return': {}}
+Job failed: Could not resize image: Image size cannot be negative
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775296}}}
+{u'return': {}}
+Job failed: Could not resize image: Failed to grow the L1 table: File too large
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Invalid version ===
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'version': 'v1', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter 'v1'"}}
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}}
-{"error": {"class": "GenericError", "desc": "Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)"}}
-{"error": {"class": "GenericError", "desc": "Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'lazy-refcounts': True, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 8, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater)
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Invalid backing file options ===
-
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Backing file and preallocation cannot be used at the same time"}}
-{"error": {"class": "GenericError", "desc": "Backing format cannot be used without backing file"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'full', 'driver': 'qcow2', 'backing-file': '/dev/null', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Backing file and preallocation cannot be used at the same time
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'backing-fmt': 'qcow2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Backing format cannot be used without backing file
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Invalid cluster size ===
-
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}}
-{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}}
-{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}}
-{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}}
-{"error": {"class": "GenericError", "desc": "Could not resize image: Failed to grow the L1 table: File too large"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size must be a power of two between 512 and 2048k
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size must be a power of two between 512 and 2048k
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4194304, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size must be a power of two between 512 and 2048k
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size must be a power of two between 512 and 2048k
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'qcow2', 'file': 'node0', 'size': 281474976710656}}}
+{u'return': {}}
+Job failed: Could not resize image: Failed to grow the L1 table: File too large
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Invalid refcount width ===
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Refcount width must be a power of two and may not exceed 64 bits
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Refcount width must be a power of two and may not exceed 64 bits
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 7, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Refcount width must be a power of two and may not exceed 64 bits
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}}
-{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}}
-{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
-*** done
diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207
index f5c77852d1..444ae233ae 100755
--- a/tests/qemu-iotests/207
+++ b/tests/qemu-iotests/207
@@ -1,9 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env python
#
# Test ssh image creation
#
# Copyright (C) 2018 Red Hat, Inc.
#
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -18,244 +20,198 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# creator
-owner=kwolf@redhat.com
-
-seq=`basename $0`
-echo "QA output created by $seq"
-
-here=`pwd`
-status=1 # failure is the default!
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-
-_supported_fmt raw
-_supported_proto ssh
-_supported_os Linux
-
-function do_run_qemu()
-{
- echo Testing: "$@"
- $QEMU -nographic -qmp stdio -serial none "$@"
- echo
-}
-
-function run_qemu()
-{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
- | _filter_qemu | _filter_imgfmt \
- | _filter_actual_image_size
-}
-
-echo
-echo "=== Successful image creation (defaults) ==="
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "$TEST_IMG_FILE",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- }
- },
- "size": 4194304
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-echo
-TEST_IMG=$TEST_IMG_FILE _img_info | _filter_img_info
-
-echo
-echo "=== Test host-key-check options ==="
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "$TEST_IMG_FILE",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- },
- "host-key-check": {
- "mode": "none"
- }
- },
- "size": 8388608
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "$TEST_IMG_FILE",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- },
- "host-key-check": {
- "mode": "known_hosts"
- }
- },
- "size": 4194304
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-
-key=$(ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" |
- cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1)
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "$TEST_IMG_FILE",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- },
- "host-key-check": {
- "mode": "hash",
- "type": "md5",
- "hash": "wrong"
- }
- },
- "size": 8388608
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "$TEST_IMG_FILE",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- },
- "host-key-check": {
- "mode": "hash",
- "type": "md5",
- "hash": "$key"
- }
- },
- "size": 8388608
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-
-key=$(ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" |
- cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1)
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "$TEST_IMG_FILE",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- },
- "host-key-check": {
- "mode": "hash",
- "type": "sha1",
- "hash": "wrong"
- }
- },
- "size": 4194304
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "$TEST_IMG_FILE",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- },
- "host-key-check": {
- "mode": "hash",
- "type": "sha1",
- "hash": "$key"
- }
- },
- "size": 4194304
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-echo
-echo "=== Invalid path and user ==="
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "/this/is/not/an/existing/path",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- }
- },
- "size": 4194304
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "ssh",
- "location": {
- "path": "$TEST_IMG_FILE",
- "user": "invalid user",
- "server": {
- "host": "127.0.0.1",
- "port": "22"
- }
- },
- "size": 4194304
- }
-}
-{ "execute": "quit" }
-EOF
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
+import iotests
+import subprocess
+import re
+
+iotests.verify_image_format(supported_fmts=['raw'])
+iotests.verify_protocol(supported=['ssh'])
+
+def filter_hash(msg):
+ return re.sub("'hash': '[0-9a-f]+'", "'hash': HASH", msg)
+
+def blockdev_create(vm, options):
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
+ filters=[iotests.filter_testfiles, filter_hash])
+
+ if 'return' in result:
+ assert result['return'] == {}
+ vm.run_job('job0')
+ iotests.log("")
+
+with iotests.FilePath('t.img') as disk_path, \
+ iotests.VM() as vm:
+
+ remote_path = iotests.remote_filename(disk_path)
+
+ #
+ # Successful image creation (defaults)
+ #
+ iotests.log("=== Successful image creation (defaults) ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': disk_path,
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ }
+ },
+ 'size': 4194304 })
+ vm.shutdown()
+
+ iotests.img_info_log(remote_path, filter_path=disk_path)
+ iotests.log("")
+ iotests.img_info_log(disk_path)
+
+ #
+ # Test host-key-check options
+ #
+ iotests.log("=== Test host-key-check options ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': disk_path,
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ },
+ 'host-key-check': {
+ 'mode': 'none'
+ }
+ },
+ 'size': 8388608 })
+ vm.shutdown()
+
+ iotests.img_info_log(remote_path, filter_path=disk_path)
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': disk_path,
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ },
+ 'host-key-check': {
+ 'mode': 'known_hosts'
+ }
+ },
+ 'size': 4194304 })
+ vm.shutdown()
+
+ iotests.img_info_log(remote_path, filter_path=disk_path)
+
+ md5_key = subprocess.check_output(
+ 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
+ 'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1',
+ shell=True).rstrip()
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': disk_path,
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ },
+ 'host-key-check': {
+ 'mode': 'hash',
+ 'type': 'md5',
+ 'hash': 'wrong',
+ }
+ },
+ 'size': 2097152 })
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': disk_path,
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ },
+ 'host-key-check': {
+ 'mode': 'hash',
+ 'type': 'md5',
+ 'hash': md5_key,
+ }
+ },
+ 'size': 8388608 })
+ vm.shutdown()
+
+ iotests.img_info_log(remote_path, filter_path=disk_path)
+
+ sha1_key = subprocess.check_output(
+ 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' +
+ 'cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1',
+ shell=True).rstrip()
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': disk_path,
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ },
+ 'host-key-check': {
+ 'mode': 'hash',
+ 'type': 'sha1',
+ 'hash': 'wrong',
+ }
+ },
+ 'size': 2097152 })
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': disk_path,
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ },
+ 'host-key-check': {
+ 'mode': 'hash',
+ 'type': 'sha1',
+ 'hash': sha1_key,
+ }
+ },
+ 'size': 4194304 })
+ vm.shutdown()
+
+ iotests.img_info_log(remote_path, filter_path=disk_path)
+
+ #
+ # Invalid path and user
+ #
+ iotests.log("=== Invalid path and user ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': '/this/is/not/an/existing/path',
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ },
+ 'host-key-check': {
+ 'mode': 'none'
+ }
+ },
+ 'size': 4194304 })
+ blockdev_create(vm, { 'driver': 'ssh',
+ 'location': {
+ 'path': disk_path,
+ 'user': 'invalid user',
+ 'server': {
+ 'host': '127.0.0.1',
+ 'port': '22'
+ },
+ 'host-key-check': {
+ 'mode': 'none'
+ }
+ },
+ 'size': 4194304 })
+ vm.shutdown()
diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out
index 417deee970..078b7e63cb 100644
--- a/tests/qemu-iotests/207.out
+++ b/tests/qemu-iotests/207.out
@@ -1,75 +1,80 @@
-QA output created by 207
-
=== Successful image creation (defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
-image: TEST_DIR/t.IMGFMT
+
+image: TEST_IMG
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
=== Test host-key-check options ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 8.0M (8388608 bytes)
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'known_hosts'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "remote host key does not match host_key_check 'wrong'"}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}}
+{u'return': {}}
+Job failed: remote host key does not match host_key_check 'wrong'
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 8.0M (8388608 bytes)
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "remote host key does not match host_key_check 'wrong'"}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}}
+{u'return': {}}
+Job failed: remote host key does not match host_key_check 'wrong'
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
=== Invalid path and user ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)"}}
-{"error": {"class": "GenericError", "desc": "failed to authenticate using publickey authentication and the identities held by your ssh-agent"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': '/this/is/not/an/existing/path', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{u'return': {}}
+Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'user': 'invalid user', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
+{u'return': {}}
+Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-*** done
diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210
index e607c0d296..d142841e2b 100755
--- a/tests/qemu-iotests/210
+++ b/tests/qemu-iotests/210
@@ -1,9 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env python
#
# Test luks and file image creation
#
# Copyright (C) 2018 Red Hat, Inc.
#
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -18,230 +20,165 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# creator
-owner=kwolf@redhat.com
-
-seq=`basename $0`
-echo "QA output created by $seq"
-
-here=`pwd`
-status=1 # failure is the default!
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-
-_supported_fmt luks
-_supported_proto file
-_supported_os Linux
-
-function do_run_qemu()
-{
- echo Testing: "$@"
- $QEMU -nographic -qmp stdio -serial none "$@"
- echo
-}
-
-function run_qemu()
-{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
- | _filter_qemu | _filter_imgfmt \
- | _filter_actual_image_size
-}
-
-echo
-echo "=== Successful image creation (defaults) ==="
-echo
-
-size=$((128 * 1024 * 1024))
-
-run_qemu -object secret,id=keysec0,data="foo" <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG_FILE",
- "size": 0
- }
-}
-{ "execute": "blockdev-add",
- "arguments": {
- "driver": "file",
- "node-name": "imgfile",
- "filename": "$TEST_IMG_FILE"
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "imgfile",
- "key-secret": "keysec0",
- "size": $size,
- "iter-time": 10
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Successful image creation (with non-default options) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((64 * 1024 * 1024))
-
-run_qemu -object secret,id=keysec0,data="foo" <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG_FILE",
- "size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG_FILE"
- },
- "size": $size,
- "key-secret": "keysec0",
- "cipher-alg": "twofish-128",
- "cipher-mode": "ctr",
- "ivgen-alg": "plain64",
- "ivgen-hash-alg": "md5",
- "hash-alg": "sha1",
- "iter-time": 10
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Invalid BlockdevRef ==="
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "this doesn't exist",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Zero size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \
- -object secret,id=keysec0,data="foo" <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "key-secret": "keysec0",
- "size": 0,
- "iter-time": 10
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-
-echo
-echo "=== Invalid sizes ==="
-echo
-
-# TODO Negative image sizes aren't handled correctly, but this is a problem
-# with QAPI's implementation of the 'size' type and affects other commands as
-# well. Once this is fixed, we may want to add a test case here.
-
-# 1. 2^64 - 512
-# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
-# 3. 2^63 - 512 (generally valid, but with the crypto header the file will
-# exceed 63 bits)
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \
- -object secret,id=keysec0,data="foo" <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "key-secret": "keysec0",
- "size": 18446744073709551104
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "key-secret": "keysec0",
- "size": 9223372036854775808
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "key-secret": "keysec0",
- "size": 9223372036854775296
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Resize image with invalid sizes ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \
- -blockdev driver=luks,file=node0,key-secret=keysec0,node-name=node1 \
- -object secret,id=keysec0,data="foo" <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "block_resize",
- "arguments": {
- "node-name": "node1",
- "size": 9223372036854775296
- }
-}
-{ "execute": "block_resize",
- "arguments": {
- "node-name": "node1",
- "size": 9223372036854775808
- }
-}
-{ "execute": "block_resize",
- "arguments": {
- "node-name": "node1",
- "size": 18446744073709551104
- }
-}
-{ "execute": "block_resize",
- "arguments": {
- "node-name": "node1",
- "size": -9223372036854775808
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
+import iotests
+from iotests import imgfmt
+
+iotests.verify_image_format(supported_fmts=['luks'])
+iotests.verify_protocol(supported=['file'])
+
+def blockdev_create(vm, options):
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+
+ if 'return' in result:
+ assert result['return'] == {}
+ vm.run_job('job0')
+ iotests.log("")
+
+with iotests.FilePath('t.luks') as disk_path, \
+ iotests.VM() as vm:
+
+ vm.add_object('secret,id=keysec0,data=foo')
+
+ #
+ # Successful image creation (defaults)
+ #
+ iotests.log("=== Successful image creation (defaults) ===")
+ iotests.log("")
+
+ size = 128 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
+ node_name='imgfile')
+
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'key-secret': 'keysec0',
+ 'size': size,
+ 'iter-time': 10 })
+ vm.shutdown()
+
+ # TODO Proper support for images to be used with imgopts and/or protocols
+ iotests.img_info_log(
+ 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path),
+ filter_path=disk_path,
+ extra_args=['--object', 'secret,id=keysec0,data=foo'],
+ imgopts=True)
+
+ #
+ # Successful image creation (with non-default options)
+ #
+ iotests.log("=== Successful image creation (with non-default options) ===")
+ iotests.log("")
+
+ size = 64 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'key-secret': 'keysec0',
+ 'cipher-alg': 'twofish-128',
+ 'cipher-mode': 'ctr',
+ 'ivgen-alg': 'plain64',
+ 'ivgen-hash-alg': 'md5',
+ 'hash-alg': 'sha1',
+ 'iter-time': 10 })
+ vm.shutdown()
+
+ # TODO Proper support for images to be used with imgopts and/or protocols
+ iotests.img_info_log(
+ 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path),
+ filter_path=disk_path,
+ extra_args=['--object', 'secret,id=keysec0,data=foo'],
+ imgopts=True)
+
+ #
+ # Invalid BlockdevRef
+ #
+ iotests.log("=== Invalid BlockdevRef ===")
+ iotests.log("")
+
+ size = 64 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Zero size
+ #
+ iotests.log("=== Zero size ===")
+ iotests.log("")
+
+ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'key-secret': 'keysec0',
+ 'size': 0,
+ 'iter-time': 10 })
+ vm.shutdown()
+
+ # TODO Proper support for images to be used with imgopts and/or protocols
+ iotests.img_info_log(
+ 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path),
+ filter_path=disk_path,
+ extra_args=['--object', 'secret,id=keysec0,data=foo'],
+ imgopts=True)
+
+ #
+ # Invalid sizes
+ #
+
+ # TODO Negative image sizes aren't handled correctly, but this is a problem
+ # with QAPI's implementation of the 'size' type and affects other commands as
+ # well. Once this is fixed, we may want to add a test case here.
+
+ # 1. 2^64 - 512
+ # 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
+ # 3. 2^63 - 512 (generally valid, but with the crypto header the file will
+ # exceed 63 bits)
+ iotests.log("=== Invalid sizes ===")
+ iotests.log("")
+
+ vm.launch()
+ for size in [ 18446744073709551104, 9223372036854775808, 9223372036854775296 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'key-secret': 'keysec0',
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Resize image with invalid sizes
+ #
+ iotests.log("=== Resize image with invalid sizes ===")
+ iotests.log("")
+
+ vm.add_blockdev('driver=luks,file=node0,key-secret=keysec0,node-name=node1')
+ vm.launch()
+ vm.qmp_log('block_resize', node_name='node1', size=9223372036854775296)
+ vm.qmp_log('block_resize', node_name='node1', size=9223372036854775808)
+ vm.qmp_log('block_resize', node_name='node1', size=18446744073709551104)
+ vm.qmp_log('block_resize', node_name='node1', size=-9223372036854775808)
+ vm.shutdown()
+
+ # TODO Proper support for images to be used with imgopts and/or protocols
+ iotests.img_info_log(
+ 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path),
+ filter_path=disk_path,
+ extra_args=['--object', 'secret,id=keysec0,data=foo'],
+ imgopts=True)
diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out
index 8198f8c829..078ba544a1 100644
--- a/tests/qemu-iotests/210.out
+++ b/tests/qemu-iotests/210.out
@@ -1,29 +1,31 @@
-QA output created by 210
-
=== Successful image creation (defaults) ===
-Testing: -object secret,id=keysec0,data=foo
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}
+{u'return': {}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'imgfile', 'size': 134217728}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"}
+image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT
virtual size: 128M (134217728 bytes)
+encrypted: yes
Format specific information:
ivgen alg: plain64
hash alg: sha256
cipher alg: aes-256
- uuid: 00000000-0000-0000-0000-000000000000
+ uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
cipher mode: xts
slots:
[0]:
active: true
- iters: 1024
+ iters: XXX
key offset: 4096
stripes: 4000
[1]:
@@ -48,31 +50,34 @@ Format specific information:
active: false
key offset: 1810432
payload offset: 2068480
- master key iters: 1024
+ master key iters: XXX
=== Successful image creation (with non-default options) ===
-Testing: -object secret,id=keysec0,data=foo
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'hash-alg': 'sha1', 'cipher-mode': 'ctr', 'cipher-alg': 'twofish-128', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}, 'iter-time': 10, 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'driver': 'luks', 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"}
+image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT
virtual size: 64M (67108864 bytes)
+encrypted: yes
Format specific information:
ivgen alg: plain64
hash alg: sha1
cipher alg: twofish-128
- uuid: 00000000-0000-0000-0000-000000000000
+ uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
cipher mode: ctr
slots:
[0]:
active: true
- iters: 1024
+ iters: XXX
key offset: 4096
stripes: 4000
[1]:
@@ -97,56 +102,130 @@ Format specific information:
active: false
key offset: 462848
payload offset: 528384
- master key iters: 1024
+ master key iters: XXX
=== Invalid BlockdevRef ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'luks', 'file': "this doesn't exist", 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Zero size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -object secret,id=keysec0,data=foo
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'node0', 'size': 0}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"}
+image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT
virtual size: 0 (0 bytes)
+encrypted: yes
+Format specific information:
+ ivgen alg: plain64
+ hash alg: sha256
+ cipher alg: aes-256
+ uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+ cipher mode: xts
+ slots:
+ [0]:
+ active: true
+ iters: XXX
+ key offset: 4096
+ stripes: 4000
+ [1]:
+ active: false
+ key offset: 262144
+ [2]:
+ active: false
+ key offset: 520192
+ [3]:
+ active: false
+ key offset: 778240
+ [4]:
+ active: false
+ key offset: 1036288
+ [5]:
+ active: false
+ key offset: 1294336
+ [6]:
+ active: false
+ key offset: 1552384
+ [7]:
+ active: false
+ key offset: 1810432
+ payload offset: 2068480
+ master key iters: XXX
=== Invalid sizes ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -object secret,id=keysec0,data=foo
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
-{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
-{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 18446744073709551104L}}}
+{u'return': {}}
+Job failed: The requested file size is too large
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775808L}}}
+{u'return': {}}
+Job failed: The requested file size is too large
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775296}}}
+{u'return': {}}
+Job failed: The requested file size is too large
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Resize image with invalid sizes ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -blockdev driver=IMGFMT,file=node0,key-secret=keysec0,node-name=node1 -object secret,id=keysec0,data=foo
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "The requested file size is too large"}}
-{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
-{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}}
-{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
-image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"}
+{'execute': 'block_resize', 'arguments': {'size': 9223372036854775296, 'node_name': 'node1'}}
+{u'error': {u'class': u'GenericError', u'desc': u'The requested file size is too large'}}
+{'execute': 'block_resize', 'arguments': {'size': 9223372036854775808L, 'node_name': 'node1'}}
+{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}}
+{'execute': 'block_resize', 'arguments': {'size': 18446744073709551104L, 'node_name': 'node1'}}
+{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}}
+{'execute': 'block_resize', 'arguments': {'size': -9223372036854775808, 'node_name': 'node1'}}
+{u'error': {u'class': u'GenericError', u'desc': u"Parameter 'size' expects a >0 size"}}
+image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT
virtual size: 0 (0 bytes)
-*** done
+encrypted: yes
+Format specific information:
+ ivgen alg: plain64
+ hash alg: sha256
+ cipher alg: aes-256
+ uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
+ cipher mode: xts
+ slots:
+ [0]:
+ active: true
+ iters: XXX
+ key offset: 4096
+ stripes: 4000
+ [1]:
+ active: false
+ key offset: 262144
+ [2]:
+ active: false
+ key offset: 520192
+ [3]:
+ active: false
+ key offset: 778240
+ [4]:
+ active: false
+ key offset: 1036288
+ [5]:
+ active: false
+ key offset: 1294336
+ [6]:
+ active: false
+ key offset: 1552384
+ [7]:
+ active: false
+ key offset: 1810432
+ payload offset: 2068480
+ master key iters: XXX
+
diff --git a/tests/qemu-iotests/211 b/tests/qemu-iotests/211
index 1edec26517..7b7985db6c 100755
--- a/tests/qemu-iotests/211
+++ b/tests/qemu-iotests/211
@@ -1,9 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env python
#
# Test VDI and file image creation
#
# Copyright (C) 2018 Red Hat, Inc.
#
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -18,229 +20,154 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# creator
-owner=kwolf@redhat.com
-
-seq=`basename $0`
-echo "QA output created by $seq"
-
-here=`pwd`
-status=1 # failure is the default!
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-
-_supported_fmt vdi
-_supported_proto file
-_supported_os Linux
-
-function do_run_qemu()
-{
- echo Testing: "$@"
- $QEMU -nographic -qmp stdio -serial none "$@"
- echo
-}
-
-function run_qemu()
-{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
- | _filter_qemu | _filter_imgfmt \
- | _filter_actual_image_size
-}
-
-echo
-echo "=== Successful image creation (defaults) ==="
-echo
-
-size=$((128 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "blockdev-add",
- "arguments": {
- "driver": "file",
- "node-name": "imgfile",
- "filename": "$TEST_IMG"
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "imgfile",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
-
-echo
-echo "=== Successful image creation (explicit defaults) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((64 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "preallocation": "off"
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
-
-echo
-echo "=== Successful image creation (with non-default options) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((32 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "preallocation": "metadata"
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map
-
-echo
-echo "=== Invalid BlockdevRef ==="
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "this doesn't exist",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Zero size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 0
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-echo
-echo "=== Maximum size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 562949819203584
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-echo
-echo "=== Invalid sizes ==="
-echo
-
-# TODO Negative image sizes aren't handled correctly, but this is a problem
-# with QAPI's implementation of the 'size' type and affects other commands as
-# well. Once this is fixed, we may want to add a test case here.
-
-# 1. 2^64 - 512
-# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
-# 3. 0x1fffff8000001 (one byte more than maximum image size for VDI)
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 18446744073709551104
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 9223372036854775808
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 562949819203585
- }
-}
-{ "execute": "quit" }
-EOF
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
+import iotests
+from iotests import imgfmt
+
+iotests.verify_image_format(supported_fmts=['vdi'])
+iotests.verify_protocol(supported=['file'])
+
+def blockdev_create(vm, options):
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+
+ if 'return' in result:
+ assert result['return'] == {}
+ vm.run_job('job0')
+ iotests.log("")
+
+with iotests.FilePath('t.vdi') as disk_path, \
+ iotests.VM() as vm:
+
+ #
+ # Successful image creation (defaults)
+ #
+ iotests.log("=== Successful image creation (defaults) ===")
+ iotests.log("")
+
+ size = 128 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
+ node_name='imgfile')
+
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'size': size })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+ iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path))
+
+ #
+ # Successful image creation (explicit defaults)
+ #
+ iotests.log("=== Successful image creation (explicit defaults) ===")
+ iotests.log("")
+
+ size = 64 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'preallocation': 'off' })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+ iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path))
+
+ #
+ # Successful image creation (with non-default options)
+ #
+ iotests.log("=== Successful image creation (with non-default options) ===")
+ iotests.log("")
+
+ size = 32 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'preallocation': 'metadata' })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+ iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path))
+
+ #
+ # Invalid BlockdevRef
+ #
+ iotests.log("=== Invalid BlockdevRef ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Zero size
+ #
+ iotests.log("=== Zero size ===")
+ iotests.log("")
+
+ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 0 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Maximum size
+ #
+ iotests.log("=== Maximum size ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 562949819203584 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Invalid sizes
+ #
+
+ # TODO Negative image sizes aren't handled correctly, but this is a problem
+ # with QAPI's implementation of the 'size' type and affects other commands
+ # as well. Once this is fixed, we may want to add a test case here.
+
+ # 1. 2^64 - 512
+ # 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
+ # 3. 0x1fffff8000001 (one byte more than maximum image size for VDI)
+
+ iotests.log("=== Invalid sizes ===")
+ iotests.log("")
+
+ vm.launch()
+ for size in [ 18446744073709551104, 9223372036854775808, 562949819203585 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size })
+ vm.shutdown()
diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out
index 3247bbaa64..6feaea3978 100644
--- a/tests/qemu-iotests/211.out
+++ b/tests/qemu-iotests/211.out
@@ -1,97 +1,112 @@
-QA output created by 211
-
=== Successful image creation (defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}
+{u'return': {}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 128M (134217728 bytes)
+cluster_size: 1048576
+
[{ "start": 0, "length": 134217728, "depth": 0, "zero": true, "data": false}]
=== Successful image creation (explicit defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: TEST_IMG
file format: IMGFMT
virtual size: 64M (67108864 bytes)
+cluster_size: 1048576
+
[{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}]
=== Successful image creation (with non-default options) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: TEST_IMG
file format: IMGFMT
virtual size: 32M (33554432 bytes)
-[{ "start": 0, "length": 3072, "depth": 0, "zero": false, "data": true, "offset": OFFSET},
-{ "start": 3072, "length": 33551360, "depth": 0, "zero": true, "data": true, "offset": OFFSET}]
+cluster_size: 1048576
-=== Invalid BlockdevRef ===
+[{ "start": 0, "length": 3072, "depth": 0, "zero": false, "data": true, "offset": 1024},
+{ "start": 3072, "length": 33551360, "depth": 0, "zero": true, "data": true, "offset": 4096}]
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+=== Invalid BlockdevRef ===
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': "this doesn't exist", 'size': 33554432}}}
+{u'return': {}}
+Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Zero size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 0 (0 bytes)
+cluster_size: 1048576
=== Maximum size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 512T (562949819203584 bytes)
+cluster_size: 1048576
=== Invalid sizes ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)"}}
-{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000)"}}
-{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000)"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 18446744073709551104L}}}
+{u'return': {}}
+Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 9223372036854775808L}}}
+{u'return': {}}
+Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000)
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203585}}}
+{u'return': {}}
+Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000)
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-*** done
diff --git a/tests/qemu-iotests/212 b/tests/qemu-iotests/212
index e5a1ba77ce..95c8810d83 100755
--- a/tests/qemu-iotests/212
+++ b/tests/qemu-iotests/212
@@ -1,9 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env python
#
# Test parallels and file image creation
#
# Copyright (C) 2018 Red Hat, Inc.
#
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -18,309 +20,176 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# creator
-owner=kwolf@redhat.com
-
-seq=`basename $0`
-echo "QA output created by $seq"
-
-here=`pwd`
-status=1 # failure is the default!
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-
-_supported_fmt parallels
-_supported_proto file
-_supported_os Linux
-
-function do_run_qemu()
-{
- echo Testing: "$@"
- $QEMU -nographic -qmp stdio -serial none "$@"
- echo
-}
-
-function run_qemu()
-{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
- | _filter_qemu | _filter_imgfmt \
- | _filter_actual_image_size
-}
-
-echo
-echo "=== Successful image creation (defaults) ==="
-echo
-
-size=$((128 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "blockdev-add",
- "arguments": {
- "driver": "file",
- "node-name": "imgfile",
- "filename": "$TEST_IMG"
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "imgfile",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Successful image creation (explicit defaults) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((64 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "cluster-size": 1048576
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Successful image creation (with non-default options) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((32 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "cluster-size": 65536
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Invalid BlockdevRef ==="
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "this doesn't exist",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Zero size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 0
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-echo
-echo "=== Maximum size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 4503599627369984
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-echo
-echo "=== Invalid sizes ==="
-echo
-
-# TODO Negative image sizes aren't handled correctly, but this is a problem
-# with QAPI's implementation of the 'size' type and affects other commands as
-# well. Once this is fixed, we may want to add a test case here.
-
-# 1. Misaligned image size
-# 2. 2^64 - 512
-# 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
-# 4. 2^63 - 512 (generally valid, but with the image header the file will
-# exceed 63 bits)
-# 5. 2^52 (512 bytes more than maximum image size)
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 1234
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 18446744073709551104
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 9223372036854775808
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 9223372036854775296
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 4503599627370497
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Invalid cluster size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 1234
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 128
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 4294967296
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 9223372036854775808
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 18446744073709551104
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "cluster-size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 281474976710656,
- "cluster-size": 512
- }
-}
-{ "execute": "quit" }
-EOF
-
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
+import iotests
+from iotests import imgfmt
+
+iotests.verify_image_format(supported_fmts=['parallels'])
+iotests.verify_protocol(supported=['file'])
+
+def blockdev_create(vm, options):
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+
+ if 'return' in result:
+ assert result['return'] == {}
+ vm.run_job('job0')
+ iotests.log("")
+
+with iotests.FilePath('t.parallels') as disk_path, \
+ iotests.VM() as vm:
+
+ #
+ # Successful image creation (defaults)
+ #
+ iotests.log("=== Successful image creation (defaults) ===")
+ iotests.log("")
+
+ size = 128 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
+ node_name='imgfile')
+
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'size': size })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Successful image creation (explicit defaults)
+ #
+ iotests.log("=== Successful image creation (explicit defaults) ===")
+ iotests.log("")
+
+ # Choose a different size to show that we got a new image
+ size = 64 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'cluster-size': 1048576 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Successful image creation (with non-default options)
+ #
+ iotests.log("=== Successful image creation (with non-default options) ===")
+ iotests.log("")
+
+ # Choose a different size to show that we got a new image
+ size = 32 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'cluster-size': 65536 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Invalid BlockdevRef
+ #
+ iotests.log("=== Invalid BlockdevRef ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Zero size
+ #
+ iotests.log("=== Zero size ===")
+ iotests.log("")
+
+ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 0 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Maximum size
+ #
+ iotests.log("=== Maximum size ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 4503599627369984})
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Invalid sizes
+ #
+
+ # TODO Negative image sizes aren't handled correctly, but this is a problem
+ # with QAPI's implementation of the 'size' type and affects other commands
+ # as well. Once this is fixed, we may want to add a test case here.
+
+ # 1. Misaligned image size
+ # 2. 2^64 - 512
+ # 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
+ # 4. 2^63 - 512 (generally valid, but with the image header the file will
+ # exceed 63 bits)
+ # 5. 2^52 (512 bytes more than maximum image size)
+
+ iotests.log("=== Invalid sizes ===")
+ iotests.log("")
+
+ vm.launch()
+ for size in [ 1234, 18446744073709551104, 9223372036854775808,
+ 9223372036854775296, 4503599627370497 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Invalid cluster size
+ #
+ iotests.log("=== Invalid cluster size ===")
+ iotests.log("")
+
+ vm.launch()
+ for csize in [ 1234, 128, 4294967296, 9223372036854775808,
+ 18446744073709551104, 0 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'cluster-size': csize })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 281474976710656,
+ 'cluster-size': 512 })
+ vm.shutdown()
diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out
index 587de6fad0..9150da7a2c 100644
--- a/tests/qemu-iotests/212.out
+++ b/tests/qemu-iotests/212.out
@@ -1,111 +1,156 @@
-QA output created by 212
-
=== Successful image creation (defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}
+{u'return': {}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 128M (134217728 bytes)
=== Successful image creation (explicit defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: TEST_IMG
file format: IMGFMT
virtual size: 64M (67108864 bytes)
=== Successful image creation (with non-default options) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 32M (33554432 bytes)
=== Invalid BlockdevRef ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': "this doesn't exist", 'size': 33554432}}}
+{u'return': {}}
+Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Zero size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 0 (0 bytes)
=== Maximum size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 4096T (4503599627369984 bytes)
=== Invalid sizes ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Image size must be a multiple of 512 bytes"}}
-{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}}
-{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}}
-{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}}
-{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 1234}}}
+{u'return': {}}
+Job failed: Image size must be a multiple of 512 bytes
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 18446744073709551104L}}}
+{u'return': {}}
+Job failed: Image size is too large for this cluster size
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775808L}}}
+{u'return': {}}
+Job failed: Image size is too large for this cluster size
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775296}}}
+{u'return': {}}
+Job failed: Image size is too large for this cluster size
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627370497}}}
+{u'return': {}}
+Job failed: Image size is too large for this cluster size
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Invalid cluster size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Cluster size must be a multiple of 512 bytes"}}
-{"error": {"class": "GenericError", "desc": "Cluster size must be a multiple of 512 bytes"}}
-{"error": {"class": "GenericError", "desc": "Cluster size is too large"}}
-{"error": {"class": "GenericError", "desc": "Cluster size is too large"}}
-{"error": {"class": "GenericError", "desc": "Cluster size is too large"}}
-{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}}
-{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
-*** done
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size must be a multiple of 512 bytes
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size must be a multiple of 512 bytes
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4294967296, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size is too large
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 9223372036854775808L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size is too large
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 18446744073709551104L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Cluster size is too large
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Image size is too large for this cluster size
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'parallels', 'file': 'node0', 'size': 281474976710656}}}
+{u'return': {}}
+Job failed: Image size is too large for this cluster size
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
diff --git a/tests/qemu-iotests/213 b/tests/qemu-iotests/213
index 3a00a0f6d6..4054439e3c 100755
--- a/tests/qemu-iotests/213
+++ b/tests/qemu-iotests/213
@@ -1,9 +1,11 @@
-#!/bin/bash
+#!/usr/bin/env python
#
# Test vhdx and file image creation
#
# Copyright (C) 2018 Red Hat, Inc.
#
+# Creator/Owner: Kevin Wolf <kwolf@redhat.com>
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -18,332 +20,190 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# creator
-owner=kwolf@redhat.com
-
-seq=`basename $0`
-echo "QA output created by $seq"
-
-here=`pwd`
-status=1 # failure is the default!
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-
-_supported_fmt vhdx
-_supported_proto file
-_supported_os Linux
-
-function do_run_qemu()
-{
- echo Testing: "$@"
- $QEMU -nographic -qmp stdio -serial none "$@"
- echo
-}
-
-function run_qemu()
-{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
- | _filter_qemu | _filter_imgfmt \
- | _filter_actual_image_size
-}
-
-echo
-echo "=== Successful image creation (defaults) ==="
-echo
-
-size=$((128 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "blockdev-add",
- "arguments": {
- "driver": "file",
- "node-name": "imgfile",
- "filename": "$TEST_IMG"
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "imgfile",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Successful image creation (explicit defaults) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((64 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "log-size": 1048576,
- "block-size": 8388608,
- "subformat": "dynamic",
- "block-state-zero": true
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Successful image creation (with non-default options) ==="
-echo
-
-# Choose a different size to show that we got a new image
-size=$((32 * 1024 * 1024))
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "file",
- "filename": "$TEST_IMG",
- "size": 0
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG"
- },
- "size": $size,
- "log-size": 8388608,
- "block-size": 268435456,
- "subformat": "fixed",
- "block-state-zero": false
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info --format-specific | _filter_img_info --format-specific
-
-echo
-echo "=== Invalid BlockdevRef ==="
-echo
-
-run_qemu <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "this doesn't exist",
- "size": $size
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Zero size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 0
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-echo
-echo "=== Maximum size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 70368744177664
- }
-}
-{ "execute": "quit" }
-EOF
-
-_img_info | _filter_img_info
-
-echo
-echo "=== Invalid sizes ==="
-echo
-
-# TODO Negative image sizes aren't handled correctly, but this is a problem
-# with QAPI's implementation of the 'size' type and affects other commands as
-# well. Once this is fixed, we may want to add a test case here.
-
-# 1. 2^64 - 512
-# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
-# 3. 2^63 - 512 (generally valid, but with the image header the file will
-# exceed 63 bits)
-# 4. 2^46 + 1 (one byte more than maximum image size)
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 18446744073709551104
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 9223372036854775808
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 9223372036854775296
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 70368744177665
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Invalid block size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "block-size": 1234567
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "block-size": 128
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "block-size": 3145728
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "block-size": 536870912
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "block-size": 0
- }
-}
-{ "execute": "quit" }
-EOF
-
-echo
-echo "=== Invalid log size ==="
-echo
-
-run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF
-{ "execute": "qmp_capabilities" }
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "log-size": 1234567
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "log-size": 128
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "log-size": 4294967296
- }
-}
-{ "execute": "x-blockdev-create",
- "arguments": {
- "driver": "$IMGFMT",
- "file": "node0",
- "size": 67108864,
- "log-size": 0
- }
-}
-{ "execute": "quit" }
-EOF
-
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
+import iotests
+from iotests import imgfmt
+
+iotests.verify_image_format(supported_fmts=['vhdx'])
+iotests.verify_protocol(supported=['file'])
+
+def blockdev_create(vm, options):
+ result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
+
+ if 'return' in result:
+ assert result['return'] == {}
+ vm.run_job('job0')
+ iotests.log("")
+
+with iotests.FilePath('t.vhdx') as disk_path, \
+ iotests.VM() as vm:
+
+ #
+ # Successful image creation (defaults)
+ #
+ iotests.log("=== Successful image creation (defaults) ===")
+ iotests.log("")
+
+ size = 128 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+
+ vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
+ node_name='imgfile')
+
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'imgfile',
+ 'size': size })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Successful image creation (explicit defaults)
+ #
+ iotests.log("=== Successful image creation (explicit defaults) ===")
+ iotests.log("")
+
+ # Choose a different size to show that we got a new image
+ size = 64 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'log-size': 1048576,
+ 'block-size': 8388608,
+ 'subformat': 'dynamic',
+ 'block-state-zero': True })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Successful image creation (with non-default options)
+ #
+ iotests.log("=== Successful image creation (with non-default options) ===")
+ iotests.log("")
+
+ # Choose a different size to show that we got a new image
+ size = 32 * 1024 * 1024
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': 'file',
+ 'filename': disk_path,
+ 'size': 0 })
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': {
+ 'driver': 'file',
+ 'filename': disk_path,
+ },
+ 'size': size,
+ 'log-size': 8388608,
+ 'block-size': 268435456,
+ 'subformat': 'fixed',
+ 'block-state-zero': False })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Invalid BlockdevRef
+ #
+ iotests.log("=== Invalid BlockdevRef ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': "this doesn't exist",
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Zero size
+ #
+ iotests.log("=== Zero size ===")
+ iotests.log("")
+
+ vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 0 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Maximum size
+ #
+ iotests.log("=== Maximum size ===")
+ iotests.log("")
+
+ vm.launch()
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 70368744177664 })
+ vm.shutdown()
+
+ iotests.img_info_log(disk_path)
+
+ #
+ # Invalid sizes
+ #
+
+ # TODO Negative image sizes aren't handled correctly, but this is a problem
+ # with QAPI's implementation of the 'size' type and affects other commands
+ # as well. Once this is fixed, we may want to add a test case here.
+
+ # 1. 2^64 - 512
+ # 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
+ # 3. 2^63 - 512 (generally valid, but with the image header the file will
+ # exceed 63 bits)
+ # 4. 2^46 + 1 (one byte more than maximum image size)
+
+ iotests.log("=== Invalid sizes ===")
+ iotests.log("")
+
+ vm.launch()
+ for size in [ 18446744073709551104, 9223372036854775808,
+ 9223372036854775296, 70368744177665 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': size })
+ vm.shutdown()
+
+ #
+ # Invalid block size
+ #
+ iotests.log("=== Invalid block size ===")
+ iotests.log("")
+
+ vm.launch()
+ for bsize in [ 1234567, 128, 3145728, 536870912, 0 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'block-size': bsize })
+ vm.shutdown()
+
+ #
+ # Invalid log size
+ #
+ iotests.log("=== Invalid log size ===")
+ iotests.log("")
+
+ vm.launch()
+ for lsize in [ 1234567, 128, 4294967296, 0 ]:
+ blockdev_create(vm, { 'driver': imgfmt,
+ 'file': 'node0',
+ 'size': 67108864,
+ 'log-size': lsize })
+ vm.shutdown()
diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out
index 8e8fc29cbc..e1dcd47201 100644
--- a/tests/qemu-iotests/213.out
+++ b/tests/qemu-iotests/213.out
@@ -1,121 +1,169 @@
-QA output created by 213
-
=== Successful image creation (defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}
+{u'return': {}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 128M (134217728 bytes)
+cluster_size: 8388608
=== Successful image creation (explicit defaults) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': True, 'size': 67108864}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+image: TEST_IMG
file format: IMGFMT
virtual size: 64M (67108864 bytes)
+cluster_size: 8388608
=== Successful image creation (with non-default options) ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': False, 'size': 33554432}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 32M (33554432 bytes)
+cluster_size: 268435456
=== Invalid BlockdevRef ===
-Testing:
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}}
+{u'return': {}}
+Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Zero size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 0 (0 bytes)
+cluster_size: 8388608
=== Maximum size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"return": {}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}}
+{u'return': {}}
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
-image: TEST_DIR/t.IMGFMT
+image: TEST_IMG
file format: IMGFMT
virtual size: 64T (70368744177664 bytes)
+cluster_size: 67108864
=== Invalid sizes ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}}
-{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}}
-{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}}
-{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}}
+{u'return': {}}
+Job failed: Image size too large; max of 64TB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775808L}}}
+{u'return': {}}
+Job failed: Image size too large; max of 64TB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775296}}}
+{u'return': {}}
+Job failed: Image size too large; max of 64TB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177665}}}
+{u'return': {}}
+Job failed: Image size too large; max of 64TB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Invalid block size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}}
-{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}}
-{"error": {"class": "GenericError", "desc": "Block size must be a power of two"}}
-{"error": {"class": "GenericError", "desc": "Block size must not exceed 268435456"}}
-{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Block size must be a multiple of 1 MB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 128, 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Block size must be a multiple of 1 MB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 3145728, 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Block size must be a power of two
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 536870912, 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Block size must not exceed 268435456
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 0, 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Block size must be a multiple of 1 MB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
=== Invalid log size ===
-Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
-QMP_VERSION
-{"return": {}}
-{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}}
-{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}}
-{"error": {"class": "GenericError", "desc": "Log size must be smaller than 4 GB"}}
-{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
-
-*** done
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Log size must be a multiple of 1 MB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Log size must be a multiple of 1 MB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 4294967296, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Log size must be smaller than 4 GB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
+{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 0, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
+{u'return': {}}
+Job failed: Log size must be a multiple of 1 MB
+{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
+{u'return': {}}
+
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 28159d837a..fdbdd8b300 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -109,6 +109,20 @@ def qemu_img_pipe(*args):
sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
return subp.communicate()[0]
+def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]):
+ args = [ 'info' ]
+ if imgopts:
+ args.append('--image-opts')
+ else:
+ args += [ '-f', imgfmt ]
+ args += extra_args
+ args.append(filename)
+
+ output = qemu_img_pipe(*args)
+ if not filter_path:
+ filter_path = filename
+ log(filter_img_info(output, filter_path))
+
def qemu_io(*args):
'''Run qemu-io and return the stdout data'''
args = qemu_io_args + list(args)
@@ -206,6 +220,22 @@ def filter_qmp_event(event):
event['timestamp']['microseconds'] = 'USECS'
return event
+def filter_testfiles(msg):
+ prefix = os.path.join(test_dir, "%s-" % (os.getpid()))
+ return msg.replace(prefix, 'TEST_DIR/PID-')
+
+def filter_img_info(output, filename):
+ lines = []
+ for line in output.split('\n'):
+ if 'disk size' in line or 'actual-size' in line:
+ continue
+ line = line.replace(filename, 'TEST_IMG') \
+ .replace(imgfmt, 'IMGFMT')
+ line = re.sub('iters: [0-9]+', 'iters: XXX', line)
+ line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
+ lines.append(line)
+ return '\n'.join(lines)
+
def log(msg, filters=[]):
for flt in filters:
msg = flt(msg)
@@ -281,6 +311,13 @@ def file_path(*names):
return paths[0] if len(paths) == 1 else paths
+def remote_filename(path):
+ if imgproto == 'file':
+ return path
+ elif imgproto == 'ssh':
+ return "ssh://127.0.0.1%s" % (path)
+ else:
+ raise Exception("Protocol %s not supported" % (imgproto))
class VM(qtest.QEMUQtestMachine):
'''A QEMU VM'''
@@ -383,6 +420,37 @@ 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
+
+ def qmp_log(self, cmd, filters=[filter_testfiles], **kwargs):
+ logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
+ log(logmsg, filters)
+ result = self.qmp(cmd, **kwargs)
+ log(str(result), filters)
+ return result
+
+ def run_job(self, job, auto_finalize=True, auto_dismiss=False):
+ while True:
+ for ev in self.get_qmp_events_filtered(wait=True):
+ if ev['event'] == 'JOB_STATUS_CHANGE':
+ status = ev['data']['status']
+ if status == 'aborting':
+ result = self.qmp('query-jobs')
+ for j in result['return']:
+ if j['id'] == job:
+ log('Job failed: %s' % (j['error']))
+ elif status == 'pending' and not auto_finalize:
+ self.qmp_log('job-finalize', id=job)
+ elif status == 'concluded' and not auto_dismiss:
+ self.qmp_log('job-dismiss', id=job)
+ elif status == 'null':
+ return
+ else:
+ iotests.log(ev)
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
@@ -548,6 +616,16 @@ def verify_image_format(supported_fmts=[], unsupported_fmts=[]):
if not_sup or (imgfmt in unsupported_fmts):
notrun('not suitable for this image format: %s' % imgfmt)
+def verify_protocol(supported=[], unsupported=[]):
+ assert not (supported and unsupported)
+
+ if 'generic' in supported:
+ return
+
+ not_sup = supported and (imgproto not in supported)
+ if not_sup or (imgproto in unsupported):
+ notrun('not suitable for this protocol: %s' % imgproto)
+
def verify_platform(supported_oses=['linux']):
if True not in [sys.platform.startswith(x) for x in supported_oses]:
notrun('not suitable for this OS: %s' % sys.platform)
diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
index 2cba63b881..a11c4cfbf2 100644
--- a/tests/test-bdrv-drain.c
+++ b/tests/test-bdrv-drain.c
@@ -498,7 +498,7 @@ typedef struct TestBlockJob {
static void test_job_completed(Job *job, void *opaque)
{
- job_completed(job, 0);
+ job_completed(job, 0, NULL);
}
static void coroutine_fn test_job_start(void *opaque)
diff --git a/tests/test-blockjob-txn.c b/tests/test-blockjob-txn.c
index fce836639a..58d9b87fb2 100644
--- a/tests/test-blockjob-txn.c
+++ b/tests/test-blockjob-txn.c
@@ -34,7 +34,7 @@ static void test_block_job_complete(Job *job, void *opaque)
rc = -ECANCELED;
}
- job_completed(job, rc);
+ job_completed(job, rc, NULL);
bdrv_unref(bs);
}
diff --git a/tests/test-blockjob.c b/tests/test-blockjob.c
index e408d52351..cb42f06e61 100644
--- a/tests/test-blockjob.c
+++ b/tests/test-blockjob.c
@@ -167,7 +167,7 @@ static void cancel_job_completed(Job *job, void *opaque)
{
CancelJob *s = opaque;
s->completed = true;
- job_completed(job, 0);
+ job_completed(job, 0, NULL);
}
static void cancel_job_complete(Job *job, Error **errp)