Close stringio objects at sshutils

Closes-Bug: #1956956
Change-Id: I94f597d99951459b12f0f0211ec73f2ae7fa908d
This commit is contained in:
Andrey Kurilin 2022-01-10 15:38:11 +02:00
parent 675ea00d3b
commit 2a77c63071
3 changed files with 46 additions and 26 deletions

View File

@ -17,6 +17,16 @@ Changelog
.. Release notes for existing releases are MUTABLE! If there is something that .. Release notes for existing releases are MUTABLE! If there is something that
was missed or can be improved, feel free to change it! was missed or can be improved, feel free to change it!
[unreleased]
------------
Fixed
~~~~~
* rally.utils.sshutils.SSH.execute leaves fifo files.
`Launchpad-bug #1956956 <https://launchpad.net/bugs/1956956>`_
[3.3.0] - 2021-06-16 [3.3.0] - 2021-06-16
-------------------- --------------------

View File

@ -24,7 +24,7 @@ Execute command and get output:
status, stdout, stderr = ssh.execute("ps ax") status, stdout, stderr = ssh.execute("ps ax")
if status: if status:
raise Exception("Command failed with non-zero status.") raise Exception("Command failed with non-zero status.")
print stdout.splitlines() print(stdout.splitlines())
Execute command with huge output: Execute command with huge output:
@ -157,12 +157,18 @@ class SSH(object):
client = self._get_client() client = self._get_client()
should_close_stdin = False
if isinstance(stdin, str): if isinstance(stdin, str):
stdin = io.StringIO(stdin) stdin = io.StringIO(stdin)
should_close_stdin = True
return self._run(client, cmd, stdin=stdin, stdout=stdout, try:
stderr=stderr, raise_on_error=raise_on_error, return self._run(client, cmd, stdin=stdin, stdout=stdout,
timeout=timeout) stderr=stderr, raise_on_error=raise_on_error,
timeout=timeout)
finally:
if should_close_stdin:
stdin.close()
def _run(self, client, cmd, stdin=None, stdout=None, stderr=None, def _run(self, client, cmd, stdin=None, stdout=None, stderr=None,
raise_on_error=True, timeout=3600): raise_on_error=True, timeout=3600):
@ -246,15 +252,15 @@ class SSH(object):
:returns: tuple (exit_status, stdout, stderr) :returns: tuple (exit_status, stdout, stderr)
""" """
stdout = io.StringIO() with io.StringIO() as stdout:
stderr = io.StringIO() with io.StringIO() as stderr:
exit_status, data = self.run(cmd, stderr=stderr, stdout=stdout, exit_status, data = self.run(cmd, stderr=stderr, stdout=stdout,
stdin=stdin, timeout=timeout, stdin=stdin, timeout=timeout,
raise_on_error=False) raise_on_error=False)
stdout.seek(0) stdout.seek(0)
stderr.seek(0) stderr.seek(0)
return (exit_status, stdout.read(), stderr.read()) return exit_status, stdout.read(), stderr.read()
def wait(self, timeout=120, interval=1): def wait(self, timeout=120, interval=1):
"""Wait for the host will be available via ssh.""" """Wait for the host will be available via ssh."""

View File

@ -128,22 +128,26 @@ class SSHTestCase(test.TestCase):
m_client.close.assert_called_once_with() m_client.close.assert_called_once_with()
self.assertFalse(self.ssh._client) self.assertFalse(self.ssh._client)
@mock.patch("rally.utils.sshutils.io.StringIO") def test_execute(self):
def test_execute(self, mock_string_io): stdout_txt = "stdout fake data"
mock_string_io.side_effect = stdio = [mock.Mock(), mock.Mock()] stdout_io = io.StringIO(stdout_txt)
stdio[0].read.return_value = "stdout fake data" stderr_txt = "stderr fake data"
stdio[1].read.return_value = "stderr fake data" stderr_io = io.StringIO(stderr_txt)
with mock.patch.object(self.ssh, "run") as mock_run:
mock_run.return_value = (0, None) with mock.patch("rally.utils.sshutils.io.StringIO") as mock_string_io:
status, stdout, stderr = self.ssh.execute("cmd", mock_string_io.side_effect = [stdout_io, stderr_io]
stdin="fake_stdin", with mock.patch.object(self.ssh, "run") as mock_run:
timeout=43) mock_run.return_value = (0, None)
status, stdout, stderr = self.ssh.execute("cmd",
stdin="fake_stdin",
timeout=43)
mock_run.assert_called_once_with( mock_run.assert_called_once_with(
"cmd", stdin="fake_stdin", stdout=stdio[0], "cmd", stdin="fake_stdin", stdout=stdout_io, stderr=stderr_io,
stderr=stdio[1], timeout=43, raise_on_error=False) timeout=43, raise_on_error=False)
self.assertEqual(0, status) self.assertEqual(0, status)
self.assertEqual("stdout fake data", stdout) self.assertEqual(stdout_txt, stdout)
self.assertEqual("stderr fake data", stderr) self.assertEqual(stderr_txt, stderr)
@mock.patch("rally.utils.sshutils.time") @mock.patch("rally.utils.sshutils.time")
def test_wait_timeout(self, mock_time): def test_wait_timeout(self, mock_time):