On Tue, 6 Jan 2026 15:03:11 -0500
Peter Xu <[email protected]> wrote:

> On Tue, Dec 30, 2025 at 03:05:46PM +0100, Lukas Straub wrote:
> > Add a COLO migration test for COLO migration and failover.
> > 
> > COLO does not support q35 machine at this time.
> > 
> > Signed-off-by: Lukas Straub <[email protected]>
> > ---
> >  tests/qtest/meson.build            |   7 ++-
> >  tests/qtest/migration-test.c       |   1 +
> >  tests/qtest/migration/colo-tests.c | 115 
> > +++++++++++++++++++++++++++++++++++++
> >  tests/qtest/migration/framework.c  |  65 ++++++++++++++++++++-
> >  tests/qtest/migration/framework.h  |   9 +++
> >  5 files changed, 195 insertions(+), 2 deletions(-)
> > 
> > [...]
> > +
> > +void migration_test_add_colo(MigrationTestEnv *env)
> > +{
> > +    migration_test_add("/migration/colo/plain/secondary_failover",
> > +                       test_colo_plain_secondary_failover);
> > +
> > +    migration_test_add("/migration/colo/multifd/secondary_failover",
> > +                       test_colo_multifd_secondary_failover);
> > +
> > +    if (!env->full_set) {
> > +        return;
> > +    }  
> 
> IMHO we can skip all COLO tests in full_set.  Don't worry, if it's merged
> at least Fabiano and myself will always run it, making sure migration
> patches will be smoked.
> 
> Here it's about whether we will run it in everyone's CI.

Okay, I will fix this in the next version.

> 
> > +
> > +    migration_test_add("/migration/colo/plain/primary_failover",
> > +                       test_colo_plain_primary_failover);
> > +
> > +    migration_test_add("/migration/colo/multifd/primary_failover",
> > +                       test_colo_multifd_primary_failover);
> > +
> > +    migration_test_add("/migration/colo/plain/primary_failover_checkpoint",
> > +                       test_colo_plain_primary_failover_checkpoint);
> > +    
> > migration_test_add("/migration/colo/plain/secondary_failover_checkpoint",
> > +                       test_colo_plain_secondary_failover_checkpoint);
> > +
> > +    
> > migration_test_add("/migration/colo/multifd/primary_failover_checkpoint",
> > +                       test_colo_multifd_primary_failover_checkpoint);
> > +    
> > migration_test_add("/migration/colo/multifd/secondary_failover_checkpoint",
> > +                       test_colo_multifd_secondary_failover_checkpoint);
> > +}
> > diff --git a/tests/qtest/migration/framework.c 
> > b/tests/qtest/migration/framework.c
> > index 
> > 8c1fc6e009f16dc05a47e917167f62e0250ca992..08bca49a8980f9988be9447acf54b17acd56da94
> >  100644
> > --- a/tests/qtest/migration/framework.c
> > +++ b/tests/qtest/migration/framework.c
> > @@ -315,7 +315,7 @@ int migrate_args(char **from, char **to, const char 
> > *uri, MigrateStart *args)
> >      if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
> >          memory_size = "150M";
> >  
> > -        if (g_str_equal(arch, "i386")) {
> > +        if (g_str_equal(arch, "i386") || args->is_colo) {  
> 
> OK, one more reference..
> 
> I'm curious, why Q35 is not supported?

There is a bug in the emulated ahci disk controller which crashes when
it's vmstate is loaded more than once.

> 
> >              machine_alias = "pc";
> >          } else {
> >              machine_alias = "q35";
> > @@ -1068,6 +1068,69 @@ void 
> > *migrate_hook_start_precopy_tcp_multifd_common(QTestState *from,
> >      return NULL;
> >  }
> >  
> > +int test_colo_common(MigrateCommon *args)
> > +{
> > +    QTestState *from, *to;
> > +    void *data_hook = NULL;
> > +
> > +    args->start.oob = true;
> > +    args->start.is_colo = true;
> > +    args->start.caps[MIGRATION_CAPABILITY_X_COLO] = true;
> > +
> > +    if (migrate_start(&from, &to, args->listen_uri, &args->start)) {
> > +        return -1;
> > +    }
> > +
> > +    migrate_set_parameter_int(from, "x-checkpoint-delay", 300);
> > +
> > +    if (args->start_hook) {
> > +        data_hook = args->start_hook(from, to);
> > +    }
> > +
> > +    migrate_ensure_converge(from);
> > +    wait_for_serial("src_serial");
> > +
> > +    migrate_qmp(from, to, args->connect_uri, NULL, "{}");
> > +
> > +    wait_for_migration_status(from, "colo", NULL);
> > +    wait_for_resume(to, &dst_state);
> > +
> > +    wait_for_serial("src_serial");
> > +    wait_for_serial("dest_serial");
> > +
> > +    /* wait for 3 checkpoints */
> > +    for (int i = 0; i < 3; i++) {
> > +        qtest_qmp_eventwait(to, "RESUME");
> > +        wait_for_serial("src_serial");
> > +        wait_for_serial("dest_serial");
> > +    }
> > +
> > +    if (args->colo_failover_during_checkpoint) {
> > +        qtest_qmp_eventwait(to, "STOP");
> > +    }
> > +    if (args->colo_primary_failover) {
> > +        qtest_qmp_assert_success(from, "{'exec-oob': 'yank', 'id': 
> > 'yank-cmd', "
> > +                                            "'arguments': {'instances':"
> > +                                                "[{'type': 
> > 'migration'}]}}");
> > +        qtest_qmp_assert_success(from, "{'execute': 
> > 'x-colo-lost-heartbeat'}");
> > +        wait_for_serial("src_serial");
> > +    } else {
> > +        qtest_qmp_assert_success(to, "{'exec-oob': 'yank', 'id': 
> > 'yank-cmd', "
> > +                                        "'arguments': {'instances':"
> > +                                            "[{'type': 'migration'}]}}");
> > +        qtest_qmp_assert_success(to, "{'execute': 
> > 'x-colo-lost-heartbeat'}");
> > +        wait_for_serial("dest_serial");
> > +    }
> > +
> > +    if (args->end_hook) {
> > +        args->end_hook(from, to, data_hook);
> > +    }
> > +
> > +    migrate_end(from, to, !args->colo_primary_failover);
> > +
> > +    return 0;
> > +}
> > +
> >  QTestMigrationState *get_src(void)
> >  {
> >      return &src_state;
> > diff --git a/tests/qtest/migration/framework.h 
> > b/tests/qtest/migration/framework.h
> > index 
> > 2ea13e7758697550b5531737e66d6d939dd800d1..1da532569d8c5941c99d83ae7da88ccab2bdcbe2
> >  100644
> > --- a/tests/qtest/migration/framework.h
> > +++ b/tests/qtest/migration/framework.h
> > @@ -230,6 +230,9 @@ typedef struct {
> >       */
> >      bool live;
> >  
> > +    bool colo_primary_failover;
> > +    bool colo_failover_during_checkpoint;  
> 
> Let's try to not add more per-feature fields here into the test framework
> struct.  My bad to have started doing this for postcopy tests..  I'll
> prepare patches to remove the postcopy ones.  These parameters can be
> passed from the test callers, afaict.
> 
> Thanks,
> 
> > +
> >      /* Postcopy specific fields */
> >      void *postcopy_data;
> >      PostcopyRecoveryFailStage postcopy_recovery_fail_stage;
> > @@ -248,6 +251,7 @@ void test_postcopy_common(MigrateCommon *args);
> >  void test_postcopy_recovery_common(MigrateCommon *args);
> >  int test_precopy_common(MigrateCommon *args);
> >  void test_file_common(MigrateCommon *args, bool stop_src);
> > +int test_colo_common(MigrateCommon *args);
> >  void *migrate_hook_start_precopy_tcp_multifd_common(QTestState *from,
> >                                                      QTestState *to,
> >                                                      const char *method);
> > @@ -267,5 +271,10 @@ void migration_test_add_file(MigrationTestEnv *env);
> >  void migration_test_add_precopy(MigrationTestEnv *env);
> >  void migration_test_add_cpr(MigrationTestEnv *env);
> >  void migration_test_add_misc(MigrationTestEnv *env);
> > +#ifdef CONFIG_REPLICATION
> > +void migration_test_add_colo(MigrationTestEnv *env);
> > +#else
> > +static inline void migration_test_add_colo(MigrationTestEnv *env) {};
> > +#endif
> >  
> >  #endif /* TEST_FRAMEWORK_H */
> > 
> > -- 
> > 2.39.5
> >   
> 

Attachment: pgp3BScZ9PbhA.pgp
Description: OpenPGP digital signature

Reply via email to