jobInfo->status == QEMU_DOMAIN_JOB_STATUS_POSTCOPY) {
if (events &&
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;
if (jobInfo->status == QEMU_DOMAIN_JOB_STATUS_ACTIVE &&
qemuMigrationFetchStats(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob,
- qemuDomainJobInfoPtr jobInfo)
+ qemuDomainJobInfoPtr jobInfo,
+ char **error)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
qemuMonitorMigrationStats stats;
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1;
- rv = qemuMonitorGetMigrationStats(priv->mon, &stats);
+ rv = qemuMonitorGetMigrationStats(priv->mon, &stats, error);
if (qemuDomainObjExitMonitor(driver, vm) < 0 || rv < 0)
return -1;
{
qemuDomainObjPrivatePtr priv = vm->privateData;
qemuDomainJobInfoPtr jobInfo = priv->job.current;
-
+ char *error = NULL;
bool events = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MIGRATION_EVENT);
+ int ret = -1;
- if (!events &&
- qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo) < 0)
- return -1;
+ if (!events ||
+ jobInfo->stats.status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) {
+ if (qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo, &error) < 0)
+ return -1;
+ }
qemuMigrationUpdateJobType(jobInfo);
case QEMU_DOMAIN_JOB_STATUS_NONE:
virReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"),
qemuMigrationJobName(vm), _("is not active"));
- return -1;
+ goto cleanup;
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;
case QEMU_DOMAIN_JOB_STATUS_CANCELED:
virReportError(VIR_ERR_OPERATION_ABORTED, _("%s: %s"),
qemuMigrationJobName(vm), _("canceled by client"));
- return -1;
+ goto cleanup;
case QEMU_DOMAIN_JOB_STATUS_COMPLETED:
case QEMU_DOMAIN_JOB_STATUS_ACTIVE:
case QEMU_DOMAIN_JOB_STATUS_POSTCOPY:
break;
}
- return 0;
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(error);
+ return ret;
}
}
if (events)
- ignore_value(qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo));
+ ignore_value(qemuMigrationFetchStats(driver, vm, asyncJob, jobInfo, NULL));
qemuDomainJobInfoUpdateTime(jobInfo);
qemuDomainJobInfoUpdateDowntime(jobInfo);
if (virDomainObjGetState(vm, &reason) == VIR_DOMAIN_PAUSED &&
reason == VIR_DOMAIN_PAUSED_POSTCOPY &&
qemuMigrationFetchStats(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT,
- jobInfo) < 0)
+ jobInfo, NULL) < 0)
VIR_WARN("Could not refresh migration statistics");
qemuDomainJobInfoUpdateTime(jobInfo);
qemuMigrationFetchStats(virQEMUDriverPtr driver,
virDomainObjPtr vm,
qemuDomainAsyncJob asyncJob,
- qemuDomainJobInfoPtr jobInfo);
+ qemuDomainJobInfoPtr jobInfo,
+ char **error);
int
qemuMigrationErrorInit(virQEMUDriverPtr driver);
int
qemuMonitorGetMigrationStats(qemuMonitorPtr mon,
- qemuMonitorMigrationStatsPtr stats)
+ qemuMonitorMigrationStatsPtr stats,
+ char **error)
{
QEMU_CHECK_MONITOR(mon);
+ if (error)
+ *error = NULL;
+
if (mon->json)
- return qemuMonitorJSONGetMigrationStats(mon, stats);
+ return qemuMonitorJSONGetMigrationStats(mon, stats, error);
else
return qemuMonitorTextGetMigrationStats(mon, stats);
}
};
int qemuMonitorGetMigrationStats(qemuMonitorPtr mon,
- qemuMonitorMigrationStatsPtr stats);
+ qemuMonitorMigrationStatsPtr stats,
+ char **error);
typedef enum {
QEMU_MONITOR_MIGRATION_CAPS_XBZRLE,
static int
qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply,
- qemuMonitorMigrationStatsPtr stats)
+ qemuMonitorMigrationStatsPtr stats,
+ char **error)
{
virJSONValuePtr ret;
virJSONValuePtr ram;
const char *statusstr;
int rc;
double mbps;
+ const char *tmp;
ret = virJSONValueObjectGetObject(reply, "return");
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;
+ 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_POSTCOPY:
case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon,
- qemuMonitorMigrationStatsPtr stats)
+ qemuMonitorMigrationStatsPtr stats,
+ char **error)
{
int ret = -1;
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-migrate",
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
goto cleanup;
- if (qemuMonitorJSONGetMigrationStatsReply(reply, stats) < 0)
+ if (qemuMonitorJSONGetMigrationStatsReply(reply, stats, error) < 0)
goto cleanup;
ret = 0;
qemuMonitorMigrationParamsPtr params);
int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon,
- qemuMonitorMigrationStatsPtr stats);
+ qemuMonitorMigrationStatsPtr stats,
+ char **error);
int qemuMonitorJSONGetMigrationCapabilities(qemuMonitorPtr mon,
char ***capabilities);
qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt);
int ret = -1;
qemuMonitorMigrationStats stats, expectedStats;
+ char *error = NULL;
if (!test)
return -1;
" }"
" },"
" \"id\": \"libvirt-13\""
+ "}") < 0 ||
+ qemuMonitorTestAddItem(test, "query-migrate",
+ "{"
+ " \"return\": {"
+ " \"status\": \"failed\","
+ " \"error-desc\": \"It's broken\""
+ " },"
+ " \"id\": \"libvirt-14\""
"}") < 0)
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;
- 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",
- "Invalid migration status");
+ "Invalid failed migration status");
goto cleanup;
}
ret = 0;
cleanup:
qemuMonitorTestFree(test);
+ VIR_FREE(error);
return ret;
}