Signed-off-by: Pavel Hrdina <phrdina@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list