writing files correctly

This commit is contained in:
ghe0 2024-12-12 02:48:18 +02:00
parent d4c5cc2634
commit df34fc719c
Signed by: ghe0
GPG Key ID: 451028EE56A0FBB4
4 changed files with 68 additions and 43 deletions

@ -7,7 +7,7 @@
source "/etc/detee/daemon/vms/$VM_UUID"
mandatory_vars=("KERNEL" "INITRD" "PARAMS" "CPU_TYPE" \
"VCPUS" "MEMORY" "MAX_MEMORY" "DISK" "DISK_SIZE")
"VCPUS" "MEMORY" "MAX_MEMORY" "DISK")
for var in "${mandatory_vars[@]}"; do
if [ -z "${!var}" ]; then
echo "Environment variable $var is not set."
@ -51,8 +51,6 @@ done <<< "$( echo "$interfaces" )"
vm_disk="/root/dtrfs/arch-1-ghe0.qcow2"
[[ -f $DISK ]] || qemu-img create -f qcow2 ${DISK} ${DISK_SIZE}
qemu-system-x86_64 $qemu_device_params \
-enable-kvm -cpu $CPU_TYPE -vga none \
-machine q35,confidential-guest-support=sev0,memory-backend=ram1 \

@ -19,7 +19,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// println!("{:#?}", config);
// let config = Config::from_file("test_data/config5.yaml")?;
// println!("{:#?}", config);
let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req4.yaml")?;
let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req2.yaml")?;
// println!("{:#?}", new_vm_req);
// let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req2.yaml")?;
@ -29,11 +29,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req4.yaml")?;
// println!("{:#?}", new_vm_req);
let vm = state::VM::new(new_vm_req, &config, &mut res);
let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req4.yaml")?;
let vm = state::VM::new(new_vm_req, &config, &mut res);
let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req4.yaml")?;
let vm = state::VM::new(new_vm_req, &config, &mut res);
println!("vm: {:#?}", vm);
println!("res: {:#?}", res);
println!("{:?}", vm.unwrap().start());
Ok(())
}

@ -205,6 +205,22 @@ impl Resources {
self.reserved_ports.insert(*host_port);
}
}
fn free_vm_resources(&mut self, vm: &VM) {
self.reserved_vcpus -= vm.vcpus;
self.reserved_memory -= vm.memory;
for nic in vm.nics.iter() {
if let Some(vtap) = nic.if_config.vtap_name() {
self.reserved_if_names.remove(&vtap);
}
for ip in nic.ips.iter() {
self.reserved_ips.remove(&ip.address.clone());
}
}
for (host_port, _) in vm.fw_ports.iter() {
self.reserved_ports.remove(host_port);
}
}
}
#[derive(Debug)]
@ -427,6 +443,28 @@ impl VM {
Ok(vm)
}
pub fn start(&self) -> Result<()> {
self.create_disk()?;
self.write_vm_config()?;
self.write_systemd_unit_file()?;
// TODO: systemctl daemon-reload
// TODO: systemctl start
// TODO: systemctl enable
Ok(())
}
pub fn delete(&self, res: &mut Resources) -> Result<()> {
// TODO: systemctl stop
// TODO: systemctl disable
res.free_vm_resources(&self);
self.delete_systemd_unit_file()?;
// TODO: systemctl daemon-reload
self.delete_disk()?;
self.delete_vm_config()?;
self.delete_vtap_interfaces()?;
Ok(())
}
pub fn deploy(&self) -> Result<()> {
self.create_disk()?;
self.write_vm_config()?;
@ -435,20 +473,11 @@ impl VM {
Ok(())
}
pub fn delete(&self) -> Result<()> {
// TODO: systemctl disable, systemctl stop
self.delete_disk()?;
self.delete_vtap_interfaces()?;
self.delete_systemd_unit_file()?;
// TODO: systemctl daemon-reload
Ok(())
}
// For the MVP, the T-Contract offers VM+IP+Disk as a bundle.
// This means we can enforce the path to the disk.
// This may change in the future as the VM is allowed to have multiple disks.
pub fn disk_path(&self) -> String {
VM_DISK_DIR.to_string() + "/" + &self.uuid + ".qcow2"
VM_DISK_DIR.to_string() + &self.uuid + ".qcow2"
}
pub fn kernel_params(&self) -> String {
@ -493,11 +522,11 @@ impl VM {
vars += &format!(
"KERNEL={}\n",
VM_BOOT_DIR.to_string() + "/" + &self.kernel_sha
VM_BOOT_DIR.to_string() + &self.kernel_sha
);
vars += &format!(
"INITRD={}\n",
VM_BOOT_DIR.to_string() + "/" + &self.dtrfs_sha
VM_BOOT_DIR.to_string() + &self.dtrfs_sha
);
vars += &format!("PARAMS={}\n", self.kernel_params());
vars += &format!("CPU_TYPE={}\n", QEMU_VM_CPU_TYPE);
@ -505,15 +534,14 @@ impl VM {
vars += &format!("MEMORY={}MB\n", self.memory);
vars += &format!("MAX_MEMORY={}MB\n", self.memory + 256);
vars += &format!("DISK={}\n", self.disk_path());
vars += &format!("DISK_SIZE={}GB\n", self.disk_size);
let mut file = File::create(VM_CONFIG_DIR.to_string() + "/" + &self.uuid)?;
let mut file = File::create(VM_CONFIG_DIR.to_string() + &self.uuid)?;
file.write_all(vars.as_bytes())?;
Ok(())
}
pub fn delete_vm_config(&self) -> Result<()> {
remove_file(VM_CONFIG_DIR.to_string() + "/" + &self.uuid)?;
remove_file(VM_CONFIG_DIR.to_string() + &self.uuid)?;
Ok(())
}
@ -540,27 +568,27 @@ impl VM {
pub fn write_systemd_unit_file(&self) -> Result<()> {
let mut contents = String::new();
contents += &format!("[Unit]");
contents += &format!("Description=DeTEE {}", self.uuid);
contents += &format!("After=network.target");
contents += &format!("");
contents += &format!("[Service]");
contents += &format!("Type=simple");
contents += &format!("Environment=VM_UUID={}", self.uuid);
contents += &format!("ExecStart={}", START_VM_SCRIPT);
contents += &format!("ExecStop=/bin/kill -s SIGINT $MAINPID");
contents += &format!("Restart=always");
contents += &format!("");
contents += &format!("[Install]");
contents += &format!("WantedBy=multi-user.target");
contents += &format!("[Unit]\n");
contents += &format!("Description=DeTEE {}\n", self.uuid);
contents += &format!("After=network.target\n");
contents += &format!("\n");
contents += &format!("[Service]\n");
contents += &format!("Type=simple\n");
contents += &format!("Environment=VM_UUID={}\n", self.uuid);
contents += &format!("ExecStart={}\n", START_VM_SCRIPT);
contents += &format!("ExecStop=/bin/kill -s SIGINT $MAINPID\n");
contents += &format!("Restart=always\n");
contents += &format!("\n");
contents += &format!("[Install]\n");
contents += &format!("WantedBy=multi-user.target\n");
let mut file = File::create("/etc/systemd/system/".to_string() + &self.uuid + ".service")?;
let mut file = File::create("/tmp/etc/systemd/system/".to_string() + &self.uuid + ".service")?;
file.write_all(contents.as_bytes())?;
Ok(())
}
pub fn delete_systemd_unit_file(&self) -> Result<()> {
remove_file("/etc/systemd/system/".to_string() + &self.uuid + ".service")?;
remove_file("/tmp/etc/systemd/system/".to_string() + &self.uuid + ".service")?;
Ok(())
}
@ -568,14 +596,17 @@ impl VM {
let result = Command::new("qemu-img")
.arg("create")
.arg("-f")
.arg("qcow2")
.arg(self.disk_path())
.arg(self.disk_size.to_string() + "G")
.output()?;
if !result.status.success() {
return Err(anyhow!(
"Could not create VM Disk:\n{:?}\n{:?}",
result.stdout,
result.stderr
String::from_utf8(result.stdout)
.unwrap_or("Could not grab stdout from creation script.".to_string()),
String::from_utf8(result.stderr)
.unwrap_or("Could not grab stderr from creation script.".to_string()),
));
}
Ok(())
@ -592,7 +623,7 @@ fn download_and_check_sha(url: &str, sha: &str) -> Result<()> {
use std::fs::File;
use std::io::copy;
use std::path::Path;
let save_path = VM_BOOT_DIR.to_string() + "/" + sha;
let save_path = VM_BOOT_DIR.to_string() + sha;
let response = get(url)?;
if !response.status().is_success() {
return Err(anyhow!("Failed to download file: {}", response.status()));

@ -1,4 +1,4 @@
uuid: "default-uuid"
uuid: "DuTenPulaMeaCuUUIDulTauCuTot"
hostname: "testing-vm"
admin_key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAAKeyExampleForTesting"
extra_ports: [1234, 5678]