@@ -215,19 +215,19 @@ setup_steps() ->
215
215
fun rabbit_ct_helpers :ensure_rabbitmqctl_app /1 ,
216
216
fun rabbit_ct_helpers :ensure_rabbitmq_plugins_cmd /1 ,
217
217
fun set_lager_flood_limit /1 ,
218
+ fun configure_metadata_store /1 ,
218
219
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
221
221
];
222
222
_ ->
223
223
[
224
224
fun rabbit_ct_helpers :ensure_rabbitmqctl_cmd /1 ,
225
225
fun rabbit_ct_helpers :load_rabbitmqctl_app /1 ,
226
226
fun rabbit_ct_helpers :ensure_rabbitmq_plugins_cmd /1 ,
227
227
fun set_lager_flood_limit /1 ,
228
+ fun configure_metadata_store /1 ,
228
229
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
231
231
]
232
232
end .
233
233
@@ -441,8 +441,24 @@ start_rabbitmq_node(Master, Config, NodeConfig, I) ->
441
441
{failed_boot_attempts , Attempts + 1 }),
442
442
start_rabbitmq_node (Master , Config , NodeConfig5 , I );
443
443
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
446
462
end .
447
463
448
464
run_node_steps (Config , NodeConfig , I , [Step | Rest ]) ->
@@ -883,6 +899,67 @@ query_node(Config, NodeConfig) ->
883
899
cover_add_node (Nodename ),
884
900
rabbit_ct_helpers :set_config (NodeConfig , Vars ).
885
901
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 to enable expected metadata store" ,
943
+ [Nodename ]),
944
+ Ret = enable_feature_flag (Config , [Nodename ], khepri_db ),
945
+ case Ret of
946
+ ok ->
947
+ ok ;
948
+ {error , missing_clustered_nodes } ->
949
+ ct :pal (
950
+ " Tried to enable Khepri on ~s as expected, but node "
951
+ " not ready; retrying in 1 second" ,
952
+ [Nodename ]),
953
+ timer :sleep (1000 ),
954
+ maybe_enable_khepri_as_expected (Config , Nodename );
955
+ _ ->
956
+ ct :pal (
957
+ " Tried to enable Khepri on ~s as expected: ~0p " ,
958
+ [Nodename , Ret ]),
959
+ ok
960
+ end
961
+ end .
962
+
886
963
maybe_cluster_nodes (Config ) ->
887
964
Clustered0 = rabbit_ct_helpers :get_config (Config , rmq_nodes_clustered ),
888
965
Clustered = case Clustered0 of
@@ -999,57 +1076,71 @@ share_dist_and_proxy_ports_map(Config) ->
999
1076
configured_metadata_store (Config ) ->
1000
1077
case rabbit_ct_helpers :get_config (Config , metadata_store ) of
1001
1078
khepri ->
1002
- {khepri , []};
1003
- {khepri , _FFs0 } = Khepri ->
1004
- Khepri ;
1079
+ khepri ;
1005
1080
mnesia ->
1006
1081
mnesia ;
1007
1082
_ ->
1008
1083
case os :getenv (" RABBITMQ_METADATA_STORE" ) of
1009
- " khepri" ->
1010
- {khepri , []};
1011
- _ ->
1012
- mnesia
1084
+ " khepri" -> khepri ;
1085
+ _ -> mnesia
1013
1086
end
1014
1087
end .
1015
1088
1016
1089
configure_metadata_store (Config ) ->
1017
1090
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
1091
+ Value = rabbit_ct_helpers :get_app_env (
1092
+ Config , rabbit , forced_feature_flags_on_init , undefined ),
1093
+ MetadataStore = configured_metadata_store (Config ),
1094
+ Config1 = rabbit_ct_helpers :set_config (
1095
+ Config , {metadata_store , MetadataStore }),
1096
+ % % To enabled or disable `khepri_db', we use the relative forced feature
1097
+ % % flags mechanism. This allows us to select the state of Khepri without
1098
+ % % having to worry about other feature flags.
1099
+ % %
1100
+ % % However, RabbitMQ 4.0.x and older don't support it. See the
1101
+ % % `uses_expected_metadata_store/2' check to see how Khepri is enabled in
1102
+ % % this case.
1103
+ case MetadataStore of
1104
+ khepri ->
1105
+ ct :log (" Enabling Khepri metadata store" ),
1106
+ case Value of
1107
+ undefined ->
1108
+ rabbit_ct_helpers :merge_app_env (
1109
+ Config1 ,
1110
+ {rabbit ,
1111
+ [{forced_feature_flags_on_init ,
1112
+ {rel , [khepri_db ], []}}]});
1113
+ _ ->
1114
+ rabbit_ct_helpers :merge_app_env (
1115
+ Config1 ,
1116
+ {rabbit ,
1117
+ [{forced_feature_flags_on_init ,
1118
+ [khepri_db | Value ]}]})
1026
1119
end ;
1027
1120
mnesia ->
1028
1121
ct :log (" Enabling Mnesia metadata store" ),
1029
- Config
1122
+ case Value of
1123
+ undefined ->
1124
+ rabbit_ct_helpers :merge_app_env (
1125
+ Config1 ,
1126
+ {rabbit ,
1127
+ [{forced_feature_flags_on_init ,
1128
+ {rel , [], [khepri_db ]}}]});
1129
+ _ ->
1130
+ rabbit_ct_helpers :merge_app_env (
1131
+ Config1 ,
1132
+ {rabbit ,
1133
+ [{forced_feature_flags_on_init ,
1134
+ Value -- [khepri_db ]}]})
1135
+ end
1030
1136
end .
1031
1137
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
-
1047
1138
% % Waits until the metadata store replica on Node is up to date with the leader.
1048
1139
await_metadata_store_consistent (Config , Node ) ->
1049
1140
case configured_metadata_store (Config ) of
1050
1141
mnesia ->
1051
1142
ok ;
1052
- { khepri , _ } ->
1143
+ khepri ->
1053
1144
RaClusterName = rabbit_khepri :get_ra_cluster_name (),
1054
1145
Leader = rpc (Config , Node , ra_leaderboard , lookup_leader , [RaClusterName ]),
1055
1146
LastAppliedLeader = ra_last_applied (Leader ),
0 commit comments