mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
New commands, QEmu awaits now the TCP connection
This commit is contained in:
parent
192b0c09fe
commit
18a589317f
5 changed files with 95 additions and 35 deletions
|
@ -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<Vec<Log>> = 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<Local>,
|
||||
pub action: Action
|
||||
pub level: LogCoverage,
|
||||
pub text: String
|
||||
}
|
||||
|
||||
struct State {
|
||||
isles: Vec<Box<Isle>>,
|
||||
specs: Vec<IsleParameter>,
|
||||
logs: Vec<Log>
|
||||
specs: Vec<IsleParameter>
|
||||
}
|
||||
|
||||
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<u32> {
|
||||
|
@ -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<Log> {
|
||||
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<i32> {
|
||||
self.exist_isle(id)?;
|
||||
|
||||
self.isles[id as usize].stop()
|
||||
}
|
||||
|
||||
pub fn remove_isle(&mut self, id: u32) -> Result<i32> {
|
||||
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<String> {
|
||||
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())
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <bytesnake@mailbox.org>")
|
||||
|
@ -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()
|
||||
|
|
Loading…
Add table
Reference in a new issue