idrac 0.7.1 → 0.7.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.
data/lib/idrac/license.rb CHANGED
@@ -3,61 +3,347 @@ module IDRAC
3
3
  # Gets the license information from the iDRAC
4
4
  # @return [Hash] License details
5
5
  def license_info
6
+ # Try the standard license endpoint first (works in iDRAC 9+)
6
7
  response = authenticated_request(:get, "/redfish/v1/LicenseService/Licenses")
7
- if response.status != 200
8
- debug "Failed to retrieve licenses list: #{response.status}", 1, :red
9
- return nil
10
- end
8
+
9
+ if response.status == 200
10
+ license_data = JSON.parse(response.body)
11
+ debug "License collection: #{license_data}", 2
11
12
 
12
- license_data = JSON.parse(response.body)
13
- debug "License collection: #{license_data}", 2
13
+ # Check if there are any license entries
14
+ if !license_data["Members"] || license_data["Members"].empty?
15
+ debug "No licenses found", 1, :yellow
16
+ return try_dell_oem_license_path()
17
+ end
14
18
 
15
- # Check if there are any license entries
16
- if !license_data["Members"] || license_data["Members"].empty?
17
- debug "No licenses found", 1, :yellow
18
- return nil
19
- end
20
-
21
- # Get the first license in the list
22
- license_uri = license_data["Members"][0]["@odata.id"]
23
- debug "Using license URI: #{license_uri}", 2
19
+ # Get the first license in the list
20
+ license_uri = license_data["Members"][0]["@odata.id"]
21
+ debug "Using license URI: #{license_uri}", 2
24
22
 
25
- # Get detailed license information
26
- license_response = authenticated_request(:get, license_uri)
27
- if license_response.status != 200
28
- debug "Failed to retrieve license details: #{license_response.status}", 1, :red
29
- return nil
30
- end
23
+ # Get detailed license information
24
+ license_response = authenticated_request(:get, license_uri)
25
+ if license_response.status != 200
26
+ debug "Failed to retrieve license details: #{license_response.status}", 1, :red
27
+ return try_dell_oem_license_path()
28
+ end
31
29
 
32
- license_details = JSON.parse(license_response.body)
33
- debug "License details: #{license_details}", 2
30
+ license_details = JSON.parse(license_response.body)
31
+ debug "License details: #{license_details}", 2
34
32
 
35
- return license_details
33
+ return license_details
34
+ else
35
+ # The endpoint is not available (probably iDRAC 8)
36
+ debug "Standard license endpoint failed: #{response.status}, trying Dell OEM path", 1, :yellow
37
+ return try_dell_oem_license_path()
38
+ end
36
39
  end
37
40
 
38
- # Extracts the iDRAC version from the license description
41
+ # Extracts the iDRAC version from the license description or server header
39
42
  # @return [Integer, nil] The license version (e.g. 9) or nil if not found
40
43
  def license_version
44
+ # First try to get from license info
41
45
  license = license_info
42
- return nil unless license
46
+ if license
47
+ # Check the Description field, which often contains the version
48
+ # Example: "iDRAC9 Enterprise License"
49
+ if license["Description"]&.match(/iDRAC(\d+)/i)
50
+ version = license["Description"].match(/iDRAC(\d+)/i)[1].to_i
51
+ debug "Found license version from Description: #{version}", 1
52
+ return version
53
+ end
43
54
 
44
- # Check the Description field, which often contains the version
45
- # Example: "iDRAC9 Enterprise License"
46
- if license["Description"]&.match(/iDRAC(\d+)/i)
47
- version = license["Description"].match(/iDRAC(\d+)/i)[1].to_i
48
- debug "Found license version from Description: #{version}", 1
49
- return version
55
+ # Try alternative fields if Description didn't work
56
+ if license["Name"]&.match(/iDRAC(\d+)/i)
57
+ version = license["Name"].match(/iDRAC(\d+)/i)[1].to_i
58
+ debug "Found license version from Name: #{version}", 1
59
+ return version
60
+ end
61
+
62
+ # For Dell OEM license response format
63
+ if license["LicenseDescription"]&.match(/iDRAC(\d+)/i)
64
+ version = license["LicenseDescription"].match(/iDRAC(\d+)/i)[1].to_i
65
+ debug "Found license version from LicenseDescription: #{version}", 1
66
+ return version
67
+ end
50
68
  end
51
-
52
- # Try alternative fields if Description didn't work
53
- if license["Name"]&.match(/iDRAC(\d+)/i)
54
- version = license["Name"].match(/iDRAC(\d+)/i)[1].to_i
55
- debug "Found license version from Name: #{version}", 1
69
+
70
+ # If license info failed or didn't have version info, try to get from server header
71
+ # Make a simple request to check the server header (often contains iDRAC version)
72
+ response = authenticated_request(:get, "/redfish/v1")
73
+ if response.headers["server"] && response.headers["server"].match(/iDRAC\/(\d+)/i)
74
+ version = response.headers["server"].match(/iDRAC\/(\d+)/i)[1].to_i
75
+ debug "Found license version from server header: #{version}", 1
56
76
  return version
57
77
  end
58
-
59
- debug "Could not determine license version from license info", 1, :yellow
78
+
79
+ debug "Could not determine license version from license info or server header", 1, :yellow
60
80
  nil
61
81
  end
82
+
83
+ private
84
+
85
+ # Attempt to get license information using Dell OEM extension path (for iDRAC 8)
86
+ # @return [Hash, nil] License info or nil if not found
87
+ def try_dell_oem_license_path
88
+ # Try several potential Dell license paths (order matters - most likely first)
89
+ dell_license_paths = [
90
+ "/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellLicenseManagementService/Licenses",
91
+ "/redfish/v1/Managers/iDRAC.Embedded.1/Attributes", # iDRAC attributes might contain license info
92
+ "/redfish/v1/Managers/iDRAC.Embedded.1" # Manager entity might have license info embedded
93
+ ]
94
+
95
+ dell_license_paths.each do |path|
96
+ response = authenticated_request(:get, path)
97
+
98
+ if response.status == 200
99
+ debug "Found valid Dell license path: #{path}", 2
100
+ data = JSON.parse(response.body)
101
+
102
+ # Check for license info in this response based on the path
103
+ if path.include?("DellLicenseManagementService")
104
+ return handle_dell_license_service_response(data)
105
+ elsif path.include?("Attributes")
106
+ return handle_dell_attributes_response(data)
107
+ elsif path.include?("iDRAC.Embedded.1") && !path.include?("Attributes")
108
+ return handle_dell_manager_response(data)
109
+ end
110
+ else
111
+ debug "Dell path #{path} response status: #{response.status}", 3
112
+ end
113
+ end
114
+
115
+ # If we couldn't find any API path that works, try the service tag detection method
116
+ service_tag = get_service_tag
117
+ if service_tag
118
+ # Service tag is often used to indicate Enterprise licenses on Dell systems
119
+ license_type = determine_license_type()
120
+ return {
121
+ "Id" => "iDRAC-License",
122
+ "Description" => "iDRAC8 #{license_type} License",
123
+ "Name" => "iDRAC License",
124
+ "LicenseType" => license_type,
125
+ "Status" => { "Health" => "OK" },
126
+ "Removable" => false,
127
+ "EntitlementID" => service_tag # Dell often uses service tag as entitlement ID
128
+ }
129
+ end
130
+
131
+ # Fall back to feature detection if all else fails
132
+ debug "All Dell OEM license paths failed, using fallback detection", 1, :yellow
133
+ return create_fallback_license_info()
134
+ end
135
+
136
+ # Handle response from Dell License Management Service
137
+ def handle_dell_license_service_response(data)
138
+ # Check if there are any license entries
139
+ if !data["Members"] || data["Members"].empty?
140
+ debug "No licenses found in Dell OEM path", 1, :yellow
141
+ return create_fallback_license_info(use_basic: true)
142
+ end
143
+
144
+ # Get the first license in the list
145
+ license_uri = data["Members"][0]["@odata.id"]
146
+ debug "Using Dell OEM license URI: #{license_uri}", 2
147
+
148
+ # Get detailed license information
149
+ license_response = authenticated_request(:get, license_uri)
150
+ if license_response.status != 200
151
+ debug "Failed to retrieve Dell OEM license details: #{license_response.status}", 1, :red
152
+ return create_fallback_license_info(use_basic: true)
153
+ end
154
+
155
+ dell_license = JSON.parse(license_response.body)
156
+ debug "Dell OEM license details: #{dell_license}", 2
157
+
158
+ # Convert Dell OEM license format to standard format
159
+ license_info = {
160
+ "Id" => dell_license["EntitlementID"] || "iDRAC-License",
161
+ "Description" => dell_license["LicenseDescription"] || "iDRAC License",
162
+ "Name" => dell_license["LicenseDescription"] || "iDRAC License",
163
+ "LicenseType" => dell_license["LicenseType"] || get_license_type_from_description(dell_license["LicenseDescription"]),
164
+ "Status" => { "Health" => "OK" },
165
+ "Removable" => true
166
+ }
167
+
168
+ return license_info
169
+ end
170
+
171
+ # Handle response from Dell Manager attributes
172
+ def handle_dell_attributes_response(data)
173
+ # Look for license information in attributes
174
+ if data["Attributes"] && (
175
+ data["Attributes"]["LicensableDevice.1.LicenseInfo.1"] ||
176
+ data["Attributes"]["System.ServerOS.1.OSName"] ||
177
+ data["Attributes"]["iDRAC.Info.1.LicensingInfo"]
178
+ )
179
+
180
+ license_info = data["Attributes"]["LicensableDevice.1.LicenseInfo.1"] ||
181
+ data["Attributes"]["iDRAC.Info.1.LicensingInfo"]
182
+
183
+ if license_info
184
+ license_type = license_info.include?("Enterprise") ? "Enterprise" :
185
+ license_info.include?("Express") ? "Express" : "Basic"
186
+
187
+ return {
188
+ "Id" => "iDRAC-License",
189
+ "Description" => "iDRAC8 #{license_type} License",
190
+ "Name" => "iDRAC License",
191
+ "LicenseType" => license_type,
192
+ "Status" => { "Health" => "OK" },
193
+ "Removable" => false
194
+ }
195
+ end
196
+ end
197
+
198
+ # If no license attributes found, fall back to feature detection
199
+ license_type = determine_license_type()
200
+ return {
201
+ "Id" => "iDRAC-License",
202
+ "Description" => "iDRAC8 #{license_type} License",
203
+ "Name" => "iDRAC License",
204
+ "LicenseType" => license_type,
205
+ "Status" => { "Health" => "OK" },
206
+ "Removable" => false
207
+ }
208
+ end
209
+
210
+ # Handle response from Dell Manager entity
211
+ def handle_dell_manager_response(data)
212
+ # Look for license information in Oem data
213
+ if data["Oem"] && data["Oem"]["Dell"]
214
+ dell_data = data["Oem"]["Dell"]
215
+
216
+ if dell_data["DellLicenseManagementService"]
217
+ # Found license service reference, but need to query it directly
218
+ service_uri = dell_data["DellLicenseManagementService"]["@odata.id"]
219
+ debug "Found license service URI: #{service_uri}", 2
220
+
221
+ service_response = authenticated_request(:get, service_uri)
222
+ if service_response.status == 200
223
+ return handle_dell_license_service_response(JSON.parse(service_response.body))
224
+ end
225
+ end
226
+
227
+ # Check if license info is embedded directly
228
+ if dell_data["LicenseType"] || dell_data["License"]
229
+ license_type = dell_data["LicenseType"] ||
230
+ (dell_data["License"] && dell_data["License"].include?("Enterprise") ? "Enterprise" :
231
+ dell_data["License"].include?("Express") ? "Express" : "Basic")
232
+
233
+ return {
234
+ "Id" => "iDRAC-License",
235
+ "Description" => "iDRAC8 #{license_type} License",
236
+ "Name" => "iDRAC License",
237
+ "LicenseType" => license_type,
238
+ "Status" => { "Health" => "OK" },
239
+ "Removable" => false
240
+ }
241
+ end
242
+ end
243
+
244
+ # Check for license type in model name or description
245
+ if data["Model"] && data["Model"].include?("Enterprise")
246
+ return {
247
+ "Id" => "iDRAC-License",
248
+ "Description" => "iDRAC8 Enterprise License",
249
+ "Name" => "iDRAC License",
250
+ "LicenseType" => "Enterprise",
251
+ "Status" => { "Health" => "OK" },
252
+ "Removable" => false
253
+ }
254
+ end
255
+
256
+ # If no license info found in manager data, fall back to feature detection
257
+ license_type = determine_license_type()
258
+ return {
259
+ "Id" => "iDRAC-License",
260
+ "Description" => "iDRAC8 #{license_type} License",
261
+ "Name" => "iDRAC License",
262
+ "LicenseType" => license_type,
263
+ "Status" => { "Health" => "OK" },
264
+ "Removable" => false
265
+ }
266
+ end
267
+
268
+ # Get service tag from system info
269
+ def get_service_tag
270
+ response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1")
271
+ if response.status == 200
272
+ data = JSON.parse(response.body)
273
+ return data["SKU"] if data["SKU"] # Service tag is usually in SKU field
274
+ end
275
+
276
+ # Try alternate location
277
+ response = authenticated_request(:get, "/redfish/v1")
278
+ if response.status == 200
279
+ data = JSON.parse(response.body)
280
+ if data["Oem"] && data["Oem"]["Dell"] && data["Oem"]["Dell"]["ServiceTag"]
281
+ return data["Oem"]["Dell"]["ServiceTag"]
282
+ end
283
+ end
284
+
285
+ nil
286
+ end
287
+
288
+ # Helper method to extract license type from description
289
+ def get_license_type_from_description(description)
290
+ return "Unknown" unless description
291
+
292
+ if description.include?("Enterprise")
293
+ return "Enterprise"
294
+ elsif description.include?("Express")
295
+ return "Express"
296
+ elsif description.include?("Datacenter")
297
+ return "Datacenter"
298
+ else
299
+ return "Basic"
300
+ end
301
+ end
302
+
303
+ # Creates a basic license info object based on system information
304
+ # Used as a fallback when neither the standard nor Dell OEM endpoints work
305
+ # @return [Hash] A basic license info object
306
+ def create_fallback_license_info(use_basic: false)
307
+ # Get the iDRAC version number from server headers
308
+ version = nil
309
+ response = authenticated_request(:get, "/redfish/v1")
310
+ if response.headers["server"] && response.headers["server"].match(/iDRAC\/(\d+)/i)
311
+ version = response.headers["server"].match(/iDRAC\/(\d+)/i)[1].to_i
312
+ end
313
+
314
+ # Try to determine if it's Enterprise or Express based on available features
315
+ license_type = use_basic ? "Basic" : determine_license_type
316
+
317
+ license_info = {
318
+ "Id" => "iDRAC-License",
319
+ "Description" => version ? "iDRAC#{version} #{license_type} License" : "iDRAC License",
320
+ "Name" => "iDRAC License",
321
+ "LicenseType" => license_type,
322
+ "Status" => { "Health" => "OK" },
323
+ "Removable" => false
324
+ }
325
+
326
+ debug "Created fallback license info: #{license_info}", 2
327
+ license_info
328
+ end
329
+
330
+ # Attempt to determine the license type (Enterprise/Express) based on available features
331
+ # @return [String] The license type (Enterprise, Express, or Basic)
332
+ def determine_license_type
333
+ # We can try to check for features only available in Enterprise
334
+ begin
335
+ # For example, virtual media is typically an Enterprise feature
336
+ virtual_media_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia")
337
+ # If we successfully get virtual media, it's likely Enterprise
338
+ if virtual_media_response.status == 200
339
+ return "Enterprise"
340
+ end
341
+ rescue
342
+ # If the request fails, don't fail the whole method
343
+ end
344
+
345
+ # Default to basic license if we can't determine
346
+ return "Express"
347
+ end
62
348
  end
63
349
  end
@@ -3,8 +3,94 @@ require 'colorize'
3
3
 
4
4
  module IDRAC
5
5
  module Lifecycle
6
- # Check if the Lifecycle Controller is enabled
6
+ # This follows from these Scripts "GetIdracLcSystemAttributesREDFISH.py" and "SetIdracLcSystemAttributesREDFISH.py"
7
+ # They can do more than just the lifecycle, but that's what we need right now.
8
+ # True or False if it's enabled or not
7
9
  def get_lifecycle_status
10
+ # Check iDRAC version first to determine the right approach
11
+ idrac_version = get_idrac_version rescue 0
12
+
13
+ debug "Detected iDRAC version: #{idrac_version}", 1
14
+
15
+ # Use version-specific methods
16
+ if idrac_version > 9
17
+ debug "Using modern approach for iDRAC > 9", 1
18
+ return get_lifecycle_status_modern_firmware
19
+ elsif idrac_version == 9
20
+ debug "Using registry approach for iDRAC 9", 1
21
+ return get_lifecycle_status_from_registry
22
+ else
23
+ debug "Using SCP approach for older iDRAC (v#{idrac_version})", 1
24
+ return get_lifecycle_status_from_scp
25
+ end
26
+ end
27
+
28
+ # Get lifecycle status from SCP export (for older iDRAC firmware)
29
+ def get_lifecycle_status_from_scp
30
+ debug "Exporting System Configuration Profile to check LifecycleController state...", 1
31
+
32
+ begin
33
+ # Use the SCP export to get LifecycleController state
34
+ scp = get_system_configuration_profile(target: "LifecycleController")
35
+
36
+ # Check if we have data in the expected format
37
+ if scp && scp["SystemConfiguration"] && scp["SystemConfiguration"]["Components"]
38
+ # Find the LifecycleController component
39
+ lc_component = scp["SystemConfiguration"]["Components"].find do |component|
40
+ component["FQDD"] == "LifecycleController.Embedded.1"
41
+ end
42
+
43
+ if lc_component && lc_component["Attributes"]
44
+ # Find the LifecycleControllerState attribute
45
+ lc_state_attr = lc_component["Attributes"].find do |attr|
46
+ attr["Name"] == "LCAttributes.1#LifecycleControllerState"
47
+ end
48
+
49
+ if lc_state_attr
50
+ debug "Found LifecycleController state from SCP: #{lc_state_attr["Value"]}", 1
51
+ return lc_state_attr["Value"] == "Enabled"
52
+ end
53
+ end
54
+ end
55
+
56
+ debug "Could not find LifecycleController state in SCP export", 1, :yellow
57
+ return false
58
+ rescue => e
59
+ debug "Error getting Lifecycle Controller status from SCP: #{e.message}", 1, :red
60
+ debug e.backtrace.join("\n"), 3, :red
61
+ return false
62
+ end
63
+ end
64
+
65
+ # Get lifecycle status from registry (for iDRAC 9)
66
+ def get_lifecycle_status_from_registry
67
+ # This big JSON explains all the attributes:
68
+ path = "/redfish/v1/Registries/ManagerAttributeRegistry/ManagerAttributeRegistry.v1_0_0.json"
69
+ response = authenticated_request(:get, path)
70
+ if response.status != 200
71
+ debug "Failed to get any Lifecycle Controller Attributes".red, 1
72
+ return false
73
+ end
74
+ attributes = JSON.parse(response.body)
75
+ # This is the attribute we want:
76
+ target = attributes&.dig('RegistryEntries', 'Attributes')&.find {|q| q['AttributeName'] =~ /LCAttributes.1.LifecycleControllerState/ }
77
+ # This is the FQDN of the attribute we want to get the value of:
78
+ fqdn = target.dig('Id') # LifecycleController.Embedded.1#LCAttributes.1#LifecycleControllerState
79
+ # This is the Current Value:
80
+ response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellAttributes/#{fqdn}")
81
+ if response.status != 200
82
+ debug "Failed to get Lifecycle Controller Attributes".red, 1
83
+ return false
84
+ end
85
+ attributes = JSON.parse(response.body)
86
+ # There is a ValueName and a Value Display Name (e.g. Enabled, Disabled, Recovery)
87
+ display = attributes&.dig('Attributes','LCAttributes.1.LifecycleControllerState')
88
+ value = target&.dig('Value')&.find { |v| v['ValueDisplayName'] == display }&.dig('ValueName')&.to_i
89
+ value == 1
90
+ end
91
+
92
+ # Check if the Lifecycle Controller is enabled
93
+ def get_lifecycle_status_modern_firmware
8
94
  # Try the standard Attributes endpoint first
9
95
  path = "/redfish/v1/Managers/iDRAC.Embedded.1/Attributes"
10
96
  response = authenticated_request(:get, path)
@@ -201,4 +287,4 @@ module IDRAC
201
287
  debug "Lifecycle Controller is now #{status ? 'Enabled' : 'Disabled'}".green, 1
202
288
  end
203
289
  end
204
- end
290
+ end
data/lib/idrac/power.rb CHANGED
@@ -78,32 +78,10 @@ module IDRAC
78
78
 
79
79
  response = authenticated_request(:post, path, body: payload.to_json, headers: { 'Content-Type' => 'application/json' })
80
80
 
81
- case response.status
82
- when 200, 204
83
- puts "Server power off command sent successfully".green
84
- when 409
85
- # Conflict -- Server is already off
86
- begin
87
- error_data = JSON.parse(response.body)
88
- if error_data["error"] && error_data["error"]["@Message.ExtendedInfo"] &&
89
- error_data["error"]["@Message.ExtendedInfo"].any? { |m| m["Message"] =~ /Server is already powered OFF/ }
90
- puts "Server is already powered OFF.".yellow
91
- return false
92
- else
93
- raise Error, "Failed to power off: #{error_data.inspect}"
94
- end
95
- rescue JSON::ParserError
96
- raise Error, "Failed to power off with status 409: #{response.body}"
97
- end
81
+ if response.status == 409
82
+ puts "Server is already powered OFF.".yellow
98
83
  else
99
- error_message = "Failed to power off server. Status code: #{response.status}"
100
- begin
101
- error_data = JSON.parse(response.body)
102
- error_message += ", Message: #{error_data['error']['message']}" if error_data['error'] && error_data['error']['message']
103
- rescue
104
- # Ignore JSON parsing errors
105
- end
106
- raise Error, error_message
84
+ handle_response(response)
107
85
  end
108
86
 
109
87
  # Wait for power state change if requested
@@ -124,6 +102,13 @@ module IDRAC
124
102
  login unless @session_id
125
103
 
126
104
  puts "Rebooting server...".light_cyan
105
+
106
+ # Check current power state first
107
+ current_state = get_power_state rescue "Unknown"
108
+ if current_state == "Off"
109
+ puts "Server is currently off, powering on instead of rebooting".yellow
110
+ return power_on
111
+ end
127
112
 
128
113
  # Send reboot command (Reset with ResetType=ForceRestart)
129
114
  path = "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"
@@ -134,16 +119,17 @@ module IDRAC
134
119
  if response.status >= 200 && response.status < 300
135
120
  puts "Server reboot command sent successfully".green
136
121
  return true
137
- else
138
- error_message = "Failed to reboot server. Status code: #{response.status}"
139
- begin
140
- error_data = JSON.parse(response.body)
141
- error_message += ", Message: #{error_data['error']['message']}" if error_data['error'] && error_data['error']['message']
142
- rescue
143
- # Ignore JSON parsing errors
144
- end
122
+ elsif response.status == 409
123
+ error_data = JSON.parse(response.body) rescue nil
124
+ puts "Received conflict (409) error from iDRAC: #{error_data.inspect}"
125
+ # Try gracefulRestart as an alternative
126
+ puts "Trying GracefulRestart instead...".yellow
127
+ payload = { "ResetType" => "GracefulRestart" }
128
+ response = authenticated_request(:post, path, body: payload.to_json, headers: { 'Content-Type' => 'application/json' })
145
129
 
146
- raise Error, error_message
130
+ handle_response(response)
131
+ else
132
+ raise Error, "Failed to reboot server. Status code: #{response.status}"
147
133
  end
148
134
  end
149
135
 
@@ -154,16 +140,7 @@ module IDRAC
154
140
  # Get system information
155
141
  response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$select=PowerState")
156
142
 
157
- if response.status == 200
158
- begin
159
- system_data = JSON.parse(response.body)
160
- return system_data["PowerState"]
161
- rescue JSON::ParserError
162
- raise Error, "Failed to parse power state response: #{response.body}"
163
- end
164
- else
165
- raise Error, "Failed to get power state. Status code: #{response.status}"
166
- end
143
+ JSON.parse(handle_response(response))&.dig("PowerState")
167
144
  end
168
145
 
169
146
  def get_power_usage_watts
@@ -172,25 +149,7 @@ module IDRAC
172
149
 
173
150
  response = authenticated_request(:get, "/redfish/v1/Chassis/System.Embedded.1/Power")
174
151
 
175
- if response.status == 200
176
- begin
177
- data = JSON.parse(response.body)
178
- watts = data["PowerControl"][0]["PowerConsumedWatts"]
179
- # puts "Power usage: #{watts} watts".light_cyan
180
- return watts.to_f
181
- rescue JSON::ParserError
182
- raise Error, "Failed to parse power usage response: #{response.body}"
183
- end
184
- else
185
- error_message = "Failed to get power usage. Status code: #{response.status}"
186
- begin
187
- error_data = JSON.parse(response.body)
188
- error_message += ", Message: #{error_data['error']['message']}" if error_data['error'] && error_data['error']['message']
189
- rescue
190
- # Ignore JSON parsing errors
191
- end
192
- raise Error, error_message
193
- end
152
+ JSON.parse(handle_response(response))&.dig("PowerControl", 0, "PowerConsumedWatts")&.to_f
194
153
  end
195
154
 
196
155
  private