Implement launching a local daemon (#261)
Allow AppImage and non-systemd systems to launch a local burrow daemon.
This commit is contained in:
parent
c4c342dc8b
commit
c755f752a0
9 changed files with 192 additions and 27 deletions
111
burrow-gtk/src/components/settings/daemon_group.rs
Normal file
111
burrow-gtk/src/components/settings/daemon_group.rs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue