feat: agent base implementation
Some checks failed
Rust CI / test (push) Failing after 18s

This commit is contained in:
2025-08-15 13:30:14 +09:00
commit 986cb5f1ac
18 changed files with 340 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
[package]
name = "dlx-vm"
version = "0.1.0"
edition = "2024"
[dependencies]
thiserror = "2.0.14"

View File

@@ -0,0 +1,9 @@
use thiserror::Error;
use crate::qemu::error::QemuError;
#[derive(Debug, Clone, Error)]
pub enum VmError {
#[error("QEMU error")]
Qemu(#[from] QemuError),
}

View File

@@ -0,0 +1,4 @@
mod error;
mod model;
mod qemu;
mod service;

View File

@@ -0,0 +1,3 @@
pub mod disk;
pub mod net;
pub mod vm;

View File

@@ -0,0 +1,7 @@
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Disk {
pub file: String,
pub index: u32,
pub format: Option<String>,
pub media: String,
}

View File

@@ -0,0 +1,2 @@
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VmNet(pub String);

View File

@@ -0,0 +1,15 @@
use crate::model::{disk::Disk, net::VmNet};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct MemoryMB(pub u32);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MachineAccel(pub String);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CloudInitVM {
pub mem: MemoryMB,
pub nets: Vec<VmNet>,
pub disks: Vec<Disk>,
pub machine: MachineAccel,
}

View File

@@ -0,0 +1,4 @@
pub mod config;
pub mod error;
pub mod param;
pub mod runner;

View File

@@ -0,0 +1,7 @@
use crate::qemu::param::QemuParam;
#[derive(Debug, Clone)]
pub struct QemuConfig {
pub executable: String,
pub param: QemuParam,
}

View File

@@ -0,0 +1,7 @@
use thiserror::Error;
#[derive(Debug, Clone, Error)]
pub enum QemuError {
#[error("unknown qemu error")]
Unknown,
}

View File

@@ -0,0 +1,158 @@
use crate::model::{
disk::Disk,
net::VmNet,
vm::{CloudInitVM, MachineAccel, MemoryMB},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct QemuParam(pub String);
pub trait IntoQemuParam {
fn into_qemu_param(self) -> QemuParam;
}
impl IntoQemuParam for MachineAccel {
fn into_qemu_param(self) -> QemuParam {
QemuParam(format!("-machine accel={}", self.0))
}
}
impl IntoQemuParam for MemoryMB {
fn into_qemu_param(self) -> QemuParam {
QemuParam(format!("-m {}", self.0))
}
}
impl IntoQemuParam for VmNet {
fn into_qemu_param(self) -> QemuParam {
QemuParam(format!("-net {}", self.0))
}
}
impl IntoQemuParam for Disk {
fn into_qemu_param(self) -> QemuParam {
let mut v: Vec<String> = vec![];
v.push(format!("file={}", self.file));
v.push(format!("index={}", self.index));
if let Some(format) = self.format {
v.push(format!("format={}", format));
}
v.push(format!("media={}", self.media));
let v = v.join(",");
QemuParam(format!("-drive {}", v))
}
}
impl IntoQemuParam for CloudInitVM {
fn into_qemu_param(self) -> QemuParam {
let mut params: Vec<QemuParam> = vec![];
params.push(self.mem.into_qemu_param());
let nets: Vec<QemuParam> = self
.nets
.into_iter()
.map(IntoQemuParam::into_qemu_param)
.collect();
params.extend_from_slice(&nets);
let disks: Vec<QemuParam> = self
.disks
.into_iter()
.map(IntoQemuParam::into_qemu_param)
.collect();
params.extend_from_slice(&disks);
params.push(self.machine.into_qemu_param());
let param = params
.into_iter()
.map(|e| e.0)
.collect::<Vec<String>>()
.join(" ");
QemuParam(param)
}
}
#[cfg(test)]
mod tests {
use crate::{
model::{
disk::Disk,
net::VmNet,
vm::{CloudInitVM, MachineAccel, MemoryMB},
},
qemu::param::{IntoQemuParam, QemuParam},
};
#[test]
fn test_into_qemu_param_disk_format() {
let disk = Disk {
file: "f".into(),
index: 1,
format: Some("123".into()),
media: "m".into(),
};
let param = disk.into_qemu_param();
assert_eq!(
param,
QemuParam("-drive file=f,index=1,format=123,media=m".into())
)
}
#[test]
fn test_into_qemu_param_disk_no_format() {
let disk = Disk {
file: "f".into(),
index: 1,
format: None,
media: "m".into(),
};
let param = disk.into_qemu_param();
assert_eq!(param, QemuParam("-drive file=f,index=1,media=m".into()))
}
#[test]
fn test_into_qemu_param_mem() {
let param = MemoryMB(1024).into_qemu_param();
assert_eq!(param, QemuParam("-m 1024".into()));
}
#[test]
fn test_into_qemu_param_machine() {
let param = MachineAccel("kvm:tcg".into()).into_qemu_param();
assert_eq!(param, QemuParam("-machine accel=kvm:tcg".into()));
}
#[test]
fn test_into_qemu_param_net() {
let param = VmNet("nic".into()).into_qemu_param();
assert_eq!(param, QemuParam("-net nic".into()));
}
#[test]
fn test_into_qemu_param_vm() {
let vm = CloudInitVM {
mem: MemoryMB(1024),
nets: vec![VmNet("1".into()), VmNet("2".into())],
disks: vec![Disk {
file: "f".into(),
index: 1,
format: None,
media: "m".into(),
}],
machine: MachineAccel("kvm:tcg".into()),
};
let param = vm.into_qemu_param();
assert_eq!(
param.0,
"-m 1024 -net 1 -net 2 -drive file=f,index=1,media=m -machine accel=kvm:tcg"
);
}
}

View File

@@ -0,0 +1,15 @@
use std::process::Command;
use crate::qemu::config::QemuConfig;
pub fn run_qemu(config: &QemuConfig) {
let args: Vec<String> = config
.param
.clone()
.0
.split(" ")
.map(|s| s.to_string())
.collect();
let handle = Command::new(&config.executable).args(&args).spawn();
}

View File

@@ -0,0 +1 @@
pub mod runner;

View File

@@ -0,0 +1,2 @@
pub trait RunnerService {
}