-
Notifications
You must be signed in to change notification settings - Fork 93
[reconfigurator] background task for marking VMMs to be stopped for update #11170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
bd86820
61c1251
6e317a8
10ce875
87864be
f9d662c
80be57a
5796d5f
0e9d65a
4598157
53139af
aa0c46b
84e868e
effee09
ac7cbd3
fc8c765
4e3f9b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -94,6 +94,7 @@ use nexus_types::internal_api::background::TufArtifactReplicationCounters; | |
| use nexus_types::internal_api::background::TufArtifactReplicationRequest; | ||
| use nexus_types::internal_api::background::TufArtifactReplicationStatus; | ||
| use nexus_types::internal_api::background::TufRepoPrunerStatus; | ||
| use nexus_types::internal_api::background::VmmMarkStopForUpdateStatus; | ||
| use nexus_types::internal_api::background::fm_rendezvous; | ||
| use omicron_uuid_kinds::BlueprintUuid; | ||
| use omicron_uuid_kinds::CollectionUuid; | ||
|
|
@@ -1426,6 +1427,9 @@ fn print_task_details(bgtask: &BackgroundTask, details: &serde_json::Value) { | |
| "switch_port_config_manager" => { | ||
| print_task_switch_port_settings_manager(details); | ||
| } | ||
| "vmm_mark_stop_for_update" => { | ||
| print_task_vmm_mark_stop_for_update(details); | ||
| } | ||
| _ => { | ||
| println!( | ||
| "warning: unknown background task: {:?} \ | ||
|
|
@@ -2842,6 +2846,33 @@ fn print_task_audit_log_cleanup(details: &serde_json::Value) { | |
| }; | ||
| } | ||
|
|
||
| fn print_task_vmm_mark_stop_for_update(details: &serde_json::Value) { | ||
| match serde_json::from_value::<VmmMarkStopForUpdateStatus>(details.clone()) | ||
| { | ||
| Err(error) => eprintln!( | ||
| "warning: failed to interpret task details: {:?}: {:?}", | ||
| error, details | ||
| ), | ||
| Ok(status) => { | ||
| let VmmMarkStopForUpdateStatus { disabled, vmms_marked, error } = | ||
| status; | ||
|
|
||
| if disabled { | ||
| println!(" task explicitly disabled by config!"); | ||
| } | ||
|
|
||
| const MARKED: &str = "VMMs marked:"; | ||
| const ERROR: &str = "error:"; | ||
| const WIDTH: usize = const_max_len(&[MARKED, ERROR]) + 1; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. every time I see someone use my silly little |
||
|
|
||
| println!(" {MARKED:<WIDTH$}{}", vmms_marked); | ||
| if let Some(error) = &error { | ||
| println!(" {ERROR:<WIDTH$}{error}"); | ||
| } | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| fn print_task_audit_log_timeout_incomplete(details: &serde_json::Value) { | ||
| match serde_json::from_value::<AuditLogTimeoutIncompleteStatus>( | ||
| details.clone(), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -477,6 +477,8 @@ pub struct BackgroundTaskConfig { | |
| pub audit_log_cleanup: AuditLogCleanupConfig, | ||
| /// configuration for populate switch ports task | ||
| pub populate_switch_ports: PopulateSwitchPortsConfig, | ||
| /// configuration for the task that marks VMMs to stop for an update | ||
| pub vmm_mark_stop_for_update: VmmMarkStopForUpdateConfig, | ||
| } | ||
|
|
||
| #[serde_as] | ||
|
|
@@ -523,6 +525,23 @@ pub struct AuditLogCleanupConfig { | |
| pub max_deleted_per_activation: u32, | ||
| } | ||
|
|
||
| #[serde_as] | ||
| #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] | ||
| pub struct VmmMarkStopForUpdateConfig { | ||
| /// period (in seconds) for periodic activations of this task | ||
| #[serde_as(as = "DurationSeconds<u64>")] | ||
| pub period_secs: Duration, | ||
|
|
||
| /// disable marking VMMs to stop for a sled update. | ||
| /// | ||
| /// This is an emergency lever for support / operations. It should only be | ||
| /// necessary if something has gone extremely wrong. | ||
|
Comment on lines
+537
to
+538
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the nexus config is really something support / operations can control - it's not persistent if the sled (or Nexus zone) restarts, and requires manually bouncing the service within the zone for it to take effect. If we need an emergency stop for support, I think we need a config in crdb that can be toggled via omdb, like the controls we have on the blueprint planner? If having an easy way to enable/disable this task between releases is all we need, then putting it here is great.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I would put this in the DB config in this case, given the comment that it's an emergency disable switch.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup! I was planning to implement the omdb commands in a follow up PR. It's the penultimate item in #11169. The comment on there is basically the same one from other configs, was just following the pattern there.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Hmm if we're going to do omdb commands to control this, then we don't need a flag here right?
Which configs are those? AFAIK a flag at this level should really only be for "this is still in development so disabled by default" kinds of things. |
||
| /// | ||
| /// Default: Off | ||
| #[serde(default)] | ||
| pub disable: bool, | ||
| } | ||
|
|
||
| #[serde_as] | ||
| #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] | ||
| pub struct PopulateSwitchPortsConfig { | ||
|
|
@@ -1376,6 +1395,7 @@ mod test { | |
| audit_log_cleanup.retention_days = 90 | ||
| audit_log_cleanup.max_deleted_per_activation = 10000 | ||
| populate_switch_ports.period_secs = 31 | ||
| vmm_mark_stop_for_update.period_secs = 300 | ||
| [default_region_allocation_strategy] | ||
| type = "random" | ||
| seed = 0 | ||
|
|
@@ -1656,6 +1676,10 @@ mod test { | |
| populate_switch_ports: PopulateSwitchPortsConfig { | ||
| period_secs: Duration::from_secs(31), | ||
| }, | ||
| vmm_mark_stop_for_update: VmmMarkStopForUpdateConfig { | ||
| period_secs: Duration::from_secs(300), | ||
| disable: false, | ||
| }, | ||
| }, | ||
| multicast: MulticastConfig { enabled: false }, | ||
| default_region_allocation_strategy: | ||
|
|
@@ -1772,6 +1796,7 @@ mod test { | |
| audit_log_cleanup.retention_days = 90 | ||
| audit_log_cleanup.max_deleted_per_activation = 10000 | ||
| populate_switch_ports.period_secs = 31 | ||
| vmm_mark_stop_for_update.period_secs = 300 | ||
|
|
||
| [default_region_allocation_strategy] | ||
| type = "random" | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -106,6 +106,31 @@ impl VmmState { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn exists_on_sled(&self) -> bool { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.to_nexus_state().exists_on_sled() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Returns the states from which a VMM can still be stopped during sled | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// evacuation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn stoppable_states() -> Vec<Self> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Self::ALL_STATES | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .iter() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .copied() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .filter(|state| match state { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // A VMM in one of these states is on its way, or is already | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // running, and can be stopped. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VmmState::Creating | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | VmmState::Starting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | VmmState::Running | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | VmmState::Rebooting => true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // A VMM in one of these states is already stopping/stopped, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // migrating, or terminal, so there is nothing to stop. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VmmState::Stopping | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | VmmState::Stopped | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | VmmState::Migrating | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | VmmState::Failed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | VmmState::Destroyed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | VmmState::SagaUnwound => false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .collect() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+110
to
+132
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like that we're explicitly declaring the list of states in which it's okay to stop a VMM for update. However, I do have some notes:
So, in sum, I would probably change this to something more like:
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, hmm. After re-reading @jgallagher's comment in #11170 (comment), I see that he explicitly mentions using a
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe another option - should we move the // ... long comment explaining what to do if you get here due to adding a new state ...
for state in VmmState::iter() {
match state {
VmmState::Creating | /* .. explicit list ... */ => {
assert!(VmmState::THE_STATES.contains(state));
}
VmmState::Failed | /* ... explicit list ... */ => {
assert!(!VmmState::THE_STATES.contains(state));
}
}
}
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, I'm fine with that approach too, as long as we structure the test in such a way that the failure occurs at compile-time --- which, if you're writing out the explicit list of states in a match, it will.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (this conversation is making me want to go back and revisit some of the other places where I've written code with a list of enum variants in a |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| impl fmt::Display for VmmState { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unless the whole status object is being printed under a heading that says what it's doing, i might expand this so that it's clear to the reader what we are marking them for...