107 lines
3.5 KiB
Python
107 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from ipaddress import IPv4Address, IPv4Network
|
|
from pathlib import Path
|
|
|
|
from uvm.config import Settings
|
|
from uvm.domain import VmRecord
|
|
from uvm.firecracker.api import FirecrackerClient
|
|
from uvm.firecracker.config import build_config, vcpu_count
|
|
|
|
|
|
class RecordingFirecrackerClient(FirecrackerClient):
|
|
def __init__(self) -> None:
|
|
self.calls: list[tuple[str, str, object]] = []
|
|
|
|
def _request(self, method: str, path: str, body: object) -> None:
|
|
self.calls.append((method, path, body))
|
|
|
|
|
|
class FirecrackerConfigTests(unittest.TestCase):
|
|
def test_builds_a_writable_vm_disk_configuration(self) -> None:
|
|
vm = VmRecord(
|
|
id="vm-test",
|
|
cpu=0.5,
|
|
ram_mib=512,
|
|
guest_ip="10.42.0.2",
|
|
gateway="10.42.0.1",
|
|
tap="uvm-test",
|
|
mac="02:fc:00:00:00:01",
|
|
socket="/tmp/firecracker.sock",
|
|
config="/tmp/config.json",
|
|
log="/tmp/firecracker.log",
|
|
disk="/vm/rootfs.ext4",
|
|
)
|
|
config = build_config(
|
|
Settings(),
|
|
vm,
|
|
Path("/images/vmlinux"),
|
|
Path("/vm/rootfs.ext4"),
|
|
)
|
|
|
|
self.assertEqual(vcpu_count(0.5), 1)
|
|
self.assertEqual(config["machine-config"]["mem_size_mib"], 512)
|
|
self.assertEqual(config["drives"][0]["path_on_host"], "/vm/rootfs.ext4")
|
|
self.assertIn("ip=10.42.0.2::10.42.0.1", config["boot-source"]["boot_args"])
|
|
self.assertNotIn("password", str(config))
|
|
|
|
def test_configures_firecracker_in_required_order_before_start(self) -> None:
|
|
vm = VmRecord(
|
|
id="vm-test",
|
|
cpu=1,
|
|
ram_mib=512,
|
|
guest_ip="10.42.0.2",
|
|
gateway="10.42.0.1",
|
|
tap="uvm-test",
|
|
mac="02:fc:00:00:00:01",
|
|
socket="/tmp/firecracker.sock",
|
|
config="/tmp/config.json",
|
|
log="/tmp/firecracker.log",
|
|
disk="/vm/rootfs.ext4",
|
|
)
|
|
config = build_config(
|
|
Settings(), vm, Path("/images/vmlinux"), Path("/vm/rootfs.ext4")
|
|
)
|
|
client = RecordingFirecrackerClient()
|
|
|
|
client.configure_and_start(config)
|
|
|
|
self.assertEqual(
|
|
[path for _method, path, _body in client.calls],
|
|
[
|
|
"/machine-config",
|
|
"/boot-source",
|
|
"/drives/rootfs",
|
|
"/network-interfaces/eth0",
|
|
"/actions",
|
|
],
|
|
)
|
|
self.assertEqual(
|
|
client.calls[0][2],
|
|
{"vcpu_count": 1, "mem_size_mib": 512, "smt": False},
|
|
)
|
|
self.assertEqual(client.calls[-1][2], {"action_type": "InstanceStart"})
|
|
|
|
def test_uses_the_configured_network_netmask_in_guest_boot_arguments(self) -> None:
|
|
settings = Settings(
|
|
network=IPv4Network("10.50.0.0/16"),
|
|
gateway=IPv4Address("10.50.0.1"),
|
|
)
|
|
vm = VmRecord(
|
|
id="vm-test",
|
|
cpu=1,
|
|
ram_mib=512,
|
|
guest_ip="10.50.0.2",
|
|
gateway="10.50.0.1",
|
|
tap="uvm-test",
|
|
mac="02:fc:00:00:00:01",
|
|
socket="/tmp/firecracker.sock",
|
|
config="/tmp/config.json",
|
|
log="/tmp/firecracker.log",
|
|
)
|
|
|
|
config = build_config(settings, vm, Path("/images/vmlinux"), Path("/vm/rootfs.ext4"))
|
|
|
|
self.assertIn("ip=10.50.0.2::10.50.0.1:255.255.0.0", config["boot-source"]["boot_args"])
|