mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
Define public API for receiving guest memory balloon events
When the guest changes its memory balloon applications may want to know what the new value is, without having to periodically poll on XML / domain info. Introduce a "balloon change" event to let apps see this * include/libvirt/libvirt.h.in: Define the virConnectDomainEventBalloonChangeCallback callback and VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE constant * python/libvirt-override-virConnect.py, python/libvirt-override.c: Wire up helpers for new event * daemon/remote.c: Helper for serializing balloon event * examples/domain-events/events-c/event-test.c, examples/domain-events/events-python/event-test.py: Add example of balloon event usage * src/conf/domain_event.c, src/conf/domain_event.h: Handling of balloon events * src/remote/remote_driver.c: Add handler of balloon events * src/remote/remote_protocol.x: Define wire protocol for balloon events * src/remote_protocol-structs: Likewise. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
db4eba91a7
commit
7ed6d7dda7
@ -582,6 +582,33 @@ static int remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virDomainPtr dom,
|
||||
unsigned long long actual,
|
||||
void *opaque)
|
||||
{
|
||||
virNetServerClientPtr client = opaque;
|
||||
remote_domain_event_balloon_change_msg data;
|
||||
|
||||
if (!client)
|
||||
return -1;
|
||||
|
||||
VIR_DEBUG("Relaying domain balloon change event %s %d %lld", dom->name, dom->id, actual);
|
||||
|
||||
/* build return data */
|
||||
memset(&data, 0, sizeof(data));
|
||||
make_nonnull_domain(&data.dom, dom);
|
||||
data.actual = actual;
|
||||
|
||||
remoteDispatchDomainEventSend(client, remoteProgram,
|
||||
REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE,
|
||||
(xdrproc_t)xdr_remote_domain_event_balloon_change_msg, &data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
|
||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
|
||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
|
||||
@ -596,6 +623,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
|
||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventTrayChange),
|
||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventPMWakeup),
|
||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventPMSuspend),
|
||||
VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBalloonChange),
|
||||
};
|
||||
|
||||
verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <libvirt/libvirt.h>
|
||||
#include <libvirt/virterror.h>
|
||||
@ -222,6 +223,17 @@ static int myDomainEventRTCChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int myDomainEventBalloonChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virDomainPtr dom,
|
||||
unsigned long long actual,
|
||||
void *opaque ATTRIBUTE_UNUSED)
|
||||
{
|
||||
printf("%s EVENT: Domain %s(%d) balloon change %" PRIuMAX "KB\n",
|
||||
__func__, virDomainGetName(dom), virDomainGetID(dom), (uintmax_t)actual);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int myDomainEventWatchdogCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virDomainPtr dom,
|
||||
int action,
|
||||
@ -391,6 +403,7 @@ int main(int argc, char **argv)
|
||||
int callback10ret = -1;
|
||||
int callback11ret = -1;
|
||||
int callback12ret = -1;
|
||||
int callback13ret = -1;
|
||||
struct sigaction action_stop;
|
||||
|
||||
memset(&action_stop, 0, sizeof(action_stop));
|
||||
@ -476,6 +489,11 @@ int main(int argc, char **argv)
|
||||
VIR_DOMAIN_EVENT_ID_PMSUSPEND,
|
||||
VIR_DOMAIN_EVENT_CALLBACK(myDomainEventPMSuspendCallback),
|
||||
strdup("pmsuspend"), myFreeFunc);
|
||||
callback13ret = virConnectDomainEventRegisterAny(dconn,
|
||||
NULL,
|
||||
VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE,
|
||||
VIR_DOMAIN_EVENT_CALLBACK(myDomainEventBalloonChangeCallback),
|
||||
strdup("callback balloonchange"), myFreeFunc);
|
||||
if ((callback1ret != -1) &&
|
||||
(callback2ret != -1) &&
|
||||
(callback3ret != -1) &&
|
||||
@ -486,7 +504,8 @@ int main(int argc, char **argv)
|
||||
(callback9ret != -1) &&
|
||||
(callback10ret != -1) &&
|
||||
(callback11ret != -1) &&
|
||||
(callback12ret != -1)) {
|
||||
(callback12ret != -1) &&
|
||||
(callback13ret != -1)) {
|
||||
if (virConnectSetKeepAlive(dconn, 5, 3) < 0) {
|
||||
virErrorPtr err = virGetLastError();
|
||||
fprintf(stderr, "Failed to start keepalive protocol: %s\n",
|
||||
@ -514,6 +533,7 @@ int main(int argc, char **argv)
|
||||
virConnectDomainEventDeregisterAny(dconn, callback10ret);
|
||||
virConnectDomainEventDeregisterAny(dconn, callback11ret);
|
||||
virConnectDomainEventDeregisterAny(dconn, callback12ret);
|
||||
virConnectDomainEventDeregisterAny(dconn, callback13ret);
|
||||
if (callback8ret != -1)
|
||||
virConnectDomainEventDeregisterAny(dconn, callback8ret);
|
||||
}
|
||||
|
@ -483,6 +483,8 @@ def myDomainEventPMWakeupCallback(conn, dom, reason, opaque):
|
||||
def myDomainEventPMSuspendCallback(conn, dom, reason, opaque):
|
||||
print "myDomainEventPMSuspendCallback: Domain %s(%s) system pmsuspend" % (
|
||||
dom.name(), dom.ID())
|
||||
def myDomainEventBalloonChangeCallback(conn, dom, utcoffset, actual):
|
||||
print "myDomainEventBalloonChangeCallback: Domain %s(%s) %d" % (dom.name(), dom.ID(), actual)
|
||||
def usage(out=sys.stderr):
|
||||
print >>out, "usage: "+os.path.basename(sys.argv[0])+" [-hdl] [uri]"
|
||||
print >>out, " uri will default to qemu:///system"
|
||||
@ -544,6 +546,7 @@ def main():
|
||||
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_TRAY_CHANGE, myDomainEventTrayChangeCallback, None)
|
||||
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_PMWAKEUP, myDomainEventPMWakeupCallback, None)
|
||||
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_PMSUSPEND, myDomainEventPMSuspendCallback, None)
|
||||
vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE, myDomainEventBalloonChangeCallback, None)
|
||||
|
||||
vc.setKeepAlive(5, 3)
|
||||
|
||||
|
@ -3861,6 +3861,22 @@ typedef void (*virConnectDomainEventPMSuspendCallback)(virConnectPtr conn,
|
||||
int reason,
|
||||
void *opaque);
|
||||
|
||||
|
||||
/**
|
||||
* virConnectDomainEventBalloonChangeCallback:
|
||||
* @conn: connection object
|
||||
* @dom: domain on which the event occurred
|
||||
* @actual: the new balloon level measured in kibibytes(blocks of 1024 bytes)
|
||||
* @opaque: application specified data
|
||||
*
|
||||
* The callback signature to use when registering for an event of type
|
||||
* VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE with virConnectDomainEventRegisterAny()
|
||||
*/
|
||||
typedef void (*virConnectDomainEventBalloonChangeCallback)(virConnectPtr conn,
|
||||
virDomainPtr dom,
|
||||
unsigned long long actual,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* VIR_DOMAIN_EVENT_CALLBACK:
|
||||
*
|
||||
@ -3884,6 +3900,7 @@ typedef enum {
|
||||
VIR_DOMAIN_EVENT_ID_TRAY_CHANGE = 10, /* virConnectDomainEventTrayChangeCallback */
|
||||
VIR_DOMAIN_EVENT_ID_PMWAKEUP = 11, /* virConnectDomainEventPMWakeupCallback */
|
||||
VIR_DOMAIN_EVENT_ID_PMSUSPEND = 12, /* virConnectDomainEventPMSuspendCallback */
|
||||
VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE = 13, /* virConnectDomainEventBalloonChangeCallback */
|
||||
|
||||
#ifdef VIR_ENUM_SENTINELS
|
||||
/*
|
||||
|
@ -161,6 +161,15 @@
|
||||
cb(self, virDomain(self, _obj=dom), reason, opaque)
|
||||
return 0;
|
||||
|
||||
def _dispatchDomainEventBalloonChangeCallback(self, dom, actual, cbData):
|
||||
"""Dispatches events to python user domain balloon change event callbacks
|
||||
"""
|
||||
cb = cbData["cb"]
|
||||
opaque = cbData["opaque"]
|
||||
|
||||
cb(self, virDomain(self, _obj=dom), actual, opaque)
|
||||
return 0
|
||||
|
||||
def domainEventDeregisterAny(self, callbackID):
|
||||
"""Removes a Domain Event Callback. De-registering for a
|
||||
domain callback will disable delivery of this event type """
|
||||
|
@ -5352,6 +5352,53 @@ libvirt_virConnectDomainEventPMSuspendCallback(virConnectPtr conn ATTRIBUTE_UNUS
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
libvirt_virConnectDomainEventBalloonChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
|
||||
virDomainPtr dom,
|
||||
unsigned long long actual,
|
||||
void *opaque)
|
||||
{
|
||||
PyObject *pyobj_cbData = (PyObject*)opaque;
|
||||
PyObject *pyobj_dom;
|
||||
PyObject *pyobj_ret;
|
||||
PyObject *pyobj_conn;
|
||||
PyObject *dictKey;
|
||||
int ret = -1;
|
||||
|
||||
LIBVIRT_ENSURE_THREAD_STATE;
|
||||
|
||||
/* Create a python instance of this virDomainPtr */
|
||||
virDomainRef(dom);
|
||||
pyobj_dom = libvirt_virDomainPtrWrap(dom);
|
||||
Py_INCREF(pyobj_cbData);
|
||||
|
||||
dictKey = libvirt_constcharPtrWrap("conn");
|
||||
pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
|
||||
Py_DECREF(dictKey);
|
||||
|
||||
/* Call the Callback Dispatcher */
|
||||
pyobj_ret = PyObject_CallMethod(pyobj_conn,
|
||||
(char*)"_dispatchDomainEventBalloonChangeCallback",
|
||||
(char*)"OLO",
|
||||
pyobj_dom,
|
||||
(PY_LONG_LONG)actual,
|
||||
pyobj_cbData);
|
||||
|
||||
Py_DECREF(pyobj_cbData);
|
||||
Py_DECREF(pyobj_dom);
|
||||
|
||||
if(!pyobj_ret) {
|
||||
DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
|
||||
PyErr_Print();
|
||||
} else {
|
||||
Py_DECREF(pyobj_ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
LIBVIRT_RELEASE_THREAD_STATE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
|
||||
PyObject * args)
|
||||
@ -5421,6 +5468,9 @@ libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
|
||||
case VIR_DOMAIN_EVENT_ID_PMSUSPEND:
|
||||
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventPMSuspendCallback);
|
||||
break;
|
||||
case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE:
|
||||
cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventBalloonChangeCallback);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cb) {
|
||||
|
@ -121,6 +121,10 @@ struct _virDomainEvent {
|
||||
char *devAlias;
|
||||
int reason;
|
||||
} trayChange;
|
||||
struct {
|
||||
/* In unit of 1024 bytes */
|
||||
unsigned long long actual;
|
||||
} balloonChange;
|
||||
} data;
|
||||
};
|
||||
|
||||
@ -1109,6 +1113,31 @@ virDomainEventPMSuspendNewFromDom(virDomainPtr dom)
|
||||
return virDomainEventPMSuspendNew(dom->id, dom->name, dom->uuid);
|
||||
}
|
||||
|
||||
virDomainEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom,
|
||||
unsigned long long actual)
|
||||
{
|
||||
virDomainEventPtr ev =
|
||||
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE,
|
||||
dom->id, dom->name, dom->uuid);
|
||||
|
||||
if (ev)
|
||||
ev->data.balloonChange.actual = actual;
|
||||
|
||||
return ev;
|
||||
}
|
||||
virDomainEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj,
|
||||
unsigned long long actual)
|
||||
{
|
||||
virDomainEventPtr ev =
|
||||
virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE,
|
||||
obj->def->id, obj->def->name, obj->def->uuid);
|
||||
|
||||
if (ev)
|
||||
ev->data.balloonChange.actual = actual;
|
||||
|
||||
return ev;
|
||||
}
|
||||
|
||||
/**
|
||||
* virDomainEventQueuePush:
|
||||
* @evtQueue: the dom event queue
|
||||
@ -1247,6 +1276,12 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
|
||||
((virConnectDomainEventPMSuspendCallback)cb)(conn, dom, 0, cbopaque);
|
||||
break;
|
||||
|
||||
case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE:
|
||||
((virConnectDomainEventBalloonChangeCallback)cb)(conn, dom,
|
||||
event->data.balloonChange.actual,
|
||||
cbopaque);
|
||||
break;
|
||||
|
||||
default:
|
||||
VIR_WARN("Unexpected event ID %d", event->eventID);
|
||||
break;
|
||||
|
@ -125,6 +125,9 @@ virDomainEventPtr virDomainEventPMWakeupNewFromDom(virDomainPtr dom);
|
||||
virDomainEventPtr virDomainEventPMSuspendNewFromObj(virDomainObjPtr obj);
|
||||
virDomainEventPtr virDomainEventPMSuspendNewFromDom(virDomainPtr dom);
|
||||
|
||||
virDomainEventPtr virDomainEventBalloonChangeNewFromDom(virDomainPtr dom, unsigned long long actual);
|
||||
virDomainEventPtr virDomainEventBalloonChangeNewFromObj(virDomainObjPtr obj, unsigned long long actual);
|
||||
|
||||
void virDomainEventFree(virDomainEventPtr event);
|
||||
|
||||
void virDomainEventStateFree(virDomainEventStatePtr state);
|
||||
|
@ -500,6 +500,8 @@ virDomainWatchdogModelTypeToString;
|
||||
|
||||
|
||||
# domain_event.h
|
||||
virDomainEventBalloonChangeNewFromDom;
|
||||
virDomainEventBalloonChangeNewFromObj;
|
||||
virDomainEventBlockJobNewFromObj;
|
||||
virDomainEventBlockJobNewFromDom;
|
||||
virDomainEventControlErrorNewFromDom;
|
||||
|
@ -253,6 +253,10 @@ static void
|
||||
remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog,
|
||||
virNetClientPtr client,
|
||||
void *evdata, void *opaque);
|
||||
static void
|
||||
remoteDomainBuildEventBalloonChange(virNetClientProgramPtr prog,
|
||||
virNetClientPtr client,
|
||||
void *evdata, void *opaque);
|
||||
|
||||
static virNetClientProgramEvent remoteDomainEvents[] = {
|
||||
{ REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE,
|
||||
@ -307,6 +311,10 @@ static virNetClientProgramEvent remoteDomainEvents[] = {
|
||||
remoteDomainBuildEventPMSuspend,
|
||||
sizeof(remote_domain_event_pmsuspend_msg),
|
||||
(xdrproc_t)xdr_remote_domain_event_pmsuspend_msg },
|
||||
{ REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE,
|
||||
remoteDomainBuildEventBalloonChange,
|
||||
sizeof(remote_domain_event_balloon_change_msg),
|
||||
(xdrproc_t)xdr_remote_domain_event_balloon_change_msg },
|
||||
};
|
||||
|
||||
enum virDrvOpenRemoteFlags {
|
||||
@ -3889,6 +3897,29 @@ remoteDomainBuildEventPMSuspend(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
||||
remoteDomainEventQueue(priv, event);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
remoteDomainBuildEventBalloonChange(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
|
||||
virNetClientPtr client ATTRIBUTE_UNUSED,
|
||||
void *evdata, void *opaque)
|
||||
{
|
||||
virConnectPtr conn = opaque;
|
||||
struct private_data *priv = conn->privateData;
|
||||
remote_domain_event_balloon_change_msg *msg = evdata;
|
||||
virDomainPtr dom;
|
||||
virDomainEventPtr event = NULL;
|
||||
|
||||
dom = get_nonnull_domain(conn, msg->dom);
|
||||
if (!dom)
|
||||
return;
|
||||
|
||||
event = virDomainEventBalloonChangeNewFromDom(dom, msg->actual);
|
||||
virDomainFree(dom);
|
||||
|
||||
remoteDomainEventQueue(priv, event);
|
||||
}
|
||||
|
||||
|
||||
static virDrvOpenStatus ATTRIBUTE_NONNULL (1)
|
||||
remoteSecretOpen(virConnectPtr conn, virConnectAuthPtr auth,
|
||||
unsigned int flags)
|
||||
|
@ -2192,6 +2192,11 @@ struct remote_domain_event_pmsuspend_msg {
|
||||
remote_nonnull_domain dom;
|
||||
};
|
||||
|
||||
struct remote_domain_event_balloon_change_msg {
|
||||
remote_nonnull_domain dom;
|
||||
unsigned hyper actual;
|
||||
};
|
||||
|
||||
struct remote_domain_managed_save_args {
|
||||
remote_nonnull_domain dom;
|
||||
unsigned int flags;
|
||||
@ -2838,7 +2843,8 @@ enum remote_procedure {
|
||||
REMOTE_PROC_DOMAIN_SNAPSHOT_HAS_METADATA = 272, /* autogen autogen */
|
||||
REMOTE_PROC_CONNECT_LIST_ALL_DOMAINS = 273, /* skipgen skipgen priority:high */
|
||||
REMOTE_PROC_DOMAIN_LIST_ALL_SNAPSHOTS = 274, /* skipgen skipgen priority:high */
|
||||
REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275 /* skipgen skipgen priority:high */
|
||||
REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275, /* skipgen skipgen priority:high */
|
||||
REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE = 276 /* autogen autogen */
|
||||
|
||||
/*
|
||||
* Notice how the entries are grouped in sets of 10 ?
|
||||
|
@ -1661,6 +1661,10 @@ struct remote_domain_event_pmwakeup_msg {
|
||||
struct remote_domain_event_pmsuspend_msg {
|
||||
remote_nonnull_domain dom;
|
||||
};
|
||||
struct remote_domain_event_balloon_change_msg {
|
||||
remote_nonnull_domain dom;
|
||||
uint64_t actual;
|
||||
};
|
||||
struct remote_domain_managed_save_args {
|
||||
remote_nonnull_domain dom;
|
||||
u_int flags;
|
||||
@ -2246,4 +2250,5 @@ enum remote_procedure {
|
||||
REMOTE_PROC_CONNECT_LIST_ALL_DOMAINS = 273,
|
||||
REMOTE_PROC_DOMAIN_LIST_ALL_SNAPSHOTS = 274,
|
||||
REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275,
|
||||
REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE = 276,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user