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;
job_completed(job, data->ret);
job_completed(job, data->ret, NULL);
g_free(data);
}

View File

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

View File

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

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_insert_bs(bjob->blk, mirror_top_bs, &error_abort);
job_completed(job, data->ret);
job_completed(job, data->ret, NULL);
g_free(data);
bdrv_drained_end(src);

View File

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

View File

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

View File

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

View File

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

View File

@ -124,6 +124,9 @@ typedef struct Job {
/** Estimated progress_current value at the completion of the job */
int64_t progress_total;
/** Error string for a failed job (NULL if, and only if, job->ret == 0) */
char *error;
/** ret code passed to job_completed. */
int ret;
@ -466,13 +469,15 @@ void job_transition_to_ready(Job *job);
/**
* @job: The job being completed.
* @ret: The status code.
* @error: The error message for a failing job (only with @ret < 0). If @ret is
* negative, but NULL is given for @error, strerror() is used.
*
* Marks @job as completed. If @ret is non-zero, the job transaction it is part
* of is aborted. If @ret is zero, the job moves into the WAITING state. If it
* is the last job to complete in its transaction, all jobs in the transaction
* move from WAITING to PENDING.
*/
void job_completed(Job *job, int ret);
void job_completed(Job *job, int ret, Error *error);
/** Asynchronously complete the specified @job. */
void job_complete(Job *job, Error **errp);

View File

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

16
job.c
View File

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

View File

@ -4011,16 +4011,20 @@
} }
##
# @x-blockdev-create:
# @blockdev-create:
#
# Create an image format on a given node.
# TODO Replace with something asynchronous (block job?)
# Starts a job to create an image format on a given node. The job is
# automatically finalized, but a manual job-dismiss is required.
#
# Since: 2.12
# @job-id: Identifier for the newly created job.
#
# @options: Options for the image creation.
#
# Since: 3.0
##
{ 'command': 'x-blockdev-create',
'data': 'BlockdevCreateOptions',
'boxed': true }
{ 'command': 'blockdev-create',
'data': { 'job-id': 'str',
'options': 'BlockdevCreateOptions' } }
##
# @blockdev-open-tray:

View File

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

View File

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

View File

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

View File

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

View File

@ -1,75 +1,80 @@
QA output created by 207
=== Successful image creation (defaults) ===
Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
image: TEST_DIR/t.IMGFMT
image: TEST_IMG
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
=== Test host-key-check options ===
Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 8.0M (8388608 bytes)
Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'known_hosts'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
Testing:
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "remote host key does not match host_key_check 'wrong'"}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}}
{u'return': {}}
Job failed: remote host key does not match host_key_check 'wrong'
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 8.0M (8388608 bytes)
Testing:
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "remote host key does not match host_key_check 'wrong'"}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_DIR/t.IMGFMT"}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}}
{u'return': {}}
Job failed: remote host key does not match host_key_check 'wrong'
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}}
file format: IMGFMT
virtual size: 4.0M (4194304 bytes)
=== Invalid path and user ===
Testing:
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)"}}
{"error": {"class": "GenericError", "desc": "failed to authenticate using publickey authentication and the identities held by your ssh-agent"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': '/this/is/not/an/existing/path', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
{u'return': {}}
Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31)
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'user': 'invalid user', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}}
{u'return': {}}
Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
*** done

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,121 +1,169 @@
QA output created by 213
=== Successful image creation (defaults) ===
Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
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
virtual size: 128M (134217728 bytes)
cluster_size: 8388608
=== Successful image creation (explicit defaults) ===
Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: TEST_DIR/t.IMGFMT
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': True, 'size': 67108864}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: TEST_IMG
file format: IMGFMT
virtual size: 64M (67108864 bytes)
cluster_size: 8388608
=== Successful image creation (with non-default options) ===
Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
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
virtual size: 32M (33554432 bytes)
cluster_size: 268435456
=== Invalid BlockdevRef ===
Testing:
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "Cannot find device=this doesn't exist nor node_name=this doesn't exist"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}}
{u'return': {}}
Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
=== Zero size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: TEST_DIR/t.IMGFMT
image: TEST_IMG
file format: IMGFMT
virtual size: 0 (0 bytes)
cluster_size: 8388608
=== Maximum size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
QMP_VERSION
{"return": {}}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}}
{u'return': {}}
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
image: TEST_DIR/t.IMGFMT
image: TEST_IMG
file format: IMGFMT
virtual size: 64T (70368744177664 bytes)
cluster_size: 67108864
=== Invalid sizes ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}}
{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}}
{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}}
{"error": {"class": "GenericError", "desc": "Image size too large; max of 64TB"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}}
{u'return': {}}
Job failed: Image size too large; max of 64TB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775808L}}}
{u'return': {}}
Job failed: Image size too large; max of 64TB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775296}}}
{u'return': {}}
Job failed: Image size too large; max of 64TB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177665}}}
{u'return': {}}
Job failed: Image size too large; max of 64TB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
=== Invalid block size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}}
{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}}
{"error": {"class": "GenericError", "desc": "Block size must be a power of two"}}
{"error": {"class": "GenericError", "desc": "Block size must not exceed 268435456"}}
{"error": {"class": "GenericError", "desc": "Block size must be a multiple of 1 MB"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Block size must be a multiple of 1 MB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 128, 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Block size must be a multiple of 1 MB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 3145728, 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Block size must be a power of two
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 536870912, 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Block size must not exceed 268435456
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 0, 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Block size must be a multiple of 1 MB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
=== Invalid log size ===
Testing: -blockdev driver=file,filename=TEST_DIR/t.IMGFMT,node-name=node0
QMP_VERSION
{"return": {}}
{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}}
{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}}
{"error": {"class": "GenericError", "desc": "Log size must be smaller than 4 GB"}}
{"error": {"class": "GenericError", "desc": "Log size must be a multiple of 1 MB"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Log size must be a multiple of 1 MB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Log size must be a multiple of 1 MB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 4294967296, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Log size must be smaller than 4 GB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 0, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}}
{u'return': {}}
Job failed: Log size must be a multiple of 1 MB
{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}}
{u'return': {}}
*** 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))))
return subp.communicate()[0]
def img_info_log(filename, filter_path=None, imgopts=False, extra_args=[]):
args = [ 'info' ]
if imgopts:
args.append('--image-opts')
else:
args += [ '-f', imgfmt ]
args += extra_args
args.append(filename)
output = qemu_img_pipe(*args)
if not filter_path:
filter_path = filename
log(filter_img_info(output, filter_path))
def qemu_io(*args):
'''Run qemu-io and return the stdout data'''
args = qemu_io_args + list(args)
@ -206,6 +220,22 @@ def filter_qmp_event(event):
event['timestamp']['microseconds'] = 'USECS'
return event
def filter_testfiles(msg):
prefix = os.path.join(test_dir, "%s-" % (os.getpid()))
return msg.replace(prefix, 'TEST_DIR/PID-')
def filter_img_info(output, filename):
lines = []
for line in output.split('\n'):
if 'disk size' in line or 'actual-size' in line:
continue
line = line.replace(filename, 'TEST_IMG') \
.replace(imgfmt, 'IMGFMT')
line = re.sub('iters: [0-9]+', 'iters: XXX', line)
line = re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', line)
lines.append(line)
return '\n'.join(lines)
def log(msg, filters=[]):
for flt in filters:
msg = flt(msg)
@ -281,6 +311,13 @@ def file_path(*names):
return paths[0] if len(paths) == 1 else paths
def remote_filename(path):
if imgproto == 'file':
return path
elif imgproto == 'ssh':
return "ssh://127.0.0.1%s" % (path)
else:
raise Exception("Protocol %s not supported" % (imgproto))
class VM(qtest.QEMUQtestMachine):
'''A QEMU VM'''
@ -383,6 +420,37 @@ class VM(qtest.QEMUQtestMachine):
output_list += [key + '=' + obj[key]]
return ','.join(output_list)
def get_qmp_events_filtered(self, wait=True):
result = []
for ev in self.get_qmp_events(wait=wait):
result.append(filter_qmp_event(ev))
return result
def qmp_log(self, cmd, filters=[filter_testfiles], **kwargs):
logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs)
log(logmsg, filters)
result = self.qmp(cmd, **kwargs)
log(str(result), filters)
return result
def run_job(self, job, auto_finalize=True, auto_dismiss=False):
while True:
for ev in self.get_qmp_events_filtered(wait=True):
if ev['event'] == 'JOB_STATUS_CHANGE':
status = ev['data']['status']
if status == 'aborting':
result = self.qmp('query-jobs')
for j in result['return']:
if j['id'] == job:
log('Job failed: %s' % (j['error']))
elif status == 'pending' and not auto_finalize:
self.qmp_log('job-finalize', id=job)
elif status == 'concluded' and not auto_dismiss:
self.qmp_log('job-dismiss', id=job)
elif status == 'null':
return
else:
iotests.log(ev)
index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')
@ -548,6 +616,16 @@ def verify_image_format(supported_fmts=[], unsupported_fmts=[]):
if not_sup or (imgfmt in unsupported_fmts):
notrun('not suitable for this image format: %s' % imgfmt)
def verify_protocol(supported=[], unsupported=[]):
assert not (supported and unsupported)
if 'generic' in supported:
return
not_sup = supported and (imgproto not in supported)
if not_sup or (imgproto in unsupported):
notrun('not suitable for this protocol: %s' % imgproto)
def verify_platform(supported_oses=['linux']):
if True not in [sys.platform.startswith(x) for x in supported_oses]:
notrun('not suitable for this OS: %s' % sys.platform)

View File

@ -498,7 +498,7 @@ typedef struct TestBlockJob {
static void test_job_completed(Job *job, void *opaque)
{
job_completed(job, 0);
job_completed(job, 0, NULL);
}
static void coroutine_fn test_job_start(void *opaque)

View File

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

View File

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