idrac 0.9.3 → 0.9.4
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/lib/idrac/license.rb +91 -316
- data/lib/idrac/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 54237d0e5e104838b8770088791b1896b11928d0092572035ee05117de1d6733
|
|
4
|
+
data.tar.gz: 802a048dcf46d8d9a1eab4626be4425269ee58d0012b61f1ac167b44a8b1def9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 95ff7c2f6e83194632b4ceb9febd251f01332f39271c02bfc2e0f35e677159b873b7ff74a8906f5b293af855aa2fb3f69ed4e73242be8ca704f6346da507c9a8
|
|
7
|
+
data.tar.gz: 94f8e2b5ab66ff0cf428bdb1903d3ba3d38d9b3e2002323e36a866ffb4461ae22a2766861550d4daf0fe74b274e2991ef9280fd9732581af9d0b86d3209b7047
|
data/lib/idrac/license.rb
CHANGED
|
@@ -1,359 +1,134 @@
|
|
|
1
1
|
module IDRAC
|
|
2
2
|
module License
|
|
3
3
|
# Gets the license information from the iDRAC
|
|
4
|
-
# @return [Hash] License details
|
|
4
|
+
# @return [Hash, nil] License details
|
|
5
5
|
def license_info
|
|
6
|
-
# Try
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
debug "License collection: #{license_data}", 2
|
|
12
|
-
|
|
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
|
|
18
|
-
|
|
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
|
|
22
|
-
|
|
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()
|
|
6
|
+
# Try standard endpoint first (iDRAC 9+)
|
|
7
|
+
if (data = safe_get("/redfish/v1/LicenseService/Licenses"))
|
|
8
|
+
if data["Members"]&.any?
|
|
9
|
+
license_uri = data["Members"][0]["@odata.id"]
|
|
10
|
+
return safe_get(license_uri) || try_dell_oem_license_path
|
|
28
11
|
end
|
|
29
|
-
|
|
30
|
-
license_details = JSON.parse(license_response.body)
|
|
31
|
-
debug "License details: #{license_details}", 2
|
|
32
|
-
|
|
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
12
|
end
|
|
13
|
+
|
|
14
|
+
try_dell_oem_license_path
|
|
39
15
|
end
|
|
40
16
|
|
|
41
|
-
# Extracts the iDRAC
|
|
42
|
-
# @return [Integer, nil]
|
|
17
|
+
# Extracts the iDRAC generation (e.g. 8, 9) from license or server header
|
|
18
|
+
# @return [Integer, nil]
|
|
43
19
|
def license_version
|
|
44
|
-
# Use memoization to cache the result and avoid multiple API calls
|
|
45
20
|
@license_version ||= compute_license_version
|
|
46
21
|
end
|
|
47
|
-
|
|
48
|
-
# Clear the cached license version (useful if iDRAC state changes)
|
|
22
|
+
|
|
49
23
|
def clear_license_version_cache
|
|
50
24
|
@license_version = nil
|
|
51
25
|
end
|
|
52
|
-
|
|
26
|
+
|
|
53
27
|
private
|
|
54
|
-
|
|
28
|
+
|
|
29
|
+
# GET that returns parsed JSON on 200, nil otherwise. Never raises on 4xx.
|
|
30
|
+
def safe_get(path)
|
|
31
|
+
response = authenticated_request(:get, path) { |r| r }
|
|
32
|
+
return nil unless response.status == 200
|
|
33
|
+
JSON.parse(response.body)
|
|
34
|
+
rescue JSON::ParserError
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
|
|
55
38
|
def compute_license_version
|
|
56
|
-
# First try to get from license info
|
|
57
39
|
license = license_info
|
|
58
40
|
if license
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
debug "Found license version from Description: #{version}", 1
|
|
64
|
-
return version
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Try alternative fields if Description didn't work
|
|
68
|
-
if license["Name"]&.match(/iDRAC(\d+)/i)
|
|
69
|
-
version = license["Name"].match(/iDRAC(\d+)/i)[1].to_i
|
|
70
|
-
debug "Found license version from Name: #{version}", 1
|
|
71
|
-
return version
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# For Dell OEM license response format
|
|
75
|
-
if license["LicenseDescription"]&.match(/iDRAC(\d+)/i)
|
|
76
|
-
version = license["LicenseDescription"].match(/iDRAC(\d+)/i)[1].to_i
|
|
77
|
-
debug "Found license version from LicenseDescription: #{version}", 1
|
|
78
|
-
return version
|
|
41
|
+
%w[Description Name LicenseDescription].each do |field|
|
|
42
|
+
if license[field]&.match(/iDRAC(\d+)/i)
|
|
43
|
+
return $1.to_i
|
|
44
|
+
end
|
|
79
45
|
end
|
|
80
46
|
end
|
|
81
|
-
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
-
response
|
|
85
|
-
|
|
86
|
-
version = response.headers["server"].match(/iDRAC\/(\d+)/i)[1].to_i
|
|
87
|
-
debug "Found license version from server header: #{version}", 1
|
|
88
|
-
return version
|
|
47
|
+
|
|
48
|
+
# Fall back to server header
|
|
49
|
+
response = authenticated_request(:get, "/redfish/v1") { |r| r }
|
|
50
|
+
if response.headers["server"]&.match(/iDRAC\/(\d+)/i)
|
|
51
|
+
return $1.to_i
|
|
89
52
|
end
|
|
90
|
-
|
|
91
|
-
debug "Could not determine license version from license info or server header", 1, :yellow
|
|
53
|
+
|
|
92
54
|
nil
|
|
93
55
|
end
|
|
94
|
-
|
|
95
|
-
# Attempt to get license information using Dell OEM extension path (for iDRAC 8)
|
|
96
|
-
# @return [Hash, nil] License info or nil if not found
|
|
56
|
+
|
|
97
57
|
def try_dell_oem_license_path
|
|
98
|
-
# Try
|
|
99
|
-
|
|
100
|
-
"
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
# Check for license info in this response based on the path
|
|
113
|
-
if path.include?("DellLicenseManagementService")
|
|
114
|
-
return handle_dell_license_service_response(data)
|
|
115
|
-
elsif path.include?("Attributes")
|
|
116
|
-
return handle_dell_attributes_response(data)
|
|
117
|
-
elsif path.include?("iDRAC.Embedded.1") && !path.include?("Attributes")
|
|
118
|
-
return handle_dell_manager_response(data)
|
|
58
|
+
# Try Dell OEM license service (iDRAC 8)
|
|
59
|
+
if (data = safe_get("/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellLicenseManagementService/Licenses"))
|
|
60
|
+
if data["Members"]&.any?
|
|
61
|
+
license_uri = data["Members"][0]["@odata.id"]
|
|
62
|
+
if (details = safe_get(license_uri))
|
|
63
|
+
return {
|
|
64
|
+
"Id" => details["EntitlementID"] || "iDRAC-License",
|
|
65
|
+
"Description" => details["LicenseDescription"] || "iDRAC License",
|
|
66
|
+
"Name" => details["LicenseDescription"] || "iDRAC License",
|
|
67
|
+
"LicenseType" => details["LicenseType"] || license_type_from(details["LicenseDescription"]),
|
|
68
|
+
"Status" => { "Health" => "OK" },
|
|
69
|
+
"Removable" => true
|
|
70
|
+
}
|
|
119
71
|
end
|
|
120
|
-
else
|
|
121
|
-
debug "Dell path #{path} response status: #{response.status}", 3
|
|
122
72
|
end
|
|
123
73
|
end
|
|
124
|
-
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
"Id" => "iDRAC-License",
|
|
132
|
-
"Description" => "iDRAC8 #{license_type} License",
|
|
133
|
-
"Name" => "iDRAC License",
|
|
134
|
-
"LicenseType" => license_type,
|
|
135
|
-
"Status" => { "Health" => "OK" },
|
|
136
|
-
"Removable" => false,
|
|
137
|
-
"EntitlementID" => service_tag # Dell often uses service tag as entitlement ID
|
|
138
|
-
}
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Fall back to feature detection if all else fails
|
|
142
|
-
debug "All Dell OEM license paths failed, using fallback detection", 1, :yellow
|
|
143
|
-
return create_fallback_license_info()
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
# Handle response from Dell License Management Service
|
|
147
|
-
def handle_dell_license_service_response(data)
|
|
148
|
-
# Check if there are any license entries
|
|
149
|
-
if !data["Members"] || data["Members"].empty?
|
|
150
|
-
debug "No licenses found in Dell OEM path", 1, :yellow
|
|
151
|
-
return create_fallback_license_info(use_basic: true)
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
# Get the first license in the list
|
|
155
|
-
license_uri = data["Members"][0]["@odata.id"]
|
|
156
|
-
debug "Using Dell OEM license URI: #{license_uri}", 2
|
|
157
|
-
|
|
158
|
-
# Get detailed license information
|
|
159
|
-
license_response = authenticated_request(:get, license_uri)
|
|
160
|
-
if license_response.status != 200
|
|
161
|
-
debug "Failed to retrieve Dell OEM license details: #{license_response.status}", 1, :red
|
|
162
|
-
return create_fallback_license_info(use_basic: true)
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
dell_license = JSON.parse(license_response.body)
|
|
166
|
-
debug "Dell OEM license details: #{dell_license}", 2
|
|
167
|
-
|
|
168
|
-
# Convert Dell OEM license format to standard format
|
|
169
|
-
license_info = {
|
|
170
|
-
"Id" => dell_license["EntitlementID"] || "iDRAC-License",
|
|
171
|
-
"Description" => dell_license["LicenseDescription"] || "iDRAC License",
|
|
172
|
-
"Name" => dell_license["LicenseDescription"] || "iDRAC License",
|
|
173
|
-
"LicenseType" => dell_license["LicenseType"] || get_license_type_from_description(dell_license["LicenseDescription"]),
|
|
174
|
-
"Status" => { "Health" => "OK" },
|
|
175
|
-
"Removable" => true
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return license_info
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
# Handle response from Dell Manager attributes
|
|
182
|
-
def handle_dell_attributes_response(data)
|
|
183
|
-
# Look for license information in attributes
|
|
184
|
-
if data["Attributes"] && (
|
|
185
|
-
data["Attributes"]["LicensableDevice.1.LicenseInfo.1"] ||
|
|
186
|
-
data["Attributes"]["System.ServerOS.1.OSName"] ||
|
|
187
|
-
data["Attributes"]["iDRAC.Info.1.LicensingInfo"]
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
license_info = data["Attributes"]["LicensableDevice.1.LicenseInfo.1"] ||
|
|
191
|
-
data["Attributes"]["iDRAC.Info.1.LicensingInfo"]
|
|
192
|
-
|
|
193
|
-
if license_info
|
|
194
|
-
license_type = license_info.include?("Enterprise") ? "Enterprise" :
|
|
195
|
-
license_info.include?("Express") ? "Express" : "Basic"
|
|
196
|
-
|
|
197
|
-
return {
|
|
198
|
-
"Id" => "iDRAC-License",
|
|
199
|
-
"Description" => "iDRAC8 #{license_type} License",
|
|
200
|
-
"Name" => "iDRAC License",
|
|
201
|
-
"LicenseType" => license_type,
|
|
202
|
-
"Status" => { "Health" => "OK" },
|
|
203
|
-
"Removable" => false
|
|
204
|
-
}
|
|
205
|
-
end
|
|
74
|
+
|
|
75
|
+
# Try manager attributes
|
|
76
|
+
if (data = safe_get("/redfish/v1/Managers/iDRAC.Embedded.1/Attributes"))
|
|
77
|
+
attr = data.dig("Attributes", "LicensableDevice.1.LicenseInfo.1") ||
|
|
78
|
+
data.dig("Attributes", "iDRAC.Info.1.LicensingInfo")
|
|
79
|
+
return build_license_hash(license_type_from(attr)) if attr
|
|
206
80
|
end
|
|
207
|
-
|
|
208
|
-
#
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
# Look for license information in Oem data
|
|
223
|
-
if data["Oem"] && data["Oem"]["Dell"]
|
|
224
|
-
dell_data = data["Oem"]["Dell"]
|
|
225
|
-
|
|
226
|
-
if dell_data["DellLicenseManagementService"]
|
|
227
|
-
# Found license service reference, but need to query it directly
|
|
228
|
-
service_uri = dell_data["DellLicenseManagementService"]["@odata.id"]
|
|
229
|
-
debug "Found license service URI: #{service_uri}", 2
|
|
230
|
-
|
|
231
|
-
service_response = authenticated_request(:get, service_uri)
|
|
232
|
-
if service_response.status == 200
|
|
233
|
-
return handle_dell_license_service_response(JSON.parse(service_response.body))
|
|
81
|
+
|
|
82
|
+
# Try manager entity OEM data
|
|
83
|
+
if (data = safe_get("/redfish/v1/Managers/iDRAC.Embedded.1"))
|
|
84
|
+
if (service_uri = data.dig("Oem", "Dell", "DellLicenseManagementService", "@odata.id"))
|
|
85
|
+
if (svc_data = safe_get(service_uri)) && svc_data["Members"]&.any?
|
|
86
|
+
if (details = safe_get(svc_data["Members"][0]["@odata.id"]))
|
|
87
|
+
return {
|
|
88
|
+
"Id" => details["EntitlementID"] || "iDRAC-License",
|
|
89
|
+
"Description" => details["LicenseDescription"] || "iDRAC License",
|
|
90
|
+
"Name" => details["LicenseDescription"] || "iDRAC License",
|
|
91
|
+
"LicenseType" => details["LicenseType"] || license_type_from(details["LicenseDescription"]),
|
|
92
|
+
"Status" => { "Health" => "OK" },
|
|
93
|
+
"Removable" => true
|
|
94
|
+
}
|
|
95
|
+
end
|
|
234
96
|
end
|
|
235
97
|
end
|
|
236
|
-
|
|
237
|
-
|
|
98
|
+
|
|
99
|
+
dell_data = data.dig("Oem", "Dell") || {}
|
|
238
100
|
if dell_data["LicenseType"] || dell_data["License"]
|
|
239
|
-
|
|
240
|
-
(dell_data["License"] && dell_data["License"].include?("Enterprise") ? "Enterprise" :
|
|
241
|
-
dell_data["License"].include?("Express") ? "Express" : "Basic")
|
|
242
|
-
|
|
243
|
-
return {
|
|
244
|
-
"Id" => "iDRAC-License",
|
|
245
|
-
"Description" => "iDRAC8 #{license_type} License",
|
|
246
|
-
"Name" => "iDRAC License",
|
|
247
|
-
"LicenseType" => license_type,
|
|
248
|
-
"Status" => { "Health" => "OK" },
|
|
249
|
-
"Removable" => false
|
|
250
|
-
}
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
# Check for license type in model name or description
|
|
255
|
-
if data["Model"] && data["Model"].include?("Enterprise")
|
|
256
|
-
return {
|
|
257
|
-
"Id" => "iDRAC-License",
|
|
258
|
-
"Description" => "iDRAC8 Enterprise License",
|
|
259
|
-
"Name" => "iDRAC License",
|
|
260
|
-
"LicenseType" => "Enterprise",
|
|
261
|
-
"Status" => { "Health" => "OK" },
|
|
262
|
-
"Removable" => false
|
|
263
|
-
}
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
# If no license info found in manager data, fall back to feature detection
|
|
267
|
-
license_type = determine_license_type()
|
|
268
|
-
return {
|
|
269
|
-
"Id" => "iDRAC-License",
|
|
270
|
-
"Description" => "iDRAC8 #{license_type} License",
|
|
271
|
-
"Name" => "iDRAC License",
|
|
272
|
-
"LicenseType" => license_type,
|
|
273
|
-
"Status" => { "Health" => "OK" },
|
|
274
|
-
"Removable" => false
|
|
275
|
-
}
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
# Get service tag from system info
|
|
279
|
-
def get_service_tag
|
|
280
|
-
response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1")
|
|
281
|
-
if response.status == 200
|
|
282
|
-
data = JSON.parse(response.body)
|
|
283
|
-
return data["SKU"] if data["SKU"] # Service tag is usually in SKU field
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
# Try alternate location
|
|
287
|
-
response = authenticated_request(:get, "/redfish/v1")
|
|
288
|
-
if response.status == 200
|
|
289
|
-
data = JSON.parse(response.body)
|
|
290
|
-
if data["Oem"] && data["Oem"]["Dell"] && data["Oem"]["Dell"]["ServiceTag"]
|
|
291
|
-
return data["Oem"]["Dell"]["ServiceTag"]
|
|
101
|
+
return build_license_hash(license_type_from(dell_data["LicenseType"] || dell_data["License"]))
|
|
292
102
|
end
|
|
293
103
|
end
|
|
294
|
-
|
|
295
|
-
|
|
104
|
+
|
|
105
|
+
# Last resort: detect from features
|
|
106
|
+
build_license_hash(detect_license_type)
|
|
296
107
|
end
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
return "
|
|
301
|
-
|
|
302
|
-
if
|
|
303
|
-
|
|
304
|
-
elsif description.include?("Express")
|
|
305
|
-
return "Express"
|
|
306
|
-
elsif description.include?("Datacenter")
|
|
307
|
-
return "Datacenter"
|
|
308
|
-
else
|
|
309
|
-
return "Basic"
|
|
310
|
-
end
|
|
108
|
+
|
|
109
|
+
def license_type_from(str)
|
|
110
|
+
return "Unknown" unless str
|
|
111
|
+
return "Enterprise" if str.include?("Enterprise")
|
|
112
|
+
return "Datacenter" if str.include?("Datacenter")
|
|
113
|
+
return "Express" if str.include?("Express")
|
|
114
|
+
"Basic"
|
|
311
115
|
end
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
# @return [Hash] A basic license info object
|
|
316
|
-
def create_fallback_license_info(use_basic: false)
|
|
317
|
-
# Get the iDRAC version number from server headers
|
|
318
|
-
version = nil
|
|
319
|
-
response = authenticated_request(:get, "/redfish/v1")
|
|
320
|
-
if response.headers["server"] && response.headers["server"].match(/iDRAC\/(\d+)/i)
|
|
321
|
-
version = response.headers["server"].match(/iDRAC\/(\d+)/i)[1].to_i
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
# Try to determine if it's Enterprise or Express based on available features
|
|
325
|
-
license_type = use_basic ? "Basic" : determine_license_type
|
|
326
|
-
|
|
327
|
-
license_info = {
|
|
116
|
+
|
|
117
|
+
def build_license_hash(type)
|
|
118
|
+
{
|
|
328
119
|
"Id" => "iDRAC-License",
|
|
329
|
-
"Description" =>
|
|
120
|
+
"Description" => "iDRAC #{type} License",
|
|
330
121
|
"Name" => "iDRAC License",
|
|
331
|
-
"LicenseType" =>
|
|
122
|
+
"LicenseType" => type,
|
|
332
123
|
"Status" => { "Health" => "OK" },
|
|
333
124
|
"Removable" => false
|
|
334
125
|
}
|
|
335
|
-
|
|
336
|
-
debug "Created fallback license info: #{license_info}", 2
|
|
337
|
-
license_info
|
|
338
126
|
end
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
begin
|
|
345
|
-
# For example, virtual media is typically an Enterprise feature
|
|
346
|
-
virtual_media_response = authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia")
|
|
347
|
-
# If we successfully get virtual media, it's likely Enterprise
|
|
348
|
-
if virtual_media_response.status == 200
|
|
349
|
-
return "Enterprise"
|
|
350
|
-
end
|
|
351
|
-
rescue
|
|
352
|
-
# If the request fails, don't fail the whole method
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
# Default to basic license if we can't determine
|
|
356
|
-
return "Express"
|
|
127
|
+
|
|
128
|
+
def detect_license_type
|
|
129
|
+
# Virtual media is typically Enterprise-only
|
|
130
|
+
data = safe_get("/redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia")
|
|
131
|
+
data ? "Enterprise" : "Express"
|
|
357
132
|
end
|
|
358
133
|
end
|
|
359
|
-
end
|
|
134
|
+
end
|
data/lib/idrac/version.rb
CHANGED