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:
+17
-11
@@ -124,7 +124,7 @@ class FirecrackerProcessManager:
|
||||
) from error
|
||||
|
||||
socket_path = Path(vm.socket)
|
||||
self._remove_socket(socket_path)
|
||||
self._remove_runtime_sockets(vm)
|
||||
|
||||
log_path = Path(vm.log)
|
||||
process: _PopenLike | None = None
|
||||
@@ -275,14 +275,16 @@ class FirecrackerProcessManager:
|
||||
if vm.pid is None:
|
||||
if vm.spawn_pending or vm.operation == "spawning" or vm.process_start_time is not None:
|
||||
return "unknown"
|
||||
try:
|
||||
Path(vm.socket).lstat()
|
||||
except FileNotFoundError:
|
||||
return "gone"
|
||||
except OSError:
|
||||
for socket_path in (Path(vm.socket), self._settings.guest_socket_path(vm.id)):
|
||||
try:
|
||||
socket_path.lstat()
|
||||
except FileNotFoundError:
|
||||
continue
|
||||
except OSError:
|
||||
return "unknown"
|
||||
# An unowned socket may belong to a child whose identity was never saved.
|
||||
return "unknown"
|
||||
# An unowned socket may belong to a child whose identity was never saved.
|
||||
return "unknown"
|
||||
return "gone"
|
||||
|
||||
stat = self._process_stat(vm.pid)
|
||||
if stat is None:
|
||||
@@ -330,14 +332,14 @@ class FirecrackerProcessManager:
|
||||
f"refusing to stop Firecracker PID {vm.pid}: process identity is ambiguous"
|
||||
)
|
||||
if observation == "gone":
|
||||
self._remove_socket(Path(vm.socket))
|
||||
self._remove_runtime_sockets(vm)
|
||||
return
|
||||
|
||||
try:
|
||||
pidfd = _open_pidfd(vm.pid)
|
||||
except ProcessLookupError:
|
||||
self._reap_child(vm.pid)
|
||||
self._remove_socket(Path(vm.socket))
|
||||
self._remove_runtime_sockets(vm)
|
||||
return
|
||||
except (OSError, NotImplementedError) as error:
|
||||
raise FirecrackerError(
|
||||
@@ -369,7 +371,7 @@ class FirecrackerProcessManager:
|
||||
"process identity and socket retained"
|
||||
)
|
||||
self._reap_child(vm.pid)
|
||||
self._remove_socket(Path(vm.socket))
|
||||
self._remove_runtime_sockets(vm)
|
||||
except (OSError, NotImplementedError) as error:
|
||||
raise FirecrackerError(
|
||||
f"could not safely stop Firecracker process {vm.pid}: {error}"
|
||||
@@ -455,6 +457,10 @@ class FirecrackerProcessManager:
|
||||
if process is not None and process.poll() is not None:
|
||||
self._children.pop(pid, None)
|
||||
|
||||
def _remove_runtime_sockets(self, vm: VmRecord) -> None:
|
||||
self._remove_socket(self._settings.guest_socket_path(vm.id))
|
||||
self._remove_socket(Path(vm.socket))
|
||||
|
||||
@staticmethod
|
||||
def _remove_socket(socket_path: Path) -> None:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user