From 6229ec74aa458e04111afbd30aa84a2c5c3eb188 Mon Sep 17 00:00:00 2001 From: Zack Cerza Date: Mon, 22 Jan 2024 18:20:37 -0700 Subject: [PATCH] updates from test failures --- teuthology/misc.py | 2 +- teuthology/orchestra/cluster.py | 2 +- teuthology/orchestra/remote.py | 21 ++--- teuthology/orchestra/test/test_cluster.py | 9 +- teuthology/orchestra/test/test_remote.py | 41 +++++---- teuthology/orchestra/test/test_run.py | 104 +++++++++++++--------- 6 files changed, 99 insertions(+), 80 deletions(-) diff --git a/teuthology/misc.py b/teuthology/misc.py index c03be7e856..259fd0095b 100644 --- a/teuthology/misc.py +++ b/teuthology/misc.py @@ -898,7 +898,7 @@ def reboot(node, timeout=300, interval=30): reboot_start_time = time.time() while time.time() - reboot_start_time < timeout: time.sleep(interval) - if node.is_online or node.reconnect(): + if node.is_online() or node.reconnect(): return raise RuntimeError( "{host} did not come up after reboot within {time}s".format( diff --git a/teuthology/orchestra/cluster.py b/teuthology/orchestra/cluster.py index d3a0ff17ff..9b2a894cb7 100644 --- a/teuthology/orchestra/cluster.py +++ b/teuthology/orchestra/cluster.py @@ -179,7 +179,7 @@ class Cluster(object): Return a cluster whose remotes are filtered by `func`. Example:: - cluster = ctx.cluster.filter(lambda r: r.is_online) + cluster = ctx.cluster.filter(lambda r: r.is_online()) """ result = self.__class__() for rem, roles in self.remotes.items(): diff --git a/teuthology/orchestra/remote.py b/teuthology/orchestra/remote.py index 9904397604..692916ffeb 100644 --- a/teuthology/orchestra/remote.py +++ b/teuthology/orchestra/remote.py @@ -330,8 +330,7 @@ class RemoteShell(object): self._os = OS.from_lsb_release(lsb_release) return self._os - @property - def arch(self): + async def arch(self): if not hasattr(self, '_arch'): self._arch = self.sh('uname -m').strip() return self._arch @@ -684,12 +683,11 @@ class Remote(RemoteShell): self._host_key = ' '.join((key.get_name(), key.get_base64())) return self._host_key - @property - def inventory_info(self): + async def inventory_info(self): node = dict() node['name'] = self.hostname node['user'] = self.user - node['arch'] = self.arch + node['arch'] = await self.arch() node['os_type'] = self.os.name node['os_version'] = '.'.join(self.os.version.split('.')[:2]) node['ssh_pub_key'] = self.host_key @@ -708,17 +706,16 @@ class Remote(RemoteShell): self._is_vm = teuthology.lock.query.is_vm(self.name) return self._is_vm - @property - def is_container(self): + async def is_container(self): if not hasattr(self, '_is_container'): - self._is_container = not bool(self.run( + proc = await self.run( args="test -f /run/.containerenv -o -f /.dockerenv", check_status=False, - ).returncode) + ) + self._is_container = 0 == proc.returncode return self._is_container - @property - def init_system(self): + async def init_system(self): """ Which init system does the remote use? @@ -726,7 +723,7 @@ class Remote(RemoteShell): """ if not hasattr(self, '_init_system'): self._init_system = None - proc = self.run( + proc = await self.run( args=['which', 'systemctl'], check_status=False, ) diff --git a/teuthology/orchestra/test/test_cluster.py b/teuthology/orchestra/test/test_cluster.py index 27bef8b831..0e849b6ce4 100644 --- a/teuthology/orchestra/test/test_cluster.py +++ b/teuthology/orchestra/test/test_cluster.py @@ -51,7 +51,8 @@ class TestCluster(object): ) assert str(c) == "r1[foo,bar] r2[baz]" - def test_run_all(self): + @pytest.mark.asyncio + async def test_run_all(self): r1 = Mock(spec=remote.Remote) r1.configure_mock(name='r1') ret1 = Mock(spec=run.RemoteProcess) @@ -66,14 +67,14 @@ class TestCluster(object): (r2, ['baz']), ], ) - got = c.run(args=['test']) + got = await c.run(args=['test']) r1.run.assert_called_once_with(args=['test'], wait=True) r2.run.assert_called_once_with(args=['test'], wait=True) assert len(got) == 2 assert got, [ret1 == ret2] # check identity not equality - assert got[0] is ret1 - assert got[1] is ret2 + assert await got[0] is ret1 + assert await got[1] is ret2 def test_only_one(self): r1 = Mock() diff --git a/teuthology/orchestra/test/test_remote.py b/teuthology/orchestra/test/test_remote.py index a953835e7c..79154f2c68 100644 --- a/teuthology/orchestra/test/test_remote.py +++ b/teuthology/orchestra/test/test_remote.py @@ -1,5 +1,6 @@ -from mock import patch, Mock, MagicMock -from pytest import raises +import pytest + +from mock import patch, Mock, MagicMock, AsyncMock from io import BytesIO @@ -45,11 +46,12 @@ class TestRemote(object): assert r.shortname == 'xyzzy' assert str(r) == 'jdoe@xyzzy.example.com' - def test_run(self): + @pytest.mark.asyncio + async def test_run(self): m_transport = MagicMock() m_transport.getpeername.return_value = ('name', 22) self.m_ssh.get_transport.return_value = m_transport - m_run = MagicMock() + m_run = AsyncMock() args = [ 'something', 'more', @@ -61,19 +63,20 @@ class TestRemote(object): m_run.return_value = proc rem = remote.Remote(name='jdoe@xyzzy.example.com', ssh=self.m_ssh) rem._runner = m_run - result = rem.run(args=args) + result = await rem.run(args=args) m_transport.getpeername.assert_called_once_with() m_run_call_kwargs = m_run.call_args_list[0][1] assert m_run_call_kwargs['args'] == args assert result is proc assert result.remote is rem + @pytest.mark.asyncio @patch('teuthology.util.scanner.UnitTestScanner.scan_and_write') - def test_run_unit_test(self, m_scan_and_write): + async def test_run_unit_test(self, m_scan_and_write): m_transport = MagicMock() m_transport.getpeername.return_value = ('name', 22) self.m_ssh.get_transport.return_value = m_transport - m_run = MagicMock(name="run", side_effect=CommandFailedError('mocked error', 1, 'smithi')) + m_run = AsyncMock(name="run", side_effect=CommandFailedError('mocked error', 1, 'smithi')) args = [ 'something', 'more', @@ -81,15 +84,15 @@ class TestRemote(object): rem = remote.Remote(name='jdoe@xyzzy.example.com', ssh=self.m_ssh) rem._runner = m_run m_scan_and_write.return_value = "Error Message" - with raises(UnitTestError) as exc: - rem.run_unit_test(args=args, xml_path_regex="xml_path", output_yaml="yaml_path") + with pytest.raises(UnitTestError) as exc: + await rem.run_unit_test(args=args, xml_path_regex="xml_path", output_yaml="yaml_path") assert str(exc.value) == "Unit test failed on smithi with status 1: 'Error Message'" def test_hostname(self): m_transport = MagicMock() m_transport.getpeername.return_value = ('name', 22) self.m_ssh.get_transport.return_value = m_transport - m_run = MagicMock() + m_run = AsyncMock() args = [ 'hostname', '--fqdn', @@ -112,7 +115,7 @@ class TestRemote(object): m_transport = MagicMock() m_transport.getpeername.return_value = ('name', 22) self.m_ssh.get_transport.return_value = m_transport - m_run = MagicMock() + m_run = AsyncMock() args = [ 'uname', '-m', @@ -131,7 +134,7 @@ class TestRemote(object): m_run.return_value = proc r = remote.Remote(name='jdoe@xyzzy.example.com', ssh=self.m_ssh) r._runner = m_run - assert r.arch == 'test_arch' + assert r.arch() == 'test_arch' assert len(m_run.call_args_list) == 1 m_run_call_kwargs = m_run.call_args_list[0][1] assert m_run_call_kwargs['client'] == self.m_ssh @@ -150,11 +153,12 @@ class TestRemote(object): self.m_ssh.get_transport.assert_called_once_with() m_transport.get_remote_server_key.assert_called_once_with() - def test_inventory_info(self): + @pytest.mark.asyncio + async def test_inventory_info(self): r = remote.Remote('user@host', host_key='host_key') r._arch = 'arch' r._os = opsys.OS(name='os_name', version='1.2.3', codename='code') - inv_info = r.inventory_info + inv_info = await r.inventory_info() assert inv_info == dict( name='host', user='user', @@ -201,11 +205,12 @@ class TestRemote(object): assert remote.Remote._format_size(1021112).strip() == '997KB' assert remote.Remote._format_size(1021112**2).strip() == '971GB' - def test_is_container(self): + @pytest.mark.asyncio + async def test_is_container(self): m_transport = MagicMock() m_transport.getpeername.return_value = ('name', 22) self.m_ssh.get_transport.return_value = m_transport - m_run = MagicMock() + m_run = AsyncMock() args = [] proc = RemoteProcess( client=self.m_ssh, @@ -215,8 +220,8 @@ class TestRemote(object): m_run.return_value = proc rem = remote.Remote(name='jdoe@xyzzy.example.com', ssh=self.m_ssh) rem._runner = m_run - assert rem.is_container + assert await rem.is_container() is True proc.returncode = 1 rem2 = remote.Remote(name='jdoe@xyzzy.example.com', ssh=self.m_ssh) rem2._runner = m_run - assert not rem2.is_container + assert await rem2.is_container() is False diff --git a/teuthology/orchestra/test/test_run.py b/teuthology/orchestra/test/test_run.py index e8051ccbc7..e4d51c3be1 100644 --- a/teuthology/orchestra/test/test_run.py +++ b/teuthology/orchestra/test/test_run.py @@ -1,10 +1,10 @@ from io import BytesIO import paramiko +import pytest import socket from mock import MagicMock, patch -from pytest import raises from teuthology.orchestra import run from teuthology.exceptions import (CommandCrashedError, CommandFailedError, @@ -79,29 +79,32 @@ class TestRun(object): pass self.patcher_ssh.stop() - def test_exitstatus(self): + @pytest.mark.asyncio + async def test_exitstatus(self): self.m_stdout_buf.channel.recv_exit_status.return_value = 0 - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo', 'bar baz'], ) assert proc.exitstatus == 0 - def test_run_cwd(self): + @pytest.mark.asyncio + async def test_run_cwd(self): self.m_stdout_buf.channel.recv_exit_status.return_value = 0 - run.run( + await run.run( client=self.m_ssh, args=['foo_bar_baz'], cwd='/cwd/test', ) self.m_ssh.exec_command.assert_called_with('(cd /cwd/test && exec foo_bar_baz)') - def test_capture_stdout(self): + @pytest.mark.asyncio + async def test_capture_stdout(self): output = 'foo\nbar' set_buffer_contents(self.m_stdout_buf, output) self.m_stdout_buf.channel.recv_exit_status.return_value = 0 stdout = BytesIO() - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo', 'bar baz'], stdout=stdout, @@ -110,12 +113,13 @@ class TestRun(object): assert proc.stdout.read().decode() == output assert proc.stdout.getvalue().decode() == output - def test_capture_stderr_newline(self): + @pytest.mark.asyncio + async def test_capture_stderr_newline(self): output = 'foo\nbar\n' set_buffer_contents(self.m_stderr_buf, output) self.m_stderr_buf.channel.recv_exit_status.return_value = 0 stderr = BytesIO() - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo', 'bar baz'], stderr=stderr, @@ -124,109 +128,119 @@ class TestRun(object): assert proc.stderr.read().decode() == output assert proc.stderr.getvalue().decode() == output - def test_status_bad(self): + @pytest.mark.asyncio + async def test_status_bad(self): self.m_stdout_buf.channel.recv_exit_status.return_value = 42 - with raises(CommandFailedError) as exc: - run.run( + with pytest.raises(CommandFailedError) as exc: + await run.run( client=self.m_ssh, args=['foo'], ) assert str(exc.value) == "Command failed on name with status 42: 'foo'" - def test_status_bad_nocheck(self): + @pytest.mark.asyncio + async def test_status_bad_nocheck(self): self.m_stdout_buf.channel.recv_exit_status.return_value = 42 - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo'], check_status=False, ) assert proc.exitstatus == 42 - def test_status_crash(self): + @pytest.mark.asyncio + async def test_status_crash(self): self.m_stdout_buf.channel.recv_exit_status.return_value = -1 - with raises(CommandCrashedError) as exc: - run.run( + with pytest.raises(CommandCrashedError) as exc: + await run.run( client=self.m_ssh, args=['foo'], ) assert str(exc.value) == "Command crashed: 'foo'" - def test_status_crash_nocheck(self): + @pytest.mark.asyncio + async def test_status_crash_nocheck(self): self.m_stdout_buf.channel.recv_exit_status.return_value = -1 - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo'], check_status=False, ) assert proc.exitstatus == -1 - def test_status_lost(self): + @pytest.mark.asyncio + async def test_status_lost(self): m_transport = MagicMock() m_transport.getpeername.return_value = ('name', 22) m_transport.is_active.return_value = False self.m_stdout_buf.channel.recv_exit_status.return_value = -1 self.m_ssh.get_transport.return_value = m_transport - with raises(ConnectionLostError) as exc: - run.run( + with pytest.raises(ConnectionLostError) as exc: + await run.run( client=self.m_ssh, args=['foo'], ) assert str(exc.value) == "SSH connection to name was lost: 'foo'" - def test_status_lost_socket(self): + @pytest.mark.asyncio + async def test_status_lost_socket(self): m_transport = MagicMock() m_transport.getpeername.side_effect = socket.error self.m_ssh.get_transport.return_value = m_transport - with raises(ConnectionLostError) as exc: - run.run( + with pytest.raises(ConnectionLostError) as exc: + await run.run( client=self.m_ssh, args=['foo'], ) assert str(exc.value) == "SSH connection was lost: 'foo'" - def test_status_lost_nocheck(self): + @pytest.mark.asyncio + async def test_status_lost_nocheck(self): m_transport = MagicMock() m_transport.getpeername.return_value = ('name', 22) m_transport.is_active.return_value = False self.m_stdout_buf.channel.recv_exit_status.return_value = -1 self.m_ssh.get_transport.return_value = m_transport - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo'], check_status=False, ) assert proc.exitstatus == -1 - def test_status_bad_nowait(self): + @pytest.mark.asyncio + async def test_status_bad_nowait(self): self.m_stdout_buf.channel.recv_exit_status.return_value = 42 - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo'], wait=False, ) - with raises(CommandFailedError) as exc: - proc.wait() + with pytest.raises(CommandFailedError) as exc: + await proc.wait() assert proc.returncode == 42 assert str(exc.value) == "Command failed on name with status 42: 'foo'" - def test_stdin_pipe(self): + @pytest.mark.asyncio + async def test_stdin_pipe(self): self.m_stdout_buf.channel.recv_exit_status.return_value = 0 - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo'], stdin=run.PIPE, wait=False ) assert proc.poll() == 0 - code = proc.wait() + code = await proc.wait() assert code == 0 assert proc.exitstatus == 0 - def test_stdout_pipe(self): + @pytest.mark.asyncio + async def test_stdout_pipe(self): self.m_stdout_buf.channel.recv_exit_status.return_value = 0 lines = [b'one\n', b'two', b''] set_buffer_contents(self.m_stdout_buf, lines) - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo'], stdout=run.PIPE, @@ -236,15 +250,16 @@ class TestRun(object): assert proc.stdout.readline() == lines[0] assert proc.stdout.readline() == lines[1] assert proc.stdout.readline() == lines[2] - code = proc.wait() + code = await proc.wait() assert code == 0 assert proc.exitstatus == 0 - def test_stderr_pipe(self): + @pytest.mark.asyncio + async def test_stderr_pipe(self): self.m_stdout_buf.channel.recv_exit_status.return_value = 0 lines = [b'one\n', b'two', b''] set_buffer_contents(self.m_stderr_buf, lines) - proc = run.run( + proc = await run.run( client=self.m_ssh, args=['foo'], stderr=run.PIPE, @@ -254,14 +269,15 @@ class TestRun(object): assert proc.stderr.readline() == lines[0] assert proc.stderr.readline() == lines[1] assert proc.stderr.readline() == lines[2] - code = proc.wait() + code = await proc.wait() assert code == 0 assert proc.exitstatus == 0 - def test_copy_and_close(self): - run.copy_and_close(None, MagicMock()) - run.copy_and_close('', MagicMock()) - run.copy_and_close(b'', MagicMock()) + @pytest.mark.asyncio + async def test_copy_and_close(self): + await run.copy_and_close(None, MagicMock()) + await run.copy_and_close('', MagicMock()) + await run.copy_and_close(b'', MagicMock()) class TestQuote(object): -- 2.39.5