amd-node-scraper 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- amd_node_scraper-0.0.1.dist-info/LICENSE +21 -0
- amd_node_scraper-0.0.1.dist-info/METADATA +424 -0
- amd_node_scraper-0.0.1.dist-info/RECORD +197 -0
- amd_node_scraper-0.0.1.dist-info/WHEEL +5 -0
- amd_node_scraper-0.0.1.dist-info/entry_points.txt +2 -0
- amd_node_scraper-0.0.1.dist-info/top_level.txt +1 -0
- nodescraper/__init__.py +32 -0
- nodescraper/base/__init__.py +34 -0
- nodescraper/base/inbandcollectortask.py +118 -0
- nodescraper/base/inbanddataplugin.py +39 -0
- nodescraper/base/regexanalyzer.py +120 -0
- nodescraper/cli/__init__.py +29 -0
- nodescraper/cli/cli.py +511 -0
- nodescraper/cli/constants.py +27 -0
- nodescraper/cli/dynamicparserbuilder.py +171 -0
- nodescraper/cli/helper.py +517 -0
- nodescraper/cli/inputargtypes.py +129 -0
- nodescraper/configbuilder.py +123 -0
- nodescraper/configregistry.py +66 -0
- nodescraper/configs/node_status.json +19 -0
- nodescraper/connection/__init__.py +25 -0
- nodescraper/connection/inband/__init__.py +46 -0
- nodescraper/connection/inband/inband.py +171 -0
- nodescraper/connection/inband/inbandlocal.py +93 -0
- nodescraper/connection/inband/inbandmanager.py +151 -0
- nodescraper/connection/inband/inbandremote.py +173 -0
- nodescraper/connection/inband/sshparams.py +43 -0
- nodescraper/constants.py +26 -0
- nodescraper/enums/__init__.py +40 -0
- nodescraper/enums/eventcategory.py +89 -0
- nodescraper/enums/eventpriority.py +42 -0
- nodescraper/enums/executionstatus.py +44 -0
- nodescraper/enums/osfamily.py +34 -0
- nodescraper/enums/systeminteraction.py +41 -0
- nodescraper/enums/systemlocation.py +33 -0
- nodescraper/generictypes.py +36 -0
- nodescraper/interfaces/__init__.py +44 -0
- nodescraper/interfaces/connectionmanager.py +143 -0
- nodescraper/interfaces/dataanalyzertask.py +138 -0
- nodescraper/interfaces/datacollectortask.py +185 -0
- nodescraper/interfaces/dataplugin.py +356 -0
- nodescraper/interfaces/plugin.py +127 -0
- nodescraper/interfaces/resultcollator.py +56 -0
- nodescraper/interfaces/task.py +164 -0
- nodescraper/interfaces/taskresulthook.py +39 -0
- nodescraper/models/__init__.py +48 -0
- nodescraper/models/analyzerargs.py +93 -0
- nodescraper/models/collectorargs.py +30 -0
- nodescraper/models/connectionconfig.py +34 -0
- nodescraper/models/datamodel.py +171 -0
- nodescraper/models/datapluginresult.py +39 -0
- nodescraper/models/event.py +158 -0
- nodescraper/models/pluginconfig.py +38 -0
- nodescraper/models/pluginresult.py +39 -0
- nodescraper/models/systeminfo.py +44 -0
- nodescraper/models/taskresult.py +185 -0
- nodescraper/models/timerangeargs.py +38 -0
- nodescraper/pluginexecutor.py +274 -0
- nodescraper/pluginregistry.py +152 -0
- nodescraper/plugins/__init__.py +25 -0
- nodescraper/plugins/inband/__init__.py +25 -0
- nodescraper/plugins/inband/amdsmi/__init__.py +28 -0
- nodescraper/plugins/inband/amdsmi/amdsmi_analyzer.py +821 -0
- nodescraper/plugins/inband/amdsmi/amdsmi_collector.py +1313 -0
- nodescraper/plugins/inband/amdsmi/amdsmi_plugin.py +43 -0
- nodescraper/plugins/inband/amdsmi/amdsmidata.py +1002 -0
- nodescraper/plugins/inband/amdsmi/analyzer_args.py +50 -0
- nodescraper/plugins/inband/amdsmi/cper.py +65 -0
- nodescraper/plugins/inband/bios/__init__.py +29 -0
- nodescraper/plugins/inband/bios/analyzer_args.py +64 -0
- nodescraper/plugins/inband/bios/bios_analyzer.py +93 -0
- nodescraper/plugins/inband/bios/bios_collector.py +93 -0
- nodescraper/plugins/inband/bios/bios_plugin.py +43 -0
- nodescraper/plugins/inband/bios/biosdata.py +30 -0
- nodescraper/plugins/inband/cmdline/__init__.py +25 -0
- nodescraper/plugins/inband/cmdline/analyzer_args.py +80 -0
- nodescraper/plugins/inband/cmdline/cmdline_analyzer.py +113 -0
- nodescraper/plugins/inband/cmdline/cmdline_collector.py +77 -0
- nodescraper/plugins/inband/cmdline/cmdline_plugin.py +43 -0
- nodescraper/plugins/inband/cmdline/cmdlinedata.py +30 -0
- nodescraper/plugins/inband/device_enumeration/__init__.py +29 -0
- nodescraper/plugins/inband/device_enumeration/analyzer_args.py +73 -0
- nodescraper/plugins/inband/device_enumeration/device_enumeration_analyzer.py +81 -0
- nodescraper/plugins/inband/device_enumeration/device_enumeration_collector.py +176 -0
- nodescraper/plugins/inband/device_enumeration/device_enumeration_plugin.py +45 -0
- nodescraper/plugins/inband/device_enumeration/deviceenumdata.py +36 -0
- nodescraper/plugins/inband/dimm/__init__.py +25 -0
- nodescraper/plugins/inband/dimm/collector_args.py +31 -0
- nodescraper/plugins/inband/dimm/dimm_collector.py +151 -0
- nodescraper/plugins/inband/dimm/dimm_plugin.py +40 -0
- nodescraper/plugins/inband/dimm/dimmdata.py +30 -0
- nodescraper/plugins/inband/dkms/__init__.py +25 -0
- nodescraper/plugins/inband/dkms/analyzer_args.py +85 -0
- nodescraper/plugins/inband/dkms/dkms_analyzer.py +106 -0
- nodescraper/plugins/inband/dkms/dkms_collector.py +76 -0
- nodescraper/plugins/inband/dkms/dkms_plugin.py +43 -0
- nodescraper/plugins/inband/dkms/dkmsdata.py +33 -0
- nodescraper/plugins/inband/dmesg/__init__.py +28 -0
- nodescraper/plugins/inband/dmesg/analyzer_args.py +33 -0
- nodescraper/plugins/inband/dmesg/collector_args.py +39 -0
- nodescraper/plugins/inband/dmesg/dmesg_analyzer.py +503 -0
- nodescraper/plugins/inband/dmesg/dmesg_collector.py +164 -0
- nodescraper/plugins/inband/dmesg/dmesg_plugin.py +44 -0
- nodescraper/plugins/inband/dmesg/dmesgdata.py +116 -0
- nodescraper/plugins/inband/fabrics/__init__.py +28 -0
- nodescraper/plugins/inband/fabrics/fabrics_collector.py +726 -0
- nodescraper/plugins/inband/fabrics/fabrics_plugin.py +37 -0
- nodescraper/plugins/inband/fabrics/fabricsdata.py +140 -0
- nodescraper/plugins/inband/journal/__init__.py +28 -0
- nodescraper/plugins/inband/journal/collector_args.py +33 -0
- nodescraper/plugins/inband/journal/journal_collector.py +107 -0
- nodescraper/plugins/inband/journal/journal_plugin.py +40 -0
- nodescraper/plugins/inband/journal/journaldata.py +44 -0
- nodescraper/plugins/inband/kernel/__init__.py +25 -0
- nodescraper/plugins/inband/kernel/analyzer_args.py +64 -0
- nodescraper/plugins/inband/kernel/kernel_analyzer.py +91 -0
- nodescraper/plugins/inband/kernel/kernel_collector.py +129 -0
- nodescraper/plugins/inband/kernel/kernel_plugin.py +43 -0
- nodescraper/plugins/inband/kernel/kerneldata.py +32 -0
- nodescraper/plugins/inband/kernel_module/__init__.py +25 -0
- nodescraper/plugins/inband/kernel_module/analyzer_args.py +59 -0
- nodescraper/plugins/inband/kernel_module/kernel_module_analyzer.py +211 -0
- nodescraper/plugins/inband/kernel_module/kernel_module_collector.py +264 -0
- nodescraper/plugins/inband/kernel_module/kernel_module_data.py +60 -0
- nodescraper/plugins/inband/kernel_module/kernel_module_plugin.py +43 -0
- nodescraper/plugins/inband/memory/__init__.py +25 -0
- nodescraper/plugins/inband/memory/analyzer_args.py +45 -0
- nodescraper/plugins/inband/memory/memory_analyzer.py +98 -0
- nodescraper/plugins/inband/memory/memory_collector.py +330 -0
- nodescraper/plugins/inband/memory/memory_plugin.py +43 -0
- nodescraper/plugins/inband/memory/memorydata.py +90 -0
- nodescraper/plugins/inband/network/__init__.py +28 -0
- nodescraper/plugins/inband/network/network_collector.py +1828 -0
- nodescraper/plugins/inband/network/network_plugin.py +37 -0
- nodescraper/plugins/inband/network/networkdata.py +319 -0
- nodescraper/plugins/inband/nvme/__init__.py +28 -0
- nodescraper/plugins/inband/nvme/nvme_collector.py +167 -0
- nodescraper/plugins/inband/nvme/nvme_plugin.py +37 -0
- nodescraper/plugins/inband/nvme/nvmedata.py +45 -0
- nodescraper/plugins/inband/os/__init__.py +25 -0
- nodescraper/plugins/inband/os/analyzer_args.py +64 -0
- nodescraper/plugins/inband/os/os_analyzer.py +73 -0
- nodescraper/plugins/inband/os/os_collector.py +131 -0
- nodescraper/plugins/inband/os/os_plugin.py +43 -0
- nodescraper/plugins/inband/os/osdata.py +31 -0
- nodescraper/plugins/inband/package/__init__.py +25 -0
- nodescraper/plugins/inband/package/analyzer_args.py +48 -0
- nodescraper/plugins/inband/package/package_analyzer.py +253 -0
- nodescraper/plugins/inband/package/package_collector.py +273 -0
- nodescraper/plugins/inband/package/package_plugin.py +43 -0
- nodescraper/plugins/inband/package/packagedata.py +41 -0
- nodescraper/plugins/inband/pcie/__init__.py +29 -0
- nodescraper/plugins/inband/pcie/analyzer_args.py +63 -0
- nodescraper/plugins/inband/pcie/pcie_analyzer.py +1081 -0
- nodescraper/plugins/inband/pcie/pcie_collector.py +690 -0
- nodescraper/plugins/inband/pcie/pcie_data.py +2017 -0
- nodescraper/plugins/inband/pcie/pcie_plugin.py +43 -0
- nodescraper/plugins/inband/process/__init__.py +25 -0
- nodescraper/plugins/inband/process/analyzer_args.py +45 -0
- nodescraper/plugins/inband/process/collector_args.py +31 -0
- nodescraper/plugins/inband/process/process_analyzer.py +91 -0
- nodescraper/plugins/inband/process/process_collector.py +115 -0
- nodescraper/plugins/inband/process/process_plugin.py +46 -0
- nodescraper/plugins/inband/process/processdata.py +34 -0
- nodescraper/plugins/inband/rocm/__init__.py +25 -0
- nodescraper/plugins/inband/rocm/analyzer_args.py +66 -0
- nodescraper/plugins/inband/rocm/rocm_analyzer.py +100 -0
- nodescraper/plugins/inband/rocm/rocm_collector.py +205 -0
- nodescraper/plugins/inband/rocm/rocm_plugin.py +43 -0
- nodescraper/plugins/inband/rocm/rocmdata.py +62 -0
- nodescraper/plugins/inband/storage/__init__.py +25 -0
- nodescraper/plugins/inband/storage/analyzer_args.py +38 -0
- nodescraper/plugins/inband/storage/collector_args.py +31 -0
- nodescraper/plugins/inband/storage/storage_analyzer.py +152 -0
- nodescraper/plugins/inband/storage/storage_collector.py +110 -0
- nodescraper/plugins/inband/storage/storage_plugin.py +44 -0
- nodescraper/plugins/inband/storage/storagedata.py +70 -0
- nodescraper/plugins/inband/sysctl/__init__.py +29 -0
- nodescraper/plugins/inband/sysctl/analyzer_args.py +67 -0
- nodescraper/plugins/inband/sysctl/sysctl_analyzer.py +81 -0
- nodescraper/plugins/inband/sysctl/sysctl_collector.py +101 -0
- nodescraper/plugins/inband/sysctl/sysctl_plugin.py +43 -0
- nodescraper/plugins/inband/sysctl/sysctldata.py +42 -0
- nodescraper/plugins/inband/syslog/__init__.py +28 -0
- nodescraper/plugins/inband/syslog/syslog_collector.py +121 -0
- nodescraper/plugins/inband/syslog/syslog_plugin.py +37 -0
- nodescraper/plugins/inband/syslog/syslogdata.py +46 -0
- nodescraper/plugins/inband/uptime/__init__.py +25 -0
- nodescraper/plugins/inband/uptime/uptime_collector.py +88 -0
- nodescraper/plugins/inband/uptime/uptime_plugin.py +37 -0
- nodescraper/plugins/inband/uptime/uptimedata.py +31 -0
- nodescraper/resultcollators/__init__.py +25 -0
- nodescraper/resultcollators/tablesummary.py +159 -0
- nodescraper/taskresulthooks/__init__.py +28 -0
- nodescraper/taskresulthooks/filesystemloghook.py +88 -0
- nodescraper/typeutils.py +171 -0
- nodescraper/utils.py +412 -0
nodescraper/__init__.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
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 importlib.metadata import PackageNotFoundError, version
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
__version__ = version("node-scraper")
|
|
31
|
+
except PackageNotFoundError:
|
|
32
|
+
__version__ = "unknown"
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
from .inbandcollectortask import InBandDataCollector
|
|
27
|
+
from .inbanddataplugin import InBandDataPlugin
|
|
28
|
+
from .regexanalyzer import RegexAnalyzer
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"InBandDataCollector",
|
|
32
|
+
"InBandDataPlugin",
|
|
33
|
+
"RegexAnalyzer",
|
|
34
|
+
]
|
|
@@ -0,0 +1,118 @@
|
|
|
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
|
+
import logging
|
|
27
|
+
from typing import Generic, Optional, Union
|
|
28
|
+
|
|
29
|
+
from nodescraper.connection.inband import InBandConnection
|
|
30
|
+
from nodescraper.connection.inband.inband import BaseFileArtifact, CommandArtifact
|
|
31
|
+
from nodescraper.enums import EventPriority, OSFamily, SystemInteractionLevel
|
|
32
|
+
from nodescraper.generictypes import TCollectArg, TDataModel
|
|
33
|
+
from nodescraper.interfaces import DataCollector, TaskResultHook
|
|
34
|
+
from nodescraper.interfaces.task import SystemCompatibilityError
|
|
35
|
+
from nodescraper.models import SystemInfo
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class InBandDataCollector(
|
|
39
|
+
DataCollector[InBandConnection, TDataModel, TCollectArg],
|
|
40
|
+
Generic[TDataModel, TCollectArg],
|
|
41
|
+
):
|
|
42
|
+
"""Parent class for all data collectors that collect in band data"""
|
|
43
|
+
|
|
44
|
+
SUPPORTED_OS_FAMILY: set[OSFamily] = {OSFamily.WINDOWS, OSFamily.LINUX}
|
|
45
|
+
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
system_info: SystemInfo,
|
|
49
|
+
connection: InBandConnection,
|
|
50
|
+
logger: Optional[logging.Logger] = None,
|
|
51
|
+
system_interaction_level: SystemInteractionLevel = SystemInteractionLevel.INTERACTIVE,
|
|
52
|
+
max_event_priority_level: Union[EventPriority, str] = EventPriority.CRITICAL,
|
|
53
|
+
parent: Optional[str] = None,
|
|
54
|
+
task_result_hooks: Optional[list[TaskResultHook]] = None,
|
|
55
|
+
**kwargs,
|
|
56
|
+
):
|
|
57
|
+
super().__init__(
|
|
58
|
+
system_info=system_info,
|
|
59
|
+
system_interaction_level=system_interaction_level,
|
|
60
|
+
max_event_priority_level=max_event_priority_level,
|
|
61
|
+
logger=logger,
|
|
62
|
+
connection=connection,
|
|
63
|
+
parent=parent,
|
|
64
|
+
task_result_hooks=task_result_hooks,
|
|
65
|
+
)
|
|
66
|
+
if self.system_info.os_family not in self.SUPPORTED_OS_FAMILY:
|
|
67
|
+
raise SystemCompatibilityError(
|
|
68
|
+
f"{self.system_info.os_family.name} OS family is not supported"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def _run_sut_cmd(
|
|
72
|
+
self,
|
|
73
|
+
command: str,
|
|
74
|
+
sudo: bool = False,
|
|
75
|
+
timeout: int = 300,
|
|
76
|
+
strip: bool = True,
|
|
77
|
+
log_artifact: bool = True,
|
|
78
|
+
) -> CommandArtifact:
|
|
79
|
+
"""
|
|
80
|
+
Run a command on the SUT and return the result.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
command (str): command to run on the SUT.
|
|
84
|
+
sudo (bool, optional): whether to run the command with sudo. Defaults to False.
|
|
85
|
+
timeout (int, optional): command timeout in seconds. Defaults to 300.
|
|
86
|
+
strip (bool, optional): whether output should be stripped. Defaults to True.
|
|
87
|
+
log_artifact (bool, optional): whether we should log the command result. Defaults to True.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
CommandArtifact: The result of the command execution, which includes stdout, stderr, and exit code.
|
|
91
|
+
"""
|
|
92
|
+
command_res = self.connection.run_command(
|
|
93
|
+
command=command, sudo=sudo, timeout=timeout, strip=strip
|
|
94
|
+
)
|
|
95
|
+
if log_artifact:
|
|
96
|
+
self.result.artifacts.append(command_res)
|
|
97
|
+
|
|
98
|
+
return command_res
|
|
99
|
+
|
|
100
|
+
def _read_sut_file(
|
|
101
|
+
self, filename: str, encoding="utf-8", strip: bool = True, log_artifact=True
|
|
102
|
+
) -> BaseFileArtifact:
|
|
103
|
+
"""
|
|
104
|
+
Read a file from the SUT and return its content.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
filename (str): path to the file on the SUT.
|
|
108
|
+
encoding (str, optional): encoding to use when reading the file. Defaults to "utf-8".
|
|
109
|
+
strip (bool, optional): whether the file contents should be stripped. Defaults to True.
|
|
110
|
+
log_artifact (bool, optional): whether we should log the contents of the file. Defaults to True.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
BaseFileArtifact: The content of the file read from the SUT, which includes the file name and content
|
|
114
|
+
"""
|
|
115
|
+
file_res = self.connection.read_file(filename=filename, encoding=encoding, strip=strip)
|
|
116
|
+
if log_artifact:
|
|
117
|
+
self.result.artifacts.append(file_res)
|
|
118
|
+
return file_res
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
from typing import Generic
|
|
27
|
+
|
|
28
|
+
from nodescraper.connection.inband import InBandConnectionManager, SSHConnectionParams
|
|
29
|
+
from nodescraper.generictypes import TAnalyzeArg, TCollectArg, TDataModel
|
|
30
|
+
from nodescraper.interfaces import DataPlugin
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class InBandDataPlugin(
|
|
34
|
+
DataPlugin[InBandConnectionManager, SSHConnectionParams, TDataModel, TCollectArg, TAnalyzeArg],
|
|
35
|
+
Generic[TDataModel, TCollectArg, TAnalyzeArg],
|
|
36
|
+
):
|
|
37
|
+
"""Base class for in band plugins"""
|
|
38
|
+
|
|
39
|
+
CONNECTION_TYPE = InBandConnectionManager
|
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
import re
|
|
27
|
+
from typing import Union
|
|
28
|
+
|
|
29
|
+
from pydantic import BaseModel
|
|
30
|
+
|
|
31
|
+
from nodescraper.enums import EventCategory, EventPriority
|
|
32
|
+
from nodescraper.generictypes import TAnalyzeArg, TDataModel
|
|
33
|
+
from nodescraper.interfaces.dataanalyzertask import DataAnalyzer
|
|
34
|
+
from nodescraper.models.event import Event
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ErrorRegex(BaseModel):
|
|
38
|
+
regex: re.Pattern
|
|
39
|
+
message: str
|
|
40
|
+
event_category: Union[str, EventCategory] = EventCategory.UNKNOWN
|
|
41
|
+
event_priority: EventPriority = EventPriority.ERROR
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class RegexEvent(Event):
|
|
45
|
+
@property
|
|
46
|
+
def count(self) -> int:
|
|
47
|
+
return int(self.data.get("count", 0))
|
|
48
|
+
|
|
49
|
+
@count.setter
|
|
50
|
+
def count(self, val: int):
|
|
51
|
+
self.data["count"] = val
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class RegexAnalyzer(DataAnalyzer[TDataModel, TAnalyzeArg]):
|
|
55
|
+
"""Parent class for all regex based data analyzers."""
|
|
56
|
+
|
|
57
|
+
def _build_regex_event(
|
|
58
|
+
self, regex_obj: ErrorRegex, match: Union[str, list[str]], source: str
|
|
59
|
+
) -> RegexEvent:
|
|
60
|
+
"""Build a RegexEvent object from a regex match and source.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
regex_obj (ErrorRegex): regex object containing the regex pattern, message, category, and priorit
|
|
64
|
+
match (
|
|
65
|
+
Union[str, list[str]]): matched content from the regex
|
|
66
|
+
source (str): descriptor for the content where the match was found
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
RegexEvent: an instance of RegexEvent containing the match details
|
|
70
|
+
"""
|
|
71
|
+
return RegexEvent(
|
|
72
|
+
description=regex_obj.message,
|
|
73
|
+
category=regex_obj.event_category,
|
|
74
|
+
priority=regex_obj.event_priority,
|
|
75
|
+
data={
|
|
76
|
+
"match_content": match,
|
|
77
|
+
"source": source,
|
|
78
|
+
"count": 1,
|
|
79
|
+
"task_name": self.__class__.__name__,
|
|
80
|
+
"task_type": self.TASK_TYPE,
|
|
81
|
+
},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def check_all_regexes(
|
|
85
|
+
self, content: str, source: str, error_regex: list[ErrorRegex], group=True
|
|
86
|
+
) -> list[RegexEvent]:
|
|
87
|
+
"""Iterate over all ERROR_REGEX and check content for any matches
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
content (str): content to match regex on
|
|
91
|
+
source (str): descriptor for content
|
|
92
|
+
error_regex (list[ErrorRegex]): list of regex objects to match
|
|
93
|
+
group (bool, optional): flag to control whether matches should be grouped together. Defaults to True.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
list[RegexEvent]: list of regex event objects
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
regex_map: dict[str, RegexEvent] = {}
|
|
100
|
+
regex_event_list: list[RegexEvent] = []
|
|
101
|
+
|
|
102
|
+
for error_regex_obj in error_regex:
|
|
103
|
+
for match in error_regex_obj.regex.findall(content):
|
|
104
|
+
if isinstance(match, str) and "\n" in match:
|
|
105
|
+
match = match.strip().split("\n")
|
|
106
|
+
|
|
107
|
+
# filter out empty string
|
|
108
|
+
if isinstance(match, tuple) or isinstance(match, list):
|
|
109
|
+
match = [match_val for match_val in match if match_val]
|
|
110
|
+
if len(match) == 1:
|
|
111
|
+
match = match[0]
|
|
112
|
+
|
|
113
|
+
if group and str(match) in regex_map:
|
|
114
|
+
regex_map[str(match)].count += 1
|
|
115
|
+
elif group:
|
|
116
|
+
regex_map[str(match)] = self._build_regex_event(error_regex_obj, match, source)
|
|
117
|
+
else:
|
|
118
|
+
regex_event_list.append(self._build_regex_event(error_regex_obj, match, source))
|
|
119
|
+
|
|
120
|
+
return list(regex_map.values()) if group else regex_event_list
|
|
@@ -0,0 +1,29 @@
|
|
|
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 .cli import main as cli_entry
|
|
28
|
+
|
|
29
|
+
__all__ = ["cli_entry"]
|