diff --git a/tools/hermit_proxy/Cargo.toml b/tools/hermit_proxy/Cargo.toml index 5c1a8bdaa..ec59bdb38 100755 --- a/tools/hermit_proxy/Cargo.toml +++ b/tools/hermit_proxy/Cargo.toml @@ -17,7 +17,3 @@ serde = "1.*.*" chrono = { version = "0.4", features = ["serde"] } bincode = "0.8" serde_derive = "1.*.*" - -[dependencies.env_logger] -version = "0.3" -default-features = false diff --git a/tools/hermit_proxy/src/daemon.rs b/tools/hermit_proxy/src/daemon.rs index 8bc167149..fe3e38eb4 100644 --- a/tools/hermit_proxy/src/daemon.rs +++ b/tools/hermit_proxy/src/daemon.rs @@ -141,7 +141,7 @@ pub enum ActionResult { CreateIsle(Result), StopIsle(Result), RemoveIsle(Result), - Connect(Result<()>), + Connect, Log(Vec), IsleLog(Result), List(Vec<(Result, IsleParameter)>), @@ -220,8 +220,8 @@ impl State { 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()?; + if let Ok(true) = self.isles[id as usize].is_running() { + self.isles[id as usize].stop(); } self.isles.remove(id as usize); @@ -244,7 +244,7 @@ impl State { } } - fn add_endpoint(&mut self, id: u32, stream: Arc>) -> Result<()> { + fn add_endpoint(&mut self, id: u32, stream: UnixStream) -> Result<()> { self.exist_isle(id)?; self.isles[id as usize].add_endpoint(stream) @@ -261,51 +261,60 @@ pub fn daemon_handler() { for stream in listener.incoming() { match stream { Ok(mut stream) => { - let mut stream = Arc::new(Mutex::new(stream)); + //let mut stream = Arc::new(Mutex::new(stream)); loop { - //println!("READ"); - let nread = stream.lock().unwrap().read(&mut buf); - println!("{:?}", nread); - if let Ok(nread) = nread { - if nread > 0 { - let action:Action = deserialize(&buf).unwrap(); - - state.add_log(action.clone()); + let nread = stream.read(&mut buf); - let ret = match action { - Action::KillDaemon => { - fs::remove_file("/tmp/hermit_daemon").unwrap(); - break; - }, - Action::CreateIsle(path, specs) => ActionResult::CreateIsle(state.create_isle(path,specs)), - Action::List => ActionResult::List(state.list()), - Action::Connect(id) => { - let res = ActionResult::Connect(state.add_endpoint(id, stream.clone())); - let buf: Vec = serialize(&res, Infinite).unwrap(); - stream.lock().unwrap().write(&buf); - break; - }, - Action::Log(id) => { - match id { - Some(id) => ActionResult::IsleLog(state.log_isle(id)), - None => ActionResult::Log(state.log()) - } - }, - Action::StopIsle(id) => ActionResult::StopIsle(state.stop_isle(id)), - Action::RemoveIsle(id) => ActionResult::RemoveIsle(state.remove_isle(id)), - _ => { panic!(""); } - }; + if let Ok(nread) = nread { + if nread > 0 { + let action:Action = deserialize(&buf).unwrap(); + + state.add_log(action.clone()); - println!("WRITE"); - let buf: Vec = serialize(&ret, Infinite).unwrap(); - stream.lock().unwrap().write(&buf); + let ret = match action { + Action::KillDaemon => { + fs::remove_file("/tmp/hermit_daemon").unwrap(); + break; + }, + Action::CreateIsle(path, specs) => { + let id = state.create_isle(path,specs); + let buf: Vec = serialize(&ActionResult::CreateIsle(id.clone()), Infinite).unwrap(); + stream.write(&buf); + + if let Ok(id) = id { + state.add_endpoint(id, stream); + } + break; + }, + Action::List => ActionResult::List(state.list()), + Action::Connect(id) => { + let buf: Vec = serialize(&ActionResult::Connect, Infinite).unwrap(); + stream.write(&buf); + + state.add_endpoint(id, stream); + break; + }, + Action::Log(id) => { + match id { + Some(id) => ActionResult::IsleLog(state.log_isle(id)), + None => ActionResult::Log(state.log()) + } + }, + Action::StopIsle(id) => ActionResult::StopIsle(state.stop_isle(id)), + Action::RemoveIsle(id) => ActionResult::RemoveIsle(state.remove_isle(id)), + _ => { panic!(""); } + }; + + let buf = serialize(&ret, Infinite).unwrap(); + + stream.write(&buf); + } else { + break; + } } else { break; } - } else { - break; - } } }, Err(err) => { println!("ERR: {:?}", err); } diff --git a/tools/hermit_proxy/src/hermit/error.rs b/tools/hermit_proxy/src/hermit/error.rs index 123ace22b..12e66bc02 100644 --- a/tools/hermit_proxy/src/hermit/error.rs +++ b/tools/hermit_proxy/src/hermit/error.rs @@ -4,7 +4,7 @@ use errno::errno; pub type Result = result::Result; -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, Clone)] pub enum Error { InternalError, NotEnoughMemory, @@ -45,7 +45,7 @@ impl fmt::Debug for Error { } } -#[derive(Serialize, Deserialize,Debug)] +#[derive(Serialize, Deserialize,Debug,Clone)] pub enum NameIOCTL { GetVersion, CreateVM, diff --git a/tools/hermit_proxy/src/hermit/mod.rs b/tools/hermit_proxy/src/hermit/mod.rs index 5b8ca361e..875551bb7 100644 --- a/tools/hermit_proxy/src/hermit/mod.rs +++ b/tools/hermit_proxy/src/hermit/mod.rs @@ -56,9 +56,21 @@ impl IsleParameter { let num_cpus: u32 = env::var("HERMIT_CPUS").map(|x| x.parse().unwrap_or(1)).unwrap_or(1); match isle_kind.as_str() { - "qemu" | "QEmu" | "QEMU" => { + "multi" | "MULTI" | "Multi" => { + IsleParameter::Multi { + mem_size: mem_size, + num_cpus: num_cpus + } + }, + "uhyve" | "UHyve" | "UHYVE" => { + IsleParameter::UHyve { + mem_size: mem_size, + num_cpus: num_cpus + } + }, + _ => { let binary = env::var("HERMIT_BINARY").unwrap_or("qemu-system-x86_64".into()); - let kvm = env::var("HERMIT_KVM").map(|x| x.parse().unwrap_or(false)).unwrap_or(false); + let kvm = env::var("HERMIT_KVM").map(|x| x.parse().unwrap_or(true)).unwrap_or(true); let monitor = env::var("HERMIT_MONITOR").map(|x| x.parse().unwrap_or(false)).unwrap_or(false); let capture_net = env::var("HERMIT_CAPTURE_NET").map(|x| x.parse().unwrap_or(false)).unwrap_or(false); let port = env::var("HERMIT_PORT").map(|x| x.parse().unwrap_or(18766)).unwrap_or(18766); @@ -78,20 +90,7 @@ impl IsleParameter { should_debug: debug } } - }, - "multi" | "MULTI" | "Multi" => { - IsleParameter::Multi { - mem_size: mem_size, - num_cpus: num_cpus - } - }, - "uhyve" | "UHyve" | "UHYVE" => { - IsleParameter::UHyve { - mem_size: mem_size, - num_cpus: num_cpus - } - }, - _ => { panic!(""); } + } } } } @@ -109,7 +108,7 @@ pub trait Isle { fn is_running(&mut self) -> Result; - fn add_endpoint(&mut self, stream: Arc>) -> Result<()>; + fn add_endpoint(&mut self, stream: UnixStream) -> Result<()>; fn is_available(&self) -> Result { let log = match self.log_file() { diff --git a/tools/hermit_proxy/src/hermit/multi.rs b/tools/hermit_proxy/src/hermit/multi.rs index 9ca1599a9..1beb81eca 100644 --- a/tools/hermit_proxy/src/hermit/multi.rs +++ b/tools/hermit_proxy/src/hermit/multi.rs @@ -108,7 +108,7 @@ impl Isle for Multi { Ok(true) } - fn add_endpoint(&mut self, stream: Arc>) -> Result<()> { + fn add_endpoint(&mut self, stream: UnixStream) -> Result<()> { Ok(()) } } diff --git a/tools/hermit_proxy/src/hermit/qemu.rs b/tools/hermit_proxy/src/hermit/qemu.rs index 1a3b50a3a..3f1dad545 100644 --- a/tools/hermit_proxy/src/hermit/qemu.rs +++ b/tools/hermit_proxy/src/hermit/qemu.rs @@ -61,11 +61,13 @@ impl QEmu { let num_cpus = num_cpus.to_string(); let mem_size = format!("{}B", mem_size); - let exe = env::current_exe().unwrap(); + /*let exe = env::current_exe().unwrap(); let name = exe.to_str().unwrap(); let exe_path = name.split("/").take(name.matches('/').count()).collect::>().join("/"); let exe = format!("{}/ldhermit.elf", exe_path); +*/ + let exe: String = "/opt/hermit/bin/ldhermit.elf".into(); let mut port_str; @@ -202,7 +204,7 @@ impl Isle for QEmu { Ok(state == "VM status: running") } - fn add_endpoint(&mut self, stream: Arc>) -> Result<()> { + fn add_endpoint(&mut self, stream: UnixStream) -> Result<()> { self.console.lock().unwrap().push(stream); Ok(()) diff --git a/tools/hermit_proxy/src/hermit/socket.rs b/tools/hermit_proxy/src/hermit/socket.rs index 8a20166e0..b87b2ecc6 100644 --- a/tools/hermit_proxy/src/hermit/socket.rs +++ b/tools/hermit_proxy/src/hermit/socket.rs @@ -1,5 +1,5 @@ use std::net::TcpStream; -use std::env; +use std::{env, slice}; use std::mem::transmute; use std::io::{Write, Read, Cursor}; use std::ffi::CString; @@ -21,7 +21,7 @@ use libc; const HERMIT_MAGIC: u32 = 0x7E317; -pub type Console = Arc>>>>; +pub type Console = Arc>>; #[derive(Debug)] pub struct Socket { @@ -118,27 +118,25 @@ impl Socket { match packet { Packet::Exit { arg } => break 'main, Packet::Write { fd, buf } => { - let buf_ret: [u8;8] = transmute(libc::write(fd as i32, buf.as_ptr() as *const libc::c_void, buf.len()).to_le()); - - if fd == 1 { - let ret = ActionResult::Output(String::from_utf8_unchecked(buf)); - let buf: Vec = serialize(&ret, Infinite).unwrap(); - - for stream in self.console.lock().unwrap().iter_mut() { - stream.lock().unwrap().write(&buf).unwrap(); - } - //stdout.push_str(&String::from_utf8_unchecked(buf)); - } else if fd == 2 { - let ret = ActionResult::OutputErr(String::from_utf8_unchecked(buf)); - let buf: Vec = serialize(&ret, Infinite).unwrap(); - - for stream in self.console.lock().unwrap().iter_mut() { - stream.lock().unwrap().write(&buf).unwrap(); - } - //stderr.push_str(&String::from_utf8_unchecked(buf)); + let mut buf_ret: [u8; 8]; + if fd != 1 && fd != 2 { + buf_ret = transmute(libc::write(fd as i32, buf.as_ptr() as *const libc::c_void, buf.len()).to_le()); } else { - stream.write(&buf_ret); + let res = match fd { + 1 => ActionResult::Output(String::from_utf8_unchecked(buf)), + 2 => ActionResult::OutputErr(String::from_utf8_unchecked(buf)), + _ => unreachable!() + }; + + let buf: Vec = serialize(&res, Infinite).unwrap(); + for stream in self.console.lock().unwrap().iter_mut() { + stream.write(&buf).unwrap(); + } + + buf_ret = transmute(buf.len()); } + + stream.write(&buf_ret); }, Packet::Open { name, mode, flags } => { let buf: [u8; 4] = transmute(libc::open(name.as_ptr(), flags as i32, mode as i32).to_le()); diff --git a/tools/hermit_proxy/src/hermit/uhyve/proto.rs b/tools/hermit_proxy/src/hermit/uhyve/proto.rs index b4243519a..62df90606 100644 --- a/tools/hermit_proxy/src/hermit/uhyve/proto.rs +++ b/tools/hermit_proxy/src/hermit/uhyve/proto.rs @@ -1,8 +1,8 @@ use libc::{write, read, lseek, exit, open, close, c_int, c_void, c_char}; use super::kvm_header::{kvm_run, KVM_EXIT_IO, KVM_EXIT_HLT, KVM_EXIT_MMIO,KVM_EXIT_FAIL_ENTRY, KVM_EXIT_INTERNAL_ERROR, KVM_EXIT_SHUTDOWN }; use std::ffi::CStr; -use std::ffi::CString; use bincode::{serialize, Infinite}; +use std::slice; use super::{Error, Result}; use hermit::socket::Console; @@ -58,7 +58,7 @@ pub enum Syscall { Close(*mut Close), Read(*mut Read), LSeek(*mut LSeek), - Exit(*mut isize), + Exit(*mut i32), Other(*const kvm_run) } @@ -88,7 +88,7 @@ impl Syscall { PORT_CLOSE => { Syscall::Close(guest_mem.offset(offset) as *mut Close) }, PORT_OPEN => { Syscall::Open (guest_mem.offset(offset) as *mut Open ) }, PORT_LSEEK => { Syscall::LSeek(guest_mem.offset(offset) as *mut LSeek) }, - PORT_EXIT => { Syscall::Exit( guest_mem.offset(offset) as *mut isize) }, + PORT_EXIT => { Syscall::Exit( guest_mem.offset(offset) as *mut i32) }, _ => { panic!("KVM: unhandled KVM_EXIT_IO at port 0x{}, direction {}", run.__bindgen_anon_1.io.port, run.__bindgen_anon_1.io.direction); } } } @@ -96,29 +96,36 @@ impl Syscall { } pub unsafe fn run(&self, guest_mem: *mut u8, console: Console) -> Result { - debug!("{:?}", *self); + println!("{:?}", *self); match *self { Syscall::Write(obj) => { - if (*obj).fd == 1 { - use std::io::Write; - - let cstr = CString::from_raw((*obj).buf as *mut c_char); - let ret = ActionResult::Output(cstr.into_string().unwrap_or("".into())); + use std::io::Write; + + if (*obj).fd != 1 && (*obj).fd != 2 { + (*obj).length = write((*obj).fd, guest_mem.offset((*obj).buf) as *const c_void, (*obj).length as usize); + } else { + let tmp = slice::from_raw_parts(guest_mem.offset((*obj).buf) as *const u8, (*obj).length as usize); + let content = String::from_utf8_unchecked(tmp.into()); + + let ret = match (*obj).fd { + 1 => ActionResult::Output(content), + 2 => ActionResult::OutputErr(content), + _ => unreachable!() + }; + let buf: Vec = serialize(&ret, Infinite).unwrap(); for stream in console.lock().unwrap().iter_mut() { - stream.lock().unwrap().write(&buf).unwrap(); + stream.write(&buf).unwrap(); } - } else if (*obj).fd == 2 { } - (*obj).length = write((*obj).fd, guest_mem.offset((*obj).buf) as *const c_void, (*obj).length as usize); }, Syscall::Read(obj) => { (*obj).ret = read((*obj).fd, guest_mem.offset((*obj).buf) as *mut c_void, (*obj).len); }, Syscall::Exit(obj) => { - return Ok(Return::Exit(*((guest_mem as *mut i32).offset((*obj) as isize)))); + return Ok(Return::Exit(*(guest_mem.offset((*obj) as isize)) as i32)); }, Syscall::Open(obj) => { (*obj).ret = open(guest_mem.offset((*obj).name) as *const i8, (*obj).flags, (*obj).mode); diff --git a/tools/hermit_proxy/src/hermit/uhyve/uhyve.rs b/tools/hermit_proxy/src/hermit/uhyve/uhyve.rs index 90b05c39d..72a96468d 100644 --- a/tools/hermit_proxy/src/hermit/uhyve/uhyve.rs +++ b/tools/hermit_proxy/src/hermit/uhyve/uhyve.rs @@ -164,7 +164,7 @@ impl Isle for Uhyve { self.vm.is_running() } - fn add_endpoint(&mut self, stream: Arc>) -> Result<()> { + fn add_endpoint(&mut self, stream: UnixStream) -> Result<()> { self.console.lock().unwrap().push(stream); Ok(()) diff --git a/tools/hermit_proxy/src/hermit/uhyve/vcpu.rs b/tools/hermit_proxy/src/hermit/uhyve/vcpu.rs index 836d4a30d..54120cda8 100644 --- a/tools/hermit_proxy/src/hermit/uhyve/vcpu.rs +++ b/tools/hermit_proxy/src/hermit/uhyve/vcpu.rs @@ -236,15 +236,21 @@ impl VirtualCPU { match VirtualCPU::single_run(fd, &state) { Ok(proto::Return::Exit(code)) => { state.running_state.store(false, Ordering::Relaxed); + + println!("exit {}", code); return ExitCode::Cause(Ok(code)); }, Err(err) => { state.running_state.store(false, Ordering::Relaxed); + + println!("error {:?}", err); return ExitCode::Cause(Err(err)); }, - _ => {} + _ => { + println!("RUN"); + } } } diff --git a/tools/hermit_proxy/src/main.rs b/tools/hermit_proxy/src/main.rs index e68c7b702..5c36a40e5 100644 --- a/tools/hermit_proxy/src/main.rs +++ b/tools/hermit_proxy/src/main.rs @@ -30,7 +30,7 @@ mod hermit; mod daemon; use nix::sys::signal; -use std::env; +use std::{env, fs}; use hermit::{IsleParameter, error}; use daemon::{Action, ActionResult}; @@ -128,7 +128,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_rfc3339(), log.text); + println!("{0: <10} | {1: <10} | {2: <10?}", i, log.time.format("%H:%M:%S"), log.text); i += 1; } } else if let ActionResult::IsleLog(content) = res { @@ -178,10 +178,8 @@ fn main() { Ok(id) => { let res = daemon.send(Action::Connect(id)); - if let ActionResult::Connect(Ok(_)) = res { + if let ActionResult::Connect = res { daemon.output(); - } else if let ActionResult::Connect(Err(err)) = res { - println!("Connect failed: {:?}", err); } }, Err(_) => { @@ -221,11 +219,18 @@ fn main() { env::set_var("HERMIT_APP_PORT",app_port); } + let relative_path: String = matches.value_of("file").unwrap().into(); + let path = fs::canonicalize(relative_path).unwrap(); + let res = daemon.send(Action::CreateIsle( - matches.value_of("file").unwrap().into(), + path.to_str().unwrap().into(), IsleParameter::from_env() )); + if let ActionResult::CreateIsle(_) = res { + daemon.output(); + } + println!("Created Isle with number: {:?}", res); } }