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:
2026-09-25 17:39:06 +05:30
parent dca7f78dae
commit b0bf99a6ee
25 changed files with 1893 additions and 30 deletions
+26
View File
@@ -113,6 +113,28 @@ class ProcessTestCase(unittest.TestCase):
class FirecrackerProcessSafetyTests(ProcessTestCase):
def test_vsock_socket_is_removed_only_after_confirmed_process_exit(self) -> None:
path = self.manager._settings.guest_socket_path(self.vm.id)
path.parent.mkdir(parents=True)
path.touch()
self.vm.process_start_time = None
with self.assertRaises(FirecrackerError):
self.manager.terminate(self.vm)
self.assertTrue(path.exists())
self.vm.boot_id = OLD_BOOT_ID
self.manager.terminate(self.vm)
self.assertFalse(path.exists())
def test_unowned_vsock_socket_keeps_a_missing_pid_ambiguous(self) -> None:
path = self.manager._settings.guest_socket_path(self.vm.id)
path.parent.mkdir(parents=True)
path.touch()
self.vm.pid = self.vm.process_start_time = None
self.assertEqual(self.manager.observe(self.vm), "unknown")
with self.assertRaises(FirecrackerError):
self.manager.terminate(self.vm)
self.assertTrue(path.exists())
def test_observes_a_matching_identity_as_alive(self) -> None:
self.assertEqual(self.manager.observe(self.vm), "alive")
self.assertTrue(self.manager.is_alive(self.vm))
@@ -808,6 +830,10 @@ class FirecrackerLegacyAdoptionTests(ProcessTestCase):
def root_lstat(path: Path) -> os.stat_result:
metadata = list(real_lstat(path))
metadata[4] = 0
# Model protected system ancestors independently of the caller's
# TMPDIR permissions. Unsafe-path fixtures live inside self.directory.
if path in self.directory.parents:
metadata[0] &= ~0o022
return os.stat_result(metadata)
self.root_lstat = root_lstat