]> git.proxmox.com Git - mirror_qemu.git/blame - tests/migration-test.c
docs: Convert migration.txt to rst
[mirror_qemu.git] / tests / migration-test.c
CommitLineData
ea0c6d62 1/*
2656bfd9 2 * QTest testcase for migration
ea0c6d62
DDAG
3 *
4 * Copyright (c) 2016 Red Hat, Inc. and/or its affiliates
5 * based on the vhost-user-test.c that is:
6 * Copyright (c) 2014 Virtual Open Systems Sarl.
7 *
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
10 *
11 */
12
13#include "qemu/osdep.h"
ea0c6d62
DDAG
14
15#include "libqtest.h"
16#include "qemu/option.h"
17#include "qemu/range.h"
a9c94277 18#include "qemu/sockets.h"
8228e353 19#include "chardev/char.h"
ea0c6d62 20#include "sysemu/sysemu.h"
ad723fe5 21#include "hw/nvram/chrp_nvram.h"
aaf89c8a 22
23#define MIN_NVRAM_SIZE 8192 /* from spapr_nvram.c */
ea0c6d62 24
ea0c6d62
DDAG
25const unsigned start_address = 1024 * 1024;
26const unsigned end_address = 100 * 1024 * 1024;
27bool got_stop;
28
29#if defined(__linux__)
ea0c6d62
DDAG
30#include <sys/syscall.h>
31#include <sys/vfs.h>
32#endif
33
34#if defined(__linux__) && defined(__NR_userfaultfd) && defined(CONFIG_EVENTFD)
35#include <sys/eventfd.h>
36#include <sys/ioctl.h>
37#include <linux/userfaultfd.h>
38
39static bool ufd_version_check(void)
40{
41 struct uffdio_api api_struct;
42 uint64_t ioctl_mask;
43
e1ae9fb6 44 int ufd = syscall(__NR_userfaultfd, O_CLOEXEC);
ea0c6d62
DDAG
45
46 if (ufd == -1) {
47 g_test_message("Skipping test: userfaultfd not available");
48 return false;
49 }
50
51 api_struct.api = UFFD_API;
52 api_struct.features = 0;
53 if (ioctl(ufd, UFFDIO_API, &api_struct)) {
54 g_test_message("Skipping test: UFFDIO_API failed");
55 return false;
56 }
57
58 ioctl_mask = (__u64)1 << _UFFDIO_REGISTER |
59 (__u64)1 << _UFFDIO_UNREGISTER;
60 if ((api_struct.ioctls & ioctl_mask) != ioctl_mask) {
61 g_test_message("Skipping test: Missing userfault feature");
62 return false;
63 }
64
65 return true;
66}
67
68#else
69static bool ufd_version_check(void)
70{
71 g_test_message("Skipping test: Userfault not available (builtdtime)");
72 return false;
73}
74
75#endif
76
77static const char *tmpfs;
78
79/* A simple PC boot sector that modifies memory (1-100MB) quickly
80 * outputing a 'B' every so often if it's still running.
81 */
82unsigned char bootsect[] = {
83 0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
84 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
86 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41,
87 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10,
88 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40,
89 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x75, 0xe9, 0x66, 0xb8, 0x42, 0x00, 0x66,
90 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xde, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
92 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x5c, 0x7c,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
126};
127
aaf89c8a 128static void init_bootfile_x86(const char *bootpath)
129{
130 FILE *bootfile = fopen(bootpath, "wb");
131
132 g_assert_cmpint(fwrite(bootsect, 512, 1, bootfile), ==, 1);
133 fclose(bootfile);
134}
135
136static void init_bootfile_ppc(const char *bootpath)
137{
138 FILE *bootfile;
139 char buf[MIN_NVRAM_SIZE];
ad723fe5 140 ChrpNvramPartHdr *header = (ChrpNvramPartHdr *)buf;
aaf89c8a 141
142 memset(buf, 0, MIN_NVRAM_SIZE);
143
144 /* Create a "common" partition in nvram to store boot-command property */
145
ad723fe5 146 header->signature = CHRP_NVPART_SYSTEM;
aaf89c8a 147 memcpy(header->name, "common", 6);
ad723fe5 148 chrp_nvram_finish_partition(header, MIN_NVRAM_SIZE);
aaf89c8a 149
150 /* FW_MAX_SIZE is 4MB, but slof.bin is only 900KB,
151 * so let's modify memory between 1MB and 100MB
152 * to do like PC bootsector
153 */
154
155 sprintf(buf + 16,
156 "boot-command=hex .\" _\" begin %x %x do i c@ 1 + i c! 1000 +loop "
157 ".\" B\" 0 until", end_address, start_address);
158
159 /* Write partition to the NVRAM file */
160
161 bootfile = fopen(bootpath, "wb");
162 g_assert_cmpint(fwrite(buf, MIN_NVRAM_SIZE, 1, bootfile), ==, 1);
163 fclose(bootfile);
164}
165
ea0c6d62
DDAG
166/*
167 * Wait for some output in the serial output file,
168 * we get an 'A' followed by an endless string of 'B's
169 * but on the destination we won't have the A.
170 */
171static void wait_for_serial(const char *side)
172{
173 char *serialpath = g_strdup_printf("%s/%s", tmpfs, side);
174 FILE *serialfile = fopen(serialpath, "r");
aaf89c8a 175 const char *arch = qtest_get_arch();
176 int started = (strcmp(side, "src_serial") == 0 &&
177 strcmp(arch, "ppc64") == 0) ? 0 : 1;
ea0c6d62 178
e2dd21e5 179 g_free(serialpath);
ea0c6d62
DDAG
180 do {
181 int readvalue = fgetc(serialfile);
182
aaf89c8a 183 if (!started) {
184 /* SLOF prints its banner before starting test,
185 * to ignore it, mark the start of the test with '_',
186 * ignore all characters until this marker
187 */
188 switch (readvalue) {
189 case '_':
190 started = 1;
191 break;
192 case EOF:
193 fseek(serialfile, 0, SEEK_SET);
194 usleep(1000);
195 break;
196 }
197 continue;
198 }
ea0c6d62
DDAG
199 switch (readvalue) {
200 case 'A':
201 /* Fine */
202 break;
203
204 case 'B':
205 /* It's alive! */
206 fclose(serialfile);
ea0c6d62
DDAG
207 return;
208
209 case EOF:
aaf89c8a 210 started = (strcmp(side, "src_serial") == 0 &&
211 strcmp(arch, "ppc64") == 0) ? 0 : 1;
ea0c6d62
DDAG
212 fseek(serialfile, 0, SEEK_SET);
213 usleep(1000);
214 break;
215
216 default:
217 fprintf(stderr, "Unexpected %d on %s serial\n", readvalue, side);
218 g_assert_not_reached();
219 }
220 } while (true);
221}
222
223/*
224 * Events can get in the way of responses we are actually waiting for.
225 */
863e27a8 226static QDict *wait_command(QTestState *who, const char *command)
ea0c6d62
DDAG
227{
228 const char *event_string;
863e27a8
JQ
229 QDict *response;
230
231 response = qtest_qmp(who, command);
ea0c6d62 232
863e27a8
JQ
233 while (qdict_haskey(response, "event")) {
234 /* OK, it was an event */
235 event_string = qdict_get_str(response, "event");
236 if (!strcmp(event_string, "STOP")) {
237 got_stop = true;
238 }
239 QDECREF(response);
240 response = qtest_qmp_receive(who);
ea0c6d62 241 }
863e27a8 242 return response;
ea0c6d62
DDAG
243}
244
245
246/*
247 * It's tricky to use qemu's migration event capability with qtest,
248 * events suddenly appearing confuse the qmp()/hmp() responses.
ea0c6d62
DDAG
249 */
250
863e27a8 251static uint64_t get_migration_pass(QTestState *who)
ea0c6d62
DDAG
252{
253 QDict *rsp, *rsp_return, *rsp_ram;
254 uint64_t result;
255
863e27a8 256 rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
ea0c6d62
DDAG
257 rsp_return = qdict_get_qdict(rsp, "return");
258 if (!qdict_haskey(rsp_return, "ram")) {
259 /* Still in setup */
260 result = 0;
261 } else {
262 rsp_ram = qdict_get_qdict(rsp_return, "ram");
263 result = qdict_get_try_int(rsp_ram, "dirty-sync-count", 0);
ea0c6d62 264 }
5b1ded22 265 QDECREF(rsp);
ea0c6d62
DDAG
266 return result;
267}
268
863e27a8 269static void wait_for_migration_complete(QTestState *who)
ea0c6d62
DDAG
270{
271 QDict *rsp, *rsp_return;
272 bool completed;
273
274 do {
275 const char *status;
276
863e27a8 277 rsp = wait_command(who, "{ 'execute': 'query-migrate' }");
ea0c6d62
DDAG
278 rsp_return = qdict_get_qdict(rsp, "return");
279 status = qdict_get_str(rsp_return, "status");
280 completed = strcmp(status, "completed") == 0;
281 g_assert_cmpstr(status, !=, "failed");
282 QDECREF(rsp);
283 usleep(1000 * 100);
284 } while (!completed);
285}
286
863e27a8 287static void wait_for_migration_pass(QTestState *who)
ea0c6d62 288{
863e27a8 289 uint64_t initial_pass = get_migration_pass(who);
ea0c6d62
DDAG
290 uint64_t pass;
291
292 /* Wait for the 1st sync */
293 do {
863e27a8 294 initial_pass = get_migration_pass(who);
ea0c6d62
DDAG
295 if (got_stop || initial_pass) {
296 break;
297 }
298 usleep(1000 * 100);
299 } while (true);
300
301 do {
302 usleep(1000 * 100);
863e27a8 303 pass = get_migration_pass(who);
ea0c6d62
DDAG
304 } while (pass == initial_pass && !got_stop);
305}
306
7195a871 307static void check_guests_ram(QTestState *who)
ea0c6d62
DDAG
308{
309 /* Our ASM test will have been incrementing one byte from each page from
310 * 1MB to <100MB in order.
311 * This gives us a constraint that any page's byte should be equal or less
312 * than the previous pages byte (mod 256); and they should all be equal
313 * except for one transition at the point where we meet the incrementer.
314 * (We're running this with the guest stopped).
315 */
316 unsigned address;
317 uint8_t first_byte;
318 uint8_t last_byte;
319 bool hit_edge = false;
320 bool bad = false;
321
7195a871 322 qtest_memread(who, start_address, &first_byte, 1);
ea0c6d62
DDAG
323 last_byte = first_byte;
324
325 for (address = start_address + 4096; address < end_address; address += 4096)
326 {
327 uint8_t b;
7195a871 328 qtest_memread(who, address, &b, 1);
ea0c6d62
DDAG
329 if (b != last_byte) {
330 if (((b + 1) % 256) == last_byte && !hit_edge) {
331 /* This is OK, the guest stopped at the point of
332 * incrementing the previous page but didn't get
333 * to us yet.
334 */
335 hit_edge = true;
336 } else {
337 fprintf(stderr, "Memory content inconsistency at %x"
338 " first_byte = %x last_byte = %x current = %x"
339 " hit_edge = %x\n",
340 address, first_byte, last_byte, b, hit_edge);
341 bad = true;
342 }
343 }
344 last_byte = b;
345 }
346 g_assert_false(bad);
347}
348
349static void cleanup(const char *filename)
350{
351 char *path = g_strdup_printf("%s/%s", tmpfs, filename);
352
353 unlink(path);
e2dd21e5 354 g_free(path);
ea0c6d62
DDAG
355}
356
56b4a42a
JQ
357static void migrate_check_parameter(QTestState *who, const char *parameter,
358 const char *value)
359{
360 QDict *rsp, *rsp_return;
361 const char *result;
362
363 rsp = wait_command(who, "{ 'execute': 'query-migrate-parameters' }");
364 rsp_return = qdict_get_qdict(rsp, "return");
365 result = g_strdup_printf("%" PRId64,
366 qdict_get_try_int(rsp_return, parameter, -1));
367 g_assert_cmpstr(result, ==, value);
368 QDECREF(rsp);
369}
370
371static void migrate_set_downtime(QTestState *who, const double value)
d62fbe60
JQ
372{
373 QDict *rsp;
374 gchar *cmd;
56b4a42a
JQ
375 char *expected;
376 int64_t result_int;
d62fbe60
JQ
377
378 cmd = g_strdup_printf("{ 'execute': 'migrate_set_downtime',"
56b4a42a 379 "'arguments': { 'value': %g } }", value);
d62fbe60
JQ
380 rsp = qtest_qmp(who, cmd);
381 g_free(cmd);
382 g_assert(qdict_haskey(rsp, "return"));
383 QDECREF(rsp);
56b4a42a
JQ
384 result_int = value * 1000L;
385 expected = g_strdup_printf("%" PRId64, result_int);
386 migrate_check_parameter(who, "downtime-limit", expected);
387 g_free(expected);
d62fbe60
JQ
388}
389
390static void migrate_set_speed(QTestState *who, const char *value)
391{
392 QDict *rsp;
393 gchar *cmd;
394
395 cmd = g_strdup_printf("{ 'execute': 'migrate_set_speed',"
396 "'arguments': { 'value': %s } }", value);
397 rsp = qtest_qmp(who, cmd);
398 g_free(cmd);
399 g_assert(qdict_haskey(rsp, "return"));
400 QDECREF(rsp);
56b4a42a 401 migrate_check_parameter(who, "max-bandwidth", value);
d62fbe60
JQ
402}
403
404static void migrate_set_capability(QTestState *who, const char *capability,
405 const char *value)
406{
407 QDict *rsp;
408 gchar *cmd;
409
410 cmd = g_strdup_printf("{ 'execute': 'migrate-set-capabilities',"
411 "'arguments': { "
412 "'capabilities': [ { "
413 "'capability': '%s', 'state': %s } ] } }",
414 capability, value);
415 rsp = qtest_qmp(who, cmd);
416 g_free(cmd);
417 g_assert(qdict_haskey(rsp, "return"));
418 QDECREF(rsp);
419}
420
421static void migrate(QTestState *who, const char *uri)
422{
423 QDict *rsp;
424 gchar *cmd;
425
426 cmd = g_strdup_printf("{ 'execute': 'migrate',"
427 "'arguments': { 'uri': '%s' } }",
428 uri);
429 rsp = qtest_qmp(who, cmd);
430 g_free(cmd);
431 g_assert(qdict_haskey(rsp, "return"));
432 QDECREF(rsp);
433}
434
7195a871
JQ
435static void test_migrate_start(QTestState **from, QTestState **to,
436 const char *uri)
ea0c6d62 437{
d62fbe60 438 gchar *cmd_src, *cmd_dst;
ea0c6d62 439 char *bootpath = g_strdup_printf("%s/bootsect", tmpfs);
aaf89c8a 440 const char *arch = qtest_get_arch();
ea0c6d62
DDAG
441
442 got_stop = false;
ea0c6d62 443
aaf89c8a 444 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
445 init_bootfile_x86(bootpath);
446 cmd_src = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
447 " -name pcsource,debug-threads=on"
448 " -serial file:%s/src_serial"
449 " -drive file=%s,format=raw",
450 tmpfs, bootpath);
451 cmd_dst = g_strdup_printf("-machine accel=kvm:tcg -m 150M"
452 " -name pcdest,debug-threads=on"
453 " -serial file:%s/dest_serial"
454 " -drive file=%s,format=raw"
455 " -incoming %s",
456 tmpfs, bootpath, uri);
457 } else if (strcmp(arch, "ppc64") == 0) {
171da9d5
TH
458 const char *accel;
459
460 /* On ppc64, the test only works with kvm-hv, but not with kvm-pr */
461 accel = access("/sys/module/kvm_hv", F_OK) ? "tcg" : "kvm:tcg";
aaf89c8a 462 init_bootfile_ppc(bootpath);
171da9d5 463 cmd_src = g_strdup_printf("-machine accel=%s -m 256M"
aaf89c8a 464 " -name pcsource,debug-threads=on"
465 " -serial file:%s/src_serial"
466 " -drive file=%s,if=pflash,format=raw",
171da9d5
TH
467 accel, tmpfs, bootpath);
468 cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
aaf89c8a 469 " -name pcdest,debug-threads=on"
470 " -serial file:%s/dest_serial"
471 " -incoming %s",
171da9d5 472 accel, tmpfs, uri);
aaf89c8a 473 } else {
474 g_assert_not_reached();
475 }
476
e2dd21e5
MAL
477 g_free(bootpath);
478
7195a871 479 *from = qtest_start(cmd_src);
aaf89c8a 480 g_free(cmd_src);
481
7195a871 482 *to = qtest_init(cmd_dst);
aaf89c8a 483 g_free(cmd_dst);
7195a871
JQ
484}
485
486static void test_migrate_end(QTestState *from, QTestState *to)
487{
488 unsigned char dest_byte_a, dest_byte_b, dest_byte_c, dest_byte_d;
489
490 qtest_quit(from);
491
492 qtest_memread(to, start_address, &dest_byte_a, 1);
493
494 /* Destination still running, wait for a byte to change */
495 do {
496 qtest_memread(to, start_address, &dest_byte_b, 1);
497 usleep(10 * 1000);
498 } while (dest_byte_a == dest_byte_b);
499
500 qtest_qmp_discard_response(to, "{ 'execute' : 'stop'}");
501 /* With it stopped, check nothing changes */
502 qtest_memread(to, start_address, &dest_byte_c, 1);
503 sleep(1);
504 qtest_memread(to, start_address, &dest_byte_d, 1);
505 g_assert_cmpint(dest_byte_c, ==, dest_byte_d);
506
507 check_guests_ram(to);
508
509 qtest_quit(to);
510
511 cleanup("bootsect");
512 cleanup("migsocket");
513 cleanup("src_serial");
514 cleanup("dest_serial");
515}
516
517static void test_migrate(void)
518{
519 char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
863e27a8 520 QTestState *from, *to;
7195a871
JQ
521 QDict *rsp;
522
523 test_migrate_start(&from, &to, uri);
ea0c6d62 524
d62fbe60
JQ
525 migrate_set_capability(from, "postcopy-ram", "true");
526 migrate_set_capability(to, "postcopy-ram", "true");
ea0c6d62
DDAG
527
528 /* We want to pick a speed slow enough that the test completes
529 * quickly, but that it doesn't complete precopy even on a slow
530 * machine, so also set the downtime.
531 */
d62fbe60 532 migrate_set_speed(from, "100000000");
56b4a42a 533 migrate_set_downtime(from, 0.001);
ea0c6d62
DDAG
534
535 /* Wait for the first serial output from the source */
536 wait_for_serial("src_serial");
537
d62fbe60 538 migrate(from, uri);
ea0c6d62 539
863e27a8 540 wait_for_migration_pass(from);
ea0c6d62 541
863e27a8 542 rsp = wait_command(from, "{ 'execute': 'migrate-start-postcopy' }");
ea0c6d62
DDAG
543 g_assert(qdict_haskey(rsp, "return"));
544 QDECREF(rsp);
545
546 if (!got_stop) {
863e27a8 547 qtest_qmp_eventwait(from, "STOP");
ea0c6d62
DDAG
548 }
549
863e27a8 550 qtest_qmp_eventwait(to, "RESUME");
ea0c6d62
DDAG
551
552 wait_for_serial("dest_serial");
863e27a8 553 wait_for_migration_complete(from);
ea0c6d62 554
ea0c6d62 555 g_free(uri);
ea0c6d62 556
7195a871 557 test_migrate_end(from, to);
ea0c6d62
DDAG
558}
559
560int main(int argc, char **argv)
561{
2656bfd9 562 char template[] = "/tmp/migration-test-XXXXXX";
ea0c6d62
DDAG
563 int ret;
564
565 g_test_init(&argc, &argv, NULL);
566
567 if (!ufd_version_check()) {
568 return 0;
569 }
570
571 tmpfs = mkdtemp(template);
572 if (!tmpfs) {
573 g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
574 }
575 g_assert(tmpfs);
576
577 module_call_init(MODULE_INIT_QOM);
578
2656bfd9 579 qtest_add_func("/migration/postcopy/unix", test_migrate);
ea0c6d62
DDAG
580
581 ret = g_test_run();
582
583 g_assert_cmpint(ret, ==, 0);
584
585 ret = rmdir(tmpfs);
586 if (ret != 0) {
587 g_test_message("unable to rmdir: path (%s): %s\n",
588 tmpfs, strerror(errno));
589 }
590
591 return ret;
592}