writing files correctly
This commit is contained in:
parent
d4c5cc2634
commit
df34fc719c
@ -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(())
|
||||
}
|
||||
|
97
src/state.rs
97
src/state.rs
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user