idrac 0.1.23 → 0.1.26

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: 19bd4d4dbb2b3c79b0b35e70067284d0b6c38dd548f37eabe2b1102b11dd8782
4
- data.tar.gz: 0555e28ccfedbbdfe5e100c23700ae2dc8cab849b806baf739de7a1d6fbd6d66
3
+ metadata.gz: 4d751ffb6e590b80a6a5dc72457d8a4be11213224a13ebeae50698ae9f6cafff
4
+ data.tar.gz: 5a3f826850bf9aee8e40287ff7f8ab7c5bd71944ddce2b183dbe88dabed9c3fa
5
5
  SHA512:
6
- metadata.gz: dec9acadc7a50d101322f111b4522aa886547c92e8c8d089a7811527e4be43227c7116c62b9c2b199424427ecb95ea75604160f5d728142fe14d5c78302668f0
7
- data.tar.gz: 82b726d07aa328830a9a58292542712b0075b2865de7df56a1a2f161094a50762aed2b2f3aab80e835474f729a2ebbc131b452467607cbcb2bbcb70345baf61b
6
+ metadata.gz: 553bef804c000680be8ecadb15c19f2b4a335db5a7a44b5071ccb230f168880268e906f5a296a70c8659a5bbbb14a0ffb3a6f56cfc4c9ca216e0a1f8a6024a0f
7
+ data.tar.gz: ff4d0ce0967de6fbddd425844e0c86165276c44d508a2b8de41a20ec54e3998f7d2f1d5aa7cadf34201dd26113bd0abafb1e01d13439edbcb1d22f273e31a1f5
data/README.md CHANGED
@@ -127,6 +127,28 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
127
127
 
128
128
  ## Changelog
129
129
 
130
+ ### Version 0.1.26
131
+ - **Improved Redfish Session Creation**: Fixed issues with the Redfish session creation process
132
+ - Added multiple fallback methods for creating sessions with different iDRAC versions
133
+ - Fixed 415 Unsupported Media Type error by trying different content types
134
+ - Added support for form-urlencoded requests when JSON requests fail
135
+ - Enhanced error handling and logging during session creation
136
+
137
+ ### Version 0.1.25
138
+ - **Enhanced Component Matching**: Improved firmware component matching with catalog entries
139
+ - Added extraction of model numbers and identifiers from component names (X520, H730, etc.)
140
+ - Implemented multiple matching strategies for better accuracy
141
+ - Added special handling for different component types (NIC, PERC, BIOS, iDRAC, etc.)
142
+ - Improved matching for components with different naming conventions
143
+
144
+ ### Version 0.1.24
145
+ - **Improved Firmware Update Check**: Fixed issues with firmware version comparison
146
+ - Eliminated duplicate entries in firmware update results
147
+ - Improved matching logic between installed firmware and catalog entries
148
+ - Added proper handling of BIOS updates
149
+ - Fixed missing version information in update output
150
+ - Enhanced name comparison with case-insensitive matching
151
+
130
152
  ### Version 0.1.23
131
153
  - **Fixed Duplicate Messages**: Removed duplicate "Retrieving system inventory..." message in firmware:status command
132
154
  - The message was appearing twice because it was being printed by both the CLI class and the Firmware class
data/lib/idrac/client.rb CHANGED
@@ -130,67 +130,120 @@ module IDRAC
130
130
  url = '/redfish/v1/SessionService/Sessions'
131
131
  payload = { "UserName" => username, "Password" => password }
132
132
 
133
- # Use Basic Auth for the initial session creation
134
- basic_auth_headers = {
135
- 'Authorization' => "Basic #{Base64.strict_encode64("#{username}:#{password}")}",
136
- 'Content-Type' => 'application/json'
137
- }
138
-
139
- response = connection.post(url) do |req|
140
- req.headers.merge!(basic_auth_headers)
141
- req.body = payload.to_json
133
+ # Try first with just Content-Type header (no Basic Auth)
134
+ begin
135
+ response = connection.post(url) do |req|
136
+ req.headers['Content-Type'] = 'application/json'
137
+ req.body = payload.to_json
138
+ end
139
+
140
+ if response.status == 201 || response.status == 200
141
+ # Extract X-Auth-Token from response headers
142
+ @x_auth_token = response.headers['X-Auth-Token']
143
+
144
+ # Extract session location from response headers
145
+ @session_location = response.headers['Location']
146
+
147
+ puts "Redfish session created successfully"
148
+ @sessions_maxed = false
149
+ return true
150
+ end
151
+ rescue => e
152
+ puts "First session creation attempt failed: #{e.message}"
142
153
  end
143
154
 
144
- if response.status == 201 || response.status == 200
145
- # Extract X-Auth-Token from response headers
146
- @x_auth_token = response.headers['X-Auth-Token']
147
-
148
- # Extract session location from response headers
149
- @session_location = response.headers['Location']
155
+ # If that fails, try with Basic Auth
156
+ begin
157
+ # Use Basic Auth for the session creation
158
+ basic_auth_headers = {
159
+ 'Authorization' => "Basic #{Base64.strict_encode64("#{username}:#{password}")}",
160
+ 'Content-Type' => 'application/json'
161
+ }
150
162
 
151
- puts "Redfish session created successfully"
152
- @sessions_maxed = false
153
- return true
154
- elsif response.status == 400 && response.body.include?("maximum number of user sessions")
155
- puts "Maximum sessions reached during Redfish session creation"
156
- @sessions_maxed = true
163
+ response = connection.post(url) do |req|
164
+ req.headers.merge!(basic_auth_headers)
165
+ req.body = payload.to_json
166
+ end
157
167
 
158
- # Try to clear sessions if auto_delete_sessions is enabled
159
- if @auto_delete_sessions
160
- puts "Auto-delete sessions is enabled, attempting to clear sessions"
161
- if force_clear_sessions
162
- puts "Successfully cleared sessions, trying to create a new session"
163
-
164
- # Try one more time after clearing
168
+ if response.status == 201 || response.status == 200
169
+ # Extract X-Auth-Token from response headers
170
+ @x_auth_token = response.headers['X-Auth-Token']
171
+
172
+ # Extract session location from response headers
173
+ @session_location = response.headers['Location']
174
+
175
+ puts "Redfish session created successfully with Basic Auth"
176
+ @sessions_maxed = false
177
+ return true
178
+ elsif response.status == 400 && response.body.include?("maximum number of user sessions")
179
+ puts "Maximum sessions reached during Redfish session creation"
180
+ @sessions_maxed = true
181
+
182
+ # Try to clear sessions if auto_delete_sessions is enabled
183
+ if @auto_delete_sessions
184
+ puts "Auto-delete sessions is enabled, attempting to clear sessions"
185
+ if force_clear_sessions
186
+ puts "Successfully cleared sessions, trying to create a new session"
187
+
188
+ # Try one more time after clearing
189
+ response = connection.post(url) do |req|
190
+ req.headers.merge!(basic_auth_headers)
191
+ req.body = payload.to_json
192
+ end
193
+
194
+ if response.status == 201 || response.status == 200
195
+ @x_auth_token = response.headers['X-Auth-Token']
196
+ @session_location = response.headers['Location']
197
+ puts "Redfish session created successfully after clearing sessions"
198
+ @sessions_maxed = false
199
+ return true
200
+ else
201
+ puts "Failed to create Redfish session after clearing: #{response.status} - #{response.body}"
202
+ # If we still can't create a session, switch to direct mode
203
+ @direct_mode = true
204
+ return false
205
+ end
206
+ else
207
+ puts "Failed to clear sessions, switching to direct mode"
208
+ @direct_mode = true
209
+ return false
210
+ end
211
+ else
212
+ puts "Auto-delete sessions is disabled, switching to direct mode"
213
+ @direct_mode = true
214
+ return false
215
+ end
216
+ else
217
+ puts "Failed to create Redfish session: #{response.status} - #{response.body}"
218
+
219
+ # If we get a 415 error, try with form-urlencoded
220
+ if response.status == 415
221
+ puts "Trying with form-urlencoded content type"
165
222
  response = connection.post(url) do |req|
166
- req.headers.merge!(basic_auth_headers)
167
- req.body = payload.to_json
223
+ req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
224
+ req.headers['Authorization'] = "Basic #{Base64.strict_encode64("#{username}:#{password}")}"
225
+ req.body = "UserName=#{URI.encode_www_form_component(username)}&Password=#{URI.encode_www_form_component(password)}"
168
226
  end
169
227
 
170
228
  if response.status == 201 || response.status == 200
171
229
  @x_auth_token = response.headers['X-Auth-Token']
172
230
  @session_location = response.headers['Location']
173
- puts "Redfish session created successfully after clearing sessions"
231
+ puts "Redfish session created successfully with form-urlencoded"
174
232
  @sessions_maxed = false
175
233
  return true
176
234
  else
177
- puts "Failed to create Redfish session after clearing: #{response.status} - #{response.body}"
178
- # If we still can't create a session, switch to direct mode
235
+ puts "Failed with form-urlencoded too: #{response.status} - #{response.body}"
179
236
  @direct_mode = true
180
237
  return false
181
238
  end
182
239
  else
183
- puts "Failed to clear sessions, switching to direct mode"
184
240
  @direct_mode = true
185
241
  return false
186
242
  end
187
- else
188
- puts "Auto-delete sessions is disabled, switching to direct mode"
189
- @direct_mode = true
190
- return false
191
243
  end
192
- else
193
- puts "Failed to create Redfish session: #{response.status} - #{response.body}"
244
+ rescue => e
245
+ puts "Error during Redfish session creation: #{e.message}"
246
+ @direct_mode = true
194
247
  return false
195
248
  end
196
249
  end
@@ -153,7 +153,13 @@ module IDRAC
153
153
  # Get current firmware versions
154
154
  current_versions = {}
155
155
  inventory[:firmware].each do |fw|
156
- current_versions[fw[:name]] = fw[:version]
156
+ # Use the ID as the key to avoid duplicates
157
+ current_versions[fw[:id]] = {
158
+ name: fw[:name],
159
+ version: fw[:version],
160
+ updateable: fw[:updateable],
161
+ identifiers: extract_identifiers(fw[:name]) # Extract identifiers for better matching
162
+ }
157
163
  end
158
164
 
159
165
  # Find matching components in catalog
@@ -163,29 +169,112 @@ module IDRAC
163
169
  path = component.at_xpath('Path')&.text
164
170
  component_type = component.at_xpath('ComponentType')&.text
165
171
 
172
+ next unless name && version && path # Skip if missing essential data
173
+
174
+ # Extract identifiers from catalog component name for better matching
175
+ catalog_identifiers = extract_identifiers(name)
176
+
166
177
  # Check if this component matches any of our firmware
167
- inventory[:firmware].each do |fw|
168
- if fw[:name].include?(name) || name.include?(fw[:name])
169
- current_version = fw[:version]
170
-
171
- # Simple version comparison (this could be improved)
172
- if version != current_version
173
- updates << {
174
- name: name,
175
- current_version: current_version,
176
- available_version: version,
177
- path: path,
178
- component_type: component_type,
179
- download_url: "https://downloads.dell.com/#{path}"
180
- }
178
+ # We'll track if we found a match to avoid duplicates
179
+ matched = false
180
+
181
+ current_versions.each do |id, fw_info|
182
+ # Skip if not updateable
183
+ next unless fw_info[:updateable]
184
+
185
+ # Normalize names for comparison
186
+ catalog_name = name.downcase.strip
187
+ firmware_name = fw_info[:name].downcase.strip
188
+
189
+ # Check for matches using multiple strategies
190
+ match_found = false
191
+
192
+ # 1. Check if names contain each other
193
+ if catalog_name.include?(firmware_name) || firmware_name.include?(catalog_name)
194
+ match_found = true
195
+ end
196
+
197
+ # 2. Check if BIOS components match
198
+ if (catalog_name.include?("bios") && firmware_name.include?("bios"))
199
+ match_found = true
200
+ end
201
+
202
+ # 3. Check if identifiers match
203
+ if !match_found && !fw_info[:identifiers].empty? && !catalog_identifiers.empty?
204
+ # Check if any identifier from firmware matches any identifier from catalog
205
+ if (fw_info[:identifiers] & catalog_identifiers).any?
206
+ match_found = true
181
207
  end
182
208
  end
209
+
210
+ # If we found a match and versions differ, add to updates
211
+ if match_found && !matched && version != fw_info[:version]
212
+ updates << {
213
+ name: name,
214
+ current_version: fw_info[:version],
215
+ available_version: version,
216
+ path: path,
217
+ component_type: component_type,
218
+ download_url: "https://downloads.dell.com/#{path}"
219
+ }
220
+
221
+ # Mark as matched to avoid duplicates
222
+ matched = true
223
+ end
183
224
  end
184
225
  end
185
226
 
186
227
  updates
187
228
  end
188
229
 
230
+ def extract_identifiers(name)
231
+ return [] unless name
232
+
233
+ identifiers = []
234
+
235
+ # Extract model numbers like X520, I350, etc.
236
+ model_matches = name.scan(/[IX]\d{3,4}/)
237
+ identifiers.concat(model_matches)
238
+
239
+ # Extract PERC model like H730
240
+ perc_matches = name.scan(/[HP]\d{3,4}/)
241
+ identifiers.concat(perc_matches)
242
+
243
+ # Extract other common identifiers
244
+ if name.include?("NIC") || name.include?("Ethernet") || name.include?("Network")
245
+ identifiers << "NIC"
246
+ end
247
+
248
+ if name.include?("PERC") || name.include?("RAID")
249
+ identifiers << "PERC"
250
+ # Extract PERC model like H730
251
+ perc_match = name.match(/PERC\s+([A-Z]\d{3})/)
252
+ identifiers << perc_match[1] if perc_match
253
+ end
254
+
255
+ if name.include?("BIOS")
256
+ identifiers << "BIOS"
257
+ end
258
+
259
+ if name.include?("iDRAC") || name.include?("IDRAC") || name.include?("Remote Access Controller")
260
+ identifiers << "iDRAC"
261
+ end
262
+
263
+ if name.include?("Power Supply") || name.include?("PSU")
264
+ identifiers << "PSU"
265
+ end
266
+
267
+ if name.include?("Lifecycle Controller")
268
+ identifiers << "LC"
269
+ end
270
+
271
+ if name.include?("CPLD")
272
+ identifiers << "CPLD"
273
+ end
274
+
275
+ identifiers
276
+ end
277
+
189
278
  def interactive_update(catalog_path = nil)
190
279
  updates = check_updates(catalog_path)
191
280
 
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.1.23"
4
+ VERSION = "0.1.26"
5
5
  end
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.1.23
4
+ version: 0.1.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Siegel