@@ -468,6 +468,18 @@ out:
}
colo_compare_unregister_notifier(&packets_compare_notifier);
+ /*
+ * There are only two reasons we can go here, some error happened.
+ * Or the user triggered failover.
+ */
+ if (failover_get_state() == FAILOVER_STATUS_NONE) {
+ qapi_event_send_colo_exit(COLO_MODE_PRIMARY,
+ COLO_EXIT_REASON_ERROR, NULL);
+ } else {
+ qapi_event_send_colo_exit(COLO_MODE_PRIMARY,
+ COLO_EXIT_REASON_REQUEST, NULL);
+ }
+
timer_del(s->colo_delay_timer);
/* Hope this not to be too long to wait here */
@@ -708,6 +720,13 @@ out:
if (local_err) {
error_report_err(local_err);
}
+ if (failover_get_state() == FAILOVER_STATUS_NONE) {
+ qapi_event_send_colo_exit(COLO_MODE_SECONDARY,
+ COLO_EXIT_REASON_ERROR, NULL);
+ } else {
+ qapi_event_send_colo_exit(COLO_MODE_SECONDARY,
+ COLO_EXIT_REASON_REQUEST, NULL);
+ }
if (fb) {
qemu_fclose(fb);
@@ -1203,6 +1203,20 @@
'data': [ 'none', 'require', 'active', 'completed', 'relaunch' ] }
##
+# @COLOExitReason:
+#
+# The reason for a COLO exit
+#
+# @request: COLO exit is due to an external request
+#
+# @error: COLO exit is due to an internal error
+#
+# Since: 2.9
+##
+{ 'enum': 'COLOExitReason',
+ 'data': [ 'request', 'error' ] }
+
+##
# @x-colo-lost-heartbeat:
#
# Tell qemu that heartbeat is lost, request it to do takeover procedures.
@@ -441,6 +441,27 @@
'data': { 'pass': 'int' } }
##
+# @COLO_EXIT:
+#
+# Emitted when VM finishes COLO mode due to some errors happening or
+# at the request of users.
+#
+# @mode: which COLO mode the VM was in when it exited.
+#
+# @reason: describes the reason for the COLO exit.
+#
+# Since: 2.9
+#
+# Example:
+#
+# <- { "timestamp": {"seconds": 2032141960, "microseconds": 417172},
+# "event": "COLO_EXIT", "data": {"mode": "primary", "reason": "request" } }
+#
+##
+{ 'event': 'COLO_EXIT',
+ 'data': {'mode': 'COLOMode', 'reason': 'COLOExitReason' } }
+
+##
# @ACPI_DEVICE_OST:
#
# Emitted when guest executes ACPI _OST method.