feat: Add guest execution agent and vsock support
- Introduced a standalone guest execution agent to facilitate command execution within the guest VM over Firecracker's vsock. - Enhanced FirecrackerClient to support vsock configuration, validating guest CID and UDS path. - Updated configuration to include vsock settings by default. - Refactored FirecrackerProcessManager to manage runtime sockets more effectively. - Implemented guest agent installation and provisioning in the image store. - Added API endpoints for executing commands in the VM and installing the guest agent. - Improved error handling for guest execution failures and agent availability.
This commit is contained in:
@@ -78,6 +78,7 @@ class FirecrackerConfigTests(unittest.TestCase):
|
||||
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))
|
||||
self.assertEqual(config["vsock"], {"guest_cid": 3, "uds_path": "/var/lib/uvm/vms/vm-test/vsock.sock"})
|
||||
|
||||
def test_configures_firecracker_in_required_order_before_start(self) -> None:
|
||||
vm = VmRecord(
|
||||
@@ -107,6 +108,7 @@ class FirecrackerConfigTests(unittest.TestCase):
|
||||
"/boot-source",
|
||||
"/drives/rootfs",
|
||||
"/network-interfaces/eth0",
|
||||
"/vsock",
|
||||
"/entropy",
|
||||
"/actions",
|
||||
],
|
||||
@@ -124,6 +126,7 @@ class FirecrackerConfigTests(unittest.TestCase):
|
||||
"drives": [{}],
|
||||
"network-interfaces": [{}],
|
||||
"entropy": {},
|
||||
"vsock": {"guest_cid": 3, "uds_path": "/tmp/vsock.sock"},
|
||||
}
|
||||
client = RecordingFirecrackerClient()
|
||||
|
||||
@@ -147,6 +150,31 @@ class FirecrackerConfigTests(unittest.TestCase):
|
||||
client.configure_and_start(config)
|
||||
self.assertEqual(client.calls, [])
|
||||
|
||||
def test_missing_invalid_or_failed_vsock_configuration_prevents_guest_boot(self) -> None:
|
||||
config = {
|
||||
"machine-config": {"vcpu_count": 1, "mem_size_mib": 512}, "boot-source": {},
|
||||
"drives": [{}], "network-interfaces": [{}], "entropy": {},
|
||||
}
|
||||
for vsock in (None, {}, {"guest_cid": True, "uds_path": "/tmp/vsock.sock"},
|
||||
{"guest_cid": 2, "uds_path": "/tmp/vsock.sock"}, {"guest_cid": 3, "uds_path": ""}):
|
||||
with self.subTest(vsock=vsock):
|
||||
client = RecordingFirecrackerClient()
|
||||
config["vsock"] = vsock
|
||||
with self.assertRaisesRegex(FirecrackerError, "vsock"):
|
||||
client.configure_and_start(config)
|
||||
self.assertEqual(client.calls, [])
|
||||
config["vsock"] = {"guest_cid": 3, "uds_path": "/tmp/vsock.sock"}
|
||||
client = RecordingFirecrackerClient()
|
||||
|
||||
def request(method, path, body):
|
||||
client.calls.append((method, path, body))
|
||||
if path == "/vsock":
|
||||
raise FirecrackerError("vsock unavailable")
|
||||
|
||||
with patch.object(client, "_request", side_effect=request), self.assertRaises(FirecrackerError):
|
||||
client.configure_and_start(config)
|
||||
self.assertNotIn("/actions", [path for _method, path, _body in client.calls])
|
||||
|
||||
def test_uses_the_configured_network_netmask_in_guest_boot_arguments(self) -> None:
|
||||
settings = Settings(
|
||||
network=IPv4Network("10.50.0.0/16"),
|
||||
|
||||
Reference in New Issue
Block a user