diff --git a/tools/hermit_proxy/src/daemon.rs b/tools/hermit_proxy/src/daemon.rs index 15dcb39d0..9e88ebf54 100644 --- a/tools/hermit_proxy/src/daemon.rs +++ b/tools/hermit_proxy/src/daemon.rs @@ -1,8 +1,12 @@ use std::os::unix::net::{UnixStream, UnixListener}; use std::path::Path; +use std::result; use std::thread; +use log; +use log::{LogMetadata, LogRecord, SetLoggerError, LogLevel, LogLevelFilter}; use nix::unistd::{fork, ForkResult}; use hermit::Isle; +use std::sync::RwLock; use std::io::Write; use std::io::Read; use bincode::{serialize, deserialize, Infinite}; @@ -11,9 +15,40 @@ use hermit::IsleParameter; use hermit::qemu::QEmu; use hermit::multi::Multi; use hermit::uhyve::Uhyve; -use hermit::error::Result; +use hermit::error::{Result,Error}; use chrono::{DateTime,Local}; +thread_local!{ + static LOGS: RwLock> = RwLock::new(Vec::new()); +} + +struct LocalLogger; + +impl log::Log for LocalLogger { + fn enabled(&self, metadata: &LogMetadata) -> bool { + true + } + + fn log(&self, record: &LogRecord) { + + LOGS.with(|f| { + let mut writable = f.write().unwrap(); + + writable.push(Log { time: Local::now(), level: LogCoverage::Intern, text: format!("{}", record.args()) }); + }); + + } +} + +impl LocalLogger { + pub fn init() -> result::Result<(), SetLoggerError> { + log::set_logger(|max_level| { + max_level.set(LogLevelFilter::Trace); + Box::new(LocalLogger) + }) + } +} + pub struct Connection { pub socket: UnixStream } @@ -68,21 +103,28 @@ pub enum ActionResult { KillDaemon(Result<()>) } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum LogCoverage { + All, + Communication, + Intern +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Log { pub time: DateTime, - pub action: Action + pub level: LogCoverage, + pub text: String } struct State { isles: Vec>, - specs: Vec, - logs: Vec + specs: Vec } impl State { pub fn new() -> State { - State { isles: Vec::new(), logs: Vec::new(), specs: Vec::new() } + State { isles: Vec::new(), specs: Vec::new() } } pub fn create_isle(&mut self, path: String, specs: IsleParameter) -> Result { @@ -94,7 +136,6 @@ impl State { IsleParameter::Multi{ mem_size, num_cpus } => Box::new(Multi::new(0, &path, mem_size, num_cpus)?) }; - isle.wait_until_available()?; isle.run()?; self.isles.push(isle); @@ -107,18 +148,31 @@ impl State { } pub fn log(&self) -> Vec { - self.logs.clone() + let mut logs = Vec::new(); + LOGS.with(|f| { + logs = (*f.read().unwrap()).to_vec(); + }); + + logs } pub fn add_log(&mut self, action: Action) { - self.logs.push(Log { time: Local::now(), action: action }); + LOGS.with(|f| { + let mut writable = f.write().unwrap(); + + writable.push(Log { time: Local::now(), level: LogCoverage::Communication, text: format!("{:?}",action) }); + }); } pub fn stop_isle(&mut self, id: u32) -> Result { + self.exist_isle(id)?; + self.isles[id as usize].stop() } pub fn remove_isle(&mut self, id: u32) -> Result { + self.exist_isle(id)?; + if self.isles[id as usize].is_running()? { self.isles[id as usize].stop()?; } @@ -128,12 +182,28 @@ impl State { Ok(0) } + + fn log_isle(&self, id: u32) -> Result { + self.exist_isle(id)?; + + self.isles[id as usize].output() + } + + fn exist_isle(&self, id: u32) -> Result<()> { + if self.isles.len() > id as usize { + Ok(()) + } else { + Err(Error::WrongIsleNumber) + } + } } pub fn daemon_handler() { let mut state = State::new(); let mut buf = vec![0; 256]; + LocalLogger::init(); + let listener = UnixListener::bind("/tmp/hermit_daemon").unwrap(); //for stream in listener.incoming() { // match stream { @@ -156,7 +226,7 @@ pub fn daemon_handler() { Action::List => ActionResult::List(state.list()), Action::Log(id) => { match id { - Some(id) => ActionResult::IsleLog(state.isles[id as usize].output()), + Some(id) => ActionResult::IsleLog(state.log_isle(id)), None => ActionResult::Log(state.log()) } }, diff --git a/tools/hermit_proxy/src/hermit/error.rs b/tools/hermit_proxy/src/hermit/error.rs index d1dbb6837..123ace22b 100644 --- a/tools/hermit_proxy/src/hermit/error.rs +++ b/tools/hermit_proxy/src/hermit/error.rs @@ -17,7 +17,8 @@ pub enum Error { QEmu((String, String)), MissingBinary, Protocol(String), - ParseMemory + ParseMemory, + WrongIsleNumber } impl fmt::Debug for Error { @@ -38,7 +39,8 @@ impl fmt::Debug for Error { Error::QEmu((_, ref stderr)) => write!(f, "The qemu binary has encountered an error: {}", stderr), Error::MissingBinary => write!(f, "Please specify a binary."), Error::Protocol(ref err) => write!(f, "{}", err), - Error::ParseMemory => write!(f, "Couldn't parse the guest memory size from the environment") + Error::ParseMemory => write!(f, "Couldn't parse the guest memory size from the environment"), + Error::WrongIsleNumber => write!(f, "Unknown isle number") } } } diff --git a/tools/hermit_proxy/src/hermit/mod.rs b/tools/hermit_proxy/src/hermit/mod.rs index bf837f66c..3416502ba 100644 --- a/tools/hermit_proxy/src/hermit/mod.rs +++ b/tools/hermit_proxy/src/hermit/mod.rs @@ -141,7 +141,6 @@ pub trait Isle { ino.add_watch(Path::new(&log_path), watch_mask::MODIFY | watch_mask::CREATE).unwrap(); - let mut buffer = [0; 1024]; loop { if let Some(_) = ino.read_events(&mut buffer).unwrap().next() { diff --git a/tools/hermit_proxy/src/hermit/qemu.rs b/tools/hermit_proxy/src/hermit/qemu.rs index 07262e6a2..78823e44f 100644 --- a/tools/hermit_proxy/src/hermit/qemu.rs +++ b/tools/hermit_proxy/src/hermit/qemu.rs @@ -86,10 +86,10 @@ impl QEmu { args.push("host"); } - //if add.monitor { + if add.monitor { args.push("-monitor"); args.push(&monitor_str); - //} + } if add.should_debug { args.push("-s"); @@ -100,10 +100,7 @@ impl QEmu { args.push("dump"); } - /* - if hermit_env::verbose() != "0" { - debug!("Execute {} with args {:#?}", hermit_env::qemu_binary(), args); - }*/ + debug!("Execute {} with args {:#?}", add.binary, args); let mut cmd = Command::new(add.binary); diff --git a/tools/hermit_proxy/src/main.rs b/tools/hermit_proxy/src/main.rs index c75d697a0..a5227f671 100644 --- a/tools/hermit_proxy/src/main.rs +++ b/tools/hermit_proxy/src/main.rs @@ -5,10 +5,6 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -#[macro_use] -extern crate log; -extern crate env_logger; - #[macro_use] extern crate clap; @@ -27,6 +23,9 @@ extern crate chrono; #[macro_use] extern crate nix; +#[macro_use] +extern crate log; + mod hermit; mod daemon; @@ -38,18 +37,7 @@ use daemon::{Action, ActionResult}; use std::net::Shutdown; use chrono::DateTime; -extern fn exit(_:i32) { - panic!("Aborting .."); -} - fn main() { - // register a signal - /*let sig_action = signal::SigAction::new(signal::SigHandler::Handler(exit), signal::SaFlags::empty(), signal::SigSet::empty()); - unsafe { - signal::sigaction(signal::SIGINT, &sig_action).unwrap(); - signal::sigaction(signal::SIGTERM, &sig_action).unwrap(); - }*/ - let matches = clap_app!(HermitProxy => (version: "0.0.1") (author: "Lorenz Schmidt ") @@ -127,7 +115,7 @@ fn main() { let mut i = 0; println!("{0: <10} | {1: <10} | {2: <10}", "number", "time", "action"); for log in logs { - println!("{0: <10} | {1: <10} | {2: <10?}", i, log.time.to_string(), log.action); + println!("{0: <10} | {1: <10} | {2: <10?}", i, log.time.to_rfc3339(), log.text); i += 1; } } else if let ActionResult::IsleLog(content) = res { @@ -160,6 +148,11 @@ fn main() { Ok(id) => { let res = daemon.send(Action::RemoveIsle(id)); + if let ActionResult::RemoveIsle(Ok(_)) = res { + println!("Isle {} was successfully removed", id); + } else if let ActionResult::RemoveIsle(Err(err)) = res { + println!("Remove failed: {:?}", err); + } }, Err(_) => { println!("Invalid number!"); @@ -198,7 +191,6 @@ fn main() { env::set_var("HERMIT_APP_PORT",app_port); } - env_logger::init().unwrap(); let res = daemon.send(Action::CreateIsle( matches.value_of("file").unwrap().into(), IsleParameter::from_env()