xref: /qemu/tests/qtest/migration/misc-tests.c (revision b6f568262b48ca0cb3dc018909908017551b5679)
1de8bc62cSFabiano Rosas /*
2de8bc62cSFabiano Rosas  * QTest testcases for migration
3de8bc62cSFabiano Rosas  *
4de8bc62cSFabiano Rosas  * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
5de8bc62cSFabiano Rosas  *   based on the vhost-user-test.c that is:
6de8bc62cSFabiano Rosas  *      Copyright (c) 2014 Virtual Open Systems Sarl.
7de8bc62cSFabiano Rosas  *
8de8bc62cSFabiano Rosas  * This work is licensed under the terms of the GNU GPL, version 2 or later.
9de8bc62cSFabiano Rosas  * See the COPYING file in the top-level directory.
10de8bc62cSFabiano Rosas  *
11de8bc62cSFabiano Rosas  */
12de8bc62cSFabiano Rosas 
13de8bc62cSFabiano Rosas #include "qemu/osdep.h"
1443ca9d18SSteve Sistare #include "qapi/error.h"
15407bc4bfSDaniel P. Berrangé #include "qobject/qjson.h"
16de8bc62cSFabiano Rosas #include "libqtest.h"
17de8bc62cSFabiano Rosas #include "migration/framework.h"
18de8bc62cSFabiano Rosas #include "migration/migration-qmp.h"
19de8bc62cSFabiano Rosas #include "migration/migration-util.h"
20de8bc62cSFabiano Rosas 
21de8bc62cSFabiano Rosas #define ANALYZE_SCRIPT "scripts/analyze-migration.py"
22de8bc62cSFabiano Rosas 
23de8bc62cSFabiano Rosas static char *tmpfs;
24de8bc62cSFabiano Rosas 
test_baddest(void)25de8bc62cSFabiano Rosas static void test_baddest(void)
26de8bc62cSFabiano Rosas {
27de8bc62cSFabiano Rosas     MigrateStart args = {
28de8bc62cSFabiano Rosas         .hide_stderr = true
29de8bc62cSFabiano Rosas     };
30de8bc62cSFabiano Rosas     QTestState *from, *to;
31de8bc62cSFabiano Rosas 
32de8bc62cSFabiano Rosas     if (migrate_start(&from, &to, "tcp:127.0.0.1:0", &args)) {
33de8bc62cSFabiano Rosas         return;
34de8bc62cSFabiano Rosas     }
35de8bc62cSFabiano Rosas     migrate_qmp(from, to, "tcp:127.0.0.1:0", NULL, "{}");
36de8bc62cSFabiano Rosas     wait_for_migration_fail(from, false);
37de8bc62cSFabiano Rosas     migrate_end(from, to, false);
38de8bc62cSFabiano Rosas }
39de8bc62cSFabiano Rosas 
40de8bc62cSFabiano Rosas #ifndef _WIN32
test_analyze_script(void)41de8bc62cSFabiano Rosas static void test_analyze_script(void)
42de8bc62cSFabiano Rosas {
43de8bc62cSFabiano Rosas     MigrateStart args = {
44de8bc62cSFabiano Rosas         .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
45de8bc62cSFabiano Rosas     };
46de8bc62cSFabiano Rosas     QTestState *from, *to;
47de8bc62cSFabiano Rosas     g_autofree char *uri = NULL;
48de8bc62cSFabiano Rosas     g_autofree char *file = NULL;
49de8bc62cSFabiano Rosas     int pid, wstatus;
50de8bc62cSFabiano Rosas     const char *python = g_getenv("PYTHON");
51de8bc62cSFabiano Rosas 
52de8bc62cSFabiano Rosas     if (!python) {
53de8bc62cSFabiano Rosas         g_test_skip("PYTHON variable not set");
54de8bc62cSFabiano Rosas         return;
55de8bc62cSFabiano Rosas     }
56de8bc62cSFabiano Rosas 
57de8bc62cSFabiano Rosas     /* dummy url */
58de8bc62cSFabiano Rosas     if (migrate_start(&from, &to, "tcp:127.0.0.1:0", &args)) {
59de8bc62cSFabiano Rosas         return;
60de8bc62cSFabiano Rosas     }
61de8bc62cSFabiano Rosas 
62de8bc62cSFabiano Rosas     /*
63de8bc62cSFabiano Rosas      * Setting these two capabilities causes the "configuration"
64de8bc62cSFabiano Rosas      * vmstate to include subsections for them. The script needs to
65de8bc62cSFabiano Rosas      * parse those subsections properly.
66de8bc62cSFabiano Rosas      */
67de8bc62cSFabiano Rosas     migrate_set_capability(from, "validate-uuid", true);
68de8bc62cSFabiano Rosas     migrate_set_capability(from, "x-ignore-shared", true);
69de8bc62cSFabiano Rosas 
70de8bc62cSFabiano Rosas     file = g_strdup_printf("%s/migfile", tmpfs);
71de8bc62cSFabiano Rosas     uri = g_strdup_printf("exec:cat > %s", file);
72de8bc62cSFabiano Rosas 
73de8bc62cSFabiano Rosas     migrate_ensure_converge(from);
74de8bc62cSFabiano Rosas     migrate_qmp(from, to, uri, NULL, "{}");
75de8bc62cSFabiano Rosas     wait_for_migration_complete(from);
76de8bc62cSFabiano Rosas 
77de8bc62cSFabiano Rosas     pid = fork();
78de8bc62cSFabiano Rosas     if (!pid) {
79de8bc62cSFabiano Rosas         close(1);
80de8bc62cSFabiano Rosas         open("/dev/null", O_WRONLY);
81de8bc62cSFabiano Rosas         execl(python, python, ANALYZE_SCRIPT, "-f", file, NULL);
82de8bc62cSFabiano Rosas         g_assert_not_reached();
83de8bc62cSFabiano Rosas     }
84de8bc62cSFabiano Rosas 
85de8bc62cSFabiano Rosas     g_assert(waitpid(pid, &wstatus, 0) == pid);
86de8bc62cSFabiano Rosas     if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0) {
87de8bc62cSFabiano Rosas         g_test_message("Failed to analyze the migration stream");
88de8bc62cSFabiano Rosas         g_test_fail();
89de8bc62cSFabiano Rosas     }
90de8bc62cSFabiano Rosas     migrate_end(from, to, false);
91de8bc62cSFabiano Rosas     unlink(file);
92de8bc62cSFabiano Rosas }
93de8bc62cSFabiano Rosas #endif
94de8bc62cSFabiano Rosas 
test_ignore_shared(void)95de8bc62cSFabiano Rosas static void test_ignore_shared(void)
96de8bc62cSFabiano Rosas {
97de8bc62cSFabiano Rosas     g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
98de8bc62cSFabiano Rosas     QTestState *from, *to;
99de8bc62cSFabiano Rosas     MigrateStart args = {
100de8bc62cSFabiano Rosas         .use_shmem = true,
101*115cec9dSPrasad Pandit         .caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED] = true,
102de8bc62cSFabiano Rosas     };
103de8bc62cSFabiano Rosas 
104de8bc62cSFabiano Rosas     if (migrate_start(&from, &to, uri, &args)) {
105de8bc62cSFabiano Rosas         return;
106de8bc62cSFabiano Rosas     }
107de8bc62cSFabiano Rosas 
108de8bc62cSFabiano Rosas     migrate_ensure_non_converge(from);
109de8bc62cSFabiano Rosas     migrate_prepare_for_dirty_mem(from);
110de8bc62cSFabiano Rosas 
111de8bc62cSFabiano Rosas     /* Wait for the first serial output from the source */
112de8bc62cSFabiano Rosas     wait_for_serial("src_serial");
113de8bc62cSFabiano Rosas 
114de8bc62cSFabiano Rosas     migrate_qmp(from, to, uri, NULL, "{}");
115de8bc62cSFabiano Rosas 
116de8bc62cSFabiano Rosas     migrate_wait_for_dirty_mem(from, to);
117de8bc62cSFabiano Rosas 
118de8bc62cSFabiano Rosas     wait_for_stop(from, get_src());
119de8bc62cSFabiano Rosas 
120de8bc62cSFabiano Rosas     qtest_qmp_eventwait(to, "RESUME");
121de8bc62cSFabiano Rosas 
122de8bc62cSFabiano Rosas     wait_for_serial("dest_serial");
123de8bc62cSFabiano Rosas     wait_for_migration_complete(from);
124de8bc62cSFabiano Rosas 
125de8bc62cSFabiano Rosas     /* Check whether shared RAM has been really skipped */
126de8bc62cSFabiano Rosas     g_assert_cmpint(
127de8bc62cSFabiano Rosas         read_ram_property_int(from, "transferred"), <, 4 * 1024 * 1024);
128de8bc62cSFabiano Rosas 
129de8bc62cSFabiano Rosas     migrate_end(from, to, true);
130de8bc62cSFabiano Rosas }
131de8bc62cSFabiano Rosas 
do_test_validate_uuid(MigrateStart * args,bool should_fail)132de8bc62cSFabiano Rosas static void do_test_validate_uuid(MigrateStart *args, bool should_fail)
133de8bc62cSFabiano Rosas {
134de8bc62cSFabiano Rosas     g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
135de8bc62cSFabiano Rosas     QTestState *from, *to;
136de8bc62cSFabiano Rosas 
137de8bc62cSFabiano Rosas     if (migrate_start(&from, &to, uri, args)) {
138de8bc62cSFabiano Rosas         return;
139de8bc62cSFabiano Rosas     }
140de8bc62cSFabiano Rosas 
141de8bc62cSFabiano Rosas     /*
142de8bc62cSFabiano Rosas      * UUID validation is at the begin of migration. So, the main process of
143de8bc62cSFabiano Rosas      * migration is not interesting for us here. Thus, set huge downtime for
144de8bc62cSFabiano Rosas      * very fast migration.
145de8bc62cSFabiano Rosas      */
146de8bc62cSFabiano Rosas     migrate_set_parameter_int(from, "downtime-limit", 1000000);
147de8bc62cSFabiano Rosas     migrate_set_capability(from, "validate-uuid", true);
148de8bc62cSFabiano Rosas 
149de8bc62cSFabiano Rosas     /* Wait for the first serial output from the source */
150de8bc62cSFabiano Rosas     wait_for_serial("src_serial");
151de8bc62cSFabiano Rosas 
152de8bc62cSFabiano Rosas     migrate_qmp(from, to, uri, NULL, "{}");
153de8bc62cSFabiano Rosas 
154de8bc62cSFabiano Rosas     if (should_fail) {
155de8bc62cSFabiano Rosas         qtest_set_expected_status(to, EXIT_FAILURE);
156de8bc62cSFabiano Rosas         wait_for_migration_fail(from, true);
157de8bc62cSFabiano Rosas     } else {
158de8bc62cSFabiano Rosas         wait_for_migration_complete(from);
159de8bc62cSFabiano Rosas     }
160de8bc62cSFabiano Rosas 
161de8bc62cSFabiano Rosas     migrate_end(from, to, false);
162de8bc62cSFabiano Rosas }
163de8bc62cSFabiano Rosas 
test_validate_uuid(void)164de8bc62cSFabiano Rosas static void test_validate_uuid(void)
165de8bc62cSFabiano Rosas {
166de8bc62cSFabiano Rosas     MigrateStart args = {
167de8bc62cSFabiano Rosas         .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
168de8bc62cSFabiano Rosas         .opts_target = "-uuid 11111111-1111-1111-1111-111111111111",
169de8bc62cSFabiano Rosas     };
170de8bc62cSFabiano Rosas 
171de8bc62cSFabiano Rosas     do_test_validate_uuid(&args, false);
172de8bc62cSFabiano Rosas }
173de8bc62cSFabiano Rosas 
test_validate_uuid_error(void)174de8bc62cSFabiano Rosas static void test_validate_uuid_error(void)
175de8bc62cSFabiano Rosas {
176de8bc62cSFabiano Rosas     MigrateStart args = {
177de8bc62cSFabiano Rosas         .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
178de8bc62cSFabiano Rosas         .opts_target = "-uuid 22222222-2222-2222-2222-222222222222",
179de8bc62cSFabiano Rosas         .hide_stderr = true,
180de8bc62cSFabiano Rosas     };
181de8bc62cSFabiano Rosas 
182de8bc62cSFabiano Rosas     do_test_validate_uuid(&args, true);
183de8bc62cSFabiano Rosas }
184de8bc62cSFabiano Rosas 
test_validate_uuid_src_not_set(void)185de8bc62cSFabiano Rosas static void test_validate_uuid_src_not_set(void)
186de8bc62cSFabiano Rosas {
187de8bc62cSFabiano Rosas     MigrateStart args = {
188de8bc62cSFabiano Rosas         .opts_target = "-uuid 22222222-2222-2222-2222-222222222222",
189de8bc62cSFabiano Rosas         .hide_stderr = true,
190de8bc62cSFabiano Rosas     };
191de8bc62cSFabiano Rosas 
192de8bc62cSFabiano Rosas     do_test_validate_uuid(&args, false);
193de8bc62cSFabiano Rosas }
194de8bc62cSFabiano Rosas 
test_validate_uuid_dst_not_set(void)195de8bc62cSFabiano Rosas static void test_validate_uuid_dst_not_set(void)
196de8bc62cSFabiano Rosas {
197de8bc62cSFabiano Rosas     MigrateStart args = {
198de8bc62cSFabiano Rosas         .opts_source = "-uuid 11111111-1111-1111-1111-111111111111",
199de8bc62cSFabiano Rosas         .hide_stderr = true,
200de8bc62cSFabiano Rosas     };
201de8bc62cSFabiano Rosas 
202de8bc62cSFabiano Rosas     do_test_validate_uuid(&args, false);
203de8bc62cSFabiano Rosas }
204de8bc62cSFabiano Rosas 
do_test_validate_uri_channel(MigrateCommon * args)205de8bc62cSFabiano Rosas static void do_test_validate_uri_channel(MigrateCommon *args)
206de8bc62cSFabiano Rosas {
207de8bc62cSFabiano Rosas     QTestState *from, *to;
20843ca9d18SSteve Sistare     QObject *channels;
209de8bc62cSFabiano Rosas 
210de8bc62cSFabiano Rosas     if (migrate_start(&from, &to, args->listen_uri, &args->start)) {
211de8bc62cSFabiano Rosas         return;
212de8bc62cSFabiano Rosas     }
213de8bc62cSFabiano Rosas 
214de8bc62cSFabiano Rosas     /* Wait for the first serial output from the source */
215de8bc62cSFabiano Rosas     wait_for_serial("src_serial");
216de8bc62cSFabiano Rosas 
217de8bc62cSFabiano Rosas     /*
218de8bc62cSFabiano Rosas      * 'uri' and 'channels' validation is checked even before the migration
219de8bc62cSFabiano Rosas      * starts.
220de8bc62cSFabiano Rosas      */
22143ca9d18SSteve Sistare     channels = args->connect_channels ?
22243ca9d18SSteve Sistare                qobject_from_json(args->connect_channels, &error_abort) :
22343ca9d18SSteve Sistare                NULL;
22443ca9d18SSteve Sistare     migrate_qmp_fail(from, args->connect_uri, channels, "{}");
22543ca9d18SSteve Sistare 
226de8bc62cSFabiano Rosas     migrate_end(from, to, false);
227de8bc62cSFabiano Rosas }
228de8bc62cSFabiano Rosas 
test_validate_uri_channels_both_set(void)229de8bc62cSFabiano Rosas static void test_validate_uri_channels_both_set(void)
230de8bc62cSFabiano Rosas {
231de8bc62cSFabiano Rosas     MigrateCommon args = {
232de8bc62cSFabiano Rosas         .start = {
233de8bc62cSFabiano Rosas             .hide_stderr = true,
234de8bc62cSFabiano Rosas         },
235de8bc62cSFabiano Rosas         .listen_uri = "defer",
236de8bc62cSFabiano Rosas         .connect_uri = "tcp:127.0.0.1:0",
237de8bc62cSFabiano Rosas         .connect_channels = ("[ { ""'channel-type': 'main',"
238de8bc62cSFabiano Rosas                              "    'addr': { 'transport': 'socket',"
239de8bc62cSFabiano Rosas                              "              'type': 'inet',"
240de8bc62cSFabiano Rosas                              "              'host': '127.0.0.1',"
241de8bc62cSFabiano Rosas                              "              'port': '0' } } ]"),
242de8bc62cSFabiano Rosas     };
243de8bc62cSFabiano Rosas 
244de8bc62cSFabiano Rosas     do_test_validate_uri_channel(&args);
245de8bc62cSFabiano Rosas }
246de8bc62cSFabiano Rosas 
test_validate_uri_channels_none_set(void)247de8bc62cSFabiano Rosas static void test_validate_uri_channels_none_set(void)
248de8bc62cSFabiano Rosas {
249de8bc62cSFabiano Rosas     MigrateCommon args = {
250de8bc62cSFabiano Rosas         .start = {
251de8bc62cSFabiano Rosas             .hide_stderr = true,
252de8bc62cSFabiano Rosas         },
253de8bc62cSFabiano Rosas         .listen_uri = "defer",
254de8bc62cSFabiano Rosas     };
255de8bc62cSFabiano Rosas 
256de8bc62cSFabiano Rosas     do_test_validate_uri_channel(&args);
257de8bc62cSFabiano Rosas }
258de8bc62cSFabiano Rosas 
migration_test_add_misc_smoke(MigrationTestEnv * env)25943ab3fb3SFabiano Rosas static void migration_test_add_misc_smoke(MigrationTestEnv *env)
26043ab3fb3SFabiano Rosas {
26143ab3fb3SFabiano Rosas #ifndef _WIN32
26243ab3fb3SFabiano Rosas     migration_test_add("/migration/analyze-script", test_analyze_script);
26343ab3fb3SFabiano Rosas #endif
26443ab3fb3SFabiano Rosas }
26543ab3fb3SFabiano Rosas 
migration_test_add_misc(MigrationTestEnv * env)266de8bc62cSFabiano Rosas void migration_test_add_misc(MigrationTestEnv *env)
267de8bc62cSFabiano Rosas {
268de8bc62cSFabiano Rosas     tmpfs = env->tmpfs;
269de8bc62cSFabiano Rosas 
27043ab3fb3SFabiano Rosas     migration_test_add_misc_smoke(env);
27143ab3fb3SFabiano Rosas 
272bc2a1f1aSFabiano Rosas     if (!env->full_set) {
273bc2a1f1aSFabiano Rosas         return;
274bc2a1f1aSFabiano Rosas     }
275bc2a1f1aSFabiano Rosas 
276de8bc62cSFabiano Rosas     migration_test_add("/migration/bad_dest", test_baddest);
277de8bc62cSFabiano Rosas 
278de8bc62cSFabiano Rosas     /*
279de8bc62cSFabiano Rosas      * Our CI system has problems with shared memory.
280de8bc62cSFabiano Rosas      * Don't run this test until we find a workaround.
281de8bc62cSFabiano Rosas      */
282de8bc62cSFabiano Rosas     if (getenv("QEMU_TEST_FLAKY_TESTS")) {
283de8bc62cSFabiano Rosas         migration_test_add("/migration/ignore-shared", test_ignore_shared);
284de8bc62cSFabiano Rosas     }
285de8bc62cSFabiano Rosas 
286de8bc62cSFabiano Rosas     migration_test_add("/migration/validate_uuid", test_validate_uuid);
287de8bc62cSFabiano Rosas     migration_test_add("/migration/validate_uuid_error",
288de8bc62cSFabiano Rosas                        test_validate_uuid_error);
289de8bc62cSFabiano Rosas     migration_test_add("/migration/validate_uuid_src_not_set",
290de8bc62cSFabiano Rosas                        test_validate_uuid_src_not_set);
291de8bc62cSFabiano Rosas     migration_test_add("/migration/validate_uuid_dst_not_set",
292de8bc62cSFabiano Rosas                        test_validate_uuid_dst_not_set);
293de8bc62cSFabiano Rosas     migration_test_add("/migration/validate_uri/channels/both_set",
294de8bc62cSFabiano Rosas                        test_validate_uri_channels_both_set);
295de8bc62cSFabiano Rosas     migration_test_add("/migration/validate_uri/channels/none_set",
296de8bc62cSFabiano Rosas                        test_validate_uri_channels_none_set);
297de8bc62cSFabiano Rosas }
298