[libvirt] [PATCH 2/4] event: introduce new event for cputune

Pavel Hrdina phrdina at redhat.com
Thu Aug 28 18:38:28 UTC 2014


Signed-off-by: Pavel Hrdina <phrdina at redhat.com>
---
 daemon/remote.c              |  87 +++++++++++++++++++++++++++++++
 include/libvirt/libvirt.h.in |  62 ++++++++++++++++++++++
 src/conf/domain_event.c      | 120 +++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_event.h      |   7 +++
 src/libvirt_private.syms     |   2 +
 src/remote/remote_driver.c   | 110 +++++++++++++++++++++++++++++++++++++++
 src/remote/remote_protocol.x |  39 +++++++++++++-
 src/remote_protocol-structs  |  32 ++++++++++++
 tools/virsh-domain.c         |  49 ++++++++++++++++++
 9 files changed, 507 insertions(+), 1 deletion(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 89714ca..ae42c4d 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -969,6 +969,92 @@ remoteRelayDomainEventBlockJob2(virConnectPtr conn,
 }
 
 
+static int
+remoteRelayDomainEventCputune(virConnectPtr conn,
+                              virDomainPtr dom,
+                              virDomainCputuneInfoPtr cputune,
+                              void *opaque)
+{
+    daemonClientEventCallbackPtr callback = opaque;
+    remote_domain_event_cputune_msg data;
+    size_t i;
+
+    if (callback->callbackID < 0 ||
+        !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
+        return -1;
+
+    VIR_DEBUG("Relaying domain cputune event %s %d, callback %d",
+              dom->name, dom->id, callback->callbackID);
+
+    /* build return data */
+    memset(&data, 0, sizeof(data));
+    make_nonnull_domain(&data.dom, dom);
+
+    data.shares = cputune->shares;
+    data.sharesSpecified = cputune->sharesSpecified;
+    data.period = cputune->period;
+    data.quota = cputune->quota;
+    data.emulatorPeriod = cputune->emulatorPeriod;
+    data.emulatorQuota = cputune->emulatorQuota;
+    data.nvcpupin = cputune->nvcpupin;
+
+    if (cputune->emulatorpin.map) {
+        if (VIR_ALLOC_N(data.emulatorpin.map.map_val,
+            cputune->emulatorpin.mapLen) < 0)
+            goto error;
+        memcpy(data.emulatorpin.map.map_val, cputune->emulatorpin.map,
+               cputune->emulatorpin.mapLen);
+        data.emulatorpin.map.map_len = cputune->emulatorpin.mapLen;
+        data.emulatorpin.mapLen = cputune->emulatorpin.mapLen;
+    }
+    if (cputune->vcpupin) {
+        if (VIR_ALLOC_N(data.vcpupin.vcpupin_val, data.nvcpupin) < 0)
+            goto error;
+        data.vcpupin.vcpupin_len = data.nvcpupin;
+
+        for (i = 0; i < data.nvcpupin; i++) {
+            data.vcpupin.vcpupin_val[i].vcpuid = cputune->vcpupin[i].vcpuid;
+            if (VIR_ALLOC_N(data.vcpupin.vcpupin_val[i].cpumask.map.map_val,
+                        cputune->vcpupin[i].cpumask.mapLen) < 0)
+                goto error;
+            memcpy(data.vcpupin.vcpupin_val[i].cpumask.map.map_val,
+                   cputune->vcpupin[i].cpumask.map,
+                   cputune->vcpupin[i].cpumask.mapLen);
+            data.vcpupin.vcpupin_val[i].cpumask.map.map_len =
+                cputune->vcpupin[i].cpumask.mapLen;
+            data.vcpupin.vcpupin_val[i].cpumask.mapLen =
+                cputune->vcpupin[i].cpumask.mapLen;
+        }
+    }
+
+    if (callback->legacy) {
+        remoteDispatchObjectEventSend(callback->client, remoteProgram,
+                                      REMOTE_PROC_DOMAIN_EVENT_CPUTUNE,
+                                      (xdrproc_t)xdr_remote_domain_event_cputune_msg,
+                                      &data);
+    } else {
+        remote_domain_event_callback_cputune_msg msg = { callback->callbackID,
+                                                         data };
+
+        remoteDispatchObjectEventSend(callback->client, remoteProgram,
+                                      REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CPUTUNE,
+                                      (xdrproc_t)xdr_remote_domain_event_callback_cputune_msg,
+                                      &msg);
+    }
+
+    return 0;
+
+ error:
+    VIR_FREE(data.emulatorpin.map.map_val);
+    if (data.vcpupin.vcpupin_val) {
+        for (i = 0; i < data.nvcpupin; i++)
+            VIR_FREE(data.vcpupin.vcpupin_val[i].cpumask.map.map_val);
+        VIR_FREE(data.vcpupin.vcpupin_val);
+    }
+    return -1;
+}
+
+
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@@ -987,6 +1073,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventPMSuspendDisk),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventDeviceRemoved),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockJob2),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventCputune),
 };
 
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 9358314..636b89b 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -5127,7 +5127,68 @@ typedef void (*virConnectDomainEventDeviceRemovedCallback)(virConnectPtr conn,
                                                            virDomainPtr dom,
                                                            const char *devAlias,
                                                            void *opaque);
+/**
+ * _virDomainCpumaksInfo
+ *
+ * This structure stores a mask with pinning information for emulator
+ * or vcpus.
+ */
+struct _virDomainCpumaskInfo {
+    int mapLen;
+    unsigned char *map;
+};
+typedef struct _virDomainCpumaskInfo virDomainCpumaskInfo;
+typedef virDomainCpumaskInfo *virDomainCpumaskInfoPtr;
+
+/**
+ * _virDomainVcpupinInfo
+ *
+ * This structure stores cpumask with pinning information
+ * for each vcpu where the pinning has been set.
+ */
+struct _virDomainVcpupinInfo {
+    int vcpuid;
+    virDomainCpumaskInfo cpumask;
+};
+typedef struct _virDomainVcpupinInfo virDomainVcpupinInfo;
+typedef virDomainVcpupinInfo *virDomainVcpupinInfoPtr;
+
+/**
+ * _virDomainCputuneInfo
+ *
+ * Structure containing all infromation about cputune for
+ * specific domain.
+ */
+struct _virDomainCputuneInfo {
+    unsigned long long shares;
+    int sharesSpecified;
+    unsigned long long period;
+    long long quota;
+    unsigned long long emulatorPeriod;
+    long long emulatorQuota;
+    size_t nvcpupin;
+    virDomainVcpupinInfoPtr vcpupin;
+    virDomainCpumaskInfo emulatorpin;
+};
+typedef struct _virDomainCputuneInfo virDomainCputuneInfo;
+typedef virDomainCputuneInfo *virDomainCputuneInfoPtr;
 
+/**
+ * virConnectDomainEventCputuneCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @cputune: cputune informations
+ * @opaque: application specified data
+ *
+ * This callback occurs when cpu tune is updated.
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_CPUTUNE with virConnectDomainEventRegisterAny()
+ */
+typedef void (*virConnectDomainEventCputuneCallback)(virConnectPtr conn,
+                                                     virDomainPtr dom,
+                                                     virDomainCputuneInfoPtr cputune,
+                                                     void *opaque);
 
 /**
  * VIR_DOMAIN_EVENT_CALLBACK:
@@ -5163,6 +5224,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_CPUTUNE = 17,        /* virConnectDomainEventCputuneCallback */
 
 #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..966562f 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -52,6 +52,7 @@ static virClassPtr virDomainEventBalloonChangeClass;
 static virClassPtr virDomainEventDeviceRemovedClass;
 static virClassPtr virDomainEventPMClass;
 static virClassPtr virDomainQemuMonitorEventClass;
+static virClassPtr virDomainEventCputuneClass;
 
 
 static void virDomainEventDispose(void *obj);
@@ -67,6 +68,7 @@ static void virDomainEventBalloonChangeDispose(void *obj);
 static void virDomainEventDeviceRemovedDispose(void *obj);
 static void virDomainEventPMDispose(void *obj);
 static void virDomainQemuMonitorEventDispose(void *obj);
+static void virDomainEventCputuneDispose(void *obj);
 
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
@@ -203,6 +205,14 @@ struct _virDomainQemuMonitorEvent {
 typedef struct _virDomainQemuMonitorEvent virDomainQemuMonitorEvent;
 typedef virDomainQemuMonitorEvent *virDomainQemuMonitorEventPtr;
 
+struct _virDomainEventCputune {
+    virDomainEvent parent;
+
+    virDomainCputuneInfo cputune;
+};
+typedef struct _virDomainEventCputune virDomainEventCputune;
+typedef virDomainEventCputune *virDomainEventCputunePtr;
+
 
 static int
 virDomainEventsOnceInit(void)
@@ -285,6 +295,12 @@ virDomainEventsOnceInit(void)
                       sizeof(virDomainQemuMonitorEvent),
                       virDomainQemuMonitorEventDispose)))
         return -1;
+    if (!(virDomainEventCputuneClass =
+          virClassNew(virDomainEventClass,
+                      "virDomainEventCputune",
+                      sizeof(virDomainEventCputune),
+                      virDomainEventCputuneDispose)))
+        return -1;
     return 0;
 }
 
@@ -420,6 +436,22 @@ virDomainQemuMonitorEventDispose(void *obj)
     VIR_FREE(event->details);
 }
 
+static void
+virDomainEventCputuneDispose(void *obj)
+{
+    virDomainEventCputunePtr event = obj;
+    VIR_DEBUG("obj=%p", event);
+
+    VIR_FREE(event->cputune.emulatorpin.map);
+    if (event->cputune.vcpupin) {
+        size_t i;
+        for (i = 0; i < event->cputune.nvcpupin; i++) {
+            VIR_FREE(event->cputune.vcpupin[i].cpumask.map);
+        }
+        VIR_FREE(event->cputune.vcpupin);
+    }
+}
+
 
 static void *
 virDomainEventNew(virClassPtr klass,
@@ -1175,6 +1207,84 @@ virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
                                           devAlias);
 }
 
+static virObjectEventPtr
+virDomainEventCputuneNew(int id,
+                         const char *name,
+                         unsigned char *uuid,
+                         virDomainCputune cputune)
+{
+    virDomainEventCputunePtr ev;
+    size_t i;
+
+    if (virDomainEventsInitialize() < 0)
+        return NULL;
+
+    if (!(ev = virDomainEventNew(virDomainEventCputuneClass,
+                                 VIR_DOMAIN_EVENT_ID_CPUTUNE,
+                                 id, name, uuid)))
+        return NULL;
+
+    ev->cputune.shares = cputune.shares;
+    ev->cputune.sharesSpecified = cputune.sharesSpecified;
+    ev->cputune.period = cputune.period;
+    ev->cputune.quota = cputune.quota;
+    ev->cputune.emulatorPeriod = cputune.emulator_period;
+    ev->cputune.emulatorQuota = cputune.emulator_quota;
+    ev->cputune.nvcpupin = cputune.nvcpupin;
+    ev->cputune.vcpupin = NULL;
+
+    if (cputune.emulatorpin) {
+        if (virBitmapToData(cputune.emulatorpin->cpumask,
+                            &ev->cputune.emulatorpin.map,
+                            &ev->cputune.emulatorpin.mapLen) < 0)
+            goto error;
+    }
+
+    if (cputune.vcpupin) {
+        if (VIR_ALLOC_N(ev->cputune.vcpupin, ev->cputune.nvcpupin) < 0)
+            goto error;
+        for (i = 0; i < ev->cputune.nvcpupin; i++) {
+            ev->cputune.vcpupin[i].vcpuid = cputune.vcpupin[i]->vcpuid;
+            if (virBitmapToData(cputune.vcpupin[i]->cpumask,
+                                &ev->cputune.vcpupin[i].cpumask.map,
+                                &ev->cputune.vcpupin[i].cpumask.mapLen) < 0)
+                goto error;
+        }
+    }
+
+    return (virObjectEventPtr)ev;
+
+ error:
+    VIR_FREE(ev->cputune.emulatorpin.map);
+    if (ev->cputune.vcpupin) {
+        for (i = 0; i < ev->cputune.nvcpupin; i++)
+            VIR_FREE(ev->cputune.vcpupin[i].cpumask.map);
+        VIR_FREE(ev->cputune.vcpupin);
+    }
+    virObjectUnref(ev);
+
+    return NULL;
+}
+
+virObjectEventPtr
+virDomainEventCputuneNewFromObj(virDomainObjPtr obj,
+                                virDomainCputune cputune)
+{
+    return virDomainEventCputuneNew(obj->def->id,
+                                    obj->def->name,
+                                    obj->def->uuid,
+                                    cputune);
+}
+
+virObjectEventPtr
+virDomainEventCputuneNewFromDom(virDomainPtr dom,
+                                virDomainCputune cputune)
+{
+    return virDomainEventCputuneNew(dom->id,
+                                    dom->name,
+                                    dom->uuid,
+                                    cputune);
+}
 
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
@@ -1366,6 +1476,16 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
             goto cleanup;
         }
 
+    case VIR_DOMAIN_EVENT_ID_CPUTUNE:
+        {
+            virDomainEventCputunePtr cputuneEvent;
+            cputuneEvent = (virDomainEventCputunePtr)event;
+            ((virConnectDomainEventCputuneCallback)cb)(conn, dom,
+                                                       &cputuneEvent->cputune,
+                                                       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..44c6a7b 100644
--- a/src/conf/domain_event.h
+++ b/src/conf/domain_event.h
@@ -184,6 +184,13 @@ virDomainEventDeviceRemovedNewFromObj(virDomainObjPtr obj,
 virObjectEventPtr
 virDomainEventDeviceRemovedNewFromDom(virDomainPtr dom,
                                       const char *devAlias);
+virObjectEventPtr
+virDomainEventCputuneNewFromObj(virDomainObjPtr obj,
+                                virDomainCputune cputune);
+virObjectEventPtr
+virDomainEventCputuneNewFromDom(virDomainPtr dom,
+                                virDomainCputune cputune);
+
 
 int
 virDomainEventStateRegister(virConnectPtr conn,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 71fc063..74a5487 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -439,6 +439,8 @@ virDomainEventBlockJobNewFromDom;
 virDomainEventBlockJobNewFromObj;
 virDomainEventControlErrorNewFromDom;
 virDomainEventControlErrorNewFromObj;
+virDomainEventCputuneNewFromDom;
+virDomainEventCputuneNewFromObj;
 virDomainEventDeviceRemovedNewFromDom;
 virDomainEventDeviceRemovedNewFromObj;
 virDomainEventDiskChangeNewFromDom;
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index fda27f7..ba8a738 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -326,6 +326,16 @@ remoteDomainBuildEventBlockJob2(virNetClientProgramPtr prog,
                                 void *evdata, void *opaque);
 
 static void
+remoteDomainBuildEventCputune(virNetClientProgramPtr prog,
+                              virNetClientPtr client,
+                              void *evdata, void *opaque);
+
+static void
+remoteDomainBuildEventCallbackCputune(virNetClientProgramPtr prog,
+                                      virNetClientPtr client,
+                                      void *evdata, void *opaque);
+
+static void
 remoteNetworkBuildEventLifecycle(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
                                  virNetClientPtr client ATTRIBUTE_UNUSED,
                                  void *evdata, void *opaque);
@@ -395,6 +405,10 @@ static virNetClientProgramEvent remoteEvents[] = {
       remoteDomainBuildEventDeviceRemoved,
       sizeof(remote_domain_event_device_removed_msg),
       (xdrproc_t)xdr_remote_domain_event_device_removed_msg },
+    { REMOTE_PROC_DOMAIN_EVENT_CPUTUNE,
+      remoteDomainBuildEventCputune,
+      sizeof(remote_domain_event_cputune_msg),
+      (xdrproc_t)xdr_remote_domain_event_cputune_msg },
     /* All events above here are legacy events, missing the callback
      * ID, which means the server has a single global registration and
      * we do full filtering in the client.  If the server lacks
@@ -476,6 +490,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_CPUTUNE,
+      remoteDomainBuildEventCallbackCputune,
+      sizeof(remote_domain_event_callback_cputune_msg),
+      (xdrproc_t)xdr_remote_domain_event_callback_cputune_msg },
 };
 
 
@@ -5500,6 +5518,98 @@ remoteDomainBuildEventCallbackDeviceRemoved(virNetClientProgramPtr prog ATTRIBUT
 
 
 static void
+remoteDomainBuildEventCputuneHelper(virConnectPtr conn,
+                                    remote_domain_event_cputune_msg *msg,
+                                    int callbackID)
+{
+    struct private_data *priv = conn->privateData;
+    virDomainPtr dom;
+    virDomainCputune cputune;
+    virObjectEventPtr event = NULL;
+    size_t i;
+
+    dom = get_nonnull_domain(conn, msg->dom);
+    if (!dom)
+        return;
+
+    memset(&cputune, 0, sizeof(cputune));
+
+    cputune.shares = msg->shares;
+    cputune.sharesSpecified = msg->sharesSpecified;
+    cputune.period = msg->period;
+    cputune.quota = msg->quota;
+    cputune.emulator_period = msg->emulatorPeriod;
+    cputune.emulator_quota = msg->emulatorQuota;
+    cputune.nvcpupin = msg->nvcpupin;
+
+    if (msg->nvcpupin != msg->vcpupin.vcpupin_len)
+        goto cleanup;
+
+    if (msg->emulatorpin.map.map_val) {
+        if (VIR_ALLOC(cputune.emulatorpin) < 0)
+            goto cleanup;
+        cputune.emulatorpin->cpumask = virBitmapNewData(msg->emulatorpin.map.map_val,
+                                                        msg->emulatorpin.map.map_len);
+        if (!cputune.emulatorpin->cpumask)
+            goto cleanup;
+    }
+
+    if (msg->vcpupin.vcpupin_val) {
+        if (VIR_ALLOC_N(cputune.vcpupin, cputune.nvcpupin) < 0)
+            goto cleanup;
+
+        for (i = 0; i < cputune.nvcpupin; i++) {
+            if (VIR_ALLOC(cputune.vcpupin[i]) < 0)
+                goto cleanup;
+            cputune.vcpupin[i]->vcpuid = msg->vcpupin.vcpupin_val[i].vcpuid;
+            cputune.vcpupin[i]->cpumask = virBitmapNewData(msg->vcpupin.vcpupin_val[i].cpumask.map.map_val,
+                                                           msg->vcpupin.vcpupin_val[i].cpumask.map.map_len);
+            if (!cputune.vcpupin[i]->cpumask)
+                goto cleanup;
+        }
+    }
+
+    event = virDomainEventCputuneNewFromDom(dom, cputune);
+
+    remoteEventQueue(priv, event, callbackID);
+
+ cleanup:
+    virDomainFree(dom);
+    if (cputune.emulatorpin) {
+        virBitmapFree(cputune.emulatorpin->cpumask);
+        VIR_FREE(cputune.emulatorpin);
+    }
+    if (cputune.vcpupin) {
+        for (i = 0; i < cputune.nvcpupin; i++) {
+            if (cputune.vcpupin[i]) {
+                virBitmapFree(cputune.vcpupin[i]->cpumask);
+                VIR_FREE(cputune.vcpupin[i]);
+            }
+        }
+        VIR_FREE(cputune.vcpupin);
+    }
+}
+static void
+remoteDomainBuildEventCputune(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+                              virNetClientPtr client ATTRIBUTE_UNUSED,
+                              void *evdata, void *opaque)
+{
+    virConnectPtr conn = opaque;
+    remote_domain_event_cputune_msg *msg = evdata;
+    remoteDomainBuildEventCputuneHelper(conn, msg, -1);
+}
+static void
+remoteDomainBuildEventCallbackCputune(virNetClientProgramPtr prog ATTRIBUTE_UNUSED,
+                                      virNetClientPtr client ATTRIBUTE_UNUSED,
+                                      void *evdata, void *opaque)
+{
+    virConnectPtr conn = opaque;
+    remote_domain_event_callback_cputune_msg *msg = evdata;
+    remoteDomainBuildEventCputuneHelper(conn, &msg->msg, 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 8fc552f..5c2d8f5 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2980,6 +2980,31 @@ struct remote_domain_event_block_job_2_msg {
     int status;
 };
 
+struct remote_domain_cpumask {
+    int mapLen;
+    unsigned char map<REMOTE_CPUMAP_MAX>;
+};
+struct remote_domain_vcpupin {
+    int vcpuid;
+    remote_domain_cpumask cpumask;
+};
+struct remote_domain_event_cputune_msg {
+    remote_nonnull_domain dom;
+    unsigned hyper shares;
+    int sharesSpecified;
+    unsigned hyper period;
+    hyper quota;
+    unsigned hyper emulatorPeriod;
+    hyper emulatorQuota;
+    unsigned int nvcpupin;
+    remote_domain_vcpupin vcpupin<REMOTE_VCPUINFO_MAX>;
+    remote_domain_cpumask emulatorpin;
+};
+struct remote_domain_event_callback_cputune_msg {
+    int callbackID;
+    remote_domain_event_cputune_msg msg;
+};
+
 struct remote_connect_get_cpu_model_names_args {
     remote_nonnull_string arch;
     int need_results;
@@ -5456,5 +5481,17 @@ enum remote_procedure {
      * @acl: connect:search_domains
      * @aclfilter: domain:read
      */
-    REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344
+    REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_DOMAIN_EVENT_CPUTUNE = 345,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CPUTUNE = 346
 };
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 899f1cc..8dacdd5 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2435,6 +2435,36 @@ struct remote_domain_event_block_job_2_msg {
         int                        type;
         int                        status;
 };
+struct remote_domain_cpumask {
+        int                        mapLen;
+        struct {
+                u_int              map_len;
+                u_char *           map_val;
+        } map;
+};
+struct remote_domain_vcpupin {
+        int                        vcpuid;
+        remote_domain_cpumask      cpumask;
+};
+struct remote_domain_event_cputune_msg {
+        remote_nonnull_domain      dom;
+        uint64_t                   shares;
+        int                        sharesSpecified;
+        uint64_t                   period;
+        int64_t                    quota;
+        uint64_t                   emulatorPeriod;
+        int64_t                    emulatorQuota;
+        u_int                      nvcpupin;
+        struct {
+                u_int              vcpupin_len;
+                remote_domain_vcpupin * vcpupin_val;
+        } vcpupin;
+        remote_domain_cpumask      emulatorpin;
+};
+struct remote_domain_event_callback_cputune_msg {
+        int                        callbackID;
+        remote_domain_event_cputune_msg msg;
+};
 struct remote_connect_get_cpu_model_names_args {
         remote_nonnull_string      arch;
         int                        need_results;
@@ -2890,4 +2920,6 @@ enum remote_procedure {
         REMOTE_PROC_CONNECT_GET_DOMAIN_CAPABILITIES = 342,
         REMOTE_PROC_DOMAIN_OPEN_GRAPHICS_FD = 343,
         REMOTE_PROC_CONNECT_GET_ALL_DOMAIN_STATS = 344,
+        REMOTE_PROC_DOMAIN_EVENT_CPUTUNE = 345,
+        REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CPUTUNE = 346,
 };
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index c75cd73..d2d2d96 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -11170,6 +11170,53 @@ vshEventDeviceRemovedPrint(virConnectPtr conn ATTRIBUTE_UNUSED,
         vshEventDone(data->ctl);
 }
 
+static void
+vshEventCputunePrint(virConnectPtr conn ATTRIBUTE_UNUSED,
+                     virDomainPtr dom,
+                     virDomainCputuneInfoPtr cputune,
+                     void *opaque)
+{
+    vshDomEventData *data = opaque;
+
+    if (!data->loop && *data->count)
+        return;
+
+    vshPrint(data->ctl,
+             _("event 'cpu-tune' for domain %s:\n"),
+             virDomainGetName(dom));
+    if (cputune->sharesSpecified) {
+        vshPrint(data->ctl, _("\tshares: %llu\n"), cputune->shares);
+    } else {
+        vshPrint(data->ctl, _("\tshares: not specified\n"));
+    }
+    vshPrint(data->ctl, _("\tperiod: %llu\n\tquota: %lld\n"),
+             cputune->period, cputune->quota);
+    vshPrint(data->ctl,
+             _("\temulator_period: %llu\n\temulator_quota: %lld\n"),
+             cputune->emulatorPeriod, cputune->emulatorQuota);
+    if (cputune->emulatorpin.map) {
+        char *str = virBitmapDataToString(cputune->emulatorpin.map,
+                                          cputune->emulatorpin.mapLen);
+        vshPrint(data->ctl, _("\temulatorpin: %s\n"), str);
+        VIR_FREE(str);
+    }
+
+    if (cputune->vcpupin) {
+        size_t i;
+        for (i = 0; i < cputune->nvcpupin; i++) {
+            char *str = virBitmapDataToString(cputune->vcpupin[i].cpumask.map,
+                                              cputune->vcpupin[i].cpumask.mapLen);
+            vshPrint(data->ctl, _("\tvcpupin (vcpuid: %d): %s\n"),
+                     cputune->vcpupin[i].vcpuid, str);
+            VIR_FREE(str);
+        }
+    }
+
+    (*data->count)++;
+    if (!data->loop)
+        vshEventDone(data->ctl);
+}
+
 static vshEventCallback vshEventCallbacks[] = {
     { "lifecycle",
       VIR_DOMAIN_EVENT_CALLBACK(vshEventLifecyclePrint), },
@@ -11203,6 +11250,8 @@ static vshEventCallback vshEventCallbacks[] = {
       VIR_DOMAIN_EVENT_CALLBACK(vshEventDeviceRemovedPrint), },
     { "block-job-2",
       VIR_DOMAIN_EVENT_CALLBACK(vshEventBlockJobPrint), },
+    { "cpu-tune",
+      VIR_DOMAIN_EVENT_CALLBACK(vshEventCputunePrint), },
 };
 verify(VIR_DOMAIN_EVENT_ID_LAST == ARRAY_CARDINALITY(vshEventCallbacks));
 
-- 
1.8.5.5




More information about the libvir-list mailing list