2023-03-22 18:34:06 +00:00
// Code to handle the nebula worker
2023-03-21 17:00:01 +00:00
2023-03-30 14:43:09 +00:00
use std ::error ::Error ;
use std ::fs ;
2023-03-23 17:17:37 +00:00
use std ::sync ::mpsc ::{ Receiver , TryRecvError } ;
2023-03-30 16:13:29 +00:00
use std ::time ::{ Duration , SystemTime } ;
2023-03-30 14:43:09 +00:00
use log ::{ debug , error , info } ;
2023-03-30 16:28:34 +00:00
use crate ::config ::{ load_cdata , NebulaConfig , TFClientConfig } ;
2023-03-22 18:34:06 +00:00
use crate ::daemon ::ThreadMessageSender ;
2023-03-30 14:43:09 +00:00
use crate ::dirs ::get_nebulaconfig_file ;
use crate ::embedded_nebula ::run_embedded_nebula ;
2023-03-22 18:34:06 +00:00
pub enum NebulaWorkerMessage {
2023-03-29 22:44:46 +00:00
Shutdown ,
ConfigUpdated
2023-03-22 18:34:06 +00:00
}
2023-03-30 14:43:09 +00:00
fn insert_private_key ( instance : & str ) -> Result < ( ) , Box < dyn Error > > {
2023-03-30 16:13:29 +00:00
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
}
2023-03-30 14:43:09 +00:00
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 ) ? ;
2023-03-30 16:13:29 +00:00
config . pki . key = Some ( String ::from_utf8 ( key ) ? ) ;
2023-03-30 14:43:09 +00:00
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 ( ( ) )
}
2023-03-30 11:29:02 +00:00
pub fn nebulaworker_main ( _config : TFClientConfig , instance : String , _transmitter : ThreadMessageSender , rx : Receiver < NebulaWorkerMessage > ) {
2023-03-30 16:28:34 +00:00
let _cdata = match load_cdata ( & instance ) {
2023-03-30 11:29:02 +00:00
Ok ( data ) = > data ,
Err ( e ) = > {
error! ( " unable to load cdata: {} " , e ) ;
error! ( " nebula thread exiting with error " ) ;
return ;
}
} ;
2023-03-30 14:43:09 +00:00
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 " ) ;
2023-03-30 16:13:29 +00:00
let mut last_restart_time = SystemTime ::now ( ) ;
2023-03-30 11:29:02 +00:00
// dont need to save it, because we do not, in any circumstance, write to it
2023-03-23 17:17:37 +00:00
loop {
2023-03-30 16:13:29 +00:00
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 ( ) ;
}
}
2023-03-23 17:17:37 +00:00
match rx . try_recv ( ) {
Ok ( msg ) = > {
match msg {
NebulaWorkerMessage ::Shutdown = > {
info! ( " recv on command socket: shutdown, stopping " ) ;
2023-03-30 14:43:09 +00:00
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 " ) ;
2023-03-23 17:17:37 +00:00
break ;
2023-03-29 22:44:46 +00:00
} ,
NebulaWorkerMessage ::ConfigUpdated = > {
2023-03-30 14:43:09 +00:00
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 ;
}
} ;
2023-03-30 16:13:29 +00:00
last_restart_time = SystemTime ::now ( ) ;
2023-03-30 14:43:09 +00:00
debug! ( " nebula process restarted " ) ;
2023-03-23 17:17:37 +00:00
}
}
} ,
Err ( e ) = > {
match e {
TryRecvError ::Empty = > { }
TryRecvError ::Disconnected = > {
error! ( " nebulaworker command socket disconnected, shutting down to prevent orphaning " ) ;
break ;
}
}
}
}
}
2023-03-21 17:00:01 +00:00
}