idrac 0.4.5 → 0.5.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ffcb1d99822a0e7d0015f018b6967e3977d7506438a3e2d917e0615f281aa0e3
4
- data.tar.gz: 188a912ccdcdb5712ead6b5f181d59902f9b50718e3c3e39e2949f6fbc7ad606
3
+ metadata.gz: 32086f37bcf1f9d8bfaf3bf5a54e4159cc2db5ed3b97bc5021203f266e62e7aa
4
+ data.tar.gz: c107965b24d8edc018f44c42da5f6ddd978d978a4ed83eea51304e7b80dc5f40
5
5
  SHA512:
6
- metadata.gz: dfd1714f7a86b37991a7493be186043be14a400f6e36d7712c366c1007857eee7eb4ece8390187a56f7faa921f46ffdf9ad1250ff471daf3ad2ccd884c14cda2
7
- data.tar.gz: 20d5a051050da7a5b75d08529d16e2806af72ac05161393dd1a5cca509f17b2ec497f7a9b2f9c3f0933af72394b81696ae88b48736b6de67bd8ab7ae43319b25
6
+ metadata.gz: 45d74e3ba6b18f6a86e6f644932a20b4316814814a4c37961b54092f6bfe018bfbadc3d9cade70c160dd43c7adb80d7e86e30468e88152a32631b0883b94e09d
7
+ data.tar.gz: b84528baa1d901c687107ea00dc08a1668ad5f60d258cbfb0f9fc69bcbe5efa6530d5c9c2614270f7c3044dd2cd99665168b7f6eadab53d2c4d7b17b1a88fb33
data/README.md CHANGED
@@ -15,6 +15,7 @@ A Ruby client for the Dell iDRAC API. This gem provides a command-line interface
15
15
  - Job queue management (clear, monitor, list)
16
16
  - Lifecycle log and System Event Log (SEL) management
17
17
  - Lifecycle Controller status management
18
+ - Return values as RecursiveOpenStruct objects for convenient attribute access
18
19
 
19
20
  ## Installation
20
21
 
@@ -170,6 +171,25 @@ client.clear_lifecycle!
170
171
  # Clear System Event Logs
171
172
  client.clear_system_event_logs!
172
173
 
174
+ # Working with RecursiveOpenStruct objects
175
+ # Many methods return data as RecursiveOpenStruct objects for easier property access
176
+
177
+ # Get memory information
178
+ memory_modules = client.memory
179
+ memory_modules.each do |dimm|
180
+ # Access properties directly as methods
181
+ puts "#{dimm.name}: #{dimm.capacity_bytes / (1024**3)}GB, Speed: #{dimm.speed_mhz}MHz"
182
+ end
183
+
184
+ # Get storage information
185
+ controller = client.controller
186
+ volumes = client.volumes(controller)
187
+ volumes.each do |volume|
188
+ # Access properties via dot notation
189
+ puts "#{volume.name} (#{volume.raid_level}): #{volume.capacity_bytes / (1024**3)}GB"
190
+ puts " Health: #{volume.health}, FastPath: #{volume.fastpath}"
191
+ end
192
+
173
193
  # Create a client with auto_delete_sessions disabled
174
194
  client = IDRAC.new(
175
195
  host: '192.168.1.100',
@@ -187,6 +207,12 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
187
207
 
188
208
  ## Changelog
189
209
 
210
+ ### Version 0.1.40
211
+ - **Enhanced Return Values**: Methods that return system components now provide RecursiveOpenStruct objects
212
+ - Memory, drives, volumes, PSUs, and fans now support convenient dot notation for attribute access
213
+ - Improved object structure with consistent property naming across different component types
214
+ - Better code organization and readability when working with returned objects
215
+
190
216
  ### Version 0.1.39
191
217
  - **Added Job Management**: New methods for managing iDRAC jobs
192
218
  - List jobs using `jobs` and `jobs_detail`
data/bin/idrac CHANGED
@@ -456,6 +456,37 @@ module IDRAC
456
456
  end
457
457
  end
458
458
 
459
+ desc "license_info", "Display license information"
460
+ map "license:info" => :license_info
461
+ def license_info
462
+ with_idrac_client do |client|
463
+ license = client.license_info
464
+ if license
465
+ puts "\nLicense Information:".green.bold
466
+ puts "Description: #{license['Description']}".cyan
467
+ puts "License Type: #{license['LicenseType']}".cyan
468
+ puts "License Version: #{client.license_version || 'Unknown'}".cyan
469
+ puts "Removable: #{license['Removable']}".cyan
470
+ puts "Status: #{license.dig('Status', 'Health') || 'Unknown'}".cyan
471
+ else
472
+ puts "No license information available".yellow
473
+ end
474
+ end
475
+ end
476
+
477
+ desc "license_version", "Display the iDRAC license version number"
478
+ map "license:version" => :license_version
479
+ def license_version
480
+ with_idrac_client do |client|
481
+ version = client.license_version
482
+ if version
483
+ puts version
484
+ else
485
+ puts "Unknown license version"
486
+ end
487
+ end
488
+ end
489
+
459
490
  desc "test:all", "Run tests for all major functionality areas"
460
491
  map "test" => :test_all
461
492
  option :quiet, type: :boolean, default: false, desc: "Minimize output, just show pass/fail"
@@ -472,6 +503,8 @@ module IDRAC
472
503
  # Basic information
473
504
  { name: "System Summary", method: -> (c) { c.summary } },
474
505
  { name: "Redfish Version", method: -> (c) { c.redfish_version } },
506
+ { name: "License Version", method: -> (c) { c.license_version } },
507
+ { name: "System Health", method: -> (c) { c.system_health } },
475
508
 
476
509
  # Power methods
477
510
  { name: "Power State", method: -> (c) { c.get_power_state } },
@@ -488,6 +521,7 @@ module IDRAC
488
521
 
489
522
  # System components
490
523
  { name: "Memory Info", method: -> (c) { c.memory } },
524
+ { name: "CPU Info", method: -> (c) { c.cpus } },
491
525
  { name: "PSU Info", method: -> (c) { c.psus } },
492
526
  { name: "Fan Info", method: -> (c) { c.fans } },
493
527
  { name: "NIC Info", method: -> (c) { c.nics } },
@@ -863,6 +897,27 @@ module IDRAC
863
897
  end
864
898
  end
865
899
 
900
+ desc "system_cpus", "Get processor/CPU information"
901
+ map "system:cpus" => :system_cpus
902
+ def system_cpus
903
+ with_idrac_client do |client|
904
+ cpus = client.cpus
905
+
906
+ puts "\nProcessor Summary:".green.bold
907
+ puts "=" * 50
908
+
909
+ health_color = cpus[:status] == "OK" ? :green : :red
910
+
911
+ puts "Processor Model:".ljust(25) + cpus[:model].to_s.light_cyan
912
+ puts "Processor Count:".ljust(25) + cpus[:count].to_s.light_cyan
913
+ puts "Physical Cores:".ljust(25) + cpus[:cores].to_s.light_cyan
914
+ puts "Logical Cores:".ljust(25) + cpus[:threads].to_s.light_cyan
915
+ puts "Status:".ljust(25) + cpus[:status].to_s.send(health_color)
916
+
917
+ puts "=" * 50
918
+ end
919
+ end
920
+
866
921
  desc "system_psus", "Get power supply information"
867
922
  map "system:psus" => :system_psus
868
923
  def system_psus
@@ -1103,6 +1158,68 @@ module IDRAC
1103
1158
  end
1104
1159
  end
1105
1160
 
1161
+ desc "system_info", "Get detailed system identification information"
1162
+ map "system:info" => :system_info
1163
+ def system_info
1164
+ with_idrac_client do |client|
1165
+ info = client.system_info
1166
+
1167
+ if info[:is_dell]
1168
+ puts "Dell iDRAC System:".green.bold
1169
+ puts " Service Tag: #{info[:service_tag]}".cyan
1170
+ puts " Model: #{info[:model]}".cyan
1171
+ puts " iDRAC Version: #{info[:idrac_version]}".cyan
1172
+ puts " Firmware Version: #{info[:firmware_version]}".cyan
1173
+ else
1174
+ puts "Not a Dell iDRAC system".yellow
1175
+ puts " Product: #{info[:product]}".cyan
1176
+ if info[:is_ancient_dell]
1177
+ puts " Ancient Dell System detected. Update firmware.".yellow
1178
+ end
1179
+ end
1180
+ end
1181
+ end
1182
+
1183
+ desc "system_config", "Get complete system configuration"
1184
+ map "system:config" => :system_config
1185
+ def system_config
1186
+ with_idrac_client do |client|
1187
+ response = client.authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$expand=*($levels=1)")
1188
+ if response.status == 200
1189
+ config = JSON.parse(response.body)
1190
+ puts JSON.pretty_generate(config)
1191
+ else
1192
+ puts "Failed to retrieve system configuration: #{response.status}".red
1193
+ end
1194
+ end
1195
+ end
1196
+
1197
+ desc "system_health", "Get system health status"
1198
+ map "system:health" => :system_health
1199
+ def system_health
1200
+ with_idrac_client do |client|
1201
+ health = client.system_health
1202
+
1203
+ puts "\nSystem Health Status:".green.bold
1204
+ puts "=" * 50
1205
+
1206
+ # Display overall health with color coding
1207
+ overall_color = health[:overall] == "OK" ? :green : :red
1208
+ system_color = health[:system] == "OK" ? :green : :red
1209
+ processor_color = health[:processor] == "OK" ? :green : :red
1210
+ memory_color = health[:memory] == "OK" ? :green : :red
1211
+ storage_color = health[:storage] == "OK" ? :green : (health[:storage].nil? ? :yellow : :red)
1212
+
1213
+ puts "Overall Health:".ljust(25) + health[:overall].to_s.send(overall_color)
1214
+ puts "System Health:".ljust(25) + health[:system].to_s.send(system_color)
1215
+ puts "Processor Health:".ljust(25) + health[:processor].to_s.send(processor_color)
1216
+ puts "Memory Health:".ljust(25) + health[:memory].to_s.send(memory_color)
1217
+ puts "Storage Health:".ljust(25) + (health[:storage] || "Unknown").to_s.send(storage_color)
1218
+
1219
+ puts "=" * 50
1220
+ end
1221
+ end
1222
+
1106
1223
  # Test commands
1107
1224
  desc "test_live", "Test all major functionality of the gem on a real system"
1108
1225
  map "test:live" => :test_live
data/lib/idrac/client.rb CHANGED
@@ -21,6 +21,7 @@ module IDRAC
21
21
  include System
22
22
  include VirtualMedia
23
23
  include Boot
24
+ include License
24
25
 
25
26
  def initialize(host:, username:, password:, port: 443, use_ssl: true, verify_ssl: false, direct_mode: false, auto_delete_sessions: true, retry_count: 3, retry_delay: 1)
26
27
  @host = host
@@ -0,0 +1,63 @@
1
+ module IDRAC
2
+ module License
3
+ # Gets the license information from the iDRAC
4
+ # @return [Hash] License details
5
+ def license_info
6
+ response = authenticated_request(:get, "/redfish/v1/LicenseService/Licenses")
7
+ if response.status != 200
8
+ debug "Failed to retrieve licenses list: #{response.status}", 1, :red
9
+ return nil
10
+ end
11
+
12
+ license_data = JSON.parse(response.body)
13
+ debug "License collection: #{license_data}", 2
14
+
15
+ # Check if there are any license entries
16
+ if !license_data["Members"] || license_data["Members"].empty?
17
+ debug "No licenses found", 1, :yellow
18
+ return nil
19
+ end
20
+
21
+ # Get the first license in the list
22
+ license_uri = license_data["Members"][0]["@odata.id"]
23
+ debug "Using license URI: #{license_uri}", 2
24
+
25
+ # Get detailed license information
26
+ license_response = authenticated_request(:get, license_uri)
27
+ if license_response.status != 200
28
+ debug "Failed to retrieve license details: #{license_response.status}", 1, :red
29
+ return nil
30
+ end
31
+
32
+ license_details = JSON.parse(license_response.body)
33
+ debug "License details: #{license_details}", 2
34
+
35
+ return license_details
36
+ end
37
+
38
+ # Extracts the iDRAC version from the license description
39
+ # @return [Integer, nil] The license version (e.g. 9) or nil if not found
40
+ def license_version
41
+ license = license_info
42
+ return nil unless license
43
+
44
+ # Check the Description field, which often contains the version
45
+ # Example: "iDRAC9 Enterprise License"
46
+ if license["Description"] && license["Description"].match(/iDRAC(\d+)/i)
47
+ version = license["Description"].match(/iDRAC(\d+)/i)[1].to_i
48
+ debug "Found license version from Description: #{version}", 1
49
+ return version
50
+ end
51
+
52
+ # Try alternative fields if Description didn't work
53
+ if license["Name"] && license["Name"].match(/iDRAC(\d+)/i)
54
+ version = license["Name"].match(/iDRAC(\d+)/i)[1].to_i
55
+ debug "Found license version from Name: #{version}", 1
56
+ return version
57
+ end
58
+
59
+ debug "Could not determine license version from license info", 1, :yellow
60
+ nil
61
+ end
62
+ end
63
+ end
data/lib/idrac/storage.rb CHANGED
@@ -50,7 +50,8 @@ module IDRAC
50
50
  encryption_capability: controller.dig("Oem", "Dell", "DellController", "EncryptionCapability"),
51
51
  controller_type: controller.dig("Oem", "Dell", "DellController", "ControllerType"),
52
52
  pci_slot: controller.dig("Oem", "Dell", "DellController", "PCISlot"),
53
- raw: controller
53
+ raw: controller,
54
+ odata_id: controller["@odata.id"]
54
55
  }
55
56
 
56
57
  RecursiveOpenStruct.new(controller_data, recurse_over_arrays: true)
data/lib/idrac/system.rb CHANGED
@@ -332,6 +332,110 @@ module IDRAC
332
332
  return nics_with_pci
333
333
  end
334
334
 
335
+ # Get system identification information
336
+ def system_info
337
+ response = authenticated_request(:get, "/redfish/v1")
338
+
339
+ if response.status == 200
340
+ begin
341
+ data = JSON.parse(response.body)
342
+
343
+ # Initialize return hash with defaults
344
+ info = {
345
+ is_dell: false,
346
+ is_ancient_dell: false,
347
+ product: data["Product"] || "Unknown",
348
+ service_tag: nil,
349
+ model: nil,
350
+ idrac_version: data["RedfishVersion"],
351
+ firmware_version: nil
352
+ }
353
+
354
+ # Check if it's a Dell iDRAC
355
+ if data["Product"] == "Integrated Dell Remote Access Controller"
356
+ info[:is_dell] = true
357
+
358
+ # Get service tag from Dell OEM data
359
+ info[:service_tag] = data.dig("Oem", "Dell", "ServiceTag")
360
+
361
+ # Get firmware version - try both common locations
362
+ info[:firmware_version] = data["FirmwareVersion"] || data.dig("Oem", "Dell", "FirmwareVersion")
363
+
364
+ # Get additional system information
365
+ system_response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1")
366
+ if system_response.status == 200
367
+ system_data = JSON.parse(system_response.body)
368
+ info[:model] = system_data["Model"]
369
+ end
370
+
371
+ return info
372
+ else
373
+ # Try to handle ancient Dell models where Product is null or non-standard
374
+ if data["Product"].nil? || data.dig("Oem", "Dell")
375
+ info[:is_ancient_dell] = true
376
+ return info
377
+ end
378
+ end
379
+
380
+ return info
381
+ rescue JSON::ParserError
382
+ raise Error, "Failed to parse system information: #{response.body}"
383
+ end
384
+ else
385
+ raise Error, "Failed to get system information. Status code: #{response.status}"
386
+ end
387
+ end
388
+
389
+ # Get processor/CPU information
390
+ def cpus
391
+ response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$expand=*($levels=1)")
392
+
393
+ if response.status == 200
394
+ begin
395
+ data = JSON.parse(response.body)
396
+
397
+ summary = {
398
+ count: data.dig("ProcessorSummary", "Count"),
399
+ model: data.dig("ProcessorSummary", "Model"),
400
+ cores: data.dig("ProcessorSummary", "CoreCount"),
401
+ threads: data.dig("ProcessorSummary", "LogicalProcessorCount"),
402
+ status: data.dig("ProcessorSummary", "Status", "Health")
403
+ }
404
+
405
+ return summary
406
+ rescue JSON::ParserError
407
+ raise Error, "Failed to parse processor information: #{response.body}"
408
+ end
409
+ else
410
+ raise Error, "Failed to get processor information. Status code: #{response.status}"
411
+ end
412
+ end
413
+
414
+ # Get system health status
415
+ def system_health
416
+ response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$expand=*($levels=1)")
417
+
418
+ if response.status == 200
419
+ begin
420
+ data = JSON.parse(response.body)
421
+
422
+ health = {
423
+ overall: data.dig("Status", "HealthRollup"),
424
+ system: data.dig("Status", "Health"),
425
+ processor: data.dig("ProcessorSummary", "Status", "Health"),
426
+ memory: data.dig("MemorySummary", "Status", "Health"),
427
+ storage: data.dig("Storage", "Status", "Health")
428
+ }
429
+
430
+ return health
431
+ rescue JSON::ParserError
432
+ raise Error, "Failed to parse system health information: #{response.body}"
433
+ end
434
+ else
435
+ raise Error, "Failed to get system health. Status code: #{response.status}"
436
+ end
437
+ end
438
+
335
439
  # Get system event logs
336
440
  def system_event_logs
337
441
  response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Logs/Sel?$expand=*($levels=1)")
data/lib/idrac/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IDRAC
4
- VERSION = "0.4.5"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/idrac.rb CHANGED
@@ -51,4 +51,5 @@ require 'idrac/storage'
51
51
  require 'idrac/system'
52
52
  require 'idrac/virtual_media'
53
53
  require 'idrac/boot'
54
+ require 'idrac/license'
54
55
  require 'idrac/client'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: idrac
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Siegel
@@ -241,6 +241,7 @@ files:
241
241
  - lib/idrac/firmware.rb
242
242
  - lib/idrac/firmware_catalog.rb
243
243
  - lib/idrac/jobs.rb
244
+ - lib/idrac/license.rb
244
245
  - lib/idrac/lifecycle.rb
245
246
  - lib/idrac/power.rb
246
247
  - lib/idrac/session.rb