@@ -6,6 +6,7 @@ use std::ffi::{CString, OsStr, OsString};
6
6
use std:: io:: Seek ;
7
7
use std:: os:: unix:: process:: CommandExt ;
8
8
use std:: process:: Command ;
9
+ use std:: sync:: Arc ;
9
10
10
11
use anyhow:: { ensure, Context , Result } ;
11
12
use camino:: Utf8PathBuf ;
@@ -20,19 +21,29 @@ use ostree_container::store::PrepareResult;
20
21
use ostree_ext:: composefs:: fsverity;
21
22
use ostree_ext:: composefs:: fsverity:: FsVerityHashValue ;
22
23
use ostree_ext:: container as ostree_container;
23
- use ostree_ext:: container_utils:: ostree_booted;
24
+ use ostree_ext:: container_utils:: { composefs_booted , ostree_booted} ;
24
25
use ostree_ext:: keyfileext:: KeyFileExt ;
25
26
use ostree_ext:: ostree;
26
27
use schemars:: schema_for;
27
28
use serde:: { Deserialize , Serialize } ;
28
29
29
30
use crate :: deploy:: RequiredHostSpec ;
31
+ use crate :: install:: {
32
+ open_composefs_repo, setup_composefs_bls_boot, setup_composefs_uki_boot, write_composefs_state,
33
+ BootType , BootSetupType ,
34
+ } ;
30
35
use crate :: lints;
31
36
use crate :: progress_jsonl:: { ProgressWriter , RawProgressFd } ;
32
37
use crate :: spec:: Host ;
33
38
use crate :: spec:: ImageReference ;
39
+ use crate :: status:: composefs_deployment_status;
34
40
use crate :: utils:: sigpolicy_from_opt;
35
41
42
+ use ostree_ext:: composefs_boot:: BootOps ;
43
+ use ostree_ext:: composefs_oci:: {
44
+ image:: create_filesystem as create_composefs_filesystem, pull as composefs_oci_pull,
45
+ } ;
46
+
36
47
/// Shared progress options
37
48
#[ derive( Debug , Parser , PartialEq , Eq ) ]
38
49
pub ( crate ) struct ProgressOptions {
@@ -757,6 +768,74 @@ fn prepare_for_write() -> Result<()> {
757
768
Ok ( ( ) )
758
769
}
759
770
771
+ #[ context( "Upgrading composefs" ) ]
772
+ async fn upgrade_composefs ( _opts : UpgradeOpts ) -> Result < ( ) > {
773
+ // TODO: IMPORTANT Have all the checks here that `bootc upgrade` has for an ostree booted system
774
+
775
+ let host = composefs_deployment_status ( )
776
+ . await
777
+ . context ( "Getting composefs deployment status" ) ?;
778
+
779
+ // TODO: IMPORTANT We need to check if any deployment is staged and get the image from that
780
+ let imgref = host
781
+ . spec
782
+ . image
783
+ . as_ref ( )
784
+ . ok_or_else ( || anyhow:: anyhow!( "No image source specified" ) ) ?;
785
+
786
+ let booted_image = host
787
+ . status
788
+ . booted
789
+ . ok_or ( anyhow:: anyhow!( "Could not find booted image" ) ) ?
790
+ . image
791
+ . ok_or ( anyhow:: anyhow!( "Could not find booted image" ) ) ?;
792
+
793
+ tracing:: debug!( "booted_image: {booted_image:#?}" ) ;
794
+ tracing:: debug!( "imgref: {imgref:#?}" ) ;
795
+
796
+ let digest = booted_image
797
+ . digest ( )
798
+ . context ( "Getting digest for booted image" ) ?;
799
+
800
+ let rootfs_dir = cap_std:: fs:: Dir :: open_ambient_dir ( "/sysroot" , cap_std:: ambient_authority ( ) ) ?;
801
+
802
+ let repo = open_composefs_repo ( & rootfs_dir) . context ( "Opening compoesfs repo" ) ?;
803
+
804
+ let ( id, verity) = composefs_oci_pull (
805
+ & Arc :: new ( repo) ,
806
+ & format ! ( "{}:{}" , imgref. transport, imgref. image) ,
807
+ None ,
808
+ )
809
+ . await
810
+ . context ( "Pulling composefs repo" ) ?;
811
+
812
+ tracing:: debug!(
813
+ "id = {id}, verity = {verity}" ,
814
+ id = hex:: encode( id) ,
815
+ verity = verity. to_hex( )
816
+ ) ;
817
+
818
+ let repo = open_composefs_repo ( & rootfs_dir) ?;
819
+ let mut fs = create_composefs_filesystem ( & repo, digest. digest ( ) , None )
820
+ . context ( "Failed to create composefs filesystem" ) ?;
821
+
822
+ let entries = fs. transform_for_boot ( & repo) ?;
823
+ let id = fs. commit_image ( & repo, None ) ?;
824
+
825
+ let Some ( entry) = entries. into_iter ( ) . next ( ) else {
826
+ anyhow:: bail!( "No boot entries!" ) ;
827
+ } ;
828
+
829
+ match BootType :: from ( & entry) {
830
+ BootType :: Bls => setup_composefs_bls_boot ( BootSetupType :: Upgrade , repo, & id, entry) ,
831
+ BootType :: Uki => setup_composefs_uki_boot ( BootSetupType :: Upgrade , repo, & id, entry) ,
832
+ } ?;
833
+
834
+ write_composefs_state ( & Utf8PathBuf :: from ( "/sysroot" ) , id, imgref) ?;
835
+
836
+ Ok ( ( ) )
837
+ }
838
+
760
839
/// Implementation of the `bootc upgrade` CLI command.
761
840
#[ context( "Upgrading" ) ]
762
841
async fn upgrade ( opts : UpgradeOpts ) -> Result < ( ) > {
@@ -1096,7 +1175,13 @@ impl Opt {
1096
1175
async fn run_from_opt ( opt : Opt ) -> Result < ( ) > {
1097
1176
let root = & Dir :: open_ambient_dir ( "/" , cap_std:: ambient_authority ( ) ) ?;
1098
1177
match opt {
1099
- Opt :: Upgrade ( opts) => upgrade ( opts) . await ,
1178
+ Opt :: Upgrade ( opts) => {
1179
+ if composefs_booted ( ) ? {
1180
+ upgrade_composefs ( opts) . await
1181
+ } else {
1182
+ upgrade ( opts) . await
1183
+ }
1184
+ }
1100
1185
Opt :: Switch ( opts) => switch ( opts) . await ,
1101
1186
Opt :: Rollback ( opts) => rollback ( opts) . await ,
1102
1187
Opt :: Edit ( opts) => edit ( opts) . await ,
0 commit comments