idrac 0.7.10 → 0.8.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: ada89d6fb4827e57600dda32ff7a93124b526ee3986335fb593c2a61ea767d29
4
- data.tar.gz: 4237b089a51941b56524e3d4341835b5c60c36b365cfff9e74f90faa43bf0fad
3
+ metadata.gz: 58f8d5e0d7f90857359eaf0be71c114da11ac324539b335e1a55f21567c33020
4
+ data.tar.gz: 498235abd52da11fba45a89032a5e0a72a56b53b7918e60bbdacfeda718229a2
5
5
  SHA512:
6
- metadata.gz: 7a5367ff256299d380a8be3d9b1f284051e96ac415e377667e8118cb0511b138fa7a0c3644a1d48c69bba74e5d812cd0046add67a4a1b0d7913b482de9b03d87
7
- data.tar.gz: ddc6e9496009474248636fe2037b6aa721bb9f50a333937835062f02aad4ed7fff46f098a824b0ef1eabe3c704e2584261d08e150f426e4c778886a56a7c164b
6
+ metadata.gz: 83010a42db5c2f04ce5d7c49802725e54aeb68409c2aaca00318fb32bb4c6adb69b50f22f2e2b14891934fd308b248d6b8169bcb70ba8e3f0415ea5405c3438a
7
+ data.tar.gz: d9bea26cad955e27ad749018973d999e76741b34d0645f2cc7f9abc046f977ec95d23bebbb46a2e80f990bb71cc265c7b52b1ed539dee0a8463984efa66f1864
data/README.md CHANGED
@@ -17,6 +17,8 @@ A Ruby client for the Dell iDRAC API. This gem provides a command-line interface
17
17
  - Lifecycle Controller status management
18
18
  - Return values as RecursiveOpenStruct objects for convenient attribute access
19
19
  - Reset iDRAC functionality
20
+ - Generate and download TSR (Technical Support Report) / SupportAssist collections
21
+ - SupportAssist EULA management
20
22
 
21
23
  ## Installation
22
24
 
@@ -85,6 +87,11 @@ idrac sel:clear --host=192.168.1.100
85
87
 
86
88
  # Reset iDRAC
87
89
  idrac reset --host=192.168.1.100
90
+
91
+ # TSR/SupportAssist Collection Commands
92
+ idrac tsr_collect --host=192.168.1.100 # Generate and download TSR logs
93
+ idrac tsr_status --host=192.168.1.100 # Check TSR collection status
94
+ idrac tsr_accept_eula --host=192.168.1.100 # Accept SupportAssist EULA (required before first use)
88
95
  ```
89
96
 
90
97
  All commands automatically handle session expiration by re-authenticating when necessary, ensuring that long-running operations like firmware updates complete successfully even if the iDRAC session times out.
@@ -179,6 +186,18 @@ client.clear_lifecycle!
179
186
  # Clear System Event Logs
180
187
  client.clear_system_event_logs!
181
188
 
189
+ # TSR/SupportAssist Collection operations
190
+ # Accept EULA (required only once)
191
+ client.accept_supportassist_eula
192
+
193
+ # Generate and download TSR logs
194
+ file_path = client.generate_and_download_tsr(output_file: "tsr.zip")
195
+ puts "TSR logs saved to: #{file_path}"
196
+
197
+ # Check TSR collection status
198
+ status = client.tsr_status
199
+ puts "Collection available: #{status[:available]}"
200
+
182
201
  # Working with hash objects
183
202
  # Methods return data as Ruby hashes with string keys for consistent access
184
203
 
@@ -272,6 +291,15 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
272
291
 
273
292
  ## Changelog
274
293
 
294
+ ### Version 0.8.0
295
+ - **Added TSR/SupportAssist Collection Support**: Simplified commands for generating Technical Support Reports
296
+ - Generate and download SupportAssist collections with direct file download
297
+ - Automatic EULA acceptance check with clear user guidance
298
+ - Simple CLI commands: `tsr_collect`, `tsr_status`, `tsr_accept_eula`
299
+ - Job-based generation with automatic progress tracking
300
+ - Direct download approach based on Dell's official Python implementation
301
+ - Clear error messages when EULA acceptance is required
302
+
275
303
  ### Version 0.7.8
276
304
  - **Network Redirection Support**: Added optional `host_header` parameter to Client initialization
277
305
  - Enables iDRAC access through network redirection scenarios where the connection IP differs from the Host header requirement
data/bin/idrac CHANGED
@@ -1660,6 +1660,53 @@ module IDRAC
1660
1660
  end
1661
1661
  end
1662
1662
 
1663
+ # TSR (Technical Support Report) commands
1664
+ desc "tsr_collect", "Generate and download TSR/SupportAssist collection"
1665
+ method_option :output, type: :string, desc: "Output filename"
1666
+ def tsr_collect
1667
+ with_idrac_client do |client|
1668
+ puts "Generating and downloading TSR logs...".yellow
1669
+ puts "This may take several minutes...".yellow
1670
+
1671
+ result = client.generate_and_download_tsr(output_file: options[:output])
1672
+
1673
+ if result
1674
+ puts "TSR logs saved to: #{result}".green
1675
+ puts "File size: #{File.size(result) / 1024 / 1024} MB".cyan if File.exist?(result)
1676
+ else
1677
+ puts "Failed to generate or download TSR logs".red
1678
+ end
1679
+ end
1680
+ end
1681
+
1682
+ desc "tsr_status", "Check TSR collection status"
1683
+ def tsr_status
1684
+ with_idrac_client do |client|
1685
+ status = client.tsr_status
1686
+
1687
+ puts "\nTSR Collection Status:".green.bold
1688
+ puts "Available: #{status[:available] ? 'Yes'.green : 'No'.red}"
1689
+
1690
+ if status[:collection_in_progress]
1691
+ puts "Collection in progress: Yes".yellow
1692
+ puts "Job ID: #{status[:job_id]}".cyan if status[:job_id]
1693
+ else
1694
+ puts "Collection in progress: No".green
1695
+ end
1696
+ end
1697
+ end
1698
+
1699
+ desc "tsr_accept_eula", "Accept SupportAssist EULA"
1700
+ def tsr_accept_eula
1701
+ with_idrac_client do |client|
1702
+ if client.accept_supportassist_eula
1703
+ puts "SupportAssist EULA accepted successfully".green
1704
+ else
1705
+ puts "Failed to accept SupportAssist EULA".red
1706
+ end
1707
+ end
1708
+ end
1709
+
1663
1710
  private
1664
1711
 
1665
1712
  def with_idrac_client
data/bin/idrac-tsr ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/idrac'
4
+ require 'optparse'
5
+
6
+ options = {
7
+ host: ENV['IDRAC_HOST'],
8
+ username: ENV['IDRAC_USER'] || 'root',
9
+ password: ENV['IDRAC_PASSWORD'] || 'calvin',
10
+ output: nil,
11
+ data_types: [0, 1, 2], # Default: Hardware, OS, Debug
12
+ timeout: 600,
13
+ verbose: false
14
+ }
15
+
16
+ OptionParser.new do |opts|
17
+ opts.banner = "Usage: idrac-tsr [options]"
18
+
19
+ opts.on("-h", "--host HOST", "iDRAC host address") do |h|
20
+ options[:host] = h
21
+ end
22
+
23
+ opts.on("-u", "--username USER", "Username (default: root)") do |u|
24
+ options[:username] = u
25
+ end
26
+
27
+ opts.on("-p", "--password PASS", "Password (default: calvin)") do |p|
28
+ options[:password] = p
29
+ end
30
+
31
+ opts.on("-o", "--output FILE", "Output filename (default: auto-generated)") do |o|
32
+ options[:output] = o
33
+ end
34
+
35
+ opts.on("-d", "--data TYPES", "Data types to collect (comma-separated: 0=HW,1=OS,2=Debug,3=TTY,4=All)") do |d|
36
+ options[:data_types] = d.split(',').map(&:to_i)
37
+ end
38
+
39
+ opts.on("-t", "--timeout SECONDS", Integer, "Timeout in seconds (default: 600)") do |t|
40
+ options[:timeout] = t
41
+ end
42
+
43
+ opts.on("-v", "--verbose", "Verbose output") do
44
+ options[:verbose] = true
45
+ end
46
+
47
+ opts.on("--help", "Show this message") do
48
+ puts opts
49
+ exit
50
+ end
51
+ end.parse!
52
+
53
+ if options[:host].nil?
54
+ puts "Error: Host is required. Use -h HOST or set IDRAC_HOST environment variable"
55
+ exit 1
56
+ end
57
+
58
+ begin
59
+ client = IDRAC::Client.new(
60
+ host: options[:host],
61
+ username: options[:username],
62
+ password: options[:password],
63
+ verify_ssl: false
64
+ )
65
+
66
+ client.verbosity = options[:verbose] ? 1 : 0
67
+
68
+ puts "Connecting to #{options[:host]}..."
69
+ client.login
70
+
71
+ puts "Generating TSR logs (this may take several minutes)..."
72
+ result = client.generate_and_download_tsr(
73
+ output_file: options[:output],
74
+ data_selector_values: options[:data_types],
75
+ wait_timeout: options[:timeout]
76
+ )
77
+
78
+ if result
79
+ puts "✓ TSR logs saved to: #{result}"
80
+ puts " File size: #{File.size(result) / 1024 / 1024} MB" if File.exist?(result)
81
+ else
82
+ puts "✗ Failed to download TSR logs"
83
+ exit 1
84
+ end
85
+
86
+ client.logout
87
+ rescue => e
88
+ puts "Error: #{e.message}"
89
+ exit 1
90
+ end
data/lib/idrac/client.rb CHANGED
@@ -155,6 +155,11 @@ module IDRAC
155
155
  headers['Accept'] ||= 'application/json'
156
156
  headers['Host'] = @host_header if @host_header
157
157
 
158
+ # Debug the body being sent
159
+ if body && @verbosity >= 2
160
+ debug "Request body: #{body}", 2
161
+ end
162
+
158
163
  # Determine authentication method and set headers
159
164
  if @direct_mode
160
165
  headers['Authorization'] = "Basic #{Base64.strict_encode64("#{username}:#{password}")}"
@@ -190,6 +195,7 @@ module IDRAC
190
195
  begin
191
196
  conn.options.timeout = timeout if timeout
192
197
  conn.options.open_timeout = open_timeout if open_timeout
198
+
193
199
  conn.run_request(method, path, body, headers)
194
200
  ensure
195
201
  conn.options.timeout = original_timeout
data/lib/idrac/utility.rb CHANGED
@@ -1,7 +1,355 @@
1
+
1
2
  module IDRAC
2
3
  module Utility
3
4
  include Debuggable
4
5
 
6
+ # Generate TSR (Technical Support Report) logs using SupportAssistCollection for local generation
7
+ # @param data_selector_values [Array] Array of log types to include (optional)
8
+ # Default includes all available log types
9
+ # @return [Hash] Result hash with status and job/task information
10
+ def generate_tsr_logs(data_selector_values: nil, share_type: nil, share_parameters: nil)
11
+ debug "Generating TSR/SupportAssist logs...", 1
12
+
13
+ # Check EULA status first
14
+ eula_status = supportassist_eula_status
15
+ if eula_status["EULAAccepted"] == false || eula_status["EULAAccepted"] == "false"
16
+ puts "\n" + "="*80
17
+ puts "ERROR: SupportAssist EULA Not Accepted".red.bold
18
+ puts "="*80
19
+ puts ""
20
+ puts "The SupportAssist End User License Agreement (EULA) must be accepted".yellow
21
+ puts "before you can generate TSR/SupportAssist collections.".yellow
22
+ puts ""
23
+ puts "To accept the EULA, run:".cyan
24
+ puts " idrac tsr_accept_eula --host #{@host} --port #{@port}".green.bold
25
+ puts ""
26
+ puts "="*80
27
+ return { status: :failed, error: "SupportAssist EULA not accepted" }
28
+ end
29
+
30
+ # Default data selector values for comprehensive TSR
31
+ # Valid values for SupportAssistCollection: "DebugLogs", "GPULogs", "HWData", "OSAppData", "TTYLogs", "TelemetryReports"
32
+ data_selector_values ||= ["HWData", "OSAppData"]
33
+
34
+ # Map numeric values to iDRAC expected strings if needed
35
+ if data_selector_values.is_a?(Array) && data_selector_values.first.to_s =~ /^\d+$/
36
+ data_selector_values = data_selector_values.map do |val|
37
+ case val.to_s
38
+ when "0" then "HWData"
39
+ when "1" then "OSAppData"
40
+ when "2" then "TTYLogs"
41
+ when "3" then "DebugLogs"
42
+ else "HWData" # Default to HWData
43
+ end
44
+ end
45
+ elsif data_selector_values.is_a?(String)
46
+ data_selector_values = data_selector_values.split(',')
47
+ end
48
+
49
+ debug "Data selector values: #{data_selector_values.inspect}", 1
50
+
51
+ # Use SupportAssistCollection for local generation as it supports "Local" ShareType
52
+ payload = {
53
+ "ShareType" => "Local",
54
+ "DataSelectorArrayIn" => data_selector_values,
55
+ "Filter" => "No", # Don't filter PII
56
+ "Transmit" => "No" # Don't transmit to Dell
57
+ }
58
+
59
+ debug "SupportAssist collection payload: #{payload.to_json}", 1
60
+
61
+ response = authenticated_request(
62
+ :post,
63
+ "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.SupportAssistCollection",
64
+ body: payload.to_json,
65
+ headers: { 'Content-Type' => 'application/json' }
66
+ )
67
+
68
+ case response.status
69
+ when 202
70
+ # Accepted - job created
71
+ location = response.headers["location"]
72
+ if location
73
+ debug "TSR generation job created: #{location}", 1, :green
74
+ job_id = location.split("/").last
75
+ # Wait for job to complete and capture the file location
76
+ job_result = wait_for_job_with_location(job_id)
77
+ if job_result && (job_result["JobState"] == "Completed" || job_result["JobState"] == "CompletedWithErrors")
78
+ result = { status: :success, job: job_result }
79
+ # Check if we got a file location from the job completion
80
+ result[:location] = job_result["FileLocation"] if job_result["FileLocation"]
81
+ result
82
+ else
83
+ { status: :failed, error: "Job did not complete successfully" }
84
+ end
85
+ else
86
+ { status: :accepted, message: "TSR generation initiated" }
87
+ end
88
+ when 200..299
89
+ debug "TSR generation completed immediately", 1, :green
90
+ { status: :success }
91
+ else
92
+ error_msg = parse_error_response(response)
93
+ debug "Failed to generate TSR: #{error_msg}", 1, :red
94
+ { status: :failed, error: error_msg }
95
+ end
96
+ rescue => e
97
+ debug "Error generating TSR: #{e.message}", 1, :red
98
+ { status: :error, error: e.message }
99
+ end
100
+
101
+ # Download TSR/SupportAssist logs from a URL location
102
+ # @param location [String] URL location of the TSR file
103
+ # @param output_file [String] Path to save the TSR file (optional)
104
+ # @return [String, nil] Path to downloaded file or nil if failed
105
+ def download_tsr_from_location(location, output_file: nil)
106
+ debug "Downloading TSR from location: #{location}", 1
107
+
108
+ # Default output filename with timestamp
109
+ output_file ||= "supportassist_#{@host}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.zip"
110
+
111
+ # Download the file from the location
112
+ file_response = authenticated_request(:get, location)
113
+
114
+ if file_response.status == 200 && file_response.body
115
+ File.open(output_file, 'wb') do |f|
116
+ f.write(file_response.body)
117
+ end
118
+ debug "TSR saved to: #{output_file} (#{File.size(output_file)} bytes)", 1, :green
119
+ return output_file
120
+ else
121
+ debug "Failed to download file from location. Status: #{file_response.status}", 1, :red
122
+ nil
123
+ end
124
+ rescue => e
125
+ debug "Error downloading TSR: #{e.message}", 1, :red
126
+ nil
127
+ end
128
+
129
+ # Wait for job and capture file location from response headers
130
+ # @param job_id [String] The job ID to wait for
131
+ # @param max_wait [Integer] Maximum time to wait in seconds
132
+ # @return [Hash, nil] Job data with FileLocation if available
133
+ def wait_for_job_with_location(job_id, max_wait: 600)
134
+ debug "Waiting for job #{job_id} to complete...", 1
135
+ start_time = Time.now
136
+
137
+ while (Time.now - start_time) < max_wait
138
+ job_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs/#{job_id}")
139
+
140
+ if job_response.status == 200
141
+ job_data = JSON.parse(job_response.body)
142
+
143
+ case job_data["JobState"]
144
+ when "Completed", "CompletedWithErrors"
145
+ debug "Job #{job_id} completed: #{job_data["JobState"]}", 1, :green
146
+
147
+ # Check response headers for file location
148
+ if job_response.headers["location"]
149
+ job_data["FileLocation"] = job_response.headers["location"]
150
+ debug "Found file location in headers: #{job_data["FileLocation"]}", 1, :green
151
+ end
152
+
153
+ # Also check the job data itself for output location
154
+ if job_data["Oem"] && job_data["Oem"]["Dell"] && job_data["Oem"]["Dell"]["OutputLocation"]
155
+ job_data["FileLocation"] = job_data["Oem"]["Dell"]["OutputLocation"]
156
+ debug "Found file location in job data: #{job_data["FileLocation"]}", 1, :green
157
+ end
158
+
159
+ return job_data
160
+ when "Failed", "Exception"
161
+ debug "Job #{job_id} failed: #{job_data["Message"]}", 1, :red
162
+ return job_data
163
+ else
164
+ debug "Job #{job_id} state: #{job_data["JobState"]} - #{job_data["PercentComplete"]}%", 2
165
+ sleep 5
166
+ end
167
+ else
168
+ debug "Failed to get job status: #{job_response.status}", 2
169
+ sleep 5
170
+ end
171
+ end
172
+
173
+ debug "Timeout waiting for job #{job_id}", 1, :red
174
+ nil
175
+ end
176
+
177
+ # Parse error response from iDRAC
178
+ def parse_error_response(response)
179
+ begin
180
+ data = JSON.parse(response.body)
181
+ if data["error"] && data["error"]["@Message.ExtendedInfo"]
182
+ data["error"]["@Message.ExtendedInfo"].first["Message"]
183
+ elsif data["error"] && data["error"]["message"]
184
+ data["error"]["message"]
185
+ else
186
+ "Status: #{response.status} - #{response.body}"
187
+ end
188
+ rescue
189
+ "Status: #{response.status} - #{response.body}"
190
+ end
191
+ end
192
+
193
+ # Generate and download TSR logs in a single operation
194
+ # @param output_file [String] Path to save the TSR file (optional)
195
+ # @param data_selector_values [Array] Array of log types to include (optional)
196
+ # @param wait_timeout [Integer] Maximum time to wait for generation in seconds (default: 600)
197
+ # @return [String, nil] Path to downloaded file or nil if failed
198
+ def generate_and_download_tsr(output_file: nil, data_selector_values: nil, wait_timeout: 600)
199
+ debug "Starting TSR generation and download process...", 1
200
+
201
+ output_file ||= "supportassist_#{@host}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.zip"
202
+
203
+ # First, generate the TSR
204
+ result = generate_tsr_logs(data_selector_values: data_selector_values)
205
+
206
+ if result[:status] == :success && result[:job]
207
+ debug "TSR generation completed successfully", 1, :green
208
+
209
+ # Check if the job response has a location for the file
210
+ if result[:location]
211
+ return download_tsr_from_location(result[:location], output_file: output_file)
212
+ else
213
+ # Try alternative download methods based on Dell's Python script approach
214
+ debug "Attempting to locate generated TSR file...", 1, :yellow
215
+
216
+ # Wait a moment for the file to be available
217
+ sleep 2
218
+
219
+ # Try known endpoints where the file might be available
220
+ possible_locations = [
221
+ "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/ExportedFiles/SupportAssist",
222
+ "/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellLCService/ExportedFiles",
223
+ "/downloads/supportassist_collection.zip",
224
+ "/sysmgmt/2016/server/support_assist_collection"
225
+ ]
226
+
227
+ possible_locations.each do |location|
228
+ debug "Trying location: #{location}", 2
229
+ file_response = authenticated_request(:get, location)
230
+
231
+ if file_response.status == 200 && file_response.body && file_response.body.size > 1024
232
+ File.open(output_file, 'wb') do |f|
233
+ f.write(file_response.body)
234
+ end
235
+ debug "TSR saved to: #{output_file} (#{File.size(output_file)} bytes)", 1, :green
236
+ return output_file
237
+ end
238
+ end
239
+
240
+ debug "Could not locate TSR file for direct download", 1, :yellow
241
+ debug "The collection was generated but may require network share export", 1, :yellow
242
+ end
243
+ elsif result[:status] == :accepted
244
+ debug "TSR generation was accepted but status unknown", 1, :yellow
245
+ else
246
+ debug "Failed to initiate TSR generation: #{result[:error]}", 1, :red
247
+ end
248
+
249
+ nil
250
+ end
251
+ public
252
+
253
+ # Get TSR/SupportAssist collection status
254
+ # @return [Hash] Status information
255
+ def tsr_status
256
+ debug "Checking SupportAssist collection status...", 1
257
+
258
+ response = authenticated_request(
259
+ :get,
260
+ "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService"
261
+ )
262
+
263
+ if response.status == 200
264
+ data = JSON.parse(response.body)
265
+ status = {
266
+ available: data["Actions"]&.key?("#DellLCService.SupportAssistCollection"),
267
+ export_available: data["Actions"]&.key?("#DellLCService.SupportAssistExportLastCollection"),
268
+ collection_in_progress: false
269
+ }
270
+
271
+ # Check if there's an active collection job
272
+ jobs_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs")
273
+ if jobs_response.status == 200
274
+ jobs_data = JSON.parse(jobs_response.body)
275
+ if jobs_data["Members"]
276
+ jobs_data["Members"].each do |job|
277
+ if job["Name"]&.include?("SupportAssist") || job["Name"]&.include?("TSR")
278
+ status[:collection_in_progress] = true
279
+ status[:job_id] = job["Id"]
280
+ status[:job_state] = job["JobState"]
281
+ break
282
+ end
283
+ end
284
+ end
285
+ end
286
+
287
+ debug "SupportAssist status: #{status.to_json}", 2
288
+ status
289
+ else
290
+ debug "Failed to get SupportAssist status: #{response.status}", 1, :red
291
+ { available: false, error: "Unable to determine status" }
292
+ end
293
+ rescue => e
294
+ debug "Error checking SupportAssist status: #{e.message}", 1, :red
295
+ { available: false, error: e.message }
296
+ end
297
+
298
+ # Check SupportAssist EULA status
299
+ # @return [Hash] EULA status information
300
+ def supportassist_eula_status
301
+ debug "Checking SupportAssist EULA status...", 1
302
+
303
+ response = authenticated_request(
304
+ :post,
305
+ "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.SupportAssistGetEULAStatus",
306
+ body: {}.to_json,
307
+ headers: { 'Content-Type' => 'application/json' }
308
+ )
309
+
310
+ if response.status.between?(200, 299)
311
+ begin
312
+ data = JSON.parse(response.body)
313
+ debug "EULA status: #{data.to_json}", 2
314
+ return data
315
+ rescue JSON::ParserError
316
+ return { "EULAAccepted" => "Unknown" }
317
+ end
318
+ else
319
+ error_msg = parse_error_response(response)
320
+ debug "Failed to get EULA status: #{error_msg}", 1, :red
321
+ return { "EULAAccepted" => "Error", "error" => error_msg }
322
+ end
323
+ rescue => e
324
+ debug "Error checking EULA status: #{e.message}", 1, :red
325
+ { "EULAAccepted" => "Error", "error" => e.message }
326
+ end
327
+
328
+ # Accept SupportAssist EULA
329
+ # @return [Boolean] true if successful
330
+ def accept_supportassist_eula
331
+ debug "Accepting SupportAssist EULA...", 1
332
+
333
+ response = authenticated_request(
334
+ :post,
335
+ "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.SupportAssistAcceptEULA",
336
+ body: {}.to_json,
337
+ headers: { 'Content-Type' => 'application/json' }
338
+ )
339
+
340
+ if response.status.between?(200, 299)
341
+ debug "SupportAssist EULA accepted successfully", 1, :green
342
+ true
343
+ else
344
+ error_msg = parse_error_response(response)
345
+ debug "Failed to accept EULA: #{error_msg}", 1, :red
346
+ false
347
+ end
348
+ rescue => e
349
+ debug "Error accepting EULA: #{e.message}", 1, :red
350
+ false
351
+ end
352
+
5
353
  # Reset the iDRAC controller (graceful restart)
6
354
  def reset!
7
355
  debug "Resetting iDRAC controller...", 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.7.10"
4
+ VERSION = "0.8.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: idrac
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.10
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Siegel
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-06-24 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: httparty
@@ -261,6 +260,7 @@ files:
261
260
  - README.md
262
261
  - bin/console
263
262
  - bin/idrac
263
+ - bin/idrac-tsr
264
264
  - bin/setup
265
265
  - idrac.gemspec
266
266
  - lib/idrac.rb
@@ -286,7 +286,6 @@ licenses:
286
286
  - MIT
287
287
  metadata:
288
288
  homepage_uri: http://github.com
289
- post_install_message:
290
289
  rdoc_options: []
291
290
  require_paths:
292
291
  - lib
@@ -301,8 +300,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
301
300
  - !ruby/object:Gem::Version
302
301
  version: '0'
303
302
  requirements: []
304
- rubygems_version: 3.5.16
305
- signing_key:
303
+ rubygems_version: 3.6.7
306
304
  specification_version: 4
307
305
  summary: API Client for Dell iDRAC
308
306
  test_files: []