153 lines
6.2 KiB
Rust
153 lines
6.2 KiB
Rust
// Code to handle the nebula worker
|
|
|
|
use std::error::Error;
|
|
use std::fs;
|
|
use std::sync::mpsc::{Receiver, TryRecvError};
|
|
use std::time::{Duration, SystemTime};
|
|
use log::{debug, error, info};
|
|
use crate::config::{load_cdata, NebulaConfig, TFClientConfig};
|
|
use crate::daemon::ThreadMessageSender;
|
|
use crate::dirs::get_nebulaconfig_file;
|
|
use crate::embedded_nebula::run_embedded_nebula;
|
|
|
|
pub enum NebulaWorkerMessage {
|
|
Shutdown,
|
|
ConfigUpdated
|
|
}
|
|
|
|
fn insert_private_key(instance: &str) -> Result<(), Box<dyn Error>> {
|
|
if !get_nebulaconfig_file(instance).ok_or("Could not get config file location")?.exists() {
|
|
return Ok(()); // cant insert private key into a file that does not exist - BUT. we can gracefully handle nebula crashing - we cannot gracefully handle this fn failing
|
|
}
|
|
let cdata = load_cdata(instance)?;
|
|
let key = cdata.dh_privkey.ok_or("Missing private key")?;
|
|
|
|
let config_str = fs::read_to_string(get_nebulaconfig_file(instance).ok_or("Could not get config file location")?)?;
|
|
let mut config: NebulaConfig = serde_yaml::from_str(&config_str)?;
|
|
|
|
config.pki.key = Some(String::from_utf8(key)?);
|
|
|
|
debug!("inserted private key into config: {:?}", config);
|
|
|
|
let config_str = serde_yaml::to_string(&config)?;
|
|
fs::write(get_nebulaconfig_file(instance).ok_or("Could not get config file location")?, config_str)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn nebulaworker_main(_config: TFClientConfig, instance: String, _transmitter: ThreadMessageSender, rx: Receiver<NebulaWorkerMessage>) {
|
|
let _cdata = match load_cdata(&instance) {
|
|
Ok(data) => data,
|
|
Err(e) => {
|
|
error!("unable to load cdata: {}", e);
|
|
error!("nebula thread exiting with error");
|
|
return;
|
|
}
|
|
};
|
|
|
|
info!("fixing config...");
|
|
match insert_private_key(&instance) {
|
|
Ok(_) => {
|
|
info!("config fixed (private-key embedded)");
|
|
},
|
|
Err(e) => {
|
|
error!("unable to fix config: {}", e);
|
|
error!("nebula thread exiting with error");
|
|
return;
|
|
}
|
|
}
|
|
info!("starting nebula child...");
|
|
let mut child = match run_embedded_nebula(&["-config".to_string(), get_nebulaconfig_file(&instance).unwrap().to_str().unwrap().to_string()]) {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
error!("unable to start embedded nebula binary: {}", e);
|
|
error!("nebula thread exiting with error");
|
|
return;
|
|
}
|
|
};
|
|
info!("nebula process started");
|
|
|
|
let mut last_restart_time = SystemTime::now();
|
|
|
|
// dont need to save it, because we do not, in any circumstance, write to it
|
|
loop {
|
|
if let Ok(e) = child.try_wait() {
|
|
if e.is_some() && SystemTime::now() > last_restart_time + Duration::from_secs(5) {
|
|
info!("nebula process has exited, restarting");
|
|
child = match run_embedded_nebula(&["-config".to_string(), get_nebulaconfig_file(&instance).unwrap().to_str().unwrap().to_string()]) {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
error!("unable to start embedded nebula binary: {}", e);
|
|
error!("nebula thread exiting with error");
|
|
return;
|
|
}
|
|
};
|
|
info!("nebula process started");
|
|
last_restart_time = SystemTime::now();
|
|
}
|
|
}
|
|
match rx.try_recv() {
|
|
Ok(msg) => {
|
|
match msg {
|
|
NebulaWorkerMessage::Shutdown => {
|
|
info!("recv on command socket: shutdown, stopping");
|
|
info!("shutting down nebula binary");
|
|
match child.kill() {
|
|
Ok(_) => {
|
|
debug!("nebula process exited");
|
|
},
|
|
Err(e) => {
|
|
error!("nebula process already exited: {}", e);
|
|
}
|
|
}
|
|
info!("nebula shut down");
|
|
break;
|
|
},
|
|
NebulaWorkerMessage::ConfigUpdated => {
|
|
info!("our configuration has been updated - restarting");
|
|
debug!("killing existing process");
|
|
match child.kill() {
|
|
Ok(_) => {
|
|
debug!("nebula process exited");
|
|
},
|
|
Err(e) => {
|
|
error!("nebula process already exited: {}", e);
|
|
}
|
|
}
|
|
debug!("fixing config...");
|
|
match insert_private_key(&instance) {
|
|
Ok(_) => {
|
|
debug!("config fixed (private-key embedded)");
|
|
},
|
|
Err(e) => {
|
|
error!("unable to fix config: {}", e);
|
|
error!("nebula thread exiting with error");
|
|
return;
|
|
}
|
|
}
|
|
debug!("restarting nebula process");
|
|
child = match run_embedded_nebula(&["-config".to_string(), get_nebulaconfig_file(&instance).unwrap().to_str().unwrap().to_string()]) {
|
|
Ok(c) => c,
|
|
Err(e) => {
|
|
error!("unable to start embedded nebula binary: {}", e);
|
|
error!("nebula thread exiting with error");
|
|
return;
|
|
}
|
|
};
|
|
last_restart_time = SystemTime::now();
|
|
debug!("nebula process restarted");
|
|
}
|
|
}
|
|
},
|
|
Err(e) => {
|
|
match e {
|
|
TryRecvError::Empty => {}
|
|
TryRecvError::Disconnected => {
|
|
error!("nebulaworker command socket disconnected, shutting down to prevent orphaning");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |