Module: IDRAC::System
- Included in:
- Client
- Defined in:
- lib/idrac/system.rb
Instance Method Summary collapse
-
#clear_system_event_logs ⇒ Object
Clear system event logs.
-
#cpus ⇒ Object
Get processor/CPU information.
-
#fans ⇒ Object
Get fan information.
-
#get_basic_system_info ⇒ Object
Get basic system information (used for test_live function).
-
#get_system_config ⇒ Object
Get complete system configuration.
-
#get_system_summary ⇒ Object
Get system summary information (used by CLI summary command).
-
#idrac_interface ⇒ Object
Kind of like a NIC, but serves a different purpose.
-
#idrac_network ⇒ Object
Get iDRAC network information.
-
#memory ⇒ Object
Get memory information.
-
#nics ⇒ Object
Get NIC information.
-
#nics_to_pci(nics, pci_devices) ⇒ Object
Map NICs to PCI bus IDs for Mellanox cards.
-
#pci_devices ⇒ Object
Get PCI device information.
-
#psus ⇒ Object
Get power supply information.
-
#system_event_logs ⇒ Object
Get system event logs.
-
#system_health ⇒ Object
Get system health status.
-
#system_info ⇒ Object
Get system identification information.
-
#total_memory_human(memory_data) ⇒ Object
Get total memory in human-readable format.
Instance Method Details
#clear_system_event_logs ⇒ Object
Clear system event logs
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 |
# File 'lib/idrac/system.rb', line 689 def clear_system_event_logs response = authenticated_request( :post, "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Sel/Actions/LogService.ClearLog", body: {}.to_json, headers: { 'Content-Type': 'application/json' } ) if response.status.between?(200, 299) puts "System Event Logs cleared".green return true else = "Failed to clear System Event Logs. Status code: #{response.status}" begin error_data = JSON.parse(response.body) += ", Message: #{error_data['error']['message']}" if error_data['error'] && error_data['error']['message'] rescue # Ignore JSON parsing errors end raise Error, end end |
#cpus ⇒ Object
Get processor/CPU information
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 |
# File 'lib/idrac/system.rb', line 616 def cpus response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$expand=*($levels=1)") if response.status == 200 begin data = JSON.parse(response.body) summary = { "count" => data.dig("ProcessorSummary", "Count"), "model" => data.dig("ProcessorSummary", "Model"), "cores" => data.dig("ProcessorSummary", "CoreCount"), "threads" => data.dig("ProcessorSummary", "LogicalProcessorCount"), "status" => data.dig("ProcessorSummary", "Status", "Health") } return summary rescue JSON::ParserError raise Error, "Failed to parse processor information: #{response.body}" end else raise Error, "Failed to get processor information. Status code: #{response.status}" end end |
#fans ⇒ Object
Get fan information
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/idrac/system.rb', line 73 def fans tries = 0 max_tries = 3 while tries < max_tries begin response = authenticated_request(:get, "/redfish/v1/Chassis/System.Embedded.1/Thermal?$expand=*($levels=1)") if response.status == 200 data = JSON.parse(response.body) fans = data["Fans"].map do |fan| puts "Fan: #{fan["Name"]} > #{fan["Reading"]} > #{fan.dig("Status", "Health")}" { "name" => fan["Name"], "rpm" => fan["Reading"], "serial" => fan["SerialNumber"], "status" => fan.dig("Status", "Health") } end return fans elsif response.status.between?(400, 499) # Check if system is powered off power_response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$select=PowerState") if power_response.status == 200 && JSON.parse(power_response.body)["PowerState"] == "Off" puts "WARN: System is off. Fans are not available.".yellow return [] end end rescue => e puts "WARN: Error getting fans: #{e.}".yellow end tries += 1 puts "Failed to get fans. Retrying #{tries}/#{max_tries}.".red if tries < max_tries sleep 10 end puts "Failed to get fans after #{max_tries} tries".red return [] end |
#get_basic_system_info ⇒ Object
Get basic system information (used for test_live function)
808 809 810 811 812 813 814 815 816 817 818 819 820 |
# File 'lib/idrac/system.rb', line 808 def get_basic_system_info response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1") if response.status == 200 data = JSON.parse(response.body) return { model: data["Model"], sku: data["SKU"] } else raise Error, "Failed to get basic system information: #{response.status}" end end |
#get_system_config ⇒ Object
Get complete system configuration
721 722 723 724 725 726 727 728 729 |
# File 'lib/idrac/system.rb', line 721 def get_system_config response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$expand=*($levels=1)") if response.status == 200 return JSON.parse(response.body) else raise Error, "Failed to retrieve system configuration: #{response.status}" end end |
#get_system_summary ⇒ Object
Get system summary information (used by CLI summary command)
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 |
# File 'lib/idrac/system.rb', line 732 def get_system_summary # Get system information system_response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1") system_info = JSON.parse(system_response.body) # Get iDRAC information idrac_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1") idrac_info = JSON.parse(idrac_response.body) # Initialize network info values to Unknown ip_address = "Unknown" mac_address = "Unknown" # Try to get network information begin # First, get the EthernetInterfaces collection to find available interfaces eth_collection_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/EthernetInterfaces") if eth_collection_response.status == 200 eth_collection = JSON.parse(eth_collection_response.body) if eth_collection["Members"] && eth_collection["Members"].any? # Use the first interface found first_eth = eth_collection["Members"][0]["@odata.id"] debug "Found network interface: #{first_eth}", 2 first_eth_response = authenticated_request(:get, first_eth) if first_eth_response.status == 200 first_eth_info = JSON.parse(first_eth_response.body) ip_address = first_eth_info.dig("IPv4Addresses", 0, "Address") || "Unknown" mac_address = first_eth_info.dig("MACAddress") || "Unknown" debug "Network info - IP: #{ip_address}, MAC: #{mac_address}", 2 end end end rescue => e debug "Failed to get network info: #{e.}", 1, :yellow # Failed to get network info, leave as Unknown end # Initialize license_type to Unknown license_type = "Unknown" license_description = nil # Try to get license information (new approach that works with iDRAC 8 too) license_info = license_info() rescue nil license_version = license_version() rescue nil if license_info license_type = license_info["LicenseType"] || "Unknown" license_description = license_info["Description"] end # Format the license display string license_display = license_type if license_description && license_type != "Unknown" license_display = "#{license_type} (#{license_description})" end # Return the system summary { power_state: system_info["PowerState"], model: system_info["Model"], host_name: system_info["HostName"], operating_system: system_info.dig("Oem", "Dell", "OperatingSystem"), os_version: system_info.dig("Oem", "Dell", "OperatingSystemVersion"), service_tag: system_info["SKU"], bios_version: system_info.dig("BiosVersion"), idrac_firmware: idrac_info.dig("FirmwareVersion"), ip_address: ip_address, mac_address: mac_address, license: license_display } end |
#idrac_interface ⇒ Object
Kind of like a NIC, but serves a different purpose.
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 |
# File 'lib/idrac/system.rb', line 513 def idrac_interface # First try to get the EthernetInterfaces collection to get the correct path collection_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/EthernetInterfaces") if collection_response.status == 200 collection_data = JSON.parse(collection_response.body) if collection_data["Members"] && collection_data["Members"].any? # Use the first interface found interface_path = collection_data["Members"][0]["@odata.id"] debug "Using interface path: #{interface_path}", 2 response = authenticated_request(:get, interface_path) if response.status == 200 idrac_data = JSON.parse(response.body) return { "name" => idrac_data["Id"], "status" => idrac_data.dig("Status", "Health") == 'OK' ? 'Up' : 'Down', "mac" => idrac_data["MACAddress"], "mask" => idrac_data["IPv4Addresses"].first["SubnetMask"], "ipv4" => idrac_data["IPv4Addresses"].first["Address"], "origin" => idrac_data["IPv4Addresses"].first["AddressOrigin"], # DHCP or Static "port" => nil, "speed_mbps" => idrac_data["SpeedMbps"], "kind" => "ethernet" } end end end # Fallback to the old hard-coded path response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/EthernetInterfaces/iDRAC.Embedded.1%23NIC.1") idrac_data = JSON.parse(response.body) { "name" => idrac_data["Id"], "status" => idrac_data.dig("Status", "Health") == 'OK' ? 'Up' : 'Down', "mac" => idrac_data["MACAddress"], "mask" => idrac_data["IPv4Addresses"].first["SubnetMask"], "ipv4" => idrac_data["IPv4Addresses"].first["Address"], "origin" => idrac_data["IPv4Addresses"].first["AddressOrigin"], # DHCP or Static "port" => nil, "speed_mbps" => idrac_data["SpeedMbps"], "kind" => "ethernet" } end |
#idrac_network ⇒ Object
Get iDRAC network information
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/idrac/system.rb', line 240 def idrac_network # First try to get the EthernetInterfaces collection to get the correct path collection_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/EthernetInterfaces") if collection_response.status == 200 begin collection_data = JSON.parse(collection_response.body) if collection_data["Members"] && collection_data["Members"].any? # Use the first interface found interface_path = collection_data["Members"][0]["@odata.id"] debug "Using interface path: #{interface_path}", 2 response = authenticated_request(:get, interface_path) if response.status == 200 data = JSON.parse(response.body) idrac = { "name" => data["Id"], "status" => data.dig("Status", "Health") == 'OK' ? 'Up' : 'Down', "mac" => data["MACAddress"], "mask" => data["IPv4Addresses"].first["SubnetMask"], "ipv4" => data["IPv4Addresses"].first["Address"], "origin" => data["IPv4Addresses"].first["AddressOrigin"], # DHCP or Static "port" => nil, "speed_mbps" => data["SpeedMbps"], "kind" => "ethernet" } return idrac else raise Error, "Failed to get iDRAC network. Status code: #{response.status}" end else raise Error, "No Ethernet interfaces found" end rescue JSON::ParserError raise Error, "Failed to parse iDRAC network response: #{collection_response.body}" end else # Fallback to the old hard-coded path for backwards compatibility response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/EthernetInterfaces/iDRAC.Embedded.1%23NIC.1") if response.status == 200 begin data = JSON.parse(response.body) idrac = { "name" => data["Id"], "status" => data.dig("Status", "Health") == 'OK' ? 'Up' : 'Down', "mac" => data["MACAddress"], "mask" => data["IPv4Addresses"].first["SubnetMask"], "ipv4" => data["IPv4Addresses"].first["Address"], "origin" => data["IPv4Addresses"].first["AddressOrigin"], # DHCP or Static "port" => nil, "speed_mbps" => data["SpeedMbps"], "kind" => "ethernet" } return idrac rescue JSON::ParserError raise Error, "Failed to parse iDRAC network response: #{response.body}" end else raise Error, "Failed to get iDRAC network. Status code: #{response.status}" end end end |
#memory ⇒ Object
Get memory information
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/idrac/system.rb', line 7 def memory response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1/Memory?$expand=*($levels=1)") if response.status == 200 begin data = JSON.parse(response.body) memory = data["Members"].map do |m| dimm_name = m["Name"] # e.g. DIMM A1 bank, index = /DIMM ([A-Z])(\d+)/.match(dimm_name).captures { "model" => m["Model"], "name" => m["Name"], "capacity_bytes" => m["CapacityMiB"].to_i * 1024 * 1024, "health" => m.dig("Status","Health") || "N/A", "speed_mhz" => m["OperatingSpeedMhz"], "part_number" => m["PartNumber"], "serial" => m["SerialNumber"], "bank" => bank, "index" => index.to_i } end return memory.sort_by { |m| [m["bank"] || "Z", m["index"] || 999] } rescue JSON::ParserError raise Error, "Failed to parse memory response: #{response.body}" end else raise Error, "Failed to get memory. Status code: #{response.status}" end end |
#nics ⇒ Object
Get NIC information
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/idrac/system.rb', line 117 def nics response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1/NetworkAdapters?$expand=*($levels=1)") if response.status == 200 begin adapters_data = JSON.parse(response.body) # Try to get network configuration from SCP for IP addresses nic_ip_map = {} # Try to get IP data from SCP begin scp_data = get_system_configuration_profile(target: "NIC") if scp_data && scp_data["SystemConfiguration"] && scp_data["SystemConfiguration"]["Components"] scp_data["SystemConfiguration"]["Components"].each do |component| next unless component["FQDD"] =~ /NIC\.|BCM57/ # Match NIC components # Extract IP configuration if available ip_attrs = component["Attributes"]&.select { |attr| attr["Name"] =~ /IPAddress|IPv4Address|IPV4Address/ } mac_attrs = component["Attributes"]&.select { |attr| attr["Name"] =~ /MACAddress/ } if ip_attrs&.any? && mac_attrs&.any? mac = mac_attrs.first["Value"] ip = ip_attrs.first["Value"] nic_ip_map[mac&.upcase] = ip unless ip.nil? || ip.empty? || ip == "0.0.0.0" end end end rescue => e # Ignore errors, just continue end # Try to get static IP configuration from iDRAC begin idrac_net = idrac_network if idrac_net && idrac_net["mac"] && idrac_net["ipv4"] nic_ip_map[idrac_net["mac"].upcase] = idrac_net["ipv4"] end rescue => e # Ignore errors, just continue end nics = [] # Process each network adapter adapters_data["Members"].each do |adapter| # Get basic adapter info adapter_info = { "name" => adapter["Id"], "manufacturer" => adapter["Manufacturer"], "model" => adapter["Model"], "part_number" => adapter["PartNumber"], "serial" => adapter["SerialNumber"], "ports" => [] } # Try each port type in order of preference ["NetworkPorts", "Ports"].each do |port_type| ports_path = "#{adapter["@odata.id"].split("v1/").last}/#{port_type}?$expand=*($levels=1)" begin ports_response = authenticated_request(:get, "/redfish/v1/#{ports_path}") if ports_response.status == 200 ports_data = JSON.parse(ports_response.body) if ports_data["Members"] && ports_data["Members"].any? # Process each port adapter_info["ports"] = ports_data["Members"].map do |port| # Extract port info based on port type if port_type == "NetworkPorts" # NetworkPorts style (usually iDRAC 8) mac_addr = port["AssociatedNetworkAddresses"]&.first link_speed_mbps = port.dig("SupportedLinkCapabilities", 0, "LinkSpeedMbps") || 0 port_num = port["PhysicalPortNumber"] link_status = port["LinkStatus"] else # Ports style (usually iDRAC 9) mac_addr = port.dig("Ethernet", "AssociatedMACAddresses", 0) link_speed_mbps = port["CurrentSpeedGbps"] ? (port["CurrentSpeedGbps"].to_i * 1000) : 0 port_num = port["PortId"] link_status = port["LinkStatus"] =~ /up/i ? "Up" : "Down" end # Get IP address from our mapping ip_address = nic_ip_map[mac_addr&.upcase] puts "NIC: #{port["Id"]} > #{mac_addr} > #{link_status} > #{port_num} > #{link_speed_mbps}Mbps > #{ip_address || 'No IP'}" { "name" => port["Id"], "status" => link_status, "mac" => mac_addr, "ip_address" => ip_address, "port" => port_num, "speed_mbps" => link_speed_mbps, "kind" => port_type == "NetworkPorts" ? "ethernet" : "port" } end # If we found ports, no need to try the other endpoint break end end rescue => e # Ignore errors and try the next port type end end # Add adapter to our list nics << adapter_info end return nics rescue JSON::ParserError raise Error, "Failed to parse NICs response: #{response.body}" end else raise Error, "Failed to get NICs. Status code: #{response.status}" end end |
#nics_to_pci(nics, pci_devices) ⇒ Object
Map NICs to PCI bus IDs for Mellanox cards
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
# File 'lib/idrac/system.rb', line 470 def nics_to_pci(nics, pci_devices) # Filter for Mellanox network controllers mellanox_pci = pci_devices.select do |dev| dev['device_class'] =~ /NetworkController/ && dev['manufacturer'] =~ /Mellanox/ end # Create mapping of NIC names to PCI IDs mapping = {} mellanox_pci.each do |dev| if dev['nic'] && dev['nic'] =~ /.*\/([^\/\-]+-\d+)/ nic = $1 # e.g. NIC.Slot.1-1 if dev['id'] =~ /^(\d+)-\d+-\d/ pci_bus = $1 # e.g. 59 mapping[nic] = pci_bus end end end # Add PCI bus info to each NIC port nics_with_pci = nics.map do |nic| nic_with_pci = nic.dup if nic_with_pci["ports"] nic_with_pci["ports"] = nic_with_pci["ports"].map do |port| port_with_pci = port.dup pci_bus = mapping[port["name"]] if pci_bus port_with_pci["pci"] = pci_bus port_with_pci["linux_device"] = "enp#{pci_bus}s0np0" # e.g. enp3s0np0 end port_with_pci end end nic_with_pci end return nics_with_pci end |
#pci_devices ⇒ Object
Get PCI device information
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 |
# File 'lib/idrac/system.rb', line 311 def pci_devices # First try the standard PCIeDevices endpoint response = authenticated_request(:get, "/redfish/v1/Chassis/System.Embedded.1/PCIeDevices?$expand=*($levels=1)") if response.status == 200 begin data = JSON.parse(response.body) pci = data["Members"].map do |stub| manufacturer = stub["Manufacturer"] # Get PCIe function details if available pcie_function = nil if stub.dig("Links", "PCIeFunctions", 0, "@odata.id") pcie_function_path = stub.dig("Links", "PCIeFunctions", 0, "@odata.id").split("v1/").last function_response = authenticated_request(:get, "/redfish/v1/#{pcie_function_path}") if function_response.status == 200 pcie_function = JSON.parse(function_response.body) end end # Create device info with available data device_info = { "device_class" => pcie_function ? pcie_function["DeviceClass"] : nil, "manufacturer" => manufacturer, "name" => stub["Name"], "description" => stub["Description"], "id" => pcie_function ? pcie_function["Id"] : stub["Id"], "slot_type" => pcie_function ? pcie_function.dig("Oem", "Dell", "DellPCIeFunction", "SlotType") : nil, "bus_width" => pcie_function ? pcie_function.dig("Oem", "Dell", "DellPCIeFunction", "DataBusWidth") : nil, "nic" => pcie_function ? pcie_function.dig("Links", "EthernetInterfaces", 0, "@odata.id") : nil } puts "PCI Device: #{device_info["name"]} > #{device_info["manufacturer"]} > #{device_info["device_class"]} > #{device_info["description"]} > #{device_info["id"]}" device_info end return pci rescue JSON::ParserError raise Error, "Failed to parse PCI devices response: #{response.body}" end else # For iDRAC 8, try Dell's recommended approach using System endpoint with PCIeDevices select option system_pcie_response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$select=PCIeDevices") if system_pcie_response.status == 200 begin system_data = JSON.parse(system_pcie_response.body) if system_data.key?("PCIeDevices") && !system_data["PCIeDevices"].empty? pci_devices = [] # Process each PCIe device system_data["PCIeDevices"].each do |device_link| if device_link.is_a?(Hash) && device_link["@odata.id"] device_path = device_link["@odata.id"] device_response = authenticated_request(:get, device_path) if device_response.status == 200 device_data = JSON.parse(device_response.body) pci_devices << { "device_class" => device_data["DeviceType"] || "Unknown", "manufacturer" => device_data["Manufacturer"], "name" => device_data["Name"] || device_data["Id"], "description" => device_data["Description"], "id" => device_data["Id"], "slot_type" => device_data.dig("Oem", "Dell", "SlotType"), "bus_width" => device_data.dig("Oem", "Dell", "BusWidth"), "nic" => nil } end end end return pci_devices unless pci_devices.empty? end rescue JSON::ParserError # Continue to next approach end end # Try NetworkAdapters as an alternative for finding PCIe devices (especially NICs and FC adapters) nic_response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1/NetworkAdapters?$expand=*($levels=1)") if nic_response.status == 200 begin nic_data = JSON.parse(nic_response.body) pci_devices = [] # Extract PCI info from network adapters if nic_data["Members"] && !nic_data["Members"].empty? nic_data["Members"].each do |adapter| next unless adapter["Model"] || adapter["Manufacturer"] # Check if this is a Fiber Channel adapter by name or model is_fc = (adapter["Name"] =~ /FC/i || adapter["Model"] =~ /FC/i || adapter["Id"] =~ /FC/i || adapter["Description"] =~ /Fibre/i) ? true : false device_class = is_fc ? "FibreChannelController" : "NetworkController" pci_devices << { "device_class" => device_class, "manufacturer" => adapter["Manufacturer"], "name" => adapter["Name"] || adapter["Id"], "description" => adapter["Description"], "id" => adapter["Id"], "slot_type" => adapter.dig("Oem", "Dell", "SlotType") || (adapter["Id"] =~ /Slot\.(\d+)/ ? "Slot #{$1}" : nil), "bus_width" => nil, "nic" => adapter["@odata.id"] } end return pci_devices unless pci_devices.empty? end rescue JSON::ParserError # Continue to fallback end end # Last resort: check if PCIeFunctions are directly available pcie_functions_response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1/PCIeFunctions?$expand=*($levels=1)") if pcie_functions_response.status == 200 begin functions_data = JSON.parse(pcie_functions_response.body) if functions_data["Members"] && !functions_data["Members"].empty? pci_devices = functions_data["Members"].map do |function| { "device_class" => function["DeviceClass"] || "Unknown", "manufacturer" => function["Manufacturer"] || "Unknown", "name" => function["Name"] || function["Id"], "description" => function["Description"], "id" => function["Id"], "slot_type" => function.dig("Oem", "Dell", "SlotType"), "bus_width" => function.dig("Oem", "Dell", "DataBusWidth"), "nic" => nil } end return pci_devices end rescue JSON::ParserError # Continue to fallback end end # Fallback for any version when all endpoints unavailable puts "PCI device information not available through standard or alternative endpoints" if @verbose return [] end end |
#psus ⇒ Object
Get power supply information
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/idrac/system.rb', line 41 def psus response = authenticated_request(:get, "/redfish/v1/Chassis/System.Embedded.1/Power") if response.status == 200 begin data = JSON.parse(response.body) puts "Power Supplies".green psus = data["PowerSupplies"].map do |psu| puts "PSU: #{psu["Name"]} > #{psu["PowerInputWatts"]}W > #{psu.dig("Status", "Health")}" { "name" => psu["Name"], "voltage" => psu["LineInputVoltage"], "voltage_human" => psu["LineInputVoltageType"], # AC240V "watts" => psu["PowerInputWatts"], "part" => psu["PartNumber"], "model" => psu["Model"], "serial" => psu["SerialNumber"], "status" => psu.dig("Status", "Health") } end return psus rescue JSON::ParserError raise Error, "Failed to parse PSU response: #{response.body}" end else raise Error, "Failed to get PSUs. Status code: #{response.status}" end end |
#system_event_logs ⇒ Object
Get system event logs
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 |
# File 'lib/idrac/system.rb', line 666 def system_event_logs response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Logs/Sel?$expand=*($levels=1)") if response.status == 200 begin data = JSON.parse(response.body) logs = data["Members"].map do |log| puts "#{log['Id']} : #{log['Created']} : #{log['Message']} : #{log['Severity']}".yellow log end # Sort by creation date, newest first return logs.sort_by { |log| log['Created'] }.reverse rescue JSON::ParserError raise Error, "Failed to parse system event logs response: #{response.body}" end else raise Error, "Failed to get system event logs. Status code: #{response.status}" end end |
#system_health ⇒ Object
Get system health status
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
# File 'lib/idrac/system.rb', line 641 def system_health response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$expand=*($levels=1)") if response.status == 200 begin data = JSON.parse(response.body) health = { "overall" => data.dig("Status", "HealthRollup"), "system" => data.dig("Status", "Health"), "processor" => data.dig("ProcessorSummary", "Status", "Health"), "memory" => data.dig("MemorySummary", "Status", "Health"), "storage" => data.dig("Storage", "Status", "Health") } return health rescue JSON::ParserError raise Error, "Failed to parse system health information: #{response.body}" end else raise Error, "Failed to get system health. Status code: #{response.status}" end end |
#system_info ⇒ Object
Get system identification information
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 |
# File 'lib/idrac/system.rb', line 562 def system_info response = authenticated_request(:get, "/redfish/v1") if response.status == 200 begin data = JSON.parse(response.body) # Initialize return hash with defaults info = { "is_dell" => false, "is_ancient_dell" => false, "product" => data["Product"] || "Unknown", "service_tag" => nil, "model" => nil, "idrac_version" => data["RedfishVersion"], "firmware_version" => nil } # Check if it's a Dell iDRAC if data["Product"] == "Integrated Dell Remote Access Controller" info["is_dell"] = true # Get service tag from Dell OEM data info["service_tag"] = data.dig("Oem", "Dell", "ServiceTag") # Get firmware version - try both common locations info["firmware_version"] = data["FirmwareVersion"] || data.dig("Oem", "Dell", "FirmwareVersion") # Get additional system information system_response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1") if system_response.status == 200 system_data = JSON.parse(system_response.body) info["model"] = system_data["Model"] end return info else # Try to handle ancient Dell models where Product is null or non-standard if data["Product"].nil? || data.dig("Oem", "Dell") info["is_ancient_dell"] = true return info end end return info rescue JSON::ParserError raise Error, "Failed to parse system information: #{response.body}" end else raise Error, "Failed to get system information. Status code: #{response.status}" end end |
#total_memory_human(memory_data) ⇒ Object
Get total memory in human-readable format
715 716 717 718 |
# File 'lib/idrac/system.rb', line 715 def total_memory_human(memory_data) total_memory = memory_data.sum { |m| m["capacity_bytes"] } "%0.2f GB" % (total_memory.to_f / 1.gigabyte) end |