提交 e1ca8ecb 编写于 作者: J Jiri Denemark

qemu: Check QEMU error on failed migration

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: NJiri Denemark <jdenemar@redhat.com>
Reviewed-by: NPavel Hrdina <phrdina@redhat.com>
上级 befe2018
...@@ -13117,7 +13117,8 @@ qemuDomainGetJobStatsInternal(virQEMUDriverPtr driver, ...@@ -13117,7 +13117,8 @@ qemuDomainGetJobStatsInternal(virQEMUDriverPtr driver,
jobInfo->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY) { jobInfo->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY) {
if (events && if (events &&
jobInfo->status != QEMU_DOMAIN_JOB_STATUS_ACTIVE && jobInfo->status != QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
qemuMigrationFetchStats(driver, vm, QEMU_ASYNC_JOB_NONE, jobInfo) < 0) qemuMigrationFetchStats(driver, vm, QEMU_ASYNC_JOB_NONE,
jobInfo, NULL) < 0)
goto cleanup; goto cleanup;
if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE && if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
......
...@@ -1382,7 +1382,8 @@ int ...@@ -1382,7 +1382,8 @@ int
qemuMigrationFetchStats(virQEMUDriverPtr driver, qemuMigrationFetchStats(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob, qemuDomainAsyncJob asyncJob,
qemuDomainJobInfoPtr jobInfo) qemuDomainJobInfoPtr jobInfo,
char **error)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
qemuMonitorMigrationStats stats; qemuMonitorMigrationStats stats;
...@@ -1391,7 +1392,7 @@ qemuMigrationFetchStats(virQEMUDriverPtr driver, ...@@ -1391,7 +1392,7 @@ qemuMigrationFetchStats(virQEMUDriverPtr driver,
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1; return -1;
rv = qemuMonitorGetMigrationStats(priv->mon, &stats); rv = qemuMonitorGetMigrationStats(priv->mon, &stats, error);
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0) if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
return -1; return -1;
...@@ -1427,12 +1428,15 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver, ...@@ -1427,12 +1428,15 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver,
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
qemuDomainJobInfoPtr jobInfo = priv->job.current; qemuDomainJobInfoPtr jobInfo = priv->job.current;
char *error = NULL;
bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT); bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
int ret = -1;
if (!events && if (!events ||
qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo) < 0) jobInfo->stats.status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) {
return -1; if (qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo, &error) < 0)
return -1;
}
qemuMigrationUpdateJobType(jobInfo); qemuMigrationUpdateJobType(jobInfo);
...@@ -1440,17 +1444,18 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver, ...@@ -1440,17 +1444,18 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver,
case QEMU_DOMAIN_JOB_STATUS_NONE: case QEMU_DOMAIN_JOB_STATUS_NONE:
virReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"), virReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"),
qemuMigrationJobName(vm), _("is not active")); qemuMigrationJobName(vm), _("is not active"));
return -1; goto cleanup;
case QEMU_DOMAIN_JOB_STATUS_FAILED: case QEMU_DOMAIN_JOB_STATUS_FAILED:
virReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"), virReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"),
qemuMigrationJobName(vm), _("unexpectedly failed")); qemuMigrationJobName(vm),
return -1; error ? error : _("unexpectedly failed"));
goto cleanup;
case QEMU_DOMAIN_JOB_STATUS_CANCELED: case QEMU_DOMAIN_JOB_STATUS_CANCELED:
virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"), virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
qemuMigrationJobName(vm), _("canceled by client")); qemuMigrationJobName(vm), _("canceled by client"));
return -1; goto cleanup;
case QEMU_DOMAIN_JOB_STATUS_COMPLETED: case QEMU_DOMAIN_JOB_STATUS_COMPLETED:
case QEMU_DOMAIN_JOB_STATUS_ACTIVE: case QEMU_DOMAIN_JOB_STATUS_ACTIVE:
...@@ -1459,7 +1464,12 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver, ...@@ -1459,7 +1464,12 @@ qemuMigrationCheckJobStatus(virQEMUDriverPtr driver,
case QEMU_DOMAIN_JOB_STATUS_POSTCOPY: case QEMU_DOMAIN_JOB_STATUS_POSTCOPY:
break; break;
} }
return 0;
ret = 0;
cleanup:
VIR_FREE(error);
return ret;
} }
...@@ -1577,7 +1587,7 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver, ...@@ -1577,7 +1587,7 @@ qemuMigrationWaitForCompletion(virQEMUDriverPtr driver,
} }
if (events) if (events)
ignore_value(qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo)); ignore_value(qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo, NULL));
qemuDomainJobInfoUpdateTime(jobInfo); qemuDomainJobInfoUpdateTime(jobInfo);
qemuDomainJobInfoUpdateDowntime(jobInfo); qemuDomainJobInfoUpdateDowntime(jobInfo);
...@@ -3177,7 +3187,7 @@ qemuMigrationConfirmPhase(virQEMUDriverPtr driver, ...@@ -3177,7 +3187,7 @@ qemuMigrationConfirmPhase(virQEMUDriverPtr driver,
if (virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED && if (virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
reason == VIR_DOMAIN_PAUSED_POSTCOPY && reason == VIR_DOMAIN_PAUSED_POSTCOPY &&
qemuMigrationFetchStats(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, qemuMigrationFetchStats(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
jobInfo) < 0) jobInfo, NULL) < 0)
VIR_WARN("Could not refresh migration statistics"); VIR_WARN("Could not refresh migration statistics");
qemuDomainJobInfoUpdateTime(jobInfo); qemuDomainJobInfoUpdateTime(jobInfo);
......
...@@ -282,7 +282,8 @@ int ...@@ -282,7 +282,8 @@ int
qemuMigrationFetchStats(virQEMUDriverPtr driver, qemuMigrationFetchStats(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob, qemuDomainAsyncJob asyncJob,
qemuDomainJobInfoPtr jobInfo); qemuDomainJobInfoPtr jobInfo,
char **error);
int int
qemuMigrationErrorInit(virQEMUDriverPtr driver); qemuMigrationErrorInit(virQEMUDriverPtr driver);
......
...@@ -2632,12 +2632,16 @@ qemuMonitorSetMigrationParams(qemuMonitorPtr mon, ...@@ -2632,12 +2632,16 @@ qemuMonitorSetMigrationParams(qemuMonitorPtr mon,
int int
qemuMonitorGetMigrationStats(qemuMonitorPtr mon, qemuMonitorGetMigrationStats(qemuMonitorPtr mon,
qemuMonitorMigrationStatsPtr stats) qemuMonitorMigrationStatsPtr stats,
char **error)
{ {
QEMU_CHECK_MONITOR(mon); QEMU_CHECK_MONITOR(mon);
if (error)
*error = NULL;
if (mon->json) if (mon->json)
return qemuMonitorJSONGetMigrationStats(mon, stats); return qemuMonitorJSONGetMigrationStats(mon, stats, error);
else else
return qemuMonitorTextGetMigrationStats(mon, stats); return qemuMonitorTextGetMigrationStats(mon, stats);
} }
......
...@@ -696,7 +696,8 @@ struct _qemuMonitorMigrationStats { ...@@ -696,7 +696,8 @@ struct _qemuMonitorMigrationStats {
}; };
int qemuMonitorGetMigrationStats(qemuMonitorPtr mon, int qemuMonitorGetMigrationStats(qemuMonitorPtr mon,
qemuMonitorMigrationStatsPtr stats); qemuMonitorMigrationStatsPtr stats,
char **error);
typedef enum { typedef enum {
QEMU_MONITOR_MIGRATION_CAPS_XBZRLE, QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
......
...@@ -2792,7 +2792,8 @@ qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, ...@@ -2792,7 +2792,8 @@ qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon,
static int static int
qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply, qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply,
qemuMonitorMigrationStatsPtr stats) qemuMonitorMigrationStatsPtr stats,
char **error)
{ {
virJSONValuePtr ret; virJSONValuePtr ret;
virJSONValuePtr ram; virJSONValuePtr ram;
...@@ -2801,6 +2802,7 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply, ...@@ -2801,6 +2802,7 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply,
const char *statusstr; const char *statusstr;
int rc; int rc;
double mbps; double mbps;
const char *tmp;
ret = virJSONValueObjectGetObject(reply, "return"); ret = virJSONValueObjectGetObject(reply, "return");
...@@ -2839,11 +2841,18 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply, ...@@ -2839,11 +2841,18 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply,
switch ((qemuMonitorMigrationStatus) stats->status) { switch ((qemuMonitorMigrationStatus) stats->status) {
case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE:
case QEMU_MONITOR_MIGRATION_STATUS_SETUP: case QEMU_MONITOR_MIGRATION_STATUS_SETUP:
case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED: case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED:
case QEMU_MONITOR_MIGRATION_STATUS_LAST: case QEMU_MONITOR_MIGRATION_STATUS_LAST:
break; break;
case QEMU_MONITOR_MIGRATION_STATUS_ERROR:
if (error) {
tmp = 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_ACTIVE:
case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY: case QEMU_MONITOR_MIGRATION_STATUS_POSTCOPY:
case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED: case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
...@@ -2989,7 +2998,8 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply, ...@@ -2989,7 +2998,8 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply,
int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon,
qemuMonitorMigrationStatsPtr stats) qemuMonitorMigrationStatsPtr stats,
char **error)
{ {
int ret = -1; int ret = -1;
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate", virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate",
...@@ -3007,7 +3017,7 @@ int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, ...@@ -3007,7 +3017,7 @@ int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon,
if (qemuMonitorJSONCheckError(cmd, reply) < 0) if (qemuMonitorJSONCheckError(cmd, reply) < 0)
goto cleanup; goto cleanup;
if (qemuMonitorJSONGetMigrationStatsReply(reply, stats) < 0) if (qemuMonitorJSONGetMigrationStatsReply(reply, stats, error) < 0)
goto cleanup; goto cleanup;
ret = 0; ret = 0;
......
...@@ -141,7 +141,8 @@ int qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, ...@@ -141,7 +141,8 @@ int qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon,
qemuMonitorMigrationParamsPtr params); qemuMonitorMigrationParamsPtr params);
int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon,
qemuMonitorMigrationStatsPtr stats); qemuMonitorMigrationStatsPtr stats,
char **error);
int qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon, int qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon,
char ***capabilities); char ***capabilities);
......
...@@ -1907,6 +1907,7 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStats(const void *data) ...@@ -1907,6 +1907,7 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStats(const void *data)
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt); qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
int ret = -1; int ret = -1;
qemuMonitorMigrationStats stats, expectedStats; qemuMonitorMigrationStats stats, expectedStats;
char *error = NULL;
if (!test) if (!test)
return -1; return -1;
...@@ -1931,21 +1932,43 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStats(const void *data) ...@@ -1931,21 +1932,43 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationStats(const void *data)
" }" " }"
" }," " },"
" \"id\": \"libvirt-13\"" " \"id\": \"libvirt-13\""
"}") < 0 ||
qemuMonitorTestAddItem(test, "query-migrate",
"{"
" \"return\": {"
" \"status\": \"failed\","
" \"error-desc\": \"It's broken\""
" },"
" \"id\": \"libvirt-14\""
"}") < 0) "}") < 0)
goto cleanup; goto cleanup;
if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test), &stats) < 0) if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test),
&stats, &error) < 0)
goto cleanup;
if (memcmp(&stats, &expectedStats, sizeof(stats)) != 0 || error) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
"Invalid migration statistics");
goto cleanup;
}
memset(&stats, 0, sizeof(stats));
if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test),
&stats, &error) < 0)
goto cleanup; goto cleanup;
if (memcmp(&stats, &expectedStats, sizeof(stats)) != 0) { if (stats.status != QEMU_MONITOR_MIGRATION_STATUS_ERROR ||
STRNEQ_NULLABLE(error, "It's broken")) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
"Invalid migration status"); "Invalid failed migration status");
goto cleanup; goto cleanup;
} }
ret = 0; ret = 0;
cleanup: cleanup:
qemuMonitorTestFree(test); qemuMonitorTestFree(test);
VIR_FREE(error);
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册