tests/libqtest: add some virtio-net failover migration cancelling tests
Add some tests to check the state of the machine if the migration is cancelled while we are using virtio-net failover. Signed-off-by: Laurent Vivier <lvivier@redhat.com> Acked-by: Thomas Huth <thuth@redhat.com> Message-Id: <20211208130350.10178-4-lvivier@redhat.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
parent
e32b96b559
commit
1e2077e223
@ -752,6 +752,280 @@ static void test_migrate_in(gconstpointer opaque)
|
|||||||
machine_stop(qts);
|
machine_stop(qts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_migrate_abort_wait_unplug(gconstpointer opaque)
|
||||||
|
{
|
||||||
|
QTestState *qts;
|
||||||
|
QDict *resp, *args, *ret;
|
||||||
|
g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque);
|
||||||
|
const gchar *status;
|
||||||
|
QVirtioPCIDevice *vdev;
|
||||||
|
|
||||||
|
qts = machine_start(BASE_MACHINE
|
||||||
|
"-netdev user,id=hs0 "
|
||||||
|
"-netdev user,id=hs1 ",
|
||||||
|
2);
|
||||||
|
|
||||||
|
check_one_card(qts, false, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qtest_qmp_device_add(qts, "virtio-net", "standby0",
|
||||||
|
"{'bus': 'root0',"
|
||||||
|
"'failover': 'on',"
|
||||||
|
"'netdev': 'hs0',"
|
||||||
|
"'mac': '"MAC_STANDBY0"'}");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
vdev = start_virtio_net(qts, 1, 0, "standby0");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qtest_qmp_device_add(qts, "virtio-net", "primary0",
|
||||||
|
"{'bus': 'root1',"
|
||||||
|
"'failover_pair_id': 'standby0',"
|
||||||
|
"'netdev': 'hs1',"
|
||||||
|
"'rombar': 0,"
|
||||||
|
"'romfile': '',"
|
||||||
|
"'mac': '"MAC_PRIMARY0"'}");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, true, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
args = qdict_from_jsonf_nofail("{}");
|
||||||
|
g_assert_nonnull(args);
|
||||||
|
qdict_put_str(args, "uri", uri);
|
||||||
|
|
||||||
|
resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args);
|
||||||
|
g_assert(qdict_haskey(resp, "return"));
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
/* the event is sent when QEMU asks the OS to unplug the card */
|
||||||
|
resp = get_unplug_primary_event(qts);
|
||||||
|
g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0");
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }");
|
||||||
|
g_assert(qdict_haskey(resp, "return"));
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
/* migration has been cancelled while the unplug was in progress */
|
||||||
|
|
||||||
|
/* while the card is not ejected, we must be in "cancelling" state */
|
||||||
|
ret = migrate_status(qts);
|
||||||
|
|
||||||
|
status = qdict_get_str(ret, "status");
|
||||||
|
g_assert_cmpstr(status, ==, "cancelling");
|
||||||
|
qobject_unref(ret);
|
||||||
|
|
||||||
|
/* OS unplugs the cards, QEMU can move from wait-unplug state */
|
||||||
|
qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ret = migrate_status(qts);
|
||||||
|
|
||||||
|
status = qdict_get_str(ret, "status");
|
||||||
|
if (strcmp(status, "cancelled") == 0) {
|
||||||
|
qobject_unref(ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_assert_cmpstr(status, !=, "failed");
|
||||||
|
g_assert_cmpstr(status, !=, "active");
|
||||||
|
qobject_unref(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, true, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qos_object_destroy((QOSGraphObject *)vdev);
|
||||||
|
machine_stop(qts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_migrate_abort_active(gconstpointer opaque)
|
||||||
|
{
|
||||||
|
QTestState *qts;
|
||||||
|
QDict *resp, *args, *ret;
|
||||||
|
g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque);
|
||||||
|
const gchar *status;
|
||||||
|
QVirtioPCIDevice *vdev;
|
||||||
|
|
||||||
|
qts = machine_start(BASE_MACHINE
|
||||||
|
"-netdev user,id=hs0 "
|
||||||
|
"-netdev user,id=hs1 ",
|
||||||
|
2);
|
||||||
|
|
||||||
|
check_one_card(qts, false, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qtest_qmp_device_add(qts, "virtio-net", "standby0",
|
||||||
|
"{'bus': 'root0',"
|
||||||
|
"'failover': 'on',"
|
||||||
|
"'netdev': 'hs0',"
|
||||||
|
"'mac': '"MAC_STANDBY0"'}");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
vdev = start_virtio_net(qts, 1, 0, "standby0");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qtest_qmp_device_add(qts, "virtio-net", "primary0",
|
||||||
|
"{'bus': 'root1',"
|
||||||
|
"'failover_pair_id': 'standby0',"
|
||||||
|
"'netdev': 'hs1',"
|
||||||
|
"'rombar': 0,"
|
||||||
|
"'romfile': '',"
|
||||||
|
"'mac': '"MAC_PRIMARY0"'}");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, true, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
args = qdict_from_jsonf_nofail("{}");
|
||||||
|
g_assert_nonnull(args);
|
||||||
|
qdict_put_str(args, "uri", uri);
|
||||||
|
|
||||||
|
resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args);
|
||||||
|
g_assert(qdict_haskey(resp, "return"));
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
/* the event is sent when QEMU asks the OS to unplug the card */
|
||||||
|
resp = get_unplug_primary_event(qts);
|
||||||
|
g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0");
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
/* OS unplugs the cards, QEMU can move from wait-unplug state */
|
||||||
|
qtest_outl(qts, ACPI_PCIHP_ADDR_ICH9 + PCI_EJ_BASE, 1);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ret = migrate_status(qts);
|
||||||
|
|
||||||
|
status = qdict_get_str(ret, "status");
|
||||||
|
if (strcmp(status, "wait-unplug") != 0) {
|
||||||
|
qobject_unref(ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_assert_cmpstr(status, !=, "failed");
|
||||||
|
qobject_unref(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }");
|
||||||
|
g_assert(qdict_haskey(resp, "return"));
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
ret = migrate_status(qts);
|
||||||
|
|
||||||
|
status = qdict_get_str(ret, "status");
|
||||||
|
if (strcmp(status, "cancelled") == 0) {
|
||||||
|
qobject_unref(ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_assert_cmpstr(status, !=, "failed");
|
||||||
|
g_assert_cmpstr(status, !=, "active");
|
||||||
|
qobject_unref(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, true, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qos_object_destroy((QOSGraphObject *)vdev);
|
||||||
|
machine_stop(qts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_migrate_abort_timeout(gconstpointer opaque)
|
||||||
|
{
|
||||||
|
QTestState *qts;
|
||||||
|
QDict *resp, *args, *ret;
|
||||||
|
g_autofree gchar *uri = g_strdup_printf("exec: cat > %s", (gchar *)opaque);
|
||||||
|
const gchar *status;
|
||||||
|
int total;
|
||||||
|
QVirtioPCIDevice *vdev;
|
||||||
|
|
||||||
|
qts = machine_start(BASE_MACHINE
|
||||||
|
"-netdev user,id=hs0 "
|
||||||
|
"-netdev user,id=hs1 ",
|
||||||
|
2);
|
||||||
|
|
||||||
|
check_one_card(qts, false, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qtest_qmp_device_add(qts, "virtio-net", "standby0",
|
||||||
|
"{'bus': 'root0',"
|
||||||
|
"'failover': 'on',"
|
||||||
|
"'netdev': 'hs0',"
|
||||||
|
"'mac': '"MAC_STANDBY0"'}");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
vdev = start_virtio_net(qts, 1, 0, "standby0");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, false, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qtest_qmp_device_add(qts, "virtio-net", "primary0",
|
||||||
|
"{'bus': 'root1',"
|
||||||
|
"'failover_pair_id': 'standby0',"
|
||||||
|
"'netdev': 'hs1',"
|
||||||
|
"'rombar': 0,"
|
||||||
|
"'romfile': '',"
|
||||||
|
"'mac': '"MAC_PRIMARY0"'}");
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, true, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
args = qdict_from_jsonf_nofail("{}");
|
||||||
|
g_assert_nonnull(args);
|
||||||
|
qdict_put_str(args, "uri", uri);
|
||||||
|
|
||||||
|
resp = qtest_qmp(qts, "{ 'execute': 'migrate', 'arguments': %p}", args);
|
||||||
|
g_assert(qdict_haskey(resp, "return"));
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
/* the event is sent when QEMU asks the OS to unplug the card */
|
||||||
|
resp = get_unplug_primary_event(qts);
|
||||||
|
g_assert_cmpstr(qdict_get_str(resp, "device-id"), ==, "primary0");
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
resp = qtest_qmp(qts, "{ 'execute': 'migrate_cancel' }");
|
||||||
|
g_assert(qdict_haskey(resp, "return"));
|
||||||
|
qobject_unref(resp);
|
||||||
|
|
||||||
|
/* migration has been cancelled while the unplug was in progress */
|
||||||
|
|
||||||
|
/* while the card is not ejected, we must be in "cancelling" state */
|
||||||
|
|
||||||
|
total = 0;
|
||||||
|
while (true) {
|
||||||
|
ret = migrate_status(qts);
|
||||||
|
|
||||||
|
status = qdict_get_str(ret, "status");
|
||||||
|
if (strcmp(status, "cancelled") == 0) {
|
||||||
|
qobject_unref(ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_assert_cmpstr(status, ==, "cancelling");
|
||||||
|
g_assert(qdict_haskey(ret, "total-time"));
|
||||||
|
total = qdict_get_int(ret, "total-time");
|
||||||
|
qobject_unref(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* migration timeout in this case is 30 seconds
|
||||||
|
* check we exit on the timeout (ms)
|
||||||
|
*/
|
||||||
|
g_assert_cmpint(total, >, 30000);
|
||||||
|
|
||||||
|
check_one_card(qts, true, "standby0", MAC_STANDBY0);
|
||||||
|
check_one_card(qts, true, "primary0", MAC_PRIMARY0);
|
||||||
|
|
||||||
|
qos_object_destroy((QOSGraphObject *)vdev);
|
||||||
|
machine_stop(qts);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
const gchar *tmpdir = g_get_tmp_dir();
|
const gchar *tmpdir = g_get_tmp_dir();
|
||||||
@ -778,6 +1052,14 @@ int main(int argc, char **argv)
|
|||||||
test_migrate_out);
|
test_migrate_out);
|
||||||
qtest_add_data_func("failover-virtio-net/migrate/in", tmpfile,
|
qtest_add_data_func("failover-virtio-net/migrate/in", tmpfile,
|
||||||
test_migrate_in);
|
test_migrate_in);
|
||||||
|
qtest_add_data_func("failover-virtio-net/migrate/abort/wait-unplug",
|
||||||
|
tmpfile, test_migrate_abort_wait_unplug);
|
||||||
|
qtest_add_data_func("failover-virtio-net/migrate/abort/active", tmpfile,
|
||||||
|
test_migrate_abort_active);
|
||||||
|
if (g_test_slow()) {
|
||||||
|
qtest_add_data_func("failover-virtio-net/migrate/abort/timeout",
|
||||||
|
tmpfile, test_migrate_abort_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
ret = g_test_run();
|
ret = g_test_run();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user