idrac 0.5.9 → 0.6.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: 56dcfdf9014a4dfd05c9c01a44ee4f5dec6468e6d2ee22d15e72bcf370d57257
4
- data.tar.gz: ba2a732023a86004316b8a67998dfa709d7d9cc773de39ef31c37fe3a0f60061
3
+ metadata.gz: 5c77b78a7bad9201ed36f9570e2d0d39dc57559964d736648fdcd3f34e46fded
4
+ data.tar.gz: 0e5656537537fac5cbc02cc72c5c23e174c30d76c90d3cc80b2dd4da36d20ec4
5
5
  SHA512:
6
- metadata.gz: 41d8222f030d437063369c88c7cede0fddb62967b9a20c070e615c22681bf484620782ed1b0a132727b4192c88f3871298b18f049e4a70a954d6698bb87998f8
7
- data.tar.gz: 6a6d88a11b039e6d6d2b0159370fbee14531d068844bb8c4a9157fa1038e968293fdbbda091ae6ead4fa0a706e4b92966484fe0ef63b586c718a423084817499
6
+ metadata.gz: f89101dedb96aeabd91eb5c210231d94500f65e41bd85c497a76c23478f658170d30ab11ba1ece65d113ae66a8736dd15ad6d4d44ecddf8e8da2ae3f6cd570d7
7
+ data.tar.gz: 7a072578dd6b178bc59c0ac09a66cd5752d1dd62d530d65c964aa624cf209df5bb1ed5189045ca04e3b4cab880d26646d3b045364aa352cde5fae3cca97dc6ff
data/README.md CHANGED
@@ -171,23 +171,26 @@ client.clear_lifecycle!
171
171
  # Clear System Event Logs
172
172
  client.clear_system_event_logs!
173
173
 
174
- # Working with RecursiveOpenStruct objects
175
- # Many methods return data as RecursiveOpenStruct objects for easier property access
174
+ # Working with hash objects
175
+ # Methods return data as Ruby hashes with string keys for consistent access
176
+
177
+ # Working with system components
178
+ # Methods return data as Ruby hashes with string keys for consistent access
176
179
 
177
180
  # Get memory information
178
181
  memory_modules = client.memory
179
182
  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"
183
+ # Access properties via string keys
184
+ puts "#{dimm["name"]}: #{dimm["capacity_bytes"] / (1024**3)}GB, Speed: #{dimm["speed_mhz"]}MHz"
182
185
  end
183
186
 
184
187
  # Get storage information
185
188
  controller = client.controller
186
189
  volumes = client.volumes(controller)
187
190
  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
+ # Access properties via string keys
192
+ puts "#{volume["name"]} (#{volume["raid_level"]}): #{volume["capacity_bytes"] / (1024**3)}GB"
193
+ puts " Health: #{volume["health"]}, FastPath: #{volume["fastpath"]}"
191
194
  end
192
195
 
193
196
  # Create a client with auto_delete_sessions disabled
data/bin/idrac CHANGED
@@ -581,17 +581,17 @@ module IDRAC
581
581
  puts "-" * 80
582
582
 
583
583
  controllers.each do |controller|
584
- puts "Controller: #{controller[:name]}".cyan.bold
585
- puts " Model: #{controller[:model]}"
586
- puts " Status: #{controller[:status]}"
587
- puts " Drives: #{controller[:drives_count]}"
588
- puts " Firmware: #{controller[:firmware_version]}"
589
- puts " Type: #{controller[:controller_type]}"
590
- puts " PCI Slot: #{controller[:pci_slot]}"
584
+ puts "Controller: #{controller.name}".cyan.bold
585
+ puts " Model: #{controller.model}"
586
+ puts " Status: #{controller.status}"
587
+ puts " Drives: #{controller.drives_count}"
588
+ puts " Firmware: #{controller.firmware_version}"
589
+ puts " Type: #{controller.controller_type}"
590
+ puts " PCI Slot: #{controller.pci_slot}"
591
591
 
592
- if controller[:encryption_capability]
593
- puts " Encryption: #{controller[:encryption_capability]}"
594
- puts " Encryption Mode: #{controller[:encryption_mode] || 'Disabled'}"
592
+ if controller.encryption_capability
593
+ puts " Encryption: #{controller.encryption_capability}"
594
+ puts " Encryption Mode: #{controller.encryption_mode || 'Disabled'}"
595
595
  end
596
596
 
597
597
  puts
@@ -675,7 +675,7 @@ module IDRAC
675
675
  confirmation = $stdin.gets.chomp.downcase
676
676
 
677
677
  if confirmation == 'y'
678
- client.create_virtual_disk(controller.odata_Id, drives, name: options[:name], raid_type: options[:raid])
678
+ client.create_virtual_disk(controller.odata_id, drives, name: options[:name], raid_type: options[:raid])
679
679
  puts "Volume created successfully".green
680
680
  else
681
681
  puts "Operation cancelled".yellow
data/idrac.gemspec CHANGED
@@ -33,22 +33,21 @@ Gem::Specification.new do |spec|
33
33
  spec.executables = ["idrac"]
34
34
  spec.require_paths = ["lib"]
35
35
 
36
- # Dependencies - Only specifying minimum versions
37
- spec.add_dependency "httparty", ">= 0.21.0"
38
- spec.add_dependency "nokogiri", ">= 1.15.0"
39
- spec.add_dependency "faraday", ">= 2.7.0"
40
- spec.add_dependency "faraday-multipart", ">= 1.0.0"
41
- spec.add_dependency "thor", ">= 1.2.0"
42
- spec.add_dependency "base64", ">= 0.1.0"
43
- spec.add_dependency "colorize", ">= 1.1.0"
44
- spec.add_dependency "recursive-open-struct", ">= 1.1.0"
45
- spec.add_dependency "activesupport", ">= 6.0"
36
+ # Dependencies - Using semantic versioning recommendations
37
+ spec.add_dependency "httparty", "~> 0.21", ">= 0.21.0"
38
+ spec.add_dependency "nokogiri", "~> 1.15", ">= 1.15.0"
39
+ spec.add_dependency "faraday", "~> 2.7", ">= 2.7.0"
40
+ spec.add_dependency "faraday-multipart", "~> 1.0", ">= 1.0.0"
41
+ spec.add_dependency "thor", "~> 1.2", ">= 1.2.0"
42
+ spec.add_dependency "base64", "~> 0.1", ">= 0.1.0"
43
+ spec.add_dependency "colorize", "~> 1.1", ">= 1.1.0"
44
+ spec.add_dependency "activesupport", "~> 6.0"
46
45
 
47
46
  # Development dependencies
48
- spec.add_development_dependency "bundler", ">= 2.4.0"
49
- spec.add_development_dependency "rake", ">= 13.0.0"
50
- spec.add_development_dependency "rspec", ">= 3.12.0"
51
- spec.add_development_dependency "debug", ">= 1.8.0"
47
+ spec.add_development_dependency "bundler", "~> 2.4", ">= 2.4.0"
48
+ spec.add_development_dependency "rake", "~> 13.0", ">= 13.0.0"
49
+ spec.add_development_dependency "rspec", "~> 3.12", ">= 3.12.0"
50
+ spec.add_development_dependency "debug", "~> 1.8", ">= 1.8.0"
52
51
 
53
52
  # For more information and examples about making a new gem, check out our
54
53
  # guide at: https://bundler.io/guides/creating_gem.html
data/lib/idrac/jobs.rb CHANGED
@@ -3,21 +3,16 @@ require 'colorize'
3
3
 
4
4
  module IDRAC
5
5
  module Jobs
6
- # Get a list of jobs
6
+ # Summarize jobs
7
7
  def jobs
8
8
  response = authenticated_request(:get, '/redfish/v1/Managers/iDRAC.Embedded.1/Jobs?$expand=*($levels=1)')
9
9
 
10
10
  if response.status == 200
11
11
  begin
12
12
  jobs_data = JSON.parse(response.body)
13
- puts "Jobs: #{jobs_data['Members'].count}"
14
- if jobs_data['Members'].count > 0
15
- puts "Job IDs:"
16
- jobs_data["Members"].each do |job|
17
- puts " #{job['Id']}"
18
- end
19
- end
20
- return jobs_data
13
+ { completed_count: jobs_data["Members"].select { |j| j["JobState"] == "Completed" }.count,
14
+ incomplete_count: jobs_data["Members"].select { |j| j["JobState"] != "Completed" }.count,
15
+ total_count: jobs_data["Members"].count }
21
16
  rescue JSON::ParserError
22
17
  raise Error, "Failed to parse jobs response: #{response.body}"
23
18
  end
data/lib/idrac/license.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module IDRAC
2
2
  module License
3
3
  # Gets the license information from the iDRAC
4
- # @return [RecursiveOpenStruct] License details
4
+ # @return [Hash] License details
5
5
  def license_info
6
6
  response = authenticated_request(:get, "/redfish/v1/LicenseService/Licenses")
7
7
  if response.status != 200
@@ -32,7 +32,7 @@ module IDRAC
32
32
  license_details = JSON.parse(license_response.body)
33
33
  debug "License details: #{license_details}", 2
34
34
 
35
- return RecursiveOpenStruct.new(license_details, recurse_over_arrays: true)
35
+ return license_details
36
36
  end
37
37
 
38
38
  # Extracts the iDRAC version from the license description
@@ -43,15 +43,15 @@ module IDRAC
43
43
 
44
44
  # Check the Description field, which often contains the version
45
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
46
+ if license["Description"]&.match(/iDRAC(\d+)/i)
47
+ version = license["Description"].match(/iDRAC(\d+)/i)[1].to_i
48
48
  debug "Found license version from Description: #{version}", 1
49
49
  return version
50
50
  end
51
51
 
52
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
53
+ if license["Name"]&.match(/iDRAC(\d+)/i)
54
+ version = license["Name"].match(/iDRAC(\d+)/i)[1].to_i
55
55
  debug "Found license version from Name: #{version}", 1
56
56
  return version
57
57
  end
@@ -148,14 +148,21 @@ module IDRAC
148
148
 
149
149
  # Get the system event logs
150
150
  def get_system_event_logs
151
- path = 'Managers/iDRAC.Embedded.1/Logs/Sel?$expand=*($levels=1)'
151
+ path = '/redfish/v1/Managers/iDRAC.Embedded.1/Logs/Sel?$expand=*($levels=1)'
152
152
 
153
153
  response = authenticated_request(:get, path)
154
154
 
155
155
  if response.status == 200
156
156
  begin
157
- logs_data = JSON.parse(response.body)
158
- return logs_data
157
+ data = JSON.parse(response.body)['Members'].map do |entry|
158
+ {
159
+ id: entry['Id'],
160
+ created: entry['Created'],
161
+ message: entry['Message'],
162
+ severity: entry['Severity']
163
+ }
164
+ end
165
+ return data # RecursiveOpenStruct.new(data, recurse_over_arrays: true)
159
166
  rescue JSON::ParserError
160
167
  raise Error, "Failed to parse system event logs response: #{response.body}"
161
168
  end
@@ -166,7 +173,7 @@ module IDRAC
166
173
 
167
174
  # Clear the system event logs
168
175
  def clear_system_event_logs!
169
- path = 'Managers/iDRAC.Embedded.1/LogServices/Sel/Actions/LogService.ClearLog'
176
+ path = '/redfish/v1/Managers/iDRAC.Embedded.1/LogServices/Sel/Actions/LogService.ClearLog'
170
177
 
171
178
  response = authenticated_request(:post, path, body: {}.to_json, headers: { 'Content-Type' => 'application/json' })
172
179
 
data/lib/idrac/storage.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'json'
2
2
  require 'colorize'
3
- require 'recursive-open-struct'
4
3
 
5
4
  module IDRAC
6
5
  module Storage
@@ -10,24 +9,24 @@ module IDRAC
10
9
  controller_list = controllers
11
10
 
12
11
  puts "Controllers".green
13
- controller_list.each { |c| puts "#{c.name} > #{c.drives_count}" }
12
+ controller_list.each { |c| puts "#{c["name"]} > #{c["drives_count"]}" }
14
13
 
15
14
  puts "Drives".green
16
15
  controller_list.each do |c|
17
- puts "Storage: #{c.name} > #{c.status} > #{c.drives_count}"
16
+ puts "Storage: #{c["name"]} > #{c["status"]} > #{c["drives_count"]}"
18
17
  end
19
18
 
20
19
  # Find the controller with the most drives (usually the PERC)
21
- controller_info = controller_list.max_by { |c| c.drives_count }
20
+ controller_info = controller_list.max_by { |c| c["drives_count"] }
22
21
 
23
- if controller_info.name =~ /PERC/
24
- puts "Found #{controller_info.name}".green
22
+ if controller_info["name"] =~ /PERC/
23
+ puts "Found #{controller_info["name"]}".green
25
24
  else
26
- puts "Found #{controller_info.name} but continuing...".yellow
25
+ puts "Found #{controller_info["name"]} but continuing...".yellow
27
26
  end
28
27
 
29
28
  # Return the raw controller data
30
- controller_info.raw
29
+ controller_info["raw"]
31
30
  end
32
31
 
33
32
  # Get all storage controllers and return them as an array
@@ -38,26 +37,25 @@ module IDRAC
38
37
  begin
39
38
  data = JSON.parse(response.body)
40
39
 
41
- # Transform and return all controllers as an array of RecursiveOpenStruct objects with consistent keys
40
+ # Transform and return all controllers as an array of hashes with string keys
42
41
  controllers = data["Members"].map do |controller|
43
- controller_data = {
44
- name: controller["Name"],
45
- model: controller["Model"],
46
- drives_count: controller["Drives"].size,
47
- status: controller["Status"]["Health"] || "N/A",
48
- firmware_version: controller.dig("StorageControllers", 0, "FirmwareVersion"),
49
- encryption_mode: controller.dig("Oem", "Dell", "DellController", "EncryptionMode"),
50
- encryption_capability: controller.dig("Oem", "Dell", "DellController", "EncryptionCapability"),
51
- controller_type: controller.dig("Oem", "Dell", "DellController", "ControllerType"),
52
- pci_slot: controller.dig("Oem", "Dell", "DellController", "PCISlot"),
53
- raw: controller,
54
- odata_id: controller["@odata.id"]
42
+ {
43
+ "name" => controller["Name"],
44
+ "model" => controller["Model"],
45
+ "drives_count" => controller["Drives"].size,
46
+ "status" => controller.dig("Status", "Health") || "N/A",
47
+ "firmware_version" => controller.dig("StorageControllers", 0, "FirmwareVersion"),
48
+ "encryption_mode" => controller.dig("Oem", "Dell", "DellController", "EncryptionMode"),
49
+ "encryption_capability" => controller.dig("Oem", "Dell", "DellController", "EncryptionCapability"),
50
+ "controller_type" => controller.dig("Oem", "Dell", "DellController", "ControllerType"),
51
+ "pci_slot" => controller.dig("Oem", "Dell", "DellController", "PCISlot"),
52
+ "raw" => controller,
53
+ "volumes_odata_id" => controller.dig("Volumes", "@odata.id"),
54
+ "@odata.id" => controller["@odata.id"]
55
55
  }
56
-
57
- RecursiveOpenStruct.new(controller_data, recurse_over_arrays: true)
58
56
  end
59
57
 
60
- return controllers.sort_by { |c| c.name }
58
+ return controllers.sort_by { |c| c["name"] }
61
59
  rescue JSON::ParserError
62
60
  raise Error, "Failed to parse controllers response: #{response.body}"
63
61
  end
@@ -66,23 +64,12 @@ module IDRAC
66
64
  end
67
65
  end
68
66
 
69
- # Check if controller supports encryption
70
- def controller_encryption_capable?(controller)
71
- return false unless controller
72
- controller.dig("Oem", "Dell", "DellController", "EncryptionCapability") =~ /localkey/i
73
- end
74
-
75
- # Check if controller encryption is enabled
76
- def controller_encryption_enabled?(controller)
77
- return false unless controller
78
- controller.dig("Oem", "Dell", "DellController", "EncryptionMode") =~ /localkey/i
79
- end
80
-
81
67
  # Get information about physical drives
82
68
  def drives(controller)
83
69
  raise Error, "Controller not provided" unless controller
84
70
 
85
- controller_path = controller["@odata.id"].split("v1/").last
71
+ odata_id_path = controller["@odata.id"] || controller["odata_id"]
72
+ controller_path = odata_id_path.split("v1/").last
86
73
  response = authenticated_request(:get, "/redfish/v1/#{controller_path}?$expand=*($levels=1)")
87
74
 
88
75
  if response.status == 200
@@ -91,29 +78,27 @@ module IDRAC
91
78
  drives = data["Drives"].map do |body|
92
79
  serial = body["SerialNumber"]
93
80
  serial = body["Identifiers"].first["DurableName"] if serial.blank?
94
- drive_data = {
95
- serial: serial,
96
- model: body["Model"],
97
- name: body["Name"],
98
- capacity_bytes: body["CapacityBytes"],
99
- health: body["Status"]["Health"] ? body["Status"]["Health"] : "N/A",
100
- speed_gbp: body["CapableSpeedGbs"],
101
- manufacturer: body["Manufacturer"],
102
- media_type: body["MediaType"],
103
- failure_predicted: body["FailurePredicted"],
104
- life_left_percent: body["PredictedMediaLifeLeftPercent"],
105
- certified: body.dig("Oem", "Dell", "DellPhysicalDisk", "Certified"),
106
- raid_status: body.dig("Oem", "Dell", "DellPhysicalDisk", "RaidStatus"),
107
- operation_name: body.dig("Oem", "Dell", "DellPhysicalDisk", "OperationName"),
108
- operation_progress: body.dig("Oem", "Dell", "DellPhysicalDisk", "OperationPercentCompletePercent"),
109
- encryption_ability: body["EncryptionAbility"],
110
- "@odata.id": body["@odata.id"]
81
+ {
82
+ "serial" => serial,
83
+ "model" => body["Model"],
84
+ "name" => body["Name"],
85
+ "capacity_bytes" => body["CapacityBytes"],
86
+ "health" => body.dig("Status", "Health") || "N/A",
87
+ "speed_gbp" => body["CapableSpeedGbs"],
88
+ "manufacturer" => body["Manufacturer"],
89
+ "media_type" => body["MediaType"],
90
+ "failure_predicted" => body["FailurePredicted"],
91
+ "life_left_percent" => body["PredictedMediaLifeLeftPercent"],
92
+ "certified" => body.dig("Oem", "Dell", "DellPhysicalDisk", "Certified"),
93
+ "raid_status" => body.dig("Oem", "Dell", "DellPhysicalDisk", "RaidStatus"),
94
+ "operation_name" => body.dig("Oem", "Dell", "DellPhysicalDisk", "OperationName"),
95
+ "operation_progress" => body.dig("Oem", "Dell", "DellPhysicalDisk", "OperationPercentCompletePercent"),
96
+ "encryption_ability" => body["EncryptionAbility"],
97
+ "@odata.id" => body["@odata.id"]
111
98
  }
112
-
113
- RecursiveOpenStruct.new(drive_data, recurse_over_arrays: true)
114
99
  end
115
100
 
116
- return drives.sort_by { |d| d.name }
101
+ return drives.sort_by { |d| d["name"] }
117
102
  rescue JSON::ParserError
118
103
  raise Error, "Failed to parse drives response: #{response.body}"
119
104
  end
@@ -128,9 +113,11 @@ module IDRAC
128
113
 
129
114
  puts "Volumes (e.g. Arrays)".green
130
115
 
131
- v = controller["Volumes"]
132
- path = v["@odata.id"].split("v1/").last
133
- response = authenticated_request(:get, "/redfish/v1/#{path}?$expand=*($levels=1)")
116
+ odata_id_path = controller["volumes_odata_id"]
117
+ if odata_id_path.nil?
118
+ raise Error, "No volumes_odata_id found in controller data. Make sure the controller is properly initialized."
119
+ end
120
+ response = authenticated_request(:get, "#{odata_id_path}?$expand=*($levels=1)")
134
121
 
135
122
  if response.status == 200
136
123
  begin
@@ -138,42 +125,42 @@ module IDRAC
138
125
  volumes = data["Members"].map do |vol|
139
126
  drives = vol["Links"]["Drives"]
140
127
  volume_data = {
141
- name: vol["Name"],
142
- capacity_bytes: vol["CapacityBytes"],
143
- volume_type: vol["VolumeType"],
144
- drives: drives,
145
- write_cache_policy: vol.dig("Oem", "Dell", "DellVirtualDisk", "WriteCachePolicy"),
146
- read_cache_policy: vol.dig("Oem", "Dell", "DellVirtualDisk", "ReadCachePolicy"),
147
- stripe_size: vol.dig("Oem", "Dell", "DellVirtualDisk", "StripeSize"),
148
- raid_level: vol["RAIDType"],
149
- encrypted: vol["Encrypted"],
150
- lock_status: vol.dig("Oem", "Dell", "DellVirtualDisk", "LockStatus"),
151
- odata_id: vol["@odata.id"]
128
+ "name" => vol["Name"],
129
+ "capacity_bytes" => vol["CapacityBytes"],
130
+ "volume_type" => vol["VolumeType"],
131
+ "drives" => drives,
132
+ "write_cache_policy" => vol.dig("Oem", "Dell", "DellVirtualDisk", "WriteCachePolicy"),
133
+ "read_cache_policy" => vol.dig("Oem", "Dell", "DellVirtualDisk", "ReadCachePolicy"),
134
+ "stripe_size" => vol.dig("Oem", "Dell", "DellVirtualDisk", "StripeSize"),
135
+ "raid_level" => vol["RAIDType"],
136
+ "encrypted" => vol["Encrypted"],
137
+ "lock_status" => vol.dig("Oem", "Dell", "DellVirtualDisk", "LockStatus"),
138
+ "@odata.id" => vol["@odata.id"]
152
139
  }
153
140
 
154
141
  # Check FastPath settings
155
- volume_data[:fastpath] = fastpath_good?(vol)
142
+ volume_data["fastpath"] = fastpath_good?(volume_data)
156
143
 
157
144
  # Handle volume operations and status
158
145
  if vol["Operations"].any?
159
- volume_data[:health] = vol["Status"]["Health"] ? vol["Status"]["Health"] : "N/A"
160
- volume_data[:progress] = vol["Operations"].first["PercentageComplete"]
161
- volume_data[:message] = vol["Operations"].first["OperationName"]
162
- elsif vol["Status"]["Health"] == "OK"
163
- volume_data[:health] = "OK"
164
- volume_data[:progress] = nil
165
- volume_data[:message] = nil
146
+ volume_data["health"] = vol.dig("Status", "Health") || "N/A"
147
+ volume_data["progress"] = vol["Operations"].first["PercentageComplete"]
148
+ volume_data["message"] = vol["Operations"].first["OperationName"]
149
+ elsif vol.dig("Status", "Health") == "OK"
150
+ volume_data["health"] = "OK"
151
+ volume_data["progress"] = nil
152
+ volume_data["message"] = nil
166
153
  else
167
- volume_data[:health] = "?"
168
- volume_data[:progress] = nil
169
- volume_data[:message] = nil
154
+ volume_data["health"] = "?"
155
+ volume_data["progress"] = nil
156
+ volume_data["message"] = nil
170
157
  end
171
158
 
172
- # Create the RecursiveOpenStruct after all properties are set
173
- RecursiveOpenStruct.new(volume_data, recurse_over_arrays: true)
159
+ # Return the hash directly
160
+ volume_data
174
161
  end
175
162
 
176
- return volumes.sort_by { |d| d.name }
163
+ return volumes.sort_by { |d| d["name"] }
177
164
  rescue JSON::ParserError
178
165
  raise Error, "Failed to parse volumes response: #{response.body}"
179
166
  end
@@ -187,9 +174,9 @@ module IDRAC
187
174
  return "disabled" unless volume
188
175
 
189
176
  # Modern firmware check handled by caller
190
- if volume[:write_cache_policy] == "WriteThrough" &&
191
- volume[:read_cache_policy] == "NoReadAhead" &&
192
- volume[:stripe_size] == "64KB"
177
+ if volume["write_cache_policy"] == "WriteThrough" &&
178
+ volume["read_cache_policy"] == "NoReadAhead" &&
179
+ volume["stripe_size"] == "64KB"
193
180
  return "enabled"
194
181
  else
195
182
  return "disabled"
@@ -367,7 +354,7 @@ module IDRAC
367
354
 
368
355
  # Check if all physical disks are Self-Encrypting Drives
369
356
  def all_seds?(drives)
370
- drives.all? { |d| d.encryption_ability == "SelfEncryptingDrive" }
357
+ drives.all? { |d| d["encryption_ability"] == "SelfEncryptingDrive" }
371
358
  end
372
359
 
373
360
  # Check if the system is ready for SED operations
@@ -402,5 +389,15 @@ module IDRAC
402
389
  end
403
390
  end
404
391
  end
392
+
393
+ # Check if the controller is capable of encryption
394
+ def controller_encryption_capable?(controller)
395
+ controller.dig("encryption_capability") =~ /localkey/i
396
+ end
397
+
398
+ # Check if controller encryption is enabled
399
+ def controller_encryption_enabled?(controller)
400
+ controller.dig("encryption_mode") =~ /localkey/i
401
+ end
405
402
  end
406
- end
403
+ end
data/lib/idrac/system.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'json'
2
2
  require 'colorize'
3
- require 'recursive-open-struct'
4
3
 
5
4
  module IDRAC
6
5
  module System
@@ -11,28 +10,25 @@ module IDRAC
11
10
  if response.status == 200
12
11
  begin
13
12
  data = JSON.parse(response.body)
13
+
14
14
  memory = data["Members"].map do |m|
15
15
  dimm_name = m["Name"] # e.g. DIMM A1
16
- bank, index = /DIMM ([A-Z])(\d+)/.match(dimm_name).captures rescue [nil, nil]
17
-
18
- puts "DIMM: #{m["Model"]} #{m["Name"]} > #{m["CapacityMiB"]}MiB > #{m["Status"]["Health"]} > #{m["OperatingSpeedMhz"]}MHz > #{m["PartNumber"]} / #{m["SerialNumber"]}"
16
+ bank, index = /DIMM ([A-Z])(\d+)/.match(dimm_name).captures
19
17
 
20
- memory_data = {
21
- model: m["Model"],
22
- name: m["Name"],
23
- capacity_bytes: m["CapacityMiB"].to_i.megabyte,
24
- health: m["Status"]["Health"] ? m["Status"]["Health"] : "N/A",
25
- speed_mhz: m["OperatingSpeedMhz"],
26
- part_number: m["PartNumber"],
27
- serial: m["SerialNumber"],
28
- bank: bank,
29
- index: index.to_i
18
+ {
19
+ "model" => m["Model"],
20
+ "name" => m["Name"],
21
+ "capacity_bytes" => m["CapacityMiB"].to_i * 1024 * 1024,
22
+ "health" => m.dig("Status","Health") || "N/A",
23
+ "speed_mhz" => m["OperatingSpeedMhz"],
24
+ "part_number" => m["PartNumber"],
25
+ "serial" => m["SerialNumber"],
26
+ "bank" => bank,
27
+ "index" => index.to_i
30
28
  }
31
-
32
- RecursiveOpenStruct.new(memory_data, recurse_over_arrays: true)
33
29
  end
34
30
 
35
- return memory.sort_by { |m| [m.bank || "Z", m.index || 999] }
31
+ return memory.sort_by { |m| [m["bank"] || "Z", m["index"] || 999] }
36
32
  rescue JSON::ParserError
37
33
  raise Error, "Failed to parse memory response: #{response.body}"
38
34
  end
@@ -51,19 +47,17 @@ module IDRAC
51
47
  puts "Power Supplies".green
52
48
 
53
49
  psus = data["PowerSupplies"].map do |psu|
54
- puts "PSU: #{psu["Name"]} > #{psu["PowerInputWatts"]}W > #{psu["Status"]["Health"]}"
55
- psu_data = {
56
- name: psu["Name"],
57
- voltage: psu["LineInputVoltage"],
58
- voltage_human: psu["LineInputVoltageType"], # AC240V
59
- watts: psu["PowerInputWatts"],
60
- part: psu["PartNumber"],
61
- model: psu["Model"],
62
- serial: psu["SerialNumber"],
63
- status: psu["Status"]["Health"],
50
+ puts "PSU: #{psu["Name"]} > #{psu["PowerInputWatts"]}W > #{psu.dig("Status", "Health")}"
51
+ {
52
+ "name" => psu["Name"],
53
+ "voltage" => psu["LineInputVoltage"],
54
+ "voltage_human" => psu["LineInputVoltageType"], # AC240V
55
+ "watts" => psu["PowerInputWatts"],
56
+ "part" => psu["PartNumber"],
57
+ "model" => psu["Model"],
58
+ "serial" => psu["SerialNumber"],
59
+ "status" => psu.dig("Status", "Health")
64
60
  }
65
-
66
- RecursiveOpenStruct.new(psu_data, recurse_over_arrays: true)
67
61
  end
68
62
 
69
63
  return psus
@@ -88,15 +82,13 @@ module IDRAC
88
82
  data = JSON.parse(response.body)
89
83
 
90
84
  fans = data["Fans"].map do |fan|
91
- puts "Fan: #{fan["Name"]} > #{fan["Reading"]} > #{fan["Status"]["Health"]}"
92
- fan_data = {
93
- name: fan["Name"],
94
- rpm: fan["Reading"],
95
- serial: fan["SerialNumber"],
96
- status: fan["Status"]["Health"]
85
+ puts "Fan: #{fan["Name"]} > #{fan["Reading"]} > #{fan.dig("Status", "Health")}"
86
+ {
87
+ "name" => fan["Name"],
88
+ "rpm" => fan["Reading"],
89
+ "serial" => fan["SerialNumber"],
90
+ "status" => fan.dig("Status", "Health")
97
91
  }
98
-
99
- RecursiveOpenStruct.new(fan_data, recurse_over_arrays: true)
100
92
  end
101
93
 
102
94
  return fans
@@ -222,7 +214,7 @@ module IDRAC
222
214
 
223
215
  idrac = {
224
216
  "name" => data["Id"],
225
- "status" => data["Status"]["Health"] == 'OK' ? 'Up' : 'Down',
217
+ "status" => data.dig("Status", "Health") == 'OK' ? 'Up' : 'Down',
226
218
  "mac" => data["MACAddress"],
227
219
  "mask" => data["IPv4Addresses"].first["SubnetMask"],
228
220
  "ipv4" => data["IPv4Addresses"].first["Address"],
@@ -293,15 +285,15 @@ module IDRAC
293
285
  def nics_to_pci(nics, pci_devices)
294
286
  # Filter for Mellanox network controllers
295
287
  mellanox_pci = pci_devices.select do |dev|
296
- dev[:device_class] =~ /NetworkController/ && dev[:manufacturer] =~ /Mellanox/
288
+ dev['device_class'] =~ /NetworkController/ && dev['manufacturer'] =~ /Mellanox/
297
289
  end
298
290
 
299
291
  # Create mapping of NIC names to PCI IDs
300
292
  mapping = {}
301
293
  mellanox_pci.each do |dev|
302
- if dev[:nic] && dev[:nic] =~ /.*\/([^\/\-]+-\d+)/
294
+ if dev['nic'] && dev['nic'] =~ /.*\/([^\/\-]+-\d+)/
303
295
  nic = $1 # e.g. NIC.Slot.1-1
304
- if dev[:id] =~ /^(\d+)-\d+-\d/
296
+ if dev['id'] =~ /^(\d+)-\d+-\d/
305
297
  pci_bus = $1 # e.g. 59
306
298
  mapping[nic] = pci_bus
307
299
  end
@@ -332,6 +324,22 @@ module IDRAC
332
324
  return nics_with_pci
333
325
  end
334
326
 
327
+ # Kind of like a NIC, but serves a different purpose.
328
+ def idrac_interface
329
+ response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/EthernetInterfaces/iDRAC.Embedded.1%23NIC.1")
330
+ idrac_data = JSON.parse(response.body)
331
+ {
332
+ "name" => idrac_data["Id"],
333
+ "status" => idrac_data.dig("Status", "Health") == 'OK' ? 'Up' : 'Down',
334
+ "mac" => idrac_data["MACAddress"],
335
+ "mask" => idrac_data["IPv4Addresses"].first["SubnetMask"],
336
+ "ipv4" => idrac_data["IPv4Addresses"].first["Address"],
337
+ "origin" => idrac_data["IPv4Addresses"].first["AddressOrigin"], # DHCP or Static
338
+ "port" => nil,
339
+ "speed_mbps" => idrac_data["SpeedMbps"],
340
+ "kind" => "ethernet"
341
+ }
342
+ end
335
343
  # Get system identification information
336
344
  def system_info
337
345
  response = authenticated_request(:get, "/redfish/v1")
@@ -342,42 +350,42 @@ module IDRAC
342
350
 
343
351
  # Initialize return hash with defaults
344
352
  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
353
+ "is_dell" => false,
354
+ "is_ancient_dell" => false,
355
+ "product" => data["Product"] || "Unknown",
356
+ "service_tag" => nil,
357
+ "model" => nil,
358
+ "idrac_version" => data["RedfishVersion"],
359
+ "firmware_version" => nil
352
360
  }
353
361
 
354
362
  # Check if it's a Dell iDRAC
355
363
  if data["Product"] == "Integrated Dell Remote Access Controller"
356
- info[:is_dell] = true
364
+ info["is_dell"] = true
357
365
 
358
366
  # Get service tag from Dell OEM data
359
- info[:service_tag] = data.dig("Oem", "Dell", "ServiceTag")
367
+ info["service_tag"] = data.dig("Oem", "Dell", "ServiceTag")
360
368
 
361
369
  # Get firmware version - try both common locations
362
- info[:firmware_version] = data["FirmwareVersion"] || data.dig("Oem", "Dell", "FirmwareVersion")
370
+ info["firmware_version"] = data["FirmwareVersion"] || data.dig("Oem", "Dell", "FirmwareVersion")
363
371
 
364
372
  # Get additional system information
365
373
  system_response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1")
366
374
  if system_response.status == 200
367
375
  system_data = JSON.parse(system_response.body)
368
- info[:model] = system_data["Model"]
376
+ info["model"] = system_data["Model"]
369
377
  end
370
378
 
371
- return RecursiveOpenStruct.new(info, recurse_over_arrays: true)
379
+ return info
372
380
  else
373
381
  # Try to handle ancient Dell models where Product is null or non-standard
374
382
  if data["Product"].nil? || data.dig("Oem", "Dell")
375
- info[:is_ancient_dell] = true
376
- return RecursiveOpenStruct.new(info, recurse_over_arrays: true)
383
+ info["is_ancient_dell"] = true
384
+ return info
377
385
  end
378
386
  end
379
387
 
380
- return RecursiveOpenStruct.new(info, recurse_over_arrays: true)
388
+ return info
381
389
  rescue JSON::ParserError
382
390
  raise Error, "Failed to parse system information: #{response.body}"
383
391
  end
@@ -395,14 +403,14 @@ module IDRAC
395
403
  data = JSON.parse(response.body)
396
404
 
397
405
  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")
406
+ "count" => data.dig("ProcessorSummary", "Count"),
407
+ "model" => data.dig("ProcessorSummary", "Model"),
408
+ "cores" => data.dig("ProcessorSummary", "CoreCount"),
409
+ "threads" => data.dig("ProcessorSummary", "LogicalProcessorCount"),
410
+ "status" => data.dig("ProcessorSummary", "Status", "Health")
403
411
  }
404
412
 
405
- return RecursiveOpenStruct.new(summary, recurse_over_arrays: true)
413
+ return summary
406
414
  rescue JSON::ParserError
407
415
  raise Error, "Failed to parse processor information: #{response.body}"
408
416
  end
@@ -420,14 +428,14 @@ module IDRAC
420
428
  data = JSON.parse(response.body)
421
429
 
422
430
  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")
431
+ "overall" => data.dig("Status", "HealthRollup"),
432
+ "system" => data.dig("Status", "Health"),
433
+ "processor" => data.dig("ProcessorSummary", "Status", "Health"),
434
+ "memory" => data.dig("MemorySummary", "Status", "Health"),
435
+ "storage" => data.dig("Storage", "Status", "Health")
428
436
  }
429
437
 
430
- return RecursiveOpenStruct.new(health, recurse_over_arrays: true)
438
+ return health
431
439
  rescue JSON::ParserError
432
440
  raise Error, "Failed to parse system health information: #{response.body}"
433
441
  end
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.5.9"
4
+ VERSION = "0.6.0"
5
5
  end
data/lib/idrac.rb CHANGED
@@ -7,7 +7,6 @@ require 'faraday/multipart'
7
7
  require 'base64'
8
8
  require 'uri'
9
9
  require 'colorize'
10
- require 'recursive-open-struct'
11
10
  require 'active_support'
12
11
  require 'active_support/core_ext'
13
12
  # If dev, required debug
metadata CHANGED
@@ -1,18 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: idrac
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.9
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Siegel
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2025-04-24 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: httparty
14
15
  requirement: !ruby/object:Gem::Requirement
15
16
  requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.21'
16
20
  - - ">="
17
21
  - !ruby/object:Gem::Version
18
22
  version: 0.21.0
@@ -20,6 +24,9 @@ dependencies:
20
24
  prerelease: false
21
25
  version_requirements: !ruby/object:Gem::Requirement
22
26
  requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.21'
23
30
  - - ">="
24
31
  - !ruby/object:Gem::Version
25
32
  version: 0.21.0
@@ -27,6 +34,9 @@ dependencies:
27
34
  name: nokogiri
28
35
  requirement: !ruby/object:Gem::Requirement
29
36
  requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.15'
30
40
  - - ">="
31
41
  - !ruby/object:Gem::Version
32
42
  version: 1.15.0
@@ -34,6 +44,9 @@ dependencies:
34
44
  prerelease: false
35
45
  version_requirements: !ruby/object:Gem::Requirement
36
46
  requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.15'
37
50
  - - ">="
38
51
  - !ruby/object:Gem::Version
39
52
  version: 1.15.0
@@ -41,6 +54,9 @@ dependencies:
41
54
  name: faraday
42
55
  requirement: !ruby/object:Gem::Requirement
43
56
  requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '2.7'
44
60
  - - ">="
45
61
  - !ruby/object:Gem::Version
46
62
  version: 2.7.0
@@ -48,6 +64,9 @@ dependencies:
48
64
  prerelease: false
49
65
  version_requirements: !ruby/object:Gem::Requirement
50
66
  requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '2.7'
51
70
  - - ">="
52
71
  - !ruby/object:Gem::Version
53
72
  version: 2.7.0
@@ -55,6 +74,9 @@ dependencies:
55
74
  name: faraday-multipart
56
75
  requirement: !ruby/object:Gem::Requirement
57
76
  requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '1.0'
58
80
  - - ">="
59
81
  - !ruby/object:Gem::Version
60
82
  version: 1.0.0
@@ -62,6 +84,9 @@ dependencies:
62
84
  prerelease: false
63
85
  version_requirements: !ruby/object:Gem::Requirement
64
86
  requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
65
90
  - - ">="
66
91
  - !ruby/object:Gem::Version
67
92
  version: 1.0.0
@@ -69,6 +94,9 @@ dependencies:
69
94
  name: thor
70
95
  requirement: !ruby/object:Gem::Requirement
71
96
  requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '1.2'
72
100
  - - ">="
73
101
  - !ruby/object:Gem::Version
74
102
  version: 1.2.0
@@ -76,6 +104,9 @@ dependencies:
76
104
  prerelease: false
77
105
  version_requirements: !ruby/object:Gem::Requirement
78
106
  requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.2'
79
110
  - - ">="
80
111
  - !ruby/object:Gem::Version
81
112
  version: 1.2.0
@@ -83,6 +114,9 @@ dependencies:
83
114
  name: base64
84
115
  requirement: !ruby/object:Gem::Requirement
85
116
  requirements:
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '0.1'
86
120
  - - ">="
87
121
  - !ruby/object:Gem::Version
88
122
  version: 0.1.0
@@ -90,6 +124,9 @@ dependencies:
90
124
  prerelease: false
91
125
  version_requirements: !ruby/object:Gem::Requirement
92
126
  requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '0.1'
93
130
  - - ">="
94
131
  - !ruby/object:Gem::Version
95
132
  version: 0.1.0
@@ -97,20 +134,9 @@ dependencies:
97
134
  name: colorize
98
135
  requirement: !ruby/object:Gem::Requirement
99
136
  requirements:
100
- - - ">="
137
+ - - "~>"
101
138
  - !ruby/object:Gem::Version
102
- version: 1.1.0
103
- type: :runtime
104
- prerelease: false
105
- version_requirements: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- version: 1.1.0
110
- - !ruby/object:Gem::Dependency
111
- name: recursive-open-struct
112
- requirement: !ruby/object:Gem::Requirement
113
- requirements:
139
+ version: '1.1'
114
140
  - - ">="
115
141
  - !ruby/object:Gem::Version
116
142
  version: 1.1.0
@@ -118,6 +144,9 @@ dependencies:
118
144
  prerelease: false
119
145
  version_requirements: !ruby/object:Gem::Requirement
120
146
  requirements:
147
+ - - "~>"
148
+ - !ruby/object:Gem::Version
149
+ version: '1.1'
121
150
  - - ">="
122
151
  - !ruby/object:Gem::Version
123
152
  version: 1.1.0
@@ -125,20 +154,23 @@ dependencies:
125
154
  name: activesupport
126
155
  requirement: !ruby/object:Gem::Requirement
127
156
  requirements:
128
- - - ">="
157
+ - - "~>"
129
158
  - !ruby/object:Gem::Version
130
159
  version: '6.0'
131
160
  type: :runtime
132
161
  prerelease: false
133
162
  version_requirements: !ruby/object:Gem::Requirement
134
163
  requirements:
135
- - - ">="
164
+ - - "~>"
136
165
  - !ruby/object:Gem::Version
137
166
  version: '6.0'
138
167
  - !ruby/object:Gem::Dependency
139
168
  name: bundler
140
169
  requirement: !ruby/object:Gem::Requirement
141
170
  requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.4'
142
174
  - - ">="
143
175
  - !ruby/object:Gem::Version
144
176
  version: 2.4.0
@@ -146,6 +178,9 @@ dependencies:
146
178
  prerelease: false
147
179
  version_requirements: !ruby/object:Gem::Requirement
148
180
  requirements:
181
+ - - "~>"
182
+ - !ruby/object:Gem::Version
183
+ version: '2.4'
149
184
  - - ">="
150
185
  - !ruby/object:Gem::Version
151
186
  version: 2.4.0
@@ -153,6 +188,9 @@ dependencies:
153
188
  name: rake
154
189
  requirement: !ruby/object:Gem::Requirement
155
190
  requirements:
191
+ - - "~>"
192
+ - !ruby/object:Gem::Version
193
+ version: '13.0'
156
194
  - - ">="
157
195
  - !ruby/object:Gem::Version
158
196
  version: 13.0.0
@@ -160,6 +198,9 @@ dependencies:
160
198
  prerelease: false
161
199
  version_requirements: !ruby/object:Gem::Requirement
162
200
  requirements:
201
+ - - "~>"
202
+ - !ruby/object:Gem::Version
203
+ version: '13.0'
163
204
  - - ">="
164
205
  - !ruby/object:Gem::Version
165
206
  version: 13.0.0
@@ -167,6 +208,9 @@ dependencies:
167
208
  name: rspec
168
209
  requirement: !ruby/object:Gem::Requirement
169
210
  requirements:
211
+ - - "~>"
212
+ - !ruby/object:Gem::Version
213
+ version: '3.12'
170
214
  - - ">="
171
215
  - !ruby/object:Gem::Version
172
216
  version: 3.12.0
@@ -174,6 +218,9 @@ dependencies:
174
218
  prerelease: false
175
219
  version_requirements: !ruby/object:Gem::Requirement
176
220
  requirements:
221
+ - - "~>"
222
+ - !ruby/object:Gem::Version
223
+ version: '3.12'
177
224
  - - ">="
178
225
  - !ruby/object:Gem::Version
179
226
  version: 3.12.0
@@ -181,6 +228,9 @@ dependencies:
181
228
  name: debug
182
229
  requirement: !ruby/object:Gem::Requirement
183
230
  requirements:
231
+ - - "~>"
232
+ - !ruby/object:Gem::Version
233
+ version: '1.8'
184
234
  - - ">="
185
235
  - !ruby/object:Gem::Version
186
236
  version: 1.8.0
@@ -188,6 +238,9 @@ dependencies:
188
238
  prerelease: false
189
239
  version_requirements: !ruby/object:Gem::Requirement
190
240
  requirements:
241
+ - - "~>"
242
+ - !ruby/object:Gem::Version
243
+ version: '1.8'
191
244
  - - ">="
192
245
  - !ruby/object:Gem::Version
193
246
  version: 1.8.0
@@ -225,6 +278,7 @@ licenses:
225
278
  - MIT
226
279
  metadata:
227
280
  homepage_uri: http://github.com
281
+ post_install_message:
228
282
  rdoc_options: []
229
283
  require_paths:
230
284
  - lib
@@ -239,7 +293,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
239
293
  - !ruby/object:Gem::Version
240
294
  version: '0'
241
295
  requirements: []
242
- rubygems_version: 3.6.7
296
+ rubygems_version: 3.5.16
297
+ signing_key:
243
298
  specification_version: 4
244
299
  summary: API Client for Dell iDRAC
245
300
  test_files: []