Skip to content

Commit 10a8fde

Browse files
committed
added lshw and lscpu cmds
1 parent 965103b commit 10a8fde

File tree

3 files changed

+75
-4
lines changed

3 files changed

+75
-4
lines changed

nodescraper/plugins/inband/device_enumeration/device_enumeration_collector.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from typing import Optional
2727

2828
from nodescraper.base import InBandDataCollector
29-
from nodescraper.connection.inband.inband import CommandArtifact
29+
from nodescraper.connection.inband.inband import CommandArtifact, TextFileArtifact
3030
from nodescraper.enums import EventCategory, EventPriority, ExecutionStatus, OSFamily
3131
from nodescraper.models import TaskResult
3232

@@ -41,6 +41,8 @@ class DeviceEnumerationCollector(InBandDataCollector[DeviceEnumerationDataModel,
4141
CMD_CPU_COUNT_LINUX = "lscpu | grep Socket | awk '{ print $2 }'"
4242
CMD_GPU_COUNT_LINUX = "lspci -d {vendorid_ep}: | grep -i 'VGA\\|Display\\|3D' | wc -l"
4343
CMD_VF_COUNT_LINUX = "lspci -d {vendorid_ep}: | grep -i 'Virtual Function' | wc -l"
44+
CMD_LSCPU_LINUX = "/usr/bin/lscpu"
45+
CMD_LSHW_LINUX = "lshw"
4446

4547
CMD_CPU_COUNT_WINDOWS = (
4648
'powershell -Command "(Get-WmiObject -Class Win32_Processor | Measure-Object).Count"'
@@ -86,6 +88,12 @@ def collect_data(self, args=None) -> tuple[TaskResult, Optional[DeviceEnumeratio
8688

8789
# Count AMD Virtual Functions
8890
vf_count_res = self._run_sut_cmd(self.CMD_VF_COUNT_LINUX.format(vendorid_ep=vendor_id))
91+
92+
# Collect lscpu output
93+
lscpu_res = self._run_sut_cmd(self.CMD_LSCPU_LINUX, log_artifact=False)
94+
95+
# Collect lshw output
96+
lshw_res = self._run_sut_cmd(self.CMD_LSHW_LINUX, sudo=True, log_artifact=False)
8997
else:
9098
cpu_count_res = self._run_sut_cmd(self.CMD_CPU_COUNT_WINDOWS)
9199
gpu_count_res = self._run_sut_cmd(self.CMD_GPU_COUNT_WINDOWS)
@@ -112,14 +120,42 @@ def collect_data(self, args=None) -> tuple[TaskResult, Optional[DeviceEnumeratio
112120
category=EventCategory.SW_DRIVER,
113121
)
114122

123+
if self.system_info.os_family == OSFamily.LINUX:
124+
if lscpu_res.exit_code == 0 and lscpu_res.stdout:
125+
device_enum.lscpu_output = lscpu_res.stdout
126+
self._log_event(
127+
category=EventCategory.PLATFORM,
128+
description="Collected lscpu output",
129+
priority=EventPriority.INFO,
130+
)
131+
else:
132+
self._warning(description="Cannot collect lscpu output", command=lscpu_res)
133+
134+
if lshw_res.exit_code == 0 and lshw_res.stdout:
135+
device_enum.lshw_output = lshw_res.stdout
136+
self.result.artifacts.append(
137+
TextFileArtifact(filename="lshw.txt", contents=lshw_res.stdout)
138+
)
139+
self._log_event(
140+
category=EventCategory.PLATFORM,
141+
description="Collected lshw output",
142+
priority=EventPriority.INFO,
143+
)
144+
else:
145+
self._warning(description="Cannot collect lshw output", command=lshw_res)
146+
115147
if device_enum.cpu_count or device_enum.gpu_count or device_enum.vf_count:
148+
log_data = device_enum.model_dump(
149+
exclude_none=True,
150+
exclude={"lscpu_output", "lshw_output", "task_name", "task_type", "parent"},
151+
)
116152
self._log_event(
117153
category=EventCategory.PLATFORM,
118154
description=f"Counted {device_enum.cpu_count} CPUs, {device_enum.gpu_count} GPUs, {device_enum.vf_count} VFs",
119-
data=device_enum.model_dump(exclude_none=True),
155+
data=log_data,
120156
priority=EventPriority.INFO,
121157
)
122-
self.result.message = f"Device Enumeration: {device_enum.model_dump(exclude_none=True)}"
158+
self.result.message = f"Device Enumeration: {log_data}"
123159
self.result.status = ExecutionStatus.OK
124160
return self.result, device_enum
125161
else:

nodescraper/plugins/inband/device_enumeration/deviceenumdata.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ class DeviceEnumerationDataModel(DataModel):
3232
cpu_count: Optional[int] = None
3333
gpu_count: Optional[int] = None
3434
vf_count: Optional[int] = None
35+
lscpu_output: Optional[str] = None
36+
lshw_output: Optional[str] = None

test/unit/plugin/test_device_enumeration_collector.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ def test_collect_linux(system_info, device_enumeration_collector):
5151
"""Test linux typical output"""
5252
system_info.os_family = OSFamily.LINUX
5353

54+
lscpu_output = "Architecture: x86_64\nCPU(s): 64\nSocket(s): 2"
55+
lshw_output = "*-cpu\n product: AMD EPYC 1234 64-Core Processor"
56+
5457
device_enumeration_collector._run_sut_cmd = MagicMock(
5558
side_effect=[
5659
MagicMock(
@@ -71,12 +74,30 @@ def test_collect_linux(system_info, device_enumeration_collector):
7174
stderr="",
7275
command="lspci -d 1002: | grep -i 'Virtual Function' | wc -l",
7376
),
77+
MagicMock(
78+
exit_code=0,
79+
stdout=lscpu_output,
80+
stderr="",
81+
command="/usr/bin/lscpu",
82+
),
83+
MagicMock(
84+
exit_code=0,
85+
stdout=lshw_output,
86+
stderr="",
87+
command="lshw",
88+
),
7489
]
7590
)
7691

7792
result, data = device_enumeration_collector.collect_data()
7893
assert result.status == ExecutionStatus.OK
79-
assert data == DeviceEnumerationDataModel(cpu_count=2, gpu_count=8, vf_count=0)
94+
assert data == DeviceEnumerationDataModel(
95+
cpu_count=2, gpu_count=8, vf_count=0, lscpu_output=lscpu_output, lshw_output=lshw_output
96+
)
97+
assert (
98+
len([a for a in result.artifacts if hasattr(a, "filename") and a.filename == "lshw.txt"])
99+
== 1
100+
)
80101

81102

82103
def test_collect_windows(system_info, device_enumeration_collector):
@@ -135,6 +156,18 @@ def test_collect_error(system_info, device_enumeration_collector):
135156
stderr="command failed",
136157
command="lspci -d 1002: | grep -i 'Virtual Function' | wc -l",
137158
),
159+
MagicMock(
160+
exit_code=1,
161+
stdout="",
162+
stderr="command failed",
163+
command="/usr/bin/lscpu",
164+
),
165+
MagicMock(
166+
exit_code=1,
167+
stdout="",
168+
stderr="command failed",
169+
command="lshw",
170+
),
138171
]
139172
)
140173

0 commit comments

Comments
 (0)