idrac 0.1.24 → 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: f2e790b22ca375a798916fdb6d908583d2fa4823e90a814c2e7c27796c7b6351
4
- data.tar.gz: 0ab7103ae540892dc959d22c7fa646050fe8eeaf003f6dc538c753fc3d614452
3
+ metadata.gz: 4d751ffb6e590b80a6a5dc72457d8a4be11213224a13ebeae50698ae9f6cafff
4
+ data.tar.gz: 5a3f826850bf9aee8e40287ff7f8ab7c5bd71944ddce2b183dbe88dabed9c3fa
5
5
  SHA512:
6
- metadata.gz: 89b75cdaf04c90368379af12884e55dcd4e5daa52ccda59143776934c871a60c039891a13194a52496532159bad0859f3b8502fe2f8beeaf433319ba1d5aa0e1
7
- data.tar.gz: 6dee9f26c047f9931ea846e2eaf738f91510801fdb090c384d18fd76639ca098db11ca071acb55ab81a0c319bb42ecb781d33f71ed83c66c9dac22c58c8bf2c6
6
+ metadata.gz: 553bef804c000680be8ecadb15c19f2b4a335db5a7a44b5071ccb230f168880268e906f5a296a70c8659a5bbbb14a0ffb3a6f56cfc4c9ca216e0a1f8a6024a0f
7
+ data.tar.gz: ff4d0ce0967de6fbddd425844e0c86165276c44d508a2b8de41a20ec54e3998f7d2f1d5aa7cadf34201dd26113bd0abafb1e01d13439edbcb1d22f273e31a1f5
data/README.md CHANGED
@@ -127,6 +127,20 @@ 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
+
130
144
  ### Version 0.1.24
131
145
  - **Improved Firmware Update Check**: Fixed issues with firmware version comparison
132
146
  - Eliminated duplicate entries in firmware update results
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
@@ -157,7 +157,8 @@ module IDRAC
157
157
  current_versions[fw[:id]] = {
158
158
  name: fw[:name],
159
159
  version: fw[:version],
160
- updateable: fw[:updateable]
160
+ updateable: fw[:updateable],
161
+ identifiers: extract_identifiers(fw[:name]) # Extract identifiers for better matching
161
162
  }
162
163
  end
163
164
 
@@ -170,43 +171,110 @@ module IDRAC
170
171
 
171
172
  next unless name && version && path # Skip if missing essential data
172
173
 
174
+ # Extract identifiers from catalog component name for better matching
175
+ catalog_identifiers = extract_identifiers(name)
176
+
173
177
  # Check if this component matches any of our firmware
174
178
  # We'll track if we found a match to avoid duplicates
175
179
  matched = false
176
180
 
177
181
  current_versions.each do |id, fw_info|
182
+ # Skip if not updateable
183
+ next unless fw_info[:updateable]
184
+
178
185
  # Normalize names for comparison
179
186
  catalog_name = name.downcase.strip
180
187
  firmware_name = fw_info[:name].downcase.strip
181
188
 
182
- # Check if names match or contain each other
183
- if catalog_name.include?(firmware_name) || firmware_name.include?(catalog_name) ||
184
- (catalog_name.include?("bios") && firmware_name.include?("bios"))
185
-
186
- # Skip if already matched to avoid duplicates
187
- next if matched
188
-
189
- # Compare versions
190
- if version != fw_info[:version] && fw_info[:updateable]
191
- updates << {
192
- name: name,
193
- current_version: fw_info[:version],
194
- available_version: version,
195
- path: path,
196
- component_type: component_type,
197
- download_url: "https://downloads.dell.com/#{path}"
198
- }
199
-
200
- # Mark as matched to avoid duplicates
201
- matched = true
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
202
207
  end
203
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
204
224
  end
205
225
  end
206
226
 
207
227
  updates
208
228
  end
209
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
+
210
278
  def interactive_update(catalog_path = nil)
211
279
  updates = check_updates(catalog_path)
212
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.24"
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.24
4
+ version: 0.1.26
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Siegel