Implement launching a local daemon (#261)

Allow AppImage and non-systemd systems to launch a local burrow daemon.
This commit is contained in:
David Zhong 2024-03-09 17:52:59 -08:00 committed by GitHub
parent c4c342dc8b
commit c755f752a0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 192 additions and 27 deletions

View file

@ -0,0 +1,111 @@
use super::*;
use std::process::Command;
#[derive(Debug)]
pub struct DaemonGroup {
system_setup: SystemSetup,
daemon_client: Arc<Mutex<Option<DaemonClient>>>,
already_running: bool,
}
pub struct DaemonGroupInit {
pub daemon_client: Arc<Mutex<Option<DaemonClient>>>,
pub system_setup: SystemSetup,
}
#[derive(Debug)]
pub enum DaemonGroupMsg {
LaunchLocal,
DaemonStateChange,
}
#[relm4::component(pub, async)]
impl AsyncComponent for DaemonGroup {
type Init = DaemonGroupInit;
type Input = DaemonGroupMsg;
type Output = ();
type CommandOutput = ();
view! {
#[name(group)]
adw::PreferencesGroup {
#[watch]
set_sensitive:
(model.system_setup == SystemSetup::AppImage || model.system_setup == SystemSetup::Other) &&
!model.already_running,
set_title: "Local Daemon",
set_description: Some("Run Local Daemon"),
gtk::Button {
set_label: "Launch",
connect_clicked => DaemonGroupMsg::LaunchLocal
}
}
}
async fn init(
init: Self::Init,
root: Self::Root,
sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
// Should be impossible to panic here
let model = DaemonGroup {
system_setup: init.system_setup,
daemon_client: init.daemon_client.clone(),
already_running: init.daemon_client.lock().await.is_some(),
};
let widgets = view_output!();
AsyncComponentParts { model, widgets }
}
async fn update(
&mut self,
msg: Self::Input,
_sender: AsyncComponentSender<Self>,
_root: &Self::Root,
) {
match msg {
DaemonGroupMsg::LaunchLocal => {
let burrow_original_bin = std::env::vars()
.find(|(k, _)| k == "APPDIR")
.map(|(_, v)| v + "/usr/bin/burrow")
.unwrap_or("/usr/bin/burrow".to_owned());
let mut burrow_bin =
String::from_utf8(Command::new("mktemp").output().unwrap().stdout).unwrap();
burrow_bin.pop();
let privileged_spawn_script = format!(
r#"TEMP=$(mktemp -p /root)
cp {} $TEMP
chmod +x $TEMP
setcap CAP_NET_BIND_SERVICE,CAP_NET_ADMIN+eip $TEMP
mv $TEMP /tmp/burrow-detached-daemon"#,
burrow_original_bin
)
.replace('\n', "&&");
// TODO: Handle error condition
Command::new("pkexec")
.arg("sh")
.arg("-c")
.arg(privileged_spawn_script)
.arg(&burrow_bin)
.output()
.unwrap();
Command::new("/tmp/burrow-detached-daemon")
.env("RUST_LOG", "debug")
.arg("daemon")
.spawn()
.unwrap();
}
DaemonGroupMsg::DaemonStateChange => {
self.already_running = self.daemon_client.lock().await.is_some();
}
}
}
}

View file

@ -1,11 +1,10 @@
use super::*;
use diag::{StatusTernary, SystemSetup};
#[derive(Debug)]
pub struct DiagGroup {
daemon_client: Arc<Mutex<Option<DaemonClient>>>,
init_system: SystemSetup,
system_setup: SystemSetup,
service_installed: StatusTernary,
socket_installed: StatusTernary,
socket_enabled: StatusTernary,
@ -14,19 +13,20 @@ pub struct DiagGroup {
pub struct DiagGroupInit {
pub daemon_client: Arc<Mutex<Option<DaemonClient>>>,
pub system_setup: SystemSetup,
}
impl DiagGroup {
async fn new(daemon_client: Arc<Mutex<Option<DaemonClient>>>) -> Result<Self> {
let setup = SystemSetup::new();
let system_setup = SystemSetup::new();
let daemon_running = daemon_client.lock().await.is_some();
Ok(Self {
service_installed: setup.is_service_installed()?,
socket_installed: setup.is_socket_installed()?,
socket_enabled: setup.is_socket_enabled()?,
service_installed: system_setup.is_service_installed()?,
socket_installed: system_setup.is_socket_installed()?,
socket_enabled: system_setup.is_socket_enabled()?,
daemon_running,
init_system: setup,
system_setup,
daemon_client,
})
}
@ -52,7 +52,7 @@ impl AsyncComponent for DiagGroup {
adw::ActionRow {
#[watch]
set_title: &format!("Init System: {}", model.init_system)
set_title: &format!("System Type: {}", model.system_setup)
},
adw::ActionRow {
#[watch]

View file

@ -1,5 +1,8 @@
use super::*;
use diag::{StatusTernary, SystemSetup};
mod daemon_group;
mod diag_group;
pub use diag_group::{DiagGroup, DiagGroupInit};
pub use daemon_group::{DaemonGroup, DaemonGroupInit, DaemonGroupMsg};
pub use diag_group::{DiagGroup, DiagGroupInit, DiagGroupMsg};