@@ -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 ;
@@ -19,19 +20,29 @@ use ostree::gio;
19
20
use ostree_container:: store:: PrepareResult ;
20
21
use ostree_ext:: composefs:: fsverity:: { self , FsVerityHashValue } ;
21
22
use ostree_ext:: container as ostree_container;
22
- use ostree_ext:: container_utils:: ostree_booted;
23
+ use ostree_ext:: container_utils:: { composefs_booted , ostree_booted} ;
23
24
use ostree_ext:: keyfileext:: KeyFileExt ;
24
25
use ostree_ext:: ostree;
25
26
use schemars:: schema_for;
26
27
use serde:: { Deserialize , Serialize } ;
27
28
28
29
use crate :: deploy:: RequiredHostSpec ;
30
+ use crate :: install:: {
31
+ open_composefs_repo, setup_composefs_bls_boot, setup_composefs_uki_boot, write_composefs_state,
32
+ BootType , BootSetupType ,
33
+ } ;
29
34
use crate :: lints;
30
35
use crate :: progress_jsonl:: { ProgressWriter , RawProgressFd } ;
31
36
use crate :: spec:: Host ;
32
37
use crate :: spec:: ImageReference ;
38
+ use crate :: status:: composefs_deployment_status;
33
39
use crate :: utils:: sigpolicy_from_opt;
34
40
41
+ use ostree_ext:: composefs_boot:: BootOps ;
42
+ use ostree_ext:: composefs_oci:: {
43
+ image:: create_filesystem as create_composefs_filesystem, pull as composefs_oci_pull,
44
+ } ;
45
+
35
46
/// Shared progress options
36
47
#[ derive( Debug , Parser , PartialEq , Eq ) ]
37
48
pub ( crate ) struct ProgressOptions {
@@ -747,6 +758,74 @@ fn prepare_for_write() -> Result<()> {
747
758
Ok ( ( ) )
748
759
}
749
760
761
+ #[ context( "Upgrading composefs" ) ]
762
+ async fn upgrade_composefs ( _opts : UpgradeOpts ) -> Result < ( ) > {
763
+ // TODO: IMPORTANT Have all the checks here that `bootc upgrade` has for an ostree booted system
764
+
765
+ let host = composefs_deployment_status ( )
766
+ . await
767
+ . context ( "Getting composefs deployment status" ) ?;
768
+
769
+ // TODO: IMPORTANT We need to check if any deployment is staged and get the image from that
770
+ let imgref = host
771
+ . spec
772
+ . image
773
+ . as_ref ( )
774
+ . ok_or_else ( || anyhow:: anyhow!( "No image source specified" ) ) ?;
775
+
776
+ let booted_image = host
777
+ . status
778
+ . booted
779
+ . ok_or ( anyhow:: anyhow!( "Could not find booted image" ) ) ?
780
+ . image
781
+ . ok_or ( anyhow:: anyhow!( "Could not find booted image" ) ) ?;
782
+
783
+ tracing:: debug!( "booted_image: {booted_image:#?}" ) ;
784
+ tracing:: debug!( "imgref: {imgref:#?}" ) ;
785
+
786
+ let digest = booted_image
787
+ . digest ( )
788
+ . context ( "Getting digest for booted image" ) ?;
789
+
790
+ let rootfs_dir = cap_std:: fs:: Dir :: open_ambient_dir ( "/sysroot" , cap_std:: ambient_authority ( ) ) ?;
791
+
792
+ let repo = open_composefs_repo ( & rootfs_dir) . context ( "Opening compoesfs repo" ) ?;
793
+
794
+ let ( id, verity) = composefs_oci_pull (
795
+ & Arc :: new ( repo) ,
796
+ & format ! ( "{}:{}" , imgref. transport, imgref. image) ,
797
+ None ,
798
+ )
799
+ . await
800
+ . context ( "Pulling composefs repo" ) ?;
801
+
802
+ tracing:: debug!(
803
+ "id = {id}, verity = {verity}" ,
804
+ id = hex:: encode( id) ,
805
+ verity = verity. to_hex( )
806
+ ) ;
807
+
808
+ let repo = open_composefs_repo ( & rootfs_dir) ?;
809
+ let mut fs = create_composefs_filesystem ( & repo, digest. digest ( ) , None )
810
+ . context ( "Failed to create composefs filesystem" ) ?;
811
+
812
+ let entries = fs. transform_for_boot ( & repo) ?;
813
+ let id = fs. commit_image ( & repo, None ) ?;
814
+
815
+ let Some ( entry) = entries. into_iter ( ) . next ( ) else {
816
+ anyhow:: bail!( "No boot entries!" ) ;
817
+ } ;
818
+
819
+ match BootType :: from ( & entry) {
820
+ BootType :: Bls => setup_composefs_bls_boot ( BootSetupType :: Upgrade , repo, & id, entry) ,
821
+ BootType :: Uki => setup_composefs_uki_boot ( BootSetupType :: Upgrade , repo, & id, entry) ,
822
+ } ?;
823
+
824
+ write_composefs_state ( & Utf8PathBuf :: from ( "/sysroot" ) , id, imgref) ?;
825
+
826
+ Ok ( ( ) )
827
+ }
828
+
750
829
/// Implementation of the `bootc upgrade` CLI command.
751
830
#[ context( "Upgrading" ) ]
752
831
async fn upgrade ( opts : UpgradeOpts ) -> Result < ( ) > {
@@ -1084,7 +1163,13 @@ impl Opt {
1084
1163
async fn run_from_opt ( opt : Opt ) -> Result < ( ) > {
1085
1164
let root = & Dir :: open_ambient_dir ( "/" , cap_std:: ambient_authority ( ) ) ?;
1086
1165
match opt {
1087
- Opt :: Upgrade ( opts) => upgrade ( opts) . await ,
1166
+ Opt :: Upgrade ( opts) => {
1167
+ if composefs_booted ( ) ? {
1168
+ upgrade_composefs ( opts) . await
1169
+ } else {
1170
+ upgrade ( opts) . await
1171
+ }
1172
+ }
1088
1173
Opt :: Switch ( opts) => switch ( opts) . await ,
1089
1174
Opt :: Rollback ( opts) => rollback ( opts) . await ,
1090
1175
Opt :: Edit ( opts) => edit ( opts) . await ,
0 commit comments