gms: feature_service: re-enable features on node startup
Re-enable previously persisted enabled features on node startup. The features list to be enabled is read from `system.local#enabled_features`. In case an unknown feature is encountered, the node fails to boot with an exception, because that means the node is doing a prohibited downgrade procedure. Features should be enabled before commitlog starts replaying since some features affect storage (for example, when determining used sstable format). This patch implements a part of solution proposed by Tomek in https://github.com/scylladb/scylla/issues/4458. Tests: unit(dev) Signed-off-by: Pavel Solodovnikov <pa.solodovnikov@scylladb.com>
This commit is contained in:
committed by
Avi Kivity
parent
777985b64d
commit
1365e2f13e
@@ -2932,6 +2932,41 @@ future<> system_keyspace::delete_paxos_decision(const schema& s, const partition
|
||||
).discard_result();
|
||||
}
|
||||
|
||||
future<> system_keyspace::enable_features_on_startup(sharded<gms::feature_service>& feat) {
|
||||
auto pre_enabled_features = co_await get_scylla_local_param(gms::feature_service::ENABLED_FEATURES_KEY);
|
||||
if (!pre_enabled_features) {
|
||||
co_return;
|
||||
}
|
||||
gms::feature_service& local_feat_srv = feat.local();
|
||||
const auto known_features = local_feat_srv.known_feature_set();
|
||||
const auto& registered_features = local_feat_srv.registered_features();
|
||||
const auto persisted_features = gms::feature_service::to_feature_set(*pre_enabled_features);
|
||||
for (auto&& f : persisted_features) {
|
||||
slogger.debug("Enabling persisted feature '{}'", f);
|
||||
const bool is_registered_feat = registered_features.contains(sstring(f));
|
||||
if (!is_registered_feat || !known_features.contains(f)) {
|
||||
if (is_registered_feat) {
|
||||
throw std::runtime_error(format(
|
||||
"Feature '{}' was previously enabled in the cluster but its support is disabled by this node. "
|
||||
"Set the corresponding configuration option to enable the support for the feature.", f));
|
||||
} else {
|
||||
throw std::runtime_error(format("Unknown feature '{}' was previously enabled in the cluster. "
|
||||
" That means this node is performing a prohibited downgrade procedure"
|
||||
" and should not be allowed to boot.", f));
|
||||
}
|
||||
}
|
||||
if (is_registered_feat) {
|
||||
// `gms::feature::enable` should be run within a seastar thread context
|
||||
co_await seastar::async([&local_feat_srv, f] {
|
||||
local_feat_srv.enable(sstring(f));
|
||||
});
|
||||
}
|
||||
// If a feature is not in `registered_features` but still in `known_features` list
|
||||
// that means the feature name is used for backward compatibility and should be implicitly
|
||||
// enabled in the code by default, so just skip it.
|
||||
}
|
||||
}
|
||||
|
||||
sstring system_keyspace_name() {
|
||||
return system_keyspace::NAME;
|
||||
}
|
||||
|
||||
@@ -415,6 +415,7 @@ public:
|
||||
static future<bool> cdc_is_rewritten();
|
||||
static future<> cdc_set_rewritten(std::optional<cdc::generation_id_v1>);
|
||||
|
||||
static future<> enable_features_on_startup(sharded<gms::feature_service>& feat);
|
||||
}; // class system_keyspace
|
||||
|
||||
future<> system_keyspace_make(distributed<database>& db, distributed<service::storage_service>& ss);
|
||||
|
||||
6
main.cc
6
main.cc
@@ -967,6 +967,12 @@ int main(int ac, char** av) {
|
||||
|
||||
supervisor::notify("setting up system keyspace");
|
||||
db::system_keyspace::setup(db, qp, feature_service, messaging).get();
|
||||
|
||||
// Re-enable previously enabled features on node startup.
|
||||
// This should be done before commitlog starts replaying
|
||||
// since some features affect storage.
|
||||
db::system_keyspace::enable_features_on_startup(feature_service).get();
|
||||
|
||||
supervisor::notify("starting commit log");
|
||||
auto cl = db.local().commitlog();
|
||||
if (cl != nullptr) {
|
||||
|
||||
Reference in New Issue
Block a user