src/libvirt-domain.c | 26 +++++++++++++------------- src/qemu/qemu_migration.c | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-)
When migration fails in Perform phase, we call Finish on the destination
host with cancelled=1 and get the error from there and report it to the
user. This works well if the error on the destination caused the
migration to fail. But in other cases the main error may reported by the
source and the destination would just be complaining about broken
migration stream.
In other words, we don't really know which error caused the migration to
fail and we have no way of detecting that. So instead of choosing one
error, this patch will combine the error messages from both sides of
migration into a single message and report it to the user. The result
would be, for example:
operation failed: migration failed. Message from the source host:
operation failed: job 'migration out' failed: Certificate does not
match the hostname ble.bla. Message from the destination host:
operation failed: job 'migration in' failed: load of migration
failed: Invalid argument
And yes, this is ugly, but I wasn't able to come up with a better way of
fixing this issue.
https://issues.redhat.com/browse/RHEL-58933
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/libvirt-domain.c | 26 +++++++++++++-------------
src/qemu/qemu_migration.c | 26 +++++++++++++-------------
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index e8e5379672..efccafc4d2 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -3430,26 +3430,26 @@ virDomainMigrateVersion3Full(virDomainPtr domain,
if (ddomain) {
VIR_ERROR(_("finish step ignored that migration was cancelled"));
} else {
- /* If Finish reported a useful error, use it instead of the
- * original "migration unexpectedly failed" error.
+ virErrorPtr err = virGetLastError();
+ /* When both Confirm and Finish reported an error in QEMU driver,
+ * we don't really know which error is the root cause. Let's report
+ * both errors to the user.
*
* This is ugly but we can't do better with the APIs we have. We
* only replace the error if Finish was called with cancelled == 1
* and reported a real error (old libvirt would report an error
- * from RPC instead of MIGRATE_FINISH_OK), which only happens when
- * the domain died on destination. To further reduce a possibility
- * of false positives we also check that Perform returned
- * VIR_ERR_OPERATION_FAILED.
+ * from RPC instead of MIGRATE_FINISH_OK).
*/
if (orig_err &&
orig_err->domain == VIR_FROM_QEMU &&
- orig_err->code == VIR_ERR_OPERATION_FAILED) {
- virErrorPtr err = virGetLastError();
- if (err &&
- err->domain == VIR_FROM_QEMU &&
- err->code != VIR_ERR_MIGRATE_FINISH_OK) {
- g_clear_pointer(&orig_err, virFreeError);
- }
+ orig_err->code == VIR_ERR_OPERATION_FAILED &&
+ err &&
+ err->domain == VIR_FROM_QEMU &&
+ err->code != VIR_ERR_MIGRATE_FINISH_OK) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("migration failed. Message from the source host: %1$s. Message from the destination host: %2$s"),
+ orig_err->message, err->message);
+ g_clear_pointer(&orig_err, virFreeError);
}
}
}
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1582a738a3..8c0e522828 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -5904,26 +5904,26 @@ qemuMigrationSrcPerformPeer2Peer3(virQEMUDriver *driver,
if (ddomain) {
VIR_ERROR(_("finish step ignored that migration was cancelled"));
} else {
- /* If Finish reported a useful error, use it instead of the
- * original "migration unexpectedly failed" error.
+ virErrorPtr err = virGetLastError();
+ /* When both Confirm and Finish reported an error in QEMU driver,
+ * we don't really know which error is the root cause. Let's report
+ * both errors to the user.
*
* This is ugly but we can't do better with the APIs we have. We
* only replace the error if Finish was called with cancelled == 1
* and reported a real error (old libvirt would report an error
- * from RPC instead of MIGRATE_FINISH_OK), which only happens when
- * the domain died on destination. To further reduce a possibility
- * of false positives we also check that Perform returned
- * VIR_ERR_OPERATION_FAILED.
+ * from RPC instead of MIGRATE_FINISH_OK).
*/
if (orig_err &&
orig_err->domain == VIR_FROM_QEMU &&
- orig_err->code == VIR_ERR_OPERATION_FAILED) {
- virErrorPtr err = virGetLastError();
- if (err &&
- err->domain == VIR_FROM_QEMU &&
- err->code != VIR_ERR_MIGRATE_FINISH_OK) {
- g_clear_pointer(&orig_err, virFreeError);
- }
+ orig_err->code == VIR_ERR_OPERATION_FAILED &&
+ err &&
+ err->domain == VIR_FROM_QEMU &&
+ err->code != VIR_ERR_MIGRATE_FINISH_OK) {
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("migration failed. Message from the source host: %1$s. Message from the destination host: %2$s"),
+ orig_err->message, err->message);
+ g_clear_pointer(&orig_err, virFreeError);
}
}
}
--
2.47.1
On a Wednesday in 2025, Jiri Denemark wrote: >When migration fails in Perform phase, we call Finish on the destination >host with cancelled=1 and get the error from there and report it to the >user. This works well if the error on the destination caused the >migration to fail. But in other cases the main error may reported by the >source and the destination would just be complaining about broken >migration stream. > >In other words, we don't really know which error caused the migration to >fail and we have no way of detecting that. So instead of choosing one >error, this patch will combine the error messages from both sides of >migration into a single message and report it to the user. The result >would be, for example: > > operation failed: migration failed. Message from the source host: > operation failed: job 'migration out' failed: Certificate does not > match the hostname ble.bla. Message from the destination host: > operation failed: job 'migration in' failed: load of migration > failed: Invalid argument > >And yes, this is ugly, but I wasn't able to come up with a better way of >fixing this issue. > Ugly, but more user-friendly. >https://issues.redhat.com/browse/RHEL-58933 > >Signed-off-by: Jiri Denemark <jdenemar@redhat.com> >--- > src/libvirt-domain.c | 26 +++++++++++++------------- > src/qemu/qemu_migration.c | 26 +++++++++++++------------- > 2 files changed, 26 insertions(+), 26 deletions(-) > Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
© 2016 - 2025 Red Hat, Inc.