Skip to content

Commit 9053667

Browse files
committed
reading logs
1 parent 4463430 commit 9053667

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

nodescraper/plugins/inband/dmesg/dmesg_collector.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
# SOFTWARE.
2424
#
2525
###############################################################################
26+
import re
27+
2628
from nodescraper.base import InBandDataCollector
29+
from nodescraper.connection.inband import FileArtifact
2730
from nodescraper.enums import EventCategory, EventPriority, OSFamily
2831
from nodescraper.models import TaskResult
2932

@@ -39,6 +42,84 @@ class DmesgCollector(InBandDataCollector[DmesgData, None]):
3942

4043
DMESG_CMD = "dmesg --time-format iso -x"
4144

45+
DMESG_LIST_CMD = (
46+
r"ls -1 /var/log/dmesg /var/log/dmesg.1 /var/log/dmesg.[0-9]*.gz 2>/dev/null || true"
47+
)
48+
49+
def _shell_quote(self, s: str) -> str:
50+
"""POSIX single-quote."""
51+
return "'" + s.replace("'", "'\"'\"'") + "'"
52+
53+
def _nice_dmesg_name(self, path: str) -> str:
54+
"""Map path to filename"""
55+
if path.endswith("/dmesg"):
56+
return "dmesg.log"
57+
if path.endswith("/dmesg.1"):
58+
return "dmesg.1.log"
59+
m = re.search(r"/dmesg\.(\d+)\.gz$", path)
60+
if m:
61+
return f"dmesg.{m.group(1)}.log"
62+
base = path.rsplit("/", 1)[-1]
63+
return base.replace(".gz", "") + ".log"
64+
65+
def _collect_dmesg_rotations(self) -> int:
66+
"""
67+
Collect /var/log/dmesg, /var/log/dmesg.1, and /var/log/dmesg.N.gz (decompressed).
68+
Attaches each as a text artifact.
69+
70+
Returns:
71+
list: list of logs collected.
72+
73+
"""
74+
list_res = self._run_sut_cmd(self.DMESG_LIST_CMD)
75+
paths = [p.strip() for p in (list_res.stdout or "").splitlines() if p.strip()]
76+
if not paths:
77+
self._log_event(
78+
category=EventCategory.OS,
79+
description="No /var/log/dmesg files found (including rotations).",
80+
data={"list_exit_code": list_res.exit_code},
81+
priority=EventPriority.WARNING,
82+
)
83+
return 0
84+
85+
collected, failed = [], []
86+
for p in paths:
87+
qp = self._shell_quote(p)
88+
if p.endswith(".gz"):
89+
cmd = f"(command -v gzip >/dev/null && gzip -dc {qp}) || (command -v zcat >/dev/null && zcat {qp}) || cat {qp}"
90+
else:
91+
cmd = f"cat {qp}"
92+
93+
res = self._run_sut_cmd(cmd)
94+
if res.exit_code == 0 and res.stdout is not None:
95+
fname = self._nice_dmesg_name(p)
96+
self.result.artifacts.append(FileArtifact(filename=fname, contents=res.stdout))
97+
collected.append(
98+
{"path": p, "as": fname, "bytes": len(res.stdout.encode("utf-8", "ignore"))}
99+
)
100+
else:
101+
failed.append({"path": p, "exit_code": res.exit_code, "stderr": res.stderr})
102+
103+
if collected:
104+
self._log_event(
105+
category=EventCategory.OS,
106+
description="Collected dmesg rotated files",
107+
data={"collected": collected},
108+
priority=EventPriority.INFO,
109+
)
110+
# self.result.status = self.result.status or ExecutionStatus.OK
111+
self.result.message = self.result.message or "dmesg rotated files collected"
112+
113+
if failed:
114+
self._log_event(
115+
category=EventCategory.OS,
116+
description="Some dmesg files could not be collected.",
117+
data={"failed": failed},
118+
priority=EventPriority.WARNING,
119+
)
120+
121+
return collected
122+
42123
def _get_dmesg_content(self) -> str:
43124
"""run dmesg command on system and return output
44125
@@ -68,6 +149,7 @@ def collect_data(
68149
tuple[TaskResult, DmesgData | None]: tuple containing the result of the task and the dmesg data if available
69150
"""
70151
dmesg_content = self._get_dmesg_content()
152+
_ = self._collect_dmesg_rotations()
71153

72154
if dmesg_content:
73155
dmesg_data = DmesgData(dmesg_content=dmesg_content)

nodescraper/plugins/inband/dmesg/dmesgdata.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class DmesgData(DataModel):
3434
"""Data model for in band dmesg log"""
3535

3636
dmesg_content: str
37+
dmesg_logs: list[dict] = None
3738

3839
@classmethod
3940
def get_new_dmesg_lines(cls, current_dmesg: str, new_dmesg: str) -> str:

0 commit comments

Comments
 (0)