Update tobiko shell package
Change-Id: I18d87d1763d5b501bd3694f79940d2b1ee441dd9
This commit is contained in:
parent
319803da4d
commit
2cde963248
@ -66,6 +66,7 @@ str_from_stream = _process.str_from_stream
|
|||||||
ShellProcessFixture = _process.ShellProcessFixture
|
ShellProcessFixture = _process.ShellProcessFixture
|
||||||
|
|
||||||
PsError = _ps.PsError
|
PsError = _ps.PsError
|
||||||
|
PsProcess = _ps.PsProcess
|
||||||
PsWaitTimeout = _ps.PsWaitTimeout
|
PsWaitTimeout = _ps.PsWaitTimeout
|
||||||
list_all_processes = _ps.list_all_processes
|
list_all_processes = _ps.list_all_processes
|
||||||
list_kernel_processes = _ps.list_kernel_processes
|
list_kernel_processes = _ps.list_kernel_processes
|
||||||
|
@ -85,13 +85,12 @@ class ShellReadable(ShellIOBase):
|
|||||||
def readable(self):
|
def readable(self):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def read(self, size=None):
|
def read(self, size: int = None) -> bytes:
|
||||||
size = size or self.buffer_size
|
size = size or self.buffer_size
|
||||||
try:
|
try:
|
||||||
chunk = self.delegate.read(size)
|
chunk = self.delegate.read(size)
|
||||||
except IOError:
|
except IOError:
|
||||||
LOG.exception('Error reading from %r', self)
|
LOG.exception('Error reading from %r', self)
|
||||||
chunk = None
|
|
||||||
try:
|
try:
|
||||||
self.close()
|
self.close()
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -100,6 +99,8 @@ class ShellReadable(ShellIOBase):
|
|||||||
|
|
||||||
if chunk:
|
if chunk:
|
||||||
self._data_chunks.append(chunk)
|
self._data_chunks.append(chunk)
|
||||||
|
elif chunk is None:
|
||||||
|
chunk = 'b'
|
||||||
return chunk
|
return chunk
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -18,12 +18,20 @@ from __future__ import absolute_import
|
|||||||
import collections
|
import collections
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
import tobiko
|
import tobiko
|
||||||
|
from tobiko.shell.sh import _command
|
||||||
|
from tobiko.shell.sh import _exception
|
||||||
from tobiko.shell.sh import _execute
|
from tobiko.shell.sh import _execute
|
||||||
from tobiko.shell.sh import _hostname
|
from tobiko.shell.sh import _hostname
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PsError(tobiko.TobikoException):
|
class PsError(tobiko.TobikoException):
|
||||||
message = "Unable to list processes from host: {error}"
|
message = "Unable to list processes from host: {error}"
|
||||||
|
|
||||||
@ -36,6 +44,9 @@ class PsWaitTimeout(PsError):
|
|||||||
IS_KERNEL_RE = re.compile('^\\[.*\\]$')
|
IS_KERNEL_RE = re.compile('^\\[.*\\]$')
|
||||||
|
|
||||||
|
|
||||||
|
_NOT_FOUND = object()
|
||||||
|
|
||||||
|
|
||||||
class PsProcess(collections.namedtuple('PsProcess', ['ssh_client',
|
class PsProcess(collections.namedtuple('PsProcess', ['ssh_client',
|
||||||
'pid',
|
'pid',
|
||||||
'command'])):
|
'command'])):
|
||||||
@ -46,6 +57,27 @@ class PsProcess(collections.namedtuple('PsProcess', ['ssh_client',
|
|||||||
def is_kernel(self):
|
def is_kernel(self):
|
||||||
return IS_KERNEL_RE.match(self.command) is not None
|
return IS_KERNEL_RE.match(self.command) is not None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def command_line(self) -> typing.Optional[_command.ShellCommand]:
|
||||||
|
command_line = self.__dict__.get('_command_line', _NOT_FOUND)
|
||||||
|
if command_line is _NOT_FOUND:
|
||||||
|
command_line = None
|
||||||
|
try:
|
||||||
|
output = _execute.execute(f'cat /proc/{self.pid}/cmdline',
|
||||||
|
ssh_client=self.ssh_client).stdout
|
||||||
|
except _exception.ShellCommandFailed as ex:
|
||||||
|
LOG.error(f"Unable to get process command line: {ex.stderr}")
|
||||||
|
else:
|
||||||
|
line = _command.ShellCommand(output.strip().split('\0')[:-1])
|
||||||
|
if line[0] != self.command:
|
||||||
|
LOG.error(f"Command line of process {self.pid} "
|
||||||
|
"doesn't match its command "
|
||||||
|
f"({self.command}): {line}")
|
||||||
|
else:
|
||||||
|
command_line = line
|
||||||
|
self.__dict__['command_line'] = command_line
|
||||||
|
return command_line
|
||||||
|
|
||||||
|
|
||||||
def list_kernel_processes(**list_params):
|
def list_kernel_processes(**list_params):
|
||||||
return list_processes(is_kernel=True, **list_params)
|
return list_processes(is_kernel=True, **list_params)
|
||||||
@ -55,8 +87,12 @@ def list_all_processes(**list_params):
|
|||||||
return list_processes(is_kernel=None, **list_params)
|
return list_processes(is_kernel=None, **list_params)
|
||||||
|
|
||||||
|
|
||||||
def list_processes(pid=None, command=None, is_kernel=False, ssh_client=None,
|
def list_processes(pid=None,
|
||||||
**execute_params):
|
command: typing.Optional[str] = None,
|
||||||
|
is_kernel=False,
|
||||||
|
ssh_client=None,
|
||||||
|
command_line: typing.Optional[str] = None,
|
||||||
|
**execute_params) -> tobiko.Selection[PsProcess]:
|
||||||
"""Returns the number of seconds passed since last host reboot
|
"""Returns the number of seconds passed since last host reboot
|
||||||
|
|
||||||
It reads and parses remote special file /proc/uptime and returns a floating
|
It reads and parses remote special file /proc/uptime and returns a floating
|
||||||
@ -70,7 +106,7 @@ def list_processes(pid=None, command=None, is_kernel=False, ssh_client=None,
|
|||||||
raise PsError(error=result.stderr)
|
raise PsError(error=result.stderr)
|
||||||
|
|
||||||
# Extract a list of PsProcess instances from table body
|
# Extract a list of PsProcess instances from table body
|
||||||
processes = tobiko.Selection()
|
processes = tobiko.Selection[PsProcess]()
|
||||||
for process_data in parse_table(lines=output.splitlines(),
|
for process_data in parse_table(lines=output.splitlines(),
|
||||||
schema=PS_TABLE_SCHEMA):
|
schema=PS_TABLE_SCHEMA):
|
||||||
processes.append(PsProcess(ssh_client=ssh_client, **process_data))
|
processes.append(PsProcess(ssh_client=ssh_client, **process_data))
|
||||||
@ -83,15 +119,24 @@ def list_processes(pid=None, command=None, is_kernel=False, ssh_client=None,
|
|||||||
|
|
||||||
if processes and command is not None:
|
if processes and command is not None:
|
||||||
# filter processes by command
|
# filter processes by command
|
||||||
command = re.compile(command)
|
pattern = re.compile(command)
|
||||||
processes = tobiko.select(process
|
processes = tobiko.Selection[PsProcess](
|
||||||
for process in processes
|
process
|
||||||
if command.match(process.command))
|
for process in processes
|
||||||
|
if pattern.match(process.command))
|
||||||
|
|
||||||
if processes and is_kernel is not None:
|
if processes and is_kernel is not None:
|
||||||
# filter kernel processes
|
# filter kernel processes
|
||||||
processes = processes.with_attributes(is_kernel=bool(is_kernel))
|
processes = processes.with_attributes(is_kernel=bool(is_kernel))
|
||||||
|
|
||||||
|
if processes and command_line is not None:
|
||||||
|
pattern = re.compile(command_line)
|
||||||
|
processes = tobiko.Selection[PsProcess](
|
||||||
|
process
|
||||||
|
for process in processes
|
||||||
|
if (process.command_line is not None and
|
||||||
|
pattern.match(f"{process.command_line}")))
|
||||||
|
|
||||||
return processes
|
return processes
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,9 @@ ssh_command = _command.ssh_command
|
|||||||
ssh_proxy_client = _client.ssh_proxy_client
|
ssh_proxy_client = _client.ssh_proxy_client
|
||||||
SSHConnectFailure = _client.SSHConnectFailure
|
SSHConnectFailure = _client.SSHConnectFailure
|
||||||
gather_ssh_connect_parameters = _client.gather_ssh_connect_parameters
|
gather_ssh_connect_parameters = _client.gather_ssh_connect_parameters
|
||||||
|
SSHClientType = _client.SSHClientType
|
||||||
|
ssh_client_fixture = _client.ssh_client_fixture
|
||||||
|
|
||||||
|
|
||||||
reset_default_ssh_port_forward_manager = \
|
reset_default_ssh_port_forward_manager = \
|
||||||
_forward.reset_default_ssh_port_forward_manager
|
_forward.reset_default_ssh_port_forward_manager
|
||||||
|
@ -625,3 +625,17 @@ def check_ssh_connection(client):
|
|||||||
transport.send_ignore()
|
transport.send_ignore()
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
SSHClientType = typing.Union[None, bool, SSHClientFixture]
|
||||||
|
|
||||||
|
|
||||||
|
def ssh_client_fixture(obj: SSHClientType) -> \
|
||||||
|
typing.Optional[SSHClientFixture]:
|
||||||
|
if obj is None:
|
||||||
|
return ssh_proxy_client()
|
||||||
|
if obj is False:
|
||||||
|
return None
|
||||||
|
if isinstance(obj, SSHClientFixture):
|
||||||
|
return obj
|
||||||
|
raise TypeError(f"Can't get an SSHClientFixture from objeck {obj}")
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
name: tobiko-infrared
|
name: tobiko-infrared
|
||||||
parent: tox
|
parent: tox
|
||||||
nodeset: tobiko-infrared-centos
|
nodeset: tobiko-infrared-centos
|
||||||
timeout: 1800
|
timeout: 3600
|
||||||
description: |
|
description: |
|
||||||
Run test cases using tobiko infrared plugin
|
Run test cases using tobiko infrared plugin
|
||||||
pre-run: playbooks/infrared/pre.yaml
|
pre-run: playbooks/infrared/pre.yaml
|
||||||
|
Loading…
x
Reference in New Issue
Block a user