-
Notifications
You must be signed in to change notification settings - Fork 145
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
base: refactor-prune
Are you sure you want to change the base?
Handle guest logs #2647
Conversation
9fae56b
to
741af0a
Compare
d926ddc
to
e4ac9e7
Compare
Updated^^,added an Optional log_path param to handle_guest_logs,in case we
want to let users specify the log dir in the future,though users can
specify --workdir-root.
…On Tue, Jan 30, 2024 at 12:08 AM Miloš Prchlík ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In tmt/steps/provision/local.py
<#2647 (comment)>:
> @@ -133,6 +133,43 @@ def pull(
extend_options: Optional[list[str]] = None) -> None:
""" Nothing to be done to pull workdir """
+ def acquire_log(self, log_name: str) -> Optional[str]:
+ """fetch and return content of a requested log"""
+ if log_name == 'dmesg':
+ return self.execute(Command('dmesg')).stdout
+ return None
+
+ def store_log(
+ self,
+ log_name: Optional[str],
+ log_path: Optional[Path],
Got it, I was thinking maybe users want to store the logs to dir they ran
tmt command:)
Maybe, that sounds like something users might do, but then again, it would
not be something for store_log() to decide, but for other parts of tmt,
e.g tmt.base.Run which implements tmt run: this class would decide where
to put logs, and it would task provision step with the right directory.
—
Reply to this email directly, view it on GitHub
<#2647 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AKFR23AR6H3AJ5E723H3M2DYQ7CNXAVCNFSM6AAAAABCL3RX52VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMYTQNBZGA2TOMRUGU>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
2123597
to
28f9152
Compare
686353f
to
d0556f0
Compare
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 |
d0556f0
to
bc1c505
Compare
tmt/steps/provision/__init__.py
Outdated
@@ -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] = [] |
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.
- it's already in
Guest
class,guest_
prefix is superfluous.Guest.guest_logs
vsGuest.logs
- 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.
tmt/steps/provision/__init__.py
Outdated
@@ -1646,6 +1663,60 @@ def essential_requires(cls) -> list['tmt.base.Dependency']: | |||
|
|||
return [] | |||
|
|||
def acquire_log(self, logname: str) -> Optional[str]: |
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.
This method is probably not needed anymore.
tmt/steps/provision/__init__.py
Outdated
""" | ||
raise NotImplementedError | ||
|
||
def store_log(self, path: Path, content: str, logname: Optional[str] = None) -> None: |
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.
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()
?
bc1c505
to
59ff59c
Compare
tmt/steps/provision/mrack.py
Outdated
|
||
if self.name == 'dmesg': | ||
return self.guest.execute(Command('dmesg')).stdout | ||
return tmt.utils.get_url_content(self.url) if self.url else None |
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.
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.
tmt/steps/provision/mrack.py
Outdated
|
||
@container | ||
class GuestLogBeaker(tmt.steps.provision.GuestLog): | ||
def __init__(self, guest: GuestBeaker, name: str, url: Optional[str] = None) -> None: |
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.
With container
, you shouldn't need custom __init__()
, one will be generated automagically for you.
tmt/steps/provision/__init__.py
Outdated
|
||
guest_logs = guest_logs or self.guest_logs or [] | ||
|
||
dirpath = dirpath or (self.workdir / 'logs' if self.workdir else None) or Path.cwd() |
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.
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.
tmt/steps/provision/__init__.py
Outdated
if self.workdir is None: | ||
return | ||
|
||
logs_dir = self.workdir / 'logs' |
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.
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. With
guest.logdir`, and using it in conditions and calls, we would need to change just one place.
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.
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 ;)
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.
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^^
Fetch log content,save it to provided location or current dir
59ff59c
to
b4276e0
Compare
wow,thanks for your super quick response and valuable feedbacks,impressed again,and updated^^ |
0c5ea3b
to
a27ec85
Compare
0c91b12
to
b1c66b1
Compare
Fetch log content and save it to the workdir/provision/ List the log dir in guests.yaml
Pull Request Checklist