mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-04 05:31:32 +00:00
oh my god, we have a console
This commit is contained in:
@ -5,16 +5,19 @@ pub mod mem;
|
||||
pub mod sys;
|
||||
mod x86;
|
||||
|
||||
use crate::boot::BootSetup;
|
||||
use crate::create::DomainConfig;
|
||||
use crate::elfloader::ElfImageLoader;
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fs::read;
|
||||
use std::string::FromUtf8Error;
|
||||
use xencall::domctl::DomainControl;
|
||||
use uuid::Uuid;
|
||||
use xencall::sys::CreateDomain;
|
||||
use xencall::{XenCall, XenCallError};
|
||||
use xenevtchn::EventChannelError;
|
||||
use xenstore::bus::XsdBusError;
|
||||
use xenstore::client::{XsdClient, XsdInterface};
|
||||
use xenstore::client::{XsPermissions, XsdClient, XsdInterface};
|
||||
|
||||
pub struct XenClient {
|
||||
store: XsdClient,
|
||||
@ -83,29 +86,208 @@ impl XenClient {
|
||||
Ok(XenClient { store, call })
|
||||
}
|
||||
|
||||
pub fn create(&mut self, config: DomainConfig) -> Result<(), XenClientError> {
|
||||
let domctl = DomainControl::new(&self.call);
|
||||
let domid = domctl.create_domain(CreateDomain::default())?;
|
||||
let domain = self.store.get_domain_path(domid)?;
|
||||
let vm = self.store.read_string(format!("{}/vm", domain).as_str())?;
|
||||
pub fn create(&mut self, config: DomainConfig) -> Result<u32, XenClientError> {
|
||||
let domain = CreateDomain {
|
||||
max_vcpus: config.max_vcpus,
|
||||
..Default::default()
|
||||
};
|
||||
let domid = self.call.create_domain(domain)?;
|
||||
let dom_path = self.store.get_domain_path(domid)?;
|
||||
let uuid_string = Uuid::from_bytes(domain.handle).to_string();
|
||||
let vm_path = format!("/vm/{}", uuid_string);
|
||||
let libxl_path = format!("/libxl/{}", domid);
|
||||
|
||||
let ro_perm = XsPermissions { id: 0, perms: 0 };
|
||||
|
||||
let rw_perm = XsPermissions { id: 0, perms: 0 };
|
||||
|
||||
let no_perm = XsPermissions { id: 0, perms: 0 };
|
||||
|
||||
{
|
||||
let mut tx = self.store.transaction()?;
|
||||
|
||||
tx.rm(dom_path.as_str())?;
|
||||
tx.mknod(dom_path.as_str(), &ro_perm)?;
|
||||
|
||||
tx.rm(vm_path.as_str())?;
|
||||
tx.mknod(vm_path.as_str(), &ro_perm)?;
|
||||
|
||||
tx.rm(libxl_path.as_str())?;
|
||||
tx.mknod(vm_path.as_str(), &no_perm)?;
|
||||
tx.mknod(format!("{}/device", vm_path).as_str(), &no_perm)?;
|
||||
|
||||
tx.write_string(format!("{}/vm", dom_path).as_str(), &vm_path)?;
|
||||
|
||||
tx.mknod(format!("{}/cpu", dom_path).as_str(), &ro_perm)?;
|
||||
tx.mknod(format!("{}/memory", dom_path).as_str(), &ro_perm)?;
|
||||
|
||||
tx.mknod(format!("{}/control", dom_path).as_str(), &ro_perm)?;
|
||||
|
||||
tx.mknod(format!("{}/control/shutdown", dom_path).as_str(), &rw_perm)?;
|
||||
tx.mknod(
|
||||
format!("{}/control/feature-poweroff", dom_path).as_str(),
|
||||
&rw_perm,
|
||||
)?;
|
||||
tx.mknod(
|
||||
format!("{}/control/feature-reboot", dom_path).as_str(),
|
||||
&rw_perm,
|
||||
)?;
|
||||
tx.mknod(
|
||||
format!("{}/control/feature-suspend", dom_path).as_str(),
|
||||
&rw_perm,
|
||||
)?;
|
||||
tx.mknod(format!("{}/control/sysrq", dom_path).as_str(), &rw_perm)?;
|
||||
|
||||
tx.mknod(format!("{}/data", dom_path).as_str(), &rw_perm)?;
|
||||
tx.mknod(format!("{}/drivers", dom_path).as_str(), &rw_perm)?;
|
||||
tx.mknod(format!("{}/feature", dom_path).as_str(), &rw_perm)?;
|
||||
tx.mknod(format!("{}/attr", dom_path).as_str(), &rw_perm)?;
|
||||
tx.mknod(format!("{}/error", dom_path).as_str(), &rw_perm)?;
|
||||
|
||||
tx.write_string(
|
||||
format!("{}/uuid", vm_path).as_str(),
|
||||
&Uuid::from_bytes(domain.handle).to_string(),
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/name", vm_path).as_str(),
|
||||
"mycelium",
|
||||
)?;
|
||||
tx.write_string(format!("{}/type", libxl_path).as_str(), "pv")?;
|
||||
tx.commit()?;
|
||||
}
|
||||
|
||||
self.call.set_max_vcpus(domid, config.max_vcpus)?;
|
||||
self.call.set_max_mem(domid, config.mem_mb * 1024)?;
|
||||
let image_loader = ElfImageLoader::load_file_kernel(config.kernel_path.as_str())?;
|
||||
|
||||
let console_evtchn: u32;
|
||||
let xenstore_evtchn: u32;
|
||||
let console_mfn: u64;
|
||||
let xenstore_mfn: u64;
|
||||
|
||||
{
|
||||
let mut boot = BootSetup::new(&self.call, domid);
|
||||
let initrd = read(config.initrd_path.as_str())?;
|
||||
let mut state = boot.initialize(
|
||||
&image_loader,
|
||||
initrd.as_slice(),
|
||||
config.max_vcpus,
|
||||
config.mem_mb,
|
||||
)?;
|
||||
boot.boot(&mut state, config.cmdline.as_str())?;
|
||||
console_evtchn = state.console_evtchn;
|
||||
xenstore_evtchn = state.store_evtchn;
|
||||
console_mfn = boot.phys.p2m[state.console_segment.pfn as usize];
|
||||
xenstore_mfn = boot.phys.p2m[state.xenstore_segment.pfn as usize];
|
||||
}
|
||||
|
||||
{
|
||||
let mut tx = self.store.transaction()?;
|
||||
tx.write_string(
|
||||
format!("{}/image/os_type", vm_path).as_str(),
|
||||
"linux",
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/image/kernel", vm_path).as_str(),
|
||||
&config.kernel_path,
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/image/ramdisk", vm_path).as_str(),
|
||||
&config.initrd_path,
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/image/cmdline", vm_path).as_str(),
|
||||
&config.cmdline,
|
||||
)?;
|
||||
|
||||
tx.write_string(
|
||||
format!("{}/memory/static-max", dom_path).as_str(),
|
||||
&(config.mem_mb * 1024).to_string(),
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/memory/target", dom_path).as_str(),
|
||||
&(config.mem_mb * 1024).to_string(),
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/memory/videoram", dom_path).as_str(),
|
||||
"0",
|
||||
)?;
|
||||
tx.write_string(format!("{}/domid", dom_path).as_str(), &domid.to_string())?;
|
||||
tx.write_string(
|
||||
format!("{}/store/port", dom_path).as_str(),
|
||||
&xenstore_evtchn.to_string(),
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/store/ring-ref", dom_path).as_str(),
|
||||
&xenstore_mfn.to_string(),
|
||||
)?;
|
||||
for i in 0..config.max_vcpus {
|
||||
tx.write_string(
|
||||
format!("{}/cpu/{}/availability", dom_path, i).as_str(),
|
||||
"online",
|
||||
)?;
|
||||
}
|
||||
tx.commit()?;
|
||||
}
|
||||
|
||||
self.console_device_add(&dom_path.to_string(), domid, console_evtchn, console_mfn)?;
|
||||
self.store
|
||||
.introduce_domain(domid, xenstore_mfn, xenstore_evtchn)?;
|
||||
self.call.unpause_domain(domid)?;
|
||||
|
||||
Ok(domid)
|
||||
}
|
||||
|
||||
fn console_device_add(
|
||||
&mut self,
|
||||
dom_path: &String,
|
||||
domid: u32,
|
||||
port: u32,
|
||||
mfn: u64,
|
||||
) -> Result<(), XenClientError> {
|
||||
let frontend_path = format!("{}/console", dom_path);
|
||||
let backend_path = format!("{}/backend/console/{}/{}", dom_path, domid, 0);
|
||||
let mut tx = self.store.transaction()?;
|
||||
tx.write_string(
|
||||
format!("{}/frontend-id", backend_path).as_str(),
|
||||
&domid.to_string(),
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/online", backend_path).as_str(),
|
||||
"1",
|
||||
)?;
|
||||
tx.write_string(format!("{}/state", backend_path).as_str(), "1")?;
|
||||
tx.write_string(
|
||||
format!("{}/protocol", backend_path).as_str(),
|
||||
"vt100",
|
||||
)?;
|
||||
|
||||
for (key, value) in config.clone_domain_entries() {
|
||||
let path = format!("{}/{}", domain, key);
|
||||
tx.write(path.as_str(), value.into_bytes())?;
|
||||
}
|
||||
|
||||
let domid_path = format!("{}/domid", domain);
|
||||
tx.write(domid_path.as_str(), domid.to_string().into_bytes())?;
|
||||
|
||||
for (key, value) in config.clone_domain_entries() {
|
||||
let path = format!("{}/{}", vm, key);
|
||||
tx.write(path.as_str(), value.into_bytes())?;
|
||||
}
|
||||
|
||||
tx.write_string(
|
||||
format!("{}/backend-id", frontend_path).as_str(),
|
||||
"0",
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/limit", frontend_path).as_str(),
|
||||
"1048576",
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/type", frontend_path).as_str(),
|
||||
"xenconsoled",
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/output", frontend_path).as_str(),
|
||||
"pty",
|
||||
)?;
|
||||
tx.write_string(format!("{}/tty", frontend_path).as_str(), "")?;
|
||||
tx.write_string(
|
||||
format!("{}/port", frontend_path).as_str(),
|
||||
&port.to_string(),
|
||||
)?;
|
||||
tx.write_string(
|
||||
format!("{}/ring-ref", frontend_path).as_str(),
|
||||
&mfn.to_string(),
|
||||
)?;
|
||||
tx.commit()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user