mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
lib: Introduce 'virDomainQemuMonitorCommandWithFiles'
This API has the same semantics as 'virDomainQemuMonitorCommand' but accepts file descriptors which are then forwarded to qemu. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
7cfbfe66fc
commit
f87fa77ca9
@ -37,6 +37,14 @@ typedef enum {
|
|||||||
|
|
||||||
int virDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
|
int virDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
|
||||||
char **result, unsigned int flags);
|
char **result, unsigned int flags);
|
||||||
|
int virDomainQemuMonitorCommandWithFiles(virDomainPtr domain,
|
||||||
|
const char *cmd,
|
||||||
|
unsigned int ninfiles,
|
||||||
|
int *infiles,
|
||||||
|
unsigned int *noutfiles,
|
||||||
|
int **outfiles,
|
||||||
|
char **result,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
virDomainPtr virDomainQemuAttach(virConnectPtr domain,
|
virDomainPtr virDomainQemuAttach(virConnectPtr domain,
|
||||||
unsigned int pid_value,
|
unsigned int pid_value,
|
||||||
|
@ -874,6 +874,15 @@ typedef int
|
|||||||
const char *cmd,
|
const char *cmd,
|
||||||
char **result,
|
char **result,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
typedef int
|
||||||
|
(*virDrvDomainQemuMonitorCommandWithFiles)(virDomainPtr domain,
|
||||||
|
const char *cmd,
|
||||||
|
unsigned int ninfiles,
|
||||||
|
int *infiles,
|
||||||
|
unsigned int *noutfiles,
|
||||||
|
int **outfiles,
|
||||||
|
char **result,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
typedef char *
|
typedef char *
|
||||||
(*virDrvDomainQemuAgentCommand)(virDomainPtr domain,
|
(*virDrvDomainQemuAgentCommand)(virDomainPtr domain,
|
||||||
@ -1597,6 +1606,7 @@ struct _virHypervisorDriver {
|
|||||||
virDrvDomainRevertToSnapshot domainRevertToSnapshot;
|
virDrvDomainRevertToSnapshot domainRevertToSnapshot;
|
||||||
virDrvDomainSnapshotDelete domainSnapshotDelete;
|
virDrvDomainSnapshotDelete domainSnapshotDelete;
|
||||||
virDrvDomainQemuMonitorCommand domainQemuMonitorCommand;
|
virDrvDomainQemuMonitorCommand domainQemuMonitorCommand;
|
||||||
|
virDrvDomainQemuMonitorCommandWithFiles domainQemuMonitorCommandWithFiles;
|
||||||
virDrvDomainQemuAttach domainQemuAttach;
|
virDrvDomainQemuAttach domainQemuAttach;
|
||||||
virDrvDomainQemuAgentCommand domainQemuAgentCommand;
|
virDrvDomainQemuAgentCommand domainQemuAgentCommand;
|
||||||
virDrvConnectDomainQemuMonitorEventRegister connectDomainQemuMonitorEventRegister;
|
virDrvConnectDomainQemuMonitorEventRegister connectDomainQemuMonitorEventRegister;
|
||||||
|
@ -96,6 +96,95 @@ virDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virDomainQemuMonitorCommandWithFiles:
|
||||||
|
* @domain: a domain object
|
||||||
|
* @cmd: the qemu monitor command string
|
||||||
|
* @ninfiles: number of filedescriptors passed in @infiles
|
||||||
|
* @infiles: filedescriptors to be passed to qemu with the command
|
||||||
|
* @noutfiles: if non-NULL filled with number of returned file descriptors
|
||||||
|
* @outfiles: if non-NULL filled with an array of returned file descriptors
|
||||||
|
* @result: a string returned by @cmd
|
||||||
|
* @flags: bitwise-or of supported virDomainQemuMonitorCommandFlags
|
||||||
|
*
|
||||||
|
* This API is QEMU specific, so it will only work with hypervisor
|
||||||
|
* connections to the QEMU driver with local connections using the unix socket.
|
||||||
|
*
|
||||||
|
* Send an arbitrary monitor command @cmd with file descriptors @infiles to
|
||||||
|
* @domain through the qemu monitor and optionally return file descriptors via
|
||||||
|
* @outfiles. There are several requirements to safely and successfully use
|
||||||
|
* this API:
|
||||||
|
*
|
||||||
|
* - A @cmd that queries state without making any modifications is safe
|
||||||
|
* - A @cmd that alters state that is also tracked by libvirt is unsafe,
|
||||||
|
* and may cause libvirtd to crash
|
||||||
|
* - A @cmd that alters state not tracked by the current version of
|
||||||
|
* libvirt is possible as a means to test new qemu features before
|
||||||
|
* they have support in libvirt, but no guarantees are made to safety
|
||||||
|
*
|
||||||
|
* If VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP is set, the command is
|
||||||
|
* considered to be a human monitor command and libvirt will automatically
|
||||||
|
* convert it into QMP if needed. In that case the @result will also
|
||||||
|
* be converted back from QMP.
|
||||||
|
*
|
||||||
|
* If successful, @result will be filled with the string output of the
|
||||||
|
* @cmd, and the caller must free this string.
|
||||||
|
*
|
||||||
|
* Returns 0 in case of success, -1 in case of failure
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
virDomainQemuMonitorCommandWithFiles(virDomainPtr domain,
|
||||||
|
const char *cmd,
|
||||||
|
unsigned int ninfiles,
|
||||||
|
int *infiles,
|
||||||
|
unsigned int *noutfiles,
|
||||||
|
int **outfiles,
|
||||||
|
char **result,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virConnectPtr conn;
|
||||||
|
|
||||||
|
VIR_DOMAIN_DEBUG(domain,
|
||||||
|
"cmd=%s, ninfiles=%u, infiles=%p, noutfiles=%p, outfiles=%p, result=%p, flags=0x%x",
|
||||||
|
cmd, ninfiles, infiles, noutfiles, outfiles, result, flags);
|
||||||
|
|
||||||
|
virResetLastError();
|
||||||
|
|
||||||
|
virCheckDomainReturn(domain, -1);
|
||||||
|
conn = domain->conn;
|
||||||
|
|
||||||
|
if (ninfiles > 0 || outfiles) {
|
||||||
|
int rc;
|
||||||
|
if ((rc = VIR_DRV_SUPPORTS_FEATURE(conn->driver, conn,
|
||||||
|
VIR_DRV_FEATURE_FD_PASSING) <= 0)) {
|
||||||
|
if (rc == 0)
|
||||||
|
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
|
||||||
|
_("fd passing is not supported by this connection"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virCheckNonNullArgGoto(result, error);
|
||||||
|
virCheckReadOnlyGoto(conn->flags, error);
|
||||||
|
|
||||||
|
if (conn->driver->domainQemuMonitorCommandWithFiles) {
|
||||||
|
int ret;
|
||||||
|
ret = conn->driver->domainQemuMonitorCommandWithFiles(domain, cmd,
|
||||||
|
ninfiles, infiles,
|
||||||
|
noutfiles, outfiles,
|
||||||
|
result, flags);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
virReportUnsupportedError();
|
||||||
|
|
||||||
|
error:
|
||||||
|
virDispatchError(conn);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainQemuAttach:
|
* virDomainQemuAttach:
|
||||||
* @conn: pointer to a hypervisor connection
|
* @conn: pointer to a hypervisor connection
|
||||||
|
@ -30,3 +30,8 @@ LIBVIRT_QEMU_1.2.3 {
|
|||||||
virConnectDomainQemuMonitorEventDeregister;
|
virConnectDomainQemuMonitorEventDeregister;
|
||||||
virConnectDomainQemuMonitorEventRegister;
|
virConnectDomainQemuMonitorEventRegister;
|
||||||
} LIBVIRT_QEMU_0.10.0;
|
} LIBVIRT_QEMU_0.10.0;
|
||||||
|
|
||||||
|
LIBVIRT_QEMU_8.2.0 {
|
||||||
|
global:
|
||||||
|
virDomainQemuMonitorCommandWithFiles;
|
||||||
|
} LIBVIRT_QEMU_1.2.3;
|
||||||
|
@ -47,6 +47,14 @@ struct qemu_domain_monitor_event_msg {
|
|||||||
u_int micros;
|
u_int micros;
|
||||||
remote_string details;
|
remote_string details;
|
||||||
};
|
};
|
||||||
|
struct qemu_domain_monitor_command_with_files_args {
|
||||||
|
remote_nonnull_domain dom;
|
||||||
|
remote_nonnull_string cmd;
|
||||||
|
u_int flags;
|
||||||
|
};
|
||||||
|
struct qemu_domain_monitor_command_with_files_ret {
|
||||||
|
remote_nonnull_string result;
|
||||||
|
};
|
||||||
enum qemu_procedure {
|
enum qemu_procedure {
|
||||||
QEMU_PROC_DOMAIN_MONITOR_COMMAND = 1,
|
QEMU_PROC_DOMAIN_MONITOR_COMMAND = 1,
|
||||||
QEMU_PROC_DOMAIN_ATTACH = 2,
|
QEMU_PROC_DOMAIN_ATTACH = 2,
|
||||||
@ -54,4 +62,5 @@ enum qemu_procedure {
|
|||||||
QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_REGISTER = 4,
|
QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_REGISTER = 4,
|
||||||
QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER = 5,
|
QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER = 5,
|
||||||
QEMU_PROC_DOMAIN_MONITOR_EVENT = 6,
|
QEMU_PROC_DOMAIN_MONITOR_EVENT = 6,
|
||||||
|
QEMU_PROC_DOMAIN_MONITOR_COMMAND_WITH_FILES = 7,
|
||||||
};
|
};
|
||||||
|
@ -79,6 +79,17 @@ struct qemu_domain_monitor_event_msg {
|
|||||||
remote_string details;
|
remote_string details;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct qemu_domain_monitor_command_with_files_args {
|
||||||
|
remote_nonnull_domain dom;
|
||||||
|
remote_nonnull_string cmd;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qemu_domain_monitor_command_with_files_ret {
|
||||||
|
remote_nonnull_string result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Define the program number, protocol version and procedure numbers here. */
|
/* Define the program number, protocol version and procedure numbers here. */
|
||||||
const QEMU_PROGRAM = 0x20008087;
|
const QEMU_PROGRAM = 0x20008087;
|
||||||
const QEMU_PROTOCOL_VERSION = 1;
|
const QEMU_PROTOCOL_VERSION = 1;
|
||||||
@ -151,5 +162,12 @@ enum qemu_procedure {
|
|||||||
* @generate: both
|
* @generate: both
|
||||||
* @acl: none
|
* @acl: none
|
||||||
*/
|
*/
|
||||||
QEMU_PROC_DOMAIN_MONITOR_EVENT = 6
|
QEMU_PROC_DOMAIN_MONITOR_EVENT = 6,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generate: none
|
||||||
|
* @priority: low
|
||||||
|
* @acl: domain:write
|
||||||
|
*/
|
||||||
|
QEMU_PROC_DOMAIN_MONITOR_COMMAND_WITH_FILES = 7
|
||||||
};
|
};
|
||||||
|
@ -4684,6 +4684,68 @@ qemuDispatchDomainMonitorCommand(virNetServer *server G_GNUC_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDispatchDomainMonitorCommandWithFiles(virNetServer *server G_GNUC_UNUSED,
|
||||||
|
virNetServerClient *client,
|
||||||
|
virNetMessage *msg,
|
||||||
|
struct virNetMessageError *rerr,
|
||||||
|
qemu_domain_monitor_command_with_files_args *args,
|
||||||
|
qemu_domain_monitor_command_with_files_ret *ret)
|
||||||
|
{
|
||||||
|
virDomainPtr dom = NULL;
|
||||||
|
int *infiles = NULL;
|
||||||
|
unsigned int ninfiles = 0;
|
||||||
|
int *outfiles = NULL;
|
||||||
|
unsigned int noutfiles = 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;
|
||||||
|
|
||||||
|
infiles = g_new0(int, msg->nfds);
|
||||||
|
for (i = 0; i < msg->nfds; i++) {
|
||||||
|
if ((infiles[i] = virNetMessageDupFD(msg, i)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
ninfiles++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This API can both receive FDs from the client and send FDs back, but 'msg'
|
||||||
|
* is being reused. Thus we must clear the list of FDs in it to prevent
|
||||||
|
* us sending back the FDs client sent us. */
|
||||||
|
virNetMessageClearFDs(msg);
|
||||||
|
|
||||||
|
if (virDomainQemuMonitorCommandWithFiles(dom, args->cmd, ninfiles, infiles,
|
||||||
|
&noutfiles, &outfiles,
|
||||||
|
&ret->result, args->flags) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < noutfiles; i++) {
|
||||||
|
if (virNetMessageAddFD(msg, outfiles[i]) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return 1 here to let virNetServerProgramDispatchCall know we are passing fds */
|
||||||
|
if (noutfiles > 0)
|
||||||
|
rv = 1;
|
||||||
|
else
|
||||||
|
rv = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
for (i = 0; i < noutfiles; i++)
|
||||||
|
VIR_FORCE_CLOSE(outfiles[i]);
|
||||||
|
|
||||||
|
if (rv < 0)
|
||||||
|
virNetMessageSaveError(rerr);
|
||||||
|
virObjectUnref(dom);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
remoteDispatchDomainMigrateBegin3(virNetServer *server G_GNUC_UNUSED,
|
remoteDispatchDomainMigrateBegin3(virNetServer *server G_GNUC_UNUSED,
|
||||||
virNetServerClient *client,
|
virNetServerClient *client,
|
||||||
|
@ -5931,6 +5931,62 @@ remoteDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteDomainQemuMonitorCommandWithFiles(virDomainPtr domain,
|
||||||
|
const char *cmd,
|
||||||
|
unsigned int ninfiles,
|
||||||
|
int *infiles,
|
||||||
|
unsigned int *noutfiles,
|
||||||
|
int **outfiles,
|
||||||
|
char **result,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int rv = -1;
|
||||||
|
qemu_domain_monitor_command_with_files_args args;
|
||||||
|
qemu_domain_monitor_command_with_files_ret ret;
|
||||||
|
struct private_data *priv = domain->conn->privateData;
|
||||||
|
size_t rpc_noutfiles = 0;
|
||||||
|
g_autofree int *rpc_outfiles = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
remoteDriverLock(priv);
|
||||||
|
|
||||||
|
make_nonnull_domain(&args.dom, domain);
|
||||||
|
args.cmd = (char *)cmd;
|
||||||
|
args.flags = flags;
|
||||||
|
|
||||||
|
memset(&ret, 0, sizeof(ret));
|
||||||
|
if (callFull(domain->conn, priv, REMOTE_CALL_QEMU,
|
||||||
|
infiles, ninfiles, &rpc_outfiles, &rpc_noutfiles,
|
||||||
|
QEMU_PROC_DOMAIN_MONITOR_COMMAND_WITH_FILES,
|
||||||
|
(xdrproc_t) xdr_qemu_domain_monitor_command_with_files_args, (char *) &args,
|
||||||
|
(xdrproc_t) xdr_qemu_domain_monitor_command_with_files_ret, (char *) &ret) == -1)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (outfiles)
|
||||||
|
*outfiles = g_steal_pointer(&rpc_outfiles);
|
||||||
|
|
||||||
|
if (noutfiles)
|
||||||
|
*noutfiles = rpc_noutfiles;
|
||||||
|
|
||||||
|
*result = g_strdup(ret.result);
|
||||||
|
|
||||||
|
rv = 0;
|
||||||
|
|
||||||
|
xdr_free((xdrproc_t) xdr_qemu_domain_monitor_command_with_files_ret, (char *) &ret);
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (rpc_outfiles) {
|
||||||
|
for (i = 0; rpc_noutfiles < i; i++) {
|
||||||
|
VIR_FORCE_CLOSE(rpc_outfiles[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteDriverUnlock(priv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
remoteDomainMigrateBegin3(virDomainPtr domain,
|
remoteDomainMigrateBegin3(virDomainPtr domain,
|
||||||
const char *xmlin,
|
const char *xmlin,
|
||||||
@ -8506,6 +8562,7 @@ static virHypervisorDriver hypervisor_driver = {
|
|||||||
.domainSnapshotHasMetadata = remoteDomainSnapshotHasMetadata, /* 0.9.13 */
|
.domainSnapshotHasMetadata = remoteDomainSnapshotHasMetadata, /* 0.9.13 */
|
||||||
.domainSnapshotDelete = remoteDomainSnapshotDelete, /* 0.8.0 */
|
.domainSnapshotDelete = remoteDomainSnapshotDelete, /* 0.8.0 */
|
||||||
.domainQemuMonitorCommand = remoteDomainQemuMonitorCommand, /* 0.8.3 */
|
.domainQemuMonitorCommand = remoteDomainQemuMonitorCommand, /* 0.8.3 */
|
||||||
|
.domainQemuMonitorCommandWithFiles = remoteDomainQemuMonitorCommandWithFiles, /* 8.2.0 */
|
||||||
.domainQemuAttach = remoteDomainQemuAttach, /* 0.9.4 */
|
.domainQemuAttach = remoteDomainQemuAttach, /* 0.9.4 */
|
||||||
.domainQemuAgentCommand = remoteDomainQemuAgentCommand, /* 0.10.0 */
|
.domainQemuAgentCommand = remoteDomainQemuAgentCommand, /* 0.10.0 */
|
||||||
.connectDomainQemuMonitorEventRegister = remoteConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
|
.connectDomainQemuMonitorEventRegister = remoteConnectDomainQemuMonitorEventRegister, /* 1.2.3 */
|
||||||
|
Loading…
Reference in New Issue
Block a user