Skip to content

Commit d86215f

Browse files
committed
Merge branch 'development' into alex_syslog
2 parents 1fe9aee + 5da03b4 commit d86215f

File tree

17 files changed

+243
-32
lines changed

17 files changed

+243
-32
lines changed

nodescraper/cli/cli.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,13 @@ def build_parser(
154154
help="Generate reference config from system. Writes to ./reference_config.json.",
155155
)
156156

157+
parser.add_argument(
158+
"--skip-sudo",
159+
dest="skip_sudo",
160+
action="store_true",
161+
help="Skip plugins that require sudo permissions",
162+
)
163+
157164
subparsers = parser.add_subparsers(dest="subcmd", help="Subcommands")
158165

159166
summary_parser = subparsers.add_parser(
@@ -418,6 +425,11 @@ def main(arg_input: Optional[list[str]] = None):
418425
plugin_subparser_map=plugin_subparser_map,
419426
)
420427

428+
if parsed_args.skip_sudo:
429+
plugin_config_inst_list[-1].global_args.setdefault("collection_args", {})[
430+
"skip_sudo"
431+
] = True
432+
421433
log_system_info(log_path, system_info, logger)
422434
except Exception as e:
423435
parser.error(str(e))

nodescraper/models/event.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class Event(BaseModel):
5050
timestamp: datetime.datetime = Field(
5151
default_factory=lambda: datetime.datetime.now(datetime.timezone.utc)
5252
)
53-
reporter: str = "ERROR_SCRAPER"
53+
reporter: str = "NODE_SCRAPER"
5454
category: str
5555
description: str
5656
data: dict = Field(default_factory=dict)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
###############################################################################
2+
#
3+
# MIT License
4+
#
5+
# Copyright (c) 2025 Advanced Micro Devices, Inc.
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in all
15+
# copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
# SOFTWARE.
24+
#
25+
###############################################################################
26+
27+
from nodescraper.models import CollectorArgs
28+
29+
30+
class DimmCollectorArgs(CollectorArgs):
31+
skip_sudo: bool = False

nodescraper/plugins/inband/dimm/dimm_collector.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,29 @@
2323
# SOFTWARE.
2424
#
2525
###############################################################################
26+
from typing import Optional
27+
2628
from nodescraper.base import InBandDataCollector
2729
from nodescraper.enums import EventCategory, EventPriority, ExecutionStatus, OSFamily
2830
from nodescraper.models import TaskResult
2931

32+
from .collector_args import DimmCollectorArgs
3033
from .dimmdata import DimmDataModel
3134

3235

33-
class DimmCollector(InBandDataCollector[DimmDataModel, None]):
36+
class DimmCollector(InBandDataCollector[DimmDataModel, DimmCollectorArgs]):
3437
"""Collect data on installed DIMMs"""
3538

3639
DATA_MODEL = DimmDataModel
3740

3841
def collect_data(
3942
self,
40-
args=None,
43+
args: Optional[DimmCollectorArgs] = None,
4144
) -> tuple[TaskResult, DimmDataModel | None]:
4245
"""Collect data on installed DIMMs"""
46+
if args is None:
47+
args = DimmCollectorArgs()
48+
4349
dimm_str = None
4450
if self.system_info.os_family == OSFamily.WINDOWS:
4551
res = self._run_sut_cmd("wmic memorychip get Capacity")
@@ -59,6 +65,10 @@ def collect_data(
5965
for capacity, count in capacities.items():
6066
dimm_str += f"{count} x {capacity / 1024 / 1024:.2f}GB "
6167
else:
68+
if args.skip_sudo:
69+
self.result.message = "Skipping sudo plugin"
70+
self.result.status = ExecutionStatus.NOT_RAN
71+
return self.result, None
6272
res = self._run_sut_cmd(
6373
"""sh -c 'dmidecode -t 17 | tr -s " " | grep -v "Volatile\\|None\\|Module" | grep Size' 2>/dev/null""",
6474
sudo=True,

nodescraper/plugins/inband/dimm/dimm_plugin.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@
2525
###############################################################################
2626
from nodescraper.base import InBandDataPlugin
2727

28+
from .collector_args import DimmCollectorArgs
2829
from .dimm_collector import DimmCollector
2930
from .dimmdata import DimmDataModel
3031

3132

32-
class DimmPlugin(InBandDataPlugin[DimmDataModel, None, None]):
33+
class DimmPlugin(InBandDataPlugin[DimmDataModel, DimmCollectorArgs, None]):
3334
"""Plugin for collection and analysis of DIMM data"""
3435

3536
DATA_MODEL = DimmDataModel
3637

3738
COLLECTOR = DimmCollector
39+
40+
COLLECTOR_ARGS = DimmCollectorArgs
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
###############################################################################
2+
#
3+
# MIT License
4+
#
5+
# Copyright (c) 2025 Advanced Micro Devices, Inc.
6+
#
7+
# Permission is hereby granted, free of charge, to any person obtaining a copy
8+
# of this software and associated documentation files (the "Software"), to deal
9+
# in the Software without restriction, including without limitation the rights
10+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
# copies of the Software, and to permit persons to whom the Software is
12+
# furnished to do so, subject to the following conditions:
13+
#
14+
# The above copyright notice and this permission notice shall be included in all
15+
# copies or substantial portions of the Software.
16+
#
17+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
# SOFTWARE.
24+
#
25+
###############################################################################
26+
27+
from nodescraper.models import CollectorArgs
28+
29+
30+
class DmesgCollectorArgs(CollectorArgs):
31+
skip_sudo: bool = False

nodescraper/plugins/inband/dmesg/dmesg_analyzer.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class DmesgAnalyzer(RegexAnalyzer[DmesgData, DmesgAnalyzerArgs]):
5353
event_category=EventCategory.SW_DRIVER,
5454
),
5555
ErrorRegex(
56-
regex=re.compile(r"[Kk]ernel panic.*"),
56+
regex=re.compile(r"\bkernel panic\b.*", re.IGNORECASE),
5757
message="Kernel Panic",
5858
event_category=EventCategory.SW_DRIVER,
5959
),
@@ -294,6 +294,33 @@ class DmesgAnalyzer(RegexAnalyzer[DmesgData, DmesgAnalyzerArgs]):
294294
event_category=EventCategory.SW_DRIVER,
295295
event_priority=EventPriority.WARNING,
296296
),
297+
ErrorRegex(
298+
regex=re.compile(
299+
r"(?:\[[^\]]+\]\s*)?LNetError:.*ko2iblnd:\s*No matching interfaces",
300+
re.IGNORECASE,
301+
),
302+
message="LNet: ko2iblnd has no matching interfaces",
303+
event_category=EventCategory.IO,
304+
event_priority=EventPriority.WARNING,
305+
),
306+
ErrorRegex(
307+
regex=re.compile(
308+
r"(?:\[[^\]]+\]\s*)?LNetError:\s*.*Error\s*-?\d+\s+starting up LNI\s+\w+",
309+
re.IGNORECASE,
310+
),
311+
message="LNet: Error starting up LNI",
312+
event_category=EventCategory.IO,
313+
event_priority=EventPriority.WARNING,
314+
),
315+
ErrorRegex(
316+
regex=re.compile(
317+
r"LustreError:.*ptlrpc_init_portals\(\).*network initiali[sz]ation failed",
318+
re.IGNORECASE,
319+
),
320+
message="Lustre: network initialisation failed",
321+
event_category=EventCategory.IO,
322+
event_priority=EventPriority.WARNING,
323+
),
297324
]
298325

299326
@classmethod

nodescraper/plugins/inband/dmesg/dmesg_collector.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@
2323
# SOFTWARE.
2424
#
2525
###############################################################################
26+
from typing import Optional
27+
2628
from nodescraper.base import InBandDataCollector
27-
from nodescraper.enums import EventCategory, EventPriority, OSFamily
29+
from nodescraper.enums import EventCategory, EventPriority, ExecutionStatus, OSFamily
2830
from nodescraper.models import TaskResult
2931

32+
from .collector_args import DmesgCollectorArgs
3033
from .dmesgdata import DmesgData
3134

3235

33-
class DmesgCollector(InBandDataCollector[DmesgData, None]):
36+
class DmesgCollector(InBandDataCollector[DmesgData, DmesgCollectorArgs]):
3437
"""Read dmesg log"""
3538

3639
SUPPORTED_OS_FAMILY = {OSFamily.LINUX}
@@ -60,13 +63,21 @@ def _get_dmesg_content(self) -> str:
6063

6164
def collect_data(
6265
self,
63-
args=None,
66+
args: Optional[DmesgCollectorArgs] = None,
6467
) -> tuple[TaskResult, DmesgData | None]:
6568
"""Collect dmesg data from the system
6669
6770
Returns:
6871
tuple[TaskResult, DmesgData | None]: tuple containing the result of the task and the dmesg data if available
6972
"""
73+
if args is None:
74+
args = DmesgCollectorArgs()
75+
76+
if args.skip_sudo:
77+
self.result.message = "Skipping sudo plugin"
78+
self.result.status = ExecutionStatus.NOT_RAN
79+
return self.result, None
80+
7081
dmesg_content = self._get_dmesg_content()
7182

7283
if dmesg_content:

nodescraper/plugins/inband/dmesg/dmesg_plugin.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,19 @@
2626
from nodescraper.base import InBandDataPlugin
2727

2828
from .analyzer_args import DmesgAnalyzerArgs
29+
from .collector_args import DmesgCollectorArgs
2930
from .dmesg_analyzer import DmesgAnalyzer
3031
from .dmesg_collector import DmesgCollector
3132
from .dmesgdata import DmesgData
3233

3334

34-
class DmesgPlugin(InBandDataPlugin[DmesgData, None, DmesgAnalyzerArgs]):
35+
class DmesgPlugin(InBandDataPlugin[DmesgData, DmesgCollectorArgs, DmesgAnalyzerArgs]):
3536
"""Plugin for collection and analysis of dmesg data"""
3637

3738
DATA_MODEL = DmesgData
3839

3940
COLLECTOR = DmesgCollector
4041

4142
ANALYZER = DmesgAnalyzer
43+
44+
COLLECTOR_ARGS = DmesgCollectorArgs

nodescraper/plugins/inband/kernel/kernel_collector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def collect_data(
5353
"="
5454
)[1]
5555
else:
56-
res = self._run_sut_cmd("sh -c 'uname -r'", sudo=True)
56+
res = self._run_sut_cmd("sh -c 'uname -r'")
5757
if res.exit_code == 0:
5858
kernel = res.stdout
5959

0 commit comments

Comments
 (0)