Block layer patches:

- Add blockdev-create job
 - qcow2: Silence Coverity false positive
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJbDslzAAoJEH8JsnLIjy/WtqwP/2/KV8IeTtit5Vvnvx1XwujH
 ZZ7o/al2kL9xBLROL7Yd9Kx4PlxMbFF3ijEb94zqwZ/aOiysAZNaGoiJccUAYKXx
 b3Vh/iPr2noXEGpmB8lk0I+a6SPnghaP+/rEUj4N6pTh5s1JPZHzULiuP/tajJrX
 yljaQS3pMDDOT2D3VoLMw0nhfhC5tA+i63RNrHShol1VIQCKf9BdrUkzAwTTMmur
 4Amhi9cPEg9v2WalFYymAadr1G+NUu3hO/VXOayw6pBHzyxt/ys2F5pFz7p8QtRB
 eu2iKwxeVm9hSldq3sWnPCfICqcN8PMAmSriKLzK3pl8EeEesy/+hSDIbRpFyhW+
 L+iGnJcS83fc+J5R0VgpgFzU1k68AFEJ4MvwTkd5B/N/AOENXfKG8BJVzzDJ8cwC
 XwigotsLsCZoAJUKiWMSL6bM9/23wcfSGR622D39tXt5CsmIIibfvWun9Jb2YaRq
 2noZrNTwCPpIWIl9cxgpu5T6Nje8xj9lwPc7Tp0dZQTDlMurpOUxwKiRzXqXiPcA
 UnHolgTxswz1kwVHhGgDmSyz6Z5zh8p1hlrtq6al1WKcvQjdAR+Y3wEgPGmSFhmM
 v26+0c9jerQo/8ewHVeO7kRyi6i0CZ7CFUoemxlBD1Lcz1b/p29SxObXtBFpf3wT
 9lS1HGs5yVCvYXZbwotH
 =dxiV
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2018-05-31 09:40:19 +01:00
commit fe817a8a0d
29 changed files with 1777 additions and 2022 deletions

View File

@ -321,7 +321,7 @@ static void backup_complete(Job *job, void *opaque)
{ {
BackupCompleteData *data = opaque; BackupCompleteData *data = opaque;
job_completed(job, data->ret); job_completed(job, data->ret, NULL);
g_free(data); g_free(data);
} }

View File

@ -117,7 +117,7 @@ static void commit_complete(Job *job, void *opaque)
* bdrv_set_backing_hd() to fail. */ * bdrv_set_backing_hd() to fail. */
block_job_remove_all_bdrv(bjob); block_job_remove_all_bdrv(bjob);
job_completed(job, ret); job_completed(job, ret, NULL);
g_free(data); g_free(data);
/* If bdrv_drop_intermediate() didn't already do that, remove the commit /* If bdrv_drop_intermediate() didn't already do that, remove the commit

View File

@ -24,28 +24,51 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "block/block_int.h" #include "block/block_int.h"
#include "qemu/job.h"
#include "qapi/qapi-commands-block-core.h" #include "qapi/qapi-commands-block-core.h"
#include "qapi/qapi-visit-block-core.h"
#include "qapi/clone-visitor.h"
#include "qapi/error.h" #include "qapi/error.h"
typedef struct BlockdevCreateCo { typedef struct BlockdevCreateJob {
Job common;
BlockDriver *drv; BlockDriver *drv;
BlockdevCreateOptions *opts; BlockdevCreateOptions *opts;
int ret; int ret;
Error **errp; Error *err;
} BlockdevCreateCo; } BlockdevCreateJob;
static void coroutine_fn bdrv_co_create_co_entry(void *opaque) static void blockdev_create_complete(Job *job, void *opaque)
{ {
BlockdevCreateCo *cco = opaque; BlockdevCreateJob *s = container_of(job, BlockdevCreateJob, common);
cco->ret = cco->drv->bdrv_co_create(cco->opts, cco->errp);
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); const char *fmt = BlockdevDriver_str(options->driver);
BlockDriver *drv = bdrv_find_format(fmt); 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 /* If the driver is in the schema, we know that it exists. But it may not
* be whitelisted. */ * be whitelisted. */
@ -55,22 +78,24 @@ void qmp_x_blockdev_create(BlockdevCreateOptions *options, Error **errp)
return; return;
} }
/* Call callback if it exists */ /* Error out if the driver doesn't support .bdrv_co_create */
if (!drv->bdrv_co_create) { if (!drv->bdrv_co_create) {
error_setg(errp, "Driver does not support blockdev-create"); error_setg(errp, "Driver does not support blockdev-create");
return; return;
} }
cco = (BlockdevCreateCo) { /* Create the block job */
.drv = drv, /* TODO Running in the main context. Block drivers need to error out or add
.opts = options, * locking when they use a BDS in a different AioContext. */
.ret = -EINPROGRESS, s = job_create(job_id, &blockdev_create_job_driver, NULL,
.errp = errp, qemu_get_aio_context(), JOB_DEFAULT | JOB_MANUAL_DISMISS,
}; NULL, NULL, errp);
if (!s) {
co = qemu_coroutine_create(bdrv_co_create_co_entry, &cco); return;
qemu_coroutine_enter(co);
while (cco.ret == -EINPROGRESS) {
aio_poll(qemu_get_aio_context(), true);
} }
s->drv = drv,
s->opts = QAPI_CLONE(BlockdevCreateOptions, options),
job_start(&s->common);
} }

View File

@ -581,7 +581,7 @@ static void mirror_exit(Job *job, void *opaque)
blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort); blk_set_perm(bjob->blk, 0, BLK_PERM_ALL, &error_abort);
blk_insert_bs(bjob->blk, mirror_top_bs, &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); g_free(data);
bdrv_drained_end(src); bdrv_drained_end(src);

View File

@ -768,6 +768,7 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
BDRVQcow2State *s = bs->opaque; BDRVQcow2State *s = bs->opaque;
uint64_t combined_cache_size; uint64_t combined_cache_size;
bool l2_cache_size_set, refcount_cache_size_set, combined_cache_size_set; 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); 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); 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 { } else {
uint64_t virtual_disk_size = bs->total_sectors * BDRV_SECTOR_SIZE; 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 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 /* Assign as much memory as possible to the L2 cache, and
* use the remainder for the refcount cache */ * use the remainder for the refcount cache */
@ -825,7 +824,7 @@ static void read_cache_sizes(BlockDriverState *bs, QemuOpts *opts,
* s->cluster_size); * s->cluster_size);
} }
if (!refcount_cache_size_set) { if (!refcount_cache_size_set) {
*refcount_cache_size = MIN_REFCOUNT_CACHE_SIZE * s->cluster_size; *refcount_cache_size = min_refcount_cache;
} }
} }

View File

@ -93,7 +93,7 @@ out:
} }
g_free(s->backing_file_str); g_free(s->backing_file_str);
job_completed(job, data->ret); job_completed(job, data->ret, NULL);
g_free(data); g_free(data);
} }

View File

@ -865,6 +865,7 @@ static int coroutine_fn vdi_co_do_create(BlockdevCreateOptions *create_options,
} }
} }
ret = 0;
exit: exit:
blk_unref(blk); blk_unref(blk);
bdrv_unref(bs_file); bdrv_unref(bs_file);

View File

@ -1951,7 +1951,7 @@ static int coroutine_fn vhdx_co_create(BlockdevCreateOptions *opts,
goto delete_and_exit; goto delete_and_exit;
} }
ret = 0;
delete_and_exit: delete_and_exit:
blk_unref(blk); blk_unref(blk);
bdrv_unref(bs); bdrv_unref(bs);

View File

@ -124,6 +124,9 @@ typedef struct Job {
/** Estimated progress_current value at the completion of the job */ /** Estimated progress_current value at the completion of the job */
int64_t progress_total; 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. */ /** ret code passed to job_completed. */
int ret; int ret;
@ -466,13 +469,15 @@ void job_transition_to_ready(Job *job);
/** /**
* @job: The job being completed. * @job: The job being completed.
* @ret: The status code. * @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 * 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 * 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 * is the last job to complete in its transaction, all jobs in the transaction
* move from WAITING to PENDING. * 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. */ /** Asynchronously complete the specified @job. */
void job_complete(Job *job, Error **errp); void job_complete(Job *job, Error **errp);

View File

@ -136,14 +136,9 @@ void qmp_job_dismiss(const char *id, Error **errp)
static JobInfo *job_query_single(Job *job, Error **errp) static JobInfo *job_query_single(Job *job, Error **errp)
{ {
JobInfo *info; JobInfo *info;
const char *errmsg = NULL;
assert(!job_is_internal(job)); assert(!job_is_internal(job));
if (job->ret < 0) {
errmsg = strerror(-job->ret);
}
info = g_new(JobInfo, 1); info = g_new(JobInfo, 1);
*info = (JobInfo) { *info = (JobInfo) {
.id = g_strdup(job->id), .id = g_strdup(job->id),
@ -151,8 +146,8 @@ static JobInfo *job_query_single(Job *job, Error **errp)
.status = job->status, .status = job->status,
.current_progress = job->progress_current, .current_progress = job->progress_current,
.total_progress = job->progress_total, .total_progress = job->progress_total,
.has_error = !!errmsg, .has_error = !!job->error,
.error = g_strdup(errmsg), .error = g_strdup(job->error),
}; };
return info; return info;

16
job.c
View File

@ -369,6 +369,7 @@ void job_unref(Job *job)
QLIST_REMOVE(job, job_list); QLIST_REMOVE(job, job_list);
g_free(job->error);
g_free(job->id); g_free(job->id);
g_free(job); g_free(job);
} }
@ -660,6 +661,9 @@ static void job_update_rc(Job *job)
job->ret = -ECANCELED; job->ret = -ECANCELED;
} }
if (job->ret) { if (job->ret) {
if (!job->error) {
job->error = g_strdup(strerror(-job->ret));
}
job_state_transition(job, JOB_STATUS_ABORTING); job_state_transition(job, JOB_STATUS_ABORTING);
} }
} }
@ -782,6 +786,7 @@ static int job_prepare(Job *job)
{ {
if (job->ret == 0 && job->driver->prepare) { if (job->ret == 0 && job->driver->prepare) {
job->ret = job->driver->prepare(job); job->ret = job->driver->prepare(job);
job_update_rc(job);
} }
return job->ret; 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)); assert(job && job->txn && !job_is_completed(job));
job->ret = ret; job->ret = ret;
if (error) {
assert(job->ret < 0);
job->error = g_strdup(error_get_pretty(error));
error_free(error);
}
job_update_rc(job); job_update_rc(job);
trace_job_completed(job, ret, job->ret); trace_job_completed(job, ret, job->ret);
if (job->ret) { if (job->ret) {
@ -876,7 +888,7 @@ void job_cancel(Job *job, bool force)
} }
job_cancel_async(job, force); job_cancel_async(job, force);
if (!job_started(job)) { if (!job_started(job)) {
job_completed(job, -ECANCELED); job_completed(job, -ECANCELED, NULL);
} else if (job->deferred_to_main_loop) { } else if (job->deferred_to_main_loop) {
job_completed_txn_abort(job); job_completed_txn_abort(job);
} else { } else {

View File

@ -4011,16 +4011,20 @@
} } } }
## ##
# @x-blockdev-create: # @blockdev-create:
# #
# Create an image format on a given node. # Starts a job to create an image format on a given node. The job is
# TODO Replace with something asynchronous (block job?) # 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', { 'command': 'blockdev-create',
'data': 'BlockdevCreateOptions', 'data': { 'job-id': 'str',
'boxed': true } 'options': 'BlockdevCreateOptions' } }
## ##
# @blockdev-open-tray: # @blockdev-open-tray:

View File

@ -17,10 +17,12 @@
# #
# @backup: drive backup job type, see "drive-backup" # @backup: drive backup job type, see "drive-backup"
# #
# @create: image creation job type, see "blockdev-create" (since 3.0)
#
# Since: 1.7 # Since: 1.7
## ##
{ 'enum': 'JobType', { 'enum': 'JobType',
'data': ['commit', 'stream', 'mirror', 'backup'] } 'data': ['commit', 'stream', 'mirror', 'backup', 'create'] }
## ##
# @JobStatus: # @JobStatus:

View File

@ -1,9 +1,11 @@
#!/bin/bash #!/usr/bin/env python
# #
# Test qcow2 and file image creation # Test qcow2 and file image creation
# #
# Copyright (C) 2018 Red Hat, Inc. # 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 # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# creator import iotests
owner=kwolf@redhat.com from iotests import imgfmt
seq=`basename $0` iotests.verify_image_format(supported_fmts=['qcow2'])
echo "QA output created by $seq"
here=`pwd` def blockdev_create(vm, options):
status=1 # failure is the default! result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
# get standard environment, filters and checks if 'return' in result:
. ./common.rc assert result['return'] == {}
. ./common.filter vm.run_job('job0')
iotests.log("")
_supported_fmt qcow2 with iotests.FilePath('t.qcow2') as disk_path, \
_supported_proto file iotests.FilePath('t.qcow2.base') as backing_path, \
_supported_os Linux iotests.VM() as vm:
function do_run_qemu() vm.add_object('secret,id=keysec0,data=foo')
{
echo Testing: "$@"
$QEMU -nographic -qmp stdio -serial none "$@"
echo
}
function run_qemu() #
{ # Successful image creation (defaults)
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ #
| _filter_qemu | _filter_imgfmt \ iotests.log("=== Successful image creation (defaults) ===")
| _filter_actual_image_size iotests.log("")
}
echo size = 128 * 1024 * 1024
echo "=== Successful image creation (defaults) ==="
echo
size=$((128 * 1024 * 1024)) vm.launch()
blockdev_create(vm, { 'driver': 'file',
'filename': disk_path,
'size': 0 })
run_qemu <<EOF vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
{ "execute": "qmp_capabilities" } node_name='imgfile')
{ "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 blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
'size': size })
vm.shutdown()
echo iotests.img_info_log(disk_path)
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)) # Successful image creation (inline blockdev-add, explicit defaults)
#
iotests.log("=== Successful image creation (inline blockdev-add, explicit defaults) ===")
iotests.log("")
run_qemu <<EOF # Choose a different size to show that we got a new image
{ "execute": "qmp_capabilities" } size = 64 * 1024 * 1024
{ "execute": "x-blockdev-create",
"arguments": { vm.launch()
"driver": "file", blockdev_create(vm, { 'driver': 'file',
"filename": "$TEST_IMG", 'filename': disk_path,
"size": 0, 'size': 0,
"preallocation": "off", 'preallocation': 'off',
"nocow": false 'nocow': False })
}
} blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': {
"arguments": { 'driver': 'file',
"driver": "$IMGFMT", 'filename': disk_path,
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"version": "v3", 'version': 'v3',
"cluster-size": 65536, 'cluster-size': 65536,
"preallocation": "off", 'preallocation': 'off',
"lazy-refcounts": false, 'lazy-refcounts': False,
"refcount-bits": 16 'refcount-bits': 16 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific iotests.img_info_log(disk_path)
echo #
echo "=== Successful image creation (v3 non-default options) ===" # Successful image creation (v3 non-default options)
echo #
iotests.log("=== Successful image creation (v3 non-default options) ===")
iotests.log("")
# Choose a different size to show that we got a new image # Choose a different size to show that we got a new image
size=$((32 * 1024 * 1024)) size = 32 * 1024 * 1024
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'file',
{ "execute": "x-blockdev-create", 'filename': disk_path,
"arguments": { 'size': 0,
"driver": "file", 'preallocation': 'falloc',
"filename": "$TEST_IMG", 'nocow': True })
"size": 0,
"preallocation": "falloc", blockdev_create(vm, { 'driver': imgfmt,
"nocow": true 'file': {
} 'driver': 'file',
} 'filename': disk_path,
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"version": "v3", 'version': 'v3',
"cluster-size": 2097152, 'cluster-size': 2097152,
"preallocation": "metadata", 'preallocation': 'metadata',
"lazy-refcounts": true, 'lazy-refcounts': True,
"refcount-bits": 1 'refcount-bits': 1 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific iotests.img_info_log(disk_path)
echo #
echo "=== Successful image creation (v2 non-default options) ===" # Successful image creation (v2 non-default options)
echo #
iotests.log("=== Successful image creation (v2 non-default options) ===")
iotests.log("")
mv $TEST_IMG $TEST_IMG.base vm.launch()
blockdev_create(vm, { 'driver': 'file',
'filename': disk_path,
'size': 0 })
run_qemu <<EOF blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "qmp_capabilities" } 'file': {
{ "execute": "x-blockdev-create", 'driver': 'file',
"arguments": { 'filename': disk_path,
"driver": "file",
"filename": "$TEST_IMG",
"size": 0
}
}
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"backing-file": "$TEST_IMG.base", 'backing-file': backing_path,
"backing-fmt": "qcow2", 'backing-fmt': 'qcow2',
"version": "v2", 'version': 'v2',
"cluster-size": 512 'cluster-size': 512 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific iotests.img_info_log(disk_path)
echo #
echo "=== Successful image creation (encrypted) ===" # Successful image creation (encrypted)
echo #
iotests.log("=== Successful image creation (encrypted) ===")
iotests.log("")
run_qemu -object secret,id=keysec0,data="foo" <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': {
"arguments": { 'driver': 'file',
"driver": "$IMGFMT", 'filename': disk_path,
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"encrypt": { 'encrypt': {
"format": "luks", 'format': 'luks',
"key-secret": "keysec0", 'key-secret': 'keysec0',
"cipher-alg": "twofish-128", 'cipher-alg': 'twofish-128',
"cipher-mode": "ctr", 'cipher-mode': 'ctr',
"ivgen-alg": "plain64", 'ivgen-alg': 'plain64',
"ivgen-hash-alg": "md5", 'ivgen-hash-alg': 'md5',
"hash-alg": "sha1", 'hash-alg': 'sha1',
"iter-time": 10 'iter-time': 10,
} }})
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific | _filter_img_info --format-specific iotests.img_info_log(disk_path)
echo #
echo "=== Invalid BlockdevRef ===" # Invalid BlockdevRef
echo #
iotests.log("=== Invalid BlockdevRef ===")
iotests.log("")
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': "this doesn't exist",
"arguments": { 'size': size })
"driver": "$IMGFMT", vm.shutdown()
"file": "this doesn't exist",
"size": $size
}
}
{ "execute": "quit" }
EOF
#
# Invalid sizes
#
iotests.log("=== Invalid sizes ===")
echo # TODO Negative image sizes aren't handled correctly, but this is a problem
echo "=== Invalid sizes ===" # with QAPI's implementation of the 'size' type and affects other commands
echo # 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)
# TODO Negative image sizes aren't handled correctly, but this is a problem vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
# 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 vm.launch()
# 2. 2^64 - 512 for size in [ 1234, 18446744073709551104, 9223372036854775808,
# 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this) 9223372036854775296 ]:
# 4. 2^63 - 512 (generally valid, but qcow2 can't handle images this size) blockdev_create(vm, { 'driver': imgfmt,
'file': 'node0',
'size': size })
vm.shutdown()
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF #
{ "execute": "qmp_capabilities" } # Invalid version
{ "execute": "x-blockdev-create", #
"arguments": { iotests.log("=== Invalid version ===")
"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 vm.launch()
echo "=== Invalid version ===" blockdev_create(vm, { 'driver': imgfmt,
echo '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()
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF #
{ "execute": "qmp_capabilities" } # Invalid backing file options
{ "execute": "x-blockdev-create", #
"arguments": { iotests.log("=== Invalid backing file options ===")
"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 vm.launch()
echo "=== Invalid backing file options ===" blockdev_create(vm, { 'driver': imgfmt,
echo 'file': 'node0',
'size': 67108864,
'backing-file': '/dev/null',
'preallocation': 'full' })
blockdev_create(vm, { 'driver': imgfmt,
'file': 'node0',
'size': 67108864,
'backing-fmt': imgfmt })
vm.shutdown()
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF #
{ "execute": "qmp_capabilities" } # Invalid cluster size
{ "execute": "x-blockdev-create", #
"arguments": { iotests.log("=== Invalid cluster size ===")
"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 vm.launch()
echo "=== Invalid cluster size ===" for csize in [ 1234, 128, 4194304, 0 ]:
echo 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()
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF #
{ "execute": "qmp_capabilities" } # Invalid refcount width
{ "execute": "x-blockdev-create", #
"arguments": { iotests.log("=== Invalid refcount width ===")
"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 vm.launch()
echo "=== Invalid refcount width ===" for refcount_bits in [ 128, 0, 7 ]:
echo blockdev_create(vm, { 'driver': imgfmt,
'file': 'node0',
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF 'size': 67108864,
{ "execute": "qmp_capabilities" } 'refcount-bits': refcount_bits })
{ "execute": "x-blockdev-create", vm.shutdown()
"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

View File

@ -1,17 +1,18 @@
QA output created by 206
=== Successful image creation (defaults) === === Successful image creation (defaults) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT {'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_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 128M (134217728 bytes) virtual size: 128M (134217728 bytes)
cluster_size: 65536 cluster_size: 65536
@ -23,15 +24,17 @@ Format specific information:
=== Successful image creation (inline blockdev-add, explicit defaults) === === Successful image creation (inline blockdev-add, explicit defaults) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
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 file format: IMGFMT
virtual size: 64M (67108864 bytes) virtual size: 64M (67108864 bytes)
cluster_size: 65536 cluster_size: 65536
@ -43,15 +46,17 @@ Format specific information:
=== Successful image creation (v3 non-default options) === === Successful image creation (v3 non-default options) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT {'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_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 32M (33554432 bytes) virtual size: 32M (33554432 bytes)
cluster_size: 2097152 cluster_size: 2097152
@ -63,19 +68,21 @@ Format specific information:
=== Successful image creation (v2 non-default options) === === Successful image creation (v2 non-default options) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
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 file format: IMGFMT
virtual size: 32M (33554432 bytes) virtual size: 32M (33554432 bytes)
cluster_size: 512 cluster_size: 512
backing file: TEST_DIR/t.IMGFMT.base backing file: TEST_IMG.base
backing file format: IMGFMT backing file format: IMGFMT
Format specific information: Format specific information:
compat: 0.10 compat: 0.10
@ -83,16 +90,16 @@ Format specific information:
=== Successful image creation (encrypted) === === Successful image creation (encrypted) ===
Testing: -object secret,id=keysec0,data=foo {'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}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT image: TEST_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 32M (33554432 bytes) virtual size: 32M (33554432 bytes)
encrypted: yes
cluster_size: 65536
Format specific information: Format specific information:
compat: 1.1 compat: 1.1
lazy refcounts: false lazy refcounts: false
@ -101,13 +108,13 @@ Format specific information:
ivgen alg: plain64 ivgen alg: plain64
hash alg: sha1 hash alg: sha1
cipher alg: twofish-128 cipher alg: twofish-128
uuid: 00000000-0000-0000-0000-000000000000 uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
format: luks format: luks
cipher mode: ctr cipher mode: ctr
slots: slots:
[0]: [0]:
active: true active: true
iters: 1024 iters: XXX
key offset: 4096 key offset: 4096
stripes: 4000 stripes: 4000
[1]: [1]:
@ -132,78 +139,118 @@ Format specific information:
active: false active: false
key offset: 462848 key offset: 462848
payload offset: 528384 payload offset: 528384
master key iters: 1024 master key iters: XXX
corrupt: false corrupt: false
=== Invalid BlockdevRef === === Invalid BlockdevRef ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': "this doesn't exist", 'size': 33554432}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Invalid sizes === === Invalid sizes ===
{'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': {}}
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 18446744073709551104L}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Could not resize image: Image size cannot be negative
{"error": {"class": "GenericError", "desc": "Image size must be a multiple of 512 bytes"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Could not resize image: Image size cannot be negative"}} {u'return': {}}
{"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': 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 === === 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 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'lazy-refcounts': True, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)
{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater)"}} {u'return': {}}
{"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': {'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 === === Invalid backing file options ===
{'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': {}}
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'backing-fmt': 'qcow2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Backing format cannot be used without backing file
{"error": {"class": "GenericError", "desc": "Backing file and preallocation cannot be used at the same time"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Backing format cannot be used without backing file"}} {u'return': {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Invalid cluster size === === Invalid cluster size ===
{'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': {}}
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: 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"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Cluster size must be a power of two between 512 and 2048k"}} {u'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": "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': 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 === === 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': {}}
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: 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"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}} {u'return': {}}
{"error": {"class": "GenericError", "desc": "Refcount width must be a power of two and may not exceed 64 bits"}}
{"return": {}} {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 7, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} {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': {}}
*** done

View File

@ -1,9 +1,11 @@
#!/bin/bash #!/usr/bin/env python
# #
# Test ssh image creation # Test ssh image creation
# #
# Copyright (C) 2018 Red Hat, Inc. # 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 # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# creator import iotests
owner=kwolf@redhat.com import subprocess
import re
seq=`basename $0` iotests.verify_image_format(supported_fmts=['raw'])
echo "QA output created by $seq" iotests.verify_protocol(supported=['ssh'])
here=`pwd` def filter_hash(msg):
status=1 # failure is the default! return re.sub("'hash': '[0-9a-f]+'", "'hash': HASH", msg)
# get standard environment, filters and checks def blockdev_create(vm, options):
. ./common.rc result = vm.qmp_log('blockdev-create', job_id='job0', options=options,
. ./common.filter filters=[iotests.filter_testfiles, filter_hash])
_supported_fmt raw if 'return' in result:
_supported_proto ssh assert result['return'] == {}
_supported_os Linux vm.run_job('job0')
iotests.log("")
function do_run_qemu() with iotests.FilePath('t.img') as disk_path, \
{ iotests.VM() as vm:
echo Testing: "$@"
$QEMU -nographic -qmp stdio -serial none "$@"
echo
}
function run_qemu() remote_path = iotests.remote_filename(disk_path)
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
| _filter_qemu | _filter_imgfmt \
| _filter_actual_image_size
}
echo #
echo "=== Successful image creation (defaults) ===" # Successful image creation (defaults)
echo #
iotests.log("=== Successful image creation (defaults) ===")
iotests.log("")
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'ssh',
{ "execute": "x-blockdev-create", 'location': {
"arguments": { 'path': disk_path,
"driver": "ssh", 'server': {
"location": { 'host': '127.0.0.1',
"path": "$TEST_IMG_FILE", 'port': '22'
"server": {
"host": "127.0.0.1",
"port": "22"
} }
}, },
"size": 4194304 'size': 4194304 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(remote_path, filter_path=disk_path)
echo iotests.log("")
TEST_IMG=$TEST_IMG_FILE _img_info | _filter_img_info iotests.img_info_log(disk_path)
echo #
echo "=== Test host-key-check options ===" # Test host-key-check options
echo #
iotests.log("=== Test host-key-check options ===")
iotests.log("")
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'ssh',
{ "execute": "x-blockdev-create", 'location': {
"arguments": { 'path': disk_path,
"driver": "ssh", 'server': {
"location": { 'host': '127.0.0.1',
"path": "$TEST_IMG_FILE", 'port': '22'
"server": {
"host": "127.0.0.1",
"port": "22"
}, },
"host-key-check": { 'host-key-check': {
"mode": "none" 'mode': 'none'
} }
}, },
"size": 8388608 'size': 8388608 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(remote_path, filter_path=disk_path)
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'ssh',
{ "execute": "x-blockdev-create", 'location': {
"arguments": { 'path': disk_path,
"driver": "ssh", 'server': {
"location": { 'host': '127.0.0.1',
"path": "$TEST_IMG_FILE", 'port': '22'
"server": {
"host": "127.0.0.1",
"port": "22"
}, },
"host-key-check": { 'host-key-check': {
"mode": "known_hosts" 'mode': 'known_hosts'
} }
}, },
"size": 4194304 'size': 4194304 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info 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()
key=$(ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | vm.launch()
cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1) blockdev_create(vm, { 'driver': 'ssh',
'location': {
run_qemu <<EOF 'path': disk_path,
{ "execute": "qmp_capabilities" } 'server': {
{ "execute": "x-blockdev-create", 'host': '127.0.0.1',
"arguments": { 'port': '22'
"driver": "ssh",
"location": {
"path": "$TEST_IMG_FILE",
"server": {
"host": "127.0.0.1",
"port": "22"
}, },
"host-key-check": { 'host-key-check': {
"mode": "hash", 'mode': 'hash',
"type": "md5", 'type': 'md5',
"hash": "wrong" 'hash': 'wrong',
} }
}, },
"size": 8388608 'size': 2097152 })
} blockdev_create(vm, { 'driver': 'ssh',
} 'location': {
{ "execute": "x-blockdev-create", 'path': disk_path,
"arguments": { 'server': {
"driver": "ssh", 'host': '127.0.0.1',
"location": { 'port': '22'
"path": "$TEST_IMG_FILE",
"server": {
"host": "127.0.0.1",
"port": "22"
}, },
"host-key-check": { 'host-key-check': {
"mode": "hash", 'mode': 'hash',
"type": "md5", 'type': 'md5',
"hash": "$key" 'hash': md5_key,
} }
}, },
"size": 8388608 'size': 8388608 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info 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()
key=$(ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | vm.launch()
cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1) blockdev_create(vm, { 'driver': 'ssh',
'location': {
run_qemu <<EOF 'path': disk_path,
{ "execute": "qmp_capabilities" } 'server': {
{ "execute": "x-blockdev-create", 'host': '127.0.0.1',
"arguments": { 'port': '22'
"driver": "ssh",
"location": {
"path": "$TEST_IMG_FILE",
"server": {
"host": "127.0.0.1",
"port": "22"
}, },
"host-key-check": { 'host-key-check': {
"mode": "hash", 'mode': 'hash',
"type": "sha1", 'type': 'sha1',
"hash": "wrong" 'hash': 'wrong',
} }
}, },
"size": 4194304 'size': 2097152 })
} blockdev_create(vm, { 'driver': 'ssh',
} 'location': {
{ "execute": "x-blockdev-create", 'path': disk_path,
"arguments": { 'server': {
"driver": "ssh", 'host': '127.0.0.1',
"location": { 'port': '22'
"path": "$TEST_IMG_FILE",
"server": {
"host": "127.0.0.1",
"port": "22"
}, },
"host-key-check": { 'host-key-check': {
"mode": "hash", 'mode': 'hash',
"type": "sha1", 'type': 'sha1',
"hash": "$key" 'hash': sha1_key,
} }
}, },
"size": 4194304 'size': 4194304 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(remote_path, filter_path=disk_path)
echo #
echo "=== Invalid path and user ===" # Invalid path and user
echo #
iotests.log("=== Invalid path and user ===")
iotests.log("")
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'ssh',
{ "execute": "x-blockdev-create", 'location': {
"arguments": { 'path': '/this/is/not/an/existing/path',
"driver": "ssh", 'server': {
"location": { 'host': '127.0.0.1',
"path": "/this/is/not/an/existing/path", 'port': '22'
"server": { },
"host": "127.0.0.1", 'host-key-check': {
"port": "22" 'mode': 'none'
} }
}, },
"size": 4194304 'size': 4194304 })
} blockdev_create(vm, { 'driver': 'ssh',
} 'location': {
{ "execute": "x-blockdev-create", 'path': disk_path,
"arguments": { 'user': 'invalid user',
"driver": "ssh", 'server': {
"location": { 'host': '127.0.0.1',
"path": "$TEST_IMG_FILE", 'port': '22'
"user": "invalid user", },
"server": { 'host-key-check': {
"host": "127.0.0.1", 'mode': 'none'
"port": "22"
} }
}, },
"size": 4194304 'size': 4194304 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
# success, all done
echo "*** done"
rm -f $seq.full
status=0

View File

@ -1,75 +1,80 @@
QA output created by 207
=== Successful image creation (defaults) === === Successful image creation (defaults) ===
Testing: {'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}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'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"}} image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT file format: IMGFMT
virtual size: 4.0M (4194304 bytes) virtual size: 4.0M (4194304 bytes)
image: TEST_DIR/t.IMGFMT
image: TEST_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 4.0M (4194304 bytes) virtual size: 4.0M (4194304 bytes)
=== Test host-key-check options === === Test host-key-check options ===
Testing: {'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}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'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"}} image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT file format: IMGFMT
virtual size: 8.0M (8388608 bytes) 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 file format: IMGFMT
virtual size: 4.0M (4194304 bytes) 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 file format: IMGFMT
virtual size: 8.0M (8388608 bytes) 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 file format: IMGFMT
virtual size: 4.0M (4194304 bytes) virtual size: 4.0M (4194304 bytes)
=== Invalid path and user === === Invalid path and user ===
Testing: {'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}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: 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 open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "failed to authenticate using publickey authentication and the identities held by your ssh-agent"}} {u'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'}, '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

View File

@ -1,9 +1,11 @@
#!/bin/bash #!/usr/bin/env python
# #
# Test luks and file image creation # Test luks and file image creation
# #
# Copyright (C) 2018 Red Hat, Inc. # 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 # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# creator import iotests
owner=kwolf@redhat.com from iotests import imgfmt
seq=`basename $0` iotests.verify_image_format(supported_fmts=['luks'])
echo "QA output created by $seq" iotests.verify_protocol(supported=['file'])
here=`pwd` def blockdev_create(vm, options):
status=1 # failure is the default! result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
# get standard environment, filters and checks if 'return' in result:
. ./common.rc assert result['return'] == {}
. ./common.filter vm.run_job('job0')
iotests.log("")
_supported_fmt luks with iotests.FilePath('t.luks') as disk_path, \
_supported_proto file iotests.VM() as vm:
_supported_os Linux
function do_run_qemu() vm.add_object('secret,id=keysec0,data=foo')
{
echo Testing: "$@"
$QEMU -nographic -qmp stdio -serial none "$@"
echo
}
function run_qemu() #
{ # Successful image creation (defaults)
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \ #
| _filter_qemu | _filter_imgfmt \ iotests.log("=== Successful image creation (defaults) ===")
| _filter_actual_image_size iotests.log("")
}
echo size = 128 * 1024 * 1024
echo "=== Successful image creation (defaults) ==="
echo
size=$((128 * 1024 * 1024)) vm.launch()
blockdev_create(vm, { 'driver': 'file',
'filename': disk_path,
'size': 0 })
run_qemu -object secret,id=keysec0,data="foo" <<EOF vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
{ "execute": "qmp_capabilities" } node_name='imgfile')
{ "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 blockdev_create(vm, { 'driver': imgfmt,
'file': 'imgfile',
'key-secret': 'keysec0',
'size': size,
'iter-time': 10 })
vm.shutdown()
echo # TODO Proper support for images to be used with imgopts and/or protocols
echo "=== Successful image creation (with non-default options) ===" iotests.img_info_log(
echo '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)
# Choose a different size to show that we got a new image #
size=$((64 * 1024 * 1024)) # Successful image creation (with non-default options)
#
iotests.log("=== Successful image creation (with non-default options) ===")
iotests.log("")
run_qemu -object secret,id=keysec0,data="foo" <<EOF size = 64 * 1024 * 1024
{ "execute": "qmp_capabilities" }
{ "execute": "x-blockdev-create", vm.launch()
"arguments": { blockdev_create(vm, { 'driver': 'file',
"driver": "file", 'filename': disk_path,
"filename": "$TEST_IMG_FILE", 'size': 0 })
"size": 0 blockdev_create(vm, { 'driver': imgfmt,
} 'file': {
} 'driver': 'file',
{ "execute": "x-blockdev-create", 'filename': disk_path,
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG_FILE"
}, },
"size": $size, 'size': size,
"key-secret": "keysec0", 'key-secret': 'keysec0',
"cipher-alg": "twofish-128", 'cipher-alg': 'twofish-128',
"cipher-mode": "ctr", 'cipher-mode': 'ctr',
"ivgen-alg": "plain64", 'ivgen-alg': 'plain64',
"ivgen-hash-alg": "md5", 'ivgen-hash-alg': 'md5',
"hash-alg": "sha1", 'hash-alg': 'sha1',
"iter-time": 10 'iter-time': 10 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific | _filter_img_info --format-specific # 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)
echo #
echo "=== Invalid BlockdevRef ===" # Invalid BlockdevRef
echo #
iotests.log("=== Invalid BlockdevRef ===")
iotests.log("")
run_qemu <<EOF size = 64 * 1024 * 1024
{ "execute": "qmp_capabilities" }
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": "this doesn't exist",
"size": $size
}
}
{ "execute": "quit" }
EOF
echo vm.launch()
echo "=== Zero size ===" blockdev_create(vm, { 'driver': imgfmt,
echo 'file': "this doesn't exist",
'size': size })
vm.shutdown()
run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \ #
-object secret,id=keysec0,data="foo" <<EOF # Zero size
{ "execute": "qmp_capabilities" } #
{ "execute": "x-blockdev-create", iotests.log("=== Zero size ===")
"arguments": { iotests.log("")
"driver": "$IMGFMT",
"file": "node0",
"key-secret": "keysec0",
"size": 0,
"iter-time": 10
}
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info 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)
echo #
echo "=== Invalid sizes ===" # Invalid sizes
echo #
# TODO Negative image sizes aren't handled correctly, but this is a problem # 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 # 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. # well. Once this is fixed, we may want to add a test case here.
# 1. 2^64 - 512 # 1. 2^64 - 512
# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) # 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 # 3. 2^63 - 512 (generally valid, but with the crypto header the file will
# exceed 63 bits) # exceed 63 bits)
iotests.log("=== Invalid sizes ===")
iotests.log("")
run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \ vm.launch()
-object secret,id=keysec0,data="foo" <<EOF for size in [ 18446744073709551104, 9223372036854775808, 9223372036854775296 ]:
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': 'node0',
"arguments": { 'key-secret': 'keysec0',
"driver": "$IMGFMT", 'size': size })
"file": "node0", vm.shutdown()
"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 ===" # Resize image with invalid sizes
echo #
iotests.log("=== Resize image with invalid sizes ===")
iotests.log("")
run_qemu -blockdev driver=file,filename="$TEST_IMG_FILE",node-name=node0 \ vm.add_blockdev('driver=luks,file=node0,key-secret=keysec0,node-name=node1')
-blockdev driver=luks,file=node0,key-secret=keysec0,node-name=node1 \ vm.launch()
-object secret,id=keysec0,data="foo" <<EOF vm.qmp_log('block_resize', node_name='node1', size=9223372036854775296)
{ "execute": "qmp_capabilities" } vm.qmp_log('block_resize', node_name='node1', size=9223372036854775808)
{ "execute": "block_resize", vm.qmp_log('block_resize', node_name='node1', size=18446744073709551104)
"arguments": { vm.qmp_log('block_resize', node_name='node1', size=-9223372036854775808)
"node-name": "node1", vm.shutdown()
"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 # TODO Proper support for images to be used with imgopts and/or protocols
iotests.img_info_log(
# success, all done 'driver=luks,file.driver=file,file.filename=%s,key-secret=keysec0' % (disk_path),
echo "*** done" filter_path=disk_path,
rm -f $seq.full extra_args=['--object', 'secret,id=keysec0,data=foo'],
status=0 imgopts=True)

View File

@ -1,29 +1,31 @@
QA output created by 210
=== Successful image creation (defaults) === === Successful image creation (defaults) ===
Testing: -object secret,id=keysec0,data=foo {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"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': '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_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT file format: IMGFMT
virtual size: 128M (134217728 bytes) virtual size: 128M (134217728 bytes)
encrypted: yes
Format specific information: Format specific information:
ivgen alg: plain64 ivgen alg: plain64
hash alg: sha256 hash alg: sha256
cipher alg: aes-256 cipher alg: aes-256
uuid: 00000000-0000-0000-0000-000000000000 uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
cipher mode: xts cipher mode: xts
slots: slots:
[0]: [0]:
active: true active: true
iters: 1024 iters: XXX
key offset: 4096 key offset: 4096
stripes: 4000 stripes: 4000
[1]: [1]:
@ -48,31 +50,34 @@ Format specific information:
active: false active: false
key offset: 1810432 key offset: 1810432
payload offset: 2068480 payload offset: 2068480
master key iters: 1024 master key iters: XXX
=== Successful image creation (with non-default options) === === Successful image creation (with non-default options) ===
Testing: -object secret,id=keysec0,data=foo {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"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': '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_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT file format: IMGFMT
virtual size: 64M (67108864 bytes) virtual size: 64M (67108864 bytes)
encrypted: yes
Format specific information: Format specific information:
ivgen alg: plain64 ivgen alg: plain64
hash alg: sha1 hash alg: sha1
cipher alg: twofish-128 cipher alg: twofish-128
uuid: 00000000-0000-0000-0000-000000000000 uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
cipher mode: ctr cipher mode: ctr
slots: slots:
[0]: [0]:
active: true active: true
iters: 1024 iters: XXX
key offset: 4096 key offset: 4096
stripes: 4000 stripes: 4000
[1]: [1]:
@ -97,56 +102,130 @@ Format specific information:
active: false active: false
key offset: 462848 key offset: 462848
payload offset: 528384 payload offset: 528384
master key iters: 1024 master key iters: XXX
=== Invalid BlockdevRef === === Invalid BlockdevRef ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'luks', 'file': "this doesn't exist", 'size': 67108864}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Zero size === === Zero size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -object secret,id=keysec0,data=foo {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'node0', 'size': 0}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"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"} image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
file format: IMGFMT file format: IMGFMT
virtual size: 0 (0 bytes) 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 === === Invalid sizes ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 -object secret,id=keysec0,data=foo {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 18446744073709551104L}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: The requested file size is too large
{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} {u'return': {}}
{"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': 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 === === 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 {'execute': 'block_resize', 'arguments': {'size': 9223372036854775296, 'node_name': 'node1'}}
QMP_VERSION {u'error': {u'class': u'GenericError', u'desc': u'The requested file size is too large'}}
{"return": {}} {'execute': 'block_resize', 'arguments': {'size': 9223372036854775808L, 'node_name': 'node1'}}
{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} {u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} {'execute': 'block_resize', 'arguments': {'size': 18446744073709551104L, 'node_name': 'node1'}}
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} {u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}}
{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}} {'execute': 'block_resize', 'arguments': {'size': -9223372036854775808, 'node_name': 'node1'}}
{"return": {}} {u'error': {u'class': u'GenericError', u'desc': u"Parameter 'size' expects a >0 size"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"}
image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "key-secret": "keysec0"}
file format: IMGFMT file format: IMGFMT
virtual size: 0 (0 bytes) 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

View File

@ -1,9 +1,11 @@
#!/bin/bash #!/usr/bin/env python
# #
# Test VDI and file image creation # Test VDI and file image creation
# #
# Copyright (C) 2018 Red Hat, Inc. # 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 # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# creator import iotests
owner=kwolf@redhat.com from iotests import imgfmt
seq=`basename $0` iotests.verify_image_format(supported_fmts=['vdi'])
echo "QA output created by $seq" iotests.verify_protocol(supported=['file'])
here=`pwd` def blockdev_create(vm, options):
status=1 # failure is the default! result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
# get standard environment, filters and checks if 'return' in result:
. ./common.rc assert result['return'] == {}
. ./common.filter vm.run_job('job0')
iotests.log("")
_supported_fmt vdi with iotests.FilePath('t.vdi') as disk_path, \
_supported_proto file iotests.VM() as vm:
_supported_os Linux
function do_run_qemu() #
{ # Successful image creation (defaults)
echo Testing: "$@" #
$QEMU -nographic -qmp stdio -serial none "$@" iotests.log("=== Successful image creation (defaults) ===")
echo iotests.log("")
}
function run_qemu() size = 128 * 1024 * 1024
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
| _filter_qemu | _filter_imgfmt \
| _filter_actual_image_size
}
echo vm.launch()
echo "=== Successful image creation (defaults) ===" blockdev_create(vm, { 'driver': 'file',
echo 'filename': disk_path,
'size': 0 })
size=$((128 * 1024 * 1024)) vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
node_name='imgfile')
run_qemu <<EOF blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "qmp_capabilities" } 'file': 'imgfile',
{ "execute": "x-blockdev-create", 'size': size })
"arguments": { vm.shutdown()
"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 iotests.img_info_log(disk_path)
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path))
echo #
echo "=== Successful image creation (explicit defaults) ===" # Successful image creation (explicit defaults)
echo #
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
size=$((64 * 1024 * 1024))
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'file',
{ "execute": "x-blockdev-create", 'filename': disk_path,
"arguments": { 'size': 0 })
"driver": "file", blockdev_create(vm, { 'driver': imgfmt,
"filename": "$TEST_IMG", 'file': {
"size": 0 'driver': 'file',
} 'filename': disk_path,
}
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"preallocation": "off" 'preallocation': 'off' })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific | _filter_img_info --format-specific iotests.img_info_log(disk_path)
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path))
echo #
echo "=== Successful image creation (with non-default options) ===" # Successful image creation (with non-default options)
echo #
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
size=$((32 * 1024 * 1024))
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'file',
{ "execute": "x-blockdev-create", 'filename': disk_path,
"arguments": { 'size': 0 })
"driver": "file", blockdev_create(vm, { 'driver': imgfmt,
"filename": "$TEST_IMG", 'file': {
"size": 0 'driver': 'file',
} 'filename': disk_path,
}
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"preallocation": "metadata" 'preallocation': 'metadata' })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific | _filter_img_info --format-specific iotests.img_info_log(disk_path)
$QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map iotests.log(iotests.qemu_img_pipe('map', '--output=json', disk_path))
echo #
echo "=== Invalid BlockdevRef ===" # Invalid BlockdevRef
echo #
iotests.log("=== Invalid BlockdevRef ===")
iotests.log("")
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': "this doesn't exist",
"arguments": { 'size': size })
"driver": "$IMGFMT", vm.shutdown()
"file": "this doesn't exist",
"size": $size
}
}
{ "execute": "quit" }
EOF
echo #
echo "=== Zero size ===" # Zero size
echo #
iotests.log("=== Zero size ===")
iotests.log("")
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
{ "execute": "qmp_capabilities" } vm.launch()
{ "execute": "x-blockdev-create", blockdev_create(vm, { 'driver': imgfmt,
"arguments": { 'file': 'node0',
"driver": "$IMGFMT", 'size': 0 })
"file": "node0", vm.shutdown()
"size": 0
}
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(disk_path)
echo #
echo "=== Maximum size ===" # Maximum size
echo #
iotests.log("=== Maximum size ===")
iotests.log("")
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': 'node0',
"arguments": { 'size': 562949819203584 })
"driver": "$IMGFMT", vm.shutdown()
"file": "node0",
"size": 562949819203584
}
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(disk_path)
echo #
echo "=== Invalid sizes ===" # Invalid sizes
echo #
# TODO Negative image sizes aren't handled correctly, but this is a problem # 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 # with QAPI's implementation of the 'size' type and affects other commands
# well. Once this is fixed, we may want to add a test case here. # as well. Once this is fixed, we may want to add a test case here.
# 1. 2^64 - 512 # 1. 2^64 - 512
# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) # 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this)
# 3. 0x1fffff8000001 (one byte more than maximum image size for VDI) # 3. 0x1fffff8000001 (one byte more than maximum image size for VDI)
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF iotests.log("=== Invalid sizes ===")
{ "execute": "qmp_capabilities" } iotests.log("")
{ "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 vm.launch()
echo "*** done" for size in [ 18446744073709551104, 9223372036854775808, 562949819203585 ]:
rm -f $seq.full blockdev_create(vm, { 'driver': imgfmt,
status=0 'file': 'node0',
'size': size })
vm.shutdown()

View File

@ -1,97 +1,112 @@
QA output created by 211
=== Successful image creation (defaults) === === Successful image creation (defaults) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT {'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_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 128M (134217728 bytes) virtual size: 128M (134217728 bytes)
cluster_size: 1048576
[{ "start": 0, "length": 134217728, "depth": 0, "zero": true, "data": false}] [{ "start": 0, "length": 134217728, "depth": 0, "zero": true, "data": false}]
=== Successful image creation (explicit defaults) === === Successful image creation (explicit defaults) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
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 file format: IMGFMT
virtual size: 64M (67108864 bytes) virtual size: 64M (67108864 bytes)
cluster_size: 1048576
[{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}] [{ "start": 0, "length": 67108864, "depth": 0, "zero": true, "data": false}]
=== Successful image creation (with non-default options) === === Successful image creation (with non-default options) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
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 file format: IMGFMT
virtual size: 32M (33554432 bytes) virtual size: 32M (33554432 bytes)
[{ "start": 0, "length": 3072, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, cluster_size: 1048576
{ "start": 3072, "length": 33551360, "depth": 0, "zero": true, "data": true, "offset": OFFSET}]
[{ "start": 0, "length": 3072, "depth": 0, "zero": false, "data": true, "offset": 1024},
{ "start": 3072, "length": 33551360, "depth": 0, "zero": true, "data": true, "offset": 4096}]
=== Invalid BlockdevRef === === Invalid BlockdevRef ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': "this doesn't exist", 'size': 33554432}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Zero size === === Zero size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT image: TEST_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 0 (0 bytes) virtual size: 0 (0 bytes)
cluster_size: 1048576
=== Maximum size === === Maximum size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT image: TEST_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 512T (562949819203584 bytes) virtual size: 512T (562949819203584 bytes)
cluster_size: 1048576
=== Invalid sizes === === Invalid sizes ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 18446744073709551104L}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)
{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000)"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000)"}} {u'return': {}}
{"error": {"class": "GenericError", "desc": "Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000)"}}
{"return": {}} {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 9223372036854775808L}}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} {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

View File

@ -1,9 +1,11 @@
#!/bin/bash #!/usr/bin/env python
# #
# Test parallels and file image creation # Test parallels and file image creation
# #
# Copyright (C) 2018 Red Hat, Inc. # 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 # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# creator import iotests
owner=kwolf@redhat.com from iotests import imgfmt
seq=`basename $0` iotests.verify_image_format(supported_fmts=['parallels'])
echo "QA output created by $seq" iotests.verify_protocol(supported=['file'])
here=`pwd` def blockdev_create(vm, options):
status=1 # failure is the default! result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
# get standard environment, filters and checks if 'return' in result:
. ./common.rc assert result['return'] == {}
. ./common.filter vm.run_job('job0')
iotests.log("")
_supported_fmt parallels with iotests.FilePath('t.parallels') as disk_path, \
_supported_proto file iotests.VM() as vm:
_supported_os Linux
function do_run_qemu() #
{ # Successful image creation (defaults)
echo Testing: "$@" #
$QEMU -nographic -qmp stdio -serial none "$@" iotests.log("=== Successful image creation (defaults) ===")
echo iotests.log("")
}
function run_qemu() size = 128 * 1024 * 1024
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
| _filter_qemu | _filter_imgfmt \
| _filter_actual_image_size
}
echo vm.launch()
echo "=== Successful image creation (defaults) ===" blockdev_create(vm, { 'driver': 'file',
echo 'filename': disk_path,
'size': 0 })
size=$((128 * 1024 * 1024)) vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
node_name='imgfile')
run_qemu <<EOF blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "qmp_capabilities" } 'file': 'imgfile',
{ "execute": "x-blockdev-create", 'size': size })
"arguments": { vm.shutdown()
"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 iotests.img_info_log(disk_path)
echo #
echo "=== Successful image creation (explicit defaults) ===" # Successful image creation (explicit defaults)
echo #
iotests.log("=== Successful image creation (explicit defaults) ===")
iotests.log("")
# Choose a different size to show that we got a new image # Choose a different size to show that we got a new image
size=$((64 * 1024 * 1024)) size = 64 * 1024 * 1024
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'file',
{ "execute": "x-blockdev-create", 'filename': disk_path,
"arguments": { 'size': 0 })
"driver": "file", blockdev_create(vm, { 'driver': imgfmt,
"filename": "$TEST_IMG", 'file': {
"size": 0 'driver': 'file',
} 'filename': disk_path,
}
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"cluster-size": 1048576 'cluster-size': 1048576 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific | _filter_img_info --format-specific iotests.img_info_log(disk_path)
echo #
echo "=== Successful image creation (with non-default options) ===" # Successful image creation (with non-default options)
echo #
iotests.log("=== Successful image creation (with non-default options) ===")
iotests.log("")
# Choose a different size to show that we got a new image # Choose a different size to show that we got a new image
size=$((32 * 1024 * 1024)) size = 32 * 1024 * 1024
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'file',
{ "execute": "x-blockdev-create", 'filename': disk_path,
"arguments": { 'size': 0 })
"driver": "file", blockdev_create(vm, { 'driver': imgfmt,
"filename": "$TEST_IMG", 'file': {
"size": 0 'driver': 'file',
} 'filename': disk_path,
}
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"cluster-size": 65536 'cluster-size': 65536 })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific | _filter_img_info --format-specific iotests.img_info_log(disk_path)
echo #
echo "=== Invalid BlockdevRef ===" # Invalid BlockdevRef
echo #
iotests.log("=== Invalid BlockdevRef ===")
iotests.log("")
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': "this doesn't exist",
"arguments": { 'size': size })
"driver": "$IMGFMT", vm.shutdown()
"file": "this doesn't exist",
"size": $size
}
}
{ "execute": "quit" }
EOF
echo #
echo "=== Zero size ===" # Zero size
echo #
iotests.log("=== Zero size ===")
iotests.log("")
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
{ "execute": "qmp_capabilities" } vm.launch()
{ "execute": "x-blockdev-create", blockdev_create(vm, { 'driver': imgfmt,
"arguments": { 'file': 'node0',
"driver": "$IMGFMT", 'size': 0 })
"file": "node0", vm.shutdown()
"size": 0
}
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(disk_path)
echo #
echo "=== Maximum size ===" # Maximum size
echo #
iotests.log("=== Maximum size ===")
iotests.log("")
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': 'node0',
"arguments": { 'size': 4503599627369984})
"driver": "$IMGFMT", vm.shutdown()
"file": "node0",
"size": 4503599627369984
}
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(disk_path)
echo #
echo "=== Invalid sizes ===" # Invalid sizes
echo #
# TODO Negative image sizes aren't handled correctly, but this is a problem # 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 # with QAPI's implementation of the 'size' type and affects other commands
# well. Once this is fixed, we may want to add a test case here. # as well. Once this is fixed, we may want to add a test case here.
# 1. Misaligned image size # 1. Misaligned image size
# 2. 2^64 - 512 # 2. 2^64 - 512
# 3. 2^63 = 8 EB (qemu-img enforces image sizes less than this) # 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 # 4. 2^63 - 512 (generally valid, but with the image header the file will
# exceed 63 bits) # exceed 63 bits)
# 5. 2^52 (512 bytes more than maximum image size) # 5. 2^52 (512 bytes more than maximum image size)
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF iotests.log("=== Invalid sizes ===")
{ "execute": "qmp_capabilities" } iotests.log("")
{ "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 vm.launch()
echo "=== Invalid cluster size ===" for size in [ 1234, 18446744073709551104, 9223372036854775808,
echo 9223372036854775296, 4503599627370497 ]:
blockdev_create(vm, { 'driver': imgfmt,
'file': 'node0',
'size': size })
vm.shutdown()
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF #
{ "execute": "qmp_capabilities" } # Invalid cluster size
{ "execute": "x-blockdev-create", #
"arguments": { iotests.log("=== Invalid cluster size ===")
"driver": "$IMGFMT", iotests.log("")
"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
vm.launch()
# success, all done for csize in [ 1234, 128, 4294967296, 9223372036854775808,
echo "*** done" 18446744073709551104, 0 ]:
rm -f $seq.full blockdev_create(vm, { 'driver': imgfmt,
status=0 'file': 'node0',
'size': 67108864,
'cluster-size': csize })
blockdev_create(vm, { 'driver': imgfmt,
'file': 'node0',
'size': 281474976710656,
'cluster-size': 512 })
vm.shutdown()

View File

@ -1,111 +1,156 @@
QA output created by 212
=== Successful image creation (defaults) === === Successful image creation (defaults) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT {'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_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 128M (134217728 bytes) virtual size: 128M (134217728 bytes)
=== Successful image creation (explicit defaults) === === Successful image creation (explicit defaults) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
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 file format: IMGFMT
virtual size: 64M (67108864 bytes) virtual size: 64M (67108864 bytes)
=== Successful image creation (with non-default options) === === Successful image creation (with non-default options) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT {'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_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 32M (33554432 bytes) virtual size: 32M (33554432 bytes)
=== Invalid BlockdevRef === === Invalid BlockdevRef ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': "this doesn't exist", 'size': 33554432}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Zero size === === Zero size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT image: TEST_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 0 (0 bytes) virtual size: 0 (0 bytes)
=== Maximum size === === Maximum size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT image: TEST_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 4096T (4503599627369984 bytes) virtual size: 4096T (4503599627369984 bytes)
=== Invalid sizes === === Invalid sizes ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 1234}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Image size must be a multiple of 512 bytes
{"error": {"class": "GenericError", "desc": "Image size must be a multiple of 512 bytes"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} {u'return': {}}
{"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': 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 === === Invalid cluster size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Cluster size must be a multiple of 512 bytes
{"error": {"class": "GenericError", "desc": "Cluster size must be a multiple of 512 bytes"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Cluster size must be a multiple of 512 bytes"}} {u'return': {}}
{"error": {"class": "GenericError", "desc": "Cluster size is too large"}}
{"error": {"class": "GenericError", "desc": "Cluster size is too large"}} {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}}
{"error": {"class": "GenericError", "desc": "Cluster size is too large"}} {u'return': {}}
{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} Job failed: Cluster size must be a multiple of 512 bytes
{"error": {"class": "GenericError", "desc": "Image size is too large for this cluster size"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'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': {}}
*** done

View File

@ -1,9 +1,11 @@
#!/bin/bash #!/usr/bin/env python
# #
# Test vhdx and file image creation # Test vhdx and file image creation
# #
# Copyright (C) 2018 Red Hat, Inc. # 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 # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# creator import iotests
owner=kwolf@redhat.com from iotests import imgfmt
seq=`basename $0` iotests.verify_image_format(supported_fmts=['vhdx'])
echo "QA output created by $seq" iotests.verify_protocol(supported=['file'])
here=`pwd` def blockdev_create(vm, options):
status=1 # failure is the default! result = vm.qmp_log('blockdev-create', job_id='job0', options=options)
# get standard environment, filters and checks if 'return' in result:
. ./common.rc assert result['return'] == {}
. ./common.filter vm.run_job('job0')
iotests.log("")
_supported_fmt vhdx with iotests.FilePath('t.vhdx') as disk_path, \
_supported_proto file iotests.VM() as vm:
_supported_os Linux
function do_run_qemu() #
{ # Successful image creation (defaults)
echo Testing: "$@" #
$QEMU -nographic -qmp stdio -serial none "$@" iotests.log("=== Successful image creation (defaults) ===")
echo iotests.log("")
}
function run_qemu() size = 128 * 1024 * 1024
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
| _filter_qemu | _filter_imgfmt \
| _filter_actual_image_size
}
echo vm.launch()
echo "=== Successful image creation (defaults) ===" blockdev_create(vm, { 'driver': 'file',
echo 'filename': disk_path,
'size': 0 })
size=$((128 * 1024 * 1024)) vm.qmp_log('blockdev-add', driver='file', filename=disk_path,
node_name='imgfile')
run_qemu <<EOF blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "qmp_capabilities" } 'file': 'imgfile',
{ "execute": "x-blockdev-create", 'size': size })
"arguments": { vm.shutdown()
"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 iotests.img_info_log(disk_path)
echo #
echo "=== Successful image creation (explicit defaults) ===" # Successful image creation (explicit defaults)
echo #
iotests.log("=== Successful image creation (explicit defaults) ===")
iotests.log("")
# Choose a different size to show that we got a new image # Choose a different size to show that we got a new image
size=$((64 * 1024 * 1024)) size = 64 * 1024 * 1024
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'file',
{ "execute": "x-blockdev-create", 'filename': disk_path,
"arguments": { 'size': 0 })
"driver": "file", blockdev_create(vm, { 'driver': imgfmt,
"filename": "$TEST_IMG", 'file': {
"size": 0 'driver': 'file',
} 'filename': disk_path,
}
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"log-size": 1048576, 'log-size': 1048576,
"block-size": 8388608, 'block-size': 8388608,
"subformat": "dynamic", 'subformat': 'dynamic',
"block-state-zero": true 'block-state-zero': True })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific | _filter_img_info --format-specific iotests.img_info_log(disk_path)
echo #
echo "=== Successful image creation (with non-default options) ===" # Successful image creation (with non-default options)
echo #
iotests.log("=== Successful image creation (with non-default options) ===")
iotests.log("")
# Choose a different size to show that we got a new image # Choose a different size to show that we got a new image
size=$((32 * 1024 * 1024)) size = 32 * 1024 * 1024
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': 'file',
{ "execute": "x-blockdev-create", 'filename': disk_path,
"arguments": { 'size': 0 })
"driver": "file", blockdev_create(vm, { 'driver': imgfmt,
"filename": "$TEST_IMG", 'file': {
"size": 0 'driver': 'file',
} 'filename': disk_path,
}
{ "execute": "x-blockdev-create",
"arguments": {
"driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_IMG"
}, },
"size": $size, 'size': size,
"log-size": 8388608, 'log-size': 8388608,
"block-size": 268435456, 'block-size': 268435456,
"subformat": "fixed", 'subformat': 'fixed',
"block-state-zero": false 'block-state-zero': False })
} vm.shutdown()
}
{ "execute": "quit" }
EOF
_img_info --format-specific | _filter_img_info --format-specific iotests.img_info_log(disk_path)
echo #
echo "=== Invalid BlockdevRef ===" # Invalid BlockdevRef
echo #
iotests.log("=== Invalid BlockdevRef ===")
iotests.log("")
run_qemu <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': "this doesn't exist",
"arguments": { 'size': size })
"driver": "$IMGFMT", vm.shutdown()
"file": "this doesn't exist",
"size": $size
}
}
{ "execute": "quit" }
EOF
echo #
echo "=== Zero size ===" # Zero size
echo #
iotests.log("=== Zero size ===")
iotests.log("")
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF vm.add_blockdev('driver=file,filename=%s,node-name=node0' % (disk_path))
{ "execute": "qmp_capabilities" } vm.launch()
{ "execute": "x-blockdev-create", blockdev_create(vm, { 'driver': imgfmt,
"arguments": { 'file': 'node0',
"driver": "$IMGFMT", 'size': 0 })
"file": "node0", vm.shutdown()
"size": 0
}
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(disk_path)
echo #
echo "=== Maximum size ===" # Maximum size
echo #
iotests.log("=== Maximum size ===")
iotests.log("")
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF vm.launch()
{ "execute": "qmp_capabilities" } blockdev_create(vm, { 'driver': imgfmt,
{ "execute": "x-blockdev-create", 'file': 'node0',
"arguments": { 'size': 70368744177664 })
"driver": "$IMGFMT", vm.shutdown()
"file": "node0",
"size": 70368744177664
}
}
{ "execute": "quit" }
EOF
_img_info | _filter_img_info iotests.img_info_log(disk_path)
echo #
echo "=== Invalid sizes ===" # Invalid sizes
echo #
# TODO Negative image sizes aren't handled correctly, but this is a problem # 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 # with QAPI's implementation of the 'size' type and affects other commands
# well. Once this is fixed, we may want to add a test case here. # as well. Once this is fixed, we may want to add a test case here.
# 1. 2^64 - 512 # 1. 2^64 - 512
# 2. 2^63 = 8 EB (qemu-img enforces image sizes less than this) # 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 # 3. 2^63 - 512 (generally valid, but with the image header the file will
# exceed 63 bits) # exceed 63 bits)
# 4. 2^46 + 1 (one byte more than maximum image size) # 4. 2^46 + 1 (one byte more than maximum image size)
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF iotests.log("=== Invalid sizes ===")
{ "execute": "qmp_capabilities" } iotests.log("")
{ "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 vm.launch()
echo "=== Invalid block size ===" for size in [ 18446744073709551104, 9223372036854775808,
echo 9223372036854775296, 70368744177665 ]:
blockdev_create(vm, { 'driver': imgfmt,
'file': 'node0',
'size': size })
vm.shutdown()
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF #
{ "execute": "qmp_capabilities" } # Invalid block size
{ "execute": "x-blockdev-create", #
"arguments": { iotests.log("=== Invalid block size ===")
"driver": "$IMGFMT", iotests.log("")
"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 vm.launch()
echo "=== Invalid log size ===" for bsize in [ 1234567, 128, 3145728, 536870912, 0 ]:
echo blockdev_create(vm, { 'driver': imgfmt,
'file': 'node0',
'size': 67108864,
'block-size': bsize })
vm.shutdown()
run_qemu -blockdev driver=file,filename="$TEST_IMG",node-name=node0 <<EOF #
{ "execute": "qmp_capabilities" } # Invalid log size
{ "execute": "x-blockdev-create", #
"arguments": { iotests.log("=== Invalid log size ===")
"driver": "$IMGFMT", iotests.log("")
"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
vm.launch()
# success, all done for lsize in [ 1234567, 128, 4294967296, 0 ]:
echo "*** done" blockdev_create(vm, { 'driver': imgfmt,
rm -f $seq.full 'file': 'node0',
status=0 'size': 67108864,
'log-size': lsize })
vm.shutdown()

View File

@ -1,121 +1,169 @@
QA output created by 213
=== Successful image creation (defaults) === === Successful image creation (defaults) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT {'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_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 128M (134217728 bytes) virtual size: 128M (134217728 bytes)
cluster_size: 8388608
=== Successful image creation (explicit defaults) === === Successful image creation (explicit defaults) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
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 file format: IMGFMT
virtual size: 64M (67108864 bytes) virtual size: 64M (67108864 bytes)
cluster_size: 8388608
=== Successful image creation (with non-default options) === === Successful image creation (with non-default options) ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT {'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_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 32M (33554432 bytes) virtual size: 32M (33554432 bytes)
cluster_size: 268435456
=== Invalid BlockdevRef === === Invalid BlockdevRef ===
Testing: {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
=== Zero size === === Zero size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT image: TEST_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 0 (0 bytes) virtual size: 0 (0 bytes)
cluster_size: 8388608
=== Maximum size === === Maximum size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}}
QMP_VERSION {u'return': {}}
{"return": {}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"return": {}} {u'return': {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: TEST_DIR/t.IMGFMT image: TEST_IMG
file format: IMGFMT file format: IMGFMT
virtual size: 64T (70368744177664 bytes) virtual size: 64T (70368744177664 bytes)
cluster_size: 67108864
=== Invalid sizes === === Invalid sizes ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Image size too large; max of 64TB
{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}} {u'return': {}}
{"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': 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 === === Invalid block size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Block size must be a multiple of 1 MB
{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}} {u'return': {}}
{"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': 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 === === Invalid log size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0 {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
QMP_VERSION {u'return': {}}
{"return": {}} Job failed: Log size must be a multiple of 1 MB
{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}} {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}} {u'return': {}}
{"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"}} {'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
{"return": {}} {u'return': {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}} 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': {}}
*** done

View File

@ -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)))) sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
return subp.communicate()[0] 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): def qemu_io(*args):
'''Run qemu-io and return the stdout data''' '''Run qemu-io and return the stdout data'''
args = qemu_io_args + list(args) args = qemu_io_args + list(args)
@ -206,6 +220,22 @@ def filter_qmp_event(event):
event['timestamp']['microseconds'] = 'USECS' event['timestamp']['microseconds'] = 'USECS'
return event 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=[]): def log(msg, filters=[]):
for flt in filters: for flt in filters:
msg = flt(msg) msg = flt(msg)
@ -281,6 +311,13 @@ def file_path(*names):
return paths[0] if len(paths) == 1 else paths 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): class VM(qtest.QEMUQtestMachine):
'''A QEMU VM''' '''A QEMU VM'''
@ -383,6 +420,37 @@ class VM(qtest.QEMUQtestMachine):
output_list += [key + '=' + obj[key]] output_list += [key + '=' + obj[key]]
return ','.join(output_list) 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'([^\[]+)\[([^\]]+)\]') 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): if not_sup or (imgfmt in unsupported_fmts):
notrun('not suitable for this image format: %s' % imgfmt) 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']): def verify_platform(supported_oses=['linux']):
if True not in [sys.platform.startswith(x) for x in supported_oses]: if True not in [sys.platform.startswith(x) for x in supported_oses]:
notrun('not suitable for this OS: %s' % sys.platform) notrun('not suitable for this OS: %s' % sys.platform)

View File

@ -498,7 +498,7 @@ typedef struct TestBlockJob {
static void test_job_completed(Job *job, void *opaque) 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) static void coroutine_fn test_job_start(void *opaque)

View File

@ -34,7 +34,7 @@ static void test_block_job_complete(Job *job, void *opaque)
rc = -ECANCELED; rc = -ECANCELED;
} }
job_completed(job, rc); job_completed(job, rc, NULL);
bdrv_unref(bs); bdrv_unref(bs);
} }

View File

@ -167,7 +167,7 @@ static void cancel_job_completed(Job *job, void *opaque)
{ {
CancelJob *s = opaque; CancelJob *s = opaque;
s->completed = true; s->completed = true;
job_completed(job, 0); job_completed(job, 0, NULL);
} }
static void cancel_job_complete(Job *job, Error **errp) static void cancel_job_complete(Job *job, Error **errp)