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" 1543ca9d18SSteve Sistare #include "qapi/qmp/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 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 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 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, 101de8bc62cSFabiano Rosas }; 102de8bc62cSFabiano Rosas 103de8bc62cSFabiano Rosas if (migrate_start(&from, &to, uri, &args)) { 104de8bc62cSFabiano Rosas return; 105de8bc62cSFabiano Rosas } 106de8bc62cSFabiano Rosas 107de8bc62cSFabiano Rosas migrate_ensure_non_converge(from); 108de8bc62cSFabiano Rosas migrate_prepare_for_dirty_mem(from); 109de8bc62cSFabiano Rosas 110de8bc62cSFabiano Rosas migrate_set_capability(from, "x-ignore-shared", true); 111de8bc62cSFabiano Rosas migrate_set_capability(to, "x-ignore-shared", true); 112de8bc62cSFabiano Rosas 113de8bc62cSFabiano Rosas /* Wait for the first serial output from the source */ 114de8bc62cSFabiano Rosas wait_for_serial("src_serial"); 115de8bc62cSFabiano Rosas 116de8bc62cSFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 117de8bc62cSFabiano Rosas 118de8bc62cSFabiano Rosas migrate_wait_for_dirty_mem(from, to); 119de8bc62cSFabiano Rosas 120de8bc62cSFabiano Rosas wait_for_stop(from, get_src()); 121de8bc62cSFabiano Rosas 122de8bc62cSFabiano Rosas qtest_qmp_eventwait(to, "RESUME"); 123de8bc62cSFabiano Rosas 124de8bc62cSFabiano Rosas wait_for_serial("dest_serial"); 125de8bc62cSFabiano Rosas wait_for_migration_complete(from); 126de8bc62cSFabiano Rosas 127de8bc62cSFabiano Rosas /* Check whether shared RAM has been really skipped */ 128de8bc62cSFabiano Rosas g_assert_cmpint( 129de8bc62cSFabiano Rosas read_ram_property_int(from, "transferred"), <, 4 * 1024 * 1024); 130de8bc62cSFabiano Rosas 131de8bc62cSFabiano Rosas migrate_end(from, to, true); 132de8bc62cSFabiano Rosas } 133de8bc62cSFabiano Rosas 134de8bc62cSFabiano Rosas static void do_test_validate_uuid(MigrateStart *args, bool should_fail) 135de8bc62cSFabiano Rosas { 136de8bc62cSFabiano Rosas g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); 137de8bc62cSFabiano Rosas QTestState *from, *to; 138de8bc62cSFabiano Rosas 139de8bc62cSFabiano Rosas if (migrate_start(&from, &to, uri, args)) { 140de8bc62cSFabiano Rosas return; 141de8bc62cSFabiano Rosas } 142de8bc62cSFabiano Rosas 143de8bc62cSFabiano Rosas /* 144de8bc62cSFabiano Rosas * UUID validation is at the begin of migration. So, the main process of 145de8bc62cSFabiano Rosas * migration is not interesting for us here. Thus, set huge downtime for 146de8bc62cSFabiano Rosas * very fast migration. 147de8bc62cSFabiano Rosas */ 148de8bc62cSFabiano Rosas migrate_set_parameter_int(from, "downtime-limit", 1000000); 149de8bc62cSFabiano Rosas migrate_set_capability(from, "validate-uuid", true); 150de8bc62cSFabiano Rosas 151de8bc62cSFabiano Rosas /* Wait for the first serial output from the source */ 152de8bc62cSFabiano Rosas wait_for_serial("src_serial"); 153de8bc62cSFabiano Rosas 154de8bc62cSFabiano Rosas migrate_qmp(from, to, uri, NULL, "{}"); 155de8bc62cSFabiano Rosas 156de8bc62cSFabiano Rosas if (should_fail) { 157de8bc62cSFabiano Rosas qtest_set_expected_status(to, EXIT_FAILURE); 158de8bc62cSFabiano Rosas wait_for_migration_fail(from, true); 159de8bc62cSFabiano Rosas } else { 160de8bc62cSFabiano Rosas wait_for_migration_complete(from); 161de8bc62cSFabiano Rosas } 162de8bc62cSFabiano Rosas 163de8bc62cSFabiano Rosas migrate_end(from, to, false); 164de8bc62cSFabiano Rosas } 165de8bc62cSFabiano Rosas 166de8bc62cSFabiano Rosas static void test_validate_uuid(void) 167de8bc62cSFabiano Rosas { 168de8bc62cSFabiano Rosas MigrateStart args = { 169de8bc62cSFabiano Rosas .opts_source = "-uuid 11111111-1111-1111-1111-111111111111", 170de8bc62cSFabiano Rosas .opts_target = "-uuid 11111111-1111-1111-1111-111111111111", 171de8bc62cSFabiano Rosas }; 172de8bc62cSFabiano Rosas 173de8bc62cSFabiano Rosas do_test_validate_uuid(&args, false); 174de8bc62cSFabiano Rosas } 175de8bc62cSFabiano Rosas 176de8bc62cSFabiano Rosas static void test_validate_uuid_error(void) 177de8bc62cSFabiano Rosas { 178de8bc62cSFabiano Rosas MigrateStart args = { 179de8bc62cSFabiano Rosas .opts_source = "-uuid 11111111-1111-1111-1111-111111111111", 180de8bc62cSFabiano Rosas .opts_target = "-uuid 22222222-2222-2222-2222-222222222222", 181de8bc62cSFabiano Rosas .hide_stderr = true, 182de8bc62cSFabiano Rosas }; 183de8bc62cSFabiano Rosas 184de8bc62cSFabiano Rosas do_test_validate_uuid(&args, true); 185de8bc62cSFabiano Rosas } 186de8bc62cSFabiano Rosas 187de8bc62cSFabiano Rosas static void test_validate_uuid_src_not_set(void) 188de8bc62cSFabiano Rosas { 189de8bc62cSFabiano Rosas MigrateStart args = { 190de8bc62cSFabiano Rosas .opts_target = "-uuid 22222222-2222-2222-2222-222222222222", 191de8bc62cSFabiano Rosas .hide_stderr = true, 192de8bc62cSFabiano Rosas }; 193de8bc62cSFabiano Rosas 194de8bc62cSFabiano Rosas do_test_validate_uuid(&args, false); 195de8bc62cSFabiano Rosas } 196de8bc62cSFabiano Rosas 197de8bc62cSFabiano Rosas static void test_validate_uuid_dst_not_set(void) 198de8bc62cSFabiano Rosas { 199de8bc62cSFabiano Rosas MigrateStart args = { 200de8bc62cSFabiano Rosas .opts_source = "-uuid 11111111-1111-1111-1111-111111111111", 201de8bc62cSFabiano Rosas .hide_stderr = true, 202de8bc62cSFabiano Rosas }; 203de8bc62cSFabiano Rosas 204de8bc62cSFabiano Rosas do_test_validate_uuid(&args, false); 205de8bc62cSFabiano Rosas } 206de8bc62cSFabiano Rosas 207de8bc62cSFabiano Rosas static void do_test_validate_uri_channel(MigrateCommon *args) 208de8bc62cSFabiano Rosas { 209de8bc62cSFabiano Rosas QTestState *from, *to; 21043ca9d18SSteve Sistare QObject *channels; 211de8bc62cSFabiano Rosas 212de8bc62cSFabiano Rosas if (migrate_start(&from, &to, args->listen_uri, &args->start)) { 213de8bc62cSFabiano Rosas return; 214de8bc62cSFabiano Rosas } 215de8bc62cSFabiano Rosas 216de8bc62cSFabiano Rosas /* Wait for the first serial output from the source */ 217de8bc62cSFabiano Rosas wait_for_serial("src_serial"); 218de8bc62cSFabiano Rosas 219de8bc62cSFabiano Rosas /* 220de8bc62cSFabiano Rosas * 'uri' and 'channels' validation is checked even before the migration 221de8bc62cSFabiano Rosas * starts. 222de8bc62cSFabiano Rosas */ 22343ca9d18SSteve Sistare channels = args->connect_channels ? 22443ca9d18SSteve Sistare qobject_from_json(args->connect_channels, &error_abort) : 22543ca9d18SSteve Sistare NULL; 22643ca9d18SSteve Sistare migrate_qmp_fail(from, args->connect_uri, channels, "{}"); 22743ca9d18SSteve Sistare 228de8bc62cSFabiano Rosas migrate_end(from, to, false); 229de8bc62cSFabiano Rosas } 230de8bc62cSFabiano Rosas 231de8bc62cSFabiano Rosas static void test_validate_uri_channels_both_set(void) 232de8bc62cSFabiano Rosas { 233de8bc62cSFabiano Rosas MigrateCommon args = { 234de8bc62cSFabiano Rosas .start = { 235de8bc62cSFabiano Rosas .hide_stderr = true, 236de8bc62cSFabiano Rosas }, 237de8bc62cSFabiano Rosas .listen_uri = "defer", 238de8bc62cSFabiano Rosas .connect_uri = "tcp:127.0.0.1:0", 239de8bc62cSFabiano Rosas .connect_channels = ("[ { ""'channel-type': 'main'," 240de8bc62cSFabiano Rosas " 'addr': { 'transport': 'socket'," 241de8bc62cSFabiano Rosas " 'type': 'inet'," 242de8bc62cSFabiano Rosas " 'host': '127.0.0.1'," 243de8bc62cSFabiano Rosas " 'port': '0' } } ]"), 244de8bc62cSFabiano Rosas }; 245de8bc62cSFabiano Rosas 246de8bc62cSFabiano Rosas do_test_validate_uri_channel(&args); 247de8bc62cSFabiano Rosas } 248de8bc62cSFabiano Rosas 249de8bc62cSFabiano Rosas static void test_validate_uri_channels_none_set(void) 250de8bc62cSFabiano Rosas { 251de8bc62cSFabiano Rosas MigrateCommon args = { 252de8bc62cSFabiano Rosas .start = { 253de8bc62cSFabiano Rosas .hide_stderr = true, 254de8bc62cSFabiano Rosas }, 255de8bc62cSFabiano Rosas .listen_uri = "defer", 256de8bc62cSFabiano Rosas }; 257de8bc62cSFabiano Rosas 258de8bc62cSFabiano Rosas do_test_validate_uri_channel(&args); 259de8bc62cSFabiano Rosas } 260de8bc62cSFabiano Rosas 261*43ab3fb3SFabiano Rosas static void migration_test_add_misc_smoke(MigrationTestEnv *env) 262*43ab3fb3SFabiano Rosas { 263*43ab3fb3SFabiano Rosas #ifndef _WIN32 264*43ab3fb3SFabiano Rosas migration_test_add("/migration/analyze-script", test_analyze_script); 265*43ab3fb3SFabiano Rosas #endif 266*43ab3fb3SFabiano Rosas } 267*43ab3fb3SFabiano Rosas 268de8bc62cSFabiano Rosas void migration_test_add_misc(MigrationTestEnv *env) 269de8bc62cSFabiano Rosas { 270de8bc62cSFabiano Rosas tmpfs = env->tmpfs; 271de8bc62cSFabiano Rosas 272*43ab3fb3SFabiano Rosas migration_test_add_misc_smoke(env); 273*43ab3fb3SFabiano Rosas 274bc2a1f1aSFabiano Rosas if (!env->full_set) { 275bc2a1f1aSFabiano Rosas return; 276bc2a1f1aSFabiano Rosas } 277bc2a1f1aSFabiano Rosas 278de8bc62cSFabiano Rosas migration_test_add("/migration/bad_dest", test_baddest); 279de8bc62cSFabiano Rosas 280de8bc62cSFabiano Rosas /* 281de8bc62cSFabiano Rosas * Our CI system has problems with shared memory. 282de8bc62cSFabiano Rosas * Don't run this test until we find a workaround. 283de8bc62cSFabiano Rosas */ 284de8bc62cSFabiano Rosas if (getenv("QEMU_TEST_FLAKY_TESTS")) { 285de8bc62cSFabiano Rosas migration_test_add("/migration/ignore-shared", test_ignore_shared); 286de8bc62cSFabiano Rosas } 287de8bc62cSFabiano Rosas 288de8bc62cSFabiano Rosas migration_test_add("/migration/validate_uuid", test_validate_uuid); 289de8bc62cSFabiano Rosas migration_test_add("/migration/validate_uuid_error", 290de8bc62cSFabiano Rosas test_validate_uuid_error); 291de8bc62cSFabiano Rosas migration_test_add("/migration/validate_uuid_src_not_set", 292de8bc62cSFabiano Rosas test_validate_uuid_src_not_set); 293de8bc62cSFabiano Rosas migration_test_add("/migration/validate_uuid_dst_not_set", 294de8bc62cSFabiano Rosas test_validate_uuid_dst_not_set); 295de8bc62cSFabiano Rosas migration_test_add("/migration/validate_uri/channels/both_set", 296de8bc62cSFabiano Rosas test_validate_uri_channels_both_set); 297de8bc62cSFabiano Rosas migration_test_add("/migration/validate_uri/channels/none_set", 298de8bc62cSFabiano Rosas test_validate_uri_channels_none_set); 299de8bc62cSFabiano Rosas } 300