@@ -26,11 +26,11 @@ use schemars::schema_for;
26
26
use serde:: { Deserialize , Serialize } ;
27
27
28
28
use crate :: deploy:: RequiredHostSpec ;
29
- use crate :: lints;
30
29
use crate :: progress_jsonl:: { ProgressWriter , RawProgressFd } ;
31
30
use crate :: spec:: Host ;
32
31
use crate :: spec:: ImageReference ;
33
32
use crate :: utils:: sigpolicy_from_opt;
33
+ use crate :: lints;
34
34
35
35
/// Shared progress options
36
36
#[ derive( Debug , Parser , PartialEq , Eq ) ]
@@ -536,7 +536,7 @@ pub(crate) enum Opt {
536
536
Note on Rollbacks and the `/etc` Directory:
537
537
538
538
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
540
540
to the rolled-back deployment. The `/etc` files will revert
541
541
to their state from that previous deployment instead.
542
542
@@ -715,6 +715,56 @@ pub(crate) fn require_root(is_container: bool) -> Result<()> {
715
715
Ok ( ( ) )
716
716
}
717
717
718
+ /// Check if a deployment can perform a soft reboot
719
+ fn can_perform_soft_reboot ( deployment : Option < & crate :: spec:: BootEntry > ) -> bool {
720
+ deployment
721
+ . map ( |d| d. soft_reboot_capable )
722
+ . unwrap_or ( false )
723
+ }
724
+
725
+ /// Prepare and execute a soft reboot for the given deployment
726
+ #[ context( "Preparing soft reboot" ) ]
727
+ fn prepare_soft_reboot (
728
+ sysroot : & crate :: store:: Storage ,
729
+ deployment : & ostree:: Deployment ,
730
+ ) -> Result < ( ) > {
731
+ let cancellable = ostree:: gio:: Cancellable :: NONE ;
732
+ sysroot
733
+ . sysroot
734
+ . deployment_prepare_next_root ( deployment, false , cancellable)
735
+ . context ( "Failed to prepare soft-reboot" ) ?;
736
+ Ok ( ( ) )
737
+ }
738
+
739
+ /// Perform a soft reboot for a staged deployment
740
+ #[ context( "Soft reboot staged deployment" ) ]
741
+ fn soft_reboot_staged ( sysroot : & crate :: store:: Storage ) -> Result < ( ) > {
742
+ println ! ( "Staged deployment is soft-reboot capable, performing soft-reboot..." ) ;
743
+
744
+ let deployments_list = sysroot. deployments ( ) ;
745
+ let staged_deployment = deployments_list
746
+ . iter ( )
747
+ . find ( |d| d. is_staged ( ) )
748
+ . ok_or_else ( || anyhow:: anyhow!( "Failed to find staged deployment" ) ) ?;
749
+
750
+ prepare_soft_reboot ( sysroot, staged_deployment) ?;
751
+ Ok ( ( ) )
752
+ }
753
+
754
+ /// Perform a soft reboot for a rollback deployment
755
+ #[ context( "Soft reboot rollback deployment" ) ]
756
+ fn soft_reboot_rollback ( sysroot : & crate :: store:: Storage ) -> Result < ( ) > {
757
+ println ! ( "Rollback deployment is soft-reboot capable, performing soft-reboot..." ) ;
758
+
759
+ let deployments_list = sysroot. deployments ( ) ;
760
+ let target_deployment = deployments_list
761
+ . first ( )
762
+ . ok_or_else ( || anyhow:: anyhow!( "No deployments found after rollback" ) ) ?;
763
+
764
+ prepare_soft_reboot ( sysroot, target_deployment) ?;
765
+ Ok ( ( ) )
766
+ }
767
+
718
768
/// A few process changes that need to be made for writing.
719
769
/// IMPORTANT: This may end up re-executing the current process,
720
770
/// so anything that happens before this should be idempotent.
@@ -835,6 +885,9 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> {
835
885
println ! ( "Staged update present, not changed." ) ;
836
886
837
887
if opts. apply {
888
+ if can_perform_soft_reboot ( host. status . staged . as_ref ( ) ) {
889
+ soft_reboot_staged ( sysroot) ?;
890
+ }
838
891
crate :: reboot:: reboot ( ) ?;
839
892
}
840
893
} else if booted_unchanged {
@@ -931,6 +984,13 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
931
984
sysroot. update_mtime ( ) ?;
932
985
933
986
if opts. apply {
987
+ // Get updated status to check for soft-reboot capability
988
+ let ( _updated_deployments, updated_host) =
989
+ crate :: status:: get_status ( sysroot, Some ( & booted_deployment) ) ?;
990
+
991
+ if can_perform_soft_reboot ( updated_host. status . staged . as_ref ( ) ) {
992
+ soft_reboot_staged ( sysroot) ?;
993
+ }
934
994
crate :: reboot:: reboot ( ) ?;
935
995
}
936
996
@@ -941,10 +1001,22 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
941
1001
#[ context( "Rollback" ) ]
942
1002
async fn rollback ( opts : RollbackOpts ) -> Result < ( ) > {
943
1003
let sysroot = & get_storage ( ) . await ?;
944
- crate :: deploy:: rollback ( sysroot) . await ?;
945
1004
946
1005
if opts. apply {
1006
+ // Get status before rollback to check soft-reboot capability
1007
+ let ( _booted_deployment, _deployments, host) =
1008
+ crate :: status:: get_status_require_booted ( sysroot) ?;
1009
+ let can_soft_reboot = can_perform_soft_reboot ( host. status . rollback . as_ref ( ) ) ;
1010
+
1011
+ // Perform the rollback
1012
+ crate :: deploy:: rollback ( sysroot) . await ?;
1013
+
1014
+ if can_soft_reboot {
1015
+ soft_reboot_rollback ( sysroot) ?;
1016
+ }
947
1017
crate :: reboot:: reboot ( ) ?;
1018
+ } else {
1019
+ crate :: deploy:: rollback ( sysroot) . await ?;
948
1020
}
949
1021
950
1022
Ok ( ( ) )
0 commit comments