mirror of https://gitee.com/openkylin/libvirt.git
lib: Introduce virDomainFDAssociate API
The API can be used to associate one or more (e.g. a RO and RW fd for a disk backend image) FDs to a VM. They can be then used per definition. The primary use case for now is for complex deployment where libvirtd/virtqemud may be run inside a container and getting the image into the container is complicated. In the future it will also allow passing e.g. vhost FDs and other resources to a VM without the need to have a filesystem representation for it. Passing raw FDs has few intricacies and thus libvirt will by default not restore security labels. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
This commit is contained in:
parent
3ebfeaa206
commit
abd9025c2f
|
@ -6458,4 +6458,24 @@ int virDomainStartDirtyRateCalc(virDomainPtr domain,
|
|||
int seconds,
|
||||
unsigned int flags);
|
||||
|
||||
|
||||
/**
|
||||
* virDomainFDAssociateFlags:
|
||||
*
|
||||
* Since: 9.0.0
|
||||
*/
|
||||
typedef enum {
|
||||
/* Attempt a best-effort restore of security labels after use (Since: 9.0.0) */
|
||||
VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_RESTORE = (1 << 0),
|
||||
/* Use a seclabel allowing writes for the FD even if usage implies read-only mode (Since: 9.0.0) */
|
||||
VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_WRITABLE = (1 << 1),
|
||||
} virDomainFDAssociateFlags;
|
||||
|
||||
|
||||
int virDomainFDAssociate(virDomainPtr domain,
|
||||
const char *name,
|
||||
unsigned int nfds,
|
||||
int *fds,
|
||||
unsigned int flags);
|
||||
|
||||
#endif /* LIBVIRT_DOMAIN_H */
|
||||
|
|
|
@ -1441,6 +1441,13 @@ typedef int
|
|||
int seconds,
|
||||
unsigned int flags);
|
||||
|
||||
typedef int
|
||||
(*virDrvDomainFDAssociate)(virDomainPtr domain,
|
||||
const char *name,
|
||||
unsigned int nfds,
|
||||
int *fds,
|
||||
unsigned int flags);
|
||||
|
||||
typedef struct _virHypervisorDriver virHypervisorDriver;
|
||||
|
||||
/**
|
||||
|
@ -1712,4 +1719,5 @@ struct _virHypervisorDriver {
|
|||
virDrvDomainAuthorizedSSHKeysSet domainAuthorizedSSHKeysSet;
|
||||
virDrvDomainGetMessages domainGetMessages;
|
||||
virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
|
||||
virDrvDomainFDAssociate domainFDAssociate;
|
||||
};
|
||||
|
|
|
@ -13972,3 +13972,83 @@ virDomainStartDirtyRateCalc(virDomainPtr domain,
|
|||
virDispatchError(conn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* virDomainFDAssociate:
|
||||
* @domain: a domain object
|
||||
* @name: name for the file descriptor group
|
||||
* @nfds: number of fds in @fds
|
||||
* @fds: file descriptors to associate with domain
|
||||
* @flags: optional flags; bitwise-OR of supported virDomainFDAssociateFlags
|
||||
*
|
||||
* Associate the FDs in @fd with @domain under @name. The FDs are associated as
|
||||
* long as the connection used to associated exists and are disposed of
|
||||
* afterwards. FD may still be kept open by the hypervisor for as long as it's
|
||||
* needed.
|
||||
*
|
||||
* Security labelling (e.g. via the selinux) may be applied on the passed FDs
|
||||
* when required for usage by the VM. By default libvirt does not restore the
|
||||
* seclabels on the FDs afterwards to avoid keeping it open unnecessarily.
|
||||
*
|
||||
* Restoring of the security label can be requested by passing either
|
||||
* VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_RESTORE for a best-effort attempt to restore
|
||||
* the security label after use.
|
||||
* Requesting the restore of security label will require that the file
|
||||
* descriptors are kept open for the whole time they are used by the hypervisor,
|
||||
* or other additional overhead.
|
||||
*
|
||||
* In certain cases usage of the fd group would imply read-only access. Passing
|
||||
* VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_WRITABLE in @flags ensures that a writable
|
||||
* security label is picked in case when the file represented by the fds may
|
||||
* be used in write mode.
|
||||
*
|
||||
* Returns 0 on success, -1 on error.
|
||||
*
|
||||
* Since: 9.0.0
|
||||
*/
|
||||
int
|
||||
virDomainFDAssociate(virDomainPtr domain,
|
||||
const char *name,
|
||||
unsigned int nfds,
|
||||
int *fds,
|
||||
unsigned int flags)
|
||||
{
|
||||
virConnectPtr conn;
|
||||
int rc;
|
||||
|
||||
VIR_DOMAIN_DEBUG(domain,
|
||||
"name='%s', nfds=%u, fds=%p, flags=0x%x",
|
||||
name, nfds, fds, flags);
|
||||
|
||||
virResetLastError();
|
||||
|
||||
conn = domain->conn;
|
||||
|
||||
if ((rc = VIR_DRV_SUPPORTS_FEATURE(conn->driver, conn, VIR_DRV_FEATURE_FD_PASSING)) < 0)
|
||||
goto error;
|
||||
|
||||
if (rc == 0) {
|
||||
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
||||
_("fd passing is not supported by this connection"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
virCheckNonZeroArgGoto(nfds, error);
|
||||
virCheckNonNullArgGoto(fds, error);
|
||||
virCheckReadOnlyGoto(conn->flags, error);
|
||||
|
||||
if (!conn->driver->domainFDAssociate) {
|
||||
virReportUnsupportedError();
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((rc = conn->driver->domainFDAssociate(domain, name, nfds, fds, flags)) < 0)
|
||||
goto error;
|
||||
|
||||
return rc;
|
||||
|
||||
error:
|
||||
virDispatchError(conn);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -927,4 +927,9 @@ LIBVIRT_8.5.0 {
|
|||
virDomainAbortJobFlags;
|
||||
} LIBVIRT_8.4.0;
|
||||
|
||||
LIBVIRT_9.0.0 {
|
||||
global:
|
||||
virDomainFDAssociate;
|
||||
} LIBVIRT_8.5.0;
|
||||
|
||||
# .... define new API here using predicted next version number ....
|
||||
|
|
|
@ -7443,3 +7443,43 @@ remoteDispatchDomainGetMessages(virNetServer *server G_GNUC_UNUSED,
|
|||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
remoteDispatchDomainFdAssociate(virNetServer *server G_GNUC_UNUSED,
|
||||
virNetServerClient *client,
|
||||
virNetMessage *msg,
|
||||
struct virNetMessageError *rerr,
|
||||
remote_domain_fd_associate_args *args)
|
||||
{
|
||||
virDomainPtr dom = NULL;
|
||||
int *fds = NULL;
|
||||
unsigned int nfds = 0;
|
||||
int rv = -1;
|
||||
virConnectPtr conn = remoteGetHypervisorConn(client);
|
||||
size_t i;
|
||||
|
||||
if (!conn)
|
||||
goto cleanup;
|
||||
|
||||
if (!(dom = get_nonnull_domain(conn, args->dom)))
|
||||
goto cleanup;
|
||||
|
||||
fds = g_new0(int, msg->nfds);
|
||||
for (i = 0; i < msg->nfds; i++) {
|
||||
if ((fds[i] = virNetMessageDupFD(msg, i)) < 0)
|
||||
goto cleanup;
|
||||
nfds++;
|
||||
}
|
||||
|
||||
if (virDomainFDAssociate(dom, args->name, nfds, fds, args->flags) < 0)
|
||||
goto cleanup;
|
||||
|
||||
rv = 0;
|
||||
|
||||
cleanup:
|
||||
if (rv < 0)
|
||||
virNetMessageSaveError(rerr);
|
||||
virObjectUnref(dom);
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -8198,6 +8198,32 @@ remoteDomainGetMessages(virDomainPtr domain,
|
|||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
remoteDomainFDAssociate(virDomainPtr domain,
|
||||
const char *name,
|
||||
unsigned int nfds,
|
||||
int *fds,
|
||||
unsigned int flags)
|
||||
{
|
||||
remote_domain_fd_associate_args args;
|
||||
struct private_data *priv = domain->conn->privateData;
|
||||
VIR_LOCK_GUARD lock = remoteDriverLock(priv);
|
||||
|
||||
make_nonnull_domain(&args.dom, domain);
|
||||
args.name = (char *)name;
|
||||
args.flags = flags;
|
||||
|
||||
if (callFull(domain->conn, priv, 0, fds, nfds, NULL, NULL,
|
||||
REMOTE_PROC_DOMAIN_FD_ASSOCIATE,
|
||||
(xdrproc_t) xdr_remote_domain_fd_associate_args, (char *) &args,
|
||||
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
||||
* (name, uuid) pair into virDomainPtr or virNetworkPtr object.
|
||||
* These can return NULL if underlying memory allocations fail,
|
||||
|
@ -8638,6 +8664,7 @@ static virHypervisorDriver hypervisor_driver = {
|
|||
.domainGetMessages = remoteDomainGetMessages, /* 7.1.0 */
|
||||
.domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0 */
|
||||
.domainSetLaunchSecurityState = remoteDomainSetLaunchSecurityState, /* 8.0.0 */
|
||||
.domainFDAssociate = remoteDomainFDAssociate, /* 8.9.0 */
|
||||
};
|
||||
|
||||
static virNetworkDriver network_driver = {
|
||||
|
|
|
@ -3929,6 +3929,12 @@ struct remote_domain_event_memory_device_size_change_msg {
|
|||
unsigned hyper size;
|
||||
};
|
||||
|
||||
|
||||
struct remote_domain_fd_associate_args {
|
||||
remote_nonnull_domain dom;
|
||||
remote_nonnull_string name;
|
||||
unsigned int flags;
|
||||
};
|
||||
/*----- Protocol. -----*/
|
||||
|
||||
/* Define the program number, protocol version and procedure numbers here. */
|
||||
|
@ -6961,5 +6967,11 @@ enum remote_procedure {
|
|||
* @generate: both
|
||||
* @acl: domain:write
|
||||
*/
|
||||
REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442
|
||||
REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
|
||||
|
||||
/**
|
||||
* @generate: none
|
||||
* @acl: domain:write
|
||||
*/
|
||||
REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443
|
||||
};
|
||||
|
|
|
@ -3268,6 +3268,11 @@ struct remote_domain_event_memory_device_size_change_msg {
|
|||
remote_nonnull_string alias;
|
||||
uint64_t size;
|
||||
};
|
||||
struct remote_domain_fd_associate_args {
|
||||
remote_nonnull_domain dom;
|
||||
remote_nonnull_string name;
|
||||
u_int flags;
|
||||
};
|
||||
enum remote_procedure {
|
||||
REMOTE_PROC_CONNECT_OPEN = 1,
|
||||
REMOTE_PROC_CONNECT_CLOSE = 2,
|
||||
|
@ -3711,4 +3716,5 @@ enum remote_procedure {
|
|||
REMOTE_PROC_DOMAIN_SAVE_PARAMS = 440,
|
||||
REMOTE_PROC_DOMAIN_RESTORE_PARAMS = 441,
|
||||
REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
|
||||
REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue