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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue