mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-09-08 16:54:49 +00:00
qemu: wire up RPC for qemu monitor events
These are the first async events in the qemu protocol, so this patch looks rather big compared to most RPC additions. However, a large majority of this patch is just mechanical copy-and-paste from recently-added network events. It didn't help that this is also the first virConnect rather than virDomain prefix associated with a qemu-specific API. * src/remote/qemu_protocol.x (qemu_*_domain_monitor_event_*): New structs and RPC messages. * src/rpc/gendispatch.pl: Adjust naming conventions. * daemon/libvirtd.h (daemonClientPrivate): Track qemu events. * daemon/remote.c (remoteClientFreeFunc): Likewise. (remoteRelayDomainQemuMonitorEvent) (qemuDispatchConnectDomainMonitorEventRegister) (qemuDispatchConnectDomainMonitorEventDeregister): New functions. * src/remote/remote_driver.c (qemuEvents): Handle qemu events. (doRemoteOpen): Register for events. (remoteNetworkBuildEventLifecycle) (remoteConnectDomainQemuMonitorEventRegister) (remoteConnectDomainQemuMonitorEventDeregister): New functions. * src/qemu_protocol-structs: Regenerate. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
8059afca62
commit
e7708a1c47
@ -54,6 +54,8 @@ struct daemonClientPrivate {
|
|||||||
size_t ndomainEventCallbacks;
|
size_t ndomainEventCallbacks;
|
||||||
daemonClientEventCallbackPtr *networkEventCallbacks;
|
daemonClientEventCallbackPtr *networkEventCallbacks;
|
||||||
size_t nnetworkEventCallbacks;
|
size_t nnetworkEventCallbacks;
|
||||||
|
daemonClientEventCallbackPtr *qemuEventCallbacks;
|
||||||
|
size_t nqemuEventCallbacks;
|
||||||
|
|
||||||
# if WITH_SASL
|
# if WITH_SASL
|
||||||
virNetSASLSessionPtr sasl;
|
virNetSASLSessionPtr sasl;
|
||||||
|
209
daemon/remote.c
209
daemon/remote.c
@ -54,6 +54,7 @@
|
|||||||
#include "network_conf.h"
|
#include "network_conf.h"
|
||||||
#include "virprobe.h"
|
#include "virprobe.h"
|
||||||
#include "viraccessapicheck.h"
|
#include "viraccessapicheck.h"
|
||||||
|
#include "viraccessapicheckqemu.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_RPC
|
#define VIR_FROM_THIS VIR_FROM_RPC
|
||||||
|
|
||||||
@ -189,6 +190,33 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
remoteRelayDomainQemuMonitorEventCheckACL(virNetServerClientPtr client,
|
||||||
|
virConnectPtr conn, virDomainPtr dom)
|
||||||
|
{
|
||||||
|
virDomainDef def;
|
||||||
|
virIdentityPtr identity = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
/* For now, we just create a virDomainDef with enough contents to
|
||||||
|
* satisfy what viraccessdriverpolkit.c references. This is a bit
|
||||||
|
* fragile, but I don't know of anything better. */
|
||||||
|
def.name = dom->name;
|
||||||
|
memcpy(def.uuid, dom->uuid, VIR_UUID_BUFLEN);
|
||||||
|
|
||||||
|
if (!(identity = virNetServerClientGetIdentity(client)))
|
||||||
|
goto cleanup;
|
||||||
|
if (virIdentitySetCurrent(identity) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
ret = virConnectDomainQemuMonitorEventRegisterCheckACL(conn, &def);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
ignore_value(virIdentitySetCurrent(NULL));
|
||||||
|
virObjectUnref(identity);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
remoteRelayDomainEventLifecycle(virConnectPtr conn,
|
remoteRelayDomainEventLifecycle(virConnectPtr conn,
|
||||||
virDomainPtr dom,
|
virDomainPtr dom,
|
||||||
@ -961,6 +989,52 @@ static virConnectNetworkEventGenericCallback networkEventCallbacks[] = {
|
|||||||
|
|
||||||
verify(ARRAY_CARDINALITY(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST);
|
verify(ARRAY_CARDINALITY(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST);
|
||||||
|
|
||||||
|
static void
|
||||||
|
remoteRelayDomainQemuMonitorEvent(virConnectPtr conn,
|
||||||
|
virDomainPtr dom,
|
||||||
|
const char *event,
|
||||||
|
long long seconds,
|
||||||
|
unsigned int micros,
|
||||||
|
const char *details,
|
||||||
|
void *opaque)
|
||||||
|
{
|
||||||
|
daemonClientEventCallbackPtr callback = opaque;
|
||||||
|
qemu_domain_monitor_event_msg data;
|
||||||
|
char **details_p = NULL;
|
||||||
|
|
||||||
|
if (callback->callbackID < 0 ||
|
||||||
|
!remoteRelayDomainQemuMonitorEventCheckACL(callback->client, conn,
|
||||||
|
dom))
|
||||||
|
return;
|
||||||
|
|
||||||
|
VIR_DEBUG("Relaying qemu monitor event %s %s, callback %d",
|
||||||
|
event, details, callback->callbackID);
|
||||||
|
|
||||||
|
/* build return data */
|
||||||
|
memset(&data, 0, sizeof(data));
|
||||||
|
data.callbackID = callback->callbackID;
|
||||||
|
if (VIR_STRDUP(data.event, event) < 0)
|
||||||
|
goto error;
|
||||||
|
data.seconds = seconds;
|
||||||
|
data.micros = micros;
|
||||||
|
if (details &&
|
||||||
|
((VIR_ALLOC(details_p) < 0) ||
|
||||||
|
VIR_STRDUP(*details_p, details) < 0))
|
||||||
|
goto error;
|
||||||
|
data.details = details_p;
|
||||||
|
make_nonnull_domain(&data.dom, dom);
|
||||||
|
|
||||||
|
remoteDispatchObjectEventSend(callback->client, qemuProgram,
|
||||||
|
QEMU_PROC_DOMAIN_MONITOR_EVENT,
|
||||||
|
(xdrproc_t)xdr_qemu_domain_monitor_event_msg,
|
||||||
|
&data);
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
VIR_FREE(data.event);
|
||||||
|
VIR_FREE(details_p);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* You must hold lock for at least the client
|
* You must hold lock for at least the client
|
||||||
* We don't free stuff here, merely disconnect the client's
|
* We don't free stuff here, merely disconnect the client's
|
||||||
@ -1008,6 +1082,21 @@ void remoteClientFreeFunc(void *data)
|
|||||||
}
|
}
|
||||||
VIR_FREE(priv->networkEventCallbacks);
|
VIR_FREE(priv->networkEventCallbacks);
|
||||||
|
|
||||||
|
for (i = 0; i < priv->nqemuEventCallbacks; i++) {
|
||||||
|
int callbackID = priv->qemuEventCallbacks[i]->callbackID;
|
||||||
|
if (callbackID < 0) {
|
||||||
|
VIR_WARN("unexpected incomplete qemu monitor callback %zu", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
VIR_DEBUG("Deregistering remote qemu monitor event relay %d",
|
||||||
|
callbackID);
|
||||||
|
priv->qemuEventCallbacks[i]->callbackID = -1;
|
||||||
|
if (virConnectDomainQemuMonitorEventDeregister(priv->conn,
|
||||||
|
callbackID) < 0)
|
||||||
|
VIR_WARN("unexpected qemu monitor event deregister failure");
|
||||||
|
}
|
||||||
|
VIR_FREE(priv->qemuEventCallbacks);
|
||||||
|
|
||||||
virConnectClose(priv->conn);
|
virConnectClose(priv->conn);
|
||||||
|
|
||||||
virIdentitySetCurrent(NULL);
|
virIdentitySetCurrent(NULL);
|
||||||
@ -5869,6 +5958,126 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDispatchConnectDomainMonitorEventRegister(virNetServerPtr server ATTRIBUTE_UNUSED,
|
||||||
|
virNetServerClientPtr client,
|
||||||
|
virNetMessagePtr msg ATTRIBUTE_UNUSED,
|
||||||
|
virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED,
|
||||||
|
qemu_connect_domain_monitor_event_register_args *args,
|
||||||
|
qemu_connect_domain_monitor_event_register_ret *ret)
|
||||||
|
{
|
||||||
|
int callbackID;
|
||||||
|
int rv = -1;
|
||||||
|
daemonClientEventCallbackPtr callback = NULL;
|
||||||
|
daemonClientEventCallbackPtr ref;
|
||||||
|
struct daemonClientPrivate *priv =
|
||||||
|
virNetServerClientGetPrivateData(client);
|
||||||
|
virDomainPtr dom = NULL;
|
||||||
|
const char *event = args->event ? *args->event : NULL;
|
||||||
|
|
||||||
|
if (!priv->conn) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
virMutexLock(&priv->lock);
|
||||||
|
|
||||||
|
if (args->dom &&
|
||||||
|
!(dom = get_nonnull_domain(priv->conn, *args->dom)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* If we call register first, we could append a complete callback
|
||||||
|
* to our array, but on OOM append failure, we'd have to then hope
|
||||||
|
* deregister works to undo our register. So instead we append an
|
||||||
|
* incomplete callback to our array, then register, then fix up
|
||||||
|
* our callback; but since VIR_APPEND_ELEMENT clears 'callback' on
|
||||||
|
* success, we use 'ref' to save a copy of the pointer. */
|
||||||
|
if (VIR_ALLOC(callback) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
callback->client = client;
|
||||||
|
callback->callbackID = -1;
|
||||||
|
ref = callback;
|
||||||
|
if (VIR_APPEND_ELEMENT(priv->qemuEventCallbacks,
|
||||||
|
priv->nqemuEventCallbacks,
|
||||||
|
callback) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((callbackID = virConnectDomainQemuMonitorEventRegister(priv->conn,
|
||||||
|
dom,
|
||||||
|
event,
|
||||||
|
remoteRelayDomainQemuMonitorEvent,
|
||||||
|
ref,
|
||||||
|
remoteEventCallbackFree,
|
||||||
|
args->flags)) < 0) {
|
||||||
|
VIR_SHRINK_N(priv->qemuEventCallbacks,
|
||||||
|
priv->nqemuEventCallbacks, 1);
|
||||||
|
callback = ref;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref->callbackID = callbackID;
|
||||||
|
ret->callbackID = callbackID;
|
||||||
|
|
||||||
|
rv = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(callback);
|
||||||
|
if (rv < 0)
|
||||||
|
virNetMessageSaveError(rerr);
|
||||||
|
if (dom)
|
||||||
|
virDomainFree(dom);
|
||||||
|
virMutexUnlock(&priv->lock);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDispatchConnectDomainMonitorEventDeregister(virNetServerPtr server ATTRIBUTE_UNUSED,
|
||||||
|
virNetServerClientPtr client,
|
||||||
|
virNetMessagePtr msg ATTRIBUTE_UNUSED,
|
||||||
|
virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED,
|
||||||
|
qemu_connect_domain_monitor_event_deregister_args *args)
|
||||||
|
{
|
||||||
|
int rv = -1;
|
||||||
|
size_t i;
|
||||||
|
struct daemonClientPrivate *priv =
|
||||||
|
virNetServerClientGetPrivateData(client);
|
||||||
|
|
||||||
|
if (!priv->conn) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
virMutexLock(&priv->lock);
|
||||||
|
|
||||||
|
for (i = 0; i < priv->nqemuEventCallbacks; i++) {
|
||||||
|
if (priv->qemuEventCallbacks[i]->callbackID == args->callbackID)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == priv->nqemuEventCallbacks) {
|
||||||
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("qemu monitor event callback %d not registered"),
|
||||||
|
args->callbackID);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virConnectDomainQemuMonitorEventDeregister(priv->conn,
|
||||||
|
args->callbackID) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
VIR_DELETE_ELEMENT(priv->qemuEventCallbacks, i,
|
||||||
|
priv->nqemuEventCallbacks);
|
||||||
|
|
||||||
|
rv = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (rv < 0)
|
||||||
|
virNetMessageSaveError(rerr);
|
||||||
|
virMutexUnlock(&priv->lock);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----- Helpers. -----*/
|
/*----- Helpers. -----*/
|
||||||
|
|
||||||
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
/* get_nonnull_domain and get_nonnull_network turn an on-wire
|
||||||
|
@ -28,8 +28,30 @@ struct qemu_domain_agent_command_args {
|
|||||||
struct qemu_domain_agent_command_ret {
|
struct qemu_domain_agent_command_ret {
|
||||||
remote_string result;
|
remote_string result;
|
||||||
};
|
};
|
||||||
|
struct qemu_connect_domain_monitor_event_register_args {
|
||||||
|
remote_domain dom;
|
||||||
|
remote_string event;
|
||||||
|
u_int flags;
|
||||||
|
};
|
||||||
|
struct qemu_connect_domain_monitor_event_register_ret {
|
||||||
|
int callbackID;
|
||||||
|
};
|
||||||
|
struct qemu_connect_domain_monitor_event_deregister_args {
|
||||||
|
int callbackID;
|
||||||
|
};
|
||||||
|
struct qemu_domain_monitor_event_msg {
|
||||||
|
int callbackID;
|
||||||
|
remote_nonnull_domain dom;
|
||||||
|
remote_nonnull_string event;
|
||||||
|
int64_t seconds;
|
||||||
|
u_int micros;
|
||||||
|
remote_string details;
|
||||||
|
};
|
||||||
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,
|
||||||
QEMU_PROC_DOMAIN_AGENT_COMMAND = 3,
|
QEMU_PROC_DOMAIN_AGENT_COMMAND = 3,
|
||||||
|
QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_REGISTER = 4,
|
||||||
|
QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER = 5,
|
||||||
|
QEMU_PROC_DOMAIN_MONITOR_EVENT = 6,
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* remote_internal driver and libvirtd. This protocol is
|
* remote_internal driver and libvirtd. This protocol is
|
||||||
* internal and may change at any time.
|
* internal and may change at any time.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010-2012 Red Hat, Inc.
|
* Copyright (C) 2010-2014 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -58,6 +58,30 @@ struct qemu_domain_agent_command_ret {
|
|||||||
remote_string result;
|
remote_string result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct qemu_connect_domain_monitor_event_register_args {
|
||||||
|
remote_domain dom;
|
||||||
|
remote_string event;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qemu_connect_domain_monitor_event_register_ret {
|
||||||
|
int callbackID;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qemu_connect_domain_monitor_event_deregister_args {
|
||||||
|
int callbackID;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qemu_domain_monitor_event_msg {
|
||||||
|
int callbackID;
|
||||||
|
remote_nonnull_domain dom;
|
||||||
|
remote_nonnull_string event;
|
||||||
|
hyper seconds;
|
||||||
|
unsigned int micros;
|
||||||
|
remote_string details;
|
||||||
|
};
|
||||||
|
|
||||||
/* 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;
|
||||||
@ -108,5 +132,27 @@ enum qemu_procedure {
|
|||||||
* @priority: low
|
* @priority: low
|
||||||
* @acl: domain:write
|
* @acl: domain:write
|
||||||
*/
|
*/
|
||||||
QEMU_PROC_DOMAIN_AGENT_COMMAND = 3
|
QEMU_PROC_DOMAIN_AGENT_COMMAND = 3,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generate: none
|
||||||
|
* @priority: high
|
||||||
|
* @acl: connect:search_domains
|
||||||
|
* @acl: connect:write
|
||||||
|
* @aclfilter: domain:getattr
|
||||||
|
*/
|
||||||
|
QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_REGISTER = 4,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generate: none
|
||||||
|
* @priority: high
|
||||||
|
* @acl: connect:write
|
||||||
|
*/
|
||||||
|
QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER = 5,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @generate: both
|
||||||
|
* @acl: none
|
||||||
|
*/
|
||||||
|
QEMU_PROC_DOMAIN_MONITOR_EVENT = 6
|
||||||
};
|
};
|
||||||
|
@ -500,6 +500,19 @@ static virNetClientProgramEvent remoteEvents[] = {
|
|||||||
(xdrproc_t)xdr_remote_domain_event_callback_device_removed_msg },
|
(xdrproc_t)xdr_remote_domain_event_callback_device_removed_msg },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
remoteDomainBuildQemuMonitorEvent(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
||||||
|
virNetClientPtr client ATTRIBUTE_UNUSED,
|
||||||
|
void *evdata, void *opaque);
|
||||||
|
|
||||||
|
static virNetClientProgramEvent qemuEvents[] = {
|
||||||
|
{ QEMU_PROC_DOMAIN_MONITOR_EVENT,
|
||||||
|
remoteDomainBuildQemuMonitorEvent,
|
||||||
|
sizeof(qemu_domain_monitor_event_msg),
|
||||||
|
(xdrproc_t)xdr_qemu_domain_monitor_event_msg },
|
||||||
|
};
|
||||||
|
|
||||||
enum virDrvOpenRemoteFlags {
|
enum virDrvOpenRemoteFlags {
|
||||||
VIR_DRV_OPEN_REMOTE_RO = (1 << 0),
|
VIR_DRV_OPEN_REMOTE_RO = (1 << 0),
|
||||||
VIR_DRV_OPEN_REMOTE_USER = (1 << 1), /* Use the per-user socket path */
|
VIR_DRV_OPEN_REMOTE_USER = (1 << 1), /* Use the per-user socket path */
|
||||||
@ -977,9 +990,9 @@ doRemoteOpen(virConnectPtr conn,
|
|||||||
goto failed;
|
goto failed;
|
||||||
if (!(priv->qemuProgram = virNetClientProgramNew(QEMU_PROGRAM,
|
if (!(priv->qemuProgram = virNetClientProgramNew(QEMU_PROGRAM,
|
||||||
QEMU_PROTOCOL_VERSION,
|
QEMU_PROTOCOL_VERSION,
|
||||||
NULL,
|
qemuEvents,
|
||||||
0,
|
ARRAY_CARDINALITY(qemuEvents),
|
||||||
NULL)))
|
conn)))
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
if (virNetClientAddProgram(priv->client, priv->remoteProgram) < 0 ||
|
if (virNetClientAddProgram(priv->client, priv->remoteProgram) < 0 ||
|
||||||
@ -3175,6 +3188,103 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteConnectDomainQemuMonitorEventRegister(virConnectPtr conn,
|
||||||
|
virDomainPtr dom,
|
||||||
|
const char *event,
|
||||||
|
virConnectDomainQemuMonitorEventCallback callback,
|
||||||
|
void *opaque,
|
||||||
|
virFreeCallback freecb,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int rv = -1;
|
||||||
|
struct private_data *priv = conn->privateData;
|
||||||
|
qemu_connect_domain_monitor_event_register_args args;
|
||||||
|
qemu_connect_domain_monitor_event_register_ret ret;
|
||||||
|
int callbackID;
|
||||||
|
int count;
|
||||||
|
remote_nonnull_domain domain;
|
||||||
|
|
||||||
|
remoteDriverLock(priv);
|
||||||
|
|
||||||
|
if ((count = virDomainQemuMonitorEventStateRegisterID(conn,
|
||||||
|
priv->eventState,
|
||||||
|
dom, event, callback,
|
||||||
|
opaque, freecb, -1,
|
||||||
|
&callbackID)) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* If this is the first callback for this event, we need to enable
|
||||||
|
* events on the server */
|
||||||
|
if (count == 1) {
|
||||||
|
if (dom) {
|
||||||
|
make_nonnull_domain(&domain, dom);
|
||||||
|
args.dom = &domain;
|
||||||
|
} else {
|
||||||
|
args.dom = NULL;
|
||||||
|
}
|
||||||
|
args.event = event ? (char **) &event : NULL;
|
||||||
|
args.flags = flags;
|
||||||
|
|
||||||
|
memset(&ret, 0, sizeof(ret));
|
||||||
|
if (call(conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_REGISTER,
|
||||||
|
(xdrproc_t) xdr_qemu_connect_domain_monitor_event_register_args, (char *) &args,
|
||||||
|
(xdrproc_t) xdr_qemu_connect_domain_monitor_event_register_ret, (char *) &ret) == -1) {
|
||||||
|
virObjectEventStateDeregisterID(conn, priv->eventState,
|
||||||
|
callbackID);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
virObjectEventStateSetRemote(conn, priv->eventState, callbackID,
|
||||||
|
ret.callbackID);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = callbackID;
|
||||||
|
|
||||||
|
done:
|
||||||
|
remoteDriverUnlock(priv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
remoteConnectDomainQemuMonitorEventDeregister(virConnectPtr conn,
|
||||||
|
int callbackID)
|
||||||
|
{
|
||||||
|
struct private_data *priv = conn->privateData;
|
||||||
|
int rv = -1;
|
||||||
|
qemu_connect_domain_monitor_event_deregister_args args;
|
||||||
|
int remoteID;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
remoteDriverLock(priv);
|
||||||
|
|
||||||
|
if (virObjectEventStateEventID(conn, priv->eventState,
|
||||||
|
callbackID, &remoteID) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if ((count = virObjectEventStateDeregisterID(conn, priv->eventState,
|
||||||
|
callbackID)) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* If that was the last callback for this event, we need to disable
|
||||||
|
* events on the server */
|
||||||
|
if (count == 0) {
|
||||||
|
args.callbackID = remoteID;
|
||||||
|
|
||||||
|
if (call(conn, priv, REMOTE_CALL_QEMU, QEMU_PROC_CONNECT_DOMAIN_MONITOR_EVENT_DEREGISTER,
|
||||||
|
(xdrproc_t) xdr_qemu_connect_domain_monitor_event_deregister_args, (char *) &args,
|
||||||
|
(xdrproc_t) xdr_void, (char *) NULL) == -1)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
remoteDriverUnlock(priv);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
remoteConnectListAllInterfaces(virConnectPtr conn,
|
remoteConnectListAllInterfaces(virConnectPtr conn,
|
||||||
virInterfacePtr **ifaces,
|
virInterfacePtr **ifaces,
|
||||||
@ -5410,6 +5520,31 @@ remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
remoteDomainBuildQemuMonitorEvent(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
||||||
|
virNetClientPtr client ATTRIBUTE_UNUSED,
|
||||||
|
void *evdata, void *opaque)
|
||||||
|
{
|
||||||
|
virConnectPtr conn = opaque;
|
||||||
|
struct private_data *priv = conn->privateData;
|
||||||
|
qemu_domain_monitor_event_msg *msg = evdata;
|
||||||
|
virDomainPtr dom;
|
||||||
|
virObjectEventPtr event = NULL;
|
||||||
|
|
||||||
|
dom = get_nonnull_domain(conn, msg->dom);
|
||||||
|
if (!dom)
|
||||||
|
return;
|
||||||
|
|
||||||
|
event = virDomainQemuMonitorEventNew(dom->id, dom->name, dom->uuid,
|
||||||
|
msg->event, msg->seconds,
|
||||||
|
msg->micros,
|
||||||
|
msg->details ? *msg->details : NULL);
|
||||||
|
virDomainFree(dom);
|
||||||
|
|
||||||
|
remoteEventQueue(priv, event, msg->callbackID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static virDrvOpenStatus ATTRIBUTE_NONNULL(1)
|
static virDrvOpenStatus ATTRIBUTE_NONNULL(1)
|
||||||
remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
@ -7620,6 +7755,8 @@ static virDriver remote_driver = {
|
|||||||
.domainQemuMonitorCommand = remoteDomainQemuMonitorCommand, /* 0.8.3 */
|
.domainQemuMonitorCommand = remoteDomainQemuMonitorCommand, /* 0.8.3 */
|
||||||
.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 */
|
||||||
|
.connectDomainQemuMonitorEventDeregister = remoteConnectDomainQemuMonitorEventDeregister, /* 1.2.3 */
|
||||||
.domainOpenConsole = remoteDomainOpenConsole, /* 0.8.6 */
|
.domainOpenConsole = remoteDomainOpenConsole, /* 0.8.6 */
|
||||||
.domainOpenChannel = remoteDomainOpenChannel, /* 1.0.2 */
|
.domainOpenChannel = remoteDomainOpenChannel, /* 1.0.2 */
|
||||||
.domainOpenGraphics = remoteDomainOpenGraphics, /* 0.9.7 */
|
.domainOpenGraphics = remoteDomainOpenGraphics, /* 0.9.7 */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
#
|
#
|
||||||
# Copyright (C) 2010-2013 Red Hat, Inc.
|
# Copyright (C) 2010-2014 Red Hat, Inc.
|
||||||
#
|
#
|
||||||
# This library is free software; you can redistribute it and/or
|
# This library is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
# modify it under the terms of the GNU Lesser General Public
|
||||||
@ -927,8 +927,9 @@ elsif ($mode eq "server") {
|
|||||||
push(@args_list, "priv->conn");
|
push(@args_list, "priv->conn");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($structprefix eq "qemu" && $call->{ProcName} =~ /^Domain/) {
|
if ($structprefix eq "qemu" &&
|
||||||
$proc_name =~ s/^(Domain)/${1}Qemu/;
|
$call->{ProcName} =~ /^(Connect)?Domain/) {
|
||||||
|
$proc_name =~ s/^((Connect)?Domain)/${1}Qemu/;
|
||||||
}
|
}
|
||||||
if ($structprefix eq "lxc" && $call->{ProcName} =~ /^Domain/) {
|
if ($structprefix eq "lxc" && $call->{ProcName} =~ /^Domain/) {
|
||||||
$proc_name =~ s/^(Domain)/${1}Lxc/;
|
$proc_name =~ s/^(Domain)/${1}Lxc/;
|
||||||
@ -1704,7 +1705,7 @@ elsif ($mode eq "client") {
|
|||||||
if ($mode eq "aclsym") {
|
if ($mode eq "aclsym") {
|
||||||
my $apiname = "vir" . $call->{ProcName};
|
my $apiname = "vir" . $call->{ProcName};
|
||||||
if ($structprefix eq "qemu") {
|
if ($structprefix eq "qemu") {
|
||||||
$apiname =~ s/virDomain/virDomainQemu/;
|
$apiname =~ s/(vir(Connect)?Domain)/${1}Qemu/;
|
||||||
} elsif ($structprefix eq "lxc") {
|
} elsif ($structprefix eq "lxc") {
|
||||||
$apiname =~ s/virDomain/virDomainLxc/;
|
$apiname =~ s/virDomain/virDomainLxc/;
|
||||||
}
|
}
|
||||||
@ -1744,7 +1745,7 @@ elsif ($mode eq "client") {
|
|||||||
|
|
||||||
my $apiname = "vir" . $call->{ProcName};
|
my $apiname = "vir" . $call->{ProcName};
|
||||||
if ($structprefix eq "qemu") {
|
if ($structprefix eq "qemu") {
|
||||||
$apiname =~ s/virDomain/virDomainQemu/;
|
$apiname =~ s/(vir(Connect)?Domain)/${1}Qemu/;
|
||||||
} elsif ($structprefix eq "lxc") {
|
} elsif ($structprefix eq "lxc") {
|
||||||
$apiname =~ s/virDomain/virDomainLxc/;
|
$apiname =~ s/virDomain/virDomainLxc/;
|
||||||
}
|
}
|
||||||
@ -1856,7 +1857,7 @@ elsif ($mode eq "client") {
|
|||||||
|
|
||||||
my $apiname = "vir" . $call->{ProcName};
|
my $apiname = "vir" . $call->{ProcName};
|
||||||
if ($structprefix eq "qemu") {
|
if ($structprefix eq "qemu") {
|
||||||
$apiname =~ s/virDomain/virDomainQemu/;
|
$apiname =~ s/(vir(Connect)?Domain)/${1}Qemu/;
|
||||||
} elsif ($structprefix eq "lxc") {
|
} elsif ($structprefix eq "lxc") {
|
||||||
$apiname =~ s/virDomain/virDomainLxc/;
|
$apiname =~ s/virDomain/virDomainLxc/;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user