1812c4071SJuraj Linkeš# SPDX-License-Identifier: BSD-3-Clause 2812c4071SJuraj Linkeš# Copyright(c) 2010-2014 Intel Corporation 378534506SJuraj Linkeš# Copyright(c) 2022-2023 PANTHEON.tech s.r.o. 478534506SJuraj Linkeš# Copyright(c) 2022-2023 University of New Hampshire 5812c4071SJuraj Linkeš 66ef07151SJuraj Linkeš"""DTS exceptions. 76ef07151SJuraj Linkeš 86ef07151SJuraj LinkešThe exceptions all have different severities expressed as an integer. 96ef07151SJuraj LinkešThe highest severity of all raised exceptions is used as the exit code of DTS. 10812c4071SJuraj Linkeš""" 11812c4071SJuraj Linkeš 1278534506SJuraj Linkešfrom enum import IntEnum, unique 1378534506SJuraj Linkešfrom typing import ClassVar 14812c4071SJuraj Linkeš 1578534506SJuraj Linkeš 1678534506SJuraj Linkeš@unique 1778534506SJuraj Linkešclass ErrorSeverity(IntEnum): 186ef07151SJuraj Linkeš """The severity of errors that occur during DTS execution. 196ef07151SJuraj Linkeš 2078534506SJuraj Linkeš All exceptions are caught and the most severe error is used as return code. 2178534506SJuraj Linkeš """ 2278534506SJuraj Linkeš 236ef07151SJuraj Linkeš #: 2478534506SJuraj Linkeš NO_ERR = 0 256ef07151SJuraj Linkeš #: 2678534506SJuraj Linkeš GENERIC_ERR = 1 276ef07151SJuraj Linkeš #: 2878534506SJuraj Linkeš CONFIG_ERR = 2 296ef07151SJuraj Linkeš #: 30ad80f550SJuraj Linkeš REMOTE_CMD_EXEC_ERR = 3 316ef07151SJuraj Linkeš #: 32ad80f550SJuraj Linkeš SSH_ERR = 4 336ef07151SJuraj Linkeš #: 34680d8a24SJuraj Linkeš DPDK_BUILD_ERR = 10 356ef07151SJuraj Linkeš #: 366fc05ca7SJuraj Linkeš TESTCASE_VERIFY_ERR = 20 376ef07151SJuraj Linkeš #: 3888489c05SJeremy Spewock BLOCKING_TESTSUITE_ERR = 25 3978534506SJuraj Linkeš 4078534506SJuraj Linkeš 4178534506SJuraj Linkešclass DTSError(Exception): 426ef07151SJuraj Linkeš """The base exception from which all DTS exceptions are subclassed. 436ef07151SJuraj Linkeš 446ef07151SJuraj Linkeš Do not use this exception, only use subclassed exceptions. 4578534506SJuraj Linkeš """ 4678534506SJuraj Linkeš 476ef07151SJuraj Linkeš #: 4878534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.GENERIC_ERR 4978534506SJuraj Linkeš 5078534506SJuraj Linkeš 5178534506SJuraj Linkešclass SSHTimeoutError(DTSError): 526ef07151SJuraj Linkeš """The SSH execution of a command timed out.""" 53812c4071SJuraj Linkeš 546ef07151SJuraj Linkeš #: 5578534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 56840b1e01SJuraj Linkeš _command: str 57812c4071SJuraj Linkeš 58840b1e01SJuraj Linkeš def __init__(self, command: str): 596ef07151SJuraj Linkeš """Define the meaning of the first argument. 606ef07151SJuraj Linkeš 616ef07151SJuraj Linkeš Args: 626ef07151SJuraj Linkeš command: The executed command. 636ef07151SJuraj Linkeš """ 64840b1e01SJuraj Linkeš self._command = command 65812c4071SJuraj Linkeš 66812c4071SJuraj Linkeš def __str__(self) -> str: 676ef07151SJuraj Linkeš """Add some context to the string representation.""" 686ef07151SJuraj Linkeš return f"{self._command} execution timed out." 69812c4071SJuraj Linkeš 70812c4071SJuraj Linkeš 7178534506SJuraj Linkešclass SSHConnectionError(DTSError): 726ef07151SJuraj Linkeš """An unsuccessful SSH connection.""" 73812c4071SJuraj Linkeš 746ef07151SJuraj Linkeš #: 7578534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 76840b1e01SJuraj Linkeš _host: str 77840b1e01SJuraj Linkeš _errors: list[str] 78812c4071SJuraj Linkeš 79b8bdc4c5SJuraj Linkeš def __init__(self, host: str, errors: list[str] | None = None): 806ef07151SJuraj Linkeš """Define the meaning of the first two arguments. 816ef07151SJuraj Linkeš 826ef07151SJuraj Linkeš Args: 836ef07151SJuraj Linkeš host: The hostname to which we're trying to connect. 846ef07151SJuraj Linkeš errors: Any errors that occurred during the connection attempt. 856ef07151SJuraj Linkeš """ 86840b1e01SJuraj Linkeš self._host = host 87840b1e01SJuraj Linkeš self._errors = [] if errors is None else errors 88812c4071SJuraj Linkeš 89812c4071SJuraj Linkeš def __str__(self) -> str: 906ef07151SJuraj Linkeš """Include the errors in the string representation.""" 91840b1e01SJuraj Linkeš message = f"Error trying to connect with {self._host}." 92840b1e01SJuraj Linkeš if self._errors: 93840b1e01SJuraj Linkeš message += f" Errors encountered while retrying: {', '.join(self._errors)}" 94b8bdc4c5SJuraj Linkeš 95b8bdc4c5SJuraj Linkeš return message 96812c4071SJuraj Linkeš 97812c4071SJuraj Linkeš 9878534506SJuraj Linkešclass SSHSessionDeadError(DTSError): 996ef07151SJuraj Linkeš """The SSH session is no longer alive.""" 100812c4071SJuraj Linkeš 1016ef07151SJuraj Linkeš #: 10278534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.SSH_ERR 103840b1e01SJuraj Linkeš _host: str 104812c4071SJuraj Linkeš 105812c4071SJuraj Linkeš def __init__(self, host: str): 1066ef07151SJuraj Linkeš """Define the meaning of the first argument. 1076ef07151SJuraj Linkeš 1086ef07151SJuraj Linkeš Args: 1096ef07151SJuraj Linkeš host: The hostname of the disconnected node. 1106ef07151SJuraj Linkeš """ 111840b1e01SJuraj Linkeš self._host = host 112812c4071SJuraj Linkeš 113812c4071SJuraj Linkeš def __str__(self) -> str: 1146ef07151SJuraj Linkeš """Add some context to the string representation.""" 1156ef07151SJuraj Linkeš return f"SSH session with {self._host} has died." 11678534506SJuraj Linkeš 11778534506SJuraj Linkeš 11878534506SJuraj Linkešclass ConfigurationError(DTSError): 1196ef07151SJuraj Linkeš """An invalid configuration.""" 12078534506SJuraj Linkeš 1216ef07151SJuraj Linkeš #: 12278534506SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.CONFIG_ERR 123ad80f550SJuraj Linkeš 124ad80f550SJuraj Linkeš 125ad80f550SJuraj Linkešclass RemoteCommandExecutionError(DTSError): 1266ef07151SJuraj Linkeš """An unsuccessful execution of a remote command.""" 127ad80f550SJuraj Linkeš 1286ef07151SJuraj Linkeš #: 129ad80f550SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 1306ef07151SJuraj Linkeš #: The executed command. 131840b1e01SJuraj Linkeš command: str 132840b1e01SJuraj Linkeš _command_return_code: int 133ad80f550SJuraj Linkeš 134ad80f550SJuraj Linkeš def __init__(self, command: str, command_return_code: int): 1356ef07151SJuraj Linkeš """Define the meaning of the first two arguments. 1366ef07151SJuraj Linkeš 1376ef07151SJuraj Linkeš Args: 1386ef07151SJuraj Linkeš command: The executed command. 1396ef07151SJuraj Linkeš command_return_code: The return code of the executed command. 1406ef07151SJuraj Linkeš """ 141ad80f550SJuraj Linkeš self.command = command 142840b1e01SJuraj Linkeš self._command_return_code = command_return_code 143ad80f550SJuraj Linkeš 144ad80f550SJuraj Linkeš def __str__(self) -> str: 1456ef07151SJuraj Linkeš """Include both the command and return code in the string representation.""" 146840b1e01SJuraj Linkeš return f"Command {self.command} returned a non-zero exit code: {self._command_return_code}" 147680d8a24SJuraj Linkeš 148680d8a24SJuraj Linkeš 149*369d34b8SJeremy Spewockclass InteractiveCommandExecutionError(DTSError): 150*369d34b8SJeremy Spewock """An unsuccessful execution of a remote command in an interactive environment.""" 151*369d34b8SJeremy Spewock 152*369d34b8SJeremy Spewock #: 153*369d34b8SJeremy Spewock severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 154*369d34b8SJeremy Spewock 155*369d34b8SJeremy Spewock 156680d8a24SJuraj Linkešclass RemoteDirectoryExistsError(DTSError): 1576ef07151SJuraj Linkeš """A directory that exists on a remote node.""" 158680d8a24SJuraj Linkeš 1596ef07151SJuraj Linkeš #: 160680d8a24SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.REMOTE_CMD_EXEC_ERR 161680d8a24SJuraj Linkeš 162680d8a24SJuraj Linkeš 163680d8a24SJuraj Linkešclass DPDKBuildError(DTSError): 1646ef07151SJuraj Linkeš """A DPDK build failure.""" 165680d8a24SJuraj Linkeš 1666ef07151SJuraj Linkeš #: 167680d8a24SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.DPDK_BUILD_ERR 1686fc05ca7SJuraj Linkeš 1696fc05ca7SJuraj Linkeš 1706fc05ca7SJuraj Linkešclass TestCaseVerifyError(DTSError): 1716ef07151SJuraj Linkeš """A test case failure.""" 1726fc05ca7SJuraj Linkeš 1736ef07151SJuraj Linkeš #: 1746fc05ca7SJuraj Linkeš severity: ClassVar[ErrorSeverity] = ErrorSeverity.TESTCASE_VERIFY_ERR 1756fc05ca7SJuraj Linkeš 17688489c05SJeremy Spewock 17788489c05SJeremy Spewockclass BlockingTestSuiteError(DTSError): 1786ef07151SJuraj Linkeš """A failure in a blocking test suite.""" 1796ef07151SJuraj Linkeš 1806ef07151SJuraj Linkeš #: 18188489c05SJeremy Spewock severity: ClassVar[ErrorSeverity] = ErrorSeverity.BLOCKING_TESTSUITE_ERR 182840b1e01SJuraj Linkeš _suite_name: str 18388489c05SJeremy Spewock 18488489c05SJeremy Spewock def __init__(self, suite_name: str) -> None: 1856ef07151SJuraj Linkeš """Define the meaning of the first argument. 1866ef07151SJuraj Linkeš 1876ef07151SJuraj Linkeš Args: 1886ef07151SJuraj Linkeš suite_name: The blocking test suite. 1896ef07151SJuraj Linkeš """ 190840b1e01SJuraj Linkeš self._suite_name = suite_name 19188489c05SJeremy Spewock 19288489c05SJeremy Spewock def __str__(self) -> str: 1936ef07151SJuraj Linkeš """Add some context to the string representation.""" 194840b1e01SJuraj Linkeš return f"Blocking suite {self._suite_name} failed." 195