@@ -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, reboot} ;
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
@@ -835,6 +835,31 @@ async fn upgrade(opts: UpgradeOpts) -> Result<()> {
835
835
println ! ( "Staged update present, not changed." ) ;
836
836
837
837
if opts. apply {
838
+ // Check if we can do a soft-reboot instead of a full reboot
839
+ let can_soft_reboot = host
840
+ . status
841
+ . staged
842
+ . as_ref ( )
843
+ . map ( |s| s. soft_reboot_capable )
844
+ . unwrap_or ( false ) ;
845
+
846
+ if can_soft_reboot {
847
+ println ! ( "Staged deployment is soft-reboot capable, performing soft-reboot..." ) ;
848
+
849
+ // Find the staged deployment
850
+ let deployments_list = sysroot. deployments ( ) ;
851
+ let staged_deployment = deployments_list
852
+ . iter ( )
853
+ . find ( |d| d. is_staged ( ) )
854
+ . ok_or_else ( || anyhow:: anyhow!( "Failed to find staged deployment" ) ) ?;
855
+
856
+ // Prepare the soft-reboot using native ostree bindings
857
+ let cancellable = ostree:: gio:: Cancellable :: NONE ;
858
+ sysroot
859
+ . sysroot
860
+ . deployment_prepare_next_root ( staged_deployment, false , cancellable)
861
+ . context ( "Failed to prepare soft-reboot" ) ?;
862
+ }
838
863
crate :: reboot:: reboot ( ) ?;
839
864
}
840
865
} else if booted_unchanged {
@@ -931,6 +956,33 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
931
956
sysroot. update_mtime ( ) ?;
932
957
933
958
if opts. apply {
959
+ // Get updated status to check for soft-reboot capability
960
+ let ( _updated_deployments, updated_host) =
961
+ crate :: status:: get_status ( sysroot, Some ( & booted_deployment) ) ?;
962
+ let can_soft_reboot = updated_host
963
+ . status
964
+ . 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 staged deployment
973
+ let deployments_list = sysroot. deployments ( ) ;
974
+ let staged_deployment = deployments_list
975
+ . iter ( )
976
+ . find ( |d| d. is_staged ( ) )
977
+ . ok_or_else ( || anyhow:: anyhow!( "Failed to find staged deployment" ) ) ?;
978
+
979
+ // Prepare the soft-reboot using native ostree bindings
980
+ let cancellable = ostree:: gio:: Cancellable :: NONE ;
981
+ sysroot
982
+ . sysroot
983
+ . deployment_prepare_next_root ( staged_deployment, false , cancellable)
984
+ . context ( "Failed to prepare soft-reboot" ) ?;
985
+ }
934
986
crate :: reboot:: reboot ( ) ?;
935
987
}
936
988
@@ -941,10 +993,40 @@ async fn switch(opts: SwitchOpts) -> Result<()> {
941
993
#[ context( "Rollback" ) ]
942
994
async fn rollback ( opts : RollbackOpts ) -> Result < ( ) > {
943
995
let sysroot = & get_storage ( ) . await ?;
944
- crate :: deploy:: rollback ( sysroot) . await ?;
945
996
946
997
if opts. apply {
998
+ // Get status before rollback to check soft-reboot capability
999
+ let ( _booted_deployment, _deployments, host) =
1000
+ crate :: status:: get_status_require_booted ( sysroot) ?;
1001
+ let can_soft_reboot = host
1002
+ . status
1003
+ . rollback
1004
+ . as_ref ( )
1005
+ . map ( |r| r. soft_reboot_capable )
1006
+ . unwrap_or ( false ) ;
1007
+
1008
+ // Perform the rollback
1009
+ crate :: deploy:: rollback ( sysroot) . await ?;
1010
+
1011
+ if can_soft_reboot {
1012
+ println ! ( "Rollback deployment is soft-reboot capable, performing soft-reboot..." ) ;
1013
+
1014
+ // For rollback, get the current first deployment after rollback
1015
+ let deployments_list = sysroot. deployments ( ) ;
1016
+ let target_deployment = deployments_list
1017
+ . first ( )
1018
+ . ok_or_else ( || anyhow:: anyhow!( "No deployments found after rollback" ) ) ?;
1019
+
1020
+ // Prepare the soft-reboot using native ostree bindings
1021
+ let cancellable = ostree:: gio:: Cancellable :: NONE ;
1022
+ sysroot
1023
+ . sysroot
1024
+ . deployment_prepare_next_root ( target_deployment, false , cancellable)
1025
+ . context ( "Failed to prepare soft-reboot" ) ?;
1026
+ }
947
1027
crate :: reboot:: reboot ( ) ?;
1028
+ } else {
1029
+ crate :: deploy:: rollback ( sysroot) . await ?;
948
1030
}
949
1031
950
1032
Ok ( ( ) )
0 commit comments