mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 21:21:32 +00:00
hypha: implement loop device support directly to avoid devd
This commit is contained in:
@ -7,6 +7,9 @@ resolver = "2"
|
||||
[dependencies.xenclient]
|
||||
path = "../xenclient"
|
||||
|
||||
[dependencies.loopdev]
|
||||
path = "../loopdev"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.20"
|
||||
env_logger = "0.11.0"
|
||||
|
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