@@ -53,6 +53,7 @@ use serde::{Deserialize, Serialize};
5353#[ cfg( feature = "install-to-disk" ) ]
5454use self :: baseline:: InstallBlockDeviceOpts ;
5555use crate :: boundimage:: { BoundImage , ResolvedBoundImage } ;
56+ use crate :: cli:: ProgressOptions ;
5657use crate :: containerenv:: ContainerExecutionInfo ;
5758use crate :: deploy:: { prepare_for_pull, pull_from_prepared, PreparedImportMeta , PreparedPullResult } ;
5859use crate :: lsm;
@@ -242,6 +243,10 @@ pub(crate) struct InstallToDiskOpts {
242243 #[ clap( long) ]
243244 #[ serde( default ) ]
244245 pub ( crate ) via_loopback : bool ,
246+
247+ #[ clap( flatten) ]
248+ #[ serde( flatten) ]
249+ pub ( crate ) progress : ProgressOptions ,
245250}
246251
247252#[ derive( ValueEnum , Debug , Copy , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
@@ -317,6 +322,9 @@ pub(crate) struct InstallToFilesystemOpts {
317322
318323 #[ clap( flatten) ]
319324 pub ( crate ) config_opts : InstallConfigOpts ,
325+
326+ #[ clap( flatten) ]
327+ pub ( crate ) progress : ProgressOptions ,
320328}
321329
322330#[ derive( Debug , Clone , clap:: Parser , PartialEq , Eq ) ]
@@ -348,6 +356,9 @@ pub(crate) struct InstallToExistingRootOpts {
348356 /// via e.g. `-v /:/target`.
349357 #[ clap( default_value = ALONGSIDE_ROOT_MOUNT ) ]
350358 pub ( crate ) root_path : Utf8PathBuf ,
359+
360+ #[ clap( flatten) ]
361+ pub ( crate ) progress : ProgressOptions ,
351362}
352363
353364/// Global state captured from the container.
@@ -755,6 +766,7 @@ async fn install_container(
755766 root_setup : & RootSetup ,
756767 sysroot : & ostree:: Sysroot ,
757768 has_ostree : bool ,
769+ prog : ProgressWriter ,
758770) -> Result < ( ostree:: Deployment , InstallAleph ) > {
759771 let sepolicy = state. load_policy ( ) ?;
760772 let sepolicy = sepolicy. as_ref ( ) ;
@@ -793,15 +805,14 @@ async fn install_container(
793805 let repo = & sysroot. repo ( ) ;
794806 repo. set_disable_fsync ( true ) ;
795807
796- let pulled_image = match prepare_for_pull ( repo, & spec_imgref, Some ( & state. target_imgref ) )
797- . await ?
798- {
799- PreparedPullResult :: AlreadyPresent ( existing) => existing,
800- PreparedPullResult :: Ready ( image_meta) => {
801- check_disk_space ( root_setup. physical_root . as_fd ( ) , & image_meta, & spec_imgref) ?;
802- pull_from_prepared ( & spec_imgref, false , ProgressWriter :: default ( ) , image_meta) . await ?
803- }
804- } ;
808+ let pulled_image =
809+ match prepare_for_pull ( repo, & spec_imgref, Some ( & state. target_imgref ) ) . await ? {
810+ PreparedPullResult :: AlreadyPresent ( existing) => existing,
811+ PreparedPullResult :: Ready ( image_meta) => {
812+ check_disk_space ( root_setup. physical_root . as_fd ( ) , & image_meta, & spec_imgref) ?;
813+ pull_from_prepared ( & spec_imgref, false , prog, image_meta) . await ?
814+ }
815+ } ;
805816
806817 repo. set_disable_fsync ( false ) ;
807818
@@ -1174,6 +1185,7 @@ async fn prepare_install(
11741185 config_opts : InstallConfigOpts ,
11751186 source_opts : InstallSourceOpts ,
11761187 target_opts : InstallTargetOpts ,
1188+ _prog : ProgressWriter ,
11771189) -> Result < Arc < State > > {
11781190 tracing:: trace!( "Preparing install" ) ;
11791191 let rootfs = cap_std:: fs:: Dir :: open_ambient_dir ( "/" , cap_std:: ambient_authority ( ) )
@@ -1335,10 +1347,11 @@ async fn install_with_sysroot(
13351347 bound_images : BoundImages ,
13361348 has_ostree : bool ,
13371349 imgstore : & crate :: imgstorage:: Storage ,
1350+ prog : ProgressWriter ,
13381351) -> Result < ( ) > {
13391352 // And actually set up the container in that root, returning a deployment and
13401353 // the aleph state (see below).
1341- let ( _deployment, aleph) = install_container ( state, rootfs, & sysroot, has_ostree) . await ?;
1354+ let ( _deployment, aleph) = install_container ( state, rootfs, & sysroot, has_ostree, prog ) . await ?;
13421355 // Write the aleph data that captures the system state at the time of provisioning for aid in future debugging.
13431356 rootfs
13441357 . physical_root
@@ -1420,6 +1433,7 @@ async fn install_to_filesystem_impl(
14201433 state : & State ,
14211434 rootfs : & mut RootSetup ,
14221435 cleanup : Cleanup ,
1436+ prog : ProgressWriter ,
14231437) -> Result < ( ) > {
14241438 if matches ! ( state. selinux_state, SELinuxFinalState :: ForceTargetDisabled ) {
14251439 rootfs. kargs . push ( "selinux=0" . to_string ( ) ) ;
@@ -1461,6 +1475,7 @@ async fn install_to_filesystem_impl(
14611475 bound_images,
14621476 has_ostree,
14631477 & imgstore,
1478+ prog,
14641479 )
14651480 . await ?;
14661481
@@ -1496,6 +1511,7 @@ fn installation_complete() {
14961511#[ context( "Installing to disk" ) ]
14971512#[ cfg( feature = "install-to-disk" ) ]
14981513pub ( crate ) async fn install_to_disk ( mut opts : InstallToDiskOpts ) -> Result < ( ) > {
1514+ let prog: ProgressWriter = opts. progress . try_into ( ) ?;
14991515 let mut block_opts = opts. block_opts ;
15001516 let target_blockdev_meta = block_opts
15011517 . device
@@ -1517,7 +1533,13 @@ pub(crate) async fn install_to_disk(mut opts: InstallToDiskOpts) -> Result<()> {
15171533 } else if !target_blockdev_meta. file_type ( ) . is_block_device ( ) {
15181534 anyhow:: bail!( "Not a block device: {}" , block_opts. device) ;
15191535 }
1520- let state = prepare_install ( opts. config_opts , opts. source_opts , opts. target_opts ) . await ?;
1536+ let state = prepare_install (
1537+ opts. config_opts ,
1538+ opts. source_opts ,
1539+ opts. target_opts ,
1540+ prog. clone ( ) ,
1541+ )
1542+ . await ?;
15211543
15221544 // This is all blocking stuff
15231545 let ( mut rootfs, loopback) = {
@@ -1538,7 +1560,7 @@ pub(crate) async fn install_to_disk(mut opts: InstallToDiskOpts) -> Result<()> {
15381560 ( rootfs, loopback_dev)
15391561 } ;
15401562
1541- install_to_filesystem_impl ( & state, & mut rootfs, Cleanup :: Skip ) . await ?;
1563+ install_to_filesystem_impl ( & state, & mut rootfs, Cleanup :: Skip , prog ) . await ?;
15421564
15431565 // Drop all data about the root except the bits we need to ensure any file descriptors etc. are closed.
15441566 let ( root_path, luksdev) = rootfs. into_storage ( ) ;
@@ -1720,12 +1742,19 @@ pub(crate) async fn install_to_filesystem(
17201742 targeting_host_root : bool ,
17211743 cleanup : Cleanup ,
17221744) -> Result < ( ) > {
1745+ let prog: ProgressWriter = opts. progress . try_into ( ) ?;
17231746 // Gather global state, destructuring the provided options.
17241747 // IMPORTANT: We might re-execute the current process in this function (for SELinux among other things)
17251748 // IMPORTANT: and hence anything that is done before MUST BE IDEMPOTENT.
17261749 // IMPORTANT: In practice, we should only be gathering information before this point,
17271750 // IMPORTANT: and not performing any mutations at all.
1728- let state = prepare_install ( opts. config_opts , opts. source_opts , opts. target_opts ) . await ?;
1751+ let state = prepare_install (
1752+ opts. config_opts ,
1753+ opts. source_opts ,
1754+ opts. target_opts ,
1755+ prog. clone ( ) ,
1756+ )
1757+ . await ?;
17291758 // And the last bit of state here is the fsopts, which we also destructure now.
17301759 let mut fsopts = opts. filesystem_opts ;
17311760
@@ -1924,7 +1953,7 @@ pub(crate) async fn install_to_filesystem(
19241953 skip_finalize,
19251954 } ;
19261955
1927- install_to_filesystem_impl ( & state, & mut rootfs, cleanup) . await ?;
1956+ install_to_filesystem_impl ( & state, & mut rootfs, cleanup, prog ) . await ?;
19281957
19291958 // Drop all data about the root except the path to ensure any file descriptors etc. are closed.
19301959 drop ( rootfs) ;
@@ -1952,6 +1981,7 @@ pub(crate) async fn install_to_existing_root(opts: InstallToExistingRootOpts) ->
19521981 source_opts : opts. source_opts ,
19531982 target_opts : opts. target_opts ,
19541983 config_opts : opts. config_opts ,
1984+ progress : opts. progress ,
19551985 } ;
19561986
19571987 install_to_filesystem ( opts, true , cleanup) . await
0 commit comments