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
|
@@ -0,0 +1,44 @@
|
|
|
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 nodescraper.base import InBandDataPlugin
|
|
27
|
+
|
|
28
|
+
from .analyzer_args import StorageAnalyzerArgs
|
|
29
|
+
from .collector_args import StorageCollectorArgs
|
|
30
|
+
from .storage_analyzer import StorageAnalyzer
|
|
31
|
+
from .storage_collector import StorageCollector
|
|
32
|
+
from .storagedata import StorageDataModel
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class StoragePlugin(InBandDataPlugin[StorageDataModel, StorageCollectorArgs, StorageAnalyzerArgs]):
|
|
36
|
+
"""Plugin for collection and analysis of disk usage data"""
|
|
37
|
+
|
|
38
|
+
DATA_MODEL = StorageDataModel
|
|
39
|
+
|
|
40
|
+
COLLECTOR = StorageCollector
|
|
41
|
+
|
|
42
|
+
ANALYZER = StorageAnalyzer
|
|
43
|
+
|
|
44
|
+
COLLECTOR_ARGS = StorageCollectorArgs
|
|
@@ -0,0 +1,70 @@
|
|
|
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 pydantic import BaseModel, field_serializer, field_validator
|
|
27
|
+
|
|
28
|
+
from nodescraper.models import DataModel
|
|
29
|
+
from nodescraper.utils import bytes_to_human_readable, convert_to_bytes
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class DeviceStorageData(BaseModel):
|
|
33
|
+
total: int
|
|
34
|
+
free: int
|
|
35
|
+
used: int
|
|
36
|
+
percent: float
|
|
37
|
+
|
|
38
|
+
@field_serializer("total")
|
|
39
|
+
def serialize_total(self, total: int, _info) -> str:
|
|
40
|
+
return bytes_to_human_readable(total)
|
|
41
|
+
|
|
42
|
+
@field_serializer("free")
|
|
43
|
+
def serialize_free(self, free: int, _info) -> str:
|
|
44
|
+
return bytes_to_human_readable(free)
|
|
45
|
+
|
|
46
|
+
@field_serializer("used")
|
|
47
|
+
def serialize_used(self, used: int, _info) -> str:
|
|
48
|
+
return bytes_to_human_readable(used)
|
|
49
|
+
|
|
50
|
+
@field_serializer("percent")
|
|
51
|
+
def serialize_percent(self, percent: float, _info) -> str:
|
|
52
|
+
return f"{percent}%"
|
|
53
|
+
|
|
54
|
+
@field_validator("total", "free", "used", mode="before")
|
|
55
|
+
@classmethod
|
|
56
|
+
def parse_bytes_fields(cls, v):
|
|
57
|
+
if isinstance(v, str):
|
|
58
|
+
return convert_to_bytes(v)
|
|
59
|
+
return v
|
|
60
|
+
|
|
61
|
+
@field_validator("percent", mode="before")
|
|
62
|
+
@classmethod
|
|
63
|
+
def parse_percent_field(cls, v):
|
|
64
|
+
if isinstance(v, str) and v.endswith("%"):
|
|
65
|
+
return float(v.rstrip("%"))
|
|
66
|
+
return v
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class StorageDataModel(DataModel):
|
|
70
|
+
storage_data: dict[str, DeviceStorageData]
|
|
@@ -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
|
+
from .analyzer_args import SysctlAnalyzerArgs
|
|
27
|
+
from .sysctl_plugin import SysctlPlugin
|
|
28
|
+
|
|
29
|
+
__all__ = ["SysctlPlugin", "SysctlAnalyzerArgs"]
|
|
@@ -0,0 +1,67 @@
|
|
|
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 Optional
|
|
27
|
+
|
|
28
|
+
from nodescraper.models import AnalyzerArgs
|
|
29
|
+
from nodescraper.plugins.inband.sysctl.sysctldata import SysctlDataModel
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SysctlAnalyzerArgs(AnalyzerArgs):
|
|
33
|
+
exp_vm_swappiness: Optional[int] = None
|
|
34
|
+
exp_vm_numa_balancing: Optional[int] = None
|
|
35
|
+
exp_vm_oom_kill_allocating_task: Optional[int] = None
|
|
36
|
+
exp_vm_compaction_proactiveness: Optional[int] = None
|
|
37
|
+
exp_vm_compact_unevictable_allowed: Optional[int] = None
|
|
38
|
+
exp_vm_extfrag_threshold: Optional[int] = None
|
|
39
|
+
exp_vm_zone_reclaim_mode: Optional[int] = None
|
|
40
|
+
exp_vm_dirty_background_ratio: Optional[int] = None
|
|
41
|
+
exp_vm_dirty_ratio: Optional[int] = None
|
|
42
|
+
exp_vm_dirty_writeback_centisecs: Optional[int] = None
|
|
43
|
+
exp_kernel_numa_balancing: Optional[int] = None
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def build_from_model(cls, datamodel: SysctlDataModel) -> "SysctlAnalyzerArgs":
|
|
47
|
+
"""build analyzer args from data model
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
datamodel (SysctlDataModel): data model for plugin
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
SysctlAnalyzerArgs: instance of analyzer args class
|
|
54
|
+
"""
|
|
55
|
+
return cls(
|
|
56
|
+
exp_vm_swappiness=datamodel.vm_swappiness,
|
|
57
|
+
exp_vm_numa_balancing=datamodel.vm_numa_balancing,
|
|
58
|
+
exp_vm_oom_kill_allocating_task=datamodel.vm_oom_kill_allocating_task,
|
|
59
|
+
exp_vm_compaction_proactiveness=datamodel.vm_compaction_proactiveness,
|
|
60
|
+
exp_vm_compact_unevictable_allowed=datamodel.vm_compact_unevictable_allowed,
|
|
61
|
+
exp_vm_extfrag_threshold=datamodel.vm_extfrag_threshold,
|
|
62
|
+
exp_vm_zone_reclaim_mode=datamodel.vm_zone_reclaim_mode,
|
|
63
|
+
exp_vm_dirty_background_ratio=datamodel.vm_dirty_background_ratio,
|
|
64
|
+
exp_vm_dirty_ratio=datamodel.vm_dirty_ratio,
|
|
65
|
+
exp_vm_dirty_writeback_centisecs=datamodel.vm_dirty_writeback_centisecs,
|
|
66
|
+
exp_kernel_numa_balancing=datamodel.kernel_numa_balancing,
|
|
67
|
+
)
|
|
@@ -0,0 +1,81 @@
|
|
|
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 typing import Optional
|
|
28
|
+
|
|
29
|
+
from nodescraper.enums import EventCategory, EventPriority, ExecutionStatus
|
|
30
|
+
from nodescraper.interfaces import DataAnalyzer
|
|
31
|
+
from nodescraper.models import TaskResult
|
|
32
|
+
|
|
33
|
+
from .analyzer_args import SysctlAnalyzerArgs
|
|
34
|
+
from .sysctldata import SysctlDataModel
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SysctlAnalyzer(DataAnalyzer[SysctlDataModel, SysctlAnalyzerArgs]):
|
|
38
|
+
"""Check sysctl matches expected sysctl details"""
|
|
39
|
+
|
|
40
|
+
DATA_MODEL = SysctlDataModel
|
|
41
|
+
|
|
42
|
+
def analyze_data(
|
|
43
|
+
self, data: SysctlDataModel, args: Optional[SysctlAnalyzerArgs] = None
|
|
44
|
+
) -> TaskResult:
|
|
45
|
+
"""Analyze the Sysctl data against expected Sysctl values."""
|
|
46
|
+
mismatches = {}
|
|
47
|
+
|
|
48
|
+
if not args:
|
|
49
|
+
args = SysctlAnalyzerArgs()
|
|
50
|
+
|
|
51
|
+
for exp_field_name, expected_value in args.model_dump(exclude_unset=True).items():
|
|
52
|
+
|
|
53
|
+
data_field_name = exp_field_name.removeprefix("exp_")
|
|
54
|
+
actual_value = getattr(data, data_field_name, None)
|
|
55
|
+
|
|
56
|
+
if actual_value is None:
|
|
57
|
+
mismatches[data_field_name] = {"expected": expected_value, "actual": "missing"}
|
|
58
|
+
elif actual_value != expected_value:
|
|
59
|
+
mismatches[data_field_name] = {"expected": expected_value, "actual": actual_value}
|
|
60
|
+
|
|
61
|
+
if mismatches:
|
|
62
|
+
self.result.status = ExecutionStatus.ERROR
|
|
63
|
+
self.result.message = f"{len(mismatches)} sysctl parameter(s) mismatched."
|
|
64
|
+
self._log_event(
|
|
65
|
+
category=EventCategory.OS,
|
|
66
|
+
description="Sysctl mismatch detected",
|
|
67
|
+
data=mismatches,
|
|
68
|
+
priority=EventPriority.ERROR,
|
|
69
|
+
console_log=True,
|
|
70
|
+
)
|
|
71
|
+
else:
|
|
72
|
+
self._log_event(
|
|
73
|
+
category=EventCategory.OS,
|
|
74
|
+
description="All expected sysctl parameters matched",
|
|
75
|
+
priority=EventPriority.INFO,
|
|
76
|
+
console_log=True,
|
|
77
|
+
)
|
|
78
|
+
self.result.status = ExecutionStatus.OK
|
|
79
|
+
self.result.message = "All expected sysctl parameters match."
|
|
80
|
+
|
|
81
|
+
return self.result
|
|
@@ -0,0 +1,101 @@
|
|
|
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 Optional
|
|
27
|
+
|
|
28
|
+
from nodescraper.base import InBandDataCollector
|
|
29
|
+
from nodescraper.enums import EventCategory, EventPriority, ExecutionStatus, OSFamily
|
|
30
|
+
from nodescraper.models import TaskResult
|
|
31
|
+
|
|
32
|
+
from .sysctldata import SysctlDataModel
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SysctlCollector(InBandDataCollector[SysctlDataModel, None]):
|
|
36
|
+
"""Collect sysctl kernel VM settings."""
|
|
37
|
+
|
|
38
|
+
DATA_MODEL = SysctlDataModel
|
|
39
|
+
CMD = "sysctl -n"
|
|
40
|
+
|
|
41
|
+
def collect_data(
|
|
42
|
+
self,
|
|
43
|
+
args=None,
|
|
44
|
+
) -> tuple[TaskResult, Optional[SysctlDataModel]]:
|
|
45
|
+
"""Collect sysctl VM tuning values from the system."""
|
|
46
|
+
values = {}
|
|
47
|
+
|
|
48
|
+
if self.system_info.os_family == OSFamily.WINDOWS:
|
|
49
|
+
self._log_event(
|
|
50
|
+
category=EventCategory.OS,
|
|
51
|
+
description="Windows is not supported for sysctl collection.",
|
|
52
|
+
priority=EventPriority.WARNING,
|
|
53
|
+
console_log=True,
|
|
54
|
+
)
|
|
55
|
+
return self.result, None
|
|
56
|
+
|
|
57
|
+
for field_name in SysctlDataModel.model_fields:
|
|
58
|
+
sysctl_key = field_name.replace("_", ".", 1)
|
|
59
|
+
res = self._run_sut_cmd(f"{self.CMD} {sysctl_key}")
|
|
60
|
+
|
|
61
|
+
if res.exit_code == 0:
|
|
62
|
+
try:
|
|
63
|
+
values[field_name] = int(res.stdout.strip())
|
|
64
|
+
except ValueError:
|
|
65
|
+
self._log_event(
|
|
66
|
+
category=EventCategory.OS,
|
|
67
|
+
description=f"Invalid integer value for {sysctl_key}",
|
|
68
|
+
data={"stdout": res.stdout},
|
|
69
|
+
priority=EventPriority.ERROR,
|
|
70
|
+
console_log=True,
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
self._log_event(
|
|
74
|
+
category=EventCategory.OS,
|
|
75
|
+
description=f"Error checking Linux system setting : {sysctl_key}",
|
|
76
|
+
data={"system_setting": sysctl_key, "exit_code": res.exit_code},
|
|
77
|
+
priority=EventPriority.WARNING,
|
|
78
|
+
console_log=True,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if values:
|
|
82
|
+
sysctl_data = SysctlDataModel(**values)
|
|
83
|
+
self._log_event(
|
|
84
|
+
category="OS",
|
|
85
|
+
description="Sysctl settings read",
|
|
86
|
+
data=sysctl_data.model_dump(),
|
|
87
|
+
priority=EventPriority.INFO,
|
|
88
|
+
)
|
|
89
|
+
self.result.message = "SYSCTL data collected"
|
|
90
|
+
self.result.status = ExecutionStatus.OK
|
|
91
|
+
else:
|
|
92
|
+
sysctl_data = None
|
|
93
|
+
self._log_event(
|
|
94
|
+
category=EventCategory.OS,
|
|
95
|
+
description="Sysctl settings not read",
|
|
96
|
+
priority=EventPriority.CRITICAL,
|
|
97
|
+
)
|
|
98
|
+
self.result.message = "Sysctl settings not read"
|
|
99
|
+
self.result.status = ExecutionStatus.ERROR
|
|
100
|
+
|
|
101
|
+
return self.result, sysctl_data
|
|
@@ -0,0 +1,43 @@
|
|
|
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 nodescraper.base import InBandDataPlugin
|
|
27
|
+
|
|
28
|
+
from .analyzer_args import SysctlAnalyzerArgs
|
|
29
|
+
from .sysctl_analyzer import SysctlAnalyzer
|
|
30
|
+
from .sysctl_collector import SysctlCollector
|
|
31
|
+
from .sysctldata import SysctlDataModel
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class SysctlPlugin(InBandDataPlugin[SysctlDataModel, None, SysctlAnalyzerArgs]):
|
|
35
|
+
"""Plugin for collection and analysis of BIOS data"""
|
|
36
|
+
|
|
37
|
+
DATA_MODEL = SysctlDataModel
|
|
38
|
+
|
|
39
|
+
COLLECTOR = SysctlCollector
|
|
40
|
+
|
|
41
|
+
ANALYZER = SysctlAnalyzer
|
|
42
|
+
|
|
43
|
+
ANALYZER_ARGS = SysctlAnalyzerArgs
|
|
@@ -0,0 +1,42 @@
|
|
|
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 Optional
|
|
27
|
+
|
|
28
|
+
from nodescraper.models import DataModel
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class SysctlDataModel(DataModel):
|
|
32
|
+
vm_swappiness: Optional[int] = None
|
|
33
|
+
vm_numa_balancing: Optional[int] = None
|
|
34
|
+
vm_oom_kill_allocating_task: Optional[int] = None
|
|
35
|
+
vm_compaction_proactiveness: Optional[int] = None
|
|
36
|
+
vm_compact_unevictable_allowed: Optional[int] = None
|
|
37
|
+
vm_extfrag_threshold: Optional[int] = None
|
|
38
|
+
vm_zone_reclaim_mode: Optional[int] = None
|
|
39
|
+
vm_dirty_background_ratio: Optional[int] = None
|
|
40
|
+
vm_dirty_ratio: Optional[int] = None
|
|
41
|
+
vm_dirty_writeback_centisecs: Optional[int] = None
|
|
42
|
+
kernel_numa_balancing: Optional[int] = None
|
|
@@ -0,0 +1,28 @@
|
|
|
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 .syslog_plugin import SyslogPlugin
|
|
27
|
+
|
|
28
|
+
__all__ = ["SyslogPlugin"]
|
|
@@ -0,0 +1,121 @@
|
|
|
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 Optional
|
|
27
|
+
|
|
28
|
+
from nodescraper.base import InBandDataCollector
|
|
29
|
+
from nodescraper.connection.inband.inband import TextFileArtifact
|
|
30
|
+
from nodescraper.enums import EventCategory, EventPriority, OSFamily
|
|
31
|
+
from nodescraper.models import TaskResult
|
|
32
|
+
from nodescraper.utils import nice_rotated_name, shell_quote
|
|
33
|
+
|
|
34
|
+
from .syslogdata import SyslogData
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SyslogCollector(InBandDataCollector[SyslogData, None]):
|
|
38
|
+
"""Read syslog log"""
|
|
39
|
+
|
|
40
|
+
SUPPORTED_OS_FAMILY = {OSFamily.LINUX}
|
|
41
|
+
|
|
42
|
+
DATA_MODEL = SyslogData
|
|
43
|
+
|
|
44
|
+
CMD = r"ls -1 /var/log/syslog* 2>/dev/null | grep -E '^/var/log/syslog(\.[0-9]+(\.gz)?)?$' || true"
|
|
45
|
+
|
|
46
|
+
def _collect_syslog_rotations(self) -> list[TextFileArtifact]:
|
|
47
|
+
ret = []
|
|
48
|
+
list_res = self._run_sut_cmd(self.CMD, sudo=True)
|
|
49
|
+
paths = [p.strip() for p in (list_res.stdout or "").splitlines() if p.strip()]
|
|
50
|
+
if not paths:
|
|
51
|
+
self._log_event(
|
|
52
|
+
category=EventCategory.OS,
|
|
53
|
+
description="No /var/log/syslog files found (including rotations).",
|
|
54
|
+
data={"list_exit_code": list_res.exit_code},
|
|
55
|
+
priority=EventPriority.WARNING,
|
|
56
|
+
)
|
|
57
|
+
return []
|
|
58
|
+
|
|
59
|
+
collected_logs, failed_logs = [], []
|
|
60
|
+
collected = []
|
|
61
|
+
for p in paths:
|
|
62
|
+
qp = shell_quote(p)
|
|
63
|
+
if p.endswith(".gz"):
|
|
64
|
+
cmd = f"gzip -dc {qp} 2>/dev/null || zcat {qp} 2>/dev/null"
|
|
65
|
+
res = self._run_sut_cmd(cmd, sudo=True, log_artifact=False)
|
|
66
|
+
if res.exit_code == 0 and res.stdout is not None:
|
|
67
|
+
fname = nice_rotated_name(p, "syslog")
|
|
68
|
+
self.logger.info("Collected syslog log: %s", fname)
|
|
69
|
+
collected.append(TextFileArtifact(filename=fname, contents=res.stdout))
|
|
70
|
+
collected_logs.append(fname)
|
|
71
|
+
else:
|
|
72
|
+
failed_logs.append(p)
|
|
73
|
+
else:
|
|
74
|
+
cmd = f"cat {qp}"
|
|
75
|
+
res = self._run_sut_cmd(cmd, sudo=True, log_artifact=False)
|
|
76
|
+
if res.exit_code == 0 and res.stdout is not None:
|
|
77
|
+
fname = nice_rotated_name(p, "syslog")
|
|
78
|
+
self.logger.info("Collected syslog log: %s", fname)
|
|
79
|
+
collected_logs.append(fname)
|
|
80
|
+
collected.append(TextFileArtifact(filename=fname, contents=res.stdout))
|
|
81
|
+
else:
|
|
82
|
+
failed_logs.append(p)
|
|
83
|
+
|
|
84
|
+
if collected_logs:
|
|
85
|
+
self._log_event(
|
|
86
|
+
category=EventCategory.OS,
|
|
87
|
+
description="Collected syslog rotated files",
|
|
88
|
+
data={"collected": collected_logs},
|
|
89
|
+
priority=EventPriority.INFO,
|
|
90
|
+
)
|
|
91
|
+
self.result.message = self.result.message or "syslog rotated files collected"
|
|
92
|
+
|
|
93
|
+
if failed_logs:
|
|
94
|
+
self._log_event(
|
|
95
|
+
category=EventCategory.OS,
|
|
96
|
+
description="Some syslog files could not be collected.",
|
|
97
|
+
data={"failed": failed_logs},
|
|
98
|
+
priority=EventPriority.WARNING,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
if collected:
|
|
102
|
+
ret = collected
|
|
103
|
+
return ret
|
|
104
|
+
|
|
105
|
+
def collect_data(
|
|
106
|
+
self,
|
|
107
|
+
args=None,
|
|
108
|
+
) -> tuple[TaskResult, Optional[SyslogData]]:
|
|
109
|
+
"""Collect syslog data from the system
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
tuple[Optional[TaskResult, None]]: tuple containing the result of the task and the syslog data if available
|
|
113
|
+
"""
|
|
114
|
+
syslog_logs = self._collect_syslog_rotations()
|
|
115
|
+
|
|
116
|
+
if syslog_logs:
|
|
117
|
+
syslog_data = SyslogData(syslog_logs=syslog_logs)
|
|
118
|
+
self.result.message = "Syslog data collected"
|
|
119
|
+
return self.result, syslog_data
|
|
120
|
+
|
|
121
|
+
return self.result, None
|
|
@@ -0,0 +1,37 @@
|
|
|
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 nodescraper.base import InBandDataPlugin
|
|
27
|
+
|
|
28
|
+
from .syslog_collector import SyslogCollector
|
|
29
|
+
from .syslogdata import SyslogData
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SyslogPlugin(InBandDataPlugin[SyslogData, None, None]):
|
|
33
|
+
"""Plugin for collection of syslog data"""
|
|
34
|
+
|
|
35
|
+
DATA_MODEL = SyslogData
|
|
36
|
+
|
|
37
|
+
COLLECTOR = SyslogCollector
|