Skip to content

Commit

Permalink
cleanup(image_builder): error handling with anyhow
Browse files Browse the repository at this point in the history
Signed-off-by: Mathias-Boulay <[email protected]>
  • Loading branch information
Mathias-Boulay authored and BioTheWolff committed Apr 23, 2024
1 parent 6521bf8 commit a36c948
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 53 deletions.
1 change: 1 addition & 0 deletions src/fs-gen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ serde_json = "1.0.115"
signal-hook = "0.3.17"
tar = "0.4.40"
validator = { version = "0.17.0", features = ["derive"] }
anyhow = "1.0.82"
120 changes: 67 additions & 53 deletions src/fs-gen/src/image_builder.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::{
fs::{self},
io::Result,
path::{Path, PathBuf},
sync::Arc,
thread,
};

use anyhow::{Context, Result};
use fuse_backend_rs::{
api::{filesystem::Layer, server::Server},
overlayfs::{config::Config, OverlayFs},
Expand All @@ -21,23 +21,30 @@ pub struct FuseServer {
type BoxedLayer = Box<dyn Layer<Inode = u64, Handle = u64> + Send + Sync>;

/// Initialiazes a passthrough fs for a given layer
/// a passthrough fs is just a dummy implementation to map to the physical disk
/// # Usage
/// ```
/// let passthrough_layer = new_passthroughfs_layer("/path/to/layer")
/// ```
fn new_passthroughfs_layer(rootdir: &str) -> Result<BoxedLayer> {
let mut config = passthrough::Config::default();
config.root_dir = String::from(rootdir);
// enable xattr
config.xattr = true;
config.do_import = true;
let fs = Box::new(PassthroughFs::<()>::new(config)?);
fs.import()?;
fs.import()
.with_context(|| format!("Failed to create the passthrough layer: {}", rootdir))?;
Ok(fs as BoxedLayer)
}

/// Ensure a destination folder is created
fn ensure_folder_created(output_folder: &Path) -> Result<()> {
//TODO if there is already a folder, change names/delete it beforehand ?
let _ = fs::create_dir(output_folder);
// TODO actually make sure it works
Ok(())
fs::create_dir(output_folder).with_context(|| {
format!(
"Failed to ensure folder creation: {}",
output_folder.to_string_lossy()
)
})
}

/// Merges all the layers into a single folder for further manipulation
Expand All @@ -50,35 +57,39 @@ pub fn merge_layer(blob_paths: &[PathBuf], output_folder: &Path) -> Result<()> {
// Stack all lower layers
let mut lower_layers = Vec::new();
for lower in blob_paths {
lower_layers.push(Arc::new(
new_passthroughfs_layer(lower.to_str().unwrap()).unwrap(),
));
lower_layers.push(Arc::new(new_passthroughfs_layer(&lower.to_string_lossy())?));
}

let mountpoint = Path::new("/tmp/cloudlet_internal");
let fs_name = "cloudlet_overlay";

let _ = ensure_folder_created(mountpoint);
let _ = ensure_folder_created(output_folder);
ensure_folder_created(mountpoint)?;
ensure_folder_created(output_folder)?;

// Setup the overlay fs config
let mut config = Config::default();
config.work = "/work".into();
config.mountpoint = output_folder.to_str().unwrap().into();
config.mountpoint = output_folder.to_string_lossy().into();
config.do_import = true;

let fs = OverlayFs::new(None, lower_layers, config).unwrap();
fs.import().unwrap();
let fs = OverlayFs::new(None, lower_layers, config)
.with_context(|| "Failed to construct the Overlay fs struct !".to_string())?;
fs.import()
.with_context(|| "Failed to initialize the overlay fs".to_string())?;

// Enable a fuse session to make the fs available
let mut se = FuseSession::new(mountpoint, fs_name, "", true).unwrap();
let mut se = FuseSession::new(mountpoint, fs_name, "", true)
.with_context(|| "Failed to construct the Fuse session")?;
se.set_allow_other(false);
se.mount().unwrap();
se.mount()
.with_context(|| "Failed to mount the overlay fs".to_string())?;

// Fuse session
let mut server = FuseServer {
server: Arc::new(Server::new(Arc::new(fs))),
ch: se.new_channel().unwrap(),
ch: se
.new_channel()
.with_context(|| "Failed to create a new channel".to_string())?,
};

let handle = thread::spawn(move || {
Expand All @@ -87,52 +98,55 @@ pub fn merge_layer(blob_paths: &[PathBuf], output_folder: &Path) -> Result<()> {

println!("copy starting !");
//So now we need to copy the files
let copy_res = dircpy::copy_dir(mountpoint, output_folder);
println!("copy finished ?, {:?}", copy_res);

// main thread
// let mut signals = Signals::new(TERM_SIGNALS).unwrap();
// for _sig in signals.forever() {
// break;
// }
dircpy::copy_dir(mountpoint, output_folder).with_context(|| {
format!(
"Failed to copy directories into the output folder: {}",
output_folder.to_string_lossy()
)
})?;
println!("copy finished");

// Unmount sessions so it can be re-used in later executions of the program
se.umount().unwrap();
se.wake().unwrap();
se.wake()
.with_context(|| "Failed to exit the fuse session".to_string())?;
se.umount()
.with_context(|| "Failed to unmount the fuse session".to_string())?;

let _ = handle.join();
Ok(()) // TODO proper error handling
Ok(())
}

impl FuseServer {
/// Run a loop to execute requests from the FUSE session
///
pub fn svc_loop(&mut self) -> Result<()> {
print!("entering server loop\n");
println!("entering server loop");
loop {
match self.ch.get_request() {
Ok(value) => {
if let Some((reader, writer)) = value {
if let Err(e) =
self.server
.handle_message(reader, writer.into(), None, None)
{
match e {
fuse_backend_rs::Error::EncodeMessage(_ebadf) => {
break;
}
_ => {
print!("Handling fuse message failed");
continue;
}
}
}
} else {
print!("fuse server exits");
let value = self
.ch
.get_request()
.with_context(|| "Failed to get message from fuse session".to_string())?;

if value.is_none() {
println!("fuse server exits");
break;
}

// Technically the unwrap is safe
let (reader, writer) = value.unwrap();

if let Err(e) = self
.server
.handle_message(reader, writer.into(), None, None)
{
match e {
fuse_backend_rs::Error::EncodeMessage(_ebadf) => {
break;
}
}
Err(err) => {
println!("{:?}", err);
break;
_ => {
print!("Handling fuse message failed");
continue;
}
}
}
}
Expand Down

0 comments on commit a36c948

Please sign in to comment.