diff --git a/appmgr/src/disks.rs b/appmgr/src/disks.rs index 47efe7191..38e4dc709 100644 --- a/appmgr/src/disks.rs +++ b/appmgr/src/disks.rs @@ -1,10 +1,11 @@ use std::path::Path; +use failure::ResultExt as _; use futures::future::try_join_all; use crate::util::Invoke; use crate::Error; -use crate::ResultExt; +use crate::ResultExt as _; pub const FSTAB: &'static str = "/etc/fstab"; @@ -153,6 +154,11 @@ pub async fn bind, P1: AsRef>( dst: P1, read_only: bool, ) -> Result<(), Error> { + log::info!( + "Binding {} to {}", + src.as_ref().display(), + dst.as_ref().display() + ); let is_mountpoint = tokio::process::Command::new("mountpoint") .arg(dst.as_ref()) .stdout(std::process::Stdio::null()) @@ -185,6 +191,7 @@ pub async fn bind, P1: AsRef>( } pub async fn unmount>(mount_point: P) -> Result<(), Error> { + log::info!("Unmounting {}.", mount_point.as_ref().display()); let umount_output = tokio::process::Command::new("umount") .arg(mount_point.as_ref()) .output() @@ -192,10 +199,14 @@ pub async fn unmount>(mount_point: P) -> Result<(), Error> { crate::ensure_code!( umount_output.status.success(), crate::error::FILESYSTEM_ERROR, - "Error Unmounting Drive: {}", + "Error Unmounting Drive: {}: {}", + mount_point.as_ref().display(), std::str::from_utf8(&umount_output.stderr).unwrap_or("Unknown Error") ); - tokio::fs::remove_dir_all(mount_point.as_ref()).await?; + tokio::fs::remove_dir_all(mount_point.as_ref()) + .await + .with_context(|e| format!("rm {}: {}", mount_point.as_ref().display(), e)) + .with_code(crate::error::FILESYSTEM_ERROR)?; Ok(()) } diff --git a/appmgr/src/remove.rs b/appmgr/src/remove.rs index 9a4039129..416ce9f66 100644 --- a/appmgr/src/remove.rs +++ b/appmgr/src/remove.rs @@ -1,9 +1,11 @@ +use crate::failure::ResultExt; use std::path::Path; use linear_map::LinearMap; use crate::dependencies::{DependencyError, TaggedDependencyError}; use crate::Error; +use crate::ResultExt as _; pub async fn remove( name: &str, @@ -55,76 +57,79 @@ pub async fn remove( log::info!("Removing tor hidden service."); crate::tor::rm_svc(name).await?; log::info!("Removing app metadata."); - tokio::fs::remove_dir_all(Path::new(crate::PERSISTENCE_DIR).join("apps").join(name)) - .await?; - log::info!("Destroying mounted volume."); + let metadata_path = Path::new(crate::PERSISTENCE_DIR).join("apps").join(name); + tokio::fs::remove_dir_all(&metadata_path) + .await + .with_context(|e| format!("rm {}: {}", metadata_path.display(), e)) + .with_code(crate::error::FILESYSTEM_ERROR)?; log::info!("Unbinding shared filesystem."); - for (dep, info) in manifest.dependencies.0.iter() { - if crate::apps::list_info().await?.contains_key(dep) { + let installed_apps = crate::apps::list_info().await?; + for (dep, _) in manifest.dependencies.0.iter() { + let path = Path::new(crate::VOLUMES) + .join(name) + .join("start9") + .join("public") + .join(&dep); + if path.exists() { + crate::disks::unmount(&path).await?; + } else { + log::warn!("{} does not exist, skipping...", path.display()); + } + let path = Path::new(crate::VOLUMES) + .join(name) + .join("start9") + .join("shared") + .join(&dep); + if path.exists() { + crate::disks::unmount(&path).await?; + } else { + log::warn!("{} does not exist, skipping...", path.display()); + } + if installed_apps.contains_key(dep) { let dep_man = crate::apps::manifest(dep).await?; - if info.mount_public && dep_man.public.is_some() { - let path = Path::new(crate::VOLUMES) - .join(name) - .join("start9") - .join("public") - .join(&dep); + if let Some(shared) = dep_man.shared { + let path = Path::new(crate::VOLUMES).join(dep).join(&shared).join(name); if path.exists() { - crate::disks::unmount(&path).await?; - } - } - if info.mount_shared { - if let Some(shared) = dep_man.shared { - let path = Path::new(crate::VOLUMES) - .join(name) - .join("start9") - .join("shared") - .join(&dep); - if path.exists() { - crate::disks::unmount(&path).await?; - } - let path = Path::new(crate::VOLUMES).join(dep).join(&shared).join(name); - if path.exists() { - tokio::fs::remove_dir_all( - Path::new(crate::VOLUMES).join(dep).join(&shared).join(name), - ) - .await?; - } + tokio::fs::remove_dir_all(&path) + .await + .with_context(|e| format!("rm {}: {}", path.display(), e)) + .with_code(crate::error::FILESYSTEM_ERROR)?; } } + } else { + log::warn!("{} is not installed, skipping...", dep); } } if manifest.public.is_some() || manifest.shared.is_some() { - for dependent in crate::apps::dependents(&manifest.id, false).await? { - if let Some(info) = crate::apps::manifest(&dependent) - .await? - .dependencies - .0 - .get(&manifest.id) - { - if info.mount_public && manifest.public.is_some() { - let path = Path::new(crate::VOLUMES) - .join(name) - .join("start9") - .join("public") - .join(&manifest.id); - if path.exists() { - crate::disks::unmount(&path).await?; - } - } - if info.mount_shared && manifest.shared.is_some() { - let path = Path::new(crate::VOLUMES) - .join(name) - .join("start9") - .join("shared") - .join(&manifest.id); - if path.exists() { - crate::disks::unmount(&path).await?; - } - } + for dependent in crate::apps::dependents(name, false).await? { + let path = Path::new(crate::VOLUMES) + .join(&dependent) + .join("start9") + .join("public") + .join(name); + if path.exists() { + crate::disks::unmount(&path).await?; + } else { + log::warn!("{} does not exist, skipping...", path.display()); + } + let path = Path::new(crate::VOLUMES) + .join(dependent) + .join("start9") + .join("shared") + .join(name); + if path.exists() { + crate::disks::unmount(&path).await?; + } else { + log::warn!("{} does not exist, skipping...", path.display()); } } } - tokio::fs::remove_dir_all(Path::new(crate::VOLUMES).join(name)).await?; + log::info!("Destroying mounted volume."); + let volume_path = Path::new(crate::VOLUMES).join(name); + tokio::fs::remove_dir_all(&volume_path) + .await + .with_context(|e| format!("rm {}: {}", volume_path.display(), e)) + .with_code(crate::error::FILESYSTEM_ERROR)?; log::info!("Pruning unused docker images."); crate::ensure_code!( std::process::Command::new("docker")