From ab8e75c93d829e17e2d3eef54160252e54a0851c Mon Sep 17 00:00:00 2001 From: Ayana Yaegashi Date: Mon, 8 Dec 2025 21:55:30 +0000 Subject: [PATCH 1/4] add runtime flag --- crates/trident/src/cli.rs | 5 +++++ crates/trident/src/engine/update.rs | 6 ++++++ crates/trident/src/lib.rs | 7 ++++--- crates/trident/src/main.rs | 2 ++ crates/trident_api/src/error.rs | 7 +++++++ docs/Reference/Trident-CLI.md | 8 ++++++++ 6 files changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/trident/src/cli.rs b/crates/trident/src/cli.rs index 1bbbe4c88..7e8dbda7d 100644 --- a/crates/trident/src/cli.rs +++ b/crates/trident/src/cli.rs @@ -74,6 +74,11 @@ pub enum Commands { #[clap(long, value_delimiter = ',', num_args = 0.., default_value = "stage,finalize")] allowed_operations: Vec, + /// Boolean indicating that a runtime update is expected and an A/B + /// update should result in a fatal error + #[clap(long)] + runtime: bool, + /// Path to save the resulting Host Status #[clap(short, long)] status: Option, diff --git a/crates/trident/src/engine/update.rs b/crates/trident/src/engine/update.rs index 9b29dc462..182b81a23 100644 --- a/crates/trident/src/engine/update.rs +++ b/crates/trident/src/engine/update.rs @@ -24,6 +24,7 @@ pub(crate) fn update( host_config: &HostConfiguration, state: &mut DataStore, allowed_operations: &Operations, + expect_runtime: bool, image: OsImage, #[cfg(feature = "grpc-dangerous")] sender: &mut Option, ) -> Result { @@ -86,6 +87,11 @@ pub(crate) fn update( } ServicingType::RuntimeUpdate => {} ServicingType::AbUpdate => { + if expect_runtime { + return Err(TridentError::new( + InvalidInputError::AbUpdateRuntimeFlagMismatch, + )); + } // Execute pre-servicing scripts HooksSubsystem::new_for_local_scripts().execute_pre_servicing_scripts(&ctx)?; } diff --git a/crates/trident/src/lib.rs b/crates/trident/src/lib.rs index 5c9f2e0aa..f6c8c9209 100644 --- a/crates/trident/src/lib.rs +++ b/crates/trident/src/lib.rs @@ -262,7 +262,7 @@ impl Trident { if let Some((host_config, allowed_operations, sender)) = receiver.blocking_recv() { self.host_config = Some(host_config); if let ExitKind::NeedsReboot = - self.update(datastore, allowed_operations, &mut Some(sender))? + self.update(datastore, allowed_operations, false, &mut Some(sender))? { reboot().message("Failed to reboot after grpc update")?; } @@ -549,6 +549,7 @@ impl Trident { &mut self, datastore: &mut DataStore, allowed_operations: Operations, + runtime: bool, #[cfg(feature = "grpc-dangerous")] sender: &mut Option, ) -> Result { let mut host_config = self @@ -585,7 +586,7 @@ impl Trident { debug!("Host Configuration has been updated"); // If allowed operations include 'stage', start update if allowed_operations.has_stage() { - engine::update(&host_config, datastore, &allowed_operations, image, #[cfg(feature = "grpc-dangerous")] sender).message("Failed to execute an update") + engine::update(&host_config, datastore, &allowed_operations, runtime, image, #[cfg(feature = "grpc-dangerous")] sender).message("Failed to execute an update") } else { warn!("Host Configuration has been updated but allowed operations do not include 'stage'. Add 'stage' and re-run to stage the update"); Ok(ExitKind::Done) @@ -631,7 +632,7 @@ impl Trident { ServicingState::AbUpdateFinalized | ServicingState::Provisioned => { // Need to either re-execute the failed update OR inform the user that no update // is needed. - engine::update(&host_config, datastore, &allowed_operations, image, #[cfg(feature = "grpc-dangerous")] sender).message("Failed to update host") + engine::update(&host_config, datastore, &allowed_operations, runtime, image, #[cfg(feature = "grpc-dangerous")] sender).message("Failed to update host") } servicing_state => { Err(TridentError::new(InternalError::UnexpectedServicingState { diff --git a/crates/trident/src/main.rs b/crates/trident/src/main.rs index 5477f350f..977ec4ce7 100644 --- a/crates/trident/src/main.rs +++ b/crates/trident/src/main.rs @@ -196,10 +196,12 @@ fn run_trident( ), Commands::Update { ref allowed_operations, + runtime, .. } => trident.update( &mut datastore, cli::to_operations(allowed_operations), + runtime, #[cfg(feature = "grpc-dangerous")] &mut None, ), diff --git a/crates/trident_api/src/error.rs b/crates/trident_api/src/error.rs index 551d4ccb0..133545614 100644 --- a/crates/trident_api/src/error.rs +++ b/crates/trident_api/src/error.rs @@ -141,6 +141,13 @@ pub enum InternalError { #[derive(Debug, Eq, thiserror::Error, Serialize, Deserialize, PartialEq)] #[serde(rename_all = "kebab-case")] pub enum InvalidInputError { + #[error( + "Determined that an A/B update is required, but Trident was run with --runtime flag \ + indicating runtime update was expected. Edit Host Configuration or re-run without the \ + --runtime flag." + )] + AbUpdateRuntimeFlagMismatch, + #[error("Allowed operations must be passed via command line, not in Host Configuration")] AllowedOperationsInHostConfiguration, diff --git a/docs/Reference/Trident-CLI.md b/docs/Reference/Trident-CLI.md index 0d130eda4..01289a254 100644 --- a/docs/Reference/Trident-CLI.md +++ b/docs/Reference/Trident-CLI.md @@ -155,6 +155,9 @@ Options: -v, --verbosity Logging verbosity [OFF, ERROR, WARN, INFO, DEBUG, TRACE] [default: DEBUG] + --runtime + Boolean indicating that a runtime update is expected and an + A/B update should result in a fatal error -s, --status Path to save the resulting Host Status -e, --error @@ -183,6 +186,11 @@ Possible values: Default: `stage,finalize` +#### --runtime <RUNTIME> + +Boolean indicating that a runtime update is expected and an A/B update should result in a fatal error + + #### --status <STATUS> Path to save the resulting Host Status From 701d53e570265b91d5066665632ba13878da62af Mon Sep 17 00:00:00 2001 From: Ayana Yaegashi Date: Tue, 9 Dec 2025 20:04:50 +0000 Subject: [PATCH 2/4] edit error message --- crates/trident_api/src/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/trident_api/src/error.rs b/crates/trident_api/src/error.rs index 133545614..6f29097fb 100644 --- a/crates/trident_api/src/error.rs +++ b/crates/trident_api/src/error.rs @@ -143,8 +143,8 @@ pub enum InternalError { pub enum InvalidInputError { #[error( "Determined that an A/B update is required, but Trident was run with --runtime flag \ - indicating runtime update was expected. Edit Host Configuration or re-run without the \ - --runtime flag." + indicating runtime update was expected. Returning fatal error to avoid unexpected reboot. \ + Edit Host Configuration or re-run without the --runtime flag." )] AbUpdateRuntimeFlagMismatch, From 5777a9177407c49784b303486babc28efefc36f8 Mon Sep 17 00:00:00 2001 From: Ayana Yaegashi Date: Tue, 9 Dec 2025 21:09:24 +0000 Subject: [PATCH 3/4] update cli docs --- crates/trident/src/cli.rs | 5 +++-- docs/Reference/Trident-CLI.md | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/trident/src/cli.rs b/crates/trident/src/cli.rs index 7e8dbda7d..bb71eb5bb 100644 --- a/crates/trident/src/cli.rs +++ b/crates/trident/src/cli.rs @@ -74,8 +74,9 @@ pub enum Commands { #[clap(long, value_delimiter = ',', num_args = 0.., default_value = "stage,finalize")] allowed_operations: Vec, - /// Boolean indicating that a runtime update is expected and an A/B - /// update should result in a fatal error + /// Boolean indicating that a runtime update is expected. If Trident + /// determines that an A/B update is required, it will issue a fatal + /// error to avoid an unexpected reboot #[clap(long)] runtime: bool, diff --git a/docs/Reference/Trident-CLI.md b/docs/Reference/Trident-CLI.md index 01289a254..5c0a6347e 100644 --- a/docs/Reference/Trident-CLI.md +++ b/docs/Reference/Trident-CLI.md @@ -156,8 +156,9 @@ Options: Logging verbosity [OFF, ERROR, WARN, INFO, DEBUG, TRACE] [default: DEBUG] --runtime - Boolean indicating that a runtime update is expected and an - A/B update should result in a fatal error + Boolean indicating that a runtime update is expected. If + Trident determines that an A/B update is required, it will + issue a fatal error to avoid an unexpected reboot -s, --status Path to save the resulting Host Status -e, --error @@ -188,7 +189,7 @@ Default: `stage,finalize` #### --runtime <RUNTIME> -Boolean indicating that a runtime update is expected and an A/B update should result in a fatal error +Boolean indicating that a runtime update is expected. If Trident determines that an A/B update is required, it will issue a fatal error to avoid an unexpected reboot #### --status <STATUS> From bdf5656ca91275306cf927d16fe709f18b8c5a48 Mon Sep 17 00:00:00 2001 From: Ayana Yaegashi Date: Tue, 9 Dec 2025 21:10:38 +0000 Subject: [PATCH 4/4] call to update should have same error message --- crates/trident/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/trident/src/lib.rs b/crates/trident/src/lib.rs index f6c8c9209..53df6483f 100644 --- a/crates/trident/src/lib.rs +++ b/crates/trident/src/lib.rs @@ -632,7 +632,7 @@ impl Trident { ServicingState::AbUpdateFinalized | ServicingState::Provisioned => { // Need to either re-execute the failed update OR inform the user that no update // is needed. - engine::update(&host_config, datastore, &allowed_operations, runtime, image, #[cfg(feature = "grpc-dangerous")] sender).message("Failed to update host") + engine::update(&host_config, datastore, &allowed_operations, runtime, image, #[cfg(feature = "grpc-dangerous")] sender).message("Failed to execute an update") } servicing_state => { Err(TridentError::new(InternalError::UnexpectedServicingState {