VM works on SNP server
This commit is contained in:
parent
a8347f633d
commit
82273f63e5
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -149,7 +149,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "daemon"
|
name = "detee-snp-daemon"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "daemon"
|
name = "detee-snp-daemon"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
18
scripts/start_qemu_vm.sh
Normal file → Executable file
18
scripts/start_qemu_vm.sh
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
[[ -z "$VM_UUID" ]] || {
|
[[ -z "$VM_UUID" ]] && {
|
||||||
echo "Environment variable VM_UUID is not set."
|
echo "Environment variable VM_UUID is not set."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@ -17,6 +17,7 @@ done
|
|||||||
|
|
||||||
interfaces=$(env | grep -oE '^NETWORK_INTERFACE_[0-9]*')
|
interfaces=$(env | grep -oE '^NETWORK_INTERFACE_[0-9]*')
|
||||||
nat_configured="false"
|
nat_configured="false"
|
||||||
|
vtap_fd_counter=3
|
||||||
while read -r interface; do
|
while read -r interface; do
|
||||||
|
|
||||||
interface_type="$( echo ${!interface} | cut -d '_' -f1 )"
|
interface_type="$( echo ${!interface} | cut -d '_' -f1 )"
|
||||||
@ -24,13 +25,21 @@ while read -r interface; do
|
|||||||
if [[ "$interface_type" == "macvtap" || "$interface_type" == "ipvtap" ]]; then
|
if [[ "$interface_type" == "macvtap" || "$interface_type" == "ipvtap" ]]; then
|
||||||
interface_device="$( echo ${!interface} | cut -d '_' -f2 )"
|
interface_device="$( echo ${!interface} | cut -d '_' -f2 )"
|
||||||
interface_name="$( echo ${!interface} | cut -d '_' -f3 )"
|
interface_name="$( echo ${!interface} | cut -d '_' -f3 )"
|
||||||
|
if [[ "$interface_type" == "macvtap" ]]; then
|
||||||
ip link add link $interface_device name $interface_name type $interface_type mode bridge
|
ip link add link $interface_device name $interface_name type $interface_type mode bridge
|
||||||
|
else
|
||||||
|
ip link add link $interface_device name $interface_name type $interface_type
|
||||||
|
fi
|
||||||
ip link set $interface_name up
|
ip link set $interface_name up
|
||||||
ip link set $interface_name promisc on
|
ip link set $interface_name promisc on
|
||||||
|
|
||||||
vtap_index="$(cat /sys/class/net/${interface_name}/ifindex)"
|
vtap_index="$(cat /sys/class/net/${interface_name}/ifindex)"
|
||||||
vtap_addr="$(cat /sys/class/net/${interface_name}/address)"
|
vtap_addr="$(cat /sys/class/net/${interface_name}/address)"
|
||||||
qemu_device_params="-netdev tap,id=hostnet1,fd=3 3<>/dev/tap${macvtap_index}"
|
|
||||||
qemu_device_params+=" -device virtio-net-pci,netdev=hostnet1,mac=${macvtap_addr},romfile="
|
fd_number=$vtap_fd_counter
|
||||||
|
exec {fd_number}<> /dev/tap${vtap_index}
|
||||||
|
qemu_device_params="-netdev tap,id=hostnet1,fd=${fd_number} -device virtio-net-pci,netdev=hostnet1,mac=${vtap_addr},romfile="
|
||||||
|
((vtap_fd_counter++))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$interface_type" == "NAT" && "$nat_configured" == "false" ]]; then
|
if [[ "$interface_type" == "NAT" && "$nat_configured" == "false" ]]; then
|
||||||
@ -54,7 +63,8 @@ vm_disk="/root/dtrfs/arch-1-ghe0.qcow2"
|
|||||||
qemu-system-x86_64 $qemu_device_params \
|
qemu-system-x86_64 $qemu_device_params \
|
||||||
-enable-kvm -cpu $CPU_TYPE -vga none \
|
-enable-kvm -cpu $CPU_TYPE -vga none \
|
||||||
-machine q35,confidential-guest-support=sev0,memory-backend=ram1 \
|
-machine q35,confidential-guest-support=sev0,memory-backend=ram1 \
|
||||||
-smp $VCPUS,maxcpus=$VCPUS -m $MEMORY,slots=5,maxmem=$MAX_MEMORY \
|
-smp $VCPUS,maxcpus=$VCPUS \
|
||||||
|
-m $MEMORY,slots=5,maxmem=$MAX_MEMORY \
|
||||||
-no-reboot -bios /usr/share/edk2/ovmf/OVMF.amdsev.fd \
|
-no-reboot -bios /usr/share/edk2/ovmf/OVMF.amdsev.fd \
|
||||||
-drive file=${DISK},if=none,id=disk0,format=qcow2 \
|
-drive file=${DISK},if=none,id=disk0,format=qcow2 \
|
||||||
-device virtio-blk-pci,drive=disk0 \
|
-device virtio-blk-pci,drive=disk0 \
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
pub(crate) const DEFAULT_OVMF: &str = "/usr/share/edk2/ovmf/OVMF.amdsev.fd";
|
pub(crate) const DEFAULT_OVMF: &str = "/usr/share/edk2/ovmf/OVMF.amdsev.fd";
|
||||||
pub(crate) const VM_BOOT_DIR: &str = "/var/lib/detee/boot/";
|
pub(crate) const VM_BOOT_DIR: &str = "/var/lib/detee/boot/";
|
||||||
pub(crate) const VM_CONFIG_DIR: &str = "/etc/detee/daemon/vms/";
|
pub(crate) const VM_CONFIG_DIR: &str = "/etc/detee/daemon/vms/";
|
||||||
pub(crate) const DAEMON_CONFIG_PATH: &str = "/etc/detee/daemon/config.json";
|
pub(crate) const DAEMON_CONFIG_PATH: &str = "/etc/detee/daemon/config.yaml";
|
||||||
pub(crate) const START_VM_SCRIPT: &str = "/usr/local/bin/detee/start_qemu_vm.sh";
|
pub(crate) const START_VM_SCRIPT: &str = "/usr/local/bin/detee/start_qemu_vm.sh";
|
||||||
// TODO: research if other CPU types provide better performance
|
// TODO: research if other CPU types provide better performance
|
||||||
pub(crate) const QEMU_VM_CPU_TYPE: &str = "EPYC-v4";
|
pub(crate) const QEMU_VM_CPU_TYPE: &str = "EPYC-v4";
|
||||||
|
27
src/main.rs
27
src/main.rs
@ -7,29 +7,12 @@ use crate::config::Config;
|
|||||||
use crate::state::NewVMRequest;
|
use crate::state::NewVMRequest;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = Config::from_file("prod_setting/config1.yaml")?;
|
let args: Vec<String> = std::env::args().collect();
|
||||||
|
let config = Config::from_file(crate::constants::DAEMON_CONFIG_PATH)?;
|
||||||
let mut res = state::Resources::new(&config.volumes);
|
let mut res = state::Resources::new(&config.volumes);
|
||||||
// println!("{:#?}", config);
|
let new_vm_req = NewVMRequest::from_file(&args[1])?;
|
||||||
|
|
||||||
// let config = Config::from_file("test_data/config2.yaml")?;
|
|
||||||
// println!("{:#?}", config);
|
|
||||||
// let config = Config::from_file("test_data/config3.yaml")?;
|
|
||||||
// println!("{:#?}", config);
|
|
||||||
// let config = Config::from_file("test_data/config4.yaml")?;
|
|
||||||
// println!("{:#?}", config);
|
|
||||||
// let config = Config::from_file("test_data/config5.yaml")?;
|
|
||||||
// println!("{:#?}", config);
|
|
||||||
let new_vm_req = NewVMRequest::from_file("test_data/new_vm_req3.yaml")?;
|
|
||||||
// println!("{:#?}", new_vm_req);
|
|
||||||
|
|
||||||
// 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_req3.yaml")?;
|
|
||||||
// println!("{:#?}", new_vm_req);
|
|
||||||
// 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 vm = state::VM::new(new_vm_req, &config, &mut res);
|
||||||
println!("vm: {:#?}", vm);
|
println!("Got VM: {:#?}", vm);
|
||||||
println!("{:?}", vm.unwrap().start());
|
println!("Starting VM... \n{:?}", vm.unwrap().start());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
52
src/state.rs
52
src/state.rs
@ -38,7 +38,7 @@ impl Resources {
|
|||||||
available_gb: config_vol.max_reservation_gb,
|
available_gb: config_vol.max_reservation_gb,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Resources {
|
let mut res = Resources {
|
||||||
reserved_vcpus: 0,
|
reserved_vcpus: 0,
|
||||||
reserved_memory: 0,
|
reserved_memory: 0,
|
||||||
reserved_ports: HashSet::new(),
|
reserved_ports: HashSet::new(),
|
||||||
@ -46,7 +46,9 @@ impl Resources {
|
|||||||
reserved_ips: HashSet::new(),
|
reserved_ips: HashSet::new(),
|
||||||
reserved_if_names: HashSet::new(),
|
reserved_if_names: HashSet::new(),
|
||||||
boot_files: HashSet::new(),
|
boot_files: HashSet::new(),
|
||||||
}
|
};
|
||||||
|
res.scan_boot_files().unwrap();
|
||||||
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn available_storage_pool(&mut self, required_gb: usize) -> Option<String> {
|
fn available_storage_pool(&mut self, required_gb: usize) -> Option<String> {
|
||||||
@ -319,9 +321,7 @@ pub struct VM {
|
|||||||
// currently hardcoded to EPYC-v4
|
// currently hardcoded to EPYC-v4
|
||||||
// cpu_type: String,
|
// cpu_type: String,
|
||||||
vcpus: usize,
|
vcpus: usize,
|
||||||
// memory in MB
|
|
||||||
memory_mb: usize,
|
memory_mb: usize,
|
||||||
// disk size in GB
|
|
||||||
disk_size_gb: usize,
|
disk_size_gb: usize,
|
||||||
kernel_sha: String,
|
kernel_sha: String,
|
||||||
dtrfs_sha: String,
|
dtrfs_sha: String,
|
||||||
@ -510,7 +510,7 @@ impl VM {
|
|||||||
for nic in self.nics.iter() {
|
for nic in self.nics.iter() {
|
||||||
for ip in nic.ips.iter() {
|
for ip in nic.ips.iter() {
|
||||||
ip_string += &format!(
|
ip_string += &format!(
|
||||||
"detee_net_eth{}={}_{}_{}",
|
"detee_net_eth{}={}_{}_{} ",
|
||||||
i, ip.address, ip.mask, ip.gateway
|
i, ip.address, ip.mask, ip.gateway
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -527,12 +527,14 @@ impl VM {
|
|||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for nic in self.nics.iter() {
|
for nic in self.nics.iter() {
|
||||||
let mut interface = String::new();
|
let mut interface = String::new();
|
||||||
interface += &format!("NETWORK_INTERFACE_{}={}", i, nic.if_config.if_type());
|
interface += &format!(r#"export NETWORK_INTERFACE_{}="{}"#, i, nic.if_config.if_type());
|
||||||
// device is currently ignored in case of NAT cause we assume QEMU userspace NAT
|
// device is currently ignored in case of NAT cause we assume QEMU userspace NAT
|
||||||
if let Some(vtap_name) = nic.if_config.vtap_name() {
|
if let Some(vtap_name) = nic.if_config.vtap_name() {
|
||||||
interface += &format!("_{}_{}", nic.if_config.device_name(), vtap_name);
|
interface += &format!("_{}_{}", nic.if_config.device_name(), vtap_name);
|
||||||
}
|
}
|
||||||
vars += &format!("{}\n", interface);
|
interface += r#"""#;
|
||||||
|
vars += &format!(r#"{}"#, interface);
|
||||||
|
vars += "\n";
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,17 +543,32 @@ impl VM {
|
|||||||
ports += &format!("{}:{} ", port.0, port.1);
|
ports += &format!("{}:{} ", port.0, port.1);
|
||||||
}
|
}
|
||||||
if ports != "" {
|
if ports != "" {
|
||||||
vars += &format!("NAT_PORT_FW={}", ports.trim_end());
|
vars += &format!(r#"NAT_PORT_FW="{}""#, ports.trim_end());
|
||||||
|
vars += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
vars += &format!("KERNEL={}\n", VM_BOOT_DIR.to_string() + &self.kernel_sha);
|
vars += &format!(
|
||||||
vars += &format!("INITRD={}\n", VM_BOOT_DIR.to_string() + &self.dtrfs_sha);
|
r#"export KERNEL="{}""#,
|
||||||
vars += &format!("PARAMS={}\n", self.kernel_params());
|
VM_BOOT_DIR.to_string() + &self.kernel_sha
|
||||||
vars += &format!("CPU_TYPE={}\n", QEMU_VM_CPU_TYPE);
|
);
|
||||||
vars += &format!("VCPUS={}\n", self.vcpus);
|
vars += "\n";
|
||||||
vars += &format!("MEMORY={}MB\n", self.memory_mb);
|
vars += &format!(
|
||||||
vars += &format!("MAX_MEMORY={}MB\n", self.memory_mb + 256);
|
r#"export INITRD="{}""#,
|
||||||
vars += &format!("DISK={}\n", self.disk_path());
|
VM_BOOT_DIR.to_string() + &self.dtrfs_sha
|
||||||
|
);
|
||||||
|
vars += "\n";
|
||||||
|
vars += &format!(r#"export PARAMS="{}""#, self.kernel_params());
|
||||||
|
vars += "\n";
|
||||||
|
vars += &format!(r#"export CPU_TYPE="{}""#, QEMU_VM_CPU_TYPE);
|
||||||
|
vars += "\n";
|
||||||
|
vars += &format!(r#"export VCPUS="{}""#, self.vcpus);
|
||||||
|
vars += "\n";
|
||||||
|
vars += &format!(r#"export MEMORY="{}M""#, self.memory_mb);
|
||||||
|
vars += "\n";
|
||||||
|
vars += &format!(r#"export MAX_MEMORY="{}M""#, self.memory_mb + 256);
|
||||||
|
vars += "\n";
|
||||||
|
vars += &format!(r#"export DISK="{}""#, self.disk_path());
|
||||||
|
vars += "\n";
|
||||||
|
|
||||||
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())?;
|
file.write_all(vars.as_bytes())?;
|
||||||
@ -600,8 +617,7 @@ impl VM {
|
|||||||
contents += &format!("[Install]\n");
|
contents += &format!("[Install]\n");
|
||||||
contents += &format!("WantedBy=multi-user.target\n");
|
contents += &format!("WantedBy=multi-user.target\n");
|
||||||
|
|
||||||
let mut file =
|
let mut file = File::create("/etc/systemd/system/".to_string() + &self.uuid + ".service")?;
|
||||||
File::create("/tmp/etc/systemd/system/".to_string() + &self.uuid + ".service")?;
|
|
||||||
file.write_all(contents.as_bytes())?;
|
file.write_all(contents.as_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user