-
Couldn't load subscription status.
- Fork 219
Collect log using SerialConsole when SshShell fails to connect #3845
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
adityagesh
wants to merge
14
commits into
main
Choose a base branch
from
aditya/serial_log_after_test_failure
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
bbfc6a5
Collect log using SerialConsole when SshShell fails to connect
adityagesh f995104
SerialConsole login
adityagesh c063261
Add RunCommand feature in Azure and use it to collect logs
adityagesh a1ca77b
Revert changes - to be squashed at the end
adityagesh cbf9894
Remove serial console log collection for network failure
adityagesh 7935505
Add RunCommand class
adityagesh 82ed779
Changes based on review commands
adityagesh 74c92e8
Review comments
adityagesh 4809777
Update commands to execute
adityagesh 40957a3
Serial Console: check for prompt before executing
adityagesh 372506c
Fix connection alive issue
adityagesh 83abbd5
RunCommand to run one command at a time due to return size limitation
adityagesh 737ca41
Update review comments
adityagesh c8cd146
Update Serial Console prompt check
adityagesh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import re | ||
| from typing import List | ||
|
|
||
| from lisa.feature import Feature | ||
| from lisa.features.serial_console import SerialConsole | ||
| from lisa.util import LisaException | ||
|
|
||
|
|
||
| class NonSshExecutor(Feature): | ||
| """ | ||
| NonSshExecutor is used to run commands on the node when SSH is not available. | ||
| Lisa by default uses SSH for connection, but this feature provides an alternative | ||
| execution method for scenarios where SSH connectivity is not possible or desired. | ||
| """ | ||
|
|
||
| @classmethod | ||
| def name(cls) -> str: | ||
| return "NonSshExecutor" | ||
|
|
||
| def enabled(self) -> bool: | ||
| return True | ||
|
|
||
| def execute(self, commands: List[str]) -> List[str]: | ||
| """ | ||
| Executes a list of commands on the node and returns their outputs. | ||
|
|
||
| :param commands: A list of shell commands to execute. | ||
| :return: A string containing the output of the executed commands. | ||
| """ | ||
|
|
||
| if not self._node.features.is_supported(SerialConsole): | ||
| raise NotImplementedError( | ||
| "NonSshExecutor requires SerialConsole feature to be supported." | ||
| ) | ||
| out = self._execute(commands) | ||
| return out | ||
|
|
||
| def _execute(self, commands: List[str]) -> List[str]: | ||
| out: List[str] = [] | ||
| serial_console = self._node.features[SerialConsole] | ||
| try: | ||
| serial_console.ensure_login() | ||
| # clear the console before executing commands | ||
| _ = serial_console.read() | ||
| # write a newline and read to make sure serial console has the prompt | ||
| serial_console.write("\n") | ||
| response = serial_console.read() | ||
|
|
||
| # Check for full prompt pattern instead of individual characters | ||
| if not self._is_valid_prompt(response): | ||
| raise LisaException( | ||
| f"Valid shell prompt not found in output. " | ||
| f"Expected a shell prompt ending with $, #, or >, " | ||
| f"but got: {response.strip()}" | ||
| ) | ||
|
|
||
| for command in commands: | ||
| serial_console.write(self._add_newline(command)) | ||
| out.append(serial_console.read()) | ||
| collected_info = "\n\n".join(out) | ||
| self._log.info( | ||
| f"Collected information using NonSshExecutor:\n{collected_info}" | ||
| ) | ||
| return out | ||
| except Exception as e: | ||
| raise LisaException(f"Failed to execute commands: {e}") from e | ||
| finally: | ||
| serial_console.close() | ||
|
|
||
| def _is_valid_prompt(self, response: str) -> bool: | ||
| """ | ||
| Check if the response contains a valid shell prompt pattern. | ||
|
|
||
| :param response: The response from the serial console | ||
| :return: True if a valid prompt is found, False otherwise | ||
| """ | ||
| if not response: | ||
| return False | ||
|
|
||
| # Generic pattern that matches any prompt format: | ||
| # - Username and hostname part: word chars, @, hyphens, dots | ||
| # - Colon separator | ||
| # - Path part: ~, /, word chars, dots, hyphens, slashes | ||
| # - Optional whitespace | ||
| # - Ending with $, #, or > | ||
| # - Optional trailing whitespace | ||
| prompt_pattern = r"[a-zA-Z0-9_@.-]+:[~/a-zA-Z0-9_./-]*\s*[\$#>]\s*$" | ||
|
|
||
| # Check each line in the response for the prompt pattern | ||
| lines = response.split("\n") | ||
| for line in lines: | ||
| line = line.strip() | ||
| if re.search(prompt_pattern, line): | ||
| self._log.debug(f"Valid prompt found: '{line}'") | ||
| return True | ||
|
|
||
| self._log.debug(f"No valid prompt found in response: '{response.strip()}'") | ||
| return False | ||
|
|
||
| def _add_newline(self, command: str) -> str: | ||
| """ | ||
| Adds a newline character to the command if it does not already end with one. | ||
| newline is required to run the command in serial console. | ||
| """ | ||
| if not command.endswith("\n"): | ||
| return f"{command}\n" | ||
| return command |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this Linux specific? Consider whether you can add support for Windows. If not possible, think about how to exclude the Feature for non-Posix systems.