mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
Improved the connect command, fixed some bugs.
This commit is contained in:
parent
e2e625d847
commit
cb20bd1f5c
11 changed files with 132 additions and 110 deletions
|
@ -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
|
||||
|
|
|
@ -141,7 +141,7 @@ pub enum ActionResult {
|
|||
CreateIsle(Result<u32>),
|
||||
StopIsle(Result<i32>),
|
||||
RemoveIsle(Result<i32>),
|
||||
Connect(Result<()>),
|
||||
Connect,
|
||||
Log(Vec<Log>),
|
||||
IsleLog(Result<String>),
|
||||
List(Vec<(Result<bool>, IsleParameter)>),
|
||||
|
@ -220,8 +220,8 @@ impl State {
|
|||
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()?;
|
||||
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<Mutex<UnixStream>>) -> 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<u8> = 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<u8> = 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<u8> = 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<u8> = 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); }
|
||||
|
|
|
@ -4,7 +4,7 @@ use errno::errno;
|
|||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
#[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,
|
||||
|
|
|
@ -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<bool>;
|
||||
|
||||
fn add_endpoint(&mut self, stream: Arc<Mutex<UnixStream>>) -> Result<()>;
|
||||
fn add_endpoint(&mut self, stream: UnixStream) -> Result<()>;
|
||||
|
||||
fn is_available(&self) -> Result<bool> {
|
||||
let log = match self.log_file() {
|
||||
|
|
|
@ -108,7 +108,7 @@ impl Isle for Multi {
|
|||
Ok(true)
|
||||
}
|
||||
|
||||
fn add_endpoint(&mut self, stream: Arc<Mutex<UnixStream>>) -> Result<()> {
|
||||
fn add_endpoint(&mut self, stream: UnixStream) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<Vec<&str>>().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<Mutex<UnixStream>>) -> Result<()> {
|
||||
fn add_endpoint(&mut self, stream: UnixStream) -> Result<()> {
|
||||
self.console.lock().unwrap().push(stream);
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -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<Mutex<Vec<Arc<Mutex<UnixStream>>>>>;
|
||||
pub type Console = Arc<Mutex<Vec<UnixStream>>>;
|
||||
|
||||
#[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<u8> = 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<u8> = 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<u8> = 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());
|
||||
|
|
|
@ -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<Return> {
|
||||
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<u8> = 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);
|
||||
|
|
|
@ -164,7 +164,7 @@ impl Isle for Uhyve {
|
|||
self.vm.is_running()
|
||||
}
|
||||
|
||||
fn add_endpoint(&mut self, stream: Arc<Mutex<UnixStream>>) -> Result<()> {
|
||||
fn add_endpoint(&mut self, stream: UnixStream) -> Result<()> {
|
||||
self.console.lock().unwrap().push(stream);
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue