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