mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
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,
|
int seconds,
|
||||||
unsigned int flags);
|
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 */
|
#endif /* LIBVIRT_DOMAIN_H */
|
||||||
|
@ -1441,6 +1441,13 @@ typedef int
|
|||||||
int seconds,
|
int seconds,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
|
||||||
|
typedef int
|
||||||
|
(*virDrvDomainFDAssociate)(virDomainPtr domain,
|
||||||
|
const char *name,
|
||||||
|
unsigned int nfds,
|
||||||
|
int *fds,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
typedef struct _virHypervisorDriver virHypervisorDriver;
|
typedef struct _virHypervisorDriver virHypervisorDriver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1712,4 +1719,5 @@ struct _virHypervisorDriver {
|
|||||||
virDrvDomainAuthorizedSSHKeysSet domainAuthorizedSSHKeysSet;
|
virDrvDomainAuthorizedSSHKeysSet domainAuthorizedSSHKeysSet;
|
||||||
virDrvDomainGetMessages domainGetMessages;
|
virDrvDomainGetMessages domainGetMessages;
|
||||||
virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
|
virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc;
|
||||||
|
virDrvDomainFDAssociate domainFDAssociate;
|
||||||
};
|
};
|
||||||
|
@ -13972,3 +13972,83 @@ virDomainStartDirtyRateCalc(virDomainPtr domain,
|
|||||||
virDispatchError(conn);
|
virDispatchError(conn);
|
||||||
return -1;
|
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;
|
virDomainAbortJobFlags;
|
||||||
} LIBVIRT_8.4.0;
|
} LIBVIRT_8.4.0;
|
||||||
|
|
||||||
|
LIBVIRT_9.0.0 {
|
||||||
|
global:
|
||||||
|
virDomainFDAssociate;
|
||||||
|
} LIBVIRT_8.5.0;
|
||||||
|
|
||||||
# .... define new API here using predicted next version number ....
|
# .... define new API here using predicted next version number ....
|
||||||
|
@ -7443,3 +7443,43 @@ remoteDispatchDomainGetMessages(virNetServer *server G_GNUC_UNUSED,
|
|||||||
|
|
||||||
return rv;
|
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;
|
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
|
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
||||||
* (name, uuid) pair into virDomainPtr or virNetworkPtr object.
|
* (name, uuid) pair into virDomainPtr or virNetworkPtr object.
|
||||||
* These can return NULL if underlying memory allocations fail,
|
* These can return NULL if underlying memory allocations fail,
|
||||||
@ -8638,6 +8664,7 @@ static virHypervisorDriver hypervisor_driver = {
|
|||||||
.domainGetMessages = remoteDomainGetMessages, /* 7.1.0 */
|
.domainGetMessages = remoteDomainGetMessages, /* 7.1.0 */
|
||||||
.domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0 */
|
.domainStartDirtyRateCalc = remoteDomainStartDirtyRateCalc, /* 7.2.0 */
|
||||||
.domainSetLaunchSecurityState = remoteDomainSetLaunchSecurityState, /* 8.0.0 */
|
.domainSetLaunchSecurityState = remoteDomainSetLaunchSecurityState, /* 8.0.0 */
|
||||||
|
.domainFDAssociate = remoteDomainFDAssociate, /* 8.9.0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static virNetworkDriver network_driver = {
|
static virNetworkDriver network_driver = {
|
||||||
|
@ -3929,6 +3929,12 @@ struct remote_domain_event_memory_device_size_change_msg {
|
|||||||
unsigned hyper size;
|
unsigned hyper size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct remote_domain_fd_associate_args {
|
||||||
|
remote_nonnull_domain dom;
|
||||||
|
remote_nonnull_string name;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
/*----- Protocol. -----*/
|
/*----- Protocol. -----*/
|
||||||
|
|
||||||
/* Define the program number, protocol version and procedure numbers here. */
|
/* Define the program number, protocol version and procedure numbers here. */
|
||||||
@ -6961,5 +6967,11 @@ enum remote_procedure {
|
|||||||
* @generate: both
|
* @generate: both
|
||||||
* @acl: domain:write
|
* @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;
|
remote_nonnull_string alias;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
};
|
};
|
||||||
|
struct remote_domain_fd_associate_args {
|
||||||
|
remote_nonnull_domain dom;
|
||||||
|
remote_nonnull_string name;
|
||||||
|
u_int flags;
|
||||||
|
};
|
||||||
enum remote_procedure {
|
enum remote_procedure {
|
||||||
REMOTE_PROC_CONNECT_OPEN = 1,
|
REMOTE_PROC_CONNECT_OPEN = 1,
|
||||||
REMOTE_PROC_CONNECT_CLOSE = 2,
|
REMOTE_PROC_CONNECT_CLOSE = 2,
|
||||||
@ -3711,4 +3716,5 @@ enum remote_procedure {
|
|||||||
REMOTE_PROC_DOMAIN_SAVE_PARAMS = 440,
|
REMOTE_PROC_DOMAIN_SAVE_PARAMS = 440,
|
||||||
REMOTE_PROC_DOMAIN_RESTORE_PARAMS = 441,
|
REMOTE_PROC_DOMAIN_RESTORE_PARAMS = 441,
|
||||||
REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
|
REMOTE_PROC_DOMAIN_ABORT_JOB_FLAGS = 442,
|
||||||
|
REMOTE_PROC_DOMAIN_FD_ASSOCIATE = 443,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user