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,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 .network_collector import NetworkCollector
|
|
29
|
+
from .networkdata import NetworkDataModel
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class NetworkPlugin(InBandDataPlugin[NetworkDataModel, None, None]):
|
|
33
|
+
"""Plugin for collection of network configuration data"""
|
|
34
|
+
|
|
35
|
+
DATA_MODEL = NetworkDataModel
|
|
36
|
+
|
|
37
|
+
COLLECTOR = NetworkCollector
|
|
@@ -0,0 +1,319 @@
|
|
|
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 Dict, List, Optional
|
|
27
|
+
|
|
28
|
+
from pydantic import BaseModel, Field
|
|
29
|
+
|
|
30
|
+
from nodescraper.models import DataModel
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class IpAddress(BaseModel):
|
|
34
|
+
"""Individual IP address on an interface"""
|
|
35
|
+
|
|
36
|
+
address: str # "192.168.1.100"
|
|
37
|
+
prefix_len: Optional[int] = None # 24
|
|
38
|
+
scope: Optional[str] = None # "global", "link", "host"
|
|
39
|
+
family: Optional[str] = None # "inet", "inet6"
|
|
40
|
+
label: Optional[str] = None # interface label/alias
|
|
41
|
+
broadcast: Optional[str] = None # broadcast address
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class NetworkInterface(BaseModel):
|
|
45
|
+
"""Network interface information"""
|
|
46
|
+
|
|
47
|
+
name: str # "eth0", "lo", etc
|
|
48
|
+
index: Optional[int] = None # interface index
|
|
49
|
+
state: Optional[str] = None # "UP", "DOWN", "UNKNOWN"
|
|
50
|
+
mtu: Optional[int] = None # Maximum Transmission Unit
|
|
51
|
+
qdisc: Optional[str] = None # Queuing discipline
|
|
52
|
+
mac_address: Optional[str] = None # MAC/hardware address
|
|
53
|
+
flags: List[str] = Field(default_factory=list) # ["UP", "BROADCAST", "MULTICAST"]
|
|
54
|
+
addresses: List[IpAddress] = Field(default_factory=list) # IP addresses on this interface
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class Route(BaseModel):
|
|
58
|
+
"""Routing table entry"""
|
|
59
|
+
|
|
60
|
+
destination: str # "default", "192.168.1.0/24", etc
|
|
61
|
+
gateway: Optional[str] = None # Gateway IP
|
|
62
|
+
device: Optional[str] = None # Network interface
|
|
63
|
+
protocol: Optional[str] = None # "kernel", "boot", "static", etc
|
|
64
|
+
scope: Optional[str] = None # "link", "global", "host"
|
|
65
|
+
metric: Optional[int] = None # Route metric/priority
|
|
66
|
+
source: Optional[str] = None # Preferred source address
|
|
67
|
+
table: Optional[str] = None # Routing table name/number
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class RoutingRule(BaseModel):
|
|
71
|
+
"""Routing policy rule"""
|
|
72
|
+
|
|
73
|
+
priority: int # Rule priority
|
|
74
|
+
source: Optional[str] = None # Source address/network
|
|
75
|
+
destination: Optional[str] = None # Destination address/network
|
|
76
|
+
table: Optional[str] = None # Routing table to use
|
|
77
|
+
action: Optional[str] = None # "lookup", "unreachable", "prohibit", etc
|
|
78
|
+
iif: Optional[str] = None # Input interface
|
|
79
|
+
oif: Optional[str] = None # Output interface
|
|
80
|
+
fwmark: Optional[str] = None # Firewall mark
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class Neighbor(BaseModel):
|
|
84
|
+
"""ARP/Neighbor table entry"""
|
|
85
|
+
|
|
86
|
+
ip_address: str # IP address of the neighbor
|
|
87
|
+
device: Optional[str] = None # Network interface
|
|
88
|
+
mac_address: Optional[str] = None # Link layer (MAC) address
|
|
89
|
+
state: Optional[str] = None # "REACHABLE", "STALE", "DELAY", "PROBE", "FAILED", "INCOMPLETE"
|
|
90
|
+
flags: List[str] = Field(default_factory=list) # Additional flags like "router", "proxy"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class EthtoolInfo(BaseModel):
|
|
94
|
+
"""Ethtool information for a network interface"""
|
|
95
|
+
|
|
96
|
+
interface: str # Interface name this info belongs to
|
|
97
|
+
raw_output: str # Raw ethtool command output
|
|
98
|
+
settings: Dict[str, str] = Field(default_factory=dict) # Parsed key-value settings
|
|
99
|
+
supported_link_modes: List[str] = Field(default_factory=list) # Supported link modes
|
|
100
|
+
advertised_link_modes: List[str] = Field(default_factory=list) # Advertised link modes
|
|
101
|
+
speed: Optional[str] = None # Link speed (e.g., "10000Mb/s")
|
|
102
|
+
duplex: Optional[str] = None # Duplex mode (e.g., "Full")
|
|
103
|
+
port: Optional[str] = None # Port type (e.g., "Twisted Pair")
|
|
104
|
+
auto_negotiation: Optional[str] = None # Auto-negotiation status (e.g., "on", "off")
|
|
105
|
+
link_detected: Optional[str] = None # Link detection status (e.g., "yes", "no")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class BroadcomNicDevice(BaseModel):
|
|
109
|
+
"""Broadcom NIC device information from niccli --list_devices"""
|
|
110
|
+
|
|
111
|
+
device_num: int # Device number (1, 2, 3, etc.)
|
|
112
|
+
model: Optional[str] = None # e.g., "Broadcom BCM57608 1x400G QSFP-DD PCIe Ethernet NIC"
|
|
113
|
+
adapter_port: Optional[str] = None # e.g., "Adp#1 Port#1"
|
|
114
|
+
interface_name: Optional[str] = None # e.g., "benic1p1"
|
|
115
|
+
mac_address: Optional[str] = None # e.g., "8C:84:74:37:C3:70"
|
|
116
|
+
pci_address: Optional[str] = None # e.g., "0000:06:00.0"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class BroadcomNicQosAppEntry(BaseModel):
|
|
120
|
+
"""APP TLV entry in Broadcom NIC QoS configuration"""
|
|
121
|
+
|
|
122
|
+
priority: Optional[int] = None
|
|
123
|
+
sel: Optional[int] = None
|
|
124
|
+
dscp: Optional[int] = None
|
|
125
|
+
protocol: Optional[str] = None # "UDP or DCCP", etc.
|
|
126
|
+
port: Optional[int] = None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class BroadcomNicQos(BaseModel):
|
|
130
|
+
"""Broadcom NIC QoS information from niccli --dev X qos --ets --show"""
|
|
131
|
+
|
|
132
|
+
device_num: int # Device number this QoS info belongs to
|
|
133
|
+
raw_output: str # Raw command output
|
|
134
|
+
# ETS Configuration
|
|
135
|
+
prio_map: Dict[int, int] = Field(
|
|
136
|
+
default_factory=dict
|
|
137
|
+
) # Priority to TC mapping {0: 0, 1: 0, ...}
|
|
138
|
+
tc_bandwidth: List[int] = Field(
|
|
139
|
+
default_factory=list
|
|
140
|
+
) # TC bandwidth percentages [50, 50, 0, ...]
|
|
141
|
+
tsa_map: Dict[int, str] = Field(
|
|
142
|
+
default_factory=dict
|
|
143
|
+
) # TC to TSA mapping {0: "ets", 1: "ets", ...}
|
|
144
|
+
# PFC Configuration
|
|
145
|
+
pfc_enabled: Optional[int] = None # Bitmap of PFC enabled priorities
|
|
146
|
+
# APP TLV entries
|
|
147
|
+
app_entries: List[BroadcomNicQosAppEntry] = Field(default_factory=list)
|
|
148
|
+
# TC Rate Limit
|
|
149
|
+
tc_rate_limit: List[int] = Field(default_factory=list) # TC rate limits [100, 100, 100, ...]
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class PensandoNicCard(BaseModel):
|
|
153
|
+
"""Pensando NIC card information from nicctl show card"""
|
|
154
|
+
|
|
155
|
+
id: str # Card ID (UUID format)
|
|
156
|
+
pcie_bdf: str # PCIe Bus:Device.Function (e.g., "0000:06:00.0")
|
|
157
|
+
asic: Optional[str] = None # ASIC type (e.g., "salina")
|
|
158
|
+
fw_partition: Optional[str] = None # Firmware partition (e.g., "A")
|
|
159
|
+
serial_number: Optional[str] = None # Serial number (e.g., "FPL25330294")
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class PensandoNicDcqcn(BaseModel):
|
|
163
|
+
"""Pensando NIC DCQCN information from nicctl show dcqcn"""
|
|
164
|
+
|
|
165
|
+
nic_id: str # NIC ID (UUID format)
|
|
166
|
+
pcie_bdf: str # PCIe Bus:Device.Function (e.g., "0000:06:00.0")
|
|
167
|
+
lif_id: Optional[str] = None # Lif ID (UUID format)
|
|
168
|
+
roce_device: Optional[str] = None # ROCE device name (e.g., "rocep9s0")
|
|
169
|
+
dcqcn_profile_id: Optional[str] = None # DCQCN profile id (e.g., "1")
|
|
170
|
+
status: Optional[str] = None # Status (e.g., "Disabled")
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class PensandoNicEnvironment(BaseModel):
|
|
174
|
+
"""Pensando NIC environment information from nicctl show environment"""
|
|
175
|
+
|
|
176
|
+
nic_id: str # NIC ID (UUID format)
|
|
177
|
+
pcie_bdf: str # PCIe Bus:Device.Function (e.g., "0000:06:00.0")
|
|
178
|
+
# Power measurements in Watts
|
|
179
|
+
total_power_drawn: Optional[float] = None # Total power drawn (pin)
|
|
180
|
+
core_power: Optional[float] = None # Core power (pout1)
|
|
181
|
+
arm_power: Optional[float] = None # ARM power (pout2)
|
|
182
|
+
# Temperature measurements in Celsius
|
|
183
|
+
local_board_temperature: Optional[float] = None # Local board temperature
|
|
184
|
+
die_temperature: Optional[float] = None # Die temperature
|
|
185
|
+
# Voltage measurements in millivolts
|
|
186
|
+
input_voltage: Optional[float] = None # Input voltage
|
|
187
|
+
core_voltage: Optional[float] = None # Core voltage
|
|
188
|
+
# Frequency measurements in MHz
|
|
189
|
+
core_frequency: Optional[float] = None # Core frequency
|
|
190
|
+
cpu_frequency: Optional[float] = None # CPU frequency
|
|
191
|
+
p4_stage_frequency: Optional[float] = None # P4 stage frequency
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class PensandoNicPcieAts(BaseModel):
|
|
195
|
+
"""Pensando NIC PCIe ATS information from nicctl show pcie ats"""
|
|
196
|
+
|
|
197
|
+
nic_id: str # NIC ID (UUID format)
|
|
198
|
+
pcie_bdf: str # PCIe Bus:Device.Function (e.g., "0000:06:00.0")
|
|
199
|
+
status: str # Status (e.g., "Disabled", "Enabled")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class PensandoNicPort(BaseModel):
|
|
203
|
+
"""Pensando NIC port information from nicctl show port"""
|
|
204
|
+
|
|
205
|
+
nic_id: str # NIC ID (UUID format)
|
|
206
|
+
pcie_bdf: str # PCIe Bus:Device.Function (e.g., "0000:06:00.0")
|
|
207
|
+
port_id: str # Port ID (UUID format)
|
|
208
|
+
port_name: str # Port name (e.g., "eth1/1")
|
|
209
|
+
# Spec fields
|
|
210
|
+
spec_ifindex: Optional[str] = None
|
|
211
|
+
spec_type: Optional[str] = None
|
|
212
|
+
spec_speed: Optional[str] = None
|
|
213
|
+
spec_admin_state: Optional[str] = None
|
|
214
|
+
spec_fec_type: Optional[str] = None
|
|
215
|
+
spec_pause_type: Optional[str] = None
|
|
216
|
+
spec_num_lanes: Optional[int] = None
|
|
217
|
+
spec_mtu: Optional[int] = None
|
|
218
|
+
spec_tx_pause: Optional[str] = None
|
|
219
|
+
spec_rx_pause: Optional[str] = None
|
|
220
|
+
spec_auto_negotiation: Optional[str] = None
|
|
221
|
+
# Status fields
|
|
222
|
+
status_physical_port: Optional[int] = None
|
|
223
|
+
status_operational_status: Optional[str] = None
|
|
224
|
+
status_link_fsm_state: Optional[str] = None
|
|
225
|
+
status_fec_type: Optional[str] = None
|
|
226
|
+
status_cable_type: Optional[str] = None
|
|
227
|
+
status_num_lanes: Optional[int] = None
|
|
228
|
+
status_speed: Optional[str] = None
|
|
229
|
+
status_auto_negotiation: Optional[str] = None
|
|
230
|
+
status_mac_id: Optional[int] = None
|
|
231
|
+
status_mac_channel: Optional[int] = None
|
|
232
|
+
status_mac_address: Optional[str] = None
|
|
233
|
+
status_transceiver_type: Optional[str] = None
|
|
234
|
+
status_transceiver_state: Optional[str] = None
|
|
235
|
+
status_transceiver_pid: Optional[str] = None
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class PensandoNicQosScheduling(BaseModel):
|
|
239
|
+
"""QoS Scheduling entry"""
|
|
240
|
+
|
|
241
|
+
priority: int
|
|
242
|
+
scheduling_type: Optional[str] = None # e.g., "DWRR"
|
|
243
|
+
bandwidth: Optional[int] = None # Bandwidth in percentage
|
|
244
|
+
rate_limit: Optional[str] = None # Rate limit (e.g., "N/A" or value in Gbps)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class PensandoNicQos(BaseModel):
|
|
248
|
+
"""Pensando NIC QoS information from nicctl show qos"""
|
|
249
|
+
|
|
250
|
+
nic_id: str # NIC ID (UUID format)
|
|
251
|
+
pcie_bdf: str # PCIe Bus:Device.Function (e.g., "0000:06:00.0")
|
|
252
|
+
port_id: str # Port ID (UUID format)
|
|
253
|
+
classification_type: Optional[str] = None # e.g., "DSCP"
|
|
254
|
+
dscp_bitmap: Optional[str] = None # DSCP bitmap
|
|
255
|
+
dscp_range: Optional[str] = None # DSCP range (e.g., "0-63")
|
|
256
|
+
dscp_priority: Optional[int] = None # Priority mapped from DSCP
|
|
257
|
+
pfc_priority_bitmap: Optional[str] = None # PFC priority bitmap
|
|
258
|
+
pfc_no_drop_priorities: Optional[str] = None # PFC no-drop priorities
|
|
259
|
+
scheduling: List[PensandoNicQosScheduling] = Field(default_factory=list) # Scheduling entries
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class PensandoNicRdmaStatistic(BaseModel):
|
|
263
|
+
"""RDMA statistic entry"""
|
|
264
|
+
|
|
265
|
+
name: str # Statistic name
|
|
266
|
+
count: int # Count value
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
class PensandoNicRdmaStatistics(BaseModel):
|
|
270
|
+
"""Pensando NIC RDMA statistics from nicctl show rdma statistics"""
|
|
271
|
+
|
|
272
|
+
nic_id: str # NIC ID (UUID format)
|
|
273
|
+
pcie_bdf: str # PCIe Bus:Device.Function (e.g., "0000:06:00.0")
|
|
274
|
+
statistics: List[PensandoNicRdmaStatistic] = Field(default_factory=list) # Statistics entries
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class PensandoNicVersionHostSoftware(BaseModel):
|
|
278
|
+
"""Pensando NIC host software version from nicctl show version host-software"""
|
|
279
|
+
|
|
280
|
+
nicctl: Optional[str] = None # nicctl version
|
|
281
|
+
ipc_driver: Optional[str] = None # IPC driver version
|
|
282
|
+
ionic_driver: Optional[str] = None # ionic driver version
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class PensandoNicVersionFirmware(BaseModel):
|
|
286
|
+
"""Pensando NIC firmware version from nicctl show version firmware"""
|
|
287
|
+
|
|
288
|
+
nic_id: str # NIC ID (UUID format)
|
|
289
|
+
pcie_bdf: str # PCIe Bus:Device.Function (e.g., "0000:06:00.0")
|
|
290
|
+
cpld: Optional[str] = None # CPLD version
|
|
291
|
+
boot0: Optional[str] = None # Boot0 version
|
|
292
|
+
uboot_a: Optional[str] = None # Uboot-A version
|
|
293
|
+
firmware_a: Optional[str] = None # Firmware-A version
|
|
294
|
+
device_config_a: Optional[str] = None # Device config-A version
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class NetworkDataModel(DataModel):
|
|
298
|
+
"""Complete network configuration data"""
|
|
299
|
+
|
|
300
|
+
interfaces: List[NetworkInterface] = Field(default_factory=list)
|
|
301
|
+
routes: List[Route] = Field(default_factory=list)
|
|
302
|
+
rules: List[RoutingRule] = Field(default_factory=list)
|
|
303
|
+
neighbors: List[Neighbor] = Field(default_factory=list)
|
|
304
|
+
ethtool_info: Dict[str, EthtoolInfo] = Field(
|
|
305
|
+
default_factory=dict
|
|
306
|
+
) # Interface name -> EthtoolInfo mapping
|
|
307
|
+
broadcom_nic_devices: List[BroadcomNicDevice] = Field(default_factory=list)
|
|
308
|
+
broadcom_nic_qos: Dict[int, BroadcomNicQos] = Field(
|
|
309
|
+
default_factory=dict
|
|
310
|
+
) # Device number -> QoS info mapping
|
|
311
|
+
pensando_nic_cards: List[PensandoNicCard] = Field(default_factory=list)
|
|
312
|
+
pensando_nic_dcqcn: List[PensandoNicDcqcn] = Field(default_factory=list)
|
|
313
|
+
pensando_nic_environment: List[PensandoNicEnvironment] = Field(default_factory=list)
|
|
314
|
+
pensando_nic_pcie_ats: List[PensandoNicPcieAts] = Field(default_factory=list)
|
|
315
|
+
pensando_nic_ports: List[PensandoNicPort] = Field(default_factory=list)
|
|
316
|
+
pensando_nic_qos: List[PensandoNicQos] = Field(default_factory=list)
|
|
317
|
+
pensando_nic_rdma_statistics: List[PensandoNicRdmaStatistics] = Field(default_factory=list)
|
|
318
|
+
pensando_nic_version_host_software: Optional[PensandoNicVersionHostSoftware] = None
|
|
319
|
+
pensando_nic_version_firmware: List[PensandoNicVersionFirmware] = Field(default_factory=list)
|
|
@@ -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 .nvme_plugin import NvmePlugin
|
|
27
|
+
|
|
28
|
+
__all__ = ["NvmePlugin"]
|
|
@@ -0,0 +1,167 @@
|
|
|
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 os
|
|
27
|
+
import re
|
|
28
|
+
from typing import Optional
|
|
29
|
+
|
|
30
|
+
from pydantic import ValidationError
|
|
31
|
+
|
|
32
|
+
from nodescraper.base import InBandDataCollector
|
|
33
|
+
from nodescraper.enums import EventCategory, EventPriority, ExecutionStatus, OSFamily
|
|
34
|
+
from nodescraper.models import TaskResult
|
|
35
|
+
|
|
36
|
+
from .nvmedata import NvmeDataModel
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class NvmeCollector(InBandDataCollector[NvmeDataModel, None]):
|
|
40
|
+
"""Collect NVMe details from the system."""
|
|
41
|
+
|
|
42
|
+
DATA_MODEL = NvmeDataModel
|
|
43
|
+
CMD_LINUX = {
|
|
44
|
+
"smart_log": "nvme smart-log {dev}",
|
|
45
|
+
"error_log": "nvme error-log {dev} --log-entries=256",
|
|
46
|
+
"id_ctrl": "nvme id-ctrl {dev}",
|
|
47
|
+
"id_ns": "nvme id-ns {dev}{ns}",
|
|
48
|
+
"fw_log": "nvme fw-log {dev}",
|
|
49
|
+
"self_test_log": "nvme self-test-log {dev}",
|
|
50
|
+
"get_log": "nvme get-log {dev} --log-id=6 --log-len=512",
|
|
51
|
+
"telemetry_log": "nvme telemetry-log {dev} --output-file={dev}_{f_name}",
|
|
52
|
+
}
|
|
53
|
+
CMD_TEMPLATES = list(CMD_LINUX.values())
|
|
54
|
+
|
|
55
|
+
TELEMETRY_FILENAME = "telemetry_log.bin"
|
|
56
|
+
|
|
57
|
+
def collect_data(
|
|
58
|
+
self,
|
|
59
|
+
args=None,
|
|
60
|
+
) -> tuple[TaskResult, Optional[NvmeDataModel]]:
|
|
61
|
+
"""Collect detailed NVMe information from all NVMe devices.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
tuple[TaskResult, Optional[NvmeDataModel]]: Task result and data model with NVMe command outputs.
|
|
65
|
+
"""
|
|
66
|
+
if self.system_info.os_family == OSFamily.WINDOWS:
|
|
67
|
+
self._log_event(
|
|
68
|
+
category=EventCategory.SW_DRIVER,
|
|
69
|
+
description="NVMe collection not supported on Windows",
|
|
70
|
+
priority=EventPriority.WARNING,
|
|
71
|
+
)
|
|
72
|
+
self.result.message = "NVMe data collection skipped on Windows"
|
|
73
|
+
self.result.status = ExecutionStatus.NOT_RAN
|
|
74
|
+
return self.result, None
|
|
75
|
+
|
|
76
|
+
nvme_devices = self._get_nvme_devices()
|
|
77
|
+
if not nvme_devices:
|
|
78
|
+
self._log_event(
|
|
79
|
+
category=EventCategory.SW_DRIVER,
|
|
80
|
+
description="No NVMe devices found",
|
|
81
|
+
priority=EventPriority.ERROR,
|
|
82
|
+
)
|
|
83
|
+
self.result.message = "No NVMe devices found"
|
|
84
|
+
self.result.status = ExecutionStatus.ERROR
|
|
85
|
+
return self.result, None
|
|
86
|
+
|
|
87
|
+
all_device_data = {}
|
|
88
|
+
f_name = self.TELEMETRY_FILENAME
|
|
89
|
+
|
|
90
|
+
for dev in nvme_devices:
|
|
91
|
+
device_data = {}
|
|
92
|
+
ns_suffix = "n1"
|
|
93
|
+
cmd_map = {
|
|
94
|
+
k: v.format(dev=dev, ns=ns_suffix, f_name=f_name) for k, v in self.CMD_LINUX.items()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for key, cmd in cmd_map.items():
|
|
98
|
+
res = self._run_sut_cmd(cmd, sudo=True)
|
|
99
|
+
if "--output-file" in cmd:
|
|
100
|
+
_ = self._read_sut_file(filename=f"{dev}_{f_name}", encoding=None)
|
|
101
|
+
|
|
102
|
+
if res.exit_code == 0:
|
|
103
|
+
device_data[key] = res.stdout
|
|
104
|
+
else:
|
|
105
|
+
self._log_event(
|
|
106
|
+
category=EventCategory.SW_DRIVER,
|
|
107
|
+
description=f"Failed to execute NVMe command: '{cmd}'",
|
|
108
|
+
data={"command": cmd, "exit_code": res.exit_code},
|
|
109
|
+
priority=EventPriority.WARNING,
|
|
110
|
+
console_log=True,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
if device_data:
|
|
114
|
+
all_device_data[os.path.basename(dev)] = device_data
|
|
115
|
+
|
|
116
|
+
if all_device_data:
|
|
117
|
+
try:
|
|
118
|
+
nvme_data = NvmeDataModel(devices=all_device_data)
|
|
119
|
+
except ValidationError as exp:
|
|
120
|
+
self._log_event(
|
|
121
|
+
category=EventCategory.SW_DRIVER,
|
|
122
|
+
description="Validation error while building NvmeDataModel",
|
|
123
|
+
data={"errors": exp.errors(include_url=False)},
|
|
124
|
+
priority=EventPriority.ERROR,
|
|
125
|
+
)
|
|
126
|
+
self.result.message = "NVMe data invalid format"
|
|
127
|
+
self.result.status = ExecutionStatus.ERROR
|
|
128
|
+
return self.result, None
|
|
129
|
+
|
|
130
|
+
self._log_event(
|
|
131
|
+
category=EventCategory.SW_DRIVER,
|
|
132
|
+
description="Collected NVMe data",
|
|
133
|
+
data=nvme_data.model_dump(),
|
|
134
|
+
priority=EventPriority.INFO,
|
|
135
|
+
)
|
|
136
|
+
self.result.message = "NVMe data successfully collected"
|
|
137
|
+
self.result.status = ExecutionStatus.OK
|
|
138
|
+
return self.result, nvme_data
|
|
139
|
+
else:
|
|
140
|
+
|
|
141
|
+
self._log_event(
|
|
142
|
+
category=EventCategory.SW_DRIVER,
|
|
143
|
+
description="Failed to collect any NVMe data",
|
|
144
|
+
priority=EventPriority.ERROR,
|
|
145
|
+
)
|
|
146
|
+
self.result.message = "No NVMe data collected"
|
|
147
|
+
self.result.status = ExecutionStatus.ERROR
|
|
148
|
+
return self.result, None
|
|
149
|
+
|
|
150
|
+
def _get_nvme_devices(self) -> list[str]:
|
|
151
|
+
nvme_devs = []
|
|
152
|
+
|
|
153
|
+
res = self._run_sut_cmd("ls /dev", sudo=False)
|
|
154
|
+
if res.exit_code != 0:
|
|
155
|
+
self._log_event(
|
|
156
|
+
category=EventCategory.SW_DRIVER,
|
|
157
|
+
description="Failed to list /dev directory",
|
|
158
|
+
data={"exit_code": res.exit_code, "stderr": res.stderr},
|
|
159
|
+
priority=EventPriority.ERROR,
|
|
160
|
+
)
|
|
161
|
+
return []
|
|
162
|
+
|
|
163
|
+
for entry in res.stdout.strip().splitlines():
|
|
164
|
+
if re.fullmatch(r"nvme\d+$", entry):
|
|
165
|
+
nvme_devs.append(f"/dev/{entry}")
|
|
166
|
+
|
|
167
|
+
return nvme_devs
|
|
@@ -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 .nvme_collector import NvmeCollector
|
|
29
|
+
from .nvmedata import NvmeDataModel
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class NvmePlugin(InBandDataPlugin[NvmeDataModel, None, None]):
|
|
33
|
+
"""Plugin for collection and analysis of nvme data"""
|
|
34
|
+
|
|
35
|
+
DATA_MODEL = NvmeDataModel
|
|
36
|
+
|
|
37
|
+
COLLECTOR = NvmeCollector
|
|
@@ -0,0 +1,45 @@
|
|
|
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 pydantic import BaseModel
|
|
29
|
+
|
|
30
|
+
from nodescraper.models import DataModel
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class DeviceNvmeData(BaseModel):
|
|
34
|
+
smart_log: Optional[str] = None
|
|
35
|
+
error_log: Optional[str] = None
|
|
36
|
+
id_ctrl: Optional[str] = None
|
|
37
|
+
id_ns: Optional[str] = None
|
|
38
|
+
fw_log: Optional[str] = None
|
|
39
|
+
self_test_log: Optional[str] = None
|
|
40
|
+
get_log: Optional[str] = None
|
|
41
|
+
telemetry_log: Optional[str] = None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class NvmeDataModel(DataModel):
|
|
45
|
+
devices: dict[str, DeviceNvmeData]
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
###############################################################################
|