Skip to content

Commit 3c048fe

Browse files
committed
test: dump debug information whenever ssh.check_output fails
Print microvm logs and stack backtraces whenever running a command via SSH inside the guest fails (instead of only doing this if `wait_for_ssh_up` fails). To this by adding an `on_error` hook that gets called from `SSHConnection.check_output` if running the SSH command fails. Potentially, this could later be extended to automatically snapshot the microvm inside the hook, but for now, let's only print some data. Signed-off-by: Patrick Roy <[email protected]>
1 parent e2c787f commit 3c048fe

File tree

2 files changed

+38
-14
lines changed

2 files changed

+38
-14
lines changed

tests/framework/microvm.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,7 @@ def ssh_iface(self, iface_idx=0):
983983
ssh_key=self.ssh_key,
984984
user="root",
985985
host=guest_ip,
986+
on_error=self._dump_debug_information,
986987
)
987988

988989
@property
@@ -1002,19 +1003,23 @@ def thread_backtraces(self):
10021003
)
10031004
return "\n".join(backtraces)
10041005

1006+
def _dump_debug_information(self, exc: Exception):
1007+
"""
1008+
Dumps debug information about this microvm
1009+
1010+
Used for example when running a command inside the guest via `SSHConnection.check_output` fails.
1011+
"""
1012+
print(
1013+
f"Failure executing command via SSH in microVM: {exc}\n\n"
1014+
f"Firecracker logs:\n{self.log_data}\n"
1015+
f"Thread backtraces:\n{self.thread_backtraces}"
1016+
)
1017+
10051018
def wait_for_ssh_up(self):
10061019
"""Wait for guest running inside the microVM to come up and respond."""
1007-
try:
1008-
# Ensure that we have an initialized SSH connection to the guest that can
1009-
# run commands. The actual connection retry loop happens in SSHConnection._init_connection
1010-
self.ssh_iface(0)
1011-
except Exception as exc:
1012-
print(
1013-
f"Failed to establish SSH connection to guest: {exc}\n\n"
1014-
f"Firecracker logs:\n{self.log_data}\n"
1015-
f"Thread backtraces:\n{self.thread_backtraces}"
1016-
)
1017-
raise
1020+
# Ensure that we have an initialized SSH connection to the guest that can
1021+
# run commands. The actual connection retry loop happens in SSHConnection._init_connection
1022+
_ = self.ssh_iface(0)
10181023

10191024

10201025
class MicroVMFactory:

tests/host_tools/network.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class SSHConnection:
2525
ssh -i ssh_key_path username@hostname
2626
"""
2727

28-
def __init__(self, netns, ssh_key: Path, host, user):
28+
def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None):
2929
"""Instantiate a SSH client and connect to a microVM."""
3030
self.netns = netns
3131
self.ssh_key = ssh_key
@@ -37,6 +37,8 @@ def __init__(self, netns, ssh_key: Path, host, user):
3737
self.host = host
3838
self.user = user
3939

40+
self._on_error = None
41+
4042
self.options = [
4143
"-o",
4244
"LogLevel=ERROR",
@@ -52,7 +54,18 @@ def __init__(self, netns, ssh_key: Path, host, user):
5254
str(self.ssh_key),
5355
]
5456

55-
self._init_connection()
57+
# _init_connection loops until it can connect to the guest
58+
# dumping debug state on every iteration is not useful or wanted, so
59+
# only dump it once if _all_ iterations fail.
60+
try:
61+
self._init_connection()
62+
except Exception as exc:
63+
if on_error:
64+
on_error(exc)
65+
66+
raise
67+
68+
self._on_error = on_error
5669

5770
def remote_path(self, path):
5871
"""Convert a path to remote"""
@@ -123,7 +136,13 @@ def _exec(self, cmd, timeout=None, check=False):
123136
if self.netns is not None:
124137
cmd = ["ip", "netns", "exec", self.netns] + cmd
125138

126-
return utils.run_cmd(cmd, check=check, timeout=timeout)
139+
try:
140+
return utils.run_cmd(cmd, check=check, timeout=timeout)
141+
except Exception as exc:
142+
if self._on_error:
143+
self._on_error(exc)
144+
145+
raise
127146

128147

129148
def mac_from_ip(ip_address):

0 commit comments

Comments
 (0)