From nobody Tue Apr 30 06:40:39 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 15078162229960.9625175417637593; Thu, 12 Oct 2017 06:50:22 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 74DBA2D0FB9; Thu, 12 Oct 2017 13:50:21 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 051AF6293C; Thu, 12 Oct 2017 13:50:21 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id E2E0F410B2; Thu, 12 Oct 2017 13:50:19 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v9CDmY1R017380 for ; Thu, 12 Oct 2017 09:48:34 -0400 Received: by smtp.corp.redhat.com (Postfix) id 9AFB318977; Thu, 12 Oct 2017 13:48:34 +0000 (UTC) Received: from virval.usersys.redhat.com (unknown [10.43.2.105]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4232F60C82 for ; Thu, 12 Oct 2017 13:48:32 +0000 (UTC) Received: by virval.usersys.redhat.com (Postfix, from userid 500) id F02891002A0; Thu, 12 Oct 2017 15:48:30 +0200 (CEST) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 74DBA2D0FB9 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=libvir-list-bounces@redhat.com From: Jiri Denemark To: libvir-list@redhat.com Date: Thu, 12 Oct 2017 15:48:29 +0200 Message-Id: <7af3b66b5fab58d25dd9edf893cc64480ceba0a1.1507815958.git.jdenemar@redhat.com> Mail-Followup-To: libvir-list@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH] qemu: Check QEMU error on failed migration X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 12 Oct 2017 13:50:22 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" When migration fails, QEMU may provide a description of the error in the reply to query-migrate QMP command. We can fetch this error and use it instead of the generic "unexpectedly failed" message. Signed-off-by: Jiri Denemark Reviewed-by: Pavel Hrdina --- src/qemu/qemu_driver.c | 3 ++- src/qemu/qemu_migration.c | 36 +++++++++++++++++++++++------------- src/qemu/qemu_migration.h | 3 ++- src/qemu/qemu_monitor.c | 8 ++++++-- src/qemu/qemu_monitor.h | 3 ++- src/qemu/qemu_monitor_json.c | 18 ++++++++++++++---- src/qemu/qemu_monitor_json.h | 3 ++- tests/qemumonitorjsontest.c | 29 ++++++++++++++++++++++++++--- 8 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 7c6f1674a9..cc79d7d4e9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -13130,7 +13130,8 @@ qemuDomainGetJobStatsInternal(virQEMUDriverPtr driv= er, jobInfo->status =3D=3D QEMU_DOMAIN_JOB_STATUS_POSTCOPY) { if (events && jobInfo->status !=3D QEMU_DOMAIN_JOB_STATUS_ACTIVE && - qemuMigrationFetchStats(driver, vm, QEMU_ASYNC_JOB_NONE, jobIn= fo) < 0) + qemuMigrationFetchStats(driver, vm, QEMU_ASYNC_JOB_NONE, + jobInfo, NULL) < 0) goto cleanup; =20 if (jobInfo->status =3D=3D QEMU_DOMAIN_JOB_STATUS_ACTIVE && diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index dd60071bfd..b286d68061 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1382,7 +1382,8 @@ int qemuMigrationFetchStats(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainAsyncJob asyncJob, - qemuDomainJobInfoPtr jobInfo) + qemuDomainJobInfoPtr jobInfo, + char **error) { qemuDomainObjPrivatePtr priv =3D vm->privateData; qemuMonitorMigrationStats stats; @@ -1391,7 +1392,7 @@ qemuMigrationFetchStats(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) return -1; =20 - rv =3D qemuMonitorGetMigrationStats(priv->mon, &stats); + rv =3D qemuMonitorGetMigrationStats(priv->mon, &stats, error); =20 if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0) return -1; @@ -1427,12 +1428,15 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver, { qemuDomainObjPrivatePtr priv =3D vm->privateData; qemuDomainJobInfoPtr jobInfo =3D priv->job.current; - + char *error =3D NULL; bool events =3D virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVE= NT); + int ret =3D -1; =20 - if (!events && - qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo) < 0) - return -1; + if (!events || + jobInfo->stats.status =3D=3D QEMU_MONITOR_MIGRATION_STATUS_ERROR) { + if (qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo, &error)= < 0) + return -1; + } =20 qemuMigrationUpdateJobType(jobInfo); =20 @@ -1440,17 +1444,18 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver, case QEMU_DOMAIN_JOB_STATUS_NONE: virReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"), qemuMigrationJobName(vm), _("is not active")); - return -1; + goto cleanup; =20 case QEMU_DOMAIN_JOB_STATUS_FAILED: virReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"), - qemuMigrationJobName(vm), _("unexpectedly failed")); - return -1; + qemuMigrationJobName(vm), + error ? error : _("unexpectedly failed")); + goto cleanup; =20 case QEMU_DOMAIN_JOB_STATUS_CANCELED: virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"), qemuMigrationJobName(vm), _("canceled by client")); - return -1; + goto cleanup; =20 case QEMU_DOMAIN_JOB_STATUS_COMPLETED: case QEMU_DOMAIN_JOB_STATUS_ACTIVE: @@ -1459,7 +1464,12 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver, case QEMU_DOMAIN_JOB_STATUS_POSTCOPY: break; } - return 0; + + ret =3D 0; + + cleanup: + VIR_FREE(error); + return ret; } =20 =20 @@ -1577,7 +1587,7 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr drive= r, } =20 if (events) - ignore_value(qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo= )); + ignore_value(qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo= , NULL)); =20 qemuDomainJobInfoUpdateTime(jobInfo); qemuDomainJobInfoUpdateDowntime(jobInfo); @@ -3177,7 +3187,7 @@ qemuMigrationConfirmPhase(virQEMUDriverPtr driver, if (virDomainObjGetState(vm, &reason) =3D=3D VIR_DOMAIN_PAUSED && reason =3D=3D VIR_DOMAIN_PAUSED_POSTCOPY && qemuMigrationFetchStats(driver, vm, QEMU_ASYNC_JOB_MIGRATION_O= UT, - jobInfo) < 0) + jobInfo, NULL) < 0) VIR_WARN("Could not refresh migration statistics"); =20 qemuDomainJobInfoUpdateTime(jobInfo); diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index 57c747934d..63a4325624 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -282,7 +282,8 @@ int qemuMigrationFetchStats(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainAsyncJob asyncJob, - qemuDomainJobInfoPtr jobInfo); + qemuDomainJobInfoPtr jobInfo, + char **error); =20 int qemuMigrationErrorInit(virQEMUDriverPtr driver); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 7a26785878..551cbb77c7 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2632,12 +2632,16 @@ qemuMonitorSetMigrationParams(qemuMonitorPtr mon, =20 int qemuMonitorGetMigrationStats(qemuMonitorPtr mon, - qemuMonitorMigrationStatsPtr stats) + qemuMonitorMigrationStatsPtr stats, + char **error) { QEMU_CHECK_MONITOR(mon); =20 + if (error) + *error =3D NULL; + if (mon->json) - return qemuMonitorJSONGetMigrationStats(mon, stats); + return qemuMonitorJSONGetMigrationStats(mon, stats, error); else return qemuMonitorTextGetMigrationStats(mon, stats); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index d9c27acaef..ed57589db1 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -695,7 +695,8 @@ struct _qemuMonitorMigrationStats { }; =20 int qemuMonitorGetMigrationStats(qemuMonitorPtr mon, - qemuMonitorMigrationStatsPtr stats); + qemuMonitorMigrationStatsPtr stats, + char **error); =20 typedef enum { QEMU_MONITOR_MIGRATION_CAPS_XBZRLE, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index a9070fe636..a4b7708b99 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2792,7 +2792,8 @@ qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, =20 static int qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply, - qemuMonitorMigrationStatsPtr stats) + qemuMonitorMigrationStatsPtr stats, + char **error) { virJSONValuePtr ret; virJSONValuePtr ram; @@ -2801,6 +2802,7 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr= reply, const char *statusstr; int rc; double mbps; + const char *tmp; =20 ret =3D virJSONValueObjectGetObject(reply, "return"); =20 @@ -2839,11 +2841,18 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValueP= tr reply, switch ((qemuMonitorMigrationStatus) stats->status) { case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: case QEMU_MONITOR_MIGRATION_STATUS_SETUP: - case QEMU_MONITOR_MIGRATION_STATUS_ERROR: case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED: case QEMU_MONITOR_MIGRATION_STATUS_LAST: break; =20 + case QEMU_MONITOR_MIGRATION_STATUS_ERROR: + if (error) { + tmp =3D virJSONValueObjectGetString(ret, "error-desc"); + if (tmp && VIR_STRDUP(*error, tmp) < 0) + return -1; + } + break; + case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE: case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY: case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED: @@ -2987,7 +2996,8 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr= reply, =20 =20 int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, - qemuMonitorMigrationStatsPtr stats) + qemuMonitorMigrationStatsPtr stats, + char **error) { int ret =3D -1; virJSONValuePtr cmd =3D qemuMonitorJSONMakeCommand("query-migrate", @@ -3005,7 +3015,7 @@ int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr m= on, if (qemuMonitorJSONCheckError(cmd, reply) < 0) goto cleanup; =20 - if (qemuMonitorJSONGetMigrationStatsReply(reply, stats) < 0) + if (qemuMonitorJSONGetMigrationStatsReply(reply, stats, error) < 0) goto cleanup; =20 ret =3D 0; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index f418c74264..7c45be6725 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -141,7 +141,8 @@ int qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mo= n, qemuMonitorMigrationParamsPtr params= ); =20 int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, - qemuMonitorMigrationStatsPtr stats); + qemuMonitorMigrationStatsPtr stats, + char **error); =20 int qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon, char ***capabilities); diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index df3ef0a932..475fd270e1 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1907,6 +1907,7 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStats(c= onst void *data) qemuMonitorTestPtr test =3D qemuMonitorTestNewSimple(true, xmlopt); int ret =3D -1; qemuMonitorMigrationStats stats, expectedStats; + char *error =3D NULL; =20 if (!test) return -1; @@ -1931,21 +1932,43 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStats= (const void *data) " }" " }," " \"id\": \"libvirt-13\"" + "}") < 0 || + qemuMonitorTestAddItem(test, "query-migrate", + "{" + " \"return\": {" + " \"status\": \"failed\"," + " \"error-desc\": \"It's broken\"" + " }," + " \"id\": \"libvirt-14\"" "}") < 0) goto cleanup; =20 - if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test), = &stats) < 0) + if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test), + &stats, &error) < 0) goto cleanup; =20 - if (memcmp(&stats, &expectedStats, sizeof(stats)) !=3D 0) { + if (memcmp(&stats, &expectedStats, sizeof(stats)) !=3D 0 || error) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - "Invalid migration status"); + "Invalid migration statistics"); + goto cleanup; + } + + memset(&stats, 0, sizeof(stats)); + if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test), + &stats, &error) < 0) + goto cleanup; + + if (stats.status !=3D QEMU_MONITOR_MIGRATION_STATUS_ERROR || + STRNEQ_NULLABLE(error, "It's broken")) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + "Invalid failed migration status"); goto cleanup; } =20 ret =3D 0; cleanup: qemuMonitorTestFree(test); + VIR_FREE(error); return ret; } =20 --=20 2.14.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list