qemu: block: Add support for VIR_STORAGE_NET_PROTOCOL_NFS
Implement support for the 'nfs' native protocol driver in the qemu driver. QEMU accepts numeric UID/GID for 'nfs' protocol file driver thus libvirt needs to perform the lookup prior to passing it to qemu. Signed-off-by: Ryan Gahagan <rgahagan@cs.utexas.edu> Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
parent
86e26645ee
commit
c7570bbef8
@ -574,6 +574,29 @@ 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;
|
||||||
|
|
||||||
|
ignore_value(virJSONValueObjectCreate(&ret,
|
||||||
|
"s:host", host->name,
|
||||||
|
"s:type", "inet",
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemuBlockStorageSourceBuildHostsJSONInetSocketAddress:
|
* qemuBlockStorageSourceBuildHostsJSONInetSocketAddress:
|
||||||
* @src: disk storage source
|
* @src: disk storage source
|
||||||
@ -674,6 +697,39 @@ qemuBlockStorageSourceGetVxHSProps(virStorageSourcePtr src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static virJSONValuePtr
|
||||||
|
qemuBlockStorageSourceGetNFSProps(virStorageSourcePtr src)
|
||||||
|
{
|
||||||
|
g_autoptr(virJSONValue) server = NULL;
|
||||||
|
virJSONValuePtr ret = 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"}}
|
||||||
|
*/
|
||||||
|
if (virJSONValueObjectCreate(&ret,
|
||||||
|
"a:server", &server,
|
||||||
|
"S:path", src->path, NULL) < 0)
|
||||||
|
return 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
|
static virJSONValuePtr
|
||||||
qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src,
|
qemuBlockStorageSourceGetCURLProps(virStorageSourcePtr src,
|
||||||
bool onlytarget)
|
bool onlytarget)
|
||||||
@ -1181,6 +1237,11 @@ qemuBlockStorageSourceGetBackendProps(virStorageSourcePtr src,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_STORAGE_NET_PROTOCOL_NFS:
|
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_NONE:
|
||||||
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
case VIR_STORAGE_NET_PROTOCOL_LAST:
|
||||||
virReportEnumRangeError(virStorageNetProtocol, src->protocol);
|
virReportEnumRangeError(virStorageNetProtocol, src->protocol);
|
||||||
@ -2500,11 +2561,16 @@ qemuBlockStorageSourceCreateGetStorageProps(virStorageSourcePtr src,
|
|||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_STORAGE_NET_PROTOCOL_NFS:
|
||||||
|
driver = "nfs";
|
||||||
|
if (!(location = qemuBlockStorageSourceGetNFSProps(src)))
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
|
||||||
/* unsupported/impossible */
|
/* unsupported/impossible */
|
||||||
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
case VIR_STORAGE_NET_PROTOCOL_NBD:
|
||||||
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
case VIR_STORAGE_NET_PROTOCOL_ISCSI:
|
||||||
case VIR_STORAGE_NET_PROTOCOL_VXHS:
|
case VIR_STORAGE_NET_PROTOCOL_VXHS:
|
||||||
case VIR_STORAGE_NET_PROTOCOL_NFS:
|
|
||||||
case VIR_STORAGE_NET_PROTOCOL_HTTP:
|
case VIR_STORAGE_NET_PROTOCOL_HTTP:
|
||||||
case VIR_STORAGE_NET_PROTOCOL_HTTPS:
|
case VIR_STORAGE_NET_PROTOCOL_HTTPS:
|
||||||
case VIR_STORAGE_NET_PROTOCOL_FTP:
|
case VIR_STORAGE_NET_PROTOCOL_FTP:
|
||||||
|
@ -4626,6 +4626,37 @@ qemuDomainValidateStorageSource(virStorageSourcePtr src,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (actualType == VIR_STORAGE_TYPE_NETWORK &&
|
||||||
|
src->protocol == VIR_STORAGE_NET_PROTOCOL_NFS) {
|
||||||
|
/* NFS protocol may only be used if current QEMU supports blockdev */
|
||||||
|
if (!blockdev) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("'nfs' protocol is not supported with this QEMU binary"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NFS protocol must have exactly one host */
|
||||||
|
if (src->nhosts != 1) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("'nfs' protocol requires the usage of exactly one host"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NFS can only use a TCP protocol */
|
||||||
|
if (src->hosts[0].transport != VIR_STORAGE_NET_HOST_TRANS_TCP) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("'nfs' host must use TCP protocol"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NFS host cannot have a port */
|
||||||
|
if (src->hosts[0].port != 0) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("port cannot be specified in 'nfs' protocol host"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9590,6 +9621,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 (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:
|
/* qemuProcessPrepareStorageSourceTLS:
|
||||||
* @source: source for a disk
|
* @source: source for a disk
|
||||||
* @cfg: driver configuration
|
* @cfg: driver configuration
|
||||||
@ -10401,6 +10468,9 @@ qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDefPtr disk,
|
|||||||
priv) < 0)
|
priv) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (qemuDomainPrepareStorageSourceNFS(src) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user