From 0681391d4a8cc6dfb8588f4ba7ce1e1c7302105e Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Tue, 21 Oct 2025 14:34:18 -0700 Subject: [PATCH 1/6] Static link local builds --- Cargo.lock | 11 +++++++++++ Makefile | 4 ++-- crates/trident/Cargo.toml | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1eb430eb..4181c72cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1810,6 +1810,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-src" +version = "300.5.2+3.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d270b79e2926f5150189d475bc7e9d2c69f9c4697b185fa917d5a32b792d21b4" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.107" @@ -1818,6 +1827,7 @@ checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -3304,6 +3314,7 @@ dependencies = [ "netplan-types", "nix", "oci-client", + "openssl", "osutils", "procfs", "prost", diff --git a/Makefile b/Makefile index 5f09f6741..84992d128 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ build: .cargo/config version-vars OPENSSL_LIB_DIR=$(shell dirname `whereis libssl.a | cut -d" " -f2`) \ OPENSSL_INCLUDE_DIR=/usr/include/openssl \ TRIDENT_VERSION="$(TRIDENT_CARGO_VERSION)-dev.$(GIT_COMMIT)" \ - cargo build --release --features dangerous-options + cargo build --release --features dangerous-options --target x86_64-unknown-linux-musl @mkdir -p bin .PHONY: format @@ -149,7 +149,7 @@ artifacts/osmodifier: packaging/docker/Dockerfile-osmodifier.azl3 bin/trident: build @mkdir -p bin - @cp -u target/release/trident bin/ + @cp -u target/x86_64-unknown-linux-musl/release/trident bin/ # This will do a proper build on azl3, exactly as the pipelines would, with the custom registry and all. bin/trident-rpms-azl3.tar.gz: packaging/docker/Dockerfile.full packaging/systemd/*.service packaging/rpm/trident.spec artifacts/osmodifier packaging/selinux-policy-trident/* version-vars diff --git a/crates/trident/Cargo.toml b/crates/trident/Cargo.toml index 1582337cf..f2c7820f4 100644 --- a/crates/trident/Cargo.toml +++ b/crates/trident/Cargo.toml @@ -53,6 +53,8 @@ tracing-subscriber = { version = "0.3.19", features = ["json"] } url = { version = "2.5.4", features = ["serde"] } uuid = { version = "1.11.0", features = ["v4", "serde"] } +openssl = { version = "0.10", features = ["vendored"] } + sysdefs = { path = "../sysdefs" } osutils = { path = "../osutils" } trident_api = { path = "../trident_api" } From 0483d284d26a497a4148800d3a6027b25935de46 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Tue, 28 Oct 2025 14:16:10 -0700 Subject: [PATCH 2/6] Initial raw COSI logic --- crates/osutils/src/chroot.rs | 4 ++ crates/trident/src/engine/clean_install.rs | 68 +++++++++++++++++++ crates/trident/src/engine/newroot.rs | 6 ++ crates/trident/src/engine/storage/image.rs | 13 +++- crates/trident/src/subsystems/esp.rs | 5 +- crates/trident/src/subsystems/initrd.rs | 4 ++ crates/trident/src/subsystems/storage/mod.rs | 4 ++ .../trident/src/subsystems/storage/osimage.rs | 4 ++ crates/trident_api/src/config/host/error.rs | 3 + .../src/config/host/storage/mod.rs | 21 ++++++ 10 files changed, 128 insertions(+), 4 deletions(-) diff --git a/crates/osutils/src/chroot.rs b/crates/osutils/src/chroot.rs index 8d6484a7d..cedc7cc9f 100644 --- a/crates/osutils/src/chroot.rs +++ b/crates/osutils/src/chroot.rs @@ -28,6 +28,10 @@ impl Chroot { return Err(TridentError::new(ServicingError::EnterChroot)); } + let _ = fs::create_dir(path.join("dev")); + let _ = fs::create_dir(path.join("proc")); + let _ = fs::create_dir(path.join("sys")); + // Mount special dirs. debug!("Mounting special directories"); let mounts = vec![ diff --git a/crates/trident/src/engine/clean_install.rs b/crates/trident/src/engine/clean_install.rs index fce898199..ca769484a 100644 --- a/crates/trident/src/engine/clean_install.rs +++ b/crates/trident/src/engine/clean_install.rs @@ -213,6 +213,68 @@ fn stage_clean_install( engine::validate_host_config(subsystems, &ctx)?; + // if ctx.spec.storage.from_cosi { + // let partitions = &mut ctx + // .spec + // .storage + // .disks + // .get_mut(0) + // .structured(InternalError::Internal("No disks but storage.fromCosi set"))? + // .partitions; + // let image = ctx + // .image + // .as_ref() + // .structured(InternalError::Internal("no image"))?; + // for (n, fs) in image.filesystems().enumerate() { + // partitions.push(trident_api::config::Partition { + // id: format!("part{}", n + 1), + // partition_type: trident_api::config::PartitionType::LinuxGeneric, + // size: fs + // .image_file + // .uncompressed_size + // .next_multiple_of(1 << 20) + // .into(), + // }); + // ctx.spec + // .storage + // .filesystems + // .push(trident_api::config::FileSystem { + // device_id: Some(format!("part{}", n + 1)), + // source: trident_api::config::FileSystemSource::Image, + // mount_point: Some(trident_api::config::MountPoint { + // path: fs.mount_point.clone(), + // options: Default::default(), + // }), + // }); + // } + // partitions.sort_by_key(|p| p.size.to_bytes().unwrap_or(u64::MAX)); + // partitions.insert( + // 0, + // trident_api::config::Partition { + // id: "esp".to_string(), + // partition_type: trident_api::config::PartitionType::Esp, + // size: image + // .esp_filesystem() + // .structured(InternalError::Internal("No ESP filesystem in COSI"))? + // .image_file + // .uncompressed_size + // .next_multiple_of(1 << 20) + // .into(), + // }, + // ); + // ctx.spec + // .storage + // .filesystems + // .push(trident_api::config::FileSystem { + // device_id: Some("esp".to_string()), + // source: trident_api::config::FileSystemSource::Image, + // mount_point: Some(trident_api::config::MountPoint { + // path: "/boot/efi".into(), + // options: Default::default(), + // }), + // }); + // } + ctx.populate_filesystems()?; // Need to re-set saved Host Status in case another clean install has been previously staged @@ -324,6 +386,12 @@ pub(crate) fn finalize_clean_install( // On clean install, need to verify that AZLA entry exists in /mnt/newroot/boot/efi let esp_path = join_relative(new_root.path(), ESP_MOUNT_POINT_PATH); + + if ctx.spec.storage.raw_cosi { + new_root.unmount_all()?; + return Ok(ExitKind::NeedsReboot); + } + bootentries::create_and_update_boot_variables(&ctx, &esp_path)?; debug!( diff --git a/crates/trident/src/engine/newroot.rs b/crates/trident/src/engine/newroot.rs index db019bd41..4d8110642 100644 --- a/crates/trident/src/engine/newroot.rs +++ b/crates/trident/src/engine/newroot.rs @@ -279,6 +279,12 @@ impl NewrootMount { debug!("Mounting tmpfs to '{}'", target_path_full.display()); + if !target_path_full.exists() { + fs::create_dir(&target_path_full).structured(ServicingError::MountNewrootSpecialDir { + dir: target_path_full.clone().to_string_lossy().to_string(), + })?; + } + // Do the actual tmpfs mount MountBuilder::default() .fstype("tmpfs") diff --git a/crates/trident/src/engine/storage/image.rs b/crates/trident/src/engine/storage/image.rs index b6212b749..42337d12c 100644 --- a/crates/trident/src/engine/storage/image.rs +++ b/crates/trident/src/engine/storage/image.rs @@ -40,11 +40,20 @@ pub(super) fn deploy_images(ctx: &EngineContext) -> Result<(), TridentError> { "No OS image available for deployment", ))?; - let images = os_img + let mut images = os_img .filesystems() .map(|fs| (fs.mount_point.to_owned(), fs)) .collect::>(); + if ctx.spec.storage.raw_cosi { + images.insert( + "/boot/efi".into(), + os_img + .esp_filesystem() + .structured(InternalError::Internal("COSI doesn't have ESP"))?, + ); + } + // Now, deploy the filesystems sourced from the OS image for (id, mpp, fs) in fs_from_img { let image = images @@ -136,7 +145,7 @@ fn filesystems_from_image( continue; }; - if img_fs.is_esp() { + if img_fs.is_esp() && !ctx.spec.storage.raw_cosi { debug!( "Skipping deployment of filesystem [{}] sourced from OS Image, as it is the ESP.", filesystem.description() diff --git a/crates/trident/src/subsystems/esp.rs b/crates/trident/src/subsystems/esp.rs index 8e75ffc68..ff5e45f58 100644 --- a/crates/trident/src/subsystems/esp.rs +++ b/crates/trident/src/subsystems/esp.rs @@ -47,8 +47,9 @@ impl Subsystem for EspSubsystem { // Perform file-based deployment of ESP images, if needed, after filesystems have been // mounted and initialized. - // Deploy ESP image - deploy_esp(ctx, mount_path).structured(ServicingError::DeployESPImages)?; + if !ctx.spec.storage.raw_cosi { + deploy_esp(ctx, mount_path).structured(ServicingError::DeployESPImages)?; + } Ok(()) } diff --git a/crates/trident/src/subsystems/initrd.rs b/crates/trident/src/subsystems/initrd.rs index 1d4bbf2db..f957deabf 100644 --- a/crates/trident/src/subsystems/initrd.rs +++ b/crates/trident/src/subsystems/initrd.rs @@ -22,6 +22,10 @@ impl Subsystem for InitrdSubsystem { debug!("Skipping initrd regeneration because UKI is in use"); return Ok(()); } + if ctx.spec.storage.raw_cosi { + debug!("Skipping initrd regeneration because raw COSI is in use"); + return Ok(()); + } // We could autodetect configurations on the fly, but for more predictable // behavior and speedier subsequent boots, we will regenerate the host-specific initrd diff --git a/crates/trident/src/subsystems/storage/mod.rs b/crates/trident/src/subsystems/storage/mod.rs index fd122c40e..a30979aa6 100644 --- a/crates/trident/src/subsystems/storage/mod.rs +++ b/crates/trident/src/subsystems/storage/mod.rs @@ -188,6 +188,10 @@ impl Subsystem for StorageSubsystem { debug!("Skipping storage configuration because UKI root-verity is in use"); return Ok(()); } + if ctx.spec.storage.raw_cosi { + debug!("Skipping storage configuration because raw COSI is in use"); + return Ok(()); + } fstab::generate_fstab(ctx, Path::new(fstab::DEFAULT_FSTAB_PATH)).structured( ServicingError::GenerateFstab { diff --git a/crates/trident/src/subsystems/storage/osimage.rs b/crates/trident/src/subsystems/storage/osimage.rs index 4f58c609e..9c806252e 100644 --- a/crates/trident/src/subsystems/storage/osimage.rs +++ b/crates/trident/src/subsystems/storage/osimage.rs @@ -43,6 +43,10 @@ pub fn validate_host_config(ctx: &EngineContext) -> Result<(), TridentError> { return Ok(()); }; + if ctx.spec.storage.raw_cosi { + return Ok(()); + } + debug!("Validating Host Configuration filesystems against OS image"); validate_filesystems(os_image, ctx)?; diff --git a/crates/trident_api/src/config/host/error.rs b/crates/trident_api/src/config/host/error.rs index 3e0201d57..cb37ca35e 100644 --- a/crates/trident_api/src/config/host/error.rs +++ b/crates/trident_api/src/config/host/error.rs @@ -78,6 +78,9 @@ pub enum HostConfigurationStaticValidationError { )] ImageApiMixed, + #[error("If storage.fromCosi is set, configuration cannot also specify storage settings")] + InconsistentStorageMethod, + #[error(transparent)] InvalidStorageGraph(#[from] StorageGraphBuildError), diff --git a/crates/trident_api/src/config/host/storage/mod.rs b/crates/trident_api/src/config/host/storage/mod.rs index 0ed1d9f23..9d381f9f4 100644 --- a/crates/trident_api/src/config/host/storage/mod.rs +++ b/crates/trident_api/src/config/host/storage/mod.rs @@ -91,6 +91,10 @@ pub struct Storage { ) )] pub swap: Vec, + + /// Source the storage configuration from the COSI. + #[serde(default, skip_serializing_if = "is_default")] + pub raw_cosi: bool, } impl Storage { @@ -173,6 +177,23 @@ impl Storage { &self, require_root_mount_point: bool, ) -> Result { + // if self.raw_cosi { + // if self.encryption.is_some() + // || self.raid != Raid::default() + // || self.ab_update.is_some() + // || !self.filesystems.is_empty() + // || self.disks.len() != 1 + // || !self.disks[0].partitions.is_empty() + // || !self.disks[0].adopted_partitions.is_empty() + // || !self.verity.is_empty() + // || !self.swap.is_empty() + // { + // return Err(HostConfigurationStaticValidationError::InconsistentStorageMethod); + // } + + // return Ok(StorageGraph::default()); + // } + // Check basic constraints if let Some(encryption) = &self.encryption { From 1948b61f9e3f344feea793d51fcafc5cfaaee2e8 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Wed, 29 Oct 2025 14:03:37 -0700 Subject: [PATCH 3/6] Also skip grub --- crates/trident/src/engine/boot/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/trident/src/engine/boot/mod.rs b/crates/trident/src/engine/boot/mod.rs index d114ad9b2..80101e2a0 100644 --- a/crates/trident/src/engine/boot/mod.rs +++ b/crates/trident/src/engine/boot/mod.rs @@ -31,6 +31,10 @@ impl Subsystem for BootSubsystem { debug!("Skipping grub configuration because UKI is in use"); return Ok(()); } + if ctx.spec.storage.raw_cosi { + debug!("Skipping grub configuration because raw COSI is in use"); + return Ok(()); + } grub::update_configs(ctx, Path::new(OS_MODIFIER_NEWROOT_PATH)) .structured(ServicingError::UpdateGrubConfigs)?; From 77ba5ee1b084bf2bdaa5416b835d3871ae5064b3 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Wed, 29 Oct 2025 14:08:28 -0700 Subject: [PATCH 4/6] Revert some changes --- crates/trident_api/src/config/host/error.rs | 3 --- .../trident_api/src/config/host/storage/mod.rs | 17 ----------------- 2 files changed, 20 deletions(-) diff --git a/crates/trident_api/src/config/host/error.rs b/crates/trident_api/src/config/host/error.rs index cb37ca35e..3e0201d57 100644 --- a/crates/trident_api/src/config/host/error.rs +++ b/crates/trident_api/src/config/host/error.rs @@ -78,9 +78,6 @@ pub enum HostConfigurationStaticValidationError { )] ImageApiMixed, - #[error("If storage.fromCosi is set, configuration cannot also specify storage settings")] - InconsistentStorageMethod, - #[error(transparent)] InvalidStorageGraph(#[from] StorageGraphBuildError), diff --git a/crates/trident_api/src/config/host/storage/mod.rs b/crates/trident_api/src/config/host/storage/mod.rs index 9d381f9f4..01c97a88b 100644 --- a/crates/trident_api/src/config/host/storage/mod.rs +++ b/crates/trident_api/src/config/host/storage/mod.rs @@ -177,23 +177,6 @@ impl Storage { &self, require_root_mount_point: bool, ) -> Result { - // if self.raw_cosi { - // if self.encryption.is_some() - // || self.raid != Raid::default() - // || self.ab_update.is_some() - // || !self.filesystems.is_empty() - // || self.disks.len() != 1 - // || !self.disks[0].partitions.is_empty() - // || !self.disks[0].adopted_partitions.is_empty() - // || !self.verity.is_empty() - // || !self.swap.is_empty() - // { - // return Err(HostConfigurationStaticValidationError::InconsistentStorageMethod); - // } - - // return Ok(StorageGraph::default()); - // } - // Check basic constraints if let Some(encryption) = &self.encryption { From 49797b22fc5b6f347cd9d5b15578fdb2675958fd Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Wed, 29 Oct 2025 14:10:54 -0700 Subject: [PATCH 5/6] More revert --- crates/trident/src/engine/clean_install.rs | 62 ---------------------- 1 file changed, 62 deletions(-) diff --git a/crates/trident/src/engine/clean_install.rs b/crates/trident/src/engine/clean_install.rs index ca769484a..9e0036b8e 100644 --- a/crates/trident/src/engine/clean_install.rs +++ b/crates/trident/src/engine/clean_install.rs @@ -213,68 +213,6 @@ fn stage_clean_install( engine::validate_host_config(subsystems, &ctx)?; - // if ctx.spec.storage.from_cosi { - // let partitions = &mut ctx - // .spec - // .storage - // .disks - // .get_mut(0) - // .structured(InternalError::Internal("No disks but storage.fromCosi set"))? - // .partitions; - // let image = ctx - // .image - // .as_ref() - // .structured(InternalError::Internal("no image"))?; - // for (n, fs) in image.filesystems().enumerate() { - // partitions.push(trident_api::config::Partition { - // id: format!("part{}", n + 1), - // partition_type: trident_api::config::PartitionType::LinuxGeneric, - // size: fs - // .image_file - // .uncompressed_size - // .next_multiple_of(1 << 20) - // .into(), - // }); - // ctx.spec - // .storage - // .filesystems - // .push(trident_api::config::FileSystem { - // device_id: Some(format!("part{}", n + 1)), - // source: trident_api::config::FileSystemSource::Image, - // mount_point: Some(trident_api::config::MountPoint { - // path: fs.mount_point.clone(), - // options: Default::default(), - // }), - // }); - // } - // partitions.sort_by_key(|p| p.size.to_bytes().unwrap_or(u64::MAX)); - // partitions.insert( - // 0, - // trident_api::config::Partition { - // id: "esp".to_string(), - // partition_type: trident_api::config::PartitionType::Esp, - // size: image - // .esp_filesystem() - // .structured(InternalError::Internal("No ESP filesystem in COSI"))? - // .image_file - // .uncompressed_size - // .next_multiple_of(1 << 20) - // .into(), - // }, - // ); - // ctx.spec - // .storage - // .filesystems - // .push(trident_api::config::FileSystem { - // device_id: Some("esp".to_string()), - // source: trident_api::config::FileSystemSource::Image, - // mount_point: Some(trident_api::config::MountPoint { - // path: "/boot/efi".into(), - // options: Default::default(), - // }), - // }); - // } - ctx.populate_filesystems()?; // Need to re-set saved Host Status in case another clean install has been previously staged From b31b6032b57120979d41a2dc97722e44c9b84de9 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Thu, 30 Oct 2025 14:57:22 -0700 Subject: [PATCH 6/6] Don't overwrite ESP --- crates/trident/src/engine/storage/filesystem.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/trident/src/engine/storage/filesystem.rs b/crates/trident/src/engine/storage/filesystem.rs index c3ac10da3..59c8529db 100644 --- a/crates/trident/src/engine/storage/filesystem.rs +++ b/crates/trident/src/engine/storage/filesystem.rs @@ -55,6 +55,7 @@ fn block_devices_needing_fs_creation( FileSystemData::Image(ifs) if ctx.servicing_type == ServicingType::CleanInstall && fs.is_esp() + && !ctx.spec.storage.raw_cosi && !ctx .storage_graph .is_adopted(&ifs.device_id)