idrac 0.3.3 → 0.4.5
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/bin/idrac +34 -34
- data/idrac.gemspec +1 -0
- data/lib/idrac/storage.rb +33 -27
- data/lib/idrac/system.rb +33 -26
- data/lib/idrac/version.rb +1 -1
- data/lib/idrac.rb +1 -0
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffcb1d99822a0e7d0015f018b6967e3977d7506438a3e2d917e0615f281aa0e3
|
4
|
+
data.tar.gz: 188a912ccdcdb5712ead6b5f181d59902f9b50718e3c3e39e2949f6fbc7ad606
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dfd1714f7a86b37991a7493be186043be14a400f6e36d7712c366c1007857eee7eb4ece8390187a56f7faa921f46ffdf9ad1250ff471daf3ad2ccd884c14cda2
|
7
|
+
data.tar.gz: 20d5a051050da7a5b75d08529d16e2806af72ac05161393dd1a5cca509f17b2ec497f7a9b2f9c3f0933af72394b81696ae88b48736b6de67bd8ab7ae43319b25
|
data/bin/idrac
CHANGED
@@ -681,22 +681,22 @@ module IDRAC
|
|
681
681
|
|
682
682
|
puts "\nVirtual Disks (#{volumes.size}):".green.bold
|
683
683
|
volumes.each do |volume|
|
684
|
-
capacity_gb = volume
|
685
|
-
health_color = volume
|
684
|
+
capacity_gb = volume.capacity_bytes.to_f / (1024**3)
|
685
|
+
health_color = volume.health == "OK" ? :green : :yellow
|
686
686
|
|
687
|
-
puts "#{volume
|
688
|
-
puts " RAID Type: #{volume
|
689
|
-
puts " Health: #{volume
|
687
|
+
puts "#{volume.name}:".bold
|
688
|
+
puts " RAID Type: #{volume.raid_level || volume.volume_type}".cyan
|
689
|
+
puts " Health: #{volume.health.send(health_color)}"
|
690
690
|
puts " Capacity: #{capacity_gb.round(2)} GB".cyan
|
691
|
-
puts " Stripe Size: #{volume
|
692
|
-
puts " Read Cache: #{volume
|
693
|
-
puts " Write Cache: #{volume
|
694
|
-
puts " FastPath: #{volume
|
695
|
-
puts " Encrypted: #{volume
|
691
|
+
puts " Stripe Size: #{volume.stripe_size}".cyan
|
692
|
+
puts " Read Cache: #{volume.read_cache_policy}".cyan
|
693
|
+
puts " Write Cache: #{volume.write_cache_policy}".cyan
|
694
|
+
puts " FastPath: #{volume.fastpath == 'enabled' ? 'Enabled'.green : 'Disabled'.yellow}"
|
695
|
+
puts " Encrypted: #{volume.encrypted ? 'Yes'.green : 'No'.yellow}" if volume.encrypted != nil
|
696
696
|
|
697
|
-
if volume
|
698
|
-
puts " Progress: #{volume
|
699
|
-
puts " Operation: #{volume
|
697
|
+
if volume.progress
|
698
|
+
puts " Progress: #{volume.progress}%".cyan
|
699
|
+
puts " Operation: #{volume.message}".cyan
|
700
700
|
end
|
701
701
|
puts ""
|
702
702
|
end
|
@@ -742,7 +742,7 @@ module IDRAC
|
|
742
742
|
|
743
743
|
puts "Available volumes:".green
|
744
744
|
volumes.each_with_index do |vol, idx|
|
745
|
-
puts "#{idx+1}. #{vol
|
745
|
+
puts "#{idx+1}. #{vol.name} (#{vol.raid_level || vol.volume_type}, #{(vol.capacity_bytes.to_f / (1024**3)).round(2)} GB)"
|
746
746
|
end
|
747
747
|
|
748
748
|
print "Enter the number of the volume to delete (or 'q' to quit): "
|
@@ -757,12 +757,12 @@ module IDRAC
|
|
757
757
|
if index >= 0 && index < volumes.size
|
758
758
|
volume = volumes[index]
|
759
759
|
|
760
|
-
puts "You are about to delete '#{volume
|
760
|
+
puts "You are about to delete '#{volume.name}'. All data will be lost!".red.bold
|
761
761
|
print "Type the volume name to confirm deletion: "
|
762
762
|
confirm = $stdin.gets.chomp
|
763
763
|
|
764
764
|
if confirm == volume[:name]
|
765
|
-
client.delete_volume(volume
|
765
|
+
client.delete_volume(volume.data_id)
|
766
766
|
puts "Volume deleted successfully".green
|
767
767
|
else
|
768
768
|
puts "Volume name did not match. Operation cancelled".yellow
|
@@ -846,15 +846,15 @@ module IDRAC
|
|
846
846
|
|
847
847
|
puts "\nMemory Modules (#{memory.size}):".green.bold
|
848
848
|
memory.each do |dimm|
|
849
|
-
capacity_gb = dimm
|
850
|
-
health_color = dimm
|
849
|
+
capacity_gb = dimm.capacity_bytes.to_f / (1024**3)
|
850
|
+
health_color = dimm.health == "OK" ? :green : :red
|
851
851
|
|
852
|
-
puts "#{dimm
|
853
|
-
puts " Model: #{dimm
|
854
|
-
puts " Health: #{dimm
|
852
|
+
puts "#{dimm.name}:".bold
|
853
|
+
puts " Model: #{dimm.model}".cyan
|
854
|
+
puts " Health: #{dimm.health.send(health_color)}"
|
855
855
|
puts " Capacity: #{capacity_gb.round(2)} GB".cyan
|
856
|
-
puts " Speed: #{dimm
|
857
|
-
puts " Serial: #{dimm
|
856
|
+
puts " Speed: #{dimm.speed_mhz} MHz".cyan
|
857
|
+
puts " Serial: #{dimm.serial}".cyan
|
858
858
|
puts ""
|
859
859
|
end
|
860
860
|
|
@@ -871,14 +871,14 @@ module IDRAC
|
|
871
871
|
|
872
872
|
puts "\nPower Supplies (#{psus.size}):".green.bold
|
873
873
|
psus.each do |psu|
|
874
|
-
health_color = psu
|
874
|
+
health_color = psu.status == "OK" ? :green : :red
|
875
875
|
|
876
|
-
puts "#{psu
|
877
|
-
puts " Model: #{psu
|
878
|
-
puts " Health: #{psu
|
879
|
-
puts " Input: #{psu
|
880
|
-
puts " Output: #{psu
|
881
|
-
puts " Serial: #{psu
|
876
|
+
puts "#{psu.name}:".bold
|
877
|
+
puts " Model: #{psu.model}".cyan
|
878
|
+
puts " Health: #{psu.status.send(health_color)}"
|
879
|
+
puts " Input: #{psu.voltage} V (#{psu.voltage_human})".cyan
|
880
|
+
puts " Output: #{psu.watts} W".cyan
|
881
|
+
puts " Serial: #{psu.serial}".cyan
|
882
882
|
puts ""
|
883
883
|
end
|
884
884
|
end
|
@@ -897,11 +897,11 @@ module IDRAC
|
|
897
897
|
|
898
898
|
puts "\nFans (#{fans.size}):".green.bold
|
899
899
|
fans.each do |fan|
|
900
|
-
health_color = fan
|
900
|
+
health_color = fan.status == "OK" ? :green : :red
|
901
901
|
|
902
|
-
puts "#{fan
|
903
|
-
puts " Health: #{fan
|
904
|
-
puts " Speed: #{fan
|
902
|
+
puts "#{fan.name}:".bold
|
903
|
+
puts " Health: #{fan.status.send(health_color)}"
|
904
|
+
puts " Speed: #{fan.rpm} RPM".cyan
|
905
905
|
puts ""
|
906
906
|
end
|
907
907
|
end
|
data/idrac.gemspec
CHANGED
@@ -41,6 +41,7 @@ Gem::Specification.new do |spec|
|
|
41
41
|
spec.add_dependency "thor", ">= 1.2.0", "< 1.4.0"
|
42
42
|
spec.add_dependency "base64", "~> 0.1", ">= 0.1.0"
|
43
43
|
spec.add_dependency "colorize", "~> 1.1"
|
44
|
+
spec.add_dependency "recursive-open-struct", "~> 1.1"
|
44
45
|
|
45
46
|
# Development dependencies
|
46
47
|
spec.add_development_dependency "bundler", "~> 2.4", ">= 2.4.0"
|
data/lib/idrac/storage.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'colorize'
|
3
|
+
require 'recursive-open-struct'
|
3
4
|
|
4
5
|
module IDRAC
|
5
6
|
module Storage
|
@@ -9,24 +10,24 @@ module IDRAC
|
|
9
10
|
controller_list = controllers
|
10
11
|
|
11
12
|
puts "Controllers".green
|
12
|
-
controller_list.each { |c| puts "#{c
|
13
|
+
controller_list.each { |c| puts "#{c.name} > #{c.drives_count}" }
|
13
14
|
|
14
15
|
puts "Drives".green
|
15
16
|
controller_list.each do |c|
|
16
|
-
puts "Storage: #{c
|
17
|
+
puts "Storage: #{c.name} > #{c.status} > #{c.drives_count}"
|
17
18
|
end
|
18
19
|
|
19
20
|
# Find the controller with the most drives (usually the PERC)
|
20
|
-
controller_info = controller_list.max_by { |c| c
|
21
|
+
controller_info = controller_list.max_by { |c| c.drives_count }
|
21
22
|
|
22
|
-
if controller_info
|
23
|
-
puts "Found #{controller_info
|
23
|
+
if controller_info.name =~ /PERC/
|
24
|
+
puts "Found #{controller_info.name}".green
|
24
25
|
else
|
25
|
-
puts "Found #{controller_info
|
26
|
+
puts "Found #{controller_info.name} but continuing...".yellow
|
26
27
|
end
|
27
28
|
|
28
29
|
# Return the raw controller data
|
29
|
-
controller_info
|
30
|
+
controller_info.raw
|
30
31
|
end
|
31
32
|
|
32
33
|
# Get all storage controllers and return them as an array
|
@@ -37,9 +38,9 @@ module IDRAC
|
|
37
38
|
begin
|
38
39
|
data = JSON.parse(response.body)
|
39
40
|
|
40
|
-
# Transform and return all controllers as an array of
|
41
|
+
# Transform and return all controllers as an array of RecursiveOpenStruct objects with consistent keys
|
41
42
|
controllers = data["Members"].map do |controller|
|
42
|
-
{
|
43
|
+
controller_data = {
|
43
44
|
name: controller["Name"],
|
44
45
|
model: controller["Model"],
|
45
46
|
drives_count: controller["Drives"].size,
|
@@ -51,9 +52,11 @@ module IDRAC
|
|
51
52
|
pci_slot: controller.dig("Oem", "Dell", "DellController", "PCISlot"),
|
52
53
|
raw: controller
|
53
54
|
}
|
55
|
+
|
56
|
+
RecursiveOpenStruct.new(controller_data, recurse_over_arrays: true)
|
54
57
|
end
|
55
58
|
|
56
|
-
return controllers.sort_by { |c| c
|
59
|
+
return controllers.sort_by { |c| c.name }
|
57
60
|
rescue JSON::ParserError
|
58
61
|
raise Error, "Failed to parse controllers response: #{response.body}"
|
59
62
|
end
|
@@ -87,7 +90,7 @@ module IDRAC
|
|
87
90
|
drives = data["Drives"].map do |body|
|
88
91
|
serial = body["SerialNumber"]
|
89
92
|
serial = body["Identifiers"].first["DurableName"] if serial.blank?
|
90
|
-
{
|
93
|
+
drive_data = {
|
91
94
|
serial: serial,
|
92
95
|
model: body["Model"],
|
93
96
|
name: body["Name"],
|
@@ -105,9 +108,11 @@ module IDRAC
|
|
105
108
|
encryption_ability: body["EncryptionAbility"],
|
106
109
|
"@odata.id": body["@odata.id"]
|
107
110
|
}
|
111
|
+
|
112
|
+
RecursiveOpenStruct.new(drive_data, recurse_over_arrays: true)
|
108
113
|
end
|
109
114
|
|
110
|
-
return drives.sort_by { |d| d
|
115
|
+
return drives.sort_by { |d| d.name }
|
111
116
|
rescue JSON::ParserError
|
112
117
|
raise Error, "Failed to parse drives response: #{response.body}"
|
113
118
|
end
|
@@ -131,7 +136,7 @@ module IDRAC
|
|
131
136
|
data = JSON.parse(response.body)
|
132
137
|
volumes = data["Members"].map do |vol|
|
133
138
|
drives = vol["Links"]["Drives"]
|
134
|
-
|
139
|
+
volume_data = {
|
135
140
|
name: vol["Name"],
|
136
141
|
capacity_bytes: vol["CapacityBytes"],
|
137
142
|
volume_type: vol["VolumeType"],
|
@@ -142,31 +147,32 @@ module IDRAC
|
|
142
147
|
raid_level: vol["RAIDType"],
|
143
148
|
encrypted: vol["Encrypted"],
|
144
149
|
lock_status: vol.dig("Oem", "Dell", "DellVirtualDisk", "LockStatus"),
|
145
|
-
|
150
|
+
odata_id: vol["@odata.id"]
|
146
151
|
}
|
147
152
|
|
148
153
|
# Check FastPath settings
|
149
|
-
|
154
|
+
volume_data[:fastpath] = fastpath_good?(vol)
|
150
155
|
|
151
156
|
# Handle volume operations and status
|
152
157
|
if vol["Operations"].any?
|
153
|
-
|
154
|
-
|
155
|
-
|
158
|
+
volume_data[:health] = vol["Status"]["Health"] ? vol["Status"]["Health"] : "N/A"
|
159
|
+
volume_data[:progress] = vol["Operations"].first["PercentageComplete"]
|
160
|
+
volume_data[:message] = vol["Operations"].first["OperationName"]
|
156
161
|
elsif vol["Status"]["Health"] == "OK"
|
157
|
-
|
158
|
-
|
159
|
-
|
162
|
+
volume_data[:health] = "OK"
|
163
|
+
volume_data[:progress] = nil
|
164
|
+
volume_data[:message] = nil
|
160
165
|
else
|
161
|
-
|
162
|
-
|
163
|
-
|
166
|
+
volume_data[:health] = "?"
|
167
|
+
volume_data[:progress] = nil
|
168
|
+
volume_data[:message] = nil
|
164
169
|
end
|
165
170
|
|
166
|
-
|
171
|
+
# Create the RecursiveOpenStruct after all properties are set
|
172
|
+
RecursiveOpenStruct.new(volume_data, recurse_over_arrays: true)
|
167
173
|
end
|
168
174
|
|
169
|
-
return volumes.sort_by { |d| d
|
175
|
+
return volumes.sort_by { |d| d.name }
|
170
176
|
rescue JSON::ParserError
|
171
177
|
raise Error, "Failed to parse volumes response: #{response.body}"
|
172
178
|
end
|
@@ -360,7 +366,7 @@ module IDRAC
|
|
360
366
|
|
361
367
|
# Check if all physical disks are Self-Encrypting Drives
|
362
368
|
def all_seds?(drives)
|
363
|
-
drives.all? { |d| d
|
369
|
+
drives.all? { |d| d.encryption_ability == "SelfEncryptingDrive" }
|
364
370
|
end
|
365
371
|
|
366
372
|
# Check if the system is ready for SED operations
|
data/lib/idrac/system.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'colorize'
|
3
|
+
require 'recursive-open-struct'
|
3
4
|
|
4
5
|
module IDRAC
|
5
6
|
module System
|
@@ -16,20 +17,22 @@ module IDRAC
|
|
16
17
|
|
17
18
|
puts "DIMM: #{m["Model"]} #{m["Name"]} > #{m["CapacityMiB"]}MiB > #{m["Status"]["Health"]} > #{m["OperatingSpeedMhz"]}MHz > #{m["PartNumber"]} / #{m["SerialNumber"]}"
|
18
19
|
|
19
|
-
{
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
memory_data = {
|
21
|
+
model: m["Model"],
|
22
|
+
name: m["Name"],
|
23
|
+
capacity_bytes: m["CapacityMiB"].to_i.megabyte,
|
24
|
+
health: m["Status"]["Health"] ? m["Status"]["Health"] : "N/A",
|
25
|
+
speed_mhz: m["OperatingSpeedMhz"],
|
26
|
+
part_number: m["PartNumber"],
|
27
|
+
serial: m["SerialNumber"],
|
28
|
+
bank: bank,
|
29
|
+
index: index.to_i
|
29
30
|
}
|
31
|
+
|
32
|
+
RecursiveOpenStruct.new(memory_data, recurse_over_arrays: true)
|
30
33
|
end
|
31
34
|
|
32
|
-
return memory.sort_by { |
|
35
|
+
return memory.sort_by { |m| [m.bank || "Z", m.index || 999] }
|
33
36
|
rescue JSON::ParserError
|
34
37
|
raise Error, "Failed to parse memory response: #{response.body}"
|
35
38
|
end
|
@@ -49,16 +52,18 @@ module IDRAC
|
|
49
52
|
|
50
53
|
psus = data["PowerSupplies"].map do |psu|
|
51
54
|
puts "PSU: #{psu["Name"]} > #{psu["PowerInputWatts"]}W > #{psu["Status"]["Health"]}"
|
52
|
-
{
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
55
|
+
psu_data = {
|
56
|
+
name: psu["Name"],
|
57
|
+
voltage: psu["LineInputVoltage"],
|
58
|
+
voltage_human: psu["LineInputVoltageType"], # AC240V
|
59
|
+
watts: psu["PowerInputWatts"],
|
60
|
+
part: psu["PartNumber"],
|
61
|
+
model: psu["Model"],
|
62
|
+
serial: psu["SerialNumber"],
|
63
|
+
status: psu["Status"]["Health"],
|
61
64
|
}
|
65
|
+
|
66
|
+
RecursiveOpenStruct.new(psu_data, recurse_over_arrays: true)
|
62
67
|
end
|
63
68
|
|
64
69
|
return psus
|
@@ -84,12 +89,14 @@ module IDRAC
|
|
84
89
|
|
85
90
|
fans = data["Fans"].map do |fan|
|
86
91
|
puts "Fan: #{fan["Name"]} > #{fan["Reading"]} > #{fan["Status"]["Health"]}"
|
87
|
-
{
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
+
fan_data = {
|
93
|
+
name: fan["Name"],
|
94
|
+
rpm: fan["Reading"],
|
95
|
+
serial: fan["SerialNumber"],
|
96
|
+
status: fan["Status"]["Health"]
|
92
97
|
}
|
98
|
+
|
99
|
+
RecursiveOpenStruct.new(fan_data, recurse_over_arrays: true)
|
93
100
|
end
|
94
101
|
|
95
102
|
return fans
|
@@ -376,7 +383,7 @@ module IDRAC
|
|
376
383
|
|
377
384
|
# Get total memory in human-readable format
|
378
385
|
def total_memory_human(memory_data)
|
379
|
-
total_memory = memory_data.sum { |m| m
|
386
|
+
total_memory = memory_data.sum { |m| m.capacity_bytes }
|
380
387
|
"%0.2f GB" % (total_memory.to_f / 1.gigabyte)
|
381
388
|
end
|
382
389
|
end
|
data/lib/idrac/version.rb
CHANGED
data/lib/idrac.rb
CHANGED
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.
|
4
|
+
version: 0.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Siegel
|
@@ -144,6 +144,20 @@ dependencies:
|
|
144
144
|
- - "~>"
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '1.1'
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: recursive-open-struct
|
149
|
+
requirement: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - "~>"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '1.1'
|
154
|
+
type: :runtime
|
155
|
+
prerelease: false
|
156
|
+
version_requirements: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - "~>"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '1.1'
|
147
161
|
- !ruby/object:Gem::Dependency
|
148
162
|
name: bundler
|
149
163
|
requirement: !ruby/object:Gem::Requirement
|