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