static void test_migrate(void) { char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); QTestState *from, *to; test_migrate_start(&from, &to, uri, false); migrate_set_capability(from, "postcopy-ram", "true"); migrate_set_capability(to, "postcopy-ram", "true"); migrate_set_capability(to, "postcopy-blocktime", "true"); /* We want to pick a speed slow enough that the test completes * quickly, but that it doesn't complete precopy even on a slow * machine, so also set the downtime. */ migrate_set_parameter(from, "max-bandwidth", "100000000"); migrate_set_parameter(from, "downtime-limit", "1"); /* Wait for the first serial output from the source */ wait_for_serial("src_serial"); migrate(from, uri); wait_for_migration_pass(from); migrate_start_postcopy(from); if (!got_stop) { qtest_qmp_eventwait(from, "STOP"); } qtest_qmp_eventwait(to, "RESUME"); wait_for_serial("dest_serial"); wait_for_migration_complete(from); if (uffd_feature_thread_id) { read_blocktime(to); } g_free(uri); test_migrate_end(from, to, true); }
void qpci_unplug_acpi_device_test(QTestState *qts, const char *id, uint8_t slot) { QDict *response; response = qtest_qmp(qts, "{'execute': 'device_del'," " 'arguments': {'id': %s}}", id); g_assert(response); g_assert(!qdict_haskey(response, "error")); qobject_unref(response); qtest_outb(qts, ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot); qtest_qmp_eventwait(qts, "DEVICE_DELETED"); }
void migrate(QOSState *from, QOSState *to, const char *uri) { const char *st; QDict *rsp, *sub; bool running; set_context(from); /* Is the machine currently running? */ rsp = qmp_execute(from->qts, "query-status"); g_assert(qdict_haskey(rsp, "return")); sub = qdict_get_qdict(rsp, "return"); g_assert(qdict_haskey(sub, "running")); running = qdict_get_bool(sub, "running"); qobject_unref(rsp); /* Issue the migrate command. */ rsp = qtest_qmp(from->qts, "{ 'execute': 'migrate', 'arguments': { 'uri': %s }}", uri); g_assert(qdict_haskey(rsp, "return")); qobject_unref(rsp); /* Wait for STOP event, but only if we were running: */ if (running) { qtest_qmp_eventwait(from->qts, "STOP"); } /* If we were running, we can wait for an event. */ if (running) { migrate_allocator(from->alloc, to->alloc); set_context(to); qtest_qmp_eventwait(to->qts, "RESUME"); return; } /* Otherwise, we need to wait: poll until migration is completed. */ while (1) { rsp = qmp_execute(from->qts, "query-migrate"); g_assert(qdict_haskey(rsp, "return")); sub = qdict_get_qdict(rsp, "return"); g_assert(qdict_haskey(sub, "status")); st = qdict_get_str(sub, "status"); /* "setup", "active", "completed", "failed", "cancelled" */ if (strcmp(st, "completed") == 0) { qobject_unref(rsp); break; } if ((strcmp(st, "setup") == 0) || (strcmp(st, "active") == 0)) { qobject_unref(rsp); g_usleep(5000); continue; } fprintf(stderr, "Migration did not complete, status: %s\n", st); g_assert_not_reached(); } migrate_allocator(from->alloc, to->alloc); set_context(to); }
static void test_migrate(void) { TestServer *s = test_server_new("src"); TestServer *dest = test_server_new("dest"); char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path); QTestState *from, *to; GSource *source; gchar *cmd, *tmp; QDict *rsp; guint8 *log; guint64 size; test_server_listen(s); test_server_listen(dest); cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, "", ""); from = qtest_start(cmd); g_free(cmd); init_virtio_dev(from, s, 1u << VIRTIO_NET_F_MAC); if (!wait_for_fds(s)) { goto exit; } size = get_log_size(s); g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8)); tmp = g_strdup_printf(" -incoming %s", uri); cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, root, "", tmp); g_free(tmp); to = qtest_init(cmd); g_free(cmd); init_virtio_dev(to, dest, 1u << VIRTIO_NET_F_MAC); source = g_source_new(&test_migrate_source_funcs, sizeof(TestMigrateSource)); ((TestMigrateSource *)source)->src = s; ((TestMigrateSource *)source)->dest = dest; g_source_attach(source, NULL); /* slow down migration to have time to fiddle with log */ /* TODO: qtest could learn to break on some places */ rsp = qmp("{ 'execute': 'migrate_set_speed'," "'arguments': { 'value': 10 } }"); g_assert(qdict_haskey(rsp, "return")); qobject_unref(rsp); rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri); g_assert(qdict_haskey(rsp, "return")); qobject_unref(rsp); wait_for_log_fd(s); log = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, s->log_fd, 0); g_assert(log != MAP_FAILED); /* modify first page */ write_guest_mem(s, 0x42); log[0] = 1; munmap(log, size); /* speed things up */ rsp = qmp("{ 'execute': 'migrate_set_speed'," "'arguments': { 'value': 0 } }"); g_assert(qdict_haskey(rsp, "return")); qobject_unref(rsp); qmp_eventwait("STOP"); qtest_qmp_eventwait(to, "RESUME"); g_assert(wait_for_fds(dest)); read_guest_mem_server(to, dest); uninit_virtio_dev(dest); qtest_quit(to); g_source_destroy(source); g_source_unref(source); exit: uninit_virtio_dev(s); test_server_free(dest); qtest_quit(from); test_server_free(s); g_free(uri); }