mirror of
				https://github.com/edera-dev/krata.git
				synced 2025-11-03 23:29:39 +00:00 
			
		
		
		
	hypha: implement loop device support directly to avoid devd
This commit is contained in:
		
							
								
								
									
										36
									
								
								hypha/src/autoloop.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								hypha/src/autoloop.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
use crate::error::{HyphaError, Result};
 | 
			
		||||
use loopdev::{LoopControl, LoopDevice};
 | 
			
		||||
use std::path::Path;
 | 
			
		||||
use xenclient::BlockDeviceRef;
 | 
			
		||||
 | 
			
		||||
pub struct AutoLoop {
 | 
			
		||||
    control: LoopControl,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl AutoLoop {
 | 
			
		||||
    pub(crate) fn new(control: LoopControl) -> AutoLoop {
 | 
			
		||||
        AutoLoop { control }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn loopify(&self, file: &Path) -> Result<BlockDeviceRef> {
 | 
			
		||||
        let device = self.control.next_free()?;
 | 
			
		||||
        device.with().read_only(true).attach(file)?;
 | 
			
		||||
        let path = device
 | 
			
		||||
            .path()
 | 
			
		||||
            .ok_or(HyphaError::new("unable to get loop device path"))?
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .ok_or(HyphaError::new(
 | 
			
		||||
                "unable to convert loop device path to string",
 | 
			
		||||
            ))?
 | 
			
		||||
            .to_string();
 | 
			
		||||
        let major = device.major()?;
 | 
			
		||||
        let minor = device.minor()?;
 | 
			
		||||
        Ok(BlockDeviceRef { path, major, minor })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn unloop(&self, device: &str) -> Result<()> {
 | 
			
		||||
        let device = LoopDevice::open(device)?;
 | 
			
		||||
        device.detach()?;
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -9,15 +9,21 @@ use uuid::Uuid;
 | 
			
		||||
pub struct ConfigBlock<'a> {
 | 
			
		||||
    pub image_info: &'a ImageInfo,
 | 
			
		||||
    pub file: PathBuf,
 | 
			
		||||
    pub dir: PathBuf,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ConfigBlock<'_> {
 | 
			
		||||
    pub fn new<'a>(uuid: &Uuid, image_info: &'a ImageInfo) -> Result<ConfigBlock<'a>> {
 | 
			
		||||
        let mut file = std::env::temp_dir().clone();
 | 
			
		||||
        file.push(format!("hypha-cfg-{}", uuid));
 | 
			
		||||
        fs::create_dir_all(&file)?;
 | 
			
		||||
        let mut dir = std::env::temp_dir().clone();
 | 
			
		||||
        dir.push(format!("hypha-cfg-{}", uuid));
 | 
			
		||||
        fs::create_dir_all(&dir)?;
 | 
			
		||||
        let mut file = dir.clone();
 | 
			
		||||
        file.push("config.squashfs");
 | 
			
		||||
        Ok(ConfigBlock { image_info, file })
 | 
			
		||||
        Ok(ConfigBlock {
 | 
			
		||||
            image_info,
 | 
			
		||||
            file,
 | 
			
		||||
            dir,
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn build(&self) -> Result<()> {
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,12 @@
 | 
			
		||||
mod cfgblk;
 | 
			
		||||
pub mod cfgblk;
 | 
			
		||||
 | 
			
		||||
use crate::autoloop::AutoLoop;
 | 
			
		||||
use crate::ctl::cfgblk::ConfigBlock;
 | 
			
		||||
use crate::error::{HyphaError, Result};
 | 
			
		||||
use crate::error::Result;
 | 
			
		||||
use crate::image::cache::ImageCache;
 | 
			
		||||
use crate::image::name::ImageName;
 | 
			
		||||
use crate::image::{ImageCompiler, ImageInfo};
 | 
			
		||||
use loopdev::LoopControl;
 | 
			
		||||
use std::fs;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
use uuid::Uuid;
 | 
			
		||||
@ -12,6 +14,7 @@ use xenclient::{DomainConfig, DomainDisk, XenClient};
 | 
			
		||||
 | 
			
		||||
pub struct Controller {
 | 
			
		||||
    image_cache: ImageCache,
 | 
			
		||||
    autoloop: AutoLoop,
 | 
			
		||||
    image: String,
 | 
			
		||||
    client: XenClient,
 | 
			
		||||
    kernel_path: String,
 | 
			
		||||
@ -39,6 +42,7 @@ impl Controller {
 | 
			
		||||
        let image_cache = ImageCache::new(&image_cache_path)?;
 | 
			
		||||
        Ok(Controller {
 | 
			
		||||
            image_cache,
 | 
			
		||||
            autoloop: AutoLoop::new(LoopControl::open()?),
 | 
			
		||||
            image,
 | 
			
		||||
            client,
 | 
			
		||||
            kernel_path,
 | 
			
		||||
@ -60,14 +64,13 @@ impl Controller {
 | 
			
		||||
        let image_info = self.compile()?;
 | 
			
		||||
        let cfgblk = ConfigBlock::new(&uuid, &image_info)?;
 | 
			
		||||
        cfgblk.build()?;
 | 
			
		||||
        let cfgblk_squashfs_path = cfgblk
 | 
			
		||||
            .file
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .ok_or_else(|| HyphaError::new("failed to convert config squashfs path to string"))?;
 | 
			
		||||
        let image_squashfs_path = image_info
 | 
			
		||||
            .image_squashfs
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .ok_or_else(|| HyphaError::new("failed to convert image squashfs path to string"))?;
 | 
			
		||||
 | 
			
		||||
        let image_squashfs_path = image_info.image_squashfs.clone();
 | 
			
		||||
        let cfgblk_squashfs_path = cfgblk.file.clone();
 | 
			
		||||
 | 
			
		||||
        let image_squashfs_loop = self.autoloop.loopify(&image_squashfs_path)?;
 | 
			
		||||
        let cfgblk_squashfs_loop = self.autoloop.loopify(&cfgblk_squashfs_path)?;
 | 
			
		||||
 | 
			
		||||
        let config = DomainConfig {
 | 
			
		||||
            backend_domid: 0,
 | 
			
		||||
            name: &name,
 | 
			
		||||
@ -79,17 +82,24 @@ impl Controller {
 | 
			
		||||
            disks: vec![
 | 
			
		||||
                DomainDisk {
 | 
			
		||||
                    vdev: "xvda",
 | 
			
		||||
                    pdev: image_squashfs_path,
 | 
			
		||||
                    block: &image_squashfs_loop,
 | 
			
		||||
                    writable: false,
 | 
			
		||||
                },
 | 
			
		||||
                DomainDisk {
 | 
			
		||||
                    vdev: "xvdb",
 | 
			
		||||
                    pdev: cfgblk_squashfs_path,
 | 
			
		||||
                    block: &cfgblk_squashfs_loop,
 | 
			
		||||
                    writable: false,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        let domid = self.client.create(&config)?;
 | 
			
		||||
        Ok(domid)
 | 
			
		||||
        match self.client.create(&config) {
 | 
			
		||||
            Ok(domid) => Ok(domid),
 | 
			
		||||
            Err(error) => {
 | 
			
		||||
                let _ = self.autoloop.unloop(&image_squashfs_loop.path);
 | 
			
		||||
                let _ = self.autoloop.unloop(&cfgblk_squashfs_loop.path);
 | 
			
		||||
                let _ = fs::remove_dir(&cfgblk.dir);
 | 
			
		||||
                Err(error.into())
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,4 @@
 | 
			
		||||
pub mod autoloop;
 | 
			
		||||
pub mod container;
 | 
			
		||||
pub mod ctl;
 | 
			
		||||
pub mod error;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user