On 09/23/2014 09:36 PM, John Ferlan wrote:
On 09/23/2014 02:46 PM, Pavel Hrdina wrote:
> This new event will use typedParameters to expose what has been actually
> updated and the reason is that we can in the future extend any tunable
> values or add new tunable values. With typedParameters we don't have to
> worry about creating some other events, we will just use this universal
> event to inform user about updates.
>
> Signed-off-by: Pavel Hrdina <phrdina(a)redhat.com>
> ---
>
> since v4:
> - changed cpu-tune to tunable in virsh-domain.c
> - added REMOTE_DOMAIN_EVENT_TUNABLE_MAX to limit maximal length of tunable
> event msg
>
> daemon/remote.c | 45 +++++++++++++++++++++
> include/libvirt/libvirt.h.in | 22 +++++++++++
> src/conf/domain_event.c | 93 ++++++++++++++++++++++++++++++++++++++++++++
> src/conf/domain_event.h | 9 +++++
> src/libvirt_private.syms | 2 +
> src/remote/remote_driver.c | 42 ++++++++++++++++++++
> src/remote/remote_protocol.x | 17 +++++++-
> src/remote_protocol-structs | 9 +++++
> tools/virsh-domain.c | 33 ++++++++++++++++
> 9 files changed, 271 insertions(+), 1 deletion(-)
>
> diff --git a/daemon/remote.c b/daemon/remote.c
> index daa4b60..ddd510c 100644
> --- a/daemon/remote.c
> +++ b/daemon/remote.c
> @@ -111,6 +111,13 @@ remoteDeserializeTypedParameters(remote_typed_param
*args_params_val,
> int *nparams);
>
> static int
> +remoteSerializeTypedParameters(virTypedParameterPtr params,
> + int nparams,
> + remote_typed_param **ret_params_val,
> + u_int *ret_params_len,
> + unsigned int flags);
> +
> +static int
> remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors,
> int nerrors,
> remote_domain_disk_error **ret_errors_val,
> @@ -969,6 +976,43 @@ remoteRelayDomainEventBlockJob2(virConnectPtr conn,
> }
>
>
> +static int
> +remoteRelayDomainEventTunable(virConnectPtr conn,
> + virDomainPtr dom,
> + virTypedParameterPtr params,
> + int nparams,
> + void *opaque)
> +{
> + daemonClientEventCallbackPtr callback = opaque;
> + remote_domain_event_callback_tunable_msg data;
> +
> + if (callback->callbackID < 0 ||
> + !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
> + return -1;
> +
> + VIR_DEBUG("Relaying domain tunable event %s %d, callback %d",
> + dom->name, dom->id, callback->callbackID);
> +
> + /* build return data */
> + memset(&data, 0, sizeof(data));
> + data.callbackID = callback->callbackID;
> + make_nonnull_domain(&data.dom, dom);
> +
> + if (remoteSerializeTypedParameters(params, nparams,
> + &data.params.params_val,
> + &data.params.params_len,
> + VIR_TYPED_PARAM_STRING_OKAY) < 0)
> + return -1;
> +
> + remoteDispatchObjectEventSend(callback->client, remoteProgram,
> + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE,
> +
(xdrproc_t)xdr_remote_domain_event_callback_tunable_msg,
> + &data);
> +
> + return 0;
> +}
> +
> +
> static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
> @@ -987,6 +1031,7 @@ static virConnectDomainEventGenericCallback
domainEventCallbacks[] = {
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventPMSuspendDisk),
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemoved),
> VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJob2),
> + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventTunable),
> };
>
> verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
> diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
> index 6371b7b..86be86f 100644
> --- a/include/libvirt/libvirt.h.in
> +++ b/include/libvirt/libvirt.h.in
> @@ -5203,6 +5203,27 @@ typedef void
(*virConnectDomainEventDeviceRemovedCallback)(virConnectPtr conn,
> const char *devAlias,
> void *opaque);
>
> +/**
> + * virConnectDomainEventTunableCallback:
> + * @conn: connection object
> + * @dom: domain on which the event occurred
> + * @params: changed tunable values stored as array of virTypedParameter
> + * @nparams: size of the array
> + * @opaque: application specified data
> + *
> + * This callback occurs when tunable values are updated. The params must not
> + * be freed in the callback handler as it's done internally after the callback
> + * handler is executed.
> + *
> + * The callback signature to use when registering for an event of type
> + * VIR_DOMAIN_EVENT_ID_TUNABLE with virConnectDomainEventRegisterAny()
> + */
> +typedef void (*virConnectDomainEventTunableCallback)(virConnectPtr conn,
> + virDomainPtr dom,
> + virTypedParameterPtr params,
> + int nparams,
> + void *opaque);
> +
>
> /**
> * VIR_DOMAIN_EVENT_CALLBACK:
> @@ -5238,6 +5259,7 @@ typedef enum {
> VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK = 14, /*
virConnectDomainEventPMSuspendDiskCallback */
> VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED = 15, /*
virConnectDomainEventDeviceRemovedCallback */
> VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2 = 16, /*
virConnectDomainEventBlockJobCallback */
> + VIR_DOMAIN_EVENT_ID_TUNABLE = 17, /* virConnectDomainEventTunableCallback
*/
>
> #ifdef VIR_ENUM_SENTINELS
> VIR_DOMAIN_EVENT_ID_LAST
> diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
> index 73ae289..bf187cd 100644
> --- a/src/conf/domain_event.c
> +++ b/src/conf/domain_event.c
> @@ -34,6 +34,7 @@
> #include "viralloc.h"
> #include "virerror.h"
> #include "virstring.h"
> +#include "virtypedparam.h"
>
> #define VIR_FROM_THIS VIR_FROM_NONE
>
> @@ -52,6 +53,7 @@ static virClassPtr virDomainEventBalloonChangeClass;
> static virClassPtr virDomainEventDeviceRemovedClass;
> static virClassPtr virDomainEventPMClass;
> static virClassPtr virDomainQemuMonitorEventClass;
> +static virClassPtr virDomainEventTunableClass;
>
>
> static void virDomainEventDispose(void *obj);
> @@ -67,6 +69,7 @@ static void virDomainEventBalloonChangeDispose(void *obj);
> static void virDomainEventDeviceRemovedDispose(void *obj);
> static void virDomainEventPMDispose(void *obj);
> static void virDomainQemuMonitorEventDispose(void *obj);
> +static void virDomainEventTunableDispose(void *obj);
>
> static void
> virDomainEventDispatchDefaultFunc(virConnectPtr conn,
> @@ -203,6 +206,15 @@ struct _virDomainQemuMonitorEvent {
> typedef struct _virDomainQemuMonitorEvent virDomainQemuMonitorEvent;
> typedef virDomainQemuMonitorEvent *virDomainQemuMonitorEventPtr;
>
> +struct _virDomainEventTunable {
> + virDomainEvent parent;
> +
> + virTypedParameterPtr params;
> + int nparams;
> +};
> +typedef struct _virDomainEventTunable virDomainEventTunable;
> +typedef virDomainEventTunable *virDomainEventTunablePtr;
> +
>
> static int
> virDomainEventsOnceInit(void)
> @@ -285,6 +297,12 @@ virDomainEventsOnceInit(void)
> sizeof(virDomainQemuMonitorEvent),
> virDomainQemuMonitorEventDispose)))
> return -1;
> + if (!(virDomainEventTunableClass =
> + virClassNew(virDomainEventClass,
> + "virDomainEventTunable",
> + sizeof(virDomainEventTunable),
> + virDomainEventTunableDispose)))
> + return -1;
> return 0;
> }
>
> @@ -420,6 +438,15 @@ virDomainQemuMonitorEventDispose(void *obj)
> VIR_FREE(event->details);
> }
>
> +static void
> +virDomainEventTunableDispose(void *obj)
> +{
> + virDomainEventTunablePtr event = obj;
> + VIR_DEBUG("obj=%p", event);
> +
> + virTypedParamsFree(event->params, event->nparams);
> +}
> +
>
> static void *
> virDomainEventNew(virClassPtr klass,
> @@ -1175,6 +1202,61 @@ virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
> devAlias);
> }
>
> +/* This function consumes the params so caller don't have to care about
> + * freeing it even if error occurs. The reason is to not have to do deep
> + * copy of params.
> + */
> +static virObjectEventPtr
> +virDomainEventTunableNew(int id,
> + const char *name,
> + unsigned char *uuid,
> + virTypedParameterPtr params,
> + int nparams)
> +{
> + virDomainEventTunablePtr ev;
> +
> + if (virDomainEventsInitialize() < 0)
> + goto error;
> +
> + if (!(ev = virDomainEventNew(virDomainEventTunableClass,
> + VIR_DOMAIN_EVENT_ID_TUNABLE,
> + id, name, uuid)))
> + goto error;
> +
> + ev->params = params;
> + ev->nparams = nparams;
> +
> + return (virObjectEventPtr)ev;
> +
> + error:
> + virTypedParamsFree(params, nparams);
> + return NULL;
> +}
> +
> +virObjectEventPtr
> +virDomainEventTunableNewFromObj(virDomainObjPtr obj,
> + virTypedParameterPtr params,
> + int nparams)
> +{
> + return virDomainEventTunableNew(obj->def->id,
> + obj->def->name,
> + obj->def->uuid,
> + params,
> + nparams);
> +}
> +
> +virObjectEventPtr
> +virDomainEventTunableNewFromDom(virDomainPtr dom,
> + virTypedParameterPtr params,
> + int nparams)
> +{
> + return virDomainEventTunableNew(dom->id,
> + dom->name,
> + dom->uuid,
> + params,
> + nparams);
> +}
> +
>
> static void
> virDomainEventDispatchDefaultFunc(virConnectPtr conn,
> @@ -1366,6 +1448,17 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
> goto cleanup;
> }
>
> + case VIR_DOMAIN_EVENT_ID_TUNABLE:
> + {
> + virDomainEventTunablePtr tunableEvent;
> + tunableEvent = (virDomainEventTunablePtr)event;
> + ((virConnectDomainEventTunableCallback)cb)(conn, dom,
> + tunableEvent->params,
> + tunableEvent->nparams,
> + cbopaque);
> + goto cleanup;
> + }
> +
> case VIR_DOMAIN_EVENT_ID_LAST:
> break;
> }
> diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
> index a3330ca..dc0109c 100644
> --- a/src/conf/domain_event.h
> +++ b/src/conf/domain_event.h
> @@ -184,6 +184,15 @@ virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj,
> virObjectEventPtr
> virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
> const char *devAlias);
> +virObjectEventPtr
> +virDomainEventTunableNewFromObj(virDomainObjPtr obj,
> + virTypedParameterPtr params,
> + int nparams);
> +virObjectEventPtr
> +virDomainEventTunableNewFromDom(virDomainPtr dom,
> + virTypedParameterPtr params,
> + int nparams);
> +
>
> int
> virDomainEventStateRegister(virConnectPtr conn,
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 51a692b..a339ced 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -473,6 +473,8 @@ virDomainEventStateRegister;
> virDomainEventStateRegisterID;
> virDomainEventTrayChangeNewFromDom;
> virDomainEventTrayChangeNewFromObj;
> +virDomainEventTunableNewFromDom;
> +virDomainEventTunableNewFromObj;
> virDomainEventWatchdogNewFromDom;
> virDomainEventWatchdogNewFromObj;
> virDomainQemuMonitorEventNew;
> diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
> index 75a3a7b..79e3fd4 100644
> --- a/src/remote/remote_driver.c
> +++ b/src/remote/remote_driver.c
> @@ -331,6 +331,11 @@ remoteDomainBuildEventBlockJob2(virNetClientProgramPtr prog,
> void *evdata, void *opaque);
>
> static void
> +remoteDomainBuildEventCallbackTunable(virNetClientProgramPtr prog,
> + virNetClientPtr client,
> + void *evdata, void *opaque);
> +
> +static void
> remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> virNetClientPtr client ATTRIBUTE_UNUSED,
> void *evdata, void *opaque);
> @@ -481,6 +486,10 @@ static virNetClientProgramEvent remoteEvents[] = {
> remoteDomainBuildEventBlockJob2,
> sizeof(remote_domain_event_block_job_2_msg),
> (xdrproc_t)xdr_remote_domain_event_block_job_2_msg },
> + { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE,
> + remoteDomainBuildEventCallbackTunable,
> + sizeof(remote_domain_event_callback_tunable_msg),
> + (xdrproc_t)xdr_remote_domain_event_callback_tunable_msg },
> };
>
>
> @@ -5514,6 +5523,39 @@
remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgramPtr prog ATTRIBUT
>
>
> static void
> +remoteDomainBuildEventCallbackTunable(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> + virNetClientPtr client ATTRIBUTE_UNUSED,
> + void *evdata, void *opaque)
> +{
> + virConnectPtr conn = opaque;
> + remote_domain_event_callback_tunable_msg *msg = evdata;
> + struct private_data *priv = conn->privateData;
> + virDomainPtr dom;
> + virTypedParameterPtr params = NULL;
> + int nparams = 0;
> + virObjectEventPtr event = NULL;
> +
> + if (remoteDeserializeTypedParameters(msg->params.params_val,
> + msg->params.params_len,
> + REMOTE_CPUMAPS_MAX,
s/REMOTE_CPUMAPS_MAX/REMOTE_DOMAIN_EVENT_TUNABLE_MAX
ACK w/ that.
Ouch, thanks for caching it. Pushed,
Pavel
John
> + ¶ms, &nparams) < 0)
> + return;
> +
> + dom = get_nonnull_domain(conn, msg->dom);
> + if (!dom) {
> + virTypedParamsFree(params, nparams);
> + return;
> + }
> +
> + event = virDomainEventTunableNewFromDom(dom, params, nparams);
> +
> + virDomainFree(dom);
> +
> + remoteEventQueue(priv, event, msg->callbackID);
> +}
> +
> +
> +static void
> remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
> virNetClientPtr client ATTRIBUTE_UNUSED,
> void *evdata, void *opaque)
> diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
> index a4ca0c3..0c6a91e 100644
> --- a/src/remote/remote_protocol.x
> +++ b/src/remote/remote_protocol.x
> @@ -247,6 +247,9 @@ const REMOTE_NETWORK_DHCP_LEASES_MAX = 65536;
> /* Upper limit on count of parameters returned via bulk stats API */
> const REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX = 4096;
>
> +/* Upper limit of message size for tunable event. */
> +const REMOTE_DOMAIN_EVENT_TUNABLE_MAX = 8388608;
> +
> /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
> typedef opaque remote_uuid[VIR_UUID_BUFLEN];
>
> @@ -2990,6 +2993,12 @@ struct remote_domain_event_block_job_2_msg {
> int status;
> };
>
> +struct remote_domain_event_callback_tunable_msg {
> + int callbackID;
> + remote_nonnull_domain dom;
> + remote_typed_param params<REMOTE_DOMAIN_EVENT_TUNABLE_MAX>;
> +};
> +
> struct remote_connect_get_cpu_model_names_args {
> remote_nonnull_string arch;
> int need_results;
> @@ -5472,5 +5481,11 @@ enum remote_procedure {
> * @generate: both
> * @acl: domain:block_write
> */
> - REMOTE_PROC_DOMAIN_BLOCK_COPY = 345
> + REMOTE_PROC_DOMAIN_BLOCK_COPY = 345,
> +
> + /**
> + * @generate: both
> + * @acl: none
> + */
> + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE = 346
> };
> diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
> index e960415..6128a85 100644
> --- a/src/remote_protocol-structs
> +++ b/src/remote_protocol-structs
> @@ -2445,6 +2445,14 @@ struct remote_domain_event_block_job_2_msg {
> int type;
> int status;
> };
> +struct remote_domain_event_callback_tunable_msg {
> + int callbackID;
> + remote_nonnull_domain dom;
> + struct {
> + u_int params_len;
> + remote_typed_param * params_val;
> + } params;
> +};
> struct remote_connect_get_cpu_model_names_args {
> remote_nonnull_string arch;
> int need_results;
> @@ -2901,4 +2909,5 @@ enum remote_procedure {
> REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD = 343,
> REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344,
> REMOTE_PROC_DOMAIN_BLOCK_COPY = 345,
> + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE = 346,
> };
> diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
> index a6ced5f..ce59406 100644
> --- a/tools/virsh-domain.c
> +++ b/tools/virsh-domain.c
> @@ -11454,6 +11454,37 @@ vshEventDeviceRemovedPrint(virConnectPtr conn
ATTRIBUTE_UNUSED,
> vshEventDone(data->ctl);
> }
>
> +static void
> +vshEventTunablePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
> + virDomainPtr dom,
> + virTypedParameterPtr params,
> + int nparams,
> + void *opaque)
> +{
> + vshDomEventData *data = opaque;
> + size_t i;
> + char *value = NULL;
> +
> + if (!data->loop && *data->count)
> + return;
> +
> + vshPrint(data->ctl,
> + _("event 'tunable' for domain %s:\n"),
> + virDomainGetName(dom));
> +
> + for (i = 0; i < nparams; i++) {
> + value = virTypedParameterToString(¶ms[i]);
> + if (value) {
> + vshPrint(data->ctl, _("\t%s: %s\n"), params[i].field,
value);
> + VIR_FREE(value);
> + }
> + }
> +
> + (*data->count)++;
> + if (!data->loop)
> + vshEventDone(data->ctl);
> +}
> +
> static vshEventCallback vshEventCallbacks[] = {
> { "lifecycle",
> VIR_DOMAIN_EVENT_CALLBACK(vshEventLifecyclePrint), },
> @@ -11487,6 +11518,8 @@ static vshEventCallback vshEventCallbacks[] = {
> VIR_DOMAIN_EVENT_CALLBACK(vshEventDeviceRemovedPrint), },
> { "block-job-2",
> VIR_DOMAIN_EVENT_CALLBACK(vshEventBlockJobPrint), },
> + { "tunable",
> + VIR_DOMAIN_EVENT_CALLBACK(vshEventTunablePrint), },
> };
> verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
>
>