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.
Files changed (197) hide show
  1. amd_node_scraper-0.0.1.dist-info/LICENSE +21 -0
  2. amd_node_scraper-0.0.1.dist-info/METADATA +424 -0
  3. amd_node_scraper-0.0.1.dist-info/RECORD +197 -0
  4. amd_node_scraper-0.0.1.dist-info/WHEEL +5 -0
  5. amd_node_scraper-0.0.1.dist-info/entry_points.txt +2 -0
  6. amd_node_scraper-0.0.1.dist-info/top_level.txt +1 -0
  7. nodescraper/__init__.py +32 -0
  8. nodescraper/base/__init__.py +34 -0
  9. nodescraper/base/inbandcollectortask.py +118 -0
  10. nodescraper/base/inbanddataplugin.py +39 -0
  11. nodescraper/base/regexanalyzer.py +120 -0
  12. nodescraper/cli/__init__.py +29 -0
  13. nodescraper/cli/cli.py +511 -0
  14. nodescraper/cli/constants.py +27 -0
  15. nodescraper/cli/dynamicparserbuilder.py +171 -0
  16. nodescraper/cli/helper.py +517 -0
  17. nodescraper/cli/inputargtypes.py +129 -0
  18. nodescraper/configbuilder.py +123 -0
  19. nodescraper/configregistry.py +66 -0
  20. nodescraper/configs/node_status.json +19 -0
  21. nodescraper/connection/__init__.py +25 -0
  22. nodescraper/connection/inband/__init__.py +46 -0
  23. nodescraper/connection/inband/inband.py +171 -0
  24. nodescraper/connection/inband/inbandlocal.py +93 -0
  25. nodescraper/connection/inband/inbandmanager.py +151 -0
  26. nodescraper/connection/inband/inbandremote.py +173 -0
  27. nodescraper/connection/inband/sshparams.py +43 -0
  28. nodescraper/constants.py +26 -0
  29. nodescraper/enums/__init__.py +40 -0
  30. nodescraper/enums/eventcategory.py +89 -0
  31. nodescraper/enums/eventpriority.py +42 -0
  32. nodescraper/enums/executionstatus.py +44 -0
  33. nodescraper/enums/osfamily.py +34 -0
  34. nodescraper/enums/systeminteraction.py +41 -0
  35. nodescraper/enums/systemlocation.py +33 -0
  36. nodescraper/generictypes.py +36 -0
  37. nodescraper/interfaces/__init__.py +44 -0
  38. nodescraper/interfaces/connectionmanager.py +143 -0
  39. nodescraper/interfaces/dataanalyzertask.py +138 -0
  40. nodescraper/interfaces/datacollectortask.py +185 -0
  41. nodescraper/interfaces/dataplugin.py +356 -0
  42. nodescraper/interfaces/plugin.py +127 -0
  43. nodescraper/interfaces/resultcollator.py +56 -0
  44. nodescraper/interfaces/task.py +164 -0
  45. nodescraper/interfaces/taskresulthook.py +39 -0
  46. nodescraper/models/__init__.py +48 -0
  47. nodescraper/models/analyzerargs.py +93 -0
  48. nodescraper/models/collectorargs.py +30 -0
  49. nodescraper/models/connectionconfig.py +34 -0
  50. nodescraper/models/datamodel.py +171 -0
  51. nodescraper/models/datapluginresult.py +39 -0
  52. nodescraper/models/event.py +158 -0
  53. nodescraper/models/pluginconfig.py +38 -0
  54. nodescraper/models/pluginresult.py +39 -0
  55. nodescraper/models/systeminfo.py +44 -0
  56. nodescraper/models/taskresult.py +185 -0
  57. nodescraper/models/timerangeargs.py +38 -0
  58. nodescraper/pluginexecutor.py +274 -0
  59. nodescraper/pluginregistry.py +152 -0
  60. nodescraper/plugins/__init__.py +25 -0
  61. nodescraper/plugins/inband/__init__.py +25 -0
  62. nodescraper/plugins/inband/amdsmi/__init__.py +28 -0
  63. nodescraper/plugins/inband/amdsmi/amdsmi_analyzer.py +821 -0
  64. nodescraper/plugins/inband/amdsmi/amdsmi_collector.py +1313 -0
  65. nodescraper/plugins/inband/amdsmi/amdsmi_plugin.py +43 -0
  66. nodescraper/plugins/inband/amdsmi/amdsmidata.py +1002 -0
  67. nodescraper/plugins/inband/amdsmi/analyzer_args.py +50 -0
  68. nodescraper/plugins/inband/amdsmi/cper.py +65 -0
  69. nodescraper/plugins/inband/bios/__init__.py +29 -0
  70. nodescraper/plugins/inband/bios/analyzer_args.py +64 -0
  71. nodescraper/plugins/inband/bios/bios_analyzer.py +93 -0
  72. nodescraper/plugins/inband/bios/bios_collector.py +93 -0
  73. nodescraper/plugins/inband/bios/bios_plugin.py +43 -0
  74. nodescraper/plugins/inband/bios/biosdata.py +30 -0
  75. nodescraper/plugins/inband/cmdline/__init__.py +25 -0
  76. nodescraper/plugins/inband/cmdline/analyzer_args.py +80 -0
  77. nodescraper/plugins/inband/cmdline/cmdline_analyzer.py +113 -0
  78. nodescraper/plugins/inband/cmdline/cmdline_collector.py +77 -0
  79. nodescraper/plugins/inband/cmdline/cmdline_plugin.py +43 -0
  80. nodescraper/plugins/inband/cmdline/cmdlinedata.py +30 -0
  81. nodescraper/plugins/inband/device_enumeration/__init__.py +29 -0
  82. nodescraper/plugins/inband/device_enumeration/analyzer_args.py +73 -0
  83. nodescraper/plugins/inband/device_enumeration/device_enumeration_analyzer.py +81 -0
  84. nodescraper/plugins/inband/device_enumeration/device_enumeration_collector.py +176 -0
  85. nodescraper/plugins/inband/device_enumeration/device_enumeration_plugin.py +45 -0
  86. nodescraper/plugins/inband/device_enumeration/deviceenumdata.py +36 -0
  87. nodescraper/plugins/inband/dimm/__init__.py +25 -0
  88. nodescraper/plugins/inband/dimm/collector_args.py +31 -0
  89. nodescraper/plugins/inband/dimm/dimm_collector.py +151 -0
  90. nodescraper/plugins/inband/dimm/dimm_plugin.py +40 -0
  91. nodescraper/plugins/inband/dimm/dimmdata.py +30 -0
  92. nodescraper/plugins/inband/dkms/__init__.py +25 -0
  93. nodescraper/plugins/inband/dkms/analyzer_args.py +85 -0
  94. nodescraper/plugins/inband/dkms/dkms_analyzer.py +106 -0
  95. nodescraper/plugins/inband/dkms/dkms_collector.py +76 -0
  96. nodescraper/plugins/inband/dkms/dkms_plugin.py +43 -0
  97. nodescraper/plugins/inband/dkms/dkmsdata.py +33 -0
  98. nodescraper/plugins/inband/dmesg/__init__.py +28 -0
  99. nodescraper/plugins/inband/dmesg/analyzer_args.py +33 -0
  100. nodescraper/plugins/inband/dmesg/collector_args.py +39 -0
  101. nodescraper/plugins/inband/dmesg/dmesg_analyzer.py +503 -0
  102. nodescraper/plugins/inband/dmesg/dmesg_collector.py +164 -0
  103. nodescraper/plugins/inband/dmesg/dmesg_plugin.py +44 -0
  104. nodescraper/plugins/inband/dmesg/dmesgdata.py +116 -0
  105. nodescraper/plugins/inband/fabrics/__init__.py +28 -0
  106. nodescraper/plugins/inband/fabrics/fabrics_collector.py +726 -0
  107. nodescraper/plugins/inband/fabrics/fabrics_plugin.py +37 -0
  108. nodescraper/plugins/inband/fabrics/fabricsdata.py +140 -0
  109. nodescraper/plugins/inband/journal/__init__.py +28 -0
  110. nodescraper/plugins/inband/journal/collector_args.py +33 -0
  111. nodescraper/plugins/inband/journal/journal_collector.py +107 -0
  112. nodescraper/plugins/inband/journal/journal_plugin.py +40 -0
  113. nodescraper/plugins/inband/journal/journaldata.py +44 -0
  114. nodescraper/plugins/inband/kernel/__init__.py +25 -0
  115. nodescraper/plugins/inband/kernel/analyzer_args.py +64 -0
  116. nodescraper/plugins/inband/kernel/kernel_analyzer.py +91 -0
  117. nodescraper/plugins/inband/kernel/kernel_collector.py +129 -0
  118. nodescraper/plugins/inband/kernel/kernel_plugin.py +43 -0
  119. nodescraper/plugins/inband/kernel/kerneldata.py +32 -0
  120. nodescraper/plugins/inband/kernel_module/__init__.py +25 -0
  121. nodescraper/plugins/inband/kernel_module/analyzer_args.py +59 -0
  122. nodescraper/plugins/inband/kernel_module/kernel_module_analyzer.py +211 -0
  123. nodescraper/plugins/inband/kernel_module/kernel_module_collector.py +264 -0
  124. nodescraper/plugins/inband/kernel_module/kernel_module_data.py +60 -0
  125. nodescraper/plugins/inband/kernel_module/kernel_module_plugin.py +43 -0
  126. nodescraper/plugins/inband/memory/__init__.py +25 -0
  127. nodescraper/plugins/inband/memory/analyzer_args.py +45 -0
  128. nodescraper/plugins/inband/memory/memory_analyzer.py +98 -0
  129. nodescraper/plugins/inband/memory/memory_collector.py +330 -0
  130. nodescraper/plugins/inband/memory/memory_plugin.py +43 -0
  131. nodescraper/plugins/inband/memory/memorydata.py +90 -0
  132. nodescraper/plugins/inband/network/__init__.py +28 -0
  133. nodescraper/plugins/inband/network/network_collector.py +1828 -0
  134. nodescraper/plugins/inband/network/network_plugin.py +37 -0
  135. nodescraper/plugins/inband/network/networkdata.py +319 -0
  136. nodescraper/plugins/inband/nvme/__init__.py +28 -0
  137. nodescraper/plugins/inband/nvme/nvme_collector.py +167 -0
  138. nodescraper/plugins/inband/nvme/nvme_plugin.py +37 -0
  139. nodescraper/plugins/inband/nvme/nvmedata.py +45 -0
  140. nodescraper/plugins/inband/os/__init__.py +25 -0
  141. nodescraper/plugins/inband/os/analyzer_args.py +64 -0
  142. nodescraper/plugins/inband/os/os_analyzer.py +73 -0
  143. nodescraper/plugins/inband/os/os_collector.py +131 -0
  144. nodescraper/plugins/inband/os/os_plugin.py +43 -0
  145. nodescraper/plugins/inband/os/osdata.py +31 -0
  146. nodescraper/plugins/inband/package/__init__.py +25 -0
  147. nodescraper/plugins/inband/package/analyzer_args.py +48 -0
  148. nodescraper/plugins/inband/package/package_analyzer.py +253 -0
  149. nodescraper/plugins/inband/package/package_collector.py +273 -0
  150. nodescraper/plugins/inband/package/package_plugin.py +43 -0
  151. nodescraper/plugins/inband/package/packagedata.py +41 -0
  152. nodescraper/plugins/inband/pcie/__init__.py +29 -0
  153. nodescraper/plugins/inband/pcie/analyzer_args.py +63 -0
  154. nodescraper/plugins/inband/pcie/pcie_analyzer.py +1081 -0
  155. nodescraper/plugins/inband/pcie/pcie_collector.py +690 -0
  156. nodescraper/plugins/inband/pcie/pcie_data.py +2017 -0
  157. nodescraper/plugins/inband/pcie/pcie_plugin.py +43 -0
  158. nodescraper/plugins/inband/process/__init__.py +25 -0
  159. nodescraper/plugins/inband/process/analyzer_args.py +45 -0
  160. nodescraper/plugins/inband/process/collector_args.py +31 -0
  161. nodescraper/plugins/inband/process/process_analyzer.py +91 -0
  162. nodescraper/plugins/inband/process/process_collector.py +115 -0
  163. nodescraper/plugins/inband/process/process_plugin.py +46 -0
  164. nodescraper/plugins/inband/process/processdata.py +34 -0
  165. nodescraper/plugins/inband/rocm/__init__.py +25 -0
  166. nodescraper/plugins/inband/rocm/analyzer_args.py +66 -0
  167. nodescraper/plugins/inband/rocm/rocm_analyzer.py +100 -0
  168. nodescraper/plugins/inband/rocm/rocm_collector.py +205 -0
  169. nodescraper/plugins/inband/rocm/rocm_plugin.py +43 -0
  170. nodescraper/plugins/inband/rocm/rocmdata.py +62 -0
  171. nodescraper/plugins/inband/storage/__init__.py +25 -0
  172. nodescraper/plugins/inband/storage/analyzer_args.py +38 -0
  173. nodescraper/plugins/inband/storage/collector_args.py +31 -0
  174. nodescraper/plugins/inband/storage/storage_analyzer.py +152 -0
  175. nodescraper/plugins/inband/storage/storage_collector.py +110 -0
  176. nodescraper/plugins/inband/storage/storage_plugin.py +44 -0
  177. nodescraper/plugins/inband/storage/storagedata.py +70 -0
  178. nodescraper/plugins/inband/sysctl/__init__.py +29 -0
  179. nodescraper/plugins/inband/sysctl/analyzer_args.py +67 -0
  180. nodescraper/plugins/inband/sysctl/sysctl_analyzer.py +81 -0
  181. nodescraper/plugins/inband/sysctl/sysctl_collector.py +101 -0
  182. nodescraper/plugins/inband/sysctl/sysctl_plugin.py +43 -0
  183. nodescraper/plugins/inband/sysctl/sysctldata.py +42 -0
  184. nodescraper/plugins/inband/syslog/__init__.py +28 -0
  185. nodescraper/plugins/inband/syslog/syslog_collector.py +121 -0
  186. nodescraper/plugins/inband/syslog/syslog_plugin.py +37 -0
  187. nodescraper/plugins/inband/syslog/syslogdata.py +46 -0
  188. nodescraper/plugins/inband/uptime/__init__.py +25 -0
  189. nodescraper/plugins/inband/uptime/uptime_collector.py +88 -0
  190. nodescraper/plugins/inband/uptime/uptime_plugin.py +37 -0
  191. nodescraper/plugins/inband/uptime/uptimedata.py +31 -0
  192. nodescraper/resultcollators/__init__.py +25 -0
  193. nodescraper/resultcollators/tablesummary.py +159 -0
  194. nodescraper/taskresulthooks/__init__.py +28 -0
  195. nodescraper/taskresulthooks/filesystemloghook.py +88 -0
  196. nodescraper/typeutils.py +171 -0
  197. 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