@@ -564,7 +564,7 @@ pub(crate) fn print_configuration() -> Result<()> {
564
564
}
565
565
566
566
#[ context( "Creating ostree deployment" ) ]
567
- async fn initialize_ostree_root ( state : & State , root_setup : & RootSetup ) -> Result < Storage > {
567
+ async fn initialize_ostree_root ( state : & State , root_setup : & RootSetup ) -> Result < ( Storage , bool ) > {
568
568
let sepolicy = state. load_policy ( ) ?;
569
569
let sepolicy = sepolicy. as_ref ( ) ;
570
570
// Load a fd for the mounted target physical root
@@ -578,11 +578,17 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
578
578
579
579
let stateroot = state. stateroot ( ) ;
580
580
581
- Task :: new_and_run (
582
- "Initializing ostree layout" ,
583
- "ostree" ,
584
- [ "admin" , "init-fs" , "--modern" , rootfs. as_str ( ) ] ,
585
- ) ?;
581
+ let has_ostree = rootfs_dir. try_exists ( "ostree/repo" ) ?;
582
+ if !has_ostree {
583
+ Task :: new_and_run (
584
+ "Initializing ostree layout" ,
585
+ "ostree" ,
586
+ [ "admin" , "init-fs" , "--modern" , rootfs. as_str ( ) ] ,
587
+ ) ?;
588
+ } else {
589
+ println ! ( "Reusing extant ostree layout" ) ;
590
+ let _ = crate :: utils:: open_dir_remount_rw ( rootfs_dir, "sysroot" . into ( ) ) ?;
591
+ }
586
592
587
593
// And also label /boot AKA xbootldr, if it exists
588
594
let bootdir = rootfs. join ( "boot" ) ;
@@ -607,9 +613,14 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
607
613
let sysroot = ostree:: Sysroot :: new ( Some ( & gio:: File :: for_path ( rootfs) ) ) ;
608
614
sysroot. load ( cancellable) ?;
609
615
610
- sysroot
611
- . init_osname ( stateroot, cancellable)
612
- . context ( "initializing stateroot" ) ?;
616
+ let stateroot_exists = rootfs_dir. try_exists ( format ! ( "ostree/deploy/{stateroot}" ) ) ?;
617
+ if stateroot_exists {
618
+ anyhow:: bail!( "Cannot redeploy over extant stateroot {stateroot}" ) ;
619
+ } else {
620
+ sysroot
621
+ . init_osname ( stateroot, cancellable)
622
+ . context ( "initializing stateroot" ) ?;
623
+ }
613
624
614
625
let sysroot_dir = Dir :: reopen_dir ( & crate :: utils:: sysroot_fd ( & sysroot) ) ?;
615
626
@@ -637,14 +648,15 @@ async fn initialize_ostree_root(state: &State, root_setup: &RootSetup) -> Result
637
648
let sysroot = ostree:: Sysroot :: new ( Some ( & gio:: File :: for_path ( rootfs) ) ) ;
638
649
sysroot. load ( cancellable) ?;
639
650
let sysroot = SysrootLock :: new_from_sysroot ( & sysroot) . await ?;
640
- Storage :: new ( sysroot, & temp_run)
651
+ Ok ( ( Storage :: new ( sysroot, & temp_run) ? , has_ostree ) )
641
652
}
642
653
643
654
#[ context( "Creating ostree deployment" ) ]
644
655
async fn install_container (
645
656
state : & State ,
646
657
root_setup : & RootSetup ,
647
658
sysroot : & ostree:: Sysroot ,
659
+ has_ostree : bool ,
648
660
) -> Result < ( ostree:: Deployment , InstallAleph ) > {
649
661
let sepolicy = state. load_policy ( ) ?;
650
662
let sepolicy = sepolicy. as_ref ( ) ;
@@ -730,6 +742,7 @@ async fn install_container(
730
742
options. kargs = Some ( kargs. as_slice ( ) ) ;
731
743
options. target_imgref = Some ( & state. target_imgref ) ;
732
744
options. proxy_cfg = proxy_cfg;
745
+ options. no_clean = has_ostree;
733
746
let imgstate = crate :: utils:: async_task_with_spinner (
734
747
"Deploying container image" ,
735
748
ostree_container:: deploy:: deploy ( & sysroot, stateroot, & src_imageref, Some ( options) ) ,
@@ -1275,10 +1288,11 @@ async fn install_with_sysroot(
1275
1288
sysroot : & Storage ,
1276
1289
boot_uuid : & str ,
1277
1290
bound_images : & [ crate :: boundimage:: ResolvedBoundImage ] ,
1291
+ has_ostree : bool ,
1278
1292
) -> Result < ( ) > {
1279
1293
// And actually set up the container in that root, returning a deployment and
1280
1294
// the aleph state (see below).
1281
- let ( _deployment, aleph) = install_container ( state, rootfs, & sysroot) . await ?;
1295
+ let ( _deployment, aleph) = install_container ( state, rootfs, & sysroot, has_ostree ) . await ?;
1282
1296
// Write the aleph data that captures the system state at the time of provisioning for aid in future debugging.
1283
1297
rootfs
1284
1298
. rootfs_fd
@@ -1339,6 +1353,19 @@ async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Re
1339
1353
. ok_or_else ( || anyhow ! ( "No uuid for boot/root" ) ) ?;
1340
1354
tracing:: debug!( "boot uuid={boot_uuid}" ) ;
1341
1355
1356
+ // If we're doing an alongside install, then the /dev bootupd sees needs to be the host's.
1357
+ // What we probably really want to do here is tunnel in the host's /dev properly, but for now
1358
+ // just copy /dev/disk
1359
+ if rootfs. skip_finalize {
1360
+ if !Utf8Path :: new ( "/dev/disk" ) . try_exists ( ) ? {
1361
+ Task :: new_and_run (
1362
+ "Copying host /dev/disk" ,
1363
+ "cp" ,
1364
+ [ "-a" , "/proc/1/root/dev/disk" , "/dev/disk" ] ,
1365
+ ) ?;
1366
+ }
1367
+ }
1368
+
1342
1369
let bound_images = if state. config_opts . skip_bound_images {
1343
1370
Vec :: new ( )
1344
1371
} else {
@@ -1359,8 +1386,16 @@ async fn install_to_filesystem_impl(state: &State, rootfs: &mut RootSetup) -> Re
1359
1386
1360
1387
// Initialize the ostree sysroot (repo, stateroot, etc.)
1361
1388
{
1362
- let sysroot = initialize_ostree_root ( state, rootfs) . await ?;
1363
- install_with_sysroot ( state, rootfs, & sysroot, & boot_uuid, & bound_images) . await ?;
1389
+ let ( sysroot, has_ostree) = initialize_ostree_root ( state, rootfs) . await ?;
1390
+ install_with_sysroot (
1391
+ state,
1392
+ rootfs,
1393
+ & sysroot,
1394
+ & boot_uuid,
1395
+ & bound_images,
1396
+ has_ostree,
1397
+ )
1398
+ . await ?;
1364
1399
// We must drop the sysroot here in order to close any open file
1365
1400
// descriptors.
1366
1401
}
@@ -1501,7 +1536,8 @@ fn remove_all_in_dir_no_xdev(d: &Dir) -> Result<()> {
1501
1536
1502
1537
#[ context( "Removing boot directory content" ) ]
1503
1538
fn clean_boot_directories ( rootfs : & Dir ) -> Result < ( ) > {
1504
- let bootdir = rootfs. open_dir ( BOOT ) . context ( "Opening /boot" ) ?;
1539
+ let bootdir =
1540
+ crate :: utils:: open_dir_remount_rw ( rootfs, BOOT . into ( ) ) . context ( "Opening /boot" ) ?;
1505
1541
// This should not remove /boot/efi note.
1506
1542
remove_all_in_dir_no_xdev ( & bootdir) ?;
1507
1543
if ARCH_USES_EFI {
0 commit comments