|
|
c401cc |
From be23459e2202163a2cb2f680dbfbc268e58c4434 Mon Sep 17 00:00:00 2001
|
|
|
c401cc |
Message-Id: <be23459e2202163a2cb2f680dbfbc268e58c4434@dist-git>
|
|
|
c401cc |
From: Peter Krempa <pkrempa@redhat.com>
|
|
|
c401cc |
Date: Wed, 26 Feb 2014 14:54:31 +0100
|
|
|
c401cc |
Subject: [PATCH] test: Implement fake storage pool driver in qemuxml2argv test
|
|
|
c401cc |
|
|
|
c401cc |
https://bugzilla.redhat.com/show_bug.cgi?id=1032370
|
|
|
c401cc |
|
|
|
c401cc |
To support testing of "volume" disk backing, we need to implement a few
|
|
|
c401cc |
disk driver backend functions.
|
|
|
c401cc |
|
|
|
c401cc |
The fake storage driver uses files in storagepoolxml2xmlout/POOLNAME.xml
|
|
|
c401cc |
as XML files for pool definitions and volume names are in format
|
|
|
c401cc |
"VOL_TYPE+VOL_PATH". By default type "block" is assumed (for iSCSI test
|
|
|
c401cc |
compatibility).
|
|
|
c401cc |
|
|
|
c401cc |
The choice of this approach along with implemented functions was made so
|
|
|
c401cc |
that <disk type='volume'> can be tested in the xml2argv test.
|
|
|
c401cc |
|
|
|
c401cc |
(cherry picked from commit bae124e40ff2b9d4de75d44510619db2c08d548a)
|
|
|
c401cc |
|
|
|
c401cc |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c401cc |
---
|
|
|
c401cc |
tests/qemuxml2argvtest.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
c401cc |
1 file changed, 183 insertions(+)
|
|
|
c401cc |
|
|
|
c401cc |
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
|
|
|
c401cc |
index 0e2435b..3c969e2 100644
|
|
|
c401cc |
--- a/tests/qemuxml2argvtest.c
|
|
|
c401cc |
+++ b/tests/qemuxml2argvtest.c
|
|
|
c401cc |
@@ -18,6 +18,7 @@
|
|
|
c401cc |
# include "qemu/qemu_command.h"
|
|
|
c401cc |
# include "qemu/qemu_domain.h"
|
|
|
c401cc |
# include "datatypes.h"
|
|
|
c401cc |
+# include "conf/storage_conf.h"
|
|
|
c401cc |
# include "cpu/cpu_map.h"
|
|
|
c401cc |
# include "virstring.h"
|
|
|
c401cc |
|
|
|
c401cc |
@@ -75,6 +76,182 @@ static virSecretDriver fakeSecretDriver = {
|
|
|
c401cc |
.secretUndefine = NULL,
|
|
|
c401cc |
};
|
|
|
c401cc |
|
|
|
c401cc |
+
|
|
|
c401cc |
+# define STORAGE_POOL_XML_PATH "storagepoolxml2xmlout/"
|
|
|
c401cc |
+static const unsigned char fakeUUID[VIR_UUID_BUFLEN] = "fakeuuid";
|
|
|
c401cc |
+
|
|
|
c401cc |
+static virStoragePoolPtr
|
|
|
c401cc |
+fakeStoragePoolLookupByName(virConnectPtr conn,
|
|
|
c401cc |
+ const char *name)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ char *xmlpath = NULL;
|
|
|
c401cc |
+ virStoragePoolPtr ret = NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (STRNEQ(name, "inactive")) {
|
|
|
c401cc |
+ if (virAsprintf(&xmlpath, "%s/%s%s.xml",
|
|
|
c401cc |
+ abs_srcdir,
|
|
|
c401cc |
+ STORAGE_POOL_XML_PATH,
|
|
|
c401cc |
+ name) < 0)
|
|
|
c401cc |
+ return NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (!virFileExists(xmlpath)) {
|
|
|
c401cc |
+ virReportError(VIR_ERR_NO_STORAGE_POOL,
|
|
|
c401cc |
+ "File '%s' not found", xmlpath);
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ ret = virGetStoragePool(conn, name, fakeUUID, NULL, NULL);
|
|
|
c401cc |
+
|
|
|
c401cc |
+cleanup:
|
|
|
c401cc |
+ VIR_FREE(xmlpath);
|
|
|
c401cc |
+ return ret;
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+
|
|
|
c401cc |
+static virStorageVolPtr
|
|
|
c401cc |
+fakeStorageVolLookupByName(virStoragePoolPtr pool,
|
|
|
c401cc |
+ const char *name)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ char **volinfo = NULL;
|
|
|
c401cc |
+ virStorageVolPtr ret = NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (STREQ(pool->name, "inactive")) {
|
|
|
c401cc |
+ virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
c401cc |
+ "storage pool '%s' is not active", pool->name);
|
|
|
c401cc |
+ return NULL;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (STREQ(name, "nonexistent")) {
|
|
|
c401cc |
+ virReportError(VIR_ERR_NO_STORAGE_VOL,
|
|
|
c401cc |
+ "no storage vol with matching name '%s'", name);
|
|
|
c401cc |
+ return NULL;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (!strchr(name, '+'))
|
|
|
c401cc |
+ goto fallback;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (!(volinfo = virStringSplit(name, "+", 2)))
|
|
|
c401cc |
+ return NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (!volinfo[1])
|
|
|
c401cc |
+ goto fallback;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ ret = virGetStorageVol(pool->conn, pool->name, volinfo[1], volinfo[0],
|
|
|
c401cc |
+ NULL, NULL);
|
|
|
c401cc |
+
|
|
|
c401cc |
+cleanup:
|
|
|
c401cc |
+ virStringFreeList(volinfo);
|
|
|
c401cc |
+ return ret;
|
|
|
c401cc |
+
|
|
|
c401cc |
+fallback:
|
|
|
c401cc |
+ ret = virGetStorageVol(pool->conn, pool->name, name, "block", NULL, NULL);
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+static int
|
|
|
c401cc |
+fakeStorageVolGetInfo(virStorageVolPtr vol,
|
|
|
c401cc |
+ virStorageVolInfoPtr info)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ memset(info, 0, sizeof(*info));
|
|
|
c401cc |
+
|
|
|
c401cc |
+ info->type = virStorageVolTypeFromString(vol->key);
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (info->type < 0) {
|
|
|
c401cc |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c401cc |
+ "Invalid volume type '%s'", vol->key);
|
|
|
c401cc |
+ return -1;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ return 0;
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+
|
|
|
c401cc |
+static char *
|
|
|
c401cc |
+fakeStorageVolGetPath(virStorageVolPtr vol)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ char *ret = NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ ignore_value(virAsprintf(&ret, "/some/%s/device/%s", vol->key, vol->name));
|
|
|
c401cc |
+
|
|
|
c401cc |
+ return ret;
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+
|
|
|
c401cc |
+static char *
|
|
|
c401cc |
+fakeStoragePoolGetXMLDesc(virStoragePoolPtr pool,
|
|
|
c401cc |
+ unsigned int flags_unused ATTRIBUTE_UNUSED)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ char *xmlpath = NULL;
|
|
|
c401cc |
+ char *xmlbuf = NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (STREQ(pool->name, "inactive")) {
|
|
|
c401cc |
+ virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
|
|
|
c401cc |
+ return NULL;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (virAsprintf(&xmlpath, "%s/%s%s.xml",
|
|
|
c401cc |
+ abs_srcdir,
|
|
|
c401cc |
+ STORAGE_POOL_XML_PATH,
|
|
|
c401cc |
+ pool->name) < 0)
|
|
|
c401cc |
+ return NULL;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ if (virtTestLoadFile(xmlpath, &xmlbuf) < 0) {
|
|
|
c401cc |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c401cc |
+ "failed to load XML file '%s'",
|
|
|
c401cc |
+ xmlpath);
|
|
|
c401cc |
+ goto cleanup;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
+cleanup:
|
|
|
c401cc |
+ VIR_FREE(xmlpath);
|
|
|
c401cc |
+
|
|
|
c401cc |
+ return xmlbuf;
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+static int
|
|
|
c401cc |
+fakeStorageClose(virConnectPtr conn ATTRIBUTE_UNUSED)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ return 0;
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+static int
|
|
|
c401cc |
+fakeStoragePoolIsActive(virStoragePoolPtr pool)
|
|
|
c401cc |
+{
|
|
|
c401cc |
+ if (STREQ(pool->name, "inactive"))
|
|
|
c401cc |
+ return 0;
|
|
|
c401cc |
+
|
|
|
c401cc |
+ return 1;
|
|
|
c401cc |
+}
|
|
|
c401cc |
+
|
|
|
c401cc |
+/* Test storage pool implementation
|
|
|
c401cc |
+ *
|
|
|
c401cc |
+ * These functions aid testing of storage pool related stuff when creating a
|
|
|
c401cc |
+ * qemu command .
|
|
|
c401cc |
+ *
|
|
|
c401cc |
+ * There are a few "magic" values to pass to these functions:
|
|
|
c401cc |
+ *
|
|
|
c401cc |
+ * 1) "inactive" as
|
|
|
c401cc |
+ * a pool name for pool lookup creates a inactive pool. All other names are
|
|
|
c401cc |
+ * interpreted as file names for files of storagepooltest and are used as the
|
|
|
c401cc |
+ * definition for the pool. If the file doesn't exist the pool doesn't exist.
|
|
|
c401cc |
+ *
|
|
|
c401cc |
+ * 2) "nonexistent" returns an error while looking up a volume. Otherwise
|
|
|
c401cc |
+ * pattern VOLUME_TYPE+VOLUME_PATH can be used to simulate a volume in an pool.
|
|
|
c401cc |
+ * This creates a fake path for this volume. If the '+' sign is omitted, block
|
|
|
c401cc |
+ * type is assumed.
|
|
|
c401cc |
+ */
|
|
|
c401cc |
+static virStorageDriver fakeStorageDriver = {
|
|
|
c401cc |
+ .name = "fake_storage",
|
|
|
c401cc |
+ .storageClose = fakeStorageClose,
|
|
|
c401cc |
+ .storagePoolLookupByName = fakeStoragePoolLookupByName,
|
|
|
c401cc |
+ .storageVolLookupByName = fakeStorageVolLookupByName,
|
|
|
c401cc |
+ .storagePoolGetXMLDesc = fakeStoragePoolGetXMLDesc,
|
|
|
c401cc |
+ .storageVolGetPath = fakeStorageVolGetPath,
|
|
|
c401cc |
+ .storageVolGetInfo = fakeStorageVolGetInfo,
|
|
|
c401cc |
+ .storagePoolIsActive = fakeStoragePoolIsActive,
|
|
|
c401cc |
+};
|
|
|
c401cc |
+
|
|
|
c401cc |
typedef enum {
|
|
|
c401cc |
FLAG_EXPECT_ERROR = 1 << 0,
|
|
|
c401cc |
FLAG_EXPECT_FAILURE = 1 << 1,
|
|
|
c401cc |
@@ -103,6 +280,7 @@ static int testCompareXMLToArgvFiles(const char *xml,
|
|
|
c401cc |
if (!(conn = virGetConnect()))
|
|
|
c401cc |
goto out;
|
|
|
c401cc |
conn->secretDriver = &fakeSecretDriver;
|
|
|
c401cc |
+ conn->storageDriver = &fakeStorageDriver;
|
|
|
c401cc |
|
|
|
c401cc |
if (!(vmdef = virDomainDefParseFile(xml, driver.caps, driver.xmlopt,
|
|
|
c401cc |
QEMU_EXPECTED_VIRT_TYPES,
|
|
|
c401cc |
@@ -165,6 +343,11 @@ static int testCompareXMLToArgvFiles(const char *xml,
|
|
|
c401cc |
}
|
|
|
c401cc |
}
|
|
|
c401cc |
|
|
|
c401cc |
+ for (i = 0; i < vmdef->ndisks; i++) {
|
|
|
c401cc |
+ if (qemuTranslateDiskSourcePool(conn, vmdef->disks[i]) < 0)
|
|
|
c401cc |
+ goto out;
|
|
|
c401cc |
+ }
|
|
|
c401cc |
+
|
|
|
c401cc |
if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr,
|
|
|
c401cc |
(flags & FLAG_JSON), extraFlags,
|
|
|
c401cc |
migrateFrom, migrateFd, NULL,
|
|
|
c401cc |
--
|
|
|
c401cc |
1.9.0
|
|
|
c401cc |
|