mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-21 21:25:25 +00:00
4281362a96
Add two test images showing the use of 'data_file' and 'data_file_raw' (although the latter is not detected by libvirt) so that we can see that the qcow2 metadata parser and backing chain populators work correctly. The example files were created by: qemu-img create -f qcow2 -o data_file=raw,data_file_raw=true,preallocation=off datafile.qcow2 1k qemu-img create -f qcow2 -o data_file=rawpreallocation=off -F qcow2 -b datafile.qcow2 qcow2datafile-datafile.qcow2 Note that 'data_file_raw' is mutually exclusive with backing images. Signed-off-by: Nikolai Barybin <nikolai.barybin@virtuozzo.com> Reviewed-by: Peter Krempa <pkrempa@redhat.com> Signed-off-by: Peter Krempa <pkrempa@redhat.com>
1231 lines
56 KiB
C
1231 lines
56 KiB
C
/*
|
|
* Copyright (C) 2013-2014 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "storage_source.h"
|
|
#include "testutils.h"
|
|
#include "vircommand.h"
|
|
#include "virfile.h"
|
|
#include "virlog.h"
|
|
|
|
#include "storage/storage_driver.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
VIR_LOG_INIT("tests.storagetest");
|
|
|
|
#define datadir abs_builddir "/virstoragedata"
|
|
|
|
static void
|
|
testCleanupImages(void)
|
|
{
|
|
if (chdir(abs_builddir) < 0) {
|
|
fprintf(stderr, "unable to return to correct directory, refusing to "
|
|
"clean up %s\n", datadir);
|
|
return;
|
|
}
|
|
|
|
virFileDeleteTree(datadir);
|
|
}
|
|
|
|
|
|
static virStorageSource *
|
|
testStorageFileGetMetadata(const char *path,
|
|
int format,
|
|
uid_t uid, gid_t gid)
|
|
{
|
|
struct stat st;
|
|
g_autoptr(virStorageSource) def = virStorageSourceNew();
|
|
|
|
def->type = VIR_STORAGE_TYPE_FILE;
|
|
def->format = format;
|
|
|
|
if (stat(path, &st) == 0) {
|
|
if (S_ISDIR(st.st_mode)) {
|
|
def->type = VIR_STORAGE_TYPE_DIR;
|
|
} else if (S_ISBLK(st.st_mode)) {
|
|
def->type = VIR_STORAGE_TYPE_BLOCK;
|
|
}
|
|
}
|
|
|
|
def->path = g_strdup(path);
|
|
|
|
/* 20 is picked as an arbitrary depth, since the chains used here don't exceed it */
|
|
if (virStorageSourceGetMetadata(def, uid, gid, 20, true) < 0)
|
|
return NULL;
|
|
|
|
return g_steal_pointer(&def);
|
|
}
|
|
|
|
static char *
|
|
testPrepImages(void)
|
|
{
|
|
g_autoptr(virCommand) cmdraw = NULL;
|
|
g_autoptr(virCommand) cmdqcow2 = NULL;
|
|
g_autoptr(virCommand) cmdwrap = NULL;
|
|
g_autofree char *absraw = g_strdup_printf("%s/raw", datadir);
|
|
g_autofree char *absqcow2 = g_strdup_printf("%s/qcow2", datadir);
|
|
g_autofree char *abswrap = g_strdup_printf("%s/wrap", datadir);
|
|
g_autofree char *qemuimg = virFindFileInPath("qemu-img");
|
|
|
|
if (!qemuimg)
|
|
return NULL;
|
|
|
|
/* Clean up from any earlier failed tests */
|
|
virFileDeleteTree(datadir);
|
|
|
|
if (g_mkdir_with_parents(datadir, 0777) < 0) {
|
|
VIR_TEST_VERBOSE("unable to create directory '%s'\n", datadir);
|
|
return NULL;
|
|
}
|
|
|
|
/* create the following real backing chain with qcow2 images with absolute
|
|
* backing and different qcow2 versions:
|
|
* datadir/raw <- datadir/qcow2 (qcow2v2) <- datadir/wrap (qcow2v3) */
|
|
cmdraw = virCommandNewArgList(qemuimg, "create",
|
|
"-f", "raw",
|
|
absraw, "1k", NULL);
|
|
|
|
cmdqcow2 = virCommandNewArgList(qemuimg, "create",
|
|
"-f", "qcow2",
|
|
"-F", "raw",
|
|
"-b", absraw,
|
|
"-o", "compat=0.10",
|
|
absqcow2, NULL);
|
|
|
|
cmdwrap = virCommandNewArgList(qemuimg, "create",
|
|
"-f", "qcow2",
|
|
"-F", "qcow2",
|
|
"-b", absqcow2,
|
|
"-o", "compat=1.1",
|
|
abswrap, NULL);
|
|
|
|
if (virCommandRun(cmdraw, NULL) < 0 ||
|
|
virCommandRun(cmdqcow2, NULL) < 0 ||
|
|
virCommandRun(cmdwrap, NULL) < 0) {
|
|
VIR_TEST_VERBOSE("failed to create backing chain in '%s'\n", datadir);
|
|
return NULL;
|
|
}
|
|
|
|
return g_steal_pointer(&abswrap);
|
|
}
|
|
|
|
|
|
enum {
|
|
EXP_PASS = 0,
|
|
EXP_FAIL = 1,
|
|
};
|
|
|
|
struct testChainData
|
|
{
|
|
const char *testname;
|
|
const char *start;
|
|
virStorageFileFormat format;
|
|
unsigned int flags;
|
|
};
|
|
|
|
|
|
static int
|
|
testStorageChain(const void *args)
|
|
{
|
|
const struct testChainData *data = args;
|
|
virStorageSource *elt;
|
|
g_autoptr(virStorageSource) meta = NULL;
|
|
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
|
g_autofree char *actual = NULL;
|
|
g_autofree char *expectpath = g_strdup_printf("%s/virstoragetestdata/out/%s",
|
|
abs_srcdir, data->testname);
|
|
|
|
/* If the filename is NULL it means that the images couldn't be created,
|
|
* thus skip this particular test. */
|
|
if (!data->start)
|
|
return EXIT_AM_SKIP;
|
|
|
|
meta = testStorageFileGetMetadata(data->start, data->format, -1, -1);
|
|
if (!meta) {
|
|
if (data->flags & EXP_FAIL) {
|
|
virResetLastError();
|
|
return 0;
|
|
}
|
|
return -1;
|
|
} else if (data->flags & EXP_FAIL) {
|
|
fprintf(stderr, "call should have failed\n");
|
|
return -1;
|
|
}
|
|
|
|
if (virGetLastErrorCode()) {
|
|
fprintf(stderr, "call should not have reported error\n");
|
|
return -1;
|
|
}
|
|
|
|
for (elt = meta; virStorageSourceIsBacking(elt); elt = elt->backingStore) {
|
|
g_autofree char *strippedPath = virTestStablePath(elt->path);
|
|
g_autofree char *strippedBackingStoreRaw = virTestStablePath(elt->backingStoreRaw);
|
|
g_autofree char *strippedRelPath = virTestStablePath(elt->relPath);
|
|
|
|
virBufferAsprintf(&buf,
|
|
"path:%s\n"
|
|
"backingStoreRaw: %s\n"
|
|
"backingStoreRawFormat: %s(%d)\n"
|
|
"capacity: %lld\n"
|
|
"encryption: %d\n"
|
|
"relPath:%s\n"
|
|
"type:%s\n"
|
|
"format:%s\n"
|
|
"protocol:%s\n"
|
|
"hostname:%s\n\n",
|
|
strippedPath,
|
|
strippedBackingStoreRaw,
|
|
NULLSTR(virStorageFileFormatTypeToString(elt->backingStoreRawFormat)),
|
|
elt->backingStoreRawFormat,
|
|
elt->capacity,
|
|
!!elt->encryption,
|
|
strippedRelPath,
|
|
NULLSTR(virStorageTypeToString(elt->type)),
|
|
NULLSTR(virStorageFileFormatTypeToString(elt->format)),
|
|
virStorageNetProtocolTypeToString(elt->protocol),
|
|
NULLSTR(elt->nhosts ? elt->hosts[0].name : NULL));
|
|
|
|
if (elt->dataFileStore) {
|
|
g_autofree char *strippedPathDataFileRaw = virTestStablePath(elt->dataFileRaw);
|
|
g_autofree char *strippedPathDataFile = virTestStablePath(elt->dataFileStore->path);
|
|
|
|
virBufferAsprintf(&buf,
|
|
"dataFileRaw: %s\n\n\n"
|
|
"dataFileStoreSource:\n"
|
|
"path: %s\n"
|
|
"capacity: %lld\n"
|
|
"encryption: %d\n"
|
|
"type:%s\n"
|
|
"format:%s\n",
|
|
strippedPathDataFileRaw,
|
|
strippedPathDataFile,
|
|
elt->dataFileStore->capacity,
|
|
!!elt->dataFileStore->encryption,
|
|
NULLSTR(virStorageTypeToString(elt->dataFileStore->type)),
|
|
NULLSTR(virStorageFileFormatTypeToString(elt->dataFileStore->format)));
|
|
}
|
|
}
|
|
|
|
virBufferTrim(&buf, "\n");
|
|
|
|
actual = virBufferContentAndReset(&buf);
|
|
|
|
if (virTestCompareToFile(actual, expectpath) < 0)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct testLookupData
|
|
{
|
|
virStorageSource *chain;
|
|
const char *target;
|
|
virStorageSource *from;
|
|
const char *name;
|
|
unsigned int expIndex;
|
|
virStorageSource *expMeta;
|
|
virStorageSource *expParent;
|
|
};
|
|
|
|
static int
|
|
testStorageLookup(const void *args)
|
|
{
|
|
const struct testLookupData *data = args;
|
|
int ret = 0;
|
|
virStorageSource *result;
|
|
virStorageSource *actualParent;
|
|
|
|
result = virStorageSourceChainLookup(data->chain, data->from,
|
|
data->name, data->target, &actualParent);
|
|
if (!data->expMeta)
|
|
virResetLastError();
|
|
|
|
if (data->expMeta != result) {
|
|
fprintf(stderr, "meta: expected %s, got %s\n",
|
|
NULLSTR(data->expMeta ? data->expMeta->path : NULL),
|
|
NULLSTR(result ? result->path : NULL));
|
|
ret = -1;
|
|
}
|
|
|
|
if (data->expIndex > 0) {
|
|
if (!result) {
|
|
fprintf(stderr, "index: resulting lookup is empty, can't match index\n");
|
|
ret = -1;
|
|
} else {
|
|
if (result->id != data->expIndex) {
|
|
fprintf(stderr, "index: expected %u, got %u\n", data->expIndex, result->id);
|
|
ret = -1;
|
|
}
|
|
}
|
|
}
|
|
if (data->expParent != actualParent) {
|
|
fprintf(stderr, "parent: expected %s, got %s\n",
|
|
NULLSTR(data->expParent ? data->expParent->path : NULL),
|
|
NULLSTR(actualParent ? actualParent->path : NULL));
|
|
ret = -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static virStorageSource backingchain[12];
|
|
|
|
static void
|
|
testPathRelativePrepare(void)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS(backingchain); i++) {
|
|
backingchain[i].type = VIR_STORAGE_TYPE_FILE;
|
|
if (i < G_N_ELEMENTS(backingchain) - 1)
|
|
backingchain[i].backingStore = &backingchain[i + 1];
|
|
else
|
|
backingchain[i].backingStore = NULL;
|
|
|
|
backingchain[i].relPath = NULL;
|
|
}
|
|
|
|
/* normal relative backing chain */
|
|
backingchain[0].path = (char *) "/path/to/some/img";
|
|
|
|
backingchain[1].path = (char *) "/path/to/some/asdf";
|
|
backingchain[1].relPath = (char *) "asdf";
|
|
|
|
backingchain[2].path = (char *) "/path/to/some/test";
|
|
backingchain[2].relPath = (char *) "test";
|
|
|
|
backingchain[3].path = (char *) "/path/to/some/blah";
|
|
backingchain[3].relPath = (char *) "blah";
|
|
|
|
/* ovirt's backing chain */
|
|
backingchain[4].path = (char *) "/path/to/volume/image1";
|
|
|
|
backingchain[5].path = (char *) "/path/to/volume/image2";
|
|
backingchain[5].relPath = (char *) "../volume/image2";
|
|
|
|
backingchain[6].path = (char *) "/path/to/volume/image3";
|
|
backingchain[6].relPath = (char *) "../volume/image3";
|
|
|
|
backingchain[7].path = (char *) "/path/to/volume/image4";
|
|
backingchain[7].relPath = (char *) "../volume/image4";
|
|
|
|
/* some arbitrarily crazy backing chains */
|
|
backingchain[8].path = (char *) "/crazy/base/image";
|
|
|
|
backingchain[9].path = (char *) "/crazy/base/directory/stuff/volumes/garbage/image2";
|
|
backingchain[9].relPath = (char *) "directory/stuff/volumes/garbage/image2";
|
|
|
|
backingchain[10].path = (char *) "/crazy/base/directory/image3";
|
|
backingchain[10].relPath = (char *) "../../../image3";
|
|
|
|
backingchain[11].path = (char *) "/crazy/base/blah/image4";
|
|
backingchain[11].relPath = (char *) "../blah/image4";
|
|
}
|
|
|
|
|
|
struct testPathRelativeBacking
|
|
{
|
|
virStorageSource *top;
|
|
virStorageSource *base;
|
|
|
|
const char *expect;
|
|
};
|
|
|
|
static int
|
|
testPathRelative(const void *args)
|
|
{
|
|
const struct testPathRelativeBacking *data = args;
|
|
g_autofree char *actual = NULL;
|
|
|
|
if (virStorageSourceGetRelativeBackingPath(data->top,
|
|
data->base,
|
|
&actual) < 0) {
|
|
fprintf(stderr, "relative backing path resolution failed\n");
|
|
return -1;
|
|
}
|
|
|
|
if (STRNEQ_NULLABLE(data->expect, actual)) {
|
|
fprintf(stderr, "relative path resolution from '%s' to '%s': "
|
|
"expected '%s', got '%s'\n",
|
|
data->top->path, data->base->path,
|
|
NULLSTR(data->expect), NULLSTR(actual));
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
struct testBackingParseData {
|
|
const char *backing;
|
|
const char *expect;
|
|
int rv;
|
|
};
|
|
|
|
static int
|
|
testBackingParse(const void *args)
|
|
{
|
|
const struct testBackingParseData *data = args;
|
|
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
|
|
g_autofree char *xml = NULL;
|
|
g_autoptr(virStorageSource) src = NULL;
|
|
int rc;
|
|
int erc = data->rv;
|
|
unsigned int xmlformatflags = VIR_DOMAIN_DEF_FORMAT_SECURE;
|
|
|
|
/* expect failure return code with NULL expected data */
|
|
if (!data->expect)
|
|
erc = -1;
|
|
|
|
if ((rc = virStorageSourceNewFromBackingAbsolute(data->backing, &src)) != erc) {
|
|
fprintf(stderr, "expected return value '%d' actual '%d'\n", erc, rc);
|
|
return -1;
|
|
}
|
|
|
|
if (!src)
|
|
return 0;
|
|
|
|
if (src && !data->expect) {
|
|
fprintf(stderr, "parsing of backing store string '%s' should "
|
|
"have failed\n", data->backing);
|
|
return -1;
|
|
}
|
|
|
|
if (virDomainDiskSourceFormat(&buf, src, "source", 0, false, xmlformatflags,
|
|
false, false, NULL) < 0 ||
|
|
!(xml = virBufferContentAndReset(&buf))) {
|
|
fprintf(stderr, "failed to format disk source xml\n");
|
|
return -1;
|
|
}
|
|
|
|
if (STRNEQ(xml, data->expect)) {
|
|
fprintf(stderr, "\n backing store string '%s'\n"
|
|
"expected storage source xml:\n%s\n"
|
|
"actual storage source xml:\n%s\n",
|
|
data->backing, data->expect, xml);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
mymain(void)
|
|
{
|
|
int ret = 0;
|
|
struct testChainData data;
|
|
struct testLookupData data2;
|
|
struct testPathRelativeBacking data4;
|
|
struct testBackingParseData data5;
|
|
g_autofree char *realchain = NULL;
|
|
virStorageSource fakeChain[4];
|
|
virStorageSource *chain = &fakeChain[0];
|
|
virStorageSource *chain2 = &fakeChain[1];
|
|
virStorageSource *chain3 = &fakeChain[2];
|
|
|
|
if (storageRegisterAll() < 0)
|
|
return EXIT_FAILURE;
|
|
|
|
#define TEST_CHAIN(testname, start, format, flags) \
|
|
do { \
|
|
data = (struct testChainData){ testname, start, format, flags }; \
|
|
if (virTestRun(testname, testStorageChain, &data) < 0) \
|
|
ret = -1; \
|
|
} while (0)
|
|
|
|
/* Missing file */
|
|
TEST_CHAIN("missing", "bogus", VIR_STORAGE_FILE_RAW, EXP_FAIL);
|
|
|
|
/* Raw image, whether with right format or no specified format */
|
|
TEST_CHAIN("raw-raw",
|
|
abs_srcdir "/virstoragetestdata/images/raw",
|
|
VIR_STORAGE_FILE_RAW, EXP_PASS);
|
|
TEST_CHAIN("raw-auto",
|
|
abs_srcdir "/virstoragetestdata/images/raw",
|
|
VIR_STORAGE_FILE_AUTO, EXP_PASS);
|
|
|
|
/* Qcow2 file with relative raw backing, format provided */
|
|
TEST_CHAIN("qcow2-qcow2_raw-raw-relative",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2_raw-raw-relative.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
TEST_CHAIN("qcow2-auto_raw-raw-relative",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2_raw-raw-relative.qcow2",
|
|
VIR_STORAGE_FILE_AUTO, EXP_PASS);
|
|
|
|
/* qcow2 chain with absolute backing formatted with a real qemu-img */
|
|
|
|
/* Prep some files with qemu-img; if that is not found on PATH, the test
|
|
* using the data skips itself if the data can't be prepared */
|
|
realchain = testPrepImages();
|
|
|
|
TEST_CHAIN("qcow2-qcow2_qcow2-qcow2_raw-raw", realchain, VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
TEST_CHAIN("qcow2-auto_qcow2-qcow2_raw-raw", realchain, VIR_STORAGE_FILE_AUTO, EXP_PASS);
|
|
|
|
testCleanupImages();
|
|
|
|
/* qcow2 + datafile
|
|
* 1) qcow2 image with data file
|
|
* 2) qcow2 -> qcow2 backing image with data file */
|
|
TEST_CHAIN("qcow2-datafile",
|
|
abs_srcdir "/virstoragetestdata/images/datafile.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
TEST_CHAIN("qcow2datafile-qcow2_qcow2-datafile",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2datafile-datafile.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
|
|
/* Test various combinations of qcow2 images with missing 'backing_format' */
|
|
TEST_CHAIN("qcow2-qcow2_qcow2-qcow2_qcow2-auto",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2_qcow2-qcow2_qcow2-auto.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
TEST_CHAIN("qcow2-qcow2_qcow2-qcow2_raw-auto",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2_qcow2-qcow2_raw-auto.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
TEST_CHAIN("qcow2-qcow2_qcow2-auto_qcow2-auto",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2_qcow2-auto_qcow2-auto.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_FAIL);
|
|
TEST_CHAIN("qcow2-qcow2_qcow2-auto",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2_qcow2-auto.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
|
|
/* QCOW2 with protocol recorded inside the 'backing file format field */
|
|
TEST_CHAIN("qcow2-protocol-backing-file",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2-protocol-backing-file.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
TEST_CHAIN("qcow2-protocol-backing-nbd",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2-protocol-backing-nbd.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
|
|
/* Qcow2 file with missing backing file but specified type */
|
|
TEST_CHAIN("qcow2-qcow2_missing",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2_qcow2-missing.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_FAIL);
|
|
|
|
/* Qcow2 file with backing protocol instead of file */
|
|
TEST_CHAIN("qcow2-qcow2_nbd-raw",
|
|
abs_srcdir "/virstoragetestdata/images/qcow2_nbd-raw.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
|
|
/* qed file */
|
|
TEST_CHAIN("qed-qed_raw",
|
|
abs_srcdir "/virstoragetestdata/images/qed_raw-raw-relative",
|
|
VIR_STORAGE_FILE_QED, EXP_PASS);
|
|
TEST_CHAIN("qed-auto_raw",
|
|
abs_srcdir "/virstoragetestdata/images/qed_raw-raw-relative",
|
|
VIR_STORAGE_FILE_AUTO, EXP_PASS);
|
|
|
|
/* directory */
|
|
TEST_CHAIN("directory-raw", abs_srcdir "/virstoragetestdata/images/", VIR_STORAGE_FILE_RAW, EXP_PASS);
|
|
TEST_CHAIN("directory-none", abs_srcdir "/virstoragetestdata/images/", VIR_STORAGE_FILE_NONE, EXP_PASS);
|
|
TEST_CHAIN("directory-dir", abs_srcdir "/virstoragetestdata/images/", VIR_STORAGE_FILE_DIR, EXP_PASS);
|
|
|
|
/* Behavior of symlinks to qcow2 with relative backing files */
|
|
TEST_CHAIN("qcow2-symlinks",
|
|
abs_srcdir "/virstoragetestdata/images/sub/link2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_PASS);
|
|
|
|
/* Behavior of an infinite loop chain */
|
|
TEST_CHAIN("qcow2-qcow2_infinite-self",
|
|
abs_srcdir "/virstoragetestdata/images/loop-self.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_FAIL);
|
|
TEST_CHAIN("qcow2-qcow2_infinite-mutual",
|
|
abs_srcdir "/virstoragetestdata/images/loop-2.qcow2",
|
|
VIR_STORAGE_FILE_QCOW2, EXP_FAIL);
|
|
|
|
/* setup data for backing chain lookup testing */
|
|
if (chdir(abs_srcdir "/virstoragetestdata/lookup") < 0) {
|
|
VIR_TEST_VERBOSE("failed to chdir into '%s'\n",
|
|
abs_srcdir "/virstoragetestdata/lookup");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
memset(fakeChain, 0, sizeof(fakeChain));
|
|
fakeChain[0].backingStore = &fakeChain[1];
|
|
fakeChain[1].backingStore = &fakeChain[2];
|
|
fakeChain[2].backingStore = &fakeChain[3];
|
|
|
|
fakeChain[0].type = VIR_STORAGE_TYPE_FILE;
|
|
fakeChain[1].type = VIR_STORAGE_TYPE_FILE;
|
|
fakeChain[2].type = VIR_STORAGE_TYPE_FILE;
|
|
|
|
fakeChain[0].format = VIR_STORAGE_FILE_QCOW2;
|
|
fakeChain[1].format = VIR_STORAGE_FILE_QCOW2;
|
|
fakeChain[2].format = VIR_STORAGE_FILE_RAW;
|
|
|
|
/* backing chain with relative start and absolute backing paths */
|
|
fakeChain[0].path = (char *) "wrap";
|
|
fakeChain[1].path = (char *) abs_srcdir "/virstoragetestdata/lookup/qcow2";
|
|
fakeChain[2].path = (char *) abs_srcdir "/virstoragetestdata/lookup/raw";
|
|
|
|
#define TEST_LOOKUP_TARGET(id, target, from, name, index, meta, parent) \
|
|
do { \
|
|
data2 = (struct testLookupData){ \
|
|
chain, target, from, name, index, meta, parent, }; \
|
|
if (virTestRun("Chain lookup " #id, testStorageLookup, &data2) < 0) \
|
|
ret = -1; \
|
|
} while (0)
|
|
#define TEST_LOOKUP(id, from, name, meta, parent) \
|
|
TEST_LOOKUP_TARGET(id, NULL, from, name, 0, meta, parent)
|
|
|
|
TEST_LOOKUP(0, NULL, "bogus", NULL, NULL);
|
|
TEST_LOOKUP(1, chain, "bogus", NULL, NULL);
|
|
TEST_LOOKUP(2, NULL, "wrap", chain, NULL);
|
|
TEST_LOOKUP(3, chain, "wrap", NULL, NULL);
|
|
TEST_LOOKUP(4, chain2, "wrap", NULL, NULL);
|
|
TEST_LOOKUP(5, NULL, abs_srcdir "/virstoragetestdata/lookup/wrap", chain, NULL);
|
|
TEST_LOOKUP(6, chain, abs_srcdir "/virstoragetestdata/lookup/wrap", NULL, NULL);
|
|
TEST_LOOKUP(7, chain2, abs_srcdir "/virstoragetestdata/lookup/wrap", NULL, NULL);
|
|
TEST_LOOKUP(8, NULL, "qcow2", chain2, chain);
|
|
TEST_LOOKUP(9, chain, "qcow2", chain2, chain);
|
|
TEST_LOOKUP(10, chain2, "qcow2", NULL, NULL);
|
|
TEST_LOOKUP(11, chain3, "qcow2", NULL, NULL);
|
|
TEST_LOOKUP(12, NULL, abs_srcdir "/virstoragetestdata/lookup/qcow2", chain2, chain);
|
|
TEST_LOOKUP(13, chain, abs_srcdir "/virstoragetestdata/lookup/qcow2", chain2, chain);
|
|
TEST_LOOKUP(14, chain2, abs_srcdir "/virstoragetestdata/lookup/qcow2", NULL, NULL);
|
|
TEST_LOOKUP(15, chain3, abs_srcdir "/virstoragetestdata/lookup/qcow2", NULL, NULL);
|
|
TEST_LOOKUP(16, NULL, "raw", chain3, chain2);
|
|
TEST_LOOKUP(17, chain, "raw", chain3, chain2);
|
|
TEST_LOOKUP(18, chain2, "raw", chain3, chain2);
|
|
TEST_LOOKUP(19, chain3, "raw", NULL, NULL);
|
|
TEST_LOOKUP(20, NULL, abs_srcdir "/virstoragetestdata/lookup/raw", chain3, chain2);
|
|
TEST_LOOKUP(21, chain, abs_srcdir "/virstoragetestdata/lookup/raw", chain3, chain2);
|
|
TEST_LOOKUP(22, chain2, abs_srcdir "/virstoragetestdata/lookup/raw", chain3, chain2);
|
|
TEST_LOOKUP(23, chain3, abs_srcdir "/virstoragetestdata/lookup/raw", NULL, NULL);
|
|
TEST_LOOKUP(24, NULL, NULL, chain3, chain2);
|
|
TEST_LOOKUP(25, chain, NULL, chain3, chain2);
|
|
TEST_LOOKUP(26, chain2, NULL, chain3, chain2);
|
|
TEST_LOOKUP(27, chain3, NULL, NULL, NULL);
|
|
|
|
/* relative backing, absolute start */
|
|
fakeChain[0].path = (char *) abs_srcdir "/virstoragetestdata/lookup/wrap";
|
|
|
|
fakeChain[1].relPath = (char *) "qcow2";
|
|
fakeChain[2].relPath = (char *) "raw";
|
|
|
|
TEST_LOOKUP(28, NULL, "bogus", NULL, NULL);
|
|
TEST_LOOKUP(29, chain, "bogus", NULL, NULL);
|
|
TEST_LOOKUP(30, NULL, "wrap", chain, NULL);
|
|
TEST_LOOKUP(31, chain, "wrap", NULL, NULL);
|
|
TEST_LOOKUP(32, chain2, "wrap", NULL, NULL);
|
|
TEST_LOOKUP(33, NULL, abs_srcdir "/virstoragetestdata/lookup/wrap", chain, NULL);
|
|
TEST_LOOKUP(34, chain, abs_srcdir "/virstoragetestdata/lookup/wrap", NULL, NULL);
|
|
TEST_LOOKUP(35, chain2, abs_srcdir "/virstoragetestdata/lookup/wrap", NULL, NULL);
|
|
TEST_LOOKUP(36, NULL, "qcow2", chain2, chain);
|
|
TEST_LOOKUP(37, chain, "qcow2", chain2, chain);
|
|
TEST_LOOKUP(38, chain2, "qcow2", NULL, NULL);
|
|
TEST_LOOKUP(39, chain3, "qcow2", NULL, NULL);
|
|
TEST_LOOKUP(40, NULL, abs_srcdir "/virstoragetestdata/lookup/qcow2", chain2, chain);
|
|
TEST_LOOKUP(41, chain, abs_srcdir "/virstoragetestdata/lookup/qcow2", chain2, chain);
|
|
TEST_LOOKUP(42, chain2, abs_srcdir "/virstoragetestdata/lookup/qcow2", NULL, NULL);
|
|
TEST_LOOKUP(43, chain3, abs_srcdir "/virstoragetestdata/lookup/qcow2", NULL, NULL);
|
|
TEST_LOOKUP(44, NULL, "raw", chain3, chain2);
|
|
TEST_LOOKUP(45, chain, "raw", chain3, chain2);
|
|
TEST_LOOKUP(46, chain2, "raw", chain3, chain2);
|
|
TEST_LOOKUP(47, chain3, "raw", NULL, NULL);
|
|
TEST_LOOKUP(48, NULL, abs_srcdir "/virstoragetestdata/lookup/raw", chain3, chain2);
|
|
TEST_LOOKUP(49, chain, abs_srcdir "/virstoragetestdata/lookup/raw", chain3, chain2);
|
|
TEST_LOOKUP(50, chain2, abs_srcdir "/virstoragetestdata/lookup/raw", chain3, chain2);
|
|
TEST_LOOKUP(51, chain3, abs_srcdir "/virstoragetestdata/lookup/raw", NULL, NULL);
|
|
TEST_LOOKUP(52, NULL, NULL, chain3, chain2);
|
|
TEST_LOOKUP(53, chain, NULL, chain3, chain2);
|
|
TEST_LOOKUP(54, chain2, NULL, chain3, chain2);
|
|
TEST_LOOKUP(55, chain3, NULL, NULL, NULL);
|
|
|
|
/* Use link to wrap with cross-directory relative backing */
|
|
fakeChain[0].path = (char *) abs_srcdir "/virstoragetestdata/lookup/sub/link2";
|
|
|
|
fakeChain[1].relPath = (char *) "../qcow2";
|
|
fakeChain[2].relPath = (char *) "raw";
|
|
|
|
TEST_LOOKUP(56, NULL, "bogus", NULL, NULL);
|
|
TEST_LOOKUP(57, NULL, "sub/link2", chain, NULL);
|
|
TEST_LOOKUP(58, NULL, "wrap", chain, NULL);
|
|
TEST_LOOKUP(59, NULL, abs_srcdir "/virstoragetestdata/lookup/wrap", chain, NULL);
|
|
TEST_LOOKUP(60, NULL, "../qcow2", chain2, chain);
|
|
TEST_LOOKUP(61, NULL, "qcow2", NULL, NULL);
|
|
TEST_LOOKUP(62, NULL, abs_srcdir "/virstoragetestdata/lookup/qcow2", chain2, chain);
|
|
TEST_LOOKUP(63, NULL, "raw", chain3, chain2);
|
|
TEST_LOOKUP(64, NULL, abs_srcdir "/virstoragetestdata/lookup/raw", chain3, chain2);
|
|
TEST_LOOKUP(65, NULL, NULL, chain3, chain2);
|
|
|
|
/* index lookup */
|
|
fakeChain[0].id = 0;
|
|
fakeChain[1].id = 1;
|
|
fakeChain[2].id = 2;
|
|
|
|
TEST_LOOKUP_TARGET(66, "vda", NULL, "bogus[1]", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(67, "vda", NULL, "vda[-1]", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(68, "vda", NULL, "vda[1][1]", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(69, "vda", NULL, "wrap", 0, chain, NULL);
|
|
TEST_LOOKUP_TARGET(70, "vda", chain, "wrap", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(71, "vda", chain2, "wrap", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(72, "vda", NULL, "vda[0]", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(73, "vda", NULL, "vda[1]", 1, chain2, chain);
|
|
TEST_LOOKUP_TARGET(74, "vda", chain, "vda[1]", 1, chain2, chain);
|
|
TEST_LOOKUP_TARGET(75, "vda", chain2, "vda[1]", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(76, "vda", chain3, "vda[1]", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(77, "vda", NULL, "vda[2]", 2, chain3, chain2);
|
|
TEST_LOOKUP_TARGET(78, "vda", chain, "vda[2]", 2, chain3, chain2);
|
|
TEST_LOOKUP_TARGET(79, "vda", chain2, "vda[2]", 2, chain3, chain2);
|
|
TEST_LOOKUP_TARGET(80, "vda", chain3, "vda[2]", 0, NULL, NULL);
|
|
TEST_LOOKUP_TARGET(81, "vda", NULL, "vda[3]", 0, NULL, NULL);
|
|
|
|
#define TEST_RELATIVE_BACKING(id, TOP, BASE, EXPECT) \
|
|
do { \
|
|
data4.top = &TOP; \
|
|
data4.base = &BASE; \
|
|
data4.expect = EXPECT; \
|
|
if (virTestRun("Path relative resolve " #id, \
|
|
testPathRelative, &data4) < 0) \
|
|
ret = -1; \
|
|
} while (0)
|
|
|
|
testPathRelativePrepare();
|
|
|
|
/* few negative tests first */
|
|
|
|
/* a non-relative image is in the backing chain span */
|
|
TEST_RELATIVE_BACKING(1, backingchain[0], backingchain[1], NULL);
|
|
TEST_RELATIVE_BACKING(2, backingchain[0], backingchain[2], NULL);
|
|
TEST_RELATIVE_BACKING(3, backingchain[0], backingchain[3], NULL);
|
|
TEST_RELATIVE_BACKING(4, backingchain[1], backingchain[5], NULL);
|
|
|
|
/* image is not in chain (specified backwards) */
|
|
TEST_RELATIVE_BACKING(5, backingchain[2], backingchain[1], NULL);
|
|
|
|
/* positive tests */
|
|
TEST_RELATIVE_BACKING(6, backingchain[1], backingchain[1], "asdf");
|
|
TEST_RELATIVE_BACKING(7, backingchain[1], backingchain[2], "test");
|
|
TEST_RELATIVE_BACKING(8, backingchain[1], backingchain[3], "blah");
|
|
TEST_RELATIVE_BACKING(9, backingchain[2], backingchain[2], "test");
|
|
TEST_RELATIVE_BACKING(10, backingchain[2], backingchain[3], "blah");
|
|
TEST_RELATIVE_BACKING(11, backingchain[3], backingchain[3], "blah");
|
|
|
|
/* oVirt spelling */
|
|
TEST_RELATIVE_BACKING(12, backingchain[5], backingchain[5], "../volume/image2");
|
|
TEST_RELATIVE_BACKING(13, backingchain[5], backingchain[6], "../volume/../volume/image3");
|
|
TEST_RELATIVE_BACKING(14, backingchain[5], backingchain[7], "../volume/../volume/../volume/image4");
|
|
TEST_RELATIVE_BACKING(15, backingchain[6], backingchain[6], "../volume/image3");
|
|
TEST_RELATIVE_BACKING(16, backingchain[6], backingchain[7], "../volume/../volume/image4");
|
|
TEST_RELATIVE_BACKING(17, backingchain[7], backingchain[7], "../volume/image4");
|
|
|
|
/* crazy spellings */
|
|
TEST_RELATIVE_BACKING(17, backingchain[9], backingchain[9], "directory/stuff/volumes/garbage/image2");
|
|
TEST_RELATIVE_BACKING(18, backingchain[9], backingchain[10], "directory/stuff/volumes/garbage/../../../image3");
|
|
TEST_RELATIVE_BACKING(19, backingchain[9], backingchain[11], "directory/stuff/volumes/garbage/../../../../blah/image4");
|
|
TEST_RELATIVE_BACKING(20, backingchain[10], backingchain[10], "../../../image3");
|
|
TEST_RELATIVE_BACKING(21, backingchain[10], backingchain[11], "../../../../blah/image4");
|
|
TEST_RELATIVE_BACKING(22, backingchain[11], backingchain[11], "../blah/image4");
|
|
|
|
|
|
virTestCounterReset("Backing store parse ");
|
|
|
|
#define TEST_BACKING_PARSE_FULL(bck, xml, rc) \
|
|
do { \
|
|
data5.backing = bck; \
|
|
data5.expect = xml; \
|
|
data5.rv = rc; \
|
|
if (virTestRun(virTestCounterNext(), \
|
|
testBackingParse, &data5) < 0) \
|
|
ret = -1; \
|
|
} while (0)
|
|
|
|
#define TEST_BACKING_PARSE(bck, xml) \
|
|
TEST_BACKING_PARSE_FULL(bck, xml, 0)
|
|
|
|
TEST_BACKING_PARSE("path", "<source file='path'/>\n");
|
|
TEST_BACKING_PARSE("fat:/somedir", "<source dir='/somedir'/>\n");
|
|
TEST_BACKING_PARSE("://", NULL);
|
|
TEST_BACKING_PARSE("http://example.com",
|
|
"<source protocol='http' name=''>\n"
|
|
" <host name='example.com' port='80'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("http://example.com/",
|
|
"<source protocol='http' name=''>\n"
|
|
" <host name='example.com' port='80'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("http://example.com/file",
|
|
"<source protocol='http' name='file'>\n"
|
|
" <host name='example.com' port='80'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE_FULL("http://user:pass@example.com/file",
|
|
"<source protocol='http' name='file'>\n"
|
|
" <host name='example.com' port='80'/>\n"
|
|
"</source>\n", 1);
|
|
TEST_BACKING_PARSE("rbd:testshare:id=asdf:mon_host=example.com",
|
|
"<source protocol='rbd' name='testshare'>\n"
|
|
" <host name='example.com'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd:example.org:6000:exportname=blah",
|
|
"<source protocol='nbd' name='blah'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd:example.org:6000:exportname=:",
|
|
"<source protocol='nbd' name=':'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd:example.org:6000:exportname=:test",
|
|
"<source protocol='nbd' name=':test'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd:[::1]:6000:exportname=:test",
|
|
"<source protocol='nbd' name=':test'>\n"
|
|
" <host name='::1' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd:127.0.0.1:6000:exportname=:test",
|
|
"<source protocol='nbd' name=':test'>\n"
|
|
" <host name='127.0.0.1' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd:unix:/tmp/sock:exportname=/",
|
|
"<source protocol='nbd' name='/'>\n"
|
|
" <host transport='unix' socket='/tmp/sock'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd:unix:/tmp/sock:",
|
|
"<source protocol='nbd'>\n"
|
|
" <host transport='unix' socket='/tmp/sock:'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd:unix:/tmp/sock::exportname=:",
|
|
"<source protocol='nbd' name=':'>\n"
|
|
" <host transport='unix' socket='/tmp/sock:'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd://example.org:1234",
|
|
"<source protocol='nbd'>\n"
|
|
" <host name='example.org' port='1234'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd://example.org:1234/",
|
|
"<source protocol='nbd'>\n"
|
|
" <host name='example.org' port='1234'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd://example.org:1234/exportname",
|
|
"<source protocol='nbd' name='exportname'>\n"
|
|
" <host name='example.org' port='1234'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd+unix://?socket=/tmp/sock",
|
|
"<source protocol='nbd'>\n"
|
|
" <host transport='unix' socket='/tmp/sock'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd+unix:///?socket=/tmp/sock",
|
|
"<source protocol='nbd'>\n"
|
|
" <host transport='unix' socket='/tmp/sock'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd+unix:////?socket=/tmp/sock",
|
|
"<source protocol='nbd' name='/'>\n"
|
|
" <host transport='unix' socket='/tmp/sock'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd+unix:///exp?socket=/tmp/sock",
|
|
"<source protocol='nbd' name='exp'>\n"
|
|
" <host transport='unix' socket='/tmp/sock'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("nbd+unix:////exp?socket=/tmp/sock",
|
|
"<source protocol='nbd' name='/exp'>\n"
|
|
" <host transport='unix' socket='/tmp/sock'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE_FULL("iscsi://testuser:testpass@example.org:1234/exportname",
|
|
"<source protocol='iscsi' name='exportname'>\n"
|
|
" <host name='example.org' port='1234'/>\n"
|
|
"</source>\n", 1);
|
|
|
|
#ifdef WITH_JSON
|
|
TEST_BACKING_PARSE("json:", NULL);
|
|
TEST_BACKING_PARSE("json:asdgsdfg", NULL);
|
|
TEST_BACKING_PARSE("json:{}", NULL);
|
|
TEST_BACKING_PARSE("json: { \"file.driver\":\"blah\"}", NULL);
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"file\"}", NULL);
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"file\", "
|
|
"\"file.filename\":\"/path/to/file\"}",
|
|
"<source file='/path/to/file'/>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"file\", "
|
|
"\"filename\":\"/path/to/file\"}", NULL);
|
|
TEST_BACKING_PARSE("json:{\"file\" : { \"driver\":\"file\","
|
|
"\"filename\":\"/path/to/file\""
|
|
"}"
|
|
"}",
|
|
"<source file='/path/to/file'/>\n");
|
|
TEST_BACKING_PARSE("json:{\"driver\":\"file\","
|
|
"\"filename\":\"/path/to/file\""
|
|
"}",
|
|
"<source file='/path/to/file'/>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"host_device\", "
|
|
"\"file.filename\":\"/path/to/dev\"}",
|
|
"<source dev='/path/to/dev'/>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"host_cdrom\", "
|
|
"\"file.filename\":\"/path/to/cdrom\"}",
|
|
"<source dev='/path/to/cdrom'/>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"http\", "
|
|
"\"file.url\":\"http://example.com/file\"}",
|
|
"<source protocol='http' name='file'>\n"
|
|
" <host name='example.com' port='80'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{ \"driver\":\"http\","
|
|
"\"url\":\"http://example.com/file\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='http' name='file'>\n"
|
|
" <host name='example.com' port='80'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"ftp\", "
|
|
"\"file.url\":\"http://example.com/file\"}",
|
|
NULL);
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"gluster\", "
|
|
"\"file.filename\":\"gluster://example.com/vol/file\"}",
|
|
"<source protocol='gluster' name='vol/file'>\n"
|
|
" <host name='example.com' port='24007'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"gluster\","
|
|
"\"volume\":\"testvol\","
|
|
"\"path\":\"img.qcow2\","
|
|
"\"server\":[ { \"type\":\"tcp\","
|
|
"\"host\":\"example.com\","
|
|
"\"port\":\"1234\""
|
|
"},"
|
|
"{ \"type\":\"unix\","
|
|
"\"socket\":\"/path/socket\""
|
|
"},"
|
|
"{ \"type\":\"tcp\","
|
|
"\"host\":\"example.com\""
|
|
"}"
|
|
"]"
|
|
"}"
|
|
"}",
|
|
"<source protocol='gluster' name='testvol/img.qcow2'>\n"
|
|
" <host name='example.com' port='1234'/>\n"
|
|
" <host transport='unix' socket='/path/socket'/>\n"
|
|
" <host name='example.com' port='24007'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"gluster\","
|
|
"\"file.volume\":\"testvol\","
|
|
"\"file.path\":\"img.qcow2\","
|
|
"\"file.server\":[ { \"type\":\"tcp\","
|
|
"\"host\":\"example.com\","
|
|
"\"port\":\"1234\""
|
|
"},"
|
|
"{ \"type\":\"unix\","
|
|
"\"socket\":\"/path/socket\""
|
|
"},"
|
|
"{ \"type\":\"inet\","
|
|
"\"host\":\"example.com\""
|
|
"}"
|
|
"]"
|
|
"}",
|
|
"<source protocol='gluster' name='testvol/img.qcow2'>\n"
|
|
" <host name='example.com' port='1234'/>\n"
|
|
" <host transport='unix' socket='/path/socket'/>\n"
|
|
" <host name='example.com' port='24007'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"driver\": \"raw\","
|
|
"\"file\": {\"server.0.host\": \"A.A.A.A\","
|
|
"\"server.1.host\": \"B.B.B.B\","
|
|
"\"server.2.host\": \"C.C.C.C\","
|
|
"\"driver\": \"gluster\","
|
|
"\"path\": \"raw\","
|
|
"\"server.0.type\": \"tcp\","
|
|
"\"server.1.type\": \"tcp\","
|
|
"\"server.2.type\": \"tcp\","
|
|
"\"server.0.port\": \"24007\","
|
|
"\"server.1.port\": \"24007\","
|
|
"\"server.2.port\": \"24007\","
|
|
"\"volume\": \"vol1\"}}",
|
|
"<source protocol='gluster' name='vol1/raw'>\n"
|
|
" <host name='A.A.A.A' port='24007'/>\n"
|
|
" <host name='B.B.B.B' port='24007'/>\n"
|
|
" <host name='C.C.C.C' port='24007'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"nbd\","
|
|
"\"path\":\"/path/to/socket\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='nbd'>\n"
|
|
" <host transport='unix' socket='/path/to/socket'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"driver\":\"nbd\","
|
|
"\"path\":\"/path/to/socket\""
|
|
"}",
|
|
"<source protocol='nbd'>\n"
|
|
" <host transport='unix' socket='/path/to/socket'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"nbd\","
|
|
"\"file.path\":\"/path/to/socket\""
|
|
"}",
|
|
"<source protocol='nbd'>\n"
|
|
" <host transport='unix' socket='/path/to/socket'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"nbd\","
|
|
"\"export\":\"blah\","
|
|
"\"host\":\"example.org\","
|
|
"\"port\":\"6000\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='nbd' name='blah'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"nbd\","
|
|
"\"file.export\":\"blah\","
|
|
"\"file.host\":\"example.org\","
|
|
"\"file.port\":\"6000\""
|
|
"}",
|
|
"<source protocol='nbd' name='blah'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"nbd\","
|
|
"\"export\":\"blah\","
|
|
"\"server\": { \"type\":\"inet\","
|
|
"\"host\":\"example.org\","
|
|
"\"port\":\"6000\""
|
|
"}"
|
|
"}"
|
|
"}",
|
|
"<source protocol='nbd' name='blah'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"nbd\","
|
|
"\"server\": { \"type\":\"unix\","
|
|
"\"path\":\"/path/socket\""
|
|
"}"
|
|
"}"
|
|
"}",
|
|
"<source protocol='nbd'>\n"
|
|
" <host transport='unix' socket='/path/socket'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"ssh\","
|
|
"\"host\":\"example.org\","
|
|
"\"port\":\"6000\","
|
|
"\"path\":\"blah\","
|
|
"\"user\":\"user\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='ssh' name='blah'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"ssh\","
|
|
"\"file.host\":\"example.org\","
|
|
"\"file.port\":\"6000\","
|
|
"\"file.path\":\"blah\","
|
|
"\"file.user\":\"user\""
|
|
"}",
|
|
"<source protocol='ssh' name='blah'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"ssh\","
|
|
"\"path\":\"blah\","
|
|
"\"server\":{ \"host\":\"example.org\","
|
|
"\"port\":\"6000\""
|
|
"},"
|
|
"\"user\":\"user\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='ssh' name='blah'>\n"
|
|
" <host name='example.org' port='6000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file.driver\":\"rbd\","
|
|
"\"file.filename\":\"rbd:testshare:id=asdf:mon_host=example.com\""
|
|
"}",
|
|
"<source protocol='rbd' name='testshare'>\n"
|
|
" <host name='example.com'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"rbd\","
|
|
"\"image\":\"test\","
|
|
"\"pool\":\"libvirt\","
|
|
"\"conf\":\"/path/to/conf\","
|
|
"\"snapshot\":\"snapshotname\","
|
|
"\"server\":[ {\"host\":\"example.com\","
|
|
"\"port\":\"1234\""
|
|
"},"
|
|
"{\"host\":\"example2.com\""
|
|
"}"
|
|
"]"
|
|
"}"
|
|
"}",
|
|
"<source protocol='rbd' name='libvirt/test'>\n"
|
|
" <host name='example.com' port='1234'/>\n"
|
|
" <host name='example2.com'/>\n"
|
|
" <snapshot name='snapshotname'/>\n"
|
|
" <config file='/path/to/conf'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{ \"file\": { "
|
|
"\"driver\": \"raw\","
|
|
"\"file\": {"
|
|
"\"driver\": \"file\","
|
|
"\"filename\": \"/path/to/file\" } } }",
|
|
"<source file='/path/to/file'/>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"iscsi\","
|
|
"\"transport\":\"tcp\","
|
|
"\"portal\":\"test.org\","
|
|
"\"target\":\"iqn.2016-12.com.virttest:emulated-iscsi-noauth.target\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='iscsi' name='iqn.2016-12.com.virttest:emulated-iscsi-noauth.target/0'>\n"
|
|
" <host name='test.org' port='3260'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE_FULL("json:{\"file\":{\"driver\":\"iscsi\","
|
|
"\"transport\":\"tcp\","
|
|
"\"portal\":\"test.org\","
|
|
"\"user\":\"testuser\","
|
|
"\"target\":\"iqn.2016-12.com.virttest:emulated-iscsi-auth.target\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='iscsi' name='iqn.2016-12.com.virttest:emulated-iscsi-auth.target/0'>\n"
|
|
" <host name='test.org' port='3260'/>\n"
|
|
"</source>\n", 1);
|
|
TEST_BACKING_PARSE_FULL("json:{\"file\":{\"driver\":\"iscsi\","
|
|
"\"transport\":\"tcp\","
|
|
"\"portal\":\"test.org\","
|
|
"\"password\":\"testpass\","
|
|
"\"target\":\"iqn.2016-12.com.virttest:emulated-iscsi-auth.target\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='iscsi' name='iqn.2016-12.com.virttest:emulated-iscsi-auth.target/0'>\n"
|
|
" <host name='test.org' port='3260'/>\n"
|
|
"</source>\n", 1);
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"iscsi\","
|
|
"\"transport\":\"tcp\","
|
|
"\"portal\":\"test.org:1234\","
|
|
"\"target\":\"iqn.2016-12.com.virttest:emulated-iscsi-noauth.target\","
|
|
"\"lun\":\"6\""
|
|
"}"
|
|
"}",
|
|
"<source protocol='iscsi' name='iqn.2016-12.com.virttest:emulated-iscsi-noauth.target/6'>\n"
|
|
" <host name='test.org' port='1234'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"iscsi\","
|
|
"\"transport\":\"tcp\","
|
|
"\"portal\":\"[2001::0]:1234\","
|
|
"\"target\":\"iqn.2016-12.com.virttest:emulated-iscsi-noauth.target\","
|
|
"\"lun\":6"
|
|
"}"
|
|
"}",
|
|
"<source protocol='iscsi' name='iqn.2016-12.com.virttest:emulated-iscsi-noauth.target/6'>\n"
|
|
" <host name='[2001::0]' port='1234'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"iscsi\","
|
|
"\"transport\":\"tcp\","
|
|
"\"portal\":\"[2001::0]\","
|
|
"\"target\":\"iqn.2016-12.com.virttest:emulated-iscsi-noauth.target\","
|
|
"\"lun\":6"
|
|
"}"
|
|
"}",
|
|
"<source protocol='iscsi' name='iqn.2016-12.com.virttest:emulated-iscsi-noauth.target/6'>\n"
|
|
" <host name='[2001::0]' port='3260'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"sheepdog\","
|
|
"\"vdi\":\"test\","
|
|
"\"server\":{ \"type\":\"inet\","
|
|
"\"host\":\"example.com\","
|
|
"\"port\":\"321\""
|
|
"}"
|
|
"}"
|
|
"}",
|
|
"<source protocol='sheepdog' name='test'>\n"
|
|
" <host name='example.com' port='321'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"driver\": \"raw\","
|
|
"\"file\": {\"server.host\": \"10.10.10.10\","
|
|
"\"server.port\": \"7000\","
|
|
"\"tag\": \"\","
|
|
"\"driver\": \"sheepdog\","
|
|
"\"server.type\": \"inet\","
|
|
"\"vdi\": \"Alice\"}}",
|
|
"<source protocol='sheepdog' name='Alice'>\n"
|
|
" <host name='10.10.10.10' port='7000'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"vxhs\","
|
|
"\"vdisk-id\":\"c6718f6b-0401-441d-a8c3-1f0064d75ee0\","
|
|
"\"server\": { \"host\":\"example.com\","
|
|
"\"port\":\"9999\""
|
|
"}"
|
|
"}"
|
|
"}",
|
|
"<source protocol='vxhs' name='c6718f6b-0401-441d-a8c3-1f0064d75ee0'>\n"
|
|
" <host name='example.com' port='9999'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\":\"nfs\","
|
|
"\"user\":2,"
|
|
"\"group\":9,"
|
|
"\"path\":\"/foo/bar/baz\","
|
|
"\"server\": { \"host\":\"example.com\","
|
|
"\"type\":\"inet\""
|
|
"}"
|
|
"}"
|
|
"}",
|
|
"<source protocol='nfs' name='/foo/bar/baz'>\n"
|
|
" <host name='example.com'/>\n"
|
|
" <identity user='+2' group='+9'/>\n"
|
|
"</source>\n");
|
|
TEST_BACKING_PARSE_FULL("json:{ \"driver\": \"raw\","
|
|
"\"offset\": 10752,"
|
|
"\"size\": 4063232,"
|
|
"\"file\": { \"driver\": \"file\","
|
|
"\"filename\": \"/tmp/testfle\""
|
|
"}"
|
|
"}",
|
|
"<source file='/tmp/testfle'>\n"
|
|
" <slices>\n"
|
|
" <slice type='storage' offset='10752' size='4063232'/>\n"
|
|
" </slices>\n"
|
|
"</source>\n", 0);
|
|
|
|
TEST_BACKING_PARSE_FULL("json:{ \"file.cookie\": \"vmware_soap_session=\\\"0c8db85112873a79b7ef74f294cb70ef7f\\\"\","
|
|
"\"file.sslverify\": false,"
|
|
"\"file.driver\": \"https\","
|
|
"\"file.url\": \"https://host/folder/esx6.5-rhel7.7-x86%5f64/esx6.5-rhel7.7-x86%5f64-flat.vmdk?dcPath=data&dsName=esx6.5-matrix\","
|
|
"\"file.timeout\": 2000"
|
|
"}",
|
|
"<source protocol='https' name='folder/esx6.5-rhel7.7-x86_64/esx6.5-rhel7.7-x86_64-flat.vmdk' query='dcPath=data&dsName=esx6.5-matrix'>\n"
|
|
" <host name='host' port='443'/>\n"
|
|
" <ssl verify='no'/>\n"
|
|
" <cookies>\n"
|
|
" <cookie name='vmware_soap_session'>"0c8db85112873a79b7ef74f294cb70ef7f"</cookie>\n"
|
|
" </cookies>\n"
|
|
" <timeout seconds='2000'/>\n"
|
|
"</source>\n", 0);
|
|
|
|
TEST_BACKING_PARSE_FULL("json:{ \"file.cookie\": \"vmware_soap_session=\\\"0c8db85112873a79b7ef74f294cb70ef7f\\\"\","
|
|
"\"file.sslverify\": \"off\","
|
|
"\"file.driver\": \"https\","
|
|
"\"file.url\": \"https://host/folder/esx6.5-rhel7.7-x86%5f64/esx6.5-rhel7.7-x86%5f64-flat.vmdk?dcPath=data&dsName=esx6.5-matrix\","
|
|
"\"file.timeout\": 2000"
|
|
"}",
|
|
"<source protocol='https' name='folder/esx6.5-rhel7.7-x86_64/esx6.5-rhel7.7-x86_64-flat.vmdk' query='dcPath=data&dsName=esx6.5-matrix'>\n"
|
|
" <host name='host' port='443'/>\n"
|
|
" <ssl verify='no'/>\n"
|
|
" <cookies>\n"
|
|
" <cookie name='vmware_soap_session'>"0c8db85112873a79b7ef74f294cb70ef7f"</cookie>\n"
|
|
" </cookies>\n"
|
|
" <timeout seconds='2000'/>\n"
|
|
"</source>\n", 0);
|
|
|
|
TEST_BACKING_PARSE("json:{\"file\":{\"driver\": \"nvme\","
|
|
"\"device\": \"0000:01:00.0\","
|
|
"\"namespace\": 1"
|
|
"}"
|
|
"}",
|
|
"<source type='pci' namespace='1'>\n"
|
|
" <address domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>\n"
|
|
"</source>\n");
|
|
|
|
#endif /* WITH_JSON */
|
|
|
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
}
|
|
|
|
VIR_TEST_MAIN(mymain)
|