[libvirt] [PATCH 00/11] qemu: Add formatter for 'blockdev-create' JSON (blockdev-add saga)

To allow using blockdev-create we need to be able to generate the properties for it, this series adds the necessary bits and also converts to use 'auto-read-only' instead of 'read-only'. Kevin, please look into the test data to see if there's something wrong with the semantic usage. The data is validated against the QMP schema. Format in 2/11 will be used as the 'backing-store' string via the json:// pseudo protocol for recording into new files for network use. 5/11 is the conversion to use auto-read-only. The test data in the patch covers stadard use with -blockdev/blockdev-add 11/11 is the format to be used with 'blockdev-create' Thanks. Peter Krempa (11): qemu: block: Allow skipping non-target related data when formating disk JSON tests: qemublock: Add testing of pure disk source specification JSON generator util: json: Introduce helper to prepend string into a virJSONValueObject qemu: block: Extract formating of 'driver' attribute from child formatters qemu: block: Use 'auto-read-only' instead of 'read-only' for backing chain qemu: block: Add generator for image format creation properties qemu: block: Add generator for creating storage with blockdev-create qemu: domain: Export qemuDomainPrepareStorageSourceBlockdev conf: snapshot: Export virDomainSnapshotDiskDefParseXML conf: snapshot: Provide a function to free virDomainSnapshotDiskDefPtr tests: qemublock: Add testing of 'blockdev-create' generators src/conf/snapshot_conf.c | 13 +- src/conf/snapshot_conf.h | 6 + src/libvirt_private.syms | 1 + src/qemu/qemu_block.c | 584 ++++++++++++++++-- src/qemu/qemu_block.h | 18 +- src/qemu/qemu_command.c | 4 +- src/qemu/qemu_domain.c | 9 +- src/qemu/qemu_domain.h | 5 + src/qemu/qemu_migration.c | 4 +- src/util/virjson.c | 50 +- src/util/virjson.h | 1 + tests/qemublocktest.c | 244 +++++++- .../imagecreate/luks-encopts.json | 19 + .../imagecreate/luks-encopts.xml | 16 + .../imagecreate/luks-noopts.json | 14 + .../imagecreate/luks-noopts.xml | 14 + .../imagecreate/network-gluster-qcow2.json | 28 + .../imagecreate/network-gluster-qcow2.xml | 13 + .../imagecreate/network-rbd-qcow2.json | 26 + .../imagecreate/network-rbd-qcow2.xml | 13 + .../imagecreate/network-sheepdog-qcow2.json | 20 + .../imagecreate/network-sheepdog-qcow2.xml | 12 + .../imagecreate/network-ssh-qcow2.json | 19 + .../imagecreate/network-ssh-qcow2.xml | 12 + .../imagecreate/qcow2-backing-luks.json | 15 + .../imagecreate/qcow2-backing-luks.xml | 1 + .../imagecreate/qcow2-backing-raw-nbd.json | 15 + .../imagecreate/qcow2-backing-raw-nbd.xml | 1 + .../imagecreate/qcow2-backing-raw.json | 15 + .../imagecreate/qcow2-backing-raw.xml | 1 + .../qcow2-luks-encopts-backing.json | 24 + .../qcow2-luks-encopts-backing.xml | 1 + .../imagecreate/qcow2-luks-encopts.json | 22 + .../imagecreate/qcow2-luks-encopts.xml | 16 + .../imagecreate/qcow2-luks-noopts.json | 17 + .../imagecreate/qcow2-luks-noopts.xml | 14 + .../qemublocktestdata/imagecreate/qcow2.json | 13 + tests/qemublocktestdata/imagecreate/qcow2.xml | 11 + .../imagecreate/raw-nbd.json | 4 + .../qemublocktestdata/imagecreate/raw-nbd.xml | 12 + tests/qemublocktestdata/imagecreate/raw.json | 9 + tests/qemublocktestdata/imagecreate/raw.xml | 11 + .../xml2json/block-raw-noopts-srconly.json | 4 + .../xml2json/block-raw-noopts.json | 2 +- .../block-raw-reservations-srconly.json | 4 + .../xml2json/block-raw-reservations.json | 2 +- .../xml2json/dir-fat-cache-srconly.json | 5 + .../xml2json/dir-fat-cache.json | 2 +- .../xml2json/dir-fat-floppy-srconly.json | 5 + .../xml2json/dir-fat-floppy.json | 2 +- .../xml2json/dir-fat-readonly-srconly.json | 5 + .../xml2json/dir-fat-readonly.json | 2 +- ...ile-backing_basic-aio_threads-srconly.json | 24 + .../file-backing_basic-aio_threads.json | 8 +- ...acking_basic-cache-directsync-srconly.json | 24 + .../file-backing_basic-cache-directsync.json | 8 +- ...file-backing_basic-cache-none-srconly.json | 24 + .../file-backing_basic-cache-none.json | 8 +- ...le-backing_basic-cache-unsafe-srconly.json | 24 + .../file-backing_basic-cache-unsafe.json | 8 +- ...backing_basic-cache-writeback-srconly.json | 24 + .../file-backing_basic-cache-writeback.json | 8 +- ...king_basic-cache-writethrough-srconly.json | 24 + ...file-backing_basic-cache-writethrough.json | 8 +- .../file-backing_basic-detect-srconly.json | 24 + .../xml2json/file-backing_basic-detect.json | 8 +- .../file-backing_basic-noopts-srconly.json | 16 + .../xml2json/file-backing_basic-noopts.json | 8 +- ...le-backing_basic-unmap-detect-srconly.json | 24 + .../file-backing_basic-unmap-detect.json | 8 +- ...le-backing_basic-unmap-ignore-srconly.json | 24 + .../file-backing_basic-unmap-ignore.json | 8 +- .../file-backing_basic-unmap-srconly.json | 24 + .../xml2json/file-backing_basic-unmap.json | 8 +- .../xml2json/file-bochs-noopts-srconly.json | 4 + .../xml2json/file-bochs-noopts.json | 2 +- .../xml2json/file-cloop-noopts-srconly.json | 4 + .../xml2json/file-cloop-noopts.json | 2 +- .../xml2json/file-dmg-noopts-srconly.json | 4 + .../xml2json/file-dmg-noopts.json | 2 +- .../xml2json/file-ploop-noopts-srconly.json | 4 + .../xml2json/file-ploop-noopts.json | 2 +- ...cow2-backing-chain-encryption-srconly.json | 8 + .../file-qcow2-backing-chain-encryption.json | 4 +- ...le-qcow2-backing-chain-noopts-srconly.json | 40 ++ .../file-qcow2-backing-chain-noopts.json | 20 +- ...w2-backing-chain-unterminated-srconly.json | 8 + ...file-qcow2-backing-chain-unterminated.json | 4 +- .../xml2json/file-raw-aio_native-srconly.json | 4 + .../xml2json/file-raw-aio_native.json | 2 +- .../xml2json/file-raw-luks-srconly.json | 4 + .../xml2json/file-raw-luks.json | 2 +- .../xml2json/file-raw-noopts-srconly.json | 4 + .../xml2json/file-raw-noopts.json | 2 +- .../xml2json/file-vdi-noopts-srconly.json | 4 + .../xml2json/file-vdi-noopts.json | 2 +- .../xml2json/file-vhd-noopts-srconly.json | 4 + .../xml2json/file-vhd-noopts.json | 2 +- .../xml2json/file-vpc-noopts-srconly.json | 4 + .../xml2json/file-vpc-noopts.json | 2 +- .../xml2json/network-nbd-tls-srconly.json | 8 + .../xml2json/network-nbd-tls.json | 2 +- ...w2-backing-chain-cache-unsafe-srconly.json | 22 + ...work-qcow2-backing-chain-cache-unsafe.json | 4 +- ...backing-chain-encryption_auth-srconly.json | 22 + ...k-qcow2-backing-chain-encryption_auth.json | 4 +- .../qemu-ns.x86_64-4.0.0.args | 2 +- .../qemu-ns.x86_64-latest.args | 2 +- 108 files changed, 1764 insertions(+), 170 deletions(-) create mode 100644 tests/qemublocktestdata/imagecreate/luks-encopts.json create mode 100644 tests/qemublocktestdata/imagecreate/luks-encopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/luks-noopts.json create mode 100644 tests/qemublocktestdata/imagecreate/luks-noopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-gluster-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-gluster-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-rbd-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-rbd-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-ssh-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-ssh-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-luks.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-luks.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-raw.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-raw.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/raw-nbd.json create mode 100644 tests/qemublocktestdata/imagecreate/raw-nbd.xml create mode 100644 tests/qemublocktestdata/imagecreate/raw.json create mode 100644 tests/qemublocktestdata/imagecreate/raw.xml create mode 100644 tests/qemublocktestdata/xml2json/block-raw-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/block-raw-reservations-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/dir-fat-cache-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/dir-fat-floppy-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/dir-fat-readonly-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-none-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-detect-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-unmap-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-bochs-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-cloop-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-dmg-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-ploop-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-raw-aio_native-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-raw-luks-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-raw-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-vdi-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-vhd-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-vpc-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/network-nbd-tls-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth-srconly.json -- 2.21.0

When formatting new qcow2 images we need to provide the backing store string which should not contain any authentication or irelevant data. Add a flag for qemuBlockStorageSourceGetBackendProps which allows to skip the irrelevant data. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 121 ++++++++++++++++++++++++---------------- src/qemu/qemu_block.h | 3 +- src/qemu/qemu_command.c | 2 +- tests/qemublocktest.c | 4 +- 4 files changed, 79 insertions(+), 51 deletions(-) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 0a6522577d..771797989e 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -624,7 +624,8 @@ qemuBlockStorageSourceBuildHostsJSONInetSocketAddress(virStorageSourcePtr src) static virJSONValuePtr qemuBlockStorageSourceGetGlusterProps(virStorageSourcePtr src, - bool legacy) + bool legacy, + bool onlytarget) { VIR_AUTOPTR(virJSONValue) servers = NULL; VIR_AUTOPTR(virJSONValue) props = NULL; @@ -645,7 +646,8 @@ qemuBlockStorageSourceGetGlusterProps(virStorageSourcePtr src, "a:server", &servers, NULL) < 0) return NULL; - if (src->debug && + if (!onlytarget && + src->debug && virJSONValueObjectAdd(props, "u:debug", src->debugLevel, NULL) < 0) return NULL; @@ -654,10 +656,12 @@ qemuBlockStorageSourceGetGlusterProps(virStorageSourcePtr src, static virJSONValuePtr -qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src) +qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src, + bool onlytarget) { const char *protocol = virStorageNetProtocolTypeToString(src->protocol); VIR_AUTOPTR(virJSONValue) server = NULL; + const char *tlsAlias = src->tlsAlias; virJSONValuePtr ret = NULL; if (src->nhosts != 1) { @@ -669,6 +673,9 @@ qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src) if (!(server = qemuBlockStorageSourceBuildJSONInetSocketAddress(&src->hosts[0]))) return NULL; + if (onlytarget) + tlsAlias = NULL; + /* VxHS disk specification example: * { driver:"vxhs", * tls-creds:"objvirtio-disk0_tls0", @@ -677,7 +684,7 @@ qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src) */ ignore_value(virJSONValueObjectCreate(&ret, "s:driver", protocol, - "S:tls-creds", src->tlsAlias, + "S:tls-creds", tlsAlias, "s:vdisk-id", src->path, "a:server", &server, NULL)); @@ -686,7 +693,8 @@ qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src) static virJSONValuePtr -qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src) +qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src, + bool onlytarget) { qemuDomainStorageSourcePrivatePtr srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src); const char *passwordalias = NULL; @@ -716,7 +724,7 @@ qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src) if (!(uristr = virURIFormat(uri))) return NULL; - if (src->auth) { + if (!onlytarget && src->auth) { username = src->auth->username; passwordalias = srcPriv->secinfo->s.aes.alias; } @@ -733,7 +741,8 @@ qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src) static virJSONValuePtr -qemuBlockStorageSourceGetISCSIProps(virStorageSourcePtr src) +qemuBlockStorageSourceGetISCSIProps(virStorageSourcePtr src, + bool onlytarget) { qemuDomainStorageSourcePrivatePtr srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src); const char *protocol = virStorageNetProtocolTypeToString(src->protocol); @@ -781,7 +790,7 @@ qemuBlockStorageSourceGetISCSIProps(virStorageSourcePtr src) return NULL; } - if (src->auth) { + if (!onlytarget && src->auth) { username = src->auth->username; objalias = srcPriv->secinfo->s.aes.alias; } @@ -801,9 +810,11 @@ qemuBlockStorageSourceGetISCSIProps(virStorageSourcePtr src) static virJSONValuePtr -qemuBlockStorageSourceGetNBDProps(virStorageSourcePtr src) +qemuBlockStorageSourceGetNBDProps(virStorageSourcePtr src, + bool onlytarget) { VIR_AUTOPTR(virJSONValue) serverprops = NULL; + const char *tlsAlias = src->tlsAlias; virJSONValuePtr ret = NULL; if (src->nhosts != 1) { @@ -817,11 +828,14 @@ qemuBlockStorageSourceGetNBDProps(virStorageSourcePtr src) if (!serverprops) return NULL; + if (onlytarget) + tlsAlias = NULL; + if (virJSONValueObjectCreate(&ret, "s:driver", "nbd", "a:server", &serverprops, "S:export", src->path, - "S:tls-creds", src->tlsAlias, + "S:tls-creds", tlsAlias, NULL) < 0) return NULL; @@ -830,7 +844,8 @@ qemuBlockStorageSourceGetNBDProps(virStorageSourcePtr src) static virJSONValuePtr -qemuBlockStorageSourceGetRBDProps(virStorageSourcePtr src) +qemuBlockStorageSourceGetRBDProps(virStorageSourcePtr src, + bool onlytarget) { qemuDomainStorageSourcePrivatePtr srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src); VIR_AUTOPTR(virJSONValue) servers = NULL; @@ -844,7 +859,7 @@ qemuBlockStorageSourceGetRBDProps(virStorageSourcePtr src) !(servers = qemuBlockStorageSourceBuildHostsJSONInetSocketAddress(src))) return NULL; - if (src->auth) { + if (!onlytarget && src->auth) { username = srcPriv->secinfo->s.aes.username; keysecret = srcPriv->secinfo->s.aes.alias; /* the auth modes are modelled after our old command line generator */ @@ -943,16 +958,14 @@ qemuBlockStorageSourceGetSshProps(virStorageSourcePtr src) static virJSONValuePtr -qemuBlockStorageSourceGetFileProps(virStorageSourcePtr src) +qemuBlockStorageSourceGetFileProps(virStorageSourcePtr src, + bool onlytarget) { const char *driver = "file"; const char *iomode = NULL; const char *prManagerAlias = NULL; virJSONValuePtr ret = NULL; - if (src->iomode != VIR_DOMAIN_DISK_IO_DEFAULT) - iomode = virDomainDiskIoTypeToString(src->iomode); - if (virStorageSourceIsBlockLocal(src)) { if (src->hostcdrom) driver = "host_cdrom"; @@ -960,8 +973,13 @@ qemuBlockStorageSourceGetFileProps(virStorageSourcePtr src) driver = "host_device"; } - if (src->pr) - prManagerAlias = src->pr->mgralias; + if (!onlytarget) { + if (src->pr) + prManagerAlias = src->pr->mgralias; + + if (src->iomode != VIR_DOMAIN_DISK_IO_DEFAULT) + iomode = virDomainDiskIoTypeToString(src->iomode); + } ignore_value(virJSONValueObjectCreate(&ret, "s:driver", driver, @@ -974,21 +992,26 @@ qemuBlockStorageSourceGetFileProps(virStorageSourcePtr src) static virJSONValuePtr -qemuBlockStorageSourceGetVvfatProps(virStorageSourcePtr src) +qemuBlockStorageSourceGetVvfatProps(virStorageSourcePtr src, + bool onlytarget) { - virJSONValuePtr ret = NULL; + VIR_AUTOPTR(virJSONValue) ret = NULL; /* libvirt currently does not handle the following attributes: * '*fat-type': 'int' * '*label': 'str' */ - ignore_value(virJSONValueObjectCreate(&ret, - "s:driver", "vvfat", - "s:dir", src->path, - "b:floppy", src->floppyimg, - "b:rw", !src->readonly, NULL)); + if (virJSONValueObjectCreate(&ret, + "s:driver", "vvfat", + "s:dir", src->path, + "b:floppy", src->floppyimg, NULL) < 0) + return NULL; - return ret; + if (!onlytarget && + virJSONValueObjectAdd(ret, "b:rw", !src->readonly, NULL) < 0) + return NULL; + + VIR_RETURN_PTR(ret); } @@ -1024,13 +1047,15 @@ qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSourcePtr src, * qemuBlockStorageSourceGetBackendProps: * @src: disk source * @legacy: use legacy formatting of attributes (for -drive / old qemus) + * @onlytarget: omit any data which does not identify the image itself * * Creates a JSON object describing the underlying storage or protocol of a * storage source. Returns NULL on error and reports an appropriate error message. */ virJSONValuePtr qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, - bool legacy) + bool legacy, + bool onlytarget) { int actualType = virStorageSourceGetActualType(src); VIR_AUTOPTR(virJSONValue) fileprops = NULL; @@ -1038,14 +1063,14 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, switch ((virStorageType)actualType) { case VIR_STORAGE_TYPE_BLOCK: case VIR_STORAGE_TYPE_FILE: - if (!(fileprops = qemuBlockStorageSourceGetFileProps(src))) + if (!(fileprops = qemuBlockStorageSourceGetFileProps(src, onlytarget))) return NULL; break; case VIR_STORAGE_TYPE_DIR: /* qemu handles directories by exposing them as a device with emulated * FAT filesystem */ - if (!(fileprops = qemuBlockStorageSourceGetVvfatProps(src))) + if (!(fileprops = qemuBlockStorageSourceGetVvfatProps(src, onlytarget))) return NULL; break; @@ -1057,12 +1082,12 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, case VIR_STORAGE_TYPE_NETWORK: switch ((virStorageNetProtocol) src->protocol) { case VIR_STORAGE_NET_PROTOCOL_GLUSTER: - if (!(fileprops = qemuBlockStorageSourceGetGlusterProps(src, legacy))) + if (!(fileprops = qemuBlockStorageSourceGetGlusterProps(src, legacy, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_VXHS: - if (!(fileprops = qemuBlockStorageSourceGetVxHSProps(src))) + if (!(fileprops = qemuBlockStorageSourceGetVxHSProps(src, onlytarget))) return NULL; break; @@ -1071,22 +1096,22 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, case VIR_STORAGE_NET_PROTOCOL_FTP: case VIR_STORAGE_NET_PROTOCOL_FTPS: case VIR_STORAGE_NET_PROTOCOL_TFTP: - if (!(fileprops = qemuBlockStorageSourceGetCURLProps(src))) + if (!(fileprops = qemuBlockStorageSourceGetCURLProps(src, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_ISCSI: - if (!(fileprops = qemuBlockStorageSourceGetISCSIProps(src))) + if (!(fileprops = qemuBlockStorageSourceGetISCSIProps(src, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_NBD: - if (!(fileprops = qemuBlockStorageSourceGetNBDProps(src))) + if (!(fileprops = qemuBlockStorageSourceGetNBDProps(src, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_RBD: - if (!(fileprops = qemuBlockStorageSourceGetRBDProps(src))) + if (!(fileprops = qemuBlockStorageSourceGetRBDProps(src, onlytarget))) return NULL; break; @@ -1107,19 +1132,21 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, break; } - if (qemuBlockNodeNameValidate(src->nodestorage) < 0 || - virJSONValueObjectAdd(fileprops, "S:node-name", src->nodestorage, NULL) < 0) - return NULL; - - if (!legacy) { - if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, fileprops) < 0) + if (!onlytarget) { + if (qemuBlockNodeNameValidate(src->nodestorage) < 0 || + virJSONValueObjectAdd(fileprops, "S:node-name", src->nodestorage, NULL) < 0) return NULL; - if (virJSONValueObjectAdd(fileprops, - "b:read-only", src->readonly, - "s:discard", "unmap", - NULL) < 0) - return NULL; + if (!legacy) { + if (qemuBlockStorageSourceGetBlockdevGetCacheProps(src, fileprops) < 0) + return NULL; + + if (virJSONValueObjectAdd(fileprops, + "b:read-only", src->readonly, + "s:discard", "unmap", + NULL) < 0) + return NULL; + } } VIR_RETURN_PTR(fileprops); @@ -1440,7 +1467,7 @@ qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src) return NULL; if (!(data->formatProps = qemuBlockStorageSourceGetBlockdevProps(src)) || - !(data->storageProps = qemuBlockStorageSourceGetBackendProps(src, false))) + !(data->storageProps = qemuBlockStorageSourceGetBackendProps(src, false, false))) return NULL; data->storageNodeName = src->nodestorage; diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index 934a1f125d..7b94f4f0ff 100644 --- a/src/qemu/qemu_block.h +++ b/src/qemu/qemu_block.h @@ -58,7 +58,8 @@ qemuBlockStorageSourceSupportsConcurrentAccess(virStorageSourcePtr src); virJSONValuePtr qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, - bool legacy); + bool legacy, + bool onlytarget); virURIPtr qemuBlockStorageSourceGetURI(virStorageSourcePtr src); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 688dc324c6..b963fc7235 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1610,7 +1610,7 @@ qemuDiskSourceGetProps(virStorageSourcePtr src) virJSONValuePtr props; virJSONValuePtr ret; - if (!(props = qemuBlockStorageSourceGetBackendProps(src, true))) + if (!(props = qemuBlockStorageSourceGetBackendProps(src, true, false))) return NULL; if (virJSONValueObjectCreate(&ret, "a:file", &props, NULL) < 0) { diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index 21db3e4881..29ce27021f 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -67,7 +67,7 @@ testBackingXMLjsonXML(const void *args) return -1; } - if (!(backendprops = qemuBlockStorageSourceGetBackendProps(xmlsrc, true))) { + if (!(backendprops = qemuBlockStorageSourceGetBackendProps(xmlsrc, true, false))) { fprintf(stderr, "failed to format disk source json\n"); return -1; } @@ -213,7 +213,7 @@ testQemuDiskXMLToProps(const void *opaque) goto cleanup; if (!(formatProps = qemuBlockStorageSourceGetBlockdevProps(n)) || - !(storageProps = qemuBlockStorageSourceGetBackendProps(n, false))) { + !(storageProps = qemuBlockStorageSourceGetBackendProps(n, false, false))) { if (!data->fail) { VIR_TEST_VERBOSE("failed to generate qemu blockdev props\n"); goto cleanup; -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:25PM +0200, Peter Krempa wrote:
When formatting new qcow2 images we need to provide the backing store string which should not contain any authentication or irelevant data.
irrelevant
Add a flag for qemuBlockStorageSourceGetBackendProps which allows to skip the irrelevant data.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 121 ++++++++++++++++++++++++---------------- src/qemu/qemu_block.h | 3 +- src/qemu/qemu_command.c | 2 +- tests/qemublocktest.c | 4 +- 4 files changed, 79 insertions(+), 51 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Add testing of the host specification part so that we can be sure that no image/host specific data will be present. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemublocktest.c | 69 ++++++++++++++++++- .../xml2json/block-raw-noopts-srconly.json | 4 ++ .../block-raw-reservations-srconly.json | 4 ++ .../xml2json/dir-fat-cache-srconly.json | 5 ++ .../xml2json/dir-fat-floppy-srconly.json | 5 ++ .../xml2json/dir-fat-readonly-srconly.json | 5 ++ ...ile-backing_basic-aio_threads-srconly.json | 24 +++++++ ...acking_basic-cache-directsync-srconly.json | 24 +++++++ ...file-backing_basic-cache-none-srconly.json | 24 +++++++ ...le-backing_basic-cache-unsafe-srconly.json | 24 +++++++ ...backing_basic-cache-writeback-srconly.json | 24 +++++++ ...king_basic-cache-writethrough-srconly.json | 24 +++++++ .../file-backing_basic-detect-srconly.json | 24 +++++++ .../file-backing_basic-noopts-srconly.json | 16 +++++ ...le-backing_basic-unmap-detect-srconly.json | 24 +++++++ ...le-backing_basic-unmap-ignore-srconly.json | 24 +++++++ .../file-backing_basic-unmap-srconly.json | 24 +++++++ .../xml2json/file-bochs-noopts-srconly.json | 4 ++ .../xml2json/file-cloop-noopts-srconly.json | 4 ++ .../xml2json/file-dmg-noopts-srconly.json | 4 ++ .../xml2json/file-ploop-noopts-srconly.json | 4 ++ ...cow2-backing-chain-encryption-srconly.json | 8 +++ ...le-qcow2-backing-chain-noopts-srconly.json | 40 +++++++++++ ...w2-backing-chain-unterminated-srconly.json | 8 +++ .../xml2json/file-raw-aio_native-srconly.json | 4 ++ .../xml2json/file-raw-luks-srconly.json | 4 ++ .../xml2json/file-raw-noopts-srconly.json | 4 ++ .../xml2json/file-vdi-noopts-srconly.json | 4 ++ .../xml2json/file-vhd-noopts-srconly.json | 4 ++ .../xml2json/file-vpc-noopts-srconly.json | 4 ++ .../xml2json/network-nbd-tls-srconly.json | 8 +++ ...w2-backing-chain-cache-unsafe-srconly.json | 22 ++++++ ...backing-chain-encryption_auth-srconly.json | 22 ++++++ 33 files changed, 495 insertions(+), 1 deletion(-) create mode 100644 tests/qemublocktestdata/xml2json/block-raw-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/block-raw-reservations-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/dir-fat-cache-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/dir-fat-floppy-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/dir-fat-readonly-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-none-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-detect-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-backing_basic-unmap-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-bochs-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-cloop-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-dmg-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-ploop-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-raw-aio_native-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-raw-luks-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-raw-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-vdi-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-vhd-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/file-vpc-noopts-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/network-nbd-tls-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe-srconly.json create mode 100644 tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth-srconly.json diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index 29ce27021f..161615f7f0 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -115,6 +115,9 @@ struct testQemuDiskXMLToJSONData { virJSONValuePtr *props; size_t nprops; + virJSONValuePtr *propssrc; + size_t npropssrc; + virQEMUCapsPtr qemuCaps; }; @@ -127,8 +130,13 @@ testQemuDiskXMLToPropsClear(struct testQemuDiskXMLToJSONData *data) for (i = 0; i < data->nprops; i++) virJSONValueFree(data->props[i]); + for (i = 0; i < data->npropssrc; i++) + virJSONValueFree(data->propssrc[i]); + data->nprops = 0; VIR_FREE(data->props); + data->npropssrc = 0; + VIR_FREE(data->propssrc); } @@ -180,6 +188,7 @@ testQemuDiskXMLToProps(const void *opaque) virStorageSourcePtr n; virJSONValuePtr formatProps = NULL; virJSONValuePtr storageProps = NULL; + VIR_AUTOPTR(virJSONValue) storageSrcOnlyProps = NULL; char *xmlpath = NULL; char *xmlstr = NULL; int ret = -1; @@ -213,6 +222,7 @@ testQemuDiskXMLToProps(const void *opaque) goto cleanup; if (!(formatProps = qemuBlockStorageSourceGetBlockdevProps(n)) || + !(storageSrcOnlyProps = qemuBlockStorageSourceGetBackendProps(n, false, true)) || !(storageProps = qemuBlockStorageSourceGetBackendProps(n, false, false))) { if (!data->fail) { VIR_TEST_VERBOSE("failed to generate qemu blockdev props\n"); @@ -224,7 +234,8 @@ testQemuDiskXMLToProps(const void *opaque) } if (VIR_APPEND_ELEMENT(data->props, data->nprops, formatProps) < 0 || - VIR_APPEND_ELEMENT(data->props, data->nprops, storageProps) < 0) + VIR_APPEND_ELEMENT(data->props, data->nprops, storageProps) < 0 || + VIR_APPEND_ELEMENT(data->propssrc, data->npropssrc, storageSrcOnlyProps) < 0) goto cleanup; } @@ -268,6 +279,23 @@ testQemuDiskXMLToPropsValidateSchema(const void *opaque) virBufferFreeAndReset(&debug); } + + for (i = 0; i < data->npropssrc; i++) { + if (testQEMUSchemaValidate(data->propssrc[i], data->schemaroot, + data->schema, &debug) < 0) { + debugmsg = virBufferContentAndReset(&debug); + propsstr = virJSONValueToString(data->propssrc[i], true); + VIR_TEST_VERBOSE("json does not conform to QAPI schema"); + VIR_TEST_DEBUG("json:\n%s\ndoes not match schema. Debug output:\n %s", + propsstr, NULLSTR(debugmsg)); + VIR_FREE(debugmsg); + VIR_FREE(propsstr); + ret = -1; + } + + virBufferFreeAndReset(&debug); + } + return ret; } @@ -313,6 +341,40 @@ testQemuDiskXMLToPropsValidateFile(const void *opaque) } +static int +testQemuDiskXMLToPropsValidateFileSrcOnly(const void *opaque) +{ + struct testQemuDiskXMLToJSONData *data = (void *) opaque; + virBuffer buf = VIR_BUFFER_INITIALIZER; + VIR_AUTOFREE(char *) jsonpath = NULL; + VIR_AUTOFREE(char *) actual = NULL; + size_t i; + + if (data->fail) + return EXIT_AM_SKIP; + + if (virAsprintf(&jsonpath, "%s%s-srconly.json", + testQemuDiskXMLToJSONPath, data->name) < 0) + return -1; + + for (i = 0; i < data->npropssrc; i++) { + VIR_AUTOFREE(char *) jsonstr = NULL; + + if (!(jsonstr = virJSONValueToString(data->propssrc[i], true))) + return -1; + + virBufferAdd(&buf, jsonstr, -1); + } + + if (virBufferCheckError(&buf) < 0) + return -1; + + actual = virBufferContentAndReset(&buf); + + return virTestCompareToFile(actual, jsonpath); +} + + static int mymain(void) { @@ -411,6 +473,8 @@ mymain(void) diskxmljsondata.name = nme; \ diskxmljsondata.props = NULL; \ diskxmljsondata.nprops = 0; \ + diskxmljsondata.propssrc = NULL; \ + diskxmljsondata.npropssrc = 0; \ diskxmljsondata.fail = fl; \ if (virTestRun("disk xml to props " nme, testQemuDiskXMLToProps, \ &diskxmljsondata) < 0) \ @@ -421,6 +485,9 @@ mymain(void) if (virTestRun("disk xml to props validate file " nme, \ testQemuDiskXMLToPropsValidateFile, &diskxmljsondata) < 0) \ ret = -1; \ + if (virTestRun("disk xml to props source only validate file " nme, \ + testQemuDiskXMLToPropsValidateFileSrcOnly, &diskxmljsondata) < 0) \ + ret = -1; \ testQemuDiskXMLToPropsClear(&diskxmljsondata); \ } while (0) diff --git a/tests/qemublocktestdata/xml2json/block-raw-noopts-srconly.json b/tests/qemublocktestdata/xml2json/block-raw-noopts-srconly.json new file mode 100644 index 0000000000..72f9067353 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/block-raw-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "host_device", + "filename": "/dev/blah" +} diff --git a/tests/qemublocktestdata/xml2json/block-raw-reservations-srconly.json b/tests/qemublocktestdata/xml2json/block-raw-reservations-srconly.json new file mode 100644 index 0000000000..72f9067353 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/block-raw-reservations-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "host_device", + "filename": "/dev/blah" +} diff --git a/tests/qemublocktestdata/xml2json/dir-fat-cache-srconly.json b/tests/qemublocktestdata/xml2json/dir-fat-cache-srconly.json new file mode 100644 index 0000000000..6ec4f78d7b --- /dev/null +++ b/tests/qemublocktestdata/xml2json/dir-fat-cache-srconly.json @@ -0,0 +1,5 @@ +{ + "driver": "vvfat", + "dir": "/var/somefiles", + "floppy": false +} diff --git a/tests/qemublocktestdata/xml2json/dir-fat-floppy-srconly.json b/tests/qemublocktestdata/xml2json/dir-fat-floppy-srconly.json new file mode 100644 index 0000000000..6b0388bc18 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/dir-fat-floppy-srconly.json @@ -0,0 +1,5 @@ +{ + "driver": "vvfat", + "dir": "/var/somefiles", + "floppy": true +} diff --git a/tests/qemublocktestdata/xml2json/dir-fat-readonly-srconly.json b/tests/qemublocktestdata/xml2json/dir-fat-readonly-srconly.json new file mode 100644 index 0000000000..6ec4f78d7b --- /dev/null +++ b/tests/qemublocktestdata/xml2json/dir-fat-readonly-srconly.json @@ -0,0 +1,5 @@ +{ + "driver": "vvfat", + "dir": "/var/somefiles", + "floppy": false +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-none-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-none-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-none-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-detect-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-detect-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-detect-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-noopts-srconly.json new file mode 100644 index 0000000000..dbdf6e563b --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-noopts-srconly.json @@ -0,0 +1,16 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/c" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-srconly.json b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-srconly.json new file mode 100644 index 0000000000..ea490b0034 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-srconly.json @@ -0,0 +1,24 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} +{ + "driver": "gluster", + "volume": "images", + "path": "c", + "server": [ + { + "type": "inet", + "host": "test.org", + "port": "24007" + } + ] +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/d" +} diff --git a/tests/qemublocktestdata/xml2json/file-bochs-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-bochs-noopts-srconly.json new file mode 100644 index 0000000000..c50fa903f5 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-bochs-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/to/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-cloop-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-cloop-noopts-srconly.json new file mode 100644 index 0000000000..c50fa903f5 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-cloop-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/to/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-dmg-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-dmg-noopts-srconly.json new file mode 100644 index 0000000000..c50fa903f5 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-dmg-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/to/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-ploop-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-ploop-noopts-srconly.json new file mode 100644 index 0000000000..c50fa903f5 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-ploop-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/to/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption-srconly.json b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption-srconly.json new file mode 100644 index 0000000000..316dbc9df2 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption-srconly.json @@ -0,0 +1,8 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/a" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/b" +} diff --git a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts-srconly.json new file mode 100644 index 0000000000..d998acc194 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts-srconly.json @@ -0,0 +1,40 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1507297895" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1484071872" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1483615252" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1483605924" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1483605920" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1483546244" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1483545901" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1483545313" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1483536402" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.qcow2" +} diff --git a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated-srconly.json b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated-srconly.json new file mode 100644 index 0000000000..e0bce3bcd2 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated-srconly.json @@ -0,0 +1,8 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1507297895" +} +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/rhel7.3.1484071872" +} diff --git a/tests/qemublocktestdata/xml2json/file-raw-aio_native-srconly.json b/tests/qemublocktestdata/xml2json/file-raw-aio_native-srconly.json new file mode 100644 index 0000000000..c50fa903f5 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-raw-aio_native-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/to/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-raw-luks-srconly.json b/tests/qemublocktestdata/xml2json/file-raw-luks-srconly.json new file mode 100644 index 0000000000..6d7088211f --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-raw-luks-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/luks.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-raw-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-raw-noopts-srconly.json new file mode 100644 index 0000000000..bb3e8af9eb --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-raw-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-vdi-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-vdi-noopts-srconly.json new file mode 100644 index 0000000000..c50fa903f5 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-vdi-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/to/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-vhd-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-vhd-noopts-srconly.json new file mode 100644 index 0000000000..c50fa903f5 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-vhd-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/to/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/file-vpc-noopts-srconly.json b/tests/qemublocktestdata/xml2json/file-vpc-noopts-srconly.json new file mode 100644 index 0000000000..c50fa903f5 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/file-vpc-noopts-srconly.json @@ -0,0 +1,4 @@ +{ + "driver": "file", + "filename": "/path/to/i.img" +} diff --git a/tests/qemublocktestdata/xml2json/network-nbd-tls-srconly.json b/tests/qemublocktestdata/xml2json/network-nbd-tls-srconly.json new file mode 100644 index 0000000000..455f4e5140 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/network-nbd-tls-srconly.json @@ -0,0 +1,8 @@ +{ + "driver": "nbd", + "server": { + "type": "inet", + "host": "host1.example.com", + "port": "10809" + } +} diff --git a/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe-srconly.json b/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe-srconly.json new file mode 100644 index 0000000000..69ca9caf88 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe-srconly.json @@ -0,0 +1,22 @@ +{ + "driver": "rbd", + "pool": "rbdpool", + "image": "rbdimg", + "server": [ + { + "host": "host1.example.com", + "port": "0" + }, + { + "host": "host2.example.com", + "port": "0" + } + ] +} +{ + "driver": "iscsi", + "portal": "example.org:3260", + "target": "iscsitarget", + "lun": 1, + "transport": "tcp" +} diff --git a/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth-srconly.json b/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth-srconly.json new file mode 100644 index 0000000000..6298329812 --- /dev/null +++ b/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth-srconly.json @@ -0,0 +1,22 @@ +{ + "driver": "rbd", + "pool": "rbdpool", + "image": "rbdimg", + "server": [ + { + "host": "host1.example.com", + "port": "0" + }, + { + "host": "host2.example.com", + "port": "0" + } + ] +} +{ + "driver": "iscsi", + "portal": "example.org:3260", + "target": "iqn.2016-09.com.example:iscsitarget", + "lun": 1, + "transport": "tcp" +} -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:26PM +0200, Peter Krempa wrote:
Add testing of the host specification part so that we can be sure that no image/host specific data will be present.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- @@ -313,6 +341,40 @@ testQemuDiskXMLToPropsValidateFile(const void *opaque) }
+static int +testQemuDiskXMLToPropsValidateFileSrcOnly(const void *opaque) +{ + struct testQemuDiskXMLToJSONData *data = (void *) opaque; + virBuffer buf = VIR_BUFFER_INITIALIZER; + VIR_AUTOFREE(char *) jsonpath = NULL; + VIR_AUTOFREE(char *) actual = NULL; + size_t i; + + if (data->fail) + return EXIT_AM_SKIP; + + if (virAsprintf(&jsonpath, "%s%s-srconly.json", + testQemuDiskXMLToJSONPath, data->name) < 0) + return -1; + + for (i = 0; i < data->npropssrc; i++) { + VIR_AUTOFREE(char *) jsonstr = NULL; + + if (!(jsonstr = virJSONValueToString(data->propssrc[i], true))) + return -1;
This return skips over the virBufferContentAndReset call below. Just mark it as AUTOCLEAN even though this is the only code path needing it.
+ + virBufferAdd(&buf, jsonstr, -1); + } + + if (virBufferCheckError(&buf) < 0) + return -1; + + actual = virBufferContentAndReset(&buf); + + return virTestCompareToFile(actual, jsonpath); +} + + static int mymain(void) {
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Libvirt treats the JSON objects as lists thus the values appear in the order they were added. To avoid too much changes introduce a helper which allows to prepend a string which will allow to keep certain outputs in order. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virjson.c | 50 +++++++++++++++++++++++++++++++++------- src/util/virjson.h | 1 + 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b8772d2895..d21f415f97 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2244,6 +2244,7 @@ virJSONValueObjectGetValue; virJSONValueObjectHasKey; virJSONValueObjectIsNull; virJSONValueObjectKeysNumber; +virJSONValueObjectPrependString; virJSONValueObjectRemoveKey; virJSONValueObjectStealArray; virJSONValueObjectStealObject; diff --git a/src/util/virjson.c b/src/util/virjson.c index d2664b9d57..1cf2fb1e5c 100644 --- a/src/util/virjson.c +++ b/src/util/virjson.c @@ -606,10 +606,11 @@ virJSONValueNewObject(void) } -int -virJSONValueObjectAppend(virJSONValuePtr object, +static int +virJSONValueObjectInsert(virJSONValuePtr object, const char *key, - virJSONValuePtr value) + virJSONValuePtr value, + bool prepend) { virJSONObjectPair pair = { NULL, value }; int ret = -1; @@ -628,8 +629,13 @@ virJSONValueObjectAppend(virJSONValuePtr object, if (VIR_STRDUP(pair.key, key) < 0) return -1; - ret = VIR_APPEND_ELEMENT(object->data.object.pairs, - object->data.object.npairs, pair); + if (prepend) { + ret = VIR_INSERT_ELEMENT(object->data.object.pairs, 0, + object->data.object.npairs, pair); + } else { + ret = VIR_APPEND_ELEMENT(object->data.object.pairs, + object->data.object.npairs, pair); + } VIR_FREE(pair.key); return ret; @@ -637,14 +643,24 @@ virJSONValueObjectAppend(virJSONValuePtr object, int -virJSONValueObjectAppendString(virJSONValuePtr object, +virJSONValueObjectAppend(virJSONValuePtr object, + const char *key, + virJSONValuePtr value) +{ + return virJSONValueObjectInsert(object, key, value, false); +} + + +static int +virJSONValueObjectInsertString(virJSONValuePtr object, const char *key, - const char *value) + const char *value, + bool prepend) { virJSONValuePtr jvalue = virJSONValueNewString(value); if (!jvalue) return -1; - if (virJSONValueObjectAppend(object, key, jvalue) < 0) { + if (virJSONValueObjectInsert(object, key, jvalue, prepend) < 0) { virJSONValueFree(jvalue); return -1; } @@ -652,6 +668,24 @@ virJSONValueObjectAppendString(virJSONValuePtr object, } +int +virJSONValueObjectAppendString(virJSONValuePtr object, + const char *key, + const char *value) +{ + return virJSONValueObjectInsertString(object, key, value, false); +} + + +int +virJSONValueObjectPrependString(virJSONValuePtr object, + const char *key, + const char *value) +{ + return virJSONValueObjectInsertString(object, key, value, true); +} + + int virJSONValueObjectAppendNumberInt(virJSONValuePtr object, const char *key, diff --git a/src/util/virjson.h b/src/util/virjson.h index 41404a9a3e..a5f959595f 100644 --- a/src/util/virjson.h +++ b/src/util/virjson.h @@ -126,6 +126,7 @@ int virJSONValueObjectGetBoolean(virJSONValuePtr object, const char *key, bool * int virJSONValueObjectIsNull(virJSONValuePtr object, const char *key); int virJSONValueObjectAppendString(virJSONValuePtr object, const char *key, const char *value); +int virJSONValueObjectPrependString(virJSONValuePtr object, const char *key, const char *value); int virJSONValueObjectAppendNumberInt(virJSONValuePtr object, const char *key, int number); int virJSONValueObjectAppendNumberUint(virJSONValuePtr object, const char *key, unsigned int number); int virJSONValueObjectAppendNumberLong(virJSONValuePtr object, const char *key, long long number); -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:27PM +0200, Peter Krempa wrote:
Libvirt treats the JSON objects as lists thus the values appear in the order they were added. To avoid too much changes introduce a helper which allows to prepend a string which will allow to keep certain outputs in order.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/libvirt_private.syms | 1 + src/util/virjson.c | 50 +++++++++++++++++++++++++++++++++------- src/util/virjson.h | 1 + 3 files changed, 44 insertions(+), 8 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

To allow reusing the formatters in the code for creating JSON properties for 'blockdev-create' we need to create everyhing except the 'driver' attribute. Use the new helper virJSONValueObjectPrependString to put the driver at the same place so that we don't change any output. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 771797989e..c9e6af49c9 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -640,7 +640,6 @@ qemuBlockStorageSourceGetGlusterProps(virStorageSourcePtr src, * {type:"unix", socket:"/tmp/glusterd.socket"}, ...]} */ if (virJSONValueObjectCreate(&props, - "s:driver", "gluster", "s:volume", src->volume, "s:path", src->path, "a:server", &servers, NULL) < 0) @@ -659,7 +658,6 @@ static virJSONValuePtr qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src, bool onlytarget) { - const char *protocol = virStorageNetProtocolTypeToString(src->protocol); VIR_AUTOPTR(virJSONValue) server = NULL; const char *tlsAlias = src->tlsAlias; virJSONValuePtr ret = NULL; @@ -683,7 +681,6 @@ qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src, * server:{type:"tcp", host:"1.2.3.4", port:9999}} */ ignore_value(virJSONValueObjectCreate(&ret, - "s:driver", protocol, "S:tls-creds", tlsAlias, "s:vdisk-id", src->path, "a:server", &server, NULL)); @@ -702,7 +699,6 @@ qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src, virJSONValuePtr ret = NULL; VIR_AUTOPTR(virURI) uri = NULL; VIR_AUTOFREE(char *) uristr = NULL; - const char *driver; /** * Common options: @@ -716,7 +712,6 @@ qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src, * sslverify */ - driver = virStorageNetProtocolTypeToString(src->protocol); if (!(uri = qemuBlockStorageSourceGetURI(src))) return NULL; @@ -730,7 +725,6 @@ qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src, } ignore_value(virJSONValueObjectCreate(&ret, - "s:driver", driver, "s:url", uristr, "S:username", username, "S:password-secret", passwordalias, @@ -745,7 +739,6 @@ qemuBlockStorageSourceGetISCSIProps(virStorageSourcePtr src, bool onlytarget) { qemuDomainStorageSourcePrivatePtr srcPriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src); - const char *protocol = virStorageNetProtocolTypeToString(src->protocol); VIR_AUTOFREE(char *) target = NULL; char *lunStr = NULL; char *username = NULL; @@ -796,7 +789,6 @@ qemuBlockStorageSourceGetISCSIProps(virStorageSourcePtr src, } ignore_value(virJSONValueObjectCreate(&ret, - "s:driver", protocol, "s:portal", portal, "s:target", target, "u:lun", lun, @@ -832,7 +824,6 @@ qemuBlockStorageSourceGetNBDProps(virStorageSourcePtr src, tlsAlias = NULL; if (virJSONValueObjectCreate(&ret, - "s:driver", "nbd", "a:server", &serverprops, "S:export", src->path, "S:tls-creds", tlsAlias, @@ -880,7 +871,6 @@ qemuBlockStorageSourceGetRBDProps(virStorageSourcePtr src, } if (virJSONValueObjectCreate(&ret, - "s:driver", "rbd", "s:pool", src->volume, "s:image", src->path, "S:snapshot", src->snapshot, @@ -915,7 +905,6 @@ qemuBlockStorageSourceGetSheepdogProps(virStorageSourcePtr src) /* libvirt does not support the 'snap-id' and 'tag' properties */ if (virJSONValueObjectCreate(&ret, - "s:driver", "sheepdog", "a:server", &serverprops, "s:vdi", src->path, NULL) < 0) @@ -946,7 +935,6 @@ qemuBlockStorageSourceGetSshProps(virStorageSourcePtr src) username = src->auth->username; if (virJSONValueObjectCreate(&ret, - "s:driver", "ssh", "s:path", src->path, "a:server", &serverprops, "S:user", username, @@ -961,18 +949,10 @@ static virJSONValuePtr qemuBlockStorageSourceGetFileProps(virStorageSourcePtr src, bool onlytarget) { - const char *driver = "file"; const char *iomode = NULL; const char *prManagerAlias = NULL; virJSONValuePtr ret = NULL; - if (virStorageSourceIsBlockLocal(src)) { - if (src->hostcdrom) - driver = "host_cdrom"; - else - driver = "host_device"; - } - if (!onlytarget) { if (src->pr) prManagerAlias = src->pr->mgralias; @@ -982,7 +962,6 @@ qemuBlockStorageSourceGetFileProps(virStorageSourcePtr src, } ignore_value(virJSONValueObjectCreate(&ret, - "s:driver", driver, "s:filename", src->path, "S:aio", iomode, "S:pr-manager", prManagerAlias, @@ -1059,10 +1038,20 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, { int actualType = virStorageSourceGetActualType(src); VIR_AUTOPTR(virJSONValue) fileprops = NULL; + const char *driver = NULL; switch ((virStorageType)actualType) { case VIR_STORAGE_TYPE_BLOCK: case VIR_STORAGE_TYPE_FILE: + if (virStorageSourceIsBlockLocal(src)) { + if (src->hostcdrom) + driver = "host_cdrom"; + else + driver = "host_device"; + } else { + driver = "file"; + } + if (!(fileprops = qemuBlockStorageSourceGetFileProps(src, onlytarget))) return NULL; break; @@ -1082,11 +1071,13 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, case VIR_STORAGE_TYPE_NETWORK: switch ((virStorageNetProtocol) src->protocol) { case VIR_STORAGE_NET_PROTOCOL_GLUSTER: + driver = "gluster"; if (!(fileprops = qemuBlockStorageSourceGetGlusterProps(src, legacy, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_VXHS: + driver = "vxhs"; if (!(fileprops = qemuBlockStorageSourceGetVxHSProps(src, onlytarget))) return NULL; break; @@ -1096,31 +1087,37 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, case VIR_STORAGE_NET_PROTOCOL_FTP: case VIR_STORAGE_NET_PROTOCOL_FTPS: case VIR_STORAGE_NET_PROTOCOL_TFTP: + driver = virStorageNetProtocolTypeToString(src->protocol); if (!(fileprops = qemuBlockStorageSourceGetCURLProps(src, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_ISCSI: + driver = "iscsi"; if (!(fileprops = qemuBlockStorageSourceGetISCSIProps(src, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_NBD: + driver = "nbd"; if (!(fileprops = qemuBlockStorageSourceGetNBDProps(src, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_RBD: + driver = "rbd"; if (!(fileprops = qemuBlockStorageSourceGetRBDProps(src, onlytarget))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG: + driver = "sheepdog"; if (!(fileprops = qemuBlockStorageSourceGetSheepdogProps(src))) return NULL; break; case VIR_STORAGE_NET_PROTOCOL_SSH: + driver = "ssh"; if (!(fileprops = qemuBlockStorageSourceGetSshProps(src))) return NULL; break; @@ -1132,6 +1129,9 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, break; } + if (driver && virJSONValueObjectPrependString(fileprops, "driver", driver) < 0) + return NULL; + if (!onlytarget) { if (qemuBlockNodeNameValidate(src->nodestorage) < 0 || virJSONValueObjectAdd(fileprops, "S:node-name", src->nodestorage, NULL) < 0) -- 2.21.0

s/formating/fomatting/ On Thu, Jul 04, 2019 at 04:26:28PM +0200, Peter Krempa wrote:
To allow reusing the formatters in the code for creating JSON properties for 'blockdev-create' we need to create everyhing except the 'driver'
everything
attribute.
Use the new helper virJSONValueObjectPrependString to put the driver at the same place so that we don't change any output.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

To allow using -blockdev with blockjobs need to reopen files in read-write mode when modifying the backing chain. To achieve this we need to use 'auto-read-only' for the backing files rather than the normal 'read-only' property. That way qemu knows that the files need to be reopened. Note that the format drivers (e.g. qcow2) are still opened with the read-only property enabled when being a member of the backing chain since they are supposed to be immutable unless a block job is started. QEMU v4.0 allows also dynamic behaviour for auto-read-only which allows us to use sVirt as we only grant write permissions to files when doing a blockjob. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 26 ++++++++++++++++--- src/qemu/qemu_block.h | 6 +++-- src/qemu/qemu_command.c | 4 +-- src/qemu/qemu_migration.c | 4 ++- tests/qemublocktest.c | 7 ++--- .../xml2json/block-raw-noopts.json | 2 +- .../xml2json/block-raw-reservations.json | 2 +- .../xml2json/dir-fat-cache.json | 2 +- .../xml2json/dir-fat-floppy.json | 2 +- .../xml2json/dir-fat-readonly.json | 2 +- .../file-backing_basic-aio_threads.json | 8 +++--- .../file-backing_basic-cache-directsync.json | 8 +++--- .../file-backing_basic-cache-none.json | 8 +++--- .../file-backing_basic-cache-unsafe.json | 8 +++--- .../file-backing_basic-cache-writeback.json | 8 +++--- ...file-backing_basic-cache-writethrough.json | 8 +++--- .../xml2json/file-backing_basic-detect.json | 8 +++--- .../xml2json/file-backing_basic-noopts.json | 8 +++--- .../file-backing_basic-unmap-detect.json | 8 +++--- .../file-backing_basic-unmap-ignore.json | 8 +++--- .../xml2json/file-backing_basic-unmap.json | 8 +++--- .../xml2json/file-bochs-noopts.json | 2 +- .../xml2json/file-cloop-noopts.json | 2 +- .../xml2json/file-dmg-noopts.json | 2 +- .../xml2json/file-ploop-noopts.json | 2 +- .../file-qcow2-backing-chain-encryption.json | 4 +-- .../file-qcow2-backing-chain-noopts.json | 20 +++++++------- ...file-qcow2-backing-chain-unterminated.json | 4 +-- .../xml2json/file-raw-aio_native.json | 2 +- .../xml2json/file-raw-luks.json | 2 +- .../xml2json/file-raw-noopts.json | 2 +- .../xml2json/file-vdi-noopts.json | 2 +- .../xml2json/file-vhd-noopts.json | 2 +- .../xml2json/file-vpc-noopts.json | 2 +- .../xml2json/network-nbd-tls.json | 2 +- ...work-qcow2-backing-chain-cache-unsafe.json | 4 +-- ...k-qcow2-backing-chain-encryption_auth.json | 4 +-- .../qemu-ns.x86_64-4.0.0.args | 2 +- .../qemu-ns.x86_64-latest.args | 2 +- 39 files changed, 115 insertions(+), 92 deletions(-) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index c9e6af49c9..9abdac5ca3 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -1027,6 +1027,7 @@ qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSourcePtr src, * @src: disk source * @legacy: use legacy formatting of attributes (for -drive / old qemus) * @onlytarget: omit any data which does not identify the image itself + * @autoreadonly: Use the new auto-readonly feature in qemu * * Creates a JSON object describing the underlying storage or protocol of a * storage source. Returns NULL on error and reports an appropriate error message. @@ -1034,11 +1035,23 @@ qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSourcePtr src, virJSONValuePtr qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, bool legacy, - bool onlytarget) + bool onlytarget, + bool autoreadonly) { int actualType = virStorageSourceGetActualType(src); VIR_AUTOPTR(virJSONValue) fileprops = NULL; const char *driver = NULL; + virTristateBool aro = VIR_TRISTATE_BOOL_ABSENT; + virTristateBool ro = VIR_TRISTATE_BOOL_ABSENT; + + if (autoreadonly) { + aro = VIR_TRISTATE_BOOL_YES; + } else { + if (src->readonly) + ro = VIR_TRISTATE_BOOL_YES; + else + ro = VIR_TRISTATE_BOOL_NO; + } switch ((virStorageType)actualType) { case VIR_STORAGE_TYPE_BLOCK: @@ -1142,7 +1155,8 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, return NULL; if (virJSONValueObjectAdd(fileprops, - "b:read-only", src->readonly, + "T:read-only", ro, + "T:auto-read-only", aro, "s:discard", "unmap", NULL) < 0) return NULL; @@ -1447,6 +1461,7 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data) /** * qemuBlockStorageSourceAttachPrepareBlockdev: * @src: storage source to prepare data from + * @autoreadonly: use 'auto-read-only' feature of qemu * * Creates a qemuBlockStorageSourceAttachData structure containing data to attach * @src to a VM using the blockdev-add approach. Note that this function only @@ -1459,7 +1474,8 @@ qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data) * error is reported */ qemuBlockStorageSourceAttachDataPtr -qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src) +qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src, + bool autoreadonly) { VIR_AUTOPTR(qemuBlockStorageSourceAttachData) data = NULL; @@ -1467,7 +1483,9 @@ qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src) return NULL; if (!(data->formatProps = qemuBlockStorageSourceGetBlockdevProps(src)) || - !(data->storageProps = qemuBlockStorageSourceGetBackendProps(src, false, false))) + !(data->storageProps = qemuBlockStorageSourceGetBackendProps(src, false, + false, + autoreadonly))) return NULL; data->storageNodeName = src->nodestorage; diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index 7b94f4f0ff..12ddfad2ac 100644 --- a/src/qemu/qemu_block.h +++ b/src/qemu/qemu_block.h @@ -59,7 +59,8 @@ qemuBlockStorageSourceSupportsConcurrentAccess(virStorageSourcePtr src); virJSONValuePtr qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, bool legacy, - bool onlytarget); + bool onlytarget, + bool autoreadonly); virURIPtr qemuBlockStorageSourceGetURI(virStorageSourcePtr src); @@ -106,7 +107,8 @@ VIR_DEFINE_AUTOPTR_FUNC(qemuBlockStorageSourceAttachData, qemuBlockStorageSourceAttachDataFree); qemuBlockStorageSourceAttachDataPtr -qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src); +qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src, + bool autoreadonly); qemuBlockStorageSourceAttachDataPtr qemuBlockStorageSourceDetachPrepare(virStorageSourcePtr src, diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index b963fc7235..27f71ce0fa 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1610,7 +1610,7 @@ qemuDiskSourceGetProps(virStorageSourcePtr src) virJSONValuePtr props; virJSONValuePtr ret; - if (!(props = qemuBlockStorageSourceGetBackendProps(src, true, false))) + if (!(props = qemuBlockStorageSourceGetBackendProps(src, true, false, false))) return NULL; if (virJSONValueObjectCreate(&ret, "a:file", &props, NULL) < 0) { @@ -11206,7 +11206,7 @@ qemuBuildStorageSourceChainAttachPrepareBlockdev(virStorageSourcePtr top, return NULL; for (n = top; virStorageSourceIsBacking(n); n = n->backingStore) { - if (!(elem = qemuBlockStorageSourceAttachPrepareBlockdev(n))) + if (!(elem = qemuBlockStorageSourceAttachPrepareBlockdev(n, true))) return NULL; if (qemuBuildStorageSourceAttachPrepareCommon(n, elem, qemuCaps) < 0) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 2436f5051b..e71933446a 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -830,7 +830,9 @@ qemuMigrationSrcNBDStorageCopyBlockdev(virQEMUDriverPtr driver, virAsprintf(©src->nodeformat, "migration-%s-format", disk->dst) < 0) goto cleanup; - if (!(data = qemuBlockStorageSourceAttachPrepareBlockdev(copysrc))) + /* Migration via blockdev-mirror was supported sooner than the auto-read-only + * feature was added to qemu */ + if (!(data = qemuBlockStorageSourceAttachPrepareBlockdev(copysrc, false))) goto cleanup; if (qemuDomainObjEnterMonitorAsync(driver, vm, diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index 161615f7f0..5c381d1e3b 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -67,7 +67,8 @@ testBackingXMLjsonXML(const void *args) return -1; } - if (!(backendprops = qemuBlockStorageSourceGetBackendProps(xmlsrc, true, false))) { + if (!(backendprops = qemuBlockStorageSourceGetBackendProps(xmlsrc, true, false, + false))) { fprintf(stderr, "failed to format disk source json\n"); return -1; } @@ -222,8 +223,8 @@ testQemuDiskXMLToProps(const void *opaque) goto cleanup; if (!(formatProps = qemuBlockStorageSourceGetBlockdevProps(n)) || - !(storageSrcOnlyProps = qemuBlockStorageSourceGetBackendProps(n, false, true)) || - !(storageProps = qemuBlockStorageSourceGetBackendProps(n, false, false))) { + !(storageSrcOnlyProps = qemuBlockStorageSourceGetBackendProps(n, false, true, true)) || + !(storageProps = qemuBlockStorageSourceGetBackendProps(n, false, false, true))) { if (!data->fail) { VIR_TEST_VERBOSE("failed to generate qemu blockdev props\n"); goto cleanup; diff --git a/tests/qemublocktestdata/xml2json/block-raw-noopts.json b/tests/qemublocktestdata/xml2json/block-raw-noopts.json index f223659c76..fa8b29a1f9 100644 --- a/tests/qemublocktestdata/xml2json/block-raw-noopts.json +++ b/tests/qemublocktestdata/xml2json/block-raw-noopts.json @@ -8,6 +8,6 @@ "driver": "host_device", "filename": "/dev/blah", "node-name": "0123456789ABCDEF0123456789ABCDE", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/block-raw-reservations.json b/tests/qemublocktestdata/xml2json/block-raw-reservations.json index 2fb106d673..970723279d 100644 --- a/tests/qemublocktestdata/xml2json/block-raw-reservations.json +++ b/tests/qemublocktestdata/xml2json/block-raw-reservations.json @@ -9,6 +9,6 @@ "filename": "/dev/blah", "pr-manager": "node-a-st-pr-alias", "node-name": "node-a-st", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/dir-fat-cache.json b/tests/qemublocktestdata/xml2json/dir-fat-cache.json index ef33add681..2a24175ef4 100644 --- a/tests/qemublocktestdata/xml2json/dir-fat-cache.json +++ b/tests/qemublocktestdata/xml2json/dir-fat-cache.json @@ -18,6 +18,6 @@ "direct": true, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/dir-fat-floppy.json b/tests/qemublocktestdata/xml2json/dir-fat-floppy.json index db7954a6bc..3b4accb8ef 100644 --- a/tests/qemublocktestdata/xml2json/dir-fat-floppy.json +++ b/tests/qemublocktestdata/xml2json/dir-fat-floppy.json @@ -10,6 +10,6 @@ "floppy": true, "rw": false, "node-name": "node-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/dir-fat-readonly.json b/tests/qemublocktestdata/xml2json/dir-fat-readonly.json index a306fb4d47..986e3a3ffd 100644 --- a/tests/qemublocktestdata/xml2json/dir-fat-readonly.json +++ b/tests/qemublocktestdata/xml2json/dir-fat-readonly.json @@ -10,6 +10,6 @@ "floppy": false, "rw": false, "node-name": "node-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads.json b/tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads.json index a9bdd1bcc2..e77421d372 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-aio_threads.json @@ -10,7 +10,7 @@ "filename": "/var/lib/libvirt/images/a", "aio": "threads", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -25,7 +25,7 @@ "filename": "/var/lib/libvirt/images/b", "aio": "threads", "node-name": "node-b-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -47,7 +47,7 @@ } ], "node-name": "node-c-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -61,6 +61,6 @@ "filename": "/var/lib/libvirt/images/d", "aio": "threads", "node-name": "node-d-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync.json index 18cd183cd8..1d5ae09813 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-directsync.json @@ -17,7 +17,7 @@ "direct": true, "no-flush": false }, - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -39,7 +39,7 @@ "direct": true, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -69,7 +69,7 @@ "direct": true, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -90,6 +90,6 @@ "direct": true, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-none.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-none.json index 18cd183cd8..1d5ae09813 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-none.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-none.json @@ -17,7 +17,7 @@ "direct": true, "no-flush": false }, - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -39,7 +39,7 @@ "direct": true, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -69,7 +69,7 @@ "direct": true, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -90,6 +90,6 @@ "direct": true, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe.json index 4e92061c65..4afd7366cf 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-unsafe.json @@ -17,7 +17,7 @@ "direct": false, "no-flush": true }, - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -39,7 +39,7 @@ "direct": false, "no-flush": true }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -69,7 +69,7 @@ "direct": false, "no-flush": true }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -90,6 +90,6 @@ "direct": false, "no-flush": true }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback.json index a105b47483..9ed806eb04 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writeback.json @@ -17,7 +17,7 @@ "direct": false, "no-flush": false }, - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -39,7 +39,7 @@ "direct": false, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -69,7 +69,7 @@ "direct": false, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -90,6 +90,6 @@ "direct": false, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough.json b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough.json index a105b47483..9ed806eb04 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-cache-writethrough.json @@ -17,7 +17,7 @@ "direct": false, "no-flush": false }, - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -39,7 +39,7 @@ "direct": false, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -69,7 +69,7 @@ "direct": false, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -90,6 +90,6 @@ "direct": false, "no-flush": false }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-detect.json b/tests/qemublocktestdata/xml2json/file-backing_basic-detect.json index 44a6e90fcd..6be2df9d1d 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-detect.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-detect.json @@ -10,7 +10,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/a", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -24,7 +24,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/b", "node-name": "node-b-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -46,7 +46,7 @@ } ], "node-name": "node-c-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -59,6 +59,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/d", "node-name": "node-d-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-noopts.json b/tests/qemublocktestdata/xml2json/file-backing_basic-noopts.json index b0fd9b6988..5916347b93 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-noopts.json @@ -9,7 +9,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/a", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -23,7 +23,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/b", "node-name": "node-b-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -37,7 +37,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/c", "node-name": "node-c-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -50,6 +50,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/d", "node-name": "node-d-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json index 6cf4e77090..27e6e5ab60 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-detect.json @@ -11,7 +11,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/a", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -26,7 +26,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/b", "node-name": "node-b-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -49,7 +49,7 @@ } ], "node-name": "node-c-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -63,6 +63,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/d", "node-name": "node-d-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json index b6e454297f..63c5cd2799 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap-ignore.json @@ -11,7 +11,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/a", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -26,7 +26,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/b", "node-name": "node-b-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -49,7 +49,7 @@ } ], "node-name": "node-c-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -63,6 +63,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/d", "node-name": "node-d-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap.json b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap.json index 21a10c8543..ac952c8acd 100644 --- a/tests/qemublocktestdata/xml2json/file-backing_basic-unmap.json +++ b/tests/qemublocktestdata/xml2json/file-backing_basic-unmap.json @@ -10,7 +10,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/a", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -25,7 +25,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/b", "node-name": "node-b-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -48,7 +48,7 @@ } ], "node-name": "node-c-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -62,6 +62,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/d", "node-name": "node-d-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-bochs-noopts.json b/tests/qemublocktestdata/xml2json/file-bochs-noopts.json index 6ab43b2a1c..3692820436 100644 --- a/tests/qemublocktestdata/xml2json/file-bochs-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-bochs-noopts.json @@ -8,6 +8,6 @@ "driver": "file", "filename": "/path/to/i.img", "node-name": "test2", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-cloop-noopts.json b/tests/qemublocktestdata/xml2json/file-cloop-noopts.json index f709c3d3bd..7ae8b5ca5f 100644 --- a/tests/qemublocktestdata/xml2json/file-cloop-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-cloop-noopts.json @@ -8,6 +8,6 @@ "driver": "file", "filename": "/path/to/i.img", "node-name": "test2", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-dmg-noopts.json b/tests/qemublocktestdata/xml2json/file-dmg-noopts.json index 55261de4b2..db722a55cc 100644 --- a/tests/qemublocktestdata/xml2json/file-dmg-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-dmg-noopts.json @@ -8,6 +8,6 @@ "driver": "file", "filename": "/path/to/i.img", "node-name": "test2", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-ploop-noopts.json b/tests/qemublocktestdata/xml2json/file-ploop-noopts.json index 81fa263098..7817b0980e 100644 --- a/tests/qemublocktestdata/xml2json/file-ploop-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-ploop-noopts.json @@ -8,6 +8,6 @@ "driver": "file", "filename": "/path/to/i.img", "node-name": "test2", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption.json b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption.json index 376fce9f9e..57f1f61c05 100644 --- a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption.json +++ b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-encryption.json @@ -13,7 +13,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/a", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -31,6 +31,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/b", "node-name": "node-b-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts.json b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts.json index 6bc6e2fe30..197ee2a4b6 100644 --- a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-noopts.json @@ -9,7 +9,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1507297895", "node-name": "#block004", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -23,7 +23,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1484071872", "node-name": "#block256", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -37,7 +37,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1483615252", "node-name": "#block418", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -51,7 +51,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1483605924", "node-name": "#block624", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -65,7 +65,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1483605920", "node-name": "#block869", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -79,7 +79,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1483546244", "node-name": "#block1047", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -93,7 +93,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1483545901", "node-name": "#block1279", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -107,7 +107,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1483545313", "node-name": "#block1444", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -121,7 +121,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1483536402", "node-name": "#block1602", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } { @@ -135,6 +135,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.qcow2", "node-name": "#block1864", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated.json b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated.json index 454c07faec..3ffefa831c 100644 --- a/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated.json +++ b/tests/qemublocktestdata/xml2json/file-qcow2-backing-chain-unterminated.json @@ -9,7 +9,7 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1507297895", "node-name": "#block004", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -22,6 +22,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/rhel7.3.1484071872", "node-name": "#block256", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-raw-aio_native.json b/tests/qemublocktestdata/xml2json/file-raw-aio_native.json index 4e63561311..1ae76895cd 100644 --- a/tests/qemublocktestdata/xml2json/file-raw-aio_native.json +++ b/tests/qemublocktestdata/xml2json/file-raw-aio_native.json @@ -17,6 +17,6 @@ "direct": true, "no-flush": false }, - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-raw-luks.json b/tests/qemublocktestdata/xml2json/file-raw-luks.json index c26dd3bba5..e4ed61db07 100644 --- a/tests/qemublocktestdata/xml2json/file-raw-luks.json +++ b/tests/qemublocktestdata/xml2json/file-raw-luks.json @@ -9,6 +9,6 @@ "driver": "file", "filename": "/path/luks.img", "node-name": "test2", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-raw-noopts.json b/tests/qemublocktestdata/xml2json/file-raw-noopts.json index cace1f6448..01160c8253 100644 --- a/tests/qemublocktestdata/xml2json/file-raw-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-raw-noopts.json @@ -8,6 +8,6 @@ "driver": "file", "filename": "/var/lib/libvirt/images/i.img", "node-name": "0123456789ABCDEF0123456789ABCDE", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-vdi-noopts.json b/tests/qemublocktestdata/xml2json/file-vdi-noopts.json index 15f9da2091..5d4d6dfe5a 100644 --- a/tests/qemublocktestdata/xml2json/file-vdi-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-vdi-noopts.json @@ -8,6 +8,6 @@ "driver": "file", "filename": "/path/to/i.img", "node-name": "test2", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-vhd-noopts.json b/tests/qemublocktestdata/xml2json/file-vhd-noopts.json index ce96c4be8a..6c810d2036 100644 --- a/tests/qemublocktestdata/xml2json/file-vhd-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-vhd-noopts.json @@ -8,6 +8,6 @@ "driver": "file", "filename": "/path/to/i.img", "node-name": "test2", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/file-vpc-noopts.json b/tests/qemublocktestdata/xml2json/file-vpc-noopts.json index 9cba99e567..69b8102cf4 100644 --- a/tests/qemublocktestdata/xml2json/file-vpc-noopts.json +++ b/tests/qemublocktestdata/xml2json/file-vpc-noopts.json @@ -8,6 +8,6 @@ "driver": "file", "filename": "/path/to/i.img", "node-name": "test2", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/network-nbd-tls.json b/tests/qemublocktestdata/xml2json/network-nbd-tls.json index a1529a6c44..0dc453fb7e 100644 --- a/tests/qemublocktestdata/xml2json/network-nbd-tls.json +++ b/tests/qemublocktestdata/xml2json/network-nbd-tls.json @@ -14,6 +14,6 @@ }, "tls-creds": "node-a-s-tls0", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe.json b/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe.json index e66f62d24b..9ee18dba51 100644 --- a/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe.json +++ b/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-cache-unsafe.json @@ -34,7 +34,7 @@ "direct": false, "no-flush": true }, - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -59,6 +59,6 @@ "direct": false, "no-flush": true }, - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth.json b/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth.json index 921cb3ea69..fb19641982 100644 --- a/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth.json +++ b/tests/qemublocktestdata/xml2json/network-qcow2-backing-chain-encryption_auth.json @@ -30,7 +30,7 @@ ], "key-secret": "node-a-s-secalias", "node-name": "node-a-s", - "read-only": false, + "auto-read-only": true, "discard": "unmap" } { @@ -53,6 +53,6 @@ "user": "testuser-iscsi", "password-secret": "node-b-s-secalias", "node-name": "node-b-s", - "read-only": true, + "auto-read-only": true, "discard": "unmap" } diff --git a/tests/qemuxml2argvdata/qemu-ns.x86_64-4.0.0.args b/tests/qemuxml2argvdata/qemu-ns.x86_64-4.0.0.args index 6e059d336a..2f49af885b 100644 --- a/tests/qemuxml2argvdata/qemu-ns.x86_64-4.0.0.args +++ b/tests/qemuxml2argvdata/qemu-ns.x86_64-4.0.0.args @@ -30,7 +30,7 @@ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ -boot strict=on \ -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ -blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1",\ -"node-name":"libvirt-1-storage","read-only":false,"discard":"unmap"}' \ +"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ -blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw",\ "file":"libvirt-1-storage"}' \ -device ide-hd,bus=ide.0,unit=0,drive=libvirt-1-format,id=ide0-0-0,bootindex=1 \ diff --git a/tests/qemuxml2argvdata/qemu-ns.x86_64-latest.args b/tests/qemuxml2argvdata/qemu-ns.x86_64-latest.args index ebb7b0da37..f898ab2e07 100644 --- a/tests/qemuxml2argvdata/qemu-ns.x86_64-latest.args +++ b/tests/qemuxml2argvdata/qemu-ns.x86_64-latest.args @@ -30,7 +30,7 @@ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \ -boot strict=on \ -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \ -blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1",\ -"node-name":"libvirt-1-storage","read-only":false,"discard":"unmap"}' \ +"node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \ -blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw",\ "file":"libvirt-1-storage"}' \ -device ide-hd,bus=ide.0,unit=0,drive=libvirt-1-format,id=ide0-0-0,bootindex=1 \ -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:29PM +0200, Peter Krempa wrote:
To allow using -blockdev with blockjobs need to reopen files in read-write mode when modifying the backing chain.
-EPARSE s/blockjobs need/blockjobs QEMU needs/
To achieve this we need to use 'auto-read-only' for the backing files rather than the normal 'read-only' property. That way qemu knows that the files need to be reopened.
Note that the format drivers (e.g. qcow2) are still opened with the read-only property enabled when being a member of the backing chain since they are supposed to be immutable unless a block job is started.
QEMU v4.0 allows also dynamic behaviour for auto-read-only which allows us to use sVirt as we only grant write permissions to files when doing a blockjob.
commit 23dece19da41724349809873923e20a48b619cb7 file-posix: Make auto-read-only dynamic
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 26 ++++++++++++++++--- src/qemu/qemu_block.h | 6 +++--
[...]
.../qemu-ns.x86_64-latest.args | 2 +- 39 files changed, 115 insertions(+), 92 deletions(-)
diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index c9e6af49c9..9abdac5ca3 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -1027,6 +1027,7 @@ qemuBlockStorageSourceGetBlockdevGetCacheProps(virStorageSourcePtr src, * @src: disk source * @legacy: use legacy formatting of attributes (for -drive / old qemus) * @onlytarget: omit any data which does not identify the image itself + * @autoreadonly: Use the new auto-readonly feature in qemu
I'd rather avoid use of the word 'new'. Just copy the other wording which also spells the feature name correctly: @autoreadonly: use 'auto-read-only' feature of qemu
* * Creates a JSON object describing the underlying storage or protocol of a * storage source. Returns NULL on error and reports an appropriate error message.
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

'blockdev-add' allows us to use qemu to format images to our desired format. This patch implements helpers which convert a virStorageSourcePtr into JSON objects describing the required configuration. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 321 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_block.h | 6 + 2 files changed, 327 insertions(+) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 9abdac5ca3..54dd2b5328 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -1866,3 +1866,324 @@ qemuBlockStorageGetCopyOnReadProps(virDomainDiskDefPtr disk) return ret; } + + +static int +qemuBlockStorageSourceCreateAddBacking(virStorageSourcePtr backing, + virJSONValuePtr props, + bool format) +{ + VIR_AUTOPTR(virJSONValue) backingProps = NULL; + VIR_AUTOFREE(char *) backingJSON = NULL; + VIR_AUTOFREE(char *) backingPseudoprotocol = NULL; + const char *backingFileStr = NULL; + const char *backingFormatStr = NULL; + + if (!virStorageSourceIsBacking(backing)) + return 0; + + if (format) { + if (backing->encryption && + backing->encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) + backingFormatStr = "luks"; + else + backingFormatStr = virStorageFileFormatTypeToString(backing->format); + } + + if (virStorageSourceIsLocalStorage(backing)) { + backingFileStr = backing->path; + } else { + if (!(backingProps = qemuBlockStorageSourceGetBackendProps(backing, false, + true, false))) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("failed to generate backing file JSON properties")); + return -1; + } + + if (!(backingJSON = virJSONValueToString(backingProps, false))) + return -1; + + if (virAsprintf(&backingPseudoprotocol, "json:%s", backingJSON) < 0) + return -1; + + backingFileStr = backingPseudoprotocol; + } + + if (virJSONValueObjectAdd(props, + "S:backing-file", backingFileStr, + "S:backing-fmt", backingFormatStr, + NULL) < 0) + return -1; + + return 0; +} + + +static int +qemuBlockStorageSourceCreateGetFormatPropsGeneric(virStorageSourcePtr src, + const char *driver, + virJSONValuePtr *retprops, + virStorageSourcePtr backing) +{ + VIR_AUTOPTR(virJSONValue) props = NULL; + + if (virJSONValueObjectCreate(&props, + "s:driver", driver, + "s:file", src->nodestorage, + "u:size", src->capacity, + NULL) < 0) + return -1; + + if (backing && + qemuBlockStorageSourceCreateAddBacking(backing, props, false) < 0) + return -1; + + VIR_STEAL_PTR(*retprops, props); + return 0; +} + + +static int +qemuBlockStorageSourceCreateGetEncryptionLUKS(virStorageSourcePtr src, + virJSONValuePtr *luksProps) +{ + qemuDomainStorageSourcePrivatePtr srcpriv = QEMU_DOMAIN_STORAGE_SOURCE_PRIVATE(src); + VIR_AUTOPTR(virJSONValue) props = NULL; + VIR_AUTOFREE(char *) cipheralg = NULL; + const char *keysecret = NULL; + + if (srcpriv && + srcpriv->encinfo && + srcpriv->encinfo->type == VIR_DOMAIN_SECRET_INFO_TYPE_AES) + keysecret = srcpriv->encinfo->s.aes.alias; + + if (virJSONValueObjectCreate(&props, + "s:key-secret", keysecret, + NULL) < 0) + return -1; + + if (src->encryption) { + if (src->encryption->encinfo.cipher_name && + virAsprintf(&cipheralg, "%s-%u", + src->encryption->encinfo.cipher_name, + src->encryption->encinfo.cipher_size) < 0) + return -1; + + if (virJSONValueObjectAdd(props, + "S:cipher-alg", cipheralg, + "S:cipher-mode", src->encryption->encinfo.cipher_mode, + "S:hash-alg", src->encryption->encinfo.cipher_hash, + "S:ivgen-alg", src->encryption->encinfo.ivgen_name, + "S:ivgen-hash-alg", src->encryption->encinfo.ivgen_hash, + NULL) < 0) + return -1; + } + + VIR_STEAL_PTR(*luksProps, props); + return 0; +} + + +static int +qemuBlockStorageSourceCreateGetFormatPropsLUKS(virStorageSourcePtr src, + virJSONValuePtr *props) +{ + VIR_AUTOPTR(virJSONValue) luksprops = NULL; + + if (qemuBlockStorageSourceCreateGetEncryptionLUKS(src, &luksprops) < 0) + return -1; + + if (virJSONValueObjectAdd(luksprops, + "s:driver", "luks", + "s:file", src->nodestorage, + "u:size", src->capacity, + NULL) < 0) + return -1; + + VIR_STEAL_PTR(*props, luksprops); + return 0; +} + + +static int +qemuBlockStorageSourceCreateAddEncryptionQcow(virStorageSourcePtr src, + virJSONValuePtr props) +{ + VIR_AUTOPTR(virJSONValue) encryptProps = NULL; + + if (!src->encryption) + return 0; + + if (src->encryption->format != VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("creation of qcow/qcow2 files supports only 'luks' encryption")); + return -1; + } + + if (qemuBlockStorageSourceCreateGetEncryptionLUKS(src, &encryptProps) < 0) + return -1; + + if (virJSONValueObjectAdd(encryptProps, "s:format", "luks", NULL) < 0) + return -1; + + if (virJSONValueObjectAdd(props, "a:encrypt", &encryptProps, NULL) < 0) + return -1; + + return 0; +} + + +static int +qemuBlockStorageSourceCreateGetFormatPropsQcow2(virStorageSourcePtr src, + virStorageSourcePtr backing, + virJSONValuePtr *props) +{ + VIR_AUTOPTR(virJSONValue) qcow2props = NULL; + const char *qcow2version = NULL; + + if (STREQ_NULLABLE(src->compat, "0.10")) + qcow2version = "v2"; + else if (STREQ_NULLABLE(src->compat, "1.1")) + qcow2version = "v3"; + + if (virJSONValueObjectCreate(&qcow2props, + "s:driver", "qcow2", + "s:file", src->nodestorage, + "u:size", src->capacity, + "S:version", qcow2version, + NULL) < 0) + return -1; + + if (qemuBlockStorageSourceCreateAddBacking(backing, qcow2props, true) < 0 || + qemuBlockStorageSourceCreateAddEncryptionQcow(src, qcow2props) < 0) + return -1; + + VIR_STEAL_PTR(*props, qcow2props); + return 0; +} + + +static int +qemuBlockStorageSourceCreateGetFormatPropsQcow(virStorageSourcePtr src, + virStorageSourcePtr backing, + virJSONValuePtr *props) +{ + VIR_AUTOPTR(virJSONValue) qcowprops = NULL; + + if (virJSONValueObjectCreate(&qcowprops, + "s:driver", "qcow", + "s:file", src->nodestorage, + "u:size", src->capacity, + NULL) < 0) + return -1; + + if (qemuBlockStorageSourceCreateAddBacking(backing, qcowprops, false) < 0 || + qemuBlockStorageSourceCreateAddEncryptionQcow(src, qcowprops) < 0) + return -1; + + VIR_STEAL_PTR(*props, qcowprops); + return 0; +} + + +static int +qemuBlockStorageSourceCreateGetFormatPropsQed(virStorageSourcePtr src, + virStorageSourcePtr backing, + virJSONValuePtr *props) +{ + VIR_AUTOPTR(virJSONValue) qedprops = NULL; + + if (virJSONValueObjectCreate(&qedprops, + "s:driver", "qed", + "s:file", src->nodestorage, + "u:size", src->capacity, + NULL) < 0) + return -1; + + if (qemuBlockStorageSourceCreateAddBacking(backing, qedprops, true) < 0) + return -1; + + VIR_STEAL_PTR(*props, qedprops); + return 0; +} + + +/** + * qemuBlockStorageSourceCreateGetFormatProps: + * @src: storage source to format + * @backing: storage source describing backing image of @src (if necessary) + * @props: filled with props to be used with 'blockdev-create' to format @src + * + * @src must be properly initialized to contain node-names of the protocol layer + * which should be formatted. @props may be NULL with success returned in which + * case creation of given storage format is not supported. Note that creation + * of 'raw' storage is also returns NULL as there is nothing to do. + */ +int +qemuBlockStorageSourceCreateGetFormatProps(virStorageSourcePtr src, + virStorageSourcePtr backing, + virJSONValuePtr *props) +{ + switch ((virStorageFileFormat) src->format) { + case VIR_STORAGE_FILE_RAW: + if (!src->encryption || + src->encryption->format != VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) + return 0; + + return qemuBlockStorageSourceCreateGetFormatPropsLUKS(src, props); + + case VIR_STORAGE_FILE_QCOW2: + return qemuBlockStorageSourceCreateGetFormatPropsQcow2(src, backing, props); + + case VIR_STORAGE_FILE_QCOW: + return qemuBlockStorageSourceCreateGetFormatPropsQcow(src, backing, props); + + case VIR_STORAGE_FILE_QED: + return qemuBlockStorageSourceCreateGetFormatPropsQed(src, backing, props); + + case VIR_STORAGE_FILE_VPC: + return qemuBlockStorageSourceCreateGetFormatPropsGeneric(src, "vpc", + props, NULL); + + case VIR_STORAGE_FILE_PLOOP: + return qemuBlockStorageSourceCreateGetFormatPropsGeneric(src, "parallels", + props, NULL); + + case VIR_STORAGE_FILE_VDI: + return qemuBlockStorageSourceCreateGetFormatPropsGeneric(src, "vdi", + props, NULL); + + case VIR_STORAGE_FILE_VHD: + return qemuBlockStorageSourceCreateGetFormatPropsGeneric(src, "vhdx", + props, NULL); + + case VIR_STORAGE_FILE_VMDK: + return qemuBlockStorageSourceCreateGetFormatPropsGeneric(src, "vmdk", + props, backing); + + /* unsupported by qemu / impossible */ + case VIR_STORAGE_FILE_FAT: + case VIR_STORAGE_FILE_BOCHS: + case VIR_STORAGE_FILE_CLOOP: + case VIR_STORAGE_FILE_DMG: + case VIR_STORAGE_FILE_COW: + case VIR_STORAGE_FILE_ISO: + case VIR_STORAGE_FILE_DIR: + return 0; + + case VIR_STORAGE_FILE_AUTO_SAFE: + case VIR_STORAGE_FILE_AUTO: + case VIR_STORAGE_FILE_NONE: + virReportError(VIR_ERR_INTERNAL_ERROR, + _("mishandled storage format '%s'"), + virStorageFileFormatTypeToString(src->format)); + return -1; + + case VIR_STORAGE_FILE_LAST: + default: + break; + } + + virReportEnumRangeError(virStorageFileFormat, src->format); + return -1; +} diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index 12ddfad2ac..738ef9e8b0 100644 --- a/src/qemu/qemu_block.h +++ b/src/qemu/qemu_block.h @@ -162,3 +162,9 @@ qemuBlockSnapshotAddLegacy(virJSONValuePtr actions, virDomainDiskDefPtr disk, virStorageSourcePtr newsrc, bool reuse); + +int +qemuBlockStorageSourceCreateGetFormatProps(virStorageSourcePtr src, + virStorageSourcePtr backing, + virJSONValuePtr *props) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK; -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:30PM +0200, Peter Krempa wrote:
'blockdev-add' allows us to use qemu to format images to our desired format. This patch implements helpers which convert a virStorageSourcePtr into JSON objects describing the required configuration.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 321 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_block.h | 6 + 2 files changed, 327 insertions(+)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

QEMU allows us to create storage on certain network protocols which allow image creation through their API. Wire up the generator for using it with libvirt as well as for local files. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 88 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_block.h | 5 +++ 2 files changed, 93 insertions(+) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 54dd2b5328..709ed29375 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -2187,3 +2187,91 @@ qemuBlockStorageSourceCreateGetFormatProps(virStorageSourcePtr src, virReportEnumRangeError(virStorageFileFormat, src->format); return -1; } + + +/** + * qemuBlockStorageSourceCreateGetStorageProps: + * @src: storage source to create + * @props: filled with props to be used with 'blockdev-create' to create @src + * + * This function should be used only if @src->type is VIR_STORAGE_TYPE_NETWORK. + * Note that @props may be NULL if qemu does not support creation storage + * on given protocol. @src->physical is used as size for the storage. + */ +int +qemuBlockStorageSourceCreateGetStorageProps(virStorageSourcePtr src, + virJSONValuePtr *props) +{ + int actualType = virStorageSourceGetActualType(src); + VIR_AUTOPTR(virJSONValue) location = NULL; + const char *driver = NULL; + const char *filename = NULL; + + switch ((virStorageType) actualType) { + case VIR_STORAGE_TYPE_FILE: + driver = "file"; + filename = src->path; + break; + + case VIR_STORAGE_TYPE_NETWORK: + switch ((virStorageNetProtocol) src->protocol) { + case VIR_STORAGE_NET_PROTOCOL_GLUSTER: + driver = "gluster"; + if (!(location = qemuBlockStorageSourceGetGlusterProps(src, false, false))) + return -1; + break; + + case VIR_STORAGE_NET_PROTOCOL_RBD: + driver = "rbd"; + if (!(location = qemuBlockStorageSourceGetRBDProps(src, false))) + return -1; + break; + + case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG: + driver = "sheepdog"; + if (!(location = qemuBlockStorageSourceGetSheepdogProps(src))) + return -1; + break; + + case VIR_STORAGE_NET_PROTOCOL_SSH: + driver = "ssh"; + if (!(location = qemuBlockStorageSourceGetSshProps(src))) + return -1; + break; + + /* unsupported/impossible */ + case VIR_STORAGE_NET_PROTOCOL_NBD: + case VIR_STORAGE_NET_PROTOCOL_ISCSI: + case VIR_STORAGE_NET_PROTOCOL_VXHS: + case VIR_STORAGE_NET_PROTOCOL_HTTP: + case VIR_STORAGE_NET_PROTOCOL_HTTPS: + case VIR_STORAGE_NET_PROTOCOL_FTP: + case VIR_STORAGE_NET_PROTOCOL_FTPS: + case VIR_STORAGE_NET_PROTOCOL_TFTP: + case VIR_STORAGE_NET_PROTOCOL_NONE: + case VIR_STORAGE_NET_PROTOCOL_LAST: + return 0; + } + break; + + case VIR_STORAGE_TYPE_BLOCK: + case VIR_STORAGE_TYPE_DIR: + case VIR_STORAGE_TYPE_VOLUME: + return 0; + + case VIR_STORAGE_TYPE_NONE: + case VIR_STORAGE_TYPE_LAST: + virReportEnumRangeError(virStorageType, actualType); + return -1; + } + + if (virJSONValueObjectCreate(props, + "s:driver", driver, + "S:filename", filename, + "A:location", &location, + "u:size", src->physical, + NULL) < 0) + return -1; + + return 0; +} diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index 738ef9e8b0..a5f6a3c75b 100644 --- a/src/qemu/qemu_block.h +++ b/src/qemu/qemu_block.h @@ -168,3 +168,8 @@ qemuBlockStorageSourceCreateGetFormatProps(virStorageSourcePtr src, virStorageSourcePtr backing, virJSONValuePtr *props) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_RETURN_CHECK; + +int +qemuBlockStorageSourceCreateGetStorageProps(virStorageSourcePtr src, + virJSONValuePtr *props) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:31PM +0200, Peter Krempa wrote:
QEMU allows us to create storage on certain network protocols which allow image creation through their API. Wire up the generator for using it with libvirt as well as for local files.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_block.c | 88 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_block.h | 5 +++ 2 files changed, 93 insertions(+)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.c | 9 +-------- src/qemu/qemu_domain.h | 5 +++++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 6225ac23e2..79f18a6a7c 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -135,13 +135,6 @@ static void qemuDomainLogContextDispose(void *obj); static void qemuDomainSaveCookieDispose(void *obj); -static int -qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk, - virStorageSourcePtr src, - qemuDomainObjPrivatePtr priv, - virQEMUDriverConfigPtr cfg); - - static int qemuDomainOnceInit(void) { @@ -14146,7 +14139,7 @@ qemuDomainPrepareDiskSourceLegacy(virDomainDiskDefPtr disk, } -static int +int qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk, virStorageSourcePtr src, qemuDomainObjPrivatePtr priv, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 3eea8b0f96..c684b4cad9 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -810,6 +810,11 @@ int qemuDomainStorageSourceAccessAllow(virQEMUDriverPtr driver, bool readonly, bool newSource); +int qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk, + virStorageSourcePtr src, + qemuDomainObjPrivatePtr priv, + virQEMUDriverConfigPtr cfg); + int qemuDomainCleanupAdd(virDomainObjPtr vm, qemuDomainCleanupCallback cb); void qemuDomainCleanupRemove(virDomainObjPtr vm, -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:32PM +0200, Peter Krempa wrote:
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_domain.c | 9 +-------- src/qemu/qemu_domain.h | 5 +++++ 2 files changed, 6 insertions(+), 8 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Allow using it from the tests. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/snapshot_conf.c | 2 +- src/conf/snapshot_conf.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index c7f29360e7..247d3f71b0 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -121,7 +121,7 @@ virDomainSnapshotDefDispose(void *obj) virObjectUnref(def->cookie); } -static int +int virDomainSnapshotDiskDefParseXML(xmlNodePtr node, xmlXPathContextPtr ctxt, virDomainSnapshotDiskDefPtr def, diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h index 08b2a3b955..f4be434afc 100644 --- a/src/conf/snapshot_conf.h +++ b/src/conf/snapshot_conf.h @@ -123,6 +123,11 @@ int virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr snapshot, int default_snapshot, bool require_match); +int virDomainSnapshotDiskDefParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt, + virDomainSnapshotDiskDefPtr def, + unsigned int flags, + virDomainXMLOptionPtr xmlopt); bool virDomainSnapshotDefIsExternal(virDomainSnapshotDefPtr def); bool virDomainSnapshotIsExternal(virDomainMomentObjPtr snap); -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:33PM +0200, Peter Krempa wrote:
Allow using it from the tests.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/snapshot_conf.c | 2 +- src/conf/snapshot_conf.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-)
Consider creating a new include file snapshot_conf_priv.h for usage in tests. Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Tests will need to parse such a definition so it also needs to be freed. Provide a function for it. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/snapshot_conf.c | 11 +++++++++++ src/conf/snapshot_conf.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c index 247d3f71b0..f3385d930b 100644 --- a/src/conf/snapshot_conf.c +++ b/src/conf/snapshot_conf.c @@ -95,6 +95,17 @@ virDomainSnapshotDiskDefClear(virDomainSnapshotDiskDefPtr disk) disk->src = NULL; } +void +virDomainSnapshotDiskDefFree(virDomainSnapshotDiskDefPtr disk) +{ + if (!disk) + return; + + virDomainSnapshotDiskDefClear(disk); + VIR_FREE(disk); +} + + /* Allocate a new virDomainSnapshotDef; free with virObjectUnref() */ virDomainSnapshotDefPtr virDomainSnapshotDefNew(void) diff --git a/src/conf/snapshot_conf.h b/src/conf/snapshot_conf.h index f4be434afc..445899dd07 100644 --- a/src/conf/snapshot_conf.h +++ b/src/conf/snapshot_conf.h @@ -114,6 +114,7 @@ virDomainSnapshotDefPtr virDomainSnapshotDefParseNode(xmlDocPtr xml, bool *current, unsigned int flags); virDomainSnapshotDefPtr virDomainSnapshotDefNew(void); +void virDomainSnapshotDiskDefFree(virDomainSnapshotDiskDefPtr disk); char *virDomainSnapshotDefFormat(const char *uuidstr, virDomainSnapshotDefPtr def, virCapsPtr caps, -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:34PM +0200, Peter Krempa wrote:
Tests will need to parse such a definition so it also needs to be freed. Provide a function for it.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/conf/snapshot_conf.c | 11 +++++++++++ src/conf/snapshot_conf.h | 1 + 2 files changed, 12 insertions(+)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano

Test the output against the schema and also against what we expect. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemublocktest.c | 170 ++++++++++++++++++ .../imagecreate/luks-encopts.json | 19 ++ .../imagecreate/luks-encopts.xml | 16 ++ .../imagecreate/luks-noopts.json | 14 ++ .../imagecreate/luks-noopts.xml | 14 ++ .../imagecreate/network-gluster-qcow2.json | 28 +++ .../imagecreate/network-gluster-qcow2.xml | 13 ++ .../imagecreate/network-rbd-qcow2.json | 26 +++ .../imagecreate/network-rbd-qcow2.xml | 13 ++ .../imagecreate/network-sheepdog-qcow2.json | 20 +++ .../imagecreate/network-sheepdog-qcow2.xml | 12 ++ .../imagecreate/network-ssh-qcow2.json | 19 ++ .../imagecreate/network-ssh-qcow2.xml | 12 ++ .../imagecreate/qcow2-backing-luks.json | 15 ++ .../imagecreate/qcow2-backing-luks.xml | 1 + .../imagecreate/qcow2-backing-raw-nbd.json | 15 ++ .../imagecreate/qcow2-backing-raw-nbd.xml | 1 + .../imagecreate/qcow2-backing-raw.json | 15 ++ .../imagecreate/qcow2-backing-raw.xml | 1 + .../qcow2-luks-encopts-backing.json | 24 +++ .../qcow2-luks-encopts-backing.xml | 1 + .../imagecreate/qcow2-luks-encopts.json | 22 +++ .../imagecreate/qcow2-luks-encopts.xml | 16 ++ .../imagecreate/qcow2-luks-noopts.json | 17 ++ .../imagecreate/qcow2-luks-noopts.xml | 14 ++ .../qemublocktestdata/imagecreate/qcow2.json | 13 ++ tests/qemublocktestdata/imagecreate/qcow2.xml | 11 ++ .../imagecreate/raw-nbd.json | 4 + .../qemublocktestdata/imagecreate/raw-nbd.xml | 12 ++ tests/qemublocktestdata/imagecreate/raw.json | 9 + tests/qemublocktestdata/imagecreate/raw.xml | 11 ++ 31 files changed, 578 insertions(+) create mode 100644 tests/qemublocktestdata/imagecreate/luks-encopts.json create mode 100644 tests/qemublocktestdata/imagecreate/luks-encopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/luks-noopts.json create mode 100644 tests/qemublocktestdata/imagecreate/luks-noopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-gluster-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-gluster-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-rbd-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-rbd-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-ssh-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-ssh-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-luks.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-luks.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-raw.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-raw.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/raw-nbd.json create mode 100644 tests/qemublocktestdata/imagecreate/raw-nbd.xml create mode 100644 tests/qemublocktestdata/imagecreate/raw.json create mode 100644 tests/qemublocktestdata/imagecreate/raw.xml diff --git a/tests/qemublocktest.c b/tests/qemublocktest.c index 5c381d1e3b..cd5047a545 100644 --- a/tests/qemublocktest.c +++ b/tests/qemublocktest.c @@ -342,6 +342,138 @@ testQemuDiskXMLToPropsValidateFile(const void *opaque) } +struct testQemuImageCreateData { + const char *name; + const char *backingname; + virHashTablePtr schema; + virJSONValuePtr schemaroot; + virQEMUDriverPtr driver; + virQEMUCapsPtr qemuCaps; +}; + +static const char *testQemuImageCreatePath = abs_srcdir "/qemublocktestdata/imagecreate/"; + +static virStorageSourcePtr +testQemuImageCreateLoadDiskXML(const char *name, + virDomainXMLOptionPtr xmlopt) + +{ + virDomainSnapshotDiskDefPtr diskdef = NULL; + VIR_AUTOPTR(xmlDoc) doc = NULL; + VIR_AUTOPTR(xmlXPathContext) ctxt = NULL; + xmlNodePtr node; + VIR_AUTOFREE(char *) xmlpath = NULL; + virStorageSourcePtr ret = NULL; + + if (virAsprintf(&xmlpath, "%s%s.xml", + testQemuImageCreatePath, name) < 0) + return NULL; + + if (!(doc = virXMLParseFileCtxt(xmlpath, &ctxt))) + return NULL; + + if (!(node = virXPathNode("//disk", ctxt))) { + VIR_TEST_VERBOSE("failed to find <source> element\n"); + return NULL; + } + + if (VIR_ALLOC(diskdef) < 0) + return NULL; + + if (virDomainSnapshotDiskDefParseXML(node, ctxt, diskdef, + VIR_DOMAIN_DEF_PARSE_STATUS, + xmlopt) == 0) + VIR_STEAL_PTR(ret, diskdef->src); + + virDomainSnapshotDiskDefFree(diskdef); + return ret; +} + + +static int +testQemuImageCreate(const void *opaque) +{ + struct testQemuImageCreateData *data = (void *) opaque; + VIR_AUTOPTR(virJSONValue) protocolprops = NULL; + VIR_AUTOPTR(virJSONValue) formatprops = NULL; + VIR_AUTOUNREF(virStorageSourcePtr) src = NULL; + VIR_AUTOCLEAN(virBuffer) debug = VIR_BUFFER_INITIALIZER; + VIR_AUTOCLEAN(virBuffer) actualbuf = VIR_BUFFER_INITIALIZER; + VIR_AUTOFREE(char *) jsonprotocol = NULL; + VIR_AUTOFREE(char *) jsonformat = NULL; + VIR_AUTOFREE(char *) actual = NULL; + VIR_AUTOFREE(char *) jsonpath = NULL; + + if (!(src = testQemuImageCreateLoadDiskXML(data->name, data->driver->xmlopt))) + return -1; + + if (data->backingname && + !(src->backingStore = testQemuImageCreateLoadDiskXML(data->backingname, + data->driver->xmlopt))) + return -1; + + if (testQemuDiskXMLToJSONFakeSecrets(src) < 0) + return -1; + + /* fake some sizes */ + src->capacity = 1337; + src->physical = 42; + + if (qemuDomainValidateStorageSource(src, data->qemuCaps) < 0) + return -1; + + if (qemuBlockStorageSourceCreateGetStorageProps(src, &protocolprops) < 0) + return -1; + + if (qemuBlockStorageSourceCreateGetFormatProps(src, src->backingStore, &formatprops) < 0) + return -1; + + if (formatprops) { + if (!(jsonformat = virJSONValueToString(formatprops, true))) + return -1; + + if (testQEMUSchemaValidate(formatprops, data->schemaroot, data->schema, + &debug) < 0) { + VIR_AUTOFREE(char *) debugmsg = virBufferContentAndReset(&debug); + VIR_TEST_VERBOSE("blockdev-create format json does not conform to QAPI schema"); + VIR_TEST_DEBUG("json:\n%s\ndoes not match schema. Debug output:\n %s", + jsonformat, NULLSTR(debugmsg)); + return -1; + } + virBufferFreeAndReset(&debug); + } + + if (protocolprops) { + if (!(jsonprotocol = virJSONValueToString(protocolprops, true))) + return -1; + + if (testQEMUSchemaValidate(protocolprops, data->schemaroot, data->schema, + &debug) < 0) { + VIR_AUTOFREE(char *) debugmsg = virBufferContentAndReset(&debug); + VIR_TEST_VERBOSE("blockdev-create protocol json does not conform to QAPI schema"); + VIR_TEST_DEBUG("json:\n%s\ndoes not match schema. Debug output:\n %s", + jsonprotocol, NULLSTR(debugmsg)); + return -1; + } + virBufferFreeAndReset(&debug); + } + + virBufferStrcat(&actualbuf, "protocol:\n", NULLSTR(jsonprotocol), + "\nformat:\n", NULLSTR(jsonformat), NULL); + virBufferTrim(&actualbuf, "\n", -1); + virBufferAddLit(&actualbuf, "\n"); + + if (virAsprintf(&jsonpath, "%s%s.json", + testQemuImageCreatePath, data->name) < 0) + return -1; + + if (!(actual = virBufferContentAndReset(&actualbuf))) + return -1; + + return virTestCompareToFile(actual, jsonpath); +} + + static int testQemuDiskXMLToPropsValidateFileSrcOnly(const void *opaque) { @@ -383,6 +515,7 @@ mymain(void) virQEMUDriver driver; struct testBackingXMLjsonXMLdata xmljsonxmldata; struct testQemuDiskXMLToJSONData diskxmljsondata; + struct testQemuImageCreateData imagecreatedata; char *capslatest_x86_64 = NULL; virQEMUCapsPtr caps_x86_64 = NULL; @@ -390,6 +523,7 @@ mymain(void) return EXIT_FAILURE; diskxmljsondata.driver = &driver; + imagecreatedata.driver = &driver; if (!(capslatest_x86_64 = testQemuGetLatestCapsForArch("x86_64", "xml"))) return EXIT_FAILURE; @@ -401,6 +535,7 @@ mymain(void) return EXIT_FAILURE; diskxmljsondata.qemuCaps = caps_x86_64; + imagecreatedata.qemuCaps = caps_x86_64; virTestCounterReset("qemu storage source xml->json->xml "); @@ -548,6 +683,41 @@ mymain(void) TEST_DISK_TO_JSON("block-raw-noopts"); TEST_DISK_TO_JSON("block-raw-reservations"); +# define TEST_IMAGE_CREATE(testname, testbacking) \ + do { \ + imagecreatedata.name = testname; \ + imagecreatedata.backingname = testbacking; \ + if (virTestRun("image create xml to props " testname, testQemuImageCreate, \ + &imagecreatedata) < 0) \ + ret = -1; \ + } while (0) + imagecreatedata.schema = diskxmljsondata.schema; + if (virQEMUQAPISchemaPathGet("blockdev-create/arg-type/options", + imagecreatedata.schema, + &imagecreatedata.schemaroot) < 0 || + !imagecreatedata.schemaroot) { + VIR_TEST_VERBOSE("failed to find schema entry for blockdev-create\n"); + ret = -1; + goto cleanup; + } + + TEST_IMAGE_CREATE("raw", NULL); + TEST_IMAGE_CREATE("raw-nbd", NULL); + TEST_IMAGE_CREATE("luks-noopts", NULL); + TEST_IMAGE_CREATE("luks-encopts", NULL); + TEST_IMAGE_CREATE("qcow2", NULL); + TEST_IMAGE_CREATE("qcow2-luks-noopts", NULL); + TEST_IMAGE_CREATE("qcow2-luks-encopts", NULL); + TEST_IMAGE_CREATE("qcow2-backing-raw", "raw"); + TEST_IMAGE_CREATE("qcow2-backing-raw-nbd", "raw-nbd"); + TEST_IMAGE_CREATE("qcow2-backing-luks", "luks-noopts"); + TEST_IMAGE_CREATE("qcow2-luks-encopts-backing", "qcow2"); + + TEST_IMAGE_CREATE("network-gluster-qcow2", NULL); + TEST_IMAGE_CREATE("network-rbd-qcow2", NULL); + TEST_IMAGE_CREATE("network-ssh-qcow2", NULL); + TEST_IMAGE_CREATE("network-sheepdog-qcow2", NULL); + cleanup: virHashFree(diskxmljsondata.schema); qemuTestDriverFree(&driver); diff --git a/tests/qemublocktestdata/imagecreate/luks-encopts.json b/tests/qemublocktestdata/imagecreate/luks-encopts.json new file mode 100644 index 0000000000..f065ad89a7 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/luks-encopts.json @@ -0,0 +1,19 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.img", + "size": 42 +} + +format: +{ + "key-secret": "0123456789ABCDEF0123456789ABCDE-encalias", + "cipher-alg": "serpent-256", + "cipher-mode": "cbc", + "hash-alg": "sha256", + "ivgen-alg": "plain64", + "ivgen-hash-alg": "sha256", + "driver": "luks", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337 +} diff --git a/tests/qemublocktestdata/imagecreate/luks-encopts.xml b/tests/qemublocktestdata/imagecreate/luks-encopts.xml new file mode 100644 index 0000000000..bb0ee54adc --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/luks-encopts.xml @@ -0,0 +1,16 @@ +<disk device='disk' name='vda'> + <driver type='raw'/> + <source file='/var/lib/libvirt/images/i.img'> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + <encryption format='luks'> + <secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/> + <cipher name='serpent' size='256' mode='cbc' hash='sha256'/> + <ivgen name='plain64' hash='sha256'/> + </encryption> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/luks-noopts.json b/tests/qemublocktestdata/imagecreate/luks-noopts.json new file mode 100644 index 0000000000..1ea1948119 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/luks-noopts.json @@ -0,0 +1,14 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.img", + "size": 42 +} + +format: +{ + "key-secret": "0123456789ABCDEF0123456789ABCDE-encalias", + "driver": "luks", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337 +} diff --git a/tests/qemublocktestdata/imagecreate/luks-noopts.xml b/tests/qemublocktestdata/imagecreate/luks-noopts.xml new file mode 100644 index 0000000000..ac224b02de --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/luks-noopts.xml @@ -0,0 +1,14 @@ +<disk device='disk' name='vda'> + <driver type='raw'/> + <source file='/var/lib/libvirt/images/i.img'> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + <encryption format='luks'> + <secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/> + </encryption> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/network-gluster-qcow2.json b/tests/qemublocktestdata/imagecreate/network-gluster-qcow2.json new file mode 100644 index 0000000000..aee7bfd401 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/network-gluster-qcow2.json @@ -0,0 +1,28 @@ +protocol: +{ + "driver": "gluster", + "location": { + "volume": "asdf", + "path": "i.qcow2", + "server": [ + { + "type": "inet", + "host": "example.com", + "port": "1234" + }, + { + "type": "inet", + "host": "alternate.example.com", + "port": "3214" + } + ] + }, + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337 +} diff --git a/tests/qemublocktestdata/imagecreate/network-gluster-qcow2.xml b/tests/qemublocktestdata/imagecreate/network-gluster-qcow2.xml new file mode 100644 index 0000000000..f3dbf24180 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/network-gluster-qcow2.xml @@ -0,0 +1,13 @@ +<disk device='disk' name='vda' type='network'> + <driver type='qcow2'/> + <source protocol='gluster' name='asdf/i.qcow2'> + <host name='example.com' port='1234'/> + <host name='alternate.example.com' port='3214'/> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/network-rbd-qcow2.json b/tests/qemublocktestdata/imagecreate/network-rbd-qcow2.json new file mode 100644 index 0000000000..56d9c0f1ed --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/network-rbd-qcow2.json @@ -0,0 +1,26 @@ +protocol: +{ + "driver": "rbd", + "location": { + "pool": "asdf", + "image": "i.qcow2", + "server": [ + { + "host": "example.com", + "port": "1234" + }, + { + "host": "alternate.example.com", + "port": "4321" + } + ] + }, + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337 +} diff --git a/tests/qemublocktestdata/imagecreate/network-rbd-qcow2.xml b/tests/qemublocktestdata/imagecreate/network-rbd-qcow2.xml new file mode 100644 index 0000000000..0f6c1ddb98 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/network-rbd-qcow2.xml @@ -0,0 +1,13 @@ +<disk device='disk' name='vda' type='network'> + <driver type='qcow2'/> + <source protocol='rbd' name='asdf/i.qcow2'> + <host name='example.com' port='1234'/> + <host name='alternate.example.com' port='4321'/> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.json b/tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.json new file mode 100644 index 0000000000..b7272625a2 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.json @@ -0,0 +1,20 @@ +protocol: +{ + "driver": "sheepdog", + "location": { + "server": { + "type": "inet", + "host": "example.com", + "port": "1234" + }, + "vdi": "asdf/i.qcow2" + }, + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337 +} diff --git a/tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.xml b/tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.xml new file mode 100644 index 0000000000..1145daafdd --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.xml @@ -0,0 +1,12 @@ +<disk device='disk' name='vda' type='network'> + <driver type='qcow2'/> + <source protocol='sheepdog' name='asdf/i.qcow2'> + <host name='example.com' port='1234'/> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/network-ssh-qcow2.json b/tests/qemublocktestdata/imagecreate/network-ssh-qcow2.json new file mode 100644 index 0000000000..31416ed4fc --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/network-ssh-qcow2.json @@ -0,0 +1,19 @@ +protocol: +{ + "driver": "ssh", + "location": { + "path": "asdf/i.qcow2", + "server": { + "host": "example.com", + "port": "1234" + } + }, + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337 +} diff --git a/tests/qemublocktestdata/imagecreate/network-ssh-qcow2.xml b/tests/qemublocktestdata/imagecreate/network-ssh-qcow2.xml new file mode 100644 index 0000000000..4c44f81c81 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/network-ssh-qcow2.xml @@ -0,0 +1,12 @@ +<disk device='disk' name='vda' type='network'> + <driver type='qcow2'/> + <source protocol='ssh' name='asdf/i.qcow2'> + <host name='example.com' port='1234'/> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/qcow2-backing-luks.json b/tests/qemublocktestdata/imagecreate/qcow2-backing-luks.json new file mode 100644 index 0000000000..63ba35dc79 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-backing-luks.json @@ -0,0 +1,15 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.qcow2", + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337, + "backing-file": "/var/lib/libvirt/images/i.img", + "backing-fmt": "luks" +} diff --git a/tests/qemublocktestdata/imagecreate/qcow2-backing-luks.xml b/tests/qemublocktestdata/imagecreate/qcow2-backing-luks.xml new file mode 120000 index 0000000000..5769c2c866 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-backing-luks.xml @@ -0,0 +1 @@ +qcow2.xml \ No newline at end of file diff --git a/tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.json b/tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.json new file mode 100644 index 0000000000..34ce74a548 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.json @@ -0,0 +1,15 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.qcow2", + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337, + "backing-file": "json:{\"driver\":\"nbd\",\"server\":{\"type\":\"inet\",\"host\":\"example.com\",\"port\":\"1234\"}}", + "backing-fmt": "raw" +} diff --git a/tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.xml b/tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.xml new file mode 120000 index 0000000000..5769c2c866 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.xml @@ -0,0 +1 @@ +qcow2.xml \ No newline at end of file diff --git a/tests/qemublocktestdata/imagecreate/qcow2-backing-raw.json b/tests/qemublocktestdata/imagecreate/qcow2-backing-raw.json new file mode 100644 index 0000000000..8176c8dadd --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-backing-raw.json @@ -0,0 +1,15 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.qcow2", + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337, + "backing-file": "/var/lib/libvirt/images/i.img", + "backing-fmt": "raw" +} diff --git a/tests/qemublocktestdata/imagecreate/qcow2-backing-raw.xml b/tests/qemublocktestdata/imagecreate/qcow2-backing-raw.xml new file mode 120000 index 0000000000..5769c2c866 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-backing-raw.xml @@ -0,0 +1 @@ +qcow2.xml \ No newline at end of file diff --git a/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.json b/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.json new file mode 100644 index 0000000000..a57617dfac --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.json @@ -0,0 +1,24 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.qcow2", + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337, + "backing-file": "/var/lib/libvirt/images/i.qcow2", + "backing-fmt": "qcow2", + "encrypt": { + "key-secret": "0123456789ABCDEF0123456789ABCDE-encalias", + "cipher-alg": "serpent-256", + "cipher-mode": "cbc", + "hash-alg": "sha256", + "ivgen-alg": "plain64", + "ivgen-hash-alg": "sha256", + "format": "luks" + } +} diff --git a/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.xml b/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.xml new file mode 120000 index 0000000000..6ea018cec2 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.xml @@ -0,0 +1 @@ +qcow2-luks-encopts.xml \ No newline at end of file diff --git a/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.json b/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.json new file mode 100644 index 0000000000..8796726fcb --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.json @@ -0,0 +1,22 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.qcow2", + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337, + "encrypt": { + "key-secret": "0123456789ABCDEF0123456789ABCDE-encalias", + "cipher-alg": "serpent-256", + "cipher-mode": "cbc", + "hash-alg": "sha256", + "ivgen-alg": "plain64", + "ivgen-hash-alg": "sha256", + "format": "luks" + } +} diff --git a/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.xml b/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.xml new file mode 100644 index 0000000000..d6616bd164 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.xml @@ -0,0 +1,16 @@ +<disk device='disk' name='vda'> + <driver type='qcow2'/> + <source file='/var/lib/libvirt/images/i.qcow2'> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + <encryption format='luks'> + <secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/> + <cipher name='serpent' size='256' mode='cbc' hash='sha256'/> + <ivgen name='plain64' hash='sha256'/> + </encryption> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.json b/tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.json new file mode 100644 index 0000000000..f9caaee6bb --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.json @@ -0,0 +1,17 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.qcow2", + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337, + "encrypt": { + "key-secret": "0123456789ABCDEF0123456789ABCDE-encalias", + "format": "luks" + } +} diff --git a/tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.xml b/tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.xml new file mode 100644 index 0000000000..e2d1c42424 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.xml @@ -0,0 +1,14 @@ +<disk device='disk' name='vda'> + <driver type='qcow2'/> + <source file='/var/lib/libvirt/images/i.qcow2'> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + <encryption format='luks'> + <secret type='passphrase' uuid='f52a81b2-424e-490c-823d-6bd4235bc572'/> + </encryption> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/qcow2.json b/tests/qemublocktestdata/imagecreate/qcow2.json new file mode 100644 index 0000000000..7142cf67b6 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2.json @@ -0,0 +1,13 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.qcow2", + "size": 42 +} + +format: +{ + "driver": "qcow2", + "file": "0123456789ABCDEF0123456789ABCDE", + "size": 1337 +} diff --git a/tests/qemublocktestdata/imagecreate/qcow2.xml b/tests/qemublocktestdata/imagecreate/qcow2.xml new file mode 100644 index 0000000000..f3c235f82f --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/qcow2.xml @@ -0,0 +1,11 @@ +<disk device='disk' name='vda'> + <driver type='qcow2'/> + <source file='/var/lib/libvirt/images/i.qcow2'> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/raw-nbd.json b/tests/qemublocktestdata/imagecreate/raw-nbd.json new file mode 100644 index 0000000000..d1e089e3e3 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/raw-nbd.json @@ -0,0 +1,4 @@ +protocol: +<null> +format: +<null> diff --git a/tests/qemublocktestdata/imagecreate/raw-nbd.xml b/tests/qemublocktestdata/imagecreate/raw-nbd.xml new file mode 100644 index 0000000000..256bf23797 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/raw-nbd.xml @@ -0,0 +1,12 @@ +<disk device='disk' name='vda' type='network'> + <driver type='raw'/> + <source protocol='nbd'> + <host name='example.com' port='1234'/> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + </source> +</disk> diff --git a/tests/qemublocktestdata/imagecreate/raw.json b/tests/qemublocktestdata/imagecreate/raw.json new file mode 100644 index 0000000000..06abb25ab9 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/raw.json @@ -0,0 +1,9 @@ +protocol: +{ + "driver": "file", + "filename": "/var/lib/libvirt/images/i.img", + "size": 42 +} + +format: +<null> diff --git a/tests/qemublocktestdata/imagecreate/raw.xml b/tests/qemublocktestdata/imagecreate/raw.xml new file mode 100644 index 0000000000..3a91600bd8 --- /dev/null +++ b/tests/qemublocktestdata/imagecreate/raw.xml @@ -0,0 +1,11 @@ +<disk device='disk' name='vda'> + <driver type='raw'/> + <source file='/var/lib/libvirt/images/i.img'> + <privateData> + <nodenames> + <nodename type='storage' name='0123456789ABCDEF0123456789ABCDE'/> + <nodename type='format' name='0123456789ABCDEF0123456789ABCDE'/> + </nodenames> + </privateData> + </source> +</disk> -- 2.21.0

On Thu, Jul 04, 2019 at 04:26:35PM +0200, Peter Krempa wrote:
Test the output against the schema and also against what we expect.
Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- tests/qemublocktest.c | 170 ++++++++++++++++++ .../imagecreate/luks-encopts.json | 19 ++ .../imagecreate/luks-encopts.xml | 16 ++ .../imagecreate/luks-noopts.json | 14 ++ .../imagecreate/luks-noopts.xml | 14 ++ .../imagecreate/network-gluster-qcow2.json | 28 +++ .../imagecreate/network-gluster-qcow2.xml | 13 ++ .../imagecreate/network-rbd-qcow2.json | 26 +++ .../imagecreate/network-rbd-qcow2.xml | 13 ++ .../imagecreate/network-sheepdog-qcow2.json | 20 +++ .../imagecreate/network-sheepdog-qcow2.xml | 12 ++ .../imagecreate/network-ssh-qcow2.json | 19 ++ .../imagecreate/network-ssh-qcow2.xml | 12 ++ .../imagecreate/qcow2-backing-luks.json | 15 ++ .../imagecreate/qcow2-backing-luks.xml | 1 + .../imagecreate/qcow2-backing-raw-nbd.json | 15 ++ .../imagecreate/qcow2-backing-raw-nbd.xml | 1 + .../imagecreate/qcow2-backing-raw.json | 15 ++ .../imagecreate/qcow2-backing-raw.xml | 1 + .../qcow2-luks-encopts-backing.json | 24 +++ .../qcow2-luks-encopts-backing.xml | 1 + .../imagecreate/qcow2-luks-encopts.json | 22 +++ .../imagecreate/qcow2-luks-encopts.xml | 16 ++ .../imagecreate/qcow2-luks-noopts.json | 17 ++ .../imagecreate/qcow2-luks-noopts.xml | 14 ++ .../qemublocktestdata/imagecreate/qcow2.json | 13 ++ tests/qemublocktestdata/imagecreate/qcow2.xml | 11 ++ .../imagecreate/raw-nbd.json | 4 + .../qemublocktestdata/imagecreate/raw-nbd.xml | 12 ++ tests/qemublocktestdata/imagecreate/raw.json | 9 + tests/qemublocktestdata/imagecreate/raw.xml | 11 ++ 31 files changed, 578 insertions(+) create mode 100644 tests/qemublocktestdata/imagecreate/luks-encopts.json create mode 100644 tests/qemublocktestdata/imagecreate/luks-encopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/luks-noopts.json create mode 100644 tests/qemublocktestdata/imagecreate/luks-noopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-gluster-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-gluster-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-rbd-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-rbd-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-sheepdog-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/network-ssh-qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/network-ssh-qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-luks.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-luks.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-raw-nbd.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-backing-raw.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-backing-raw.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.json create mode 120000 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts-backing.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-encopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2-luks-noopts.xml create mode 100644 tests/qemublocktestdata/imagecreate/qcow2.json create mode 100644 tests/qemublocktestdata/imagecreate/qcow2.xml create mode 100644 tests/qemublocktestdata/imagecreate/raw-nbd.json create mode 100644 tests/qemublocktestdata/imagecreate/raw-nbd.xml create mode 100644 tests/qemublocktestdata/imagecreate/raw.json create mode 100644 tests/qemublocktestdata/imagecreate/raw.xml
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
participants (2)
-
Ján Tomko
-
Peter Krempa