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