idrac 0.11.0 → 0.11.2
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 +4 -4
- data/README.md +13 -0
- data/lib/idrac/client.rb +2 -1
- data/lib/idrac/session.rb +1 -0
- data/lib/idrac/system_config.rb +30 -0
- data/lib/idrac/utility.rb +42 -5
- data/lib/idrac/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9ad0fa030e4eec1e405f68895dfb6df28cccea13f2d4ec3a73c878e1485858f3
|
|
4
|
+
data.tar.gz: 1311e7bfd4ecc14ae1ad2ce52b0d5290db92a3c0befed2a5da7ebdebd779f291
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 152616e382e2800ba319a761be9f65d463da19273ed8e79236c2a13f32d021a87e4de138763843902e8fb9b5d000b48d47fe653f2d35b6110ad9cc7ba87ae786
|
|
7
|
+
data.tar.gz: 69f27c37739d3f22a03659d76a0fa4be4334c2c19adb67671b11194987b8c921025d00be0c8cd627d9bcc5991238e2b0d7c444ece750b5da961f3dbcb833d4c4
|
data/README.md
CHANGED
|
@@ -36,6 +36,19 @@ Or install it yourself as:
|
|
|
36
36
|
|
|
37
37
|
$ gem install idrac
|
|
38
38
|
|
|
39
|
+
## Compatibility
|
|
40
|
+
|
|
41
|
+
`activesupport` below 8.1 and `json` 3 cannot be used together: activesupport's
|
|
42
|
+
JSON encoder calls `JSON.generate(..., quirks_mode: true)`, and json 3 removed
|
|
43
|
+
that keyword, so any `hash.to_json` raises `ArgumentError: unknown keyword:
|
|
44
|
+
quirks_mode`. This is not specific to this gem — it bites anything that loads
|
|
45
|
+
`active_support/core_ext` — but idrac depends on activesupport, so pick one of:
|
|
46
|
+
|
|
47
|
+
- activesupport >= 8.1 with json 3, or
|
|
48
|
+
- activesupport 7.x with json 2.
|
|
49
|
+
|
|
50
|
+
CI covers both ends.
|
|
51
|
+
|
|
39
52
|
## Usage
|
|
40
53
|
|
|
41
54
|
### Command Line Interface
|
data/lib/idrac/client.rb
CHANGED
|
@@ -81,6 +81,7 @@ module IDRAC
|
|
|
81
81
|
faraday.response :logger, Logger.new(STDOUT), bodies: @verbosity >= 2 do |logger|
|
|
82
82
|
logger.filter(/(Authorization: Basic )([^,\n]+)/, '\1[FILTERED]')
|
|
83
83
|
logger.filter(/(Password"=>"?)([^,"]+)/, '\1[FILTERED]')
|
|
84
|
+
logger.filter(/(Password\\?"\s*[:,]\s*(?:\\?"Value\\?"\s*:\s*)?\\?")([^"\\]*)/, '\1[FILTERED]')
|
|
84
85
|
end
|
|
85
86
|
end
|
|
86
87
|
end
|
|
@@ -190,7 +191,7 @@ module IDRAC
|
|
|
190
191
|
headers['Accept'] ||= 'application/json'
|
|
191
192
|
headers['Host'] = @host_header if @host_header
|
|
192
193
|
|
|
193
|
-
debug "Request body: #{body}", 2 if body && @verbosity >= 2
|
|
194
|
+
debug "Request body: #{body.to_s.match?(/password/i) ? '[REDACTED: contains a password]' : body}", 2 if body && @verbosity >= 2
|
|
194
195
|
|
|
195
196
|
if @direct_mode
|
|
196
197
|
headers['Authorization'] = "Basic #{Base64.strict_encode64("#{username}:#{password}")}"
|
data/lib/idrac/session.rb
CHANGED
|
@@ -43,6 +43,7 @@ module IDRAC
|
|
|
43
43
|
faraday.response :logger, Logger.new(STDOUT), bodies: @verbosity >= 2 do |logger|
|
|
44
44
|
logger.filter(/(Authorization: Basic )([^,\n]+)/, '\1[FILTERED]')
|
|
45
45
|
logger.filter(/(Password"=>"?)([^,"]+)/, '\1[FILTERED]')
|
|
46
|
+
logger.filter(/(Password\\?"\s*[:,]\s*(?:\\?"Value\\?"\s*:\s*)?\\?")([^"\\]*)/, '\1[FILTERED]')
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
49
|
end
|
data/lib/idrac/system_config.rb
CHANGED
|
@@ -84,6 +84,34 @@ module IDRAC
|
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
# Set iDRAC-only attributes without touching host power. Names are Redfish-style
|
|
88
|
+
# ("VNCServer.1.Enable" => "Enabled"). iDRAC9 takes a plain PATCH (no job). iDRAC8 has
|
|
89
|
+
# no Manager Attributes resource (404), so fall back to an SCP import that targets the
|
|
90
|
+
# iDRAC only, with NoReboot and HostPowerState pinned to the host's current state.
|
|
91
|
+
# Returns { status: :success } for the PATCH, or the import job's outcome.
|
|
92
|
+
def set_idrac_attributes(attributes, timeout: 600)
|
|
93
|
+
debug "Setting iDRAC attributes: #{attributes.to_h { |k, v| [k, k.to_s.match?(/password/i) ? "[REDACTED]" : v] }}", 1, :blue
|
|
94
|
+
response = authenticated_request(:patch, "/redfish/v1/Managers/iDRAC.Embedded.1/Attributes",
|
|
95
|
+
body: { "Attributes" => attributes }.to_json) { |r| r }
|
|
96
|
+
return { status: :success } if response.status.between?(200, 299)
|
|
97
|
+
handle_response(response) unless response.status == 404
|
|
98
|
+
|
|
99
|
+
scp = { "SystemConfiguration" => { "Components" => [make_scp(fqdd: "iDRAC.Embedded.1",
|
|
100
|
+
attributes: attributes.to_h { |k, v| [k.to_s.sub(/\A([^.]+\.\d+)\./, '\1#'), v] })] } }
|
|
101
|
+
response = authenticated_request(:post,
|
|
102
|
+
"/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager.ImportSystemConfiguration",
|
|
103
|
+
body: { "ImportBuffer" => JSON.generate(scp), "ShareParameters" => { "Target" => "IDRAC" },
|
|
104
|
+
"ShutdownType" => "NoReboot", "HostPowerState" => get_power_state }.to_json)
|
|
105
|
+
wait_for_scp_import(response.headers["location"], timeout: timeout)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def enable_vnc!(password:, port: 5901)
|
|
109
|
+
set_idrac_attributes("VNCServer.1.Enable" => "Enabled", "VNCServer.1.Port" => port,
|
|
110
|
+
"VNCServer.1.Password" => password,
|
|
111
|
+
"VNCServer.1.SSLEncryptionBitLength" => "Disabled",
|
|
112
|
+
"VNCServer.1.LowerEncryptionBitLength" => "Disabled")
|
|
113
|
+
end
|
|
114
|
+
|
|
87
115
|
# Apply a system configuration profile to the iDRAC.
|
|
88
116
|
#
|
|
89
117
|
# Waits for the import JOB to finish and returns the JOB's outcome:
|
|
@@ -117,6 +145,8 @@ module IDRAC
|
|
|
117
145
|
"ImportBuffer" => JSON.generate(scp_to_apply),
|
|
118
146
|
"ShareParameters" => {"Target" => target},
|
|
119
147
|
"ShutdownType" => "Forced",
|
|
148
|
+
# Warning: reboot: false sends "Off", which POWERS THE HOST OFF after the import.
|
|
149
|
+
# For iDRAC-only attributes use set_idrac_attributes, which keeps the power state.
|
|
120
150
|
"HostPowerState" => reboot ? "On" : "Off"
|
|
121
151
|
}
|
|
122
152
|
|
data/lib/idrac/utility.rb
CHANGED
|
@@ -194,11 +194,28 @@ module IDRAC
|
|
|
194
194
|
# @param data_selector_values [Array] Array of log types to include (optional)
|
|
195
195
|
# @param wait_timeout [Integer] Maximum time to wait for generation in seconds (default: 600)
|
|
196
196
|
# @return [String, nil] Path to downloaded file or nil if failed
|
|
197
|
-
def generate_and_download_tsr(output_file: nil, data_selector_values: nil, wait_timeout: 600)
|
|
197
|
+
def generate_and_download_tsr(output_file: nil, data_selector_values: nil, accept_eula: false, wait_timeout: 600)
|
|
198
198
|
debug "Starting TSR generation and download process...", 1
|
|
199
|
-
|
|
199
|
+
|
|
200
200
|
output_file ||= "supportassist_#{@host}_#{Time.now.strftime('%Y%m%d_%H%M%S')}.zip"
|
|
201
|
-
|
|
201
|
+
|
|
202
|
+
# Accept the EULA up front when asked -- generate_tsr_logs only errors out otherwise.
|
|
203
|
+
accept_supportassist_eula if accept_eula
|
|
204
|
+
|
|
205
|
+
# Wait out a collection that is still running server-side. The iDRAC allows only one
|
|
206
|
+
# SupportAssist collection at a time, so generating now would fail with "a SupportAssist job
|
|
207
|
+
# is already running". Give up after wait_timeout seconds and fail the same way the rest of
|
|
208
|
+
# this method does (return nil).
|
|
209
|
+
wait_deadline = Time.now + wait_timeout
|
|
210
|
+
while supportassist_collection_running?
|
|
211
|
+
if Time.now > wait_deadline
|
|
212
|
+
debug "Timed out after #{wait_timeout}s waiting for a running SupportAssist collection to finish", 1, :red
|
|
213
|
+
return nil
|
|
214
|
+
end
|
|
215
|
+
debug "A SupportAssist collection is already running; waiting...", 1, :yellow
|
|
216
|
+
sleep 15
|
|
217
|
+
end
|
|
218
|
+
|
|
202
219
|
# First, generate the TSR
|
|
203
220
|
result = generate_tsr_logs(data_selector_values: data_selector_values)
|
|
204
221
|
|
|
@@ -267,8 +284,9 @@ module IDRAC
|
|
|
267
284
|
collection_in_progress: false
|
|
268
285
|
}
|
|
269
286
|
|
|
270
|
-
# Check if there's an active collection job
|
|
271
|
-
|
|
287
|
+
# Check if there's an active collection job. The list must be expanded, otherwise each
|
|
288
|
+
# Members entry is a bare @odata.id with no Name/JobState and the check never fires.
|
|
289
|
+
jobs_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs?$expand=*($levels=1)")
|
|
272
290
|
if jobs_response.status == 200
|
|
273
291
|
jobs_data = JSON.parse(jobs_response.body)
|
|
274
292
|
if jobs_data["Members"]
|
|
@@ -294,6 +312,25 @@ module IDRAC
|
|
|
294
312
|
{ available: false, error: e.message }
|
|
295
313
|
end
|
|
296
314
|
|
|
315
|
+
# True when a SupportAssist Collection job is still running server-side. Reads the expanded Dell
|
|
316
|
+
# Jobs list (bare @odata.id members carry no Name/JobState) and treats a job as running when its
|
|
317
|
+
# Name matches SupportAssist Collection, its JobState is not terminal, and it is below 100%.
|
|
318
|
+
# Use this to wait out a prior collection before starting a new one (the iDRAC allows only one).
|
|
319
|
+
def supportassist_collection_running?
|
|
320
|
+
response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs?$expand=*($levels=1)")
|
|
321
|
+
return false unless response.status == 200
|
|
322
|
+
|
|
323
|
+
members = JSON.parse(response.body)["Members"] || []
|
|
324
|
+
members.any? do |job|
|
|
325
|
+
job["Name"].to_s =~ /SupportAssist Collection/i &&
|
|
326
|
+
!IDRAC::Firmware::TERMINAL_JOB_STATES.include?(job["JobState"]) &&
|
|
327
|
+
job["PercentComplete"].to_i < 100
|
|
328
|
+
end
|
|
329
|
+
rescue => e
|
|
330
|
+
debug "Error checking SupportAssist collection state: #{e.message}", 1, :red
|
|
331
|
+
false
|
|
332
|
+
end
|
|
333
|
+
|
|
297
334
|
# Check SupportAssist EULA status
|
|
298
335
|
# @return [Hash] EULA status information
|
|
299
336
|
def supportassist_eula_status
|
data/lib/idrac/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: idrac
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.11.
|
|
4
|
+
version: 0.11.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jonathan Siegel
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: httparty
|
|
@@ -297,7 +297,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
297
297
|
- !ruby/object:Gem::Version
|
|
298
298
|
version: '0'
|
|
299
299
|
requirements: []
|
|
300
|
-
rubygems_version: 3.5.
|
|
300
|
+
rubygems_version: 3.5.22
|
|
301
301
|
signing_key:
|
|
302
302
|
specification_version: 4
|
|
303
303
|
summary: API Client for Dell iDRAC
|