diff --git a/docs/rfcs/035-safekeeper-dynamic-membership-change.md b/docs/rfcs/035-safekeeper-dynamic-membership-change.md index 8619f83ff58f..aca3b720c9af 100644 --- a/docs/rfcs/035-safekeeper-dynamic-membership-change.md +++ b/docs/rfcs/035-safekeeper-dynamic-membership-change.md @@ -356,7 +356,7 @@ Node management is similar to pageserver: 2) GET `/control/v1/safekeeper` lists safekeepers. 3) GET `/control/v1/safekeeper/:node_id` gets safekeeper. 4) PUT `/control/v1/safekeper/:node_id/scheduling_policy` changes status to e.g. - `offline` or `decomissioned`. Initially it is simpler not to schedule any + `offline` or `decommissioned`. Initially it is simpler not to schedule any migrations here. Safekeeper deploy scripts should register safekeeper at storage_contorller as diff --git a/libs/pageserver_api/src/controller_api.rs b/libs/pageserver_api/src/controller_api.rs index 1248be0b5c60..497df9e6a849 100644 --- a/libs/pageserver_api/src/controller_api.rs +++ b/libs/pageserver_api/src/controller_api.rs @@ -438,7 +438,8 @@ pub enum SkSchedulingPolicy { Active, Activating, Pause, - Decomissioned, + #[serde(alias = "Decomissioned")] + Decommissioned, } impl FromStr for SkSchedulingPolicy { @@ -449,10 +450,10 @@ impl FromStr for SkSchedulingPolicy { "active" => Self::Active, "activating" => Self::Activating, "pause" => Self::Pause, - "decomissioned" => Self::Decomissioned, + "decommissioned" | "decomissioned" => Self::Decommissioned, _ => { return Err(anyhow::anyhow!( - "Unknown scheduling policy '{s}', try active,pause,decomissioned" + "Unknown scheduling policy '{s}', try active,pause,decommissioned" )); } }) @@ -466,7 +467,7 @@ impl From for String { Active => "active", Activating => "activating", Pause => "pause", - Decomissioned => "decomissioned", + Decommissioned => "decommissioned", } .to_string() } diff --git a/storage_controller/migrations/2026-03-08-000001_fix_decommissioned_typo/down.sql b/storage_controller/migrations/2026-03-08-000001_fix_decommissioned_typo/down.sql new file mode 100644 index 000000000000..44fdc838407b --- /dev/null +++ b/storage_controller/migrations/2026-03-08-000001_fix_decommissioned_typo/down.sql @@ -0,0 +1 @@ +UPDATE safekeepers SET scheduling_policy = 'decomissioned' WHERE scheduling_policy = 'decommissioned'; diff --git a/storage_controller/migrations/2026-03-08-000001_fix_decommissioned_typo/up.sql b/storage_controller/migrations/2026-03-08-000001_fix_decommissioned_typo/up.sql new file mode 100644 index 000000000000..c4a643ef11f6 --- /dev/null +++ b/storage_controller/migrations/2026-03-08-000001_fix_decommissioned_typo/up.sql @@ -0,0 +1 @@ +UPDATE safekeepers SET scheduling_policy = 'decommissioned' WHERE scheduling_policy = 'decomissioned'; diff --git a/storage_controller/src/heartbeater.rs b/storage_controller/src/heartbeater.rs index fe916aa36aec..0fe1e200b078 100644 --- a/storage_controller/src/heartbeater.rs +++ b/storage_controller/src/heartbeater.rs @@ -326,7 +326,7 @@ impl HeartBeat for HeartbeaterTask { locked.safekeeper_reconcilers.stop_reconciler(node_id); @@ -1192,13 +1192,13 @@ impl Service { .map(|&id| NodeId(id as u64)) .collect::>(); - // Validate that we are not migrating to a decomissioned safekeeper. + // Validate that we are not migrating to a decommissioned safekeeper. for sk in new_safekeepers.iter() { if !cur_sk_set.contains(&sk.get_id()) - && sk.scheduling_policy() == SkSchedulingPolicy::Decomissioned + && sk.scheduling_policy() == SkSchedulingPolicy::Decommissioned { return Err(ApiError::BadRequest(anyhow::anyhow!( - "safekeeper {} is decomissioned", + "safekeeper {} is decommissioned", sk.get_id() ))); } diff --git a/test_runner/regress/test_safekeeper_migration.py b/test_runner/regress/test_safekeeper_migration.py index ba067b97de6a..7113ff29270a 100644 --- a/test_runner/regress/test_safekeeper_migration.py +++ b/test_runner/regress/test_safekeeper_migration.py @@ -118,9 +118,9 @@ def expect_fail(sk_set: list[int], match: str): assert len(sk_set) == 2 decom_sk = [sk.id for sk in env.safekeepers if sk.id not in sk_set][0] - env.storage_controller.safekeeper_scheduling_policy(decom_sk, "Decomissioned") + env.storage_controller.safekeeper_scheduling_policy(decom_sk, "Decommissioned") - expect_fail([sk_set[0], decom_sk], "decomissioned") + expect_fail([sk_set[0], decom_sk], "decommissioned") def test_safekeeper_migration_common_set_failpoints(neon_env_builder: NeonEnvBuilder): diff --git a/test_runner/regress/test_storage_controller.py b/test_runner/regress/test_storage_controller.py index e11be1df8c7c..3a6f977a33a6 100644 --- a/test_runner/regress/test_storage_controller.py +++ b/test_runner/regress/test_storage_controller.py @@ -3752,8 +3752,8 @@ def storcon_heartbeat(): wait_until(storcon_heartbeat) - # Now decomission it - target.safekeeper_scheduling_policy(inserted["id"], "Decomissioned") + # Now decommission it + target.safekeeper_scheduling_policy(inserted["id"], "Decommissioned") @run_only_on_default_postgres("this is like a 'unit test' against storcon db") @@ -3803,8 +3803,8 @@ def safekeeper_is_active(): wait_until(safekeeper_is_active) - # Now decomission it - target.safekeeper_scheduling_policy(inserted["id"], "Decomissioned") + # Now decommission it + target.safekeeper_scheduling_policy(inserted["id"], "Decommissioned") def eq_safekeeper_records(a: dict[str, Any], b: dict[str, Any]) -> bool: