@@ -26,7 +26,7 @@ use schemars::schema_for;
2626use serde:: { Deserialize , Serialize } ;
2727
2828use crate :: deploy:: RequiredHostSpec ;
29- use crate :: lints;
29+ use crate :: { lints, reboot } ;
3030use crate :: progress_jsonl:: { ProgressWriter , RawProgressFd } ;
3131use crate :: spec:: Host ;
3232use crate :: spec:: ImageReference ;
@@ -536,7 +536,7 @@ pub(crate) enum Opt {
536536 Note on Rollbacks and the `/etc` Directory:
537537
538538 When you perform a rollback (e.g., with `bootc rollback`), any
539- changes made to files in the `/etc` directory won’ t carry over
539+ changes made to files in the `/etc` directory won' t carry over
540540 to the rolled-back deployment. The `/etc` files will revert
541541 to their state from that previous deployment instead.
542542
@@ -835,7 +835,35 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> {
835835 println ! ( "Staged update present, not changed." ) ;
836836
837837 if opts. apply {
838- crate :: reboot:: reboot ( ) ?;
838+ // Check if we can do a soft-reboot instead of a full reboot
839+ let can_soft_reboot = host. status . staged
840+ . as_ref ( )
841+ . map ( |s| s. soft_reboot_capable )
842+ . unwrap_or ( false ) ;
843+
844+ if can_soft_reboot {
845+ println ! ( "Staged deployment is soft-reboot capable, performing soft-reboot..." ) ;
846+
847+ // Find the index of the staged deployment
848+ let deployments_list = sysroot. deployments ( ) ;
849+ let staged_index = deployments_list
850+ . iter ( )
851+ . position ( |d| d. is_staged ( ) )
852+ . ok_or_else ( || anyhow:: anyhow!( "Failed to find staged deployment index" ) ) ?;
853+
854+ // Prepare the soft-reboot using ostree admin prepare-soft-reboot
855+ let mut cmd = std:: process:: Command :: new ( "ostree" ) ;
856+ cmd. args ( [ "admin" , "prepare-soft-reboot" , & staged_index. to_string ( ) ] ) ;
857+ let status = cmd. status ( ) . context ( "Failed to run ostree admin prepare-soft-reboot" ) ?;
858+ if !status. success ( ) {
859+ anyhow:: bail!( "ostree admin prepare-soft-reboot failed" ) ;
860+ }
861+
862+ // Perform the soft-reboot
863+ crate :: reboot:: soft_reboot ( ) ?;
864+ } else {
865+ crate :: reboot:: reboot ( ) ?;
866+ }
839867 }
840868 } else if booted_unchanged {
841869 println ! ( "No update available." )
@@ -931,7 +959,36 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
931959 sysroot. update_mtime ( ) ?;
932960
933961 if opts. apply {
934- crate :: reboot:: reboot ( ) ?;
962+ // Get updated status to check for soft-reboot capability
963+ let ( _updated_deployments, updated_host) = crate :: status:: get_status ( sysroot, Some ( & booted_deployment) ) ?;
964+ let can_soft_reboot = updated_host. status . staged
965+ . as_ref ( )
966+ . map ( |s| s. soft_reboot_capable )
967+ . unwrap_or ( false ) ;
968+
969+ if can_soft_reboot {
970+ println ! ( "Staged deployment is soft-reboot capable, performing soft-reboot..." ) ;
971+
972+ // Find the index of the staged deployment
973+ let deployments_list = sysroot. deployments ( ) ;
974+ let staged_index = deployments_list
975+ . iter ( )
976+ . position ( |d| d. is_staged ( ) )
977+ . ok_or_else ( || anyhow:: anyhow!( "Failed to find staged deployment index" ) ) ?;
978+
979+ // Prepare the soft-reboot using ostree admin prepare-soft-reboot
980+ let mut cmd = std:: process:: Command :: new ( "ostree" ) ;
981+ cmd. args ( [ "admin" , "prepare-soft-reboot" , & staged_index. to_string ( ) ] ) ;
982+ let status = cmd. status ( ) . context ( "Failed to run ostree admin prepare-soft-reboot" ) ?;
983+ if !status. success ( ) {
984+ anyhow:: bail!( "ostree admin prepare-soft-reboot failed" ) ;
985+ }
986+
987+ // Perform the soft-reboot
988+ crate :: reboot:: soft_reboot ( ) ?;
989+ } else {
990+ crate :: reboot:: reboot ( ) ?;
991+ }
935992 }
936993
937994 Ok ( ( ) )
@@ -941,10 +998,39 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
941998#[ context( "Rollback" ) ]
942999async fn rollback ( opts : RollbackOpts ) -> Result < ( ) > {
9431000 let sysroot = & get_storage ( ) . await ?;
944- crate :: deploy:: rollback ( sysroot) . await ?;
945-
1001+
9461002 if opts. apply {
947- crate :: reboot:: reboot ( ) ?;
1003+ // Get status before rollback to check soft-reboot capability
1004+ let ( _booted_deployment, _deployments, host) = crate :: status:: get_status_require_booted ( sysroot) ?;
1005+ let can_soft_reboot = host. status . rollback
1006+ . as_ref ( )
1007+ . map ( |r| r. soft_reboot_capable )
1008+ . unwrap_or ( false ) ;
1009+
1010+ // Perform the rollback
1011+ crate :: deploy:: rollback ( sysroot) . await ?;
1012+
1013+ if can_soft_reboot {
1014+ println ! ( "Rollback deployment is soft-reboot capable, performing soft-reboot..." ) ;
1015+
1016+ // For rollback, the target deployment is at index 0 after the rollback operation
1017+ let target_index = 0 ;
1018+
1019+ // Prepare the soft-reboot using ostree admin prepare-soft-reboot
1020+ let mut cmd = std:: process:: Command :: new ( "ostree" ) ;
1021+ cmd. args ( [ "admin" , "prepare-soft-reboot" , & target_index. to_string ( ) ] ) ;
1022+ let status = cmd. status ( ) . context ( "Failed to run ostree admin prepare-soft-reboot" ) ?;
1023+ if !status. success ( ) {
1024+ anyhow:: bail!( "ostree admin prepare-soft-reboot failed" ) ;
1025+ }
1026+
1027+ // Perform the soft-reboot
1028+ crate :: reboot:: soft_reboot ( ) ?;
1029+ } else {
1030+ crate :: reboot:: reboot ( ) ?;
1031+ }
1032+ } else {
1033+ crate :: deploy:: rollback ( sysroot) . await ?;
9481034 }
9491035
9501036 Ok ( ( ) )
0 commit comments