Skip to content

Commit 5d88dae

Browse files
committed
test: 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 2fdd984 commit 5d88dae

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

tests/host_tools/network.py

Lines changed: 28 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

@@ -54,9 +55,13 @@ def __init__(self, netns, ssh_key: Path, host, user):
5455

5556
self._init_connection()
5657

58+
@property
59+
def user_host(self):
60+
return f"{self.user}@{self.host}"
61+
5762
def remote_path(self, path):
5863
"""Convert a path to remote"""
59-
return f"{self.user}@{self.host}:{path}"
64+
return f"{self.user_host}:{path}"
6065

6166
def _scp(self, path1, path2, options):
6267
"""Copy files to/from the VM using scp."""
@@ -98,21 +103,12 @@ def run(self, cmd_string, timeout=None, *, check=False, debug=False):
98103
99104
If `debug` is set, pass `-vvv` to `ssh`. Note that this will clobber stderr.
100105
"""
101-
command = [
102-
"ssh",
103-
*self.options,
104-
f"{self.user}@{self.host}",
105-
cmd_string,
106-
]
106+
command = ["ssh", *self.options, self.user_host, cmd_string]
107107

108108
if debug:
109109
command.insert(1, "-vvv")
110110

111-
return self._exec(
112-
command,
113-
timeout,
114-
check=check,
115-
)
111+
return self._exec(command, timeout, check=check)
116112

117113
def check_output(self, cmd_string, timeout=None, *, debug=False):
118114
"""Same as `run`, but raises an exception on non-zero return code of remote command"""
@@ -125,6 +121,26 @@ def _exec(self, cmd, timeout=None, check=False):
125121

126122
return utils.run_cmd(cmd, check=check, timeout=timeout)
127123

124+
def Popen(
125+
self,
126+
cmd: str,
127+
stdin=subprocess.DEVNULL,
128+
stdout=subprocess.PIPE,
129+
stderr=subprocess.PIPE,
130+
**kwargs,
131+
) -> subprocess.Popen:
132+
"""Execute the command in the guest and return a Popen object.
133+
134+
pop = uvm.ssh.Popen("while true; do echo $(date -Is) $RANDOM; sleep 1; done")
135+
pop.stdout.read(16)
136+
"""
137+
cmd = ["ssh", *self.options, self.user_host, cmd]
138+
if self.netns is not None:
139+
cmd = ["ip", "netns", "exec", self.netns] + cmd
140+
return subprocess.Popen(
141+
cmd, stdin=stdin, stdout=stdout, stderr=stderr, **kwargs
142+
)
143+
128144

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

0 commit comments

Comments
 (0)