On qemu-5.2.0-4.fc34.x86_64, libvirt v6.10.0-262-gbed50bcbbb with this patch series, by following script: #!/bin/bash - set -o nounset # Treat unset variables as an error VM=test NFS_EXPORT=/tmp/nfs IMG=disk1 DISK_XML=/tmp/nfs.xml mkdir -p $NFS_EXPORT echo "$NFS_EXPORT *(rw,no_root_squash,insecure)" > /etc/exports
systemctl restart nfs-server qemu-img create nfs://localhost"$NFS_EXPORT/$IMG" 100M chmod 777 $NFS_EXPORT -R virsh start $VM --console echo "<disk type='network' device='disk'> <driver name='qemu' type='raw' cache='none'/> <source protocol='nfs' name='$NFS_EXPORT/$IMG'> <host name='localhost'/> <nfs user='+107' group='+107'/> </source> <target dev='vdb' bus='virtio'/> </disk>" > $DISK_XML virsh attach-device $VM $DISK_XML virsh console $VM virsh detach-device $VM $DISK_XML virsh console $VM virsh destroy $VM virsh attach-device $VM $DISK_XML --config virsh start $VM --console virsh destroy $VM virsh detach-device $VM $DISK_XML --config It works for me. All attach/detach tests have passed. On Wed, Dec 30, 2020 at 5:23 AM Ryan Gahagan <rgaha...@cs.utexas.edu> wrote: > Signed-off-by: Ryan Gahagan <rgaha...@cs.utexas.edu> > --- > src/qemu/qemu_block.c | 79 +++++++++++++++++++++++++++++++++++++++++- > src/qemu/qemu_domain.c | 47 +++++++++++++++++++++++++ > 2 files changed, 125 insertions(+), 1 deletion(-) > > diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c > index b224a550f3..5413a4f0e8 100644 > --- a/src/qemu/qemu_block.c > +++ b/src/qemu/qemu_block.c > @@ -574,6 +574,35 @@ > qemuBlockStorageSourceBuildJSONInetSocketAddress(virStorageNetHostDefPtr > host) > } > > > +/** > + * qemuBlockStorageSourceBuildJSONNFSServer(virStorageNetHostDefPtr host) > + * @host: the virStorageNetHostDefPtr definition to build > + * > + * Formats @hosts into a json object conforming to the 'NFSServer' type > + * in qemu. > + * > + * Returns a virJSONValuePtr for a single server. > + */ > +static virJSONValuePtr > +qemuBlockStorageSourceBuildJSONNFSServer(virStorageNetHostDefPtr host) > +{ > + virJSONValuePtr ret = NULL; > + > + if (host->transport != VIR_STORAGE_NET_HOST_TRANS_TCP) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("only TCP protocol can be converted to > NFSServer")); > + return NULL; > + } > + > + ignore_value(virJSONValueObjectCreate(&ret, > + "s:host", host->name, > + "s:type", "inet", > + NULL)); > + > + return ret; > +} > + > + > /** > * qemuBlockStorageSourceBuildHostsJSONInetSocketAddress: > * @src: disk storage source > @@ -674,6 +703,44 @@ > qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src, > } > > > +static virJSONValuePtr > +qemuBlockStorageSourceGetNFSProps(virStorageSourcePtr src) > +{ > + g_autoptr(virJSONValue) server = NULL; > + virJSONValuePtr ret = NULL; > + > + if (src->nhosts != 1) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("NFS protocol accepts only one host")); > + return NULL; > + } > + > + if (!(server = > qemuBlockStorageSourceBuildJSONNFSServer(&src->hosts[0]))) > + return NULL; > + > + /* NFS disk specification example: > + * { driver:"nfs", > + * user: "0", > + * group: "0", > + * path: "/foo/bar/baz", > + * server: {type:"tcp", host:"1.2.3.4"}} > + */ > + ignore_value(virJSONValueObjectCreate(&ret, > + "a:server", &server, > + "S:path", src->path, NULL)); > + > + if (src->nfs_uid != -1 && > + virJSONValueObjectAdd(ret, "i:user", src->nfs_uid, NULL) < 0) > + return NULL; > + > + if (src->nfs_gid != -1 && > + virJSONValueObjectAdd(ret, "i:group", src->nfs_gid, NULL) < 0) > + return NULL; > + > + return ret; > +} > + > + > static virJSONValuePtr > qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src, > bool onlytarget) > @@ -1181,6 +1248,11 @@ > qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src, > break; > > case VIR_STORAGE_NET_PROTOCOL_NFS: > + driver = "nfs"; > + if (!(fileprops = qemuBlockStorageSourceGetNFSProps(src))) > + return NULL; > + break; > + > case VIR_STORAGE_NET_PROTOCOL_NONE: > case VIR_STORAGE_NET_PROTOCOL_LAST: > virReportEnumRangeError(virStorageNetProtocol, src->protocol); > @@ -2500,11 +2572,16 @@ > qemuBlockStorageSourceCreateGetStorageProps(virStorageSourcePtr src, > return -1; > break; > > + case VIR_STORAGE_NET_PROTOCOL_NFS: > + driver = "nfs"; > + if (!(location = qemuBlockStorageSourceGetNFSProps(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_NFS: > case VIR_STORAGE_NET_PROTOCOL_HTTP: > case VIR_STORAGE_NET_PROTOCOL_HTTPS: > case VIR_STORAGE_NET_PROTOCOL_FTP: > diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c > index d91c32b2c5..8812df5138 100644 > --- a/src/qemu/qemu_domain.c > +++ b/src/qemu/qemu_domain.c > @@ -4626,6 +4626,14 @@ qemuDomainValidateStorageSource(virStorageSourcePtr > src, > return -1; > } > > + /* NFS protocol may only be used if current QEMU supports blockdev */ > + if (actualType == VIR_STORAGE_TYPE_NETWORK && > + src->protocol == VIR_STORAGE_NET_PROTOCOL_NFS && > + !blockdev) { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("'nfs' protocol is not supported with this QEMU > binary")); > + } > + > return 0; > } > > @@ -9590,6 +9598,42 @@ > qemuProcessPrepareStorageSourceTLSNBD(virStorageSourcePtr src, > } > > > +/* qemuPrepareStorageSourceNFS: > + * @src: source for a disk > + * > + * If src is an NFS source, translate nfs_user and nfs_group > + * into a uid and gid field. If these strings are empty (ie "") > + * then provide the hypervisor default uid and gid. > + */ > +static int > +qemuDomainPrepareStorageSourceNFS(virStorageSourcePtr src) > +{ > + if (virStorageSourceGetActualType(src) != VIR_STORAGE_TYPE_NETWORK) > + return 0; > + > + if ((virStorageNetProtocol) src->protocol != > VIR_STORAGE_NET_PROTOCOL_NFS) > + return 0; > + > + if (src->nfs_user) { > + if (virGetUserID(src->nfs_user, &src->nfs_uid) < 0) > + return -1; > + } else { > + /* -1 indicates default UID */ > + src->nfs_uid = -1; > + } > + > + if (src->nfs_group) { > + if (virGetGroupID(src->nfs_group, &src->nfs_gid) < 0) > + return -1; > + } else { > + /* -1 indicates default GID */ > + src->nfs_gid = -1; > + } > + > + return 0; > +} > + > + > /* qemuProcessPrepareStorageSourceTLS: > * @source: source for a disk > * @cfg: driver configuration > @@ -10401,6 +10445,9 @@ > qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk, > priv) < 0) > return -1; > > + if (qemuDomainPrepareStorageSourceNFS(src) < 0) > + return -1; > + > return 0; > } > > -- > 2.29.2 > > -- Tested-by: Han Han <h...@redhat.com>