mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 13:11:31 +00:00
hypha: setup image as disk
This commit is contained in:
@ -13,12 +13,14 @@ fn main() -> Result<(), XenClientError> {
|
||||
let initrd_path = args.get(2).expect("argument not specified");
|
||||
let mut client = XenClient::open()?;
|
||||
let config = DomainConfig {
|
||||
backend_domid: 0,
|
||||
name: "xenclient-test",
|
||||
max_vcpus: 1,
|
||||
mem_mb: 512,
|
||||
kernel_path: kernel_image_path.as_str(),
|
||||
initrd_path: initrd_path.as_str(),
|
||||
cmdline: "debug elevator=noop",
|
||||
disks: vec![],
|
||||
};
|
||||
let domid = client.create(&config)?;
|
||||
println!("created domain {}", domid);
|
||||
|
@ -16,7 +16,9 @@ use xencall::sys::CreateDomain;
|
||||
use xencall::{XenCall, XenCallError};
|
||||
use xenevtchn::EventChannelError;
|
||||
use xenstore::bus::XsdBusError;
|
||||
use xenstore::client::{XsPermissions, XsdClient, XsdInterface};
|
||||
use xenstore::client::{
|
||||
XsPermission, XsdClient, XsdInterface, XS_PERM_NONE, XS_PERM_READ, XS_PERM_READ_WRITE,
|
||||
};
|
||||
|
||||
pub struct XenClient {
|
||||
store: XsdClient,
|
||||
@ -78,13 +80,21 @@ impl From<EventChannelError> for XenClientError {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DomainDisk<'a> {
|
||||
pub vdev: &'a str,
|
||||
pub pdev: &'a str,
|
||||
pub writable: bool,
|
||||
}
|
||||
|
||||
pub struct DomainConfig<'a> {
|
||||
pub backend_domid: u32,
|
||||
pub name: &'a str,
|
||||
pub max_vcpus: u32,
|
||||
pub mem_mb: u64,
|
||||
pub kernel_path: &'a str,
|
||||
pub initrd_path: &'a str,
|
||||
pub cmdline: &'a str,
|
||||
pub disks: Vec<DomainDisk<'a>>,
|
||||
}
|
||||
|
||||
impl XenClient {
|
||||
@ -100,55 +110,71 @@ impl XenClient {
|
||||
..Default::default()
|
||||
};
|
||||
let domid = self.call.create_domain(domain)?;
|
||||
let backend_dom_path = self.store.get_domain_path(0)?;
|
||||
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 ro_perm = &[
|
||||
XsPermission {
|
||||
id: 0,
|
||||
perms: XS_PERM_NONE,
|
||||
},
|
||||
XsPermission {
|
||||
id: domid,
|
||||
perms: XS_PERM_READ,
|
||||
},
|
||||
];
|
||||
|
||||
let rw_perm = &[XsPermission {
|
||||
id: domid,
|
||||
perms: XS_PERM_READ_WRITE,
|
||||
}];
|
||||
|
||||
let no_perm = &[XsPermission {
|
||||
id: 0,
|
||||
perms: XS_PERM_NONE,
|
||||
}];
|
||||
|
||||
{
|
||||
let mut tx = self.store.transaction()?;
|
||||
|
||||
tx.rm(dom_path.as_str())?;
|
||||
tx.mknod(dom_path.as_str(), &ro_perm)?;
|
||||
tx.mknod(dom_path.as_str(), ro_perm)?;
|
||||
|
||||
tx.rm(vm_path.as_str())?;
|
||||
tx.mknod(vm_path.as_str(), &ro_perm)?;
|
||||
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.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!("{}/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", dom_path).as_str(), ro_perm)?;
|
||||
|
||||
tx.mknod(format!("{}/control/shutdown", dom_path).as_str(), &rw_perm)?;
|
||||
tx.mknod(format!("{}/control/shutdown", dom_path).as_str(), rw_perm)?;
|
||||
tx.mknod(
|
||||
format!("{}/control/feature-poweroff", dom_path).as_str(),
|
||||
&rw_perm,
|
||||
rw_perm,
|
||||
)?;
|
||||
tx.mknod(
|
||||
format!("{}/control/feature-reboot", dom_path).as_str(),
|
||||
&rw_perm,
|
||||
rw_perm,
|
||||
)?;
|
||||
tx.mknod(
|
||||
format!("{}/control/feature-suspend", dom_path).as_str(),
|
||||
&rw_perm,
|
||||
rw_perm,
|
||||
)?;
|
||||
tx.mknod(format!("{}/control/sysrq", 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.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(),
|
||||
@ -156,7 +182,6 @@ impl XenClient {
|
||||
)?;
|
||||
tx.write_string(format!("{}/name", dom_path).as_str(), config.name)?;
|
||||
tx.write_string(format!("{}/name", vm_path).as_str(), config.name)?;
|
||||
tx.write_string(format!("{}/type", libxl_path).as_str(), "pv")?;
|
||||
tx.commit()?;
|
||||
}
|
||||
|
||||
@ -222,53 +247,192 @@ impl XenClient {
|
||||
&xenstore_mfn.to_string(),
|
||||
)?;
|
||||
for i in 0..config.max_vcpus {
|
||||
tx.write_string(
|
||||
format!("{}/cpu/{}/availability", dom_path, i).as_str(),
|
||||
"online",
|
||||
)?;
|
||||
let path = format!("{}/cpu/{}", dom_path, i);
|
||||
tx.mkdir(&path)?;
|
||||
tx.set_perms(&path, ro_perm)?;
|
||||
let path = format!("{}/cpu/{}/availability", dom_path, i);
|
||||
tx.write_string(&path, "online")?;
|
||||
tx.set_perms(&path, ro_perm)?;
|
||||
}
|
||||
tx.commit()?;
|
||||
}
|
||||
|
||||
self.console_device_add(&dom_path.to_string(), domid, console_evtchn, console_mfn)?;
|
||||
self.store
|
||||
.introduce_domain(domid, xenstore_mfn, xenstore_evtchn)?;
|
||||
if !self
|
||||
.store
|
||||
.introduce_domain(domid, xenstore_mfn, xenstore_evtchn)?
|
||||
{
|
||||
return Err(XenClientError::new("failed to introduce domain"));
|
||||
}
|
||||
self.console_device_add(
|
||||
&dom_path,
|
||||
&backend_dom_path,
|
||||
config.backend_domid,
|
||||
domid,
|
||||
console_evtchn,
|
||||
console_mfn,
|
||||
)?;
|
||||
for (index, disk) in config.disks.iter().enumerate() {
|
||||
self.disk_device_add(
|
||||
&dom_path,
|
||||
&backend_dom_path,
|
||||
config.backend_domid,
|
||||
domid,
|
||||
index,
|
||||
disk,
|
||||
)?;
|
||||
}
|
||||
self.call.unpause_domain(domid)?;
|
||||
|
||||
Ok(domid)
|
||||
}
|
||||
|
||||
fn disk_device_add(
|
||||
&mut self,
|
||||
dom_path: &str,
|
||||
backend_dom_path: &str,
|
||||
backend_domid: u32,
|
||||
domid: u32,
|
||||
index: usize,
|
||||
disk: &DomainDisk,
|
||||
) -> Result<(), XenClientError> {
|
||||
let id = (202 << 8) | (index << 4) as u64;
|
||||
let backend_items: Vec<(&str, String)> = vec![
|
||||
("frontend-id", domid.to_string()),
|
||||
("params", disk.pdev.to_string()),
|
||||
("script", "/etc/xen/scripts/block".to_string()),
|
||||
("online", "1".to_string()),
|
||||
("removable", "0".to_string()),
|
||||
("bootable", "1".to_string()),
|
||||
("state", "1".to_string()),
|
||||
("dev", disk.vdev.to_string()),
|
||||
("type", "phy".to_string()),
|
||||
("mode", if disk.writable { "w" } else { "r" }.to_string()),
|
||||
("device-type", "disk".to_string()),
|
||||
("discard-enable", "0".to_string()),
|
||||
("specification", "xen".to_string()),
|
||||
];
|
||||
|
||||
let frontend_items: Vec<(&str, String)> = vec![
|
||||
("backend-id", backend_domid.to_string()),
|
||||
("state", "1".to_string()),
|
||||
("virtual-device", id.to_string()),
|
||||
("device-type", "disk".to_string()),
|
||||
("trusted", "1".to_string()),
|
||||
("protocol", "x86_64-abi".to_string()),
|
||||
];
|
||||
|
||||
self.device_add(
|
||||
"vbd",
|
||||
id,
|
||||
dom_path,
|
||||
backend_dom_path,
|
||||
backend_domid,
|
||||
domid,
|
||||
frontend_items,
|
||||
backend_items,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn console_device_add(
|
||||
&mut self,
|
||||
dom_path: &String,
|
||||
dom_path: &str,
|
||||
backend_dom_path: &str,
|
||||
backend_domid: u32,
|
||||
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")?;
|
||||
let backend_entries = vec![
|
||||
("frontend-id", domid.to_string()),
|
||||
("online", "1".to_string()),
|
||||
("state", "1".to_string()),
|
||||
("protocol", "vt100".to_string()),
|
||||
];
|
||||
|
||||
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(),
|
||||
let frontend_entries = vec![
|
||||
("backend-id", backend_domid.to_string()),
|
||||
("limit", "1048576".to_string()),
|
||||
("type", "xenconsoled".to_string()),
|
||||
("output", "pty".to_string()),
|
||||
("tty", "".to_string()),
|
||||
("port", port.to_string()),
|
||||
("ring-ref", mfn.to_string()),
|
||||
];
|
||||
|
||||
self.device_add(
|
||||
"console",
|
||||
0,
|
||||
dom_path,
|
||||
backend_dom_path,
|
||||
backend_domid,
|
||||
domid,
|
||||
frontend_entries,
|
||||
backend_entries,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn device_add(
|
||||
&mut self,
|
||||
typ: &str,
|
||||
id: u64,
|
||||
dom_path: &str,
|
||||
backend_dom_path: &str,
|
||||
backend_domid: u32,
|
||||
domid: u32,
|
||||
frontend_items: Vec<(&str, String)>,
|
||||
backend_items: Vec<(&str, String)>,
|
||||
) -> Result<(), XenClientError> {
|
||||
let console_zero = typ == "console" && id == 0;
|
||||
|
||||
let frontend_path = if console_zero {
|
||||
format!("{}/console", dom_path)
|
||||
} else {
|
||||
format!("{}/device/{}/{}", dom_path, typ, id)
|
||||
};
|
||||
let backend_path = format!("{}/backend/{}/{}/{}", backend_dom_path, typ, domid, id);
|
||||
|
||||
let mut backend_items: Vec<(&str, String)> = backend_items.clone();
|
||||
let mut frontend_items: Vec<(&str, String)> = frontend_items.clone();
|
||||
backend_items.push(("frontend", frontend_path.clone()));
|
||||
frontend_items.push(("backend", backend_path.clone()));
|
||||
let frontend_perms = &[
|
||||
XsPermission {
|
||||
id: domid,
|
||||
perms: XS_PERM_NONE,
|
||||
},
|
||||
XsPermission {
|
||||
id: backend_domid,
|
||||
perms: XS_PERM_READ,
|
||||
},
|
||||
];
|
||||
|
||||
let backend_perms = &[
|
||||
XsPermission {
|
||||
id: backend_domid,
|
||||
perms: XS_PERM_NONE,
|
||||
},
|
||||
XsPermission {
|
||||
id: domid,
|
||||
perms: XS_PERM_READ,
|
||||
},
|
||||
];
|
||||
|
||||
let mut tx = self.store.transaction()?;
|
||||
tx.mknod(&frontend_path, frontend_perms)?;
|
||||
for (p, value) in &frontend_items {
|
||||
let path = format!("{}/{}", frontend_path, *p);
|
||||
tx.write_string(&path, value)?;
|
||||
if !console_zero {
|
||||
tx.set_perms(&path, frontend_perms)?;
|
||||
}
|
||||
}
|
||||
tx.mknod(&backend_path, backend_perms)?;
|
||||
for (p, value) in &backend_items {
|
||||
let path = format!("{}/{}", backend_path, *p);
|
||||
tx.write_string(&path, value)?;
|
||||
}
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
Reference in New Issue
Block a user