Implement memory failure event for virsh command and test.
Notice:
The full patch set includes 4 patches:
virsh: implement memory failure event (current patch)
qemu: monitor: handle memory failure event
qemu: process: implement domainMemoryFailure
API: introduce memory failure
To avoid build/test errors, the 4 patches should be merged/removed
together. Test all the patches with a little complex environment
(nested KVM):
1, install newly built libvirt in L1, and start a L2 vm. run command
in L1:
~# virsh event l2 --event memory-failure
2, run command in L0 to inject MCE to L1:
~# virsh qemu-monitor-command l1 --hmp mce 0 9 0xbd000000000000c0 0xd 0x62000000 0x8c
Test result in l1(recipient hypervisor case):
event 'memory-failure' for domain l2:
recipient: hypervisor
action: ignore
flags:
action required: 0
recursive: 0
Test result in l1(recipient guest case):
event 'memory-failure' for domain l2:
recipient: guest
action: inject
flags:
action required: 0
recursive: 0
Signed-off-by: zhenwei pi <pizhenwei(a)bytedance.com>
---
examples/c/misc/event-test.c | 16 ++++++++++++++++
tools/virsh-domain.c | 40 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/examples/c/misc/event-test.c b/examples/c/misc/event-test.c
index 52caa8ffa8..1651efe019 100644
--- a/examples/c/misc/event-test.c
+++ b/examples/c/misc/event-test.c
@@ -964,6 +964,21 @@ myDomainEventBlockThresholdCallback(virConnectPtr conn
G_GNUC_UNUSED,
static int
+myDomainEventMemoryFailureCallback(virConnectPtr conn G_GNUC_UNUSED,
+ virDomainPtr dom,
+ virDomainMemoryFailureRecipientType recipient,
+ virDomainMemoryFailureActionType action,
+ unsigned int flags,
+ void *opaque G_GNUC_UNUSED)
+{
+ printf("%s EVENT: Domain %s(%d) memory failure: recipient '%d', "
+ "aciont '%d', flags '%d'", __func__,
virDomainGetName(dom),
+ virDomainGetID(dom), recipient, action, flags);
+ return 0;
+}
+
+
+static int
myDomainEventMigrationIterationCallback(virConnectPtr conn G_GNUC_UNUSED,
virDomainPtr dom,
int iteration,
@@ -1093,6 +1108,7 @@ struct domainEventData domainEvents[] = {
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED,
myDomainEventDeviceRemovalFailedCallback),
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_METADATA_CHANGE,
myDomainEventMetadataChangeCallback),
DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD,
myDomainEventBlockThresholdCallback),
+ DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE,
myDomainEventMemoryFailureCallback),
};
struct storagePoolEventData {
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 8f11393197..2bfb33e528 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13590,6 +13590,44 @@ virshEventBlockThresholdPrint(virConnectPtr conn G_GNUC_UNUSED,
}
+VIR_ENUM_DECL(virshEventMemoryFailureRecipientType);
+VIR_ENUM_IMPL(virshEventMemoryFailureRecipientType,
+ VIR_DOMAIN_EVENT_MEMORY_FAILURE_RECIPIENT_LAST,
+ N_("hypervisor"),
+ N_("guest"));
+
+VIR_ENUM_DECL(virshEventMemoryFailureActionType);
+VIR_ENUM_IMPL(virshEventMemoryFailureActionType,
+ VIR_DOMAIN_EVENT_MEMORY_FAILURE_ACTION_LAST,
+ N_("ignore"),
+ N_("inject"),
+ N_("fatal"),
+ N_("reset"));
+
+static void
+virshEventMemoryFailurePrint(virConnectPtr conn G_GNUC_UNUSED,
+ virDomainPtr dom,
+ virDomainMemoryFailureRecipientType recipient,
+ virDomainMemoryFailureActionType action,
+ unsigned int flags,
+ void *opaque)
+{
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+
+ virBufferAsprintf(&buf, _("event 'memory-failure' for domain
%s:\n"
+ "recipient: %s\naction: %s\n"),
+ virDomainGetName(dom),
+
UNKNOWNSTR(virshEventMemoryFailureRecipientTypeTypeToString(recipient)),
+
UNKNOWNSTR(virshEventMemoryFailureActionTypeTypeToString(action)));
+ virBufferAsprintf(&buf, _("flags:\n"
+ "\taction required: %d\n\trecursive: %d\n"),
+ !!(flags & VIR_DOMAIN_MEMORY_FAILURE_ACTION_REQUIRED),
+ !!(flags & VIR_DOMAIN_MEMORY_FAILURE_RECURSIVE));
+
+ virshEventPrint(opaque, &buf);
+}
+
+
virshDomainEventCallback virshDomainEventCallbacks[] = {
{ "lifecycle",
VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
@@ -13639,6 +13677,8 @@ virshDomainEventCallback virshDomainEventCallbacks[] = {
VIR_DOMAIN_EVENT_CALLBACK(virshEventMetadataChangePrint), },
{ "block-threshold",
VIR_DOMAIN_EVENT_CALLBACK(virshEventBlockThresholdPrint), },
+ { "memory-failure",
+ VIR_DOMAIN_EVENT_CALLBACK(virshEventMemoryFailurePrint), },
};
G_STATIC_ASSERT(VIR_DOMAIN_EVENT_ID_LAST == G_N_ELEMENTS(virshDomainEventCallbacks));
--
2.11.0