mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
Appmgr/debug/uninstall (#260)
* with context debuggging * appmgr: fix errors * appmgr: add more logging * appmgr: more logs * appmgr: make unbind more robust Co-authored-by: Aiden McClelland <me@drbonez.dev>
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use failure::ResultExt as _;
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
|
|
||||||
use crate::util::Invoke;
|
use crate::util::Invoke;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::ResultExt;
|
use crate::ResultExt as _;
|
||||||
|
|
||||||
pub const FSTAB: &'static str = "/etc/fstab";
|
pub const FSTAB: &'static str = "/etc/fstab";
|
||||||
|
|
||||||
@@ -153,6 +154,11 @@ pub async fn bind<P0: AsRef<Path>, P1: AsRef<Path>>(
|
|||||||
dst: P1,
|
dst: P1,
|
||||||
read_only: bool,
|
read_only: bool,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
log::info!(
|
||||||
|
"Binding {} to {}",
|
||||||
|
src.as_ref().display(),
|
||||||
|
dst.as_ref().display()
|
||||||
|
);
|
||||||
let is_mountpoint = tokio::process::Command::new("mountpoint")
|
let is_mountpoint = tokio::process::Command::new("mountpoint")
|
||||||
.arg(dst.as_ref())
|
.arg(dst.as_ref())
|
||||||
.stdout(std::process::Stdio::null())
|
.stdout(std::process::Stdio::null())
|
||||||
@@ -185,6 +191,7 @@ pub async fn bind<P0: AsRef<Path>, P1: AsRef<Path>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn unmount<P: AsRef<Path>>(mount_point: P) -> Result<(), Error> {
|
pub async fn unmount<P: AsRef<Path>>(mount_point: P) -> Result<(), Error> {
|
||||||
|
log::info!("Unmounting {}.", mount_point.as_ref().display());
|
||||||
let umount_output = tokio::process::Command::new("umount")
|
let umount_output = tokio::process::Command::new("umount")
|
||||||
.arg(mount_point.as_ref())
|
.arg(mount_point.as_ref())
|
||||||
.output()
|
.output()
|
||||||
@@ -192,10 +199,14 @@ pub async fn unmount<P: AsRef<Path>>(mount_point: P) -> Result<(), Error> {
|
|||||||
crate::ensure_code!(
|
crate::ensure_code!(
|
||||||
umount_output.status.success(),
|
umount_output.status.success(),
|
||||||
crate::error::FILESYSTEM_ERROR,
|
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")
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
use crate::failure::ResultExt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use linear_map::LinearMap;
|
use linear_map::LinearMap;
|
||||||
|
|
||||||
use crate::dependencies::{DependencyError, TaggedDependencyError};
|
use crate::dependencies::{DependencyError, TaggedDependencyError};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
use crate::ResultExt as _;
|
||||||
|
|
||||||
pub async fn remove(
|
pub async fn remove(
|
||||||
name: &str,
|
name: &str,
|
||||||
@@ -55,76 +57,79 @@ pub async fn remove(
|
|||||||
log::info!("Removing tor hidden service.");
|
log::info!("Removing tor hidden service.");
|
||||||
crate::tor::rm_svc(name).await?;
|
crate::tor::rm_svc(name).await?;
|
||||||
log::info!("Removing app metadata.");
|
log::info!("Removing app metadata.");
|
||||||
tokio::fs::remove_dir_all(Path::new(crate::PERSISTENCE_DIR).join("apps").join(name))
|
let metadata_path = Path::new(crate::PERSISTENCE_DIR).join("apps").join(name);
|
||||||
.await?;
|
tokio::fs::remove_dir_all(&metadata_path)
|
||||||
log::info!("Destroying mounted volume.");
|
.await
|
||||||
|
.with_context(|e| format!("rm {}: {}", metadata_path.display(), e))
|
||||||
|
.with_code(crate::error::FILESYSTEM_ERROR)?;
|
||||||
log::info!("Unbinding shared filesystem.");
|
log::info!("Unbinding shared filesystem.");
|
||||||
for (dep, info) in manifest.dependencies.0.iter() {
|
let installed_apps = crate::apps::list_info().await?;
|
||||||
if crate::apps::list_info().await?.contains_key(dep) {
|
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?;
|
let dep_man = crate::apps::manifest(dep).await?;
|
||||||
if info.mount_public && dep_man.public.is_some() {
|
if let Some(shared) = dep_man.shared {
|
||||||
let path = Path::new(crate::VOLUMES)
|
let path = Path::new(crate::VOLUMES).join(dep).join(&shared).join(name);
|
||||||
.join(name)
|
|
||||||
.join("start9")
|
|
||||||
.join("public")
|
|
||||||
.join(&dep);
|
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
crate::disks::unmount(&path).await?;
|
tokio::fs::remove_dir_all(&path)
|
||||||
}
|
.await
|
||||||
}
|
.with_context(|e| format!("rm {}: {}", path.display(), e))
|
||||||
if info.mount_shared {
|
.with_code(crate::error::FILESYSTEM_ERROR)?;
|
||||||
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?;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log::warn!("{} is not installed, skipping...", dep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if manifest.public.is_some() || manifest.shared.is_some() {
|
if manifest.public.is_some() || manifest.shared.is_some() {
|
||||||
for dependent in crate::apps::dependents(&manifest.id, false).await? {
|
for dependent in crate::apps::dependents(name, false).await? {
|
||||||
if let Some(info) = crate::apps::manifest(&dependent)
|
let path = Path::new(crate::VOLUMES)
|
||||||
.await?
|
.join(&dependent)
|
||||||
.dependencies
|
.join("start9")
|
||||||
.0
|
.join("public")
|
||||||
.get(&manifest.id)
|
.join(name);
|
||||||
{
|
if path.exists() {
|
||||||
if info.mount_public && manifest.public.is_some() {
|
crate::disks::unmount(&path).await?;
|
||||||
let path = Path::new(crate::VOLUMES)
|
} else {
|
||||||
.join(name)
|
log::warn!("{} does not exist, skipping...", path.display());
|
||||||
.join("start9")
|
}
|
||||||
.join("public")
|
let path = Path::new(crate::VOLUMES)
|
||||||
.join(&manifest.id);
|
.join(dependent)
|
||||||
if path.exists() {
|
.join("start9")
|
||||||
crate::disks::unmount(&path).await?;
|
.join("shared")
|
||||||
}
|
.join(name);
|
||||||
}
|
if path.exists() {
|
||||||
if info.mount_shared && manifest.shared.is_some() {
|
crate::disks::unmount(&path).await?;
|
||||||
let path = Path::new(crate::VOLUMES)
|
} else {
|
||||||
.join(name)
|
log::warn!("{} does not exist, skipping...", path.display());
|
||||||
.join("start9")
|
|
||||||
.join("shared")
|
|
||||||
.join(&manifest.id);
|
|
||||||
if path.exists() {
|
|
||||||
crate::disks::unmount(&path).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.");
|
log::info!("Pruning unused docker images.");
|
||||||
crate::ensure_code!(
|
crate::ensure_code!(
|
||||||
std::process::Command::new("docker")
|
std::process::Command::new("docker")
|
||||||
|
|||||||
Reference in New Issue
Block a user