]> xenbits.xensource.com Git - libvirt.git/commitdiff
event: introduce new event for tunable values
authorPavel Hrdina <phrdina@redhat.com>
Wed, 10 Sep 2014 11:28:24 +0000 (13:28 +0200)
committerPavel Hrdina <phrdina@redhat.com>
Tue, 23 Sep 2014 19:49:57 +0000 (21:49 +0200)
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@redhat.com>
daemon/remote.c
include/libvirt/libvirt.h.in
src/conf/domain_event.c
src/conf/domain_event.h
src/libvirt_private.syms
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs
tools/virsh-domain.c

index daa4b601e40880e30ed84ab0fa1772f52bd651bc..ddd510c169d0420a1054624f688ca06535be2689 100644 (file)
@@ -110,6 +110,13 @@ remoteDeserializeTypedParameters(remote_typed_param *args_params_val,
                                  int limit,
                                  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,
@@ -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);
index 6371b7ba4adbff2fa962dd604597a59b9d2ff245..86be86ffaef096a58ca029568937b39434fbca65 100644 (file)
@@ -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
index 73ae2894b82d4dd22ae4e5ba82271aca96e9f5f3..bf187cd361df0d702c2c9e1796f478b423e82b90 100644 (file)
@@ -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;
     }
index a3330ca804fda4b85995956e98b8cc7d7b5c176d..dc0109cf67286d3406029552059fe06a9232ae9f 100644 (file)
@@ -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,
index 51a692b39ba30ff037a35af949aafea8f00a9d6e..a339ced69dad931ddc08d88703e0ec605b822e0f 100644 (file)
@@ -473,6 +473,8 @@ virDomainEventStateRegister;
 virDomainEventStateRegisterID;
 virDomainEventTrayChangeNewFromDom;
 virDomainEventTrayChangeNewFromObj;
+virDomainEventTunableNewFromDom;
+virDomainEventTunableNewFromObj;
 virDomainEventWatchdogNewFromDom;
 virDomainEventWatchdogNewFromObj;
 virDomainQemuMonitorEventNew;
index 75a3a7b4f46887c6bf63f2bdf84efb388bfb0758..dbf7c04330e496f48c5da9eab97d7030764e8b54 100644 (file)
@@ -330,6 +330,11 @@ remoteDomainBuildEventBlockJob2(virNetClientProgramPtr prog,
                                 virNetClientPtr client,
                                 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,
@@ -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 },
 };
 
 
@@ -5513,6 +5522,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_DOMAIN_EVENT_TUNABLE_MAX,
+                                         &params, &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,
index a4ca0c3421f91aa826753d9252125d831d9358a2..0c6a91ebabc2d00911b13825b16faf2f5e8fef2d 100644 (file)
@@ -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
 };
index e9604159fb1aa27d7ba332ca456e186444b7e4f9..6128a856f1f5b98a4ce816c98dfc41ba700751ef 100644 (file)
@@ -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,
 };
index a6ced5f28f9bce1c8d6f187462550a17dac04609..ce5940623d8d3449ab4b0e9c52786b5b8ff14f1e 100644 (file)
@@ -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(&params[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));