Skip to content
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

Handle guest logs #2647

Open
wants to merge 9 commits into
base: refactor-prune
Choose a base branch
from

Conversation

skycastlelily
Copy link
Collaborator

@skycastlelily skycastlelily commented Jan 26, 2024

Fetch log content and save it to the workdir/provision/ List the log dir in guests.yaml

Pull Request Checklist

  • implement the feature
  • write the documentation
  • extend the test coverage
  • update the specification
  • adjust plugin docstring
  • modify the json schema
  • mention the version
  • include a release note

@skycastlelily skycastlelily force-pushed the guest-logs branch 2 times, most recently from 9fae56b to 741af0a Compare January 29, 2024 09:15
@skycastlelily skycastlelily force-pushed the guest-logs branch 2 times, most recently from d926ddc to e4ac9e7 Compare January 30, 2024 07:18
@skycastlelily
Copy link
Collaborator Author

skycastlelily commented Jan 30, 2024 via email

@skycastlelily skycastlelily changed the title [draft]Handle guest logs Handle guest logs Jan 30, 2024
@skycastlelily skycastlelily force-pushed the guest-logs branch 2 times, most recently from 2123597 to 28f9152 Compare February 3, 2024 03:34
@happz happz added this to the 1.43 milestone Jan 27, 2025
@happz
Copy link
Collaborator

happz commented Feb 17, 2025

As briefly discussed on Slack, there might be a better implementation, bundling together log name & a way to fetch it in a class. That should give us better handling and responsibilities, plus making nicer spot for logs that do not need to be fetched at all, like #3511

@happz happz removed this from the 1.43 milestone Feb 17, 2025
@@ -993,6 +1008,8 @@ def get_data_class(cls) -> type[GuestData]:
#: Guest topology hostname or IP address for guest/guest communication.
topology_address: Optional[str] = None

guest_logs: list[GuestLog] = []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. it's already in Guest class, guest_ prefix is superfluous. Guest.guest_logs vs Guest.logs
  2. a a class-level mutable list, I would be worried that self.guest_logs.append() below would add guest-specific logs to one shared list. The list should probably be initialized in __init__() instead.

@@ -1646,6 +1663,60 @@ def essential_requires(cls) -> list['tmt.base.Dependency']:

return []

def acquire_log(self, logname: str) -> Optional[str]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is probably not needed anymore.

"""
raise NotImplementedError

def store_log(self, path: Path, content: str, logname: Optional[str] = None) -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method can move to GuestLog class, right? There's log.fetch() followed by store_log(), why not have e.g. save() method accepting this arguments, which would then call self.fetch() and self.store()?


if self.name == 'dmesg':
return self.guest.execute(Command('dmesg')).stdout
return tmt.utils.get_url_content(self.url) if self.url else None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 dmesg should have its own subclass, right? It has a different implementation of fetch() after all
2. I'm not sure it would be always possible to run self.guest.execute(), the guest may be dead. It would be better to download Beaker's console.log instead.


@container
class GuestLogBeaker(tmt.steps.provision.GuestLog):
def __init__(self, guest: GuestBeaker, name: str, url: Optional[str] = None) -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With container, you shouldn't need custom __init__(), one will be generated automagically for you.


guest_logs = guest_logs or self.guest_logs or []

dirpath = dirpath or (self.workdir / 'logs' if self.workdir else None) or Path.cwd()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a logdir property of Guest class that does this: every part of code interested in finding where guest's logs are should use guest.logdir instead of constructing the part on their own. Then you should be able to simply run guest.logdir.mkdir(parents=True, exists_ok=True) instead of checking self.workdir again below.

if self.workdir is None:
return

logs_dir = self.workdir / 'logs'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, guest.logdir should be used, and same below - if member.name == "logs" should become if member.name == guest.logdir.name- the magical string "logs" appears way too many times through the code, if we decide to rename it to "guest-logs" tomorrow, all these strings would need to be changed. Withguest.logdir`, and using it in conditions and calls, we would need to change just one place.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another point: trying to provide custom implementation to preserve some (dynamic) filenames, and by doing so, we get different levels of logging and different behavior from one step only. That's not good. Maybe we should first change how Step.prune() works, and instead of file/directory names, we should use regular expressions. Then we could just add logs/.*\.txt to Provision._preserved_workdir_members and keep using the default prune() method. That would be a nice, self-contained PR right there ;)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the problem is  plugin.prune will remove the whole workdir even if there are preserved members in it:
and here is the mr to solve it:https://github.com/teemtee/tmt/pull/3548^^

@skycastlelily
Copy link
Collaborator Author

wow,thanks for your super quick response and valuable feedbacks,impressed again,and updated^^

@skycastlelily skycastlelily changed the base branch from main to refactor-prune February 25, 2025 10:50
@skycastlelily skycastlelily added the status | blocked The merging of PR is blocked on some other issue label Feb 25, 2025
@skycastlelily skycastlelily force-pushed the refactor-prune branch 2 times, most recently from 0c5ea3b to a27ec85 Compare February 28, 2025 03:00
@skycastlelily skycastlelily force-pushed the refactor-prune branch 2 times, most recently from 0c91b12 to b1c66b1 Compare March 12, 2025 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci | full test Pull request is ready for the full test execution priority | should medium priority, should be included in the next release status | blocked The merging of PR is blocked on some other issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants