@@ -215,19 +215,19 @@ setup_steps() ->
215215 fun rabbit_ct_helpers :ensure_rabbitmqctl_app /1 ,
216216 fun rabbit_ct_helpers :ensure_rabbitmq_plugins_cmd /1 ,
217217 fun set_lager_flood_limit /1 ,
218+ fun configure_metadata_store /1 ,
218219 fun start_rabbitmq_nodes /1 ,
219- fun share_dist_and_proxy_ports_map /1 ,
220- fun configure_metadata_store /1
220+ fun share_dist_and_proxy_ports_map /1
221221 ];
222222 _ ->
223223 [
224224 fun rabbit_ct_helpers :ensure_rabbitmqctl_cmd /1 ,
225225 fun rabbit_ct_helpers :load_rabbitmqctl_app /1 ,
226226 fun rabbit_ct_helpers :ensure_rabbitmq_plugins_cmd /1 ,
227227 fun set_lager_flood_limit /1 ,
228+ fun configure_metadata_store /1 ,
228229 fun start_rabbitmq_nodes /1 ,
229- fun share_dist_and_proxy_ports_map /1 ,
230- fun configure_metadata_store /1
230+ fun share_dist_and_proxy_ports_map /1
231231 ]
232232 end .
233233
@@ -441,8 +441,24 @@ start_rabbitmq_node(Master, Config, NodeConfig, I) ->
441441 {failed_boot_attempts , Attempts + 1 }),
442442 start_rabbitmq_node (Master , Config , NodeConfig5 , I );
443443 NodeConfig4 ->
444- Master ! {self (), I , NodeConfig4 },
445- unlink (Master )
444+ case uses_expected_metadata_store (Config , NodeConfig4 ) of
445+ {MetadataStore , MetadataStore } ->
446+ Master ! {self (), I , NodeConfig4 },
447+ unlink (Master );
448+ {ExpectedMetadataStore , UsedMetadataStore } ->
449+ % % If the active metadata store is not the one expected, we
450+ % % stop the node and skip the test.
451+ stop_rabbitmq_node (Config , NodeConfig4 ),
452+ Nodename = ? config (nodename , NodeConfig4 ),
453+ Error = {skip ,
454+ rabbit_misc :format (
455+ " Node ~s is using the ~s metadata store, "
456+ " ~s was expected" ,
457+ [Nodename , UsedMetadataStore ,
458+ ExpectedMetadataStore ])},
459+ Master ! {self (), Error },
460+ unlink (Master )
461+ end
446462 end .
447463
448464run_node_steps (Config , NodeConfig , I , [Step | Rest ]) ->
@@ -883,6 +899,55 @@ query_node(Config, NodeConfig) ->
883899 cover_add_node (Nodename ),
884900 rabbit_ct_helpers :set_config (NodeConfig , Vars ).
885901
902+ uses_expected_metadata_store (Config , NodeConfig ) ->
903+ % % We want to verify if the active metadata store matches the expected one.
904+ % %
905+ % % Before that, we may need to enable `khepri_db' on the node because if it
906+ % % doesn't support the relative forced feature flags mechanism, it will
907+ % % ignore the setting from `configure_metadata_store/1'. In this case, we
908+ % % have to enable it at runtime.
909+ Nodename = ? config (nodename , NodeConfig ),
910+ ExpectedMetadataStore = rabbit_ct_helpers :get_config (
911+ Config , metadata_store ),
912+ case ExpectedMetadataStore of
913+ mnesia -> ok ;
914+ khepri -> maybe_enable_khepri_as_expected (Config , Nodename )
915+ end ,
916+ IsKhepriEnabled = rpc (Config , Nodename , rabbit_khepri , is_enabled , []),
917+ UsedMetadataStore = case IsKhepriEnabled of
918+ true -> khepri ;
919+ false -> mnesia
920+ end ,
921+ ct :pal (
922+ " Metadata store on ~s : expected=~s , used=~s " ,
923+ [Nodename , UsedMetadataStore , ExpectedMetadataStore ]),
924+ {ExpectedMetadataStore , UsedMetadataStore }.
925+
926+ maybe_enable_khepri_as_expected (Config , Nodename ) ->
927+ % % We detect if the remote node supports the relative forced feature flags
928+ % % mechanism by checking if `rabbit_feature_flags:get_require_level/1' is
929+ % % exported. This is unrelated to the mechanism but it was committed around
930+ % % the same time and was not backported either.
931+ RelativeForcedFeatureFlagsUnsupported = (
932+ rpc (Config , Nodename ,
933+ erlang , function_exported ,
934+ [rabbit_feature_flags , get_require_level , 1 ])
935+ ),
936+ case RelativeForcedFeatureFlagsUnsupported of
937+ true ->
938+ ok ;
939+ false ->
940+ ct :pal (
941+ " Relative forced feature flags unsupported on ~s , "
942+ " enable Khepri now" ,
943+ [Nodename ]),
944+ Ret = enable_feature_flag (Config , [Nodename ], khepri_db ),
945+ ct :pal (
946+ " Tried to enable Khepri on ~s as expected: ~0p " ,
947+ [Nodename , Ret ]),
948+ ok
949+ end .
950+
886951maybe_cluster_nodes (Config ) ->
887952 Clustered0 = rabbit_ct_helpers :get_config (Config , rmq_nodes_clustered ),
888953 Clustered = case Clustered0 of
@@ -999,57 +1064,71 @@ share_dist_and_proxy_ports_map(Config) ->
9991064configured_metadata_store (Config ) ->
10001065 case rabbit_ct_helpers :get_config (Config , metadata_store ) of
10011066 khepri ->
1002- {khepri , []};
1003- {khepri , _FFs0 } = Khepri ->
1004- Khepri ;
1067+ khepri ;
10051068 mnesia ->
10061069 mnesia ;
10071070 _ ->
10081071 case os :getenv (" RABBITMQ_METADATA_STORE" ) of
1009- " khepri" ->
1010- {khepri , []};
1011- _ ->
1012- mnesia
1072+ " khepri" -> khepri ;
1073+ _ -> mnesia
10131074 end
10141075 end .
10151076
10161077configure_metadata_store (Config ) ->
10171078 ct :log (" Configuring metadata store..." ),
1018- case configured_metadata_store (Config ) of
1019- {khepri , FFs0 } ->
1020- case enable_khepri_metadata_store (Config , FFs0 ) of
1021- {skip , _ } = Skip ->
1022- _ = stop_rabbitmq_nodes (Config ),
1023- Skip ;
1024- Config1 ->
1025- Config1
1079+ Value = rabbit_ct_helpers :get_app_env (
1080+ Config , rabbit , forced_feature_flags_on_init , undefined ),
1081+ MetadataStore = configured_metadata_store (Config ),
1082+ Config1 = rabbit_ct_helpers :set_config (
1083+ Config , {metadata_store , MetadataStore }),
1084+ % % To enabled or disable `khepri_db', we use the relative forced feature
1085+ % % flags mechanism. This allows us to select the state of Khepri without
1086+ % % having to worry about other feature flags.
1087+ % %
1088+ % % However, RabbitMQ 4.0.x and older don't support it. See the
1089+ % % `uses_expected_metadata_store/2' check to see how Khepri is enabled in
1090+ % % this case.
1091+ case MetadataStore of
1092+ khepri ->
1093+ ct :log (" Enabling Khepri metadata store" ),
1094+ case Value of
1095+ undefined ->
1096+ rabbit_ct_helpers :merge_app_env (
1097+ Config1 ,
1098+ {rabbit ,
1099+ [{forced_feature_flags_on_init ,
1100+ {rel , [khepri_db ], []}}]});
1101+ _ ->
1102+ rabbit_ct_helpers :merge_app_env (
1103+ Config1 ,
1104+ {rabbit ,
1105+ [{forced_feature_flags_on_init ,
1106+ [khepri_db | Value ]}]})
10261107 end ;
10271108 mnesia ->
10281109 ct :log (" Enabling Mnesia metadata store" ),
1029- Config
1110+ case Value of
1111+ undefined ->
1112+ rabbit_ct_helpers :merge_app_env (
1113+ Config1 ,
1114+ {rabbit ,
1115+ [{forced_feature_flags_on_init ,
1116+ {rel , [], [khepri_db ]}}]});
1117+ _ ->
1118+ rabbit_ct_helpers :merge_app_env (
1119+ Config1 ,
1120+ {rabbit ,
1121+ [{forced_feature_flags_on_init ,
1122+ Value -- [khepri_db ]}]})
1123+ end
10301124 end .
10311125
1032- enable_khepri_metadata_store (Config , FFs0 ) ->
1033- ct :log (" Enabling Khepri metadata store" ),
1034- FFs = [khepri_db | FFs0 ],
1035- lists :foldl (fun (_FF , {skip , _Reason } = Skip ) ->
1036- Skip ;
1037- (FF , C ) ->
1038- case enable_feature_flag (C , FF ) of
1039- ok ->
1040- C ;
1041- {skip , _ } = Skip ->
1042- ct :pal (" Enabling metadata store failed: ~p " , [Skip ]),
1043- Skip
1044- end
1045- end , Config , FFs ).
1046-
10471126% % Waits until the metadata store replica on Node is up to date with the leader.
10481127await_metadata_store_consistent (Config , Node ) ->
10491128 case configured_metadata_store (Config ) of
10501129 mnesia ->
10511130 ok ;
1052- { khepri , _ } ->
1131+ khepri ->
10531132 RaClusterName = rabbit_khepri :get_ra_cluster_name (),
10541133 Leader = rpc (Config , Node , ra_leaderboard , lookup_leader , [RaClusterName ]),
10551134 LastAppliedLeader = ra_last_applied (Leader ),
0 commit comments