master
h 264 lines 8.63 KB
Raw
1 /*
2 * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
3 * based on the vhost-user-test.c that is:
4 * Copyright (c) 2014 Virtual Open Systems Sarl.
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 *
9 */
10
11 #ifndef TEST_FRAMEWORK_H
12 #define TEST_FRAMEWORK_H
13
14 #include "libqtest.h"
15 #include <qapi/qapi-types-migration.h>
16
17 #define FILE_TEST_FILENAME "migfile"
18 #define FILE_TEST_OFFSET 0x1000
19 #define FILE_TEST_MARKER 'X'
20
21 typedef enum {
22 /*
23 * Use memory-backend-ram, private mappings
24 */
25 MEM_TYPE_ANON,
26 /*
27 * Use shmem file (under /dev/shm), shared mappings
28 */
29 MEM_TYPE_SHMEM,
30 /*
31 * Use anonymous memfd, shared mappings.
32 *
33 * NOTE: this is internally almost the same as MEM_TYPE_SHMEM on Linux,
34 * but only anonymously allocated.
35 */
36 MEM_TYPE_MEMFD,
37 MEM_TYPE_NUM,
38 } MemType;
39
40 typedef struct MigrationTestEnv {
41 bool has_kvm;
42 bool has_hvf;
43 bool has_tcg;
44 bool has_uffd;
45 bool uffd_feature_thread_id;
46 bool has_dirty_ring;
47 bool is_x86;
48 bool full_set;
49 const char *arch;
50 const char *qemu_src;
51 const char *qemu_dst;
52 char *tmpfs;
53 } MigrationTestEnv;
54
55 MigrationTestEnv *migration_get_env(void);
56 int migration_env_clean(MigrationTestEnv *env);
57
58 /*
59 * A hook that runs after the src and dst QEMUs have been
60 * created, but before the migration is started. This can
61 * be used to set migration parameters and capabilities.
62 *
63 * Returns: NULL, or a pointer to opaque state to be
64 * later passed to the TestMigrateEndHook
65 */
66 typedef void * (*TestMigrateStartHook)(QTestState *from,
67 QTestState *to);
68
69 /*
70 * A hook that runs after the migration has finished,
71 * regardless of whether it succeeded or failed, but
72 * before QEMU has terminated (unless it self-terminated
73 * due to migration error)
74 *
75 * @opaque is a pointer to state previously returned
76 * by the TestMigrateStartHook if any, or NULL.
77 */
78 typedef void (*TestMigrateEndHook)(QTestState *from,
79 QTestState *to,
80 void *opaque);
81
82 /*
83 * Our goal is to ensure that we run a single full migration
84 * iteration, and also dirty memory, ensuring that at least
85 * one further iteration is required.
86 *
87 * We can't directly synchronize with the start of a migration
88 * so we have to apply some tricks monitoring memory that is
89 * transferred.
90 *
91 * Initially we set the migration bandwidth to an insanely
92 * low value, with tiny max downtime too. This basically
93 * guarantees migration will never complete.
94 *
95 * This will result in a test that is unacceptably slow though,
96 * so we can't let the entire migration pass run at this speed.
97 * Our intent is to let it run just long enough that we can
98 * prove data prior to the marker has been transferred *AND*
99 * also prove this transferred data is dirty again.
100 *
101 * Before migration starts, we write a 64-bit magic marker
102 * into a fixed location in the src VM RAM.
103 *
104 * Then watch dst memory until the marker appears. This is
105 * proof that start_address -> MAGIC_OFFSET_BASE has been
106 * transferred.
107 *
108 * Finally we go back to the source and read a byte just
109 * before the marker until we see it flip in value. This
110 * is proof that start_address -> MAGIC_OFFSET_BASE
111 * is now dirty again.
112 *
113 * IOW, we're guaranteed at least a 2nd migration pass
114 * at this point.
115 *
116 * We can now let migration run at full speed to finish
117 * the test
118 */
119 typedef struct {
120 /*
121 * QTEST_LOG=test may override this in which case we dump errors
122 * unconditionally, because it means the user would like to be
123 * verbose.
124 */
125 bool hide_stderr;
126 MemType mem_type;
127 /* only launch the source process */
128 bool only_source;
129 /* only launch the target process */
130 bool only_target;
131 /* Use dirty ring if true; dirty logging otherwise */
132 bool use_dirty_ring;
133 const char *opts_source;
134 const char *opts_target;
135 /* suspend the src before migrating to dest. */
136 bool suspend_me;
137 /* enable OOB QMP capability */
138 bool oob;
139
140 /* Do not connect to target monitor and qtest sockets in qtest_init */
141 bool defer_target_connect;
142
143 /*
144 * Migration capabilities to be set in both source and
145 * destination. For unilateral capabilities, use
146 * migration_set_capabilities().
147 */
148 bool caps[MIGRATION_CAPABILITY__MAX];
149 } MigrateStart;
150
151 typedef enum PostcopyRecoveryFailStage {
152 /*
153 * "no failure" must be 0 as it's the default. OTOH, real failure
154 * cases must be >0 to make sure they trigger by a "if" test.
155 */
156 POSTCOPY_FAIL_NONE = 0,
157 POSTCOPY_FAIL_CHANNEL_ESTABLISH,
158 POSTCOPY_FAIL_RECOVERY,
159 POSTCOPY_FAIL_MAX
160 } PostcopyRecoveryFailStage;
161
162 typedef struct {
163 /* Optional: fine tune start parameters */
164 MigrateStart start;
165
166 /*
167 * Optional: the migration URI. If NULL, the common code should
168 * provide a default. For socket migration, the source QEMU may
169 * query the dst QEMU for the listening address and use that as
170 * the connection address. This allows for dynamically picking a
171 * free TCP port.
172 */
173 const char *uri;
174
175 /*
176 * Optional: JSON-formatted list of src QEMU URIs. If a port is
177 * defined as '0' in any QDict key a value of '0' will be
178 * automatically converted to the correct destination port.
179 */
180 const char *connect_channels;
181
182 /* Optional: callback to run at start to set migration parameters */
183 TestMigrateStartHook start_hook;
184 /* Optional: callback to run at finish to cleanup */
185 TestMigrateEndHook end_hook;
186
187 /*
188 * Optional: normally we expect the migration process to complete.
189 *
190 * There can be a variety of reasons and stages in which failure
191 * can happen during tests.
192 *
193 * If a failure is expected to happen at time of establishing
194 * the connection, then MIG_TEST_FAIL will indicate that the dst
195 * QEMU is expected to stay running and accept future migration
196 * connections.
197 *
198 * If a failure is expected to happen while processing the
199 * migration stream, then MIG_TEST_FAIL_DEST_QUIT_ERR will indicate
200 * that the dst QEMU is expected to quit with non-zero exit status
201 */
202 enum {
203 /* This test should succeed, the default */
204 MIG_TEST_SUCCEED = 0,
205 /* This test should fail, dest qemu should keep alive */
206 MIG_TEST_FAIL,
207 /* The QMP command for this migration should fail with an error */
208 MIG_TEST_QMP_ERROR,
209 } result;
210
211 /*
212 * Optional: set number of migration passes to wait for, if live==true.
213 * If zero, then merely wait for a few MB of dirty data
214 */
215 unsigned int iterations;
216
217 /*
218 * Optional: whether the guest CPUs should be running during a precopy
219 * migration test. We used to always run with live but it took much
220 * longer so we reduced live tests to only the ones that have solid
221 * reason to be tested live-only. For each of the new test cases for
222 * precopy please provide justifications to use live explicitly (please
223 * refer to existing ones with live=true), or use live=off by default.
224 */
225 bool live;
226 } MigrateCommon;
227
228 void wait_for_serial(const char *side);
229 void migrate_prepare_for_dirty_mem(QTestState *from);
230 void migrate_wait_for_dirty_mem(QTestState *from, QTestState *to);
231
232 int migrate_args(char **from, char **to, MigrateStart *args);
233 int migrate_start(QTestState **from, QTestState **to, MigrateStart *args);
234 void migrate_end(QTestState *from, QTestState *to, bool test_dest);
235
236 void test_postcopy_common(MigrateCommon *args);
237 void test_postcopy_recovery_common(MigrateCommon *args,
238 PostcopyRecoveryFailStage fail_stage);
239 int test_precopy_common(MigrateCommon *args);
240 void test_precopy_unix_common(MigrateCommon *args);
241 void test_file_common(MigrateCommon *args, bool stop_src);
242
243 typedef struct QTestMigrationState QTestMigrationState;
244 QTestMigrationState *get_src(void);
245 QTestMigrationState *get_dst(void);
246
247 #ifdef CONFIG_GNUTLS
248 void migration_test_add_tls(MigrationTestEnv *env);
249 #else
250 static inline void migration_test_add_tls(MigrationTestEnv *env) {};
251 #endif
252 void migration_test_add_compression(MigrationTestEnv *env);
253 void migration_test_add_postcopy(MigrationTestEnv *env);
254 void migration_test_add_file(MigrationTestEnv *env);
255 void migration_test_add_precopy(MigrationTestEnv *env);
256 void migration_test_add_cpr(MigrationTestEnv *env);
257 void migration_test_add_misc(MigrationTestEnv *env);
258 #ifdef CONFIG_REPLICATION
259 void migration_test_add_colo(MigrationTestEnv *env);
260 #else
261 static inline void migration_test_add_colo(MigrationTestEnv *env) {};
262 #endif
263
264 #endif /* TEST_FRAMEWORK_H */