8
8
import re
9
9
import secrets
10
10
import shlex
11
- import shutil
12
11
import signal as _signal
13
12
import string
14
13
import subprocess
57
56
ProvisionError ,
58
57
ShellScript ,
59
58
configure_constant ,
60
- create_directory ,
61
59
effective_workdir_root ,
62
60
)
63
61
@@ -981,14 +979,33 @@ def show(
981
979
class GuestLog :
982
980
name : str
983
981
984
- def fetch (self ) -> Optional [ str ] :
982
+ def fetch (self ) -> str :
985
983
"""
986
984
Fetch and return content of a log.
987
985
988
986
:returns: content of the log, or ``None`` if the log cannot be retrieved.
989
987
"""
990
988
raise NotImplementedError
991
989
990
+ def store (self , path : Path , logname : Optional [str ] = None ) -> None :
991
+ """
992
+ Save log content to a file.
993
+
994
+ :param path: a path to save into, could be a directory
995
+ or a file path.
996
+ :param content: content of the log.
997
+ :param logname: name of the log, if not set, logpath
998
+ is supposed to be a file path.
999
+ """
1000
+ # if path is file path
1001
+ if not path .is_dir ():
1002
+ path .write_text (self .fetch ())
1003
+ # if path is a directory
1004
+ elif logname :
1005
+ (path / logname ).write_text (self .fetch ())
1006
+ else :
1007
+ raise tmt .utils .GeneralError ('Log path is a directory but log name is not defined.' )
1008
+
992
1009
993
1010
class Guest (tmt .utils .Common ):
994
1011
"""
@@ -1031,8 +1048,6 @@ def get_data_class(cls) -> type[GuestData]:
1031
1048
#: Guest topology hostname or IP address for guest/guest communication.
1032
1049
topology_address : Optional [str ] = None
1033
1050
1034
- guest_logs : list [GuestLog ] = []
1035
-
1036
1051
become : bool
1037
1052
1038
1053
hardware : Optional [tmt .hardware .Hardware ]
@@ -1058,6 +1073,7 @@ def __init__(
1058
1073
"""
1059
1074
Initialize guest data
1060
1075
"""
1076
+ self .guest_logs : list [GuestLog ] = []
1061
1077
1062
1078
super ().__init__ (logger = logger , parent = parent , name = name )
1063
1079
self .load (data )
@@ -1719,33 +1735,12 @@ def essential_requires(cls) -> list['tmt.base.Dependency']:
1719
1735
1720
1736
return []
1721
1737
1722
- def acquire_log (self , logname : str ) -> Optional [str ]:
1723
- """
1724
- Fetch and return content of a log.
1725
-
1726
- :param logname: name of the log.
1727
- :returns: content of the log, or ``None`` if the log cannot be retrieved.
1728
- """
1729
- raise NotImplementedError
1730
-
1731
- def store_log (self , path : Path , content : str , logname : Optional [str ] = None ) -> None :
1738
+ @property
1739
+ def logdir (self ) -> Optional [Path ]:
1732
1740
"""
1733
- Save log content to a file.
1734
-
1735
- :param path: a path to save into, could be a directory
1736
- or a file path.
1737
- :param content: content of the log.
1738
- :param logname: name of the log, if not set, logpath
1739
- is supposed to be a file path.
1741
+ Path to store logs
1740
1742
"""
1741
- # if path is file path
1742
- if not path .is_dir ():
1743
- path .write_text (content )
1744
- # if path is a directory
1745
- elif logname :
1746
- (path / logname ).write_text (content )
1747
- else :
1748
- raise tmt .utils .GeneralError ('Log path is a directory but log name is not defined.' )
1743
+ return self .workdir / 'logs' if self .workdir else None
1749
1744
1750
1745
def fetch_logs (
1751
1746
self , dirpath : Optional [Path ] = None , guest_logs : Optional [list [GuestLog ]] = None
@@ -1761,17 +1756,11 @@ def fetch_logs(
1761
1756
1762
1757
guest_logs = guest_logs or self .guest_logs or []
1763
1758
1764
- dirpath = dirpath or (self .workdir / 'logs' if self .workdir else None ) or Path .cwd ()
1765
- if self .workdir and dirpath == self .workdir / 'logs' :
1766
- create_directory (
1767
- path = self .workdir / 'logs' , name = 'logs workdir' , quiet = True , logger = self ._logger
1768
- )
1759
+ dirpath = dirpath or self .logdir or Path .cwd ()
1760
+ if dirpath == self .logdir :
1761
+ self .logdir .mkdir (parents = True , exist_ok = True )
1769
1762
for log in guest_logs :
1770
- content = log .fetch ()
1771
- if content :
1772
- self .store_log (dirpath , content , log .name )
1773
- else :
1774
- self .store_log (dirpath , '' , log .name )
1763
+ log .store (dirpath , log .name )
1775
1764
1776
1765
1777
1766
@container
@@ -2809,28 +2798,6 @@ def show(self, keys: Optional[list[str]] = None) -> None:
2809
2798
if hardware :
2810
2799
echo (tmt .utils .format ('hardware' , tmt .utils .dict_to_yaml (hardware .to_spec ())))
2811
2800
2812
- def prune (self , logger : tmt .log .Logger ) -> None :
2813
- """Do not prune logs"""
2814
- if self .workdir is None :
2815
- return
2816
-
2817
- logs_dir = self .workdir / 'logs'
2818
- if logs_dir .exists ():
2819
- for member in self .workdir .iterdir ():
2820
- if member .name == "logs" :
2821
- logger .debug (f"Preserve '{ member .relative_to (self .workdir )} '." , level = 3 )
2822
- continue
2823
- logger .debug (f"Remove '{ member } '." , level = 3 )
2824
- try :
2825
- if member .is_file () or member .is_symlink ():
2826
- member .unlink ()
2827
- else :
2828
- shutil .rmtree (member )
2829
- except OSError as error :
2830
- logger .warning (f"Unable to remove '{ member } ': { error } " )
2831
- else :
2832
- super ().prune (logger )
2833
-
2834
2801
2835
2802
@container
2836
2803
class ProvisionTask (tmt .queue .GuestlessTask [None ]):
0 commit comments