render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
9119d9
From c4dcb385ad24712b6bd474d0ac0fec22f1978657 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <c4dcb385ad24712b6bd474d0ac0fec22f1978657@dist-git>
9119d9
From: Pavel Hrdina <phrdina@redhat.com>
9119d9
Date: Fri, 26 Sep 2014 12:43:55 +0200
9119d9
Subject: [PATCH] event: introduce new event for tunable values
9119d9
9119d9
This new event will use typedParameters to expose what has been actually
9119d9
updated and the reason is that we can in the future extend any tunable
9119d9
values or add new tunable values. With typedParameters we don't have to
9119d9
worry about creating some other events, we will just use this universal
9119d9
event to inform user about updates.
9119d9
9119d9
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
9119d9
(cherry picked from commit e426718129a91f80cfbe7261196da6945376db5c)
9119d9
9119d9
Conflicts:
9119d9
	src/remote/remote_protocol.x: Context as 1069e3b9 is not
9119d9
            backported yet.
9119d9
	src/remote_protocol-structs: Context as 1069e3b9 is not
9119d9
            backported yet.
9119d9
9119d9
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1115898
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 daemon/remote.c              | 45 +++++++++++++++++++++
9119d9
 include/libvirt/libvirt.h.in | 22 +++++++++++
9119d9
 src/conf/domain_event.c      | 93 ++++++++++++++++++++++++++++++++++++++++++++
9119d9
 src/conf/domain_event.h      |  9 +++++
9119d9
 src/libvirt_private.syms     |  2 +
9119d9
 src/remote/remote_driver.c   | 42 ++++++++++++++++++++
9119d9
 src/remote/remote_protocol.x | 17 +++++++-
9119d9
 src/remote_protocol-structs  |  9 +++++
9119d9
 tools/virsh-domain.c         | 33 ++++++++++++++++
9119d9
 9 files changed, 271 insertions(+), 1 deletion(-)
9119d9
9119d9
diff --git a/daemon/remote.c b/daemon/remote.c
9119d9
index 89714ca..fc43c69 100644
9119d9
--- a/daemon/remote.c
9119d9
+++ b/daemon/remote.c
9119d9
@@ -111,6 +111,13 @@ remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
9119d9
                                  int *nparams);
9119d9
 
9119d9
 static int
9119d9
+remoteSerializeTypedParameters(virTypedParameterPtr params,
9119d9
+                               int nparams,
9119d9
+                               remote_typed_param **ret_params_val,
9119d9
+                               u_int *ret_params_len,
9119d9
+                               unsigned int flags);
9119d9
+
9119d9
+static int
9119d9
 remoteSerializeDomainDiskErrors(virDomainDiskErrorPtr errors,
9119d9
                                 int nerrors,
9119d9
                                 remote_domain_disk_error **ret_errors_val,
9119d9
@@ -969,6 +976,43 @@ remoteRelayDomainEventBlockJob2(virConnectPtr conn,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+static int
9119d9
+remoteRelayDomainEventTunable(virConnectPtr conn,
9119d9
+                              virDomainPtr dom,
9119d9
+                              virTypedParameterPtr params,
9119d9
+                              int nparams,
9119d9
+                              void *opaque)
9119d9
+{
9119d9
+    daemonClientEventCallbackPtr callback = opaque;
9119d9
+    remote_domain_event_callback_tunable_msg data;
9119d9
+
9119d9
+    if (callback->callbackID < 0 ||
9119d9
+        !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
9119d9
+        return -1;
9119d9
+
9119d9
+    VIR_DEBUG("Relaying domain tunable event %s %d, callback %d",
9119d9
+              dom->name, dom->id, callback->callbackID);
9119d9
+
9119d9
+    /* build return data */
9119d9
+    memset(&data, 0, sizeof(data));
9119d9
+    data.callbackID = callback->callbackID;
9119d9
+    make_nonnull_domain(&data.dom, dom);
9119d9
+
9119d9
+    if (remoteSerializeTypedParameters(params, nparams,
9119d9
+                                       &data.params.params_val,
9119d9
+                                       &data.params.params_len,
9119d9
+                                       VIR_TYPED_PARAM_STRING_OKAY) < 0)
9119d9
+        return -1;
9119d9
+
9119d9
+    remoteDispatchObjectEventSend(callback->client, remoteProgram,
9119d9
+                                  REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE,
9119d9
+                                  (xdrproc_t)xdr_remote_domain_event_callback_tunable_msg,
9119d9
+                                  &data);
9119d9
+
9119d9
+    return 0;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
9119d9
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
9119d9
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
9119d9
@@ -987,6 +1031,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
9119d9
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventPMSuspendDisk),
9119d9
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemoved),
9119d9
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJob2),
9119d9
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventTunable),
9119d9
 };
9119d9
 
9119d9
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
9119d9
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
9119d9
index 0b40727..56c665c 100644
9119d9
--- a/include/libvirt/libvirt.h.in
9119d9
+++ b/include/libvirt/libvirt.h.in
9119d9
@@ -5167,6 +5167,27 @@ typedef void (*virConnectDomainEventDeviceRemovedCallback)(virConnectPtr conn,
9119d9
                                                            const char *devAlias,
9119d9
                                                            void *opaque);
9119d9
 
9119d9
+/**
9119d9
+ * virConnectDomainEventTunableCallback:
9119d9
+ * @conn: connection object
9119d9
+ * @dom: domain on which the event occurred
9119d9
+ * @params: changed tunable values stored as array of virTypedParameter
9119d9
+ * @nparams: size of the array
9119d9
+ * @opaque: application specified data
9119d9
+ *
9119d9
+ * This callback occurs when tunable values are updated. The params must not
9119d9
+ * be freed in the callback handler as it's done internally after the callback
9119d9
+ * handler is executed.
9119d9
+ *
9119d9
+ * The callback signature to use when registering for an event of type
9119d9
+ * VIR_DOMAIN_EVENT_ID_TUNABLE with virConnectDomainEventRegisterAny()
9119d9
+ */
9119d9
+typedef void (*virConnectDomainEventTunableCallback)(virConnectPtr conn,
9119d9
+                                                     virDomainPtr dom,
9119d9
+                                                     virTypedParameterPtr params,
9119d9
+                                                     int nparams,
9119d9
+                                                     void *opaque);
9119d9
+
9119d9
 
9119d9
 /**
9119d9
  * VIR_DOMAIN_EVENT_CALLBACK:
9119d9
@@ -5202,6 +5223,7 @@ typedef enum {
9119d9
     VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK = 14, /* virConnectDomainEventPMSuspendDiskCallback */
9119d9
     VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED = 15, /* virConnectDomainEventDeviceRemovedCallback */
9119d9
     VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2 = 16,    /* virConnectDomainEventBlockJobCallback */
9119d9
+    VIR_DOMAIN_EVENT_ID_TUNABLE = 17,        /* virConnectDomainEventTunableCallback */
9119d9
 
9119d9
 #ifdef VIR_ENUM_SENTINELS
9119d9
     VIR_DOMAIN_EVENT_ID_LAST
9119d9
diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
9119d9
index 73ae289..bf187cd 100644
9119d9
--- a/src/conf/domain_event.c
9119d9
+++ b/src/conf/domain_event.c
9119d9
@@ -34,6 +34,7 @@
9119d9
 #include "viralloc.h"
9119d9
 #include "virerror.h"
9119d9
 #include "virstring.h"
9119d9
+#include "virtypedparam.h"
9119d9
 
9119d9
 #define VIR_FROM_THIS VIR_FROM_NONE
9119d9
 
9119d9
@@ -52,6 +53,7 @@ static virClassPtr virDomainEventBalloonChangeClass;
9119d9
 static virClassPtr virDomainEventDeviceRemovedClass;
9119d9
 static virClassPtr virDomainEventPMClass;
9119d9
 static virClassPtr virDomainQemuMonitorEventClass;
9119d9
+static virClassPtr virDomainEventTunableClass;
9119d9
 
9119d9
 
9119d9
 static void virDomainEventDispose(void *obj);
9119d9
@@ -67,6 +69,7 @@ static void virDomainEventBalloonChangeDispose(void *obj);
9119d9
 static void virDomainEventDeviceRemovedDispose(void *obj);
9119d9
 static void virDomainEventPMDispose(void *obj);
9119d9
 static void virDomainQemuMonitorEventDispose(void *obj);
9119d9
+static void virDomainEventTunableDispose(void *obj);
9119d9
 
9119d9
 static void
9119d9
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
9119d9
@@ -203,6 +206,15 @@ struct _virDomainQemuMonitorEvent {
9119d9
 typedef struct _virDomainQemuMonitorEvent virDomainQemuMonitorEvent;
9119d9
 typedef virDomainQemuMonitorEvent *virDomainQemuMonitorEventPtr;
9119d9
 
9119d9
+struct _virDomainEventTunable {
9119d9
+    virDomainEvent parent;
9119d9
+
9119d9
+    virTypedParameterPtr params;
9119d9
+    int nparams;
9119d9
+};
9119d9
+typedef struct _virDomainEventTunable virDomainEventTunable;
9119d9
+typedef virDomainEventTunable *virDomainEventTunablePtr;
9119d9
+
9119d9
 
9119d9
 static int
9119d9
 virDomainEventsOnceInit(void)
9119d9
@@ -285,6 +297,12 @@ virDomainEventsOnceInit(void)
9119d9
                       sizeof(virDomainQemuMonitorEvent),
9119d9
                       virDomainQemuMonitorEventDispose)))
9119d9
         return -1;
9119d9
+    if (!(virDomainEventTunableClass =
9119d9
+          virClassNew(virDomainEventClass,
9119d9
+                      "virDomainEventTunable",
9119d9
+                      sizeof(virDomainEventTunable),
9119d9
+                      virDomainEventTunableDispose)))
9119d9
+        return -1;
9119d9
     return 0;
9119d9
 }
9119d9
 
9119d9
@@ -420,6 +438,15 @@ virDomainQemuMonitorEventDispose(void *obj)
9119d9
     VIR_FREE(event->details);
9119d9
 }
9119d9
 
9119d9
+static void
9119d9
+virDomainEventTunableDispose(void *obj)
9119d9
+{
9119d9
+    virDomainEventTunablePtr event = obj;
9119d9
+    VIR_DEBUG("obj=%p", event);
9119d9
+
9119d9
+    virTypedParamsFree(event->params, event->nparams);
9119d9
+}
9119d9
+
9119d9
 
9119d9
 static void *
9119d9
 virDomainEventNew(virClassPtr klass,
9119d9
@@ -1175,6 +1202,61 @@ virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
9119d9
                                           devAlias);
9119d9
 }
9119d9
 
9119d9
+/* This function consumes the params so caller don't have to care about
9119d9
+ * freeing it even if error occurs. The reason is to not have to do deep
9119d9
+ * copy of params.
9119d9
+ */
9119d9
+static virObjectEventPtr
9119d9
+virDomainEventTunableNew(int id,
9119d9
+                         const char *name,
9119d9
+                         unsigned char *uuid,
9119d9
+                         virTypedParameterPtr params,
9119d9
+                         int nparams)
9119d9
+{
9119d9
+    virDomainEventTunablePtr ev;
9119d9
+
9119d9
+    if (virDomainEventsInitialize() < 0)
9119d9
+        goto error;
9119d9
+
9119d9
+    if (!(ev = virDomainEventNew(virDomainEventTunableClass,
9119d9
+                                 VIR_DOMAIN_EVENT_ID_TUNABLE,
9119d9
+                                 id, name, uuid)))
9119d9
+        goto error;
9119d9
+
9119d9
+    ev->params = params;
9119d9
+    ev->nparams = nparams;
9119d9
+
9119d9
+    return (virObjectEventPtr)ev;
9119d9
+
9119d9
+ error:
9119d9
+    virTypedParamsFree(params, nparams);
9119d9
+    return NULL;
9119d9
+}
9119d9
+
9119d9
+virObjectEventPtr
9119d9
+virDomainEventTunableNewFromObj(virDomainObjPtr obj,
9119d9
+                                virTypedParameterPtr params,
9119d9
+                                int nparams)
9119d9
+{
9119d9
+    return virDomainEventTunableNew(obj->def->id,
9119d9
+                                    obj->def->name,
9119d9
+                                    obj->def->uuid,
9119d9
+                                    params,
9119d9
+                                    nparams);
9119d9
+}
9119d9
+
9119d9
+virObjectEventPtr
9119d9
+virDomainEventTunableNewFromDom(virDomainPtr dom,
9119d9
+                                virTypedParameterPtr params,
9119d9
+                                int nparams)
9119d9
+{
9119d9
+    return virDomainEventTunableNew(dom->id,
9119d9
+                                    dom->name,
9119d9
+                                    dom->uuid,
9119d9
+                                    params,
9119d9
+                                    nparams);
9119d9
+}
9119d9
+
9119d9
 
9119d9
 static void
9119d9
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
9119d9
@@ -1366,6 +1448,17 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
9119d9
             goto cleanup;
9119d9
         }
9119d9
 
9119d9
+    case VIR_DOMAIN_EVENT_ID_TUNABLE:
9119d9
+        {
9119d9
+            virDomainEventTunablePtr tunableEvent;
9119d9
+            tunableEvent = (virDomainEventTunablePtr)event;
9119d9
+            ((virConnectDomainEventTunableCallback)cb)(conn, dom,
9119d9
+                                                       tunableEvent->params,
9119d9
+                                                       tunableEvent->nparams,
9119d9
+                                                       cbopaque);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+
9119d9
     case VIR_DOMAIN_EVENT_ID_LAST:
9119d9
         break;
9119d9
     }
9119d9
diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
9119d9
index a3330ca..dc0109c 100644
9119d9
--- a/src/conf/domain_event.h
9119d9
+++ b/src/conf/domain_event.h
9119d9
@@ -184,6 +184,15 @@ virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj,
9119d9
 virObjectEventPtr
9119d9
 virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
9119d9
                                       const char *devAlias);
9119d9
+virObjectEventPtr
9119d9
+virDomainEventTunableNewFromObj(virDomainObjPtr obj,
9119d9
+                                virTypedParameterPtr params,
9119d9
+                                int nparams);
9119d9
+virObjectEventPtr
9119d9
+virDomainEventTunableNewFromDom(virDomainPtr dom,
9119d9
+                                virTypedParameterPtr params,
9119d9
+                                int nparams);
9119d9
+
9119d9
 
9119d9
 int
9119d9
 virDomainEventStateRegister(virConnectPtr conn,
9119d9
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
9119d9
index ab81ba2..138d84f 100644
9119d9
--- a/src/libvirt_private.syms
9119d9
+++ b/src/libvirt_private.syms
9119d9
@@ -472,6 +472,8 @@ virDomainEventStateRegister;
9119d9
 virDomainEventStateRegisterID;
9119d9
 virDomainEventTrayChangeNewFromDom;
9119d9
 virDomainEventTrayChangeNewFromObj;
9119d9
+virDomainEventTunableNewFromDom;
9119d9
+virDomainEventTunableNewFromObj;
9119d9
 virDomainEventWatchdogNewFromDom;
9119d9
 virDomainEventWatchdogNewFromObj;
9119d9
 virDomainQemuMonitorEventNew;
9119d9
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
9119d9
index 8bc4baa..6cf1aae 100644
9119d9
--- a/src/remote/remote_driver.c
9119d9
+++ b/src/remote/remote_driver.c
9119d9
@@ -326,6 +326,11 @@ remoteDomainBuildEventBlockJob2(virNetClientProgramPtr prog,
9119d9
                                 void *evdata, void *opaque);
9119d9
 
9119d9
 static void
9119d9
+remoteDomainBuildEventCallbackTunable(virNetClientProgramPtr prog,
9119d9
+                                      virNetClientPtr client,
9119d9
+                                      void *evdata, void *opaque);
9119d9
+
9119d9
+static void
9119d9
 remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
9119d9
                                  virNetClientPtr client ATTRIBUTE_UNUSED,
9119d9
                                  void *evdata, void *opaque);
9119d9
@@ -476,6 +481,10 @@ static virNetClientProgramEvent remoteEvents[] = {
9119d9
       remoteDomainBuildEventBlockJob2,
9119d9
       sizeof(remote_domain_event_block_job_2_msg),
9119d9
       (xdrproc_t)xdr_remote_domain_event_block_job_2_msg },
9119d9
+    { REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE,
9119d9
+      remoteDomainBuildEventCallbackTunable,
9119d9
+      sizeof(remote_domain_event_callback_tunable_msg),
9119d9
+      (xdrproc_t)xdr_remote_domain_event_callback_tunable_msg },
9119d9
 };
9119d9
 
9119d9
 
9119d9
@@ -5500,6 +5509,39 @@ remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgramPtr prog ATTRIBUT
9119d9
 
9119d9
 
9119d9
 static void
9119d9
+remoteDomainBuildEventCallbackTunable(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
9119d9
+                                      virNetClientPtr client ATTRIBUTE_UNUSED,
9119d9
+                                      void *evdata, void *opaque)
9119d9
+{
9119d9
+    virConnectPtr conn = opaque;
9119d9
+    remote_domain_event_callback_tunable_msg *msg = evdata;
9119d9
+    struct private_data *priv = conn->privateData;
9119d9
+    virDomainPtr dom;
9119d9
+    virTypedParameterPtr params = NULL;
9119d9
+    int nparams = 0;
9119d9
+    virObjectEventPtr event = NULL;
9119d9
+
9119d9
+    if (remoteDeserializeTypedParameters(msg->params.params_val,
9119d9
+                                         msg->params.params_len,
9119d9
+                                         REMOTE_DOMAIN_EVENT_TUNABLE_MAX,
9119d9
+                                         &params, &nparams) < 0)
9119d9
+        return;
9119d9
+
9119d9
+    dom = get_nonnull_domain(conn, msg->dom);
9119d9
+    if (!dom) {
9119d9
+        virTypedParamsFree(params, nparams);
9119d9
+        return;
9119d9
+    }
9119d9
+
9119d9
+    event = virDomainEventTunableNewFromDom(dom, params, nparams);
9119d9
+
9119d9
+    virDomainFree(dom);
9119d9
+
9119d9
+    remoteEventQueue(priv, event, msg->callbackID);
9119d9
+}
9119d9
+
9119d9
+
9119d9
+static void
9119d9
 remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
9119d9
                                  virNetClientPtr client ATTRIBUTE_UNUSED,
9119d9
                                  void *evdata, void *opaque)
9119d9
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
9119d9
index 8fc552f..e7ee2e8 100644
9119d9
--- a/src/remote/remote_protocol.x
9119d9
+++ b/src/remote/remote_protocol.x
9119d9
@@ -244,6 +244,9 @@ const REMOTE_NETWORK_DHCP_LEASES_MAX = 65536;
9119d9
 /* Upper limit on count of parameters returned via bulk stats API */
9119d9
 const REMOTE_CONNECT_GET_ALL_DOMAIN_STATS_MAX = 4096;
9119d9
 
9119d9
+/* Upper limit of message size for tunable event. */
9119d9
+const REMOTE_DOMAIN_EVENT_TUNABLE_MAX = 8388608;
9119d9
+
9119d9
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
9119d9
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
9119d9
 
9119d9
@@ -2980,6 +2983,12 @@ struct remote_domain_event_block_job_2_msg {
9119d9
     int status;
9119d9
 };
9119d9
 
9119d9
+struct remote_domain_event_callback_tunable_msg {
9119d9
+    int callbackID;
9119d9
+    remote_nonnull_domain dom;
9119d9
+    remote_typed_param params<REMOTE_DOMAIN_EVENT_TUNABLE_MAX>;
9119d9
+};
9119d9
+
9119d9
 struct remote_connect_get_cpu_model_names_args {
9119d9
     remote_nonnull_string arch;
9119d9
     int need_results;
9119d9
@@ -5456,5 +5465,11 @@ enum remote_procedure {
9119d9
      * @acl: connect:search_domains
9119d9
      * @aclfilter: domain:read
9119d9
      */
9119d9
-    REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344
9119d9
+    REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344,
9119d9
+
9119d9
+    /**
9119d9
+     * @generate: both
9119d9
+     * @acl: none
9119d9
+     */
9119d9
+    REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE = 346
9119d9
 };
9119d9
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
9119d9
index 899f1cc..9d6d104 100644
9119d9
--- a/src/remote_protocol-structs
9119d9
+++ b/src/remote_protocol-structs
9119d9
@@ -2435,6 +2435,14 @@ struct remote_domain_event_block_job_2_msg {
9119d9
         int                        type;
9119d9
         int                        status;
9119d9
 };
9119d9
+struct remote_domain_event_callback_tunable_msg {
9119d9
+        int                        callbackID;
9119d9
+        remote_nonnull_domain      dom;
9119d9
+        struct {
9119d9
+                u_int              params_len;
9119d9
+                remote_typed_param * params_val;
9119d9
+        } params;
9119d9
+};
9119d9
 struct remote_connect_get_cpu_model_names_args {
9119d9
         remote_nonnull_string      arch;
9119d9
         int                        need_results;
9119d9
@@ -2890,4 +2898,5 @@ enum remote_procedure {
9119d9
         REMOTE_PROC_CONNECT_GET_DOMAIN_CAPABILITIES = 342,
9119d9
         REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD = 343,
9119d9
         REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344,
9119d9
+        REMOTE_PROC_DOMAIN_EVENT_CALLBACK_TUNABLE = 346,
9119d9
 };
9119d9
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
9119d9
index 23395e5..f182dd0 100644
9119d9
--- a/tools/virsh-domain.c
9119d9
+++ b/tools/virsh-domain.c
9119d9
@@ -11245,6 +11245,37 @@ vshEventDeviceRemovedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
9119d9
         vshEventDone(data->ctl);
9119d9
 }
9119d9
 
9119d9
+static void
9119d9
+vshEventTunablePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
9119d9
+                     virDomainPtr dom,
9119d9
+                     virTypedParameterPtr params,
9119d9
+                     int nparams,
9119d9
+                     void *opaque)
9119d9
+{
9119d9
+    vshDomEventData *data = opaque;
9119d9
+    size_t i;
9119d9
+    char *value = NULL;
9119d9
+
9119d9
+    if (!data->loop && *data->count)
9119d9
+        return;
9119d9
+
9119d9
+    vshPrint(data->ctl,
9119d9
+             _("event 'tunable' for domain %s:\n"),
9119d9
+             virDomainGetName(dom));
9119d9
+
9119d9
+    for (i = 0; i < nparams; i++) {
9119d9
+        value = virTypedParameterToString(&params[i]);
9119d9
+        if (value) {
9119d9
+            vshPrint(data->ctl, _("\t%s: %s\n"), params[i].field, value);
9119d9
+            VIR_FREE(value);
9119d9
+        }
9119d9
+    }
9119d9
+
9119d9
+    (*data->count)++;
9119d9
+    if (!data->loop)
9119d9
+        vshEventDone(data->ctl);
9119d9
+}
9119d9
+
9119d9
 static vshEventCallback vshEventCallbacks[] = {
9119d9
     { "lifecycle",
9119d9
       VIR_DOMAIN_EVENT_CALLBACK(vshEventLifecyclePrint), },
9119d9
@@ -11278,6 +11309,8 @@ static vshEventCallback vshEventCallbacks[] = {
9119d9
       VIR_DOMAIN_EVENT_CALLBACK(vshEventDeviceRemovedPrint), },
9119d9
     { "block-job-2",
9119d9
       VIR_DOMAIN_EVENT_CALLBACK(vshEventBlockJobPrint), },
9119d9
+    { "tunable",
9119d9
+      VIR_DOMAIN_EVENT_CALLBACK(vshEventTunablePrint), },
9119d9
 };
9119d9
 verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
9119d9
 
9119d9
-- 
9119d9
2.1.1
9119d9