Skip to content

Commit 97e61ca

Browse files
committed
tests: add Microvm.ssh.Popen command
This returns a Popen object instead of waiting for the command to finish. It may be useful when we need to incrementally read the output of a long running process in the guest, without having to use screen. Signed-off-by: Pablo Barbáchano <[email protected]>
1 parent a69595f commit 97e61ca

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

tests/host_tools/network.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import ipaddress
66
import random
77
import string
8+
import subprocess
89
from dataclasses import dataclass, field
910
from pathlib import Path
1011

@@ -67,9 +68,14 @@ def __init__(self, netns, ssh_key: Path, host, user, *, on_error=None):
6768

6869
self._on_error = on_error
6970

71+
@property
72+
def user_host(self):
73+
"""remote address for in SSH format <user>@<IP>"""
74+
return f"{self.user}@{self.host}"
75+
7076
def remote_path(self, path):
7177
"""Convert a path to remote"""
72-
return f"{self.user}@{self.host}:{path}"
78+
return f"{self.user_host}:{path}"
7379

7480
def _scp(self, path1, path2, options):
7581
"""Copy files to/from the VM using scp."""
@@ -111,21 +117,12 @@ def run(self, cmd_string, timeout=None, *, check=False, debug=False):
111117
112118
If `debug` is set, pass `-vvv` to `ssh`. Note that this will clobber stderr.
113119
"""
114-
command = [
115-
"ssh",
116-
*self.options,
117-
f"{self.user}@{self.host}",
118-
cmd_string,
119-
]
120+
command = ["ssh", *self.options, self.user_host, cmd_string]
120121

121122
if debug:
122123
command.insert(1, "-vvv")
123124

124-
return self._exec(
125-
command,
126-
timeout,
127-
check=check,
128-
)
125+
return self._exec(command, timeout, check=check)
129126

130127
def check_output(self, cmd_string, timeout=None, *, debug=False):
131128
"""Same as `run`, but raises an exception on non-zero return code of remote command"""
@@ -144,6 +141,27 @@ def _exec(self, cmd, timeout=None, check=False):
144141

145142
raise
146143

144+
# pylint:disable=invalid-name
145+
def Popen(
146+
self,
147+
cmd: str,
148+
stdin=subprocess.DEVNULL,
149+
stdout=subprocess.PIPE,
150+
stderr=subprocess.PIPE,
151+
**kwargs,
152+
) -> subprocess.Popen:
153+
"""Execute the command in the guest and return a Popen object.
154+
155+
pop = uvm.ssh.Popen("while true; do echo $(date -Is) $RANDOM; sleep 1; done")
156+
pop.stdout.read(16)
157+
"""
158+
cmd = ["ssh", *self.options, self.user_host, cmd]
159+
if self.netns is not None:
160+
cmd = ["ip", "netns", "exec", self.netns] + cmd
161+
return subprocess.Popen(
162+
cmd, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs
163+
)
164+
147165

148166
def mac_from_ip(ip_address):
149167
"""Create a MAC address based on the provided IP.

0 commit comments

Comments
 (0)