mirror of
				https://github.com/edera-dev/krata.git
				synced 2025-11-03 23:29:39 +00:00 
			
		
		
		
	hypha: setup image as disk
This commit is contained in:
		@ -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