@@ -28,6 +28,7 @@
#include "net/colo-compare.h"
#include "net/colo.h"
#include "block/block.h"
+#include "qapi/qapi-events-migration.h"
static bool vmstate_loading;
static Notifier packets_compare_notifier;
@@ -514,6 +515,18 @@ out:
qemu_fclose(fb);
}
+ /*
+ * 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);
+ }
+
/* Hope this not to be too long to wait here */
qemu_sem_wait(&s->colo_exit_sem);
qemu_sem_destroy(&s->colo_exit_sem);
@@ -744,6 +757,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);
@@ -874,6 +874,43 @@
{ 'enum': 'FailoverStatus',
'data': [ 'none', 'require', 'active', 'completed', 'relaunch' ] }
+##
+# @COLO_EXIT:
+#
+# Emitted when VM finishes COLO mode due to some errors happening or
+# at the request of users.
+#
+# @mode: report COLO mode when COLO exited.
+#
+# @reason: describes the reason for the COLO exit.
+#
+# Since: 2.13
+#
+# Example:
+#
+# <- { "timestamp": {"seconds": 2032141960, "microseconds": 417172},
+# "event": "COLO_EXIT", "data": {"mode": "primary", "reason": "request" } }
+#
+##
+{ 'event': 'COLO_EXIT',
+ 'data': {'mode': 'COLOMode', 'reason': 'COLOExitReason' } }
+
+##
+# @COLOExitReason:
+#
+# The reason for a COLO exit
+#
+# @none: no failover has ever happened.
+#
+# @request: COLO exit is due to an external request
+#
+# @error: COLO exit is due to an internal error
+#
+# Since: 2.13
+##
+{ 'enum': 'COLOExitReason',
+ 'data': [ 'none', 'request', 'error' ] }
+
##
# @x-colo-lost-heartbeat:
#