diff options
-rw-r--r-- | crates/common/src/types.rs | 1 | ||||
-rw-r--r-- | crates/driver/src/driver.rs | 4 | ||||
-rw-r--r-- | crates/runner/src/init.rs | 24 | ||||
-rw-r--r-- | crates/runner/src/paths.rs | 5 | ||||
-rw-r--r-- | crates/runner/src/tar.rs | 28 | ||||
-rw-r--r-- | crates/runner/src/task.rs | 46 |
6 files changed, 54 insertions, 54 deletions
diff --git a/crates/common/src/types.rs b/crates/common/src/types.rs index 336b131..222c79f 100644 --- a/crates/common/src/types.rs +++ b/crates/common/src/types.rs @@ -38,6 +38,7 @@ pub struct Task { pub label: String, pub command: String, pub workdir: String, + pub rootfs: ArchiveHash, pub inherit: Vec<LayerHash>, pub depends: HashSet<Dependency>, pub outputs: HashMap<String, String>, diff --git a/crates/driver/src/driver.rs b/crates/driver/src/driver.rs index e3dc407..84262ac 100644 --- a/crates/driver/src/driver.rs +++ b/crates/driver/src/driver.rs @@ -298,14 +298,16 @@ impl<'ctx> Driver<'ctx> { format!("Failed to evaluate command template for task {}", task_ref) })?; + let rootfs = self.state.ctx.get_rootfs(); let task = Task { label: format!("{:#}", task_ref), command, workdir: paths::TASK_WORKDIR.to_string(), + rootfs: rootfs.0, inherit: inherit_chain, depends: task_deps, outputs: task_output, - pins: HashMap::new(), + pins: HashMap::from([rootfs.clone()]), }; Ok(Some(runner.spawn(&task))) diff --git a/crates/runner/src/init.rs b/crates/runner/src/init.rs index ad37cf0..ede8fd8 100644 --- a/crates/runner/src/init.rs +++ b/crates/runner/src/init.rs @@ -1,29 +1,8 @@ -use std::fs::File; - use nix::mount::{self, MsFlags}; use common::error::*; -use super::{tar, util::fs}; -use crate::paths; - -fn prepare_rootfs(path: &str) -> Result<()> { - tar::unpack(File::open(paths::ROOTFS_ARCHIVE)?, path) - .context("Unpacking build container rootfs failed")?; - - mount::mount::<_, _, str, str>(Some(path), path, None, MsFlags::MS_BIND, None) - .context("Failed to bind mount container rootfs")?; - mount::mount::<str, _, str, str>( - None, - path, - None, - MsFlags::MS_REMOUNT | MsFlags::MS_BIND | MsFlags::MS_RDONLY, - None, - ) - .context("Failed to mount container rootfs read-only")?; - - Ok(()) -} +use crate::{paths, util::fs}; fn prepare_dev(path: &str) -> Result<()> { fs::mkdir(path)?; @@ -83,7 +62,6 @@ pub fn init_runner() -> Result<()> { mount::mount::<str, _, str, str>(None, paths::TMP_DIR, None, MsFlags::MS_PRIVATE, None) .context("Failed to set MS_PRIVATE for build tmpdir")?; - prepare_rootfs(paths::ROOTFS_DIR)?; prepare_dev(paths::DEV_DIR)?; Ok(()) diff --git a/crates/runner/src/paths.rs b/crates/runner/src/paths.rs index b46d1bb..7af1e3a 100644 --- a/crates/runner/src/paths.rs +++ b/crates/runner/src/paths.rs @@ -5,7 +5,6 @@ //! ```text //! build/ //! ├── build.lock -//! ├── rootfs.tar //! ├── downloads/ //! │ └── ... //! ├── state/ @@ -27,7 +26,6 @@ //! │ └── ... //! └── tmp/ # temporary files (cleaned on start) //! ├── dev/ # container /dev -//! ├── rootfs/ # unpacked rootfs.tar //! ├── depends/ # unpacked dependencies //! └── task/ //! └── <input hash>/ @@ -40,14 +38,11 @@ use common::string_hash::*; -pub const ROOTFS_ARCHIVE: &str = "build/rootfs.tar"; - pub const DOWNLOADS_DIR: &str = "build/downloads"; pub const PIN_DIR: &str = "build/pinned"; pub const TMP_DIR: &str = "build/tmp"; pub const DEV_DIR: &str = "build/tmp/dev"; -pub const ROOTFS_DIR: &str = "build/tmp/rootfs"; pub const DEPENDS_TMP_DIR: &str = "build/tmp/depends"; pub const TASK_TMP_DIR: &str = "build/tmp/task"; diff --git a/crates/runner/src/tar.rs b/crates/runner/src/tar.rs index 32d8e8d..10cac92 100644 --- a/crates/runner/src/tar.rs +++ b/crates/runner/src/tar.rs @@ -11,7 +11,7 @@ use nix::{ sys::wait, }; -use common::error::*; +use common::{error::*, string_hash::ArchiveHash}; use super::{ ns, @@ -19,12 +19,28 @@ use super::{ }; use crate::paths; -pub fn pack<W: Write, P: AsRef<Path>>(archive: &mut W, source: P) -> Result<()> { +pub fn pack<W: Write, P: AsRef<Path>>( + rootfs_hash: &ArchiveHash, + archive: &mut W, + source: P, +) -> Result<()> { + let rootfs = paths::depend_dir(rootfs_hash); + let _rootfs_mount = fs::mount(&rootfs, &rootfs, None, MsFlags::MS_BIND, None) + .with_context(|| format!("Failed to bind mount rootfs to {:?}", rootfs))?; + mount::mount::<str, str, str, str>( + None, + &rootfs, + None, + MsFlags::MS_REMOUNT | MsFlags::MS_BIND | MsFlags::MS_RDONLY, + None, + ) + .context("Failed to mount container rootfs read-only")?; + let (mut piper, pipew) = fs::pipe()?; let exec_tar = || -> Result<()> { - // We are in our own mount namespace, so mounting into the shared ROOTFS_DIR is fine - let dev_target = paths::join(&[paths::ROOTFS_DIR, "dev"]); + // We are in our own mount namespace, so mounting into the shared rootfs is fine + let dev_target = paths::join(&[&rootfs, "dev"]); mount::mount::<_, _, str, str>( Some(paths::DEV_DIR), dev_target.as_str(), @@ -32,7 +48,7 @@ pub fn pack<W: Write, P: AsRef<Path>>(archive: &mut W, source: P) -> Result<()> MsFlags::MS_BIND | MsFlags::MS_REC, None, )?; - let mount_target = paths::join(&[paths::ROOTFS_DIR, paths::TASK_BUILDDIR]); + let mount_target = paths::join(&[&rootfs, paths::TASK_BUILDDIR]); mount::mount::<_, _, str, str>( Some(source.as_ref()), mount_target.as_str(), @@ -41,7 +57,7 @@ pub fn pack<W: Write, P: AsRef<Path>>(archive: &mut W, source: P) -> Result<()> None, )?; - ns::pivot_root(paths::ROOTFS_DIR); + ns::pivot_root(&rootfs); let err = Command::new("tar") .args(&[ diff --git a/crates/runner/src/task.rs b/crates/runner/src/task.rs index c43fc2f..8981d13 100644 --- a/crates/runner/src/task.rs +++ b/crates/runner/src/task.rs @@ -51,6 +51,7 @@ fn input_hash(task: &Task) -> InputHash { struct HashInput<'a> { pub command: &'a str, pub workdir: &'a str, + pub rootfs: &'a ArchiveHash, pub inherit: &'a [LayerHash], pub depends: HashMap<DependencyHash, &'a Dependency>, pub outputs: &'a HashMap<String, String>, @@ -58,6 +59,7 @@ fn input_hash(task: &Task) -> InputHash { let input = HashInput { command: &task.command, workdir: &task.workdir, + rootfs: &task.rootfs, inherit: &task.inherit, depends: task .depends @@ -180,22 +182,27 @@ fn check_conflicts( Ok(()) } -fn init_task_rootfs(input_hash: &InputHash, depends: &DependMap) -> Result<Stack<fs::Mount>> { +fn init_task_rootfs(input_hash: &InputHash, task: &Task) -> Result<Stack<fs::Mount>> { let task_tmp_dir = paths::task_tmp_dir(input_hash); let mount_target = paths::join(&[&task_tmp_dir, paths::TASK_TMP_ROOTFS_SUBDIR]); + let rootfs = paths::depend_dir(&task.rootfs); + + let depends = unpack_dependencies(input_hash, task).context("Failed to unpack dependencies")?; let mut mounts = Stack::new(); mounts.push( - fs::mount( - paths::ROOTFS_DIR, - &mount_target, - None, - MsFlags::MS_BIND, - None, - ) - .with_context(|| format!("Failed to bind mount rootfs to {:?}", mount_target))?, + fs::mount(rootfs, &mount_target, None, MsFlags::MS_BIND, None) + .with_context(|| format!("Failed to bind mount rootfs to {:?}", mount_target))?, ); + mount::mount::<str, str, str, str>( + None, + &mount_target, + None, + MsFlags::MS_REMOUNT | MsFlags::MS_BIND | MsFlags::MS_RDONLY, + None, + ) + .context("Failed to mount container rootfs read-only")?; let (mut dirs, mut files) = get_contents(&mount_target, "")?; @@ -209,11 +216,11 @@ fn init_task_rootfs(input_hash: &InputHash, depends: &DependMap) -> Result<Stack ))); } - let dep_target = mount_target.clone() + path; + let dep_target = mount_target.clone() + &path; let dep_paths: Box<[_]> = dep_hashes.iter().map(paths::depend_dir).collect(); for dep in dep_paths.iter() { - let (dep_dirs, dep_files) = get_contents(dep, path)?; + let (dep_dirs, dep_files) = get_contents(dep, &path)?; check_conflicts(&dirs, &files, &dep_dirs, &dep_files)?; dirs.extend(dep_dirs); files.extend(dep_files); @@ -306,6 +313,8 @@ fn unpack_dependency(task: &Task, hash: &ArchiveHash) -> Result<()> { fn unpack_dependencies(input_hash: &InputHash, task: &Task) -> Result<DependMap> { let task_tmp_dir = paths::task_tmp_dir(input_hash); + unpack_dependency(task, &task.rootfs)?; + let mut ret = DependMap::new(); for dep in &task.depends { @@ -330,7 +339,7 @@ fn unpack_dependencies(input_hash: &InputHash, task: &Task) -> Result<DependMap> Ok(ret) } -fn collect_output(input_hash: &InputHash, path: &str) -> Result<Option<ArchiveHash>> { +fn collect_output(input_hash: &InputHash, task: &Task, path: &str) -> Result<Option<ArchiveHash>> { let source = paths::join(&[&paths::task_tmp_dir(input_hash), path]); if !Path::new(&source).is_dir() { return Ok(None); @@ -344,7 +353,7 @@ fn collect_output(input_hash: &InputHash, path: &str) -> Result<Option<ArchiveHa let writer = TeeWriter::new(file, hasher); let mut buffered_writer = BufWriter::with_capacity(16 * 1024 * 1024, writer); - super::tar::pack(&mut buffered_writer, &source)?; + super::tar::pack(&task.rootfs, &mut buffered_writer, &source)?; let writer = buffered_writer.into_inner()?; let (file, hasher) = writer.into_inner(); @@ -364,7 +373,7 @@ fn collect_outputs(input_hash: &InputHash, task: &Task) -> Result<HashMap<String let mut ret = HashMap::new(); for (name, path) in &task.outputs { - if let Some(hash) = collect_output(input_hash, path)? { + if let Some(hash) = collect_output(input_hash, task, path)? { ret.insert(name.clone(), hash); } } @@ -374,9 +383,8 @@ fn collect_outputs(input_hash: &InputHash, task: &Task) -> Result<HashMap<String fn run_task(input_hash: &InputHash, task: &Task, jobserver: &mut Jobserver) -> Result<()> { let _workdir_mount = init_task(input_hash, task).context("Failed to initialize task")?; - let depends = unpack_dependencies(input_hash, task).context("Failed to unpack dependencies")?; let _rootfs_mounts = - init_task_rootfs(input_hash, &depends).context("Failed to initialize task rootfs")?; + init_task_rootfs(input_hash, task).context("Failed to initialize task rootfs")?; let task_tmp_dir = paths::task_tmp_dir(input_hash); let rootfs = paths::join(&[&task_tmp_dir, paths::TASK_TMP_ROOTFS_SUBDIR]); @@ -475,7 +483,7 @@ fn run_task(input_hash: &InputHash, task: &Task, jobserver: &mut Jobserver) -> R Ok(()) } -fn hash_layer(input_hash: &InputHash) -> Result<Option<LayerHash>> { +fn hash_layer(input_hash: &InputHash, task: &Task) -> Result<Option<LayerHash>> { let task_state_dir = paths::task_state_dir(input_hash); let task_layer_dir = paths::join(&[&task_state_dir, paths::TASK_STATE_LAYER_SUBDIR]); @@ -487,7 +495,7 @@ fn hash_layer(input_hash: &InputHash) -> Result<Option<LayerHash>> { let hasher = LayerHasher::new(); let mut buffered_writer = BufWriter::with_capacity(16 * 1024 * 1024, hasher); - tar::pack(&mut buffered_writer, &task_layer_dir)?; + tar::pack(&task.rootfs, &mut buffered_writer, &task_layer_dir)?; let hasher = buffered_writer.into_inner()?; Ok(Some(LayerHash(StringHash(hasher.finalize().into())))) @@ -529,7 +537,7 @@ fn run_and_hash_task( let outputs = collect_outputs(input_hash, task)?; - let layer = hash_layer(input_hash)?; + let layer = hash_layer(input_hash, task)?; move_layer(input_hash, &layer)?; Ok(TaskOutput { |