radfish 0.1.6 → 0.2.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 +4 -4
- data/README.md +5 -2
- data/lib/radfish/cli.rb +62 -15
- data/lib/radfish/client.rb +36 -1
- data/lib/radfish/controller.rb +34 -0
- data/lib/radfish/core/storage.rb +5 -5
- data/lib/radfish/system_info.rb +2 -2
- data/lib/radfish/version.rb +2 -2
- data/lib/radfish.rb +2 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b04f4c83ffefc35a7faaa8793ca8c7fdc6c9eea300d1f9d21ae9b0e3a1cc93a
|
4
|
+
data.tar.gz: 4dcf1830e6510676f6b45014b339a5767a6de9ba73d444d107adb31a87e255a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9b99bdc943bf4915c6f2b94ee1e37ae04e368e71f8f022ece2322b47c890bd4532b54dd9401ce2b71a9f3d678c2b04c5704c136328f27225403b90af715110a
|
7
|
+
data.tar.gz: 22be0c17c6b71173d7e01ccdbbe049375035a98909cb76639d8a1ef414507847ca780d95f36df23556a9b924cba3519a6b2d531efa82d076252a5e3ac48da2f5
|
data/README.md
CHANGED
@@ -129,7 +129,9 @@ radfish system [OPTIONS] # Display system information
|
|
129
129
|
radfish cpus [OPTIONS] # List CPUs
|
130
130
|
radfish memory [OPTIONS] # List memory modules
|
131
131
|
radfish nics [OPTIONS] # List network interfaces
|
132
|
-
radfish
|
132
|
+
radfish storage controllers # List storage controllers
|
133
|
+
radfish storage drives # List drives across controllers
|
134
|
+
radfish storage volumes # List volumes across controllers
|
133
135
|
radfish psus [OPTIONS] # List power supplies
|
134
136
|
```
|
135
137
|
|
@@ -361,7 +363,8 @@ info = client.system_info
|
|
361
363
|
client.cpus # CPU information
|
362
364
|
client.memory # Memory DIMMs
|
363
365
|
client.nics # Network interfaces
|
364
|
-
client.drives
|
366
|
+
client.controllers.each { |c| c.drives } # Physical drives (per controller)
|
367
|
+
client.controllers.each { |c| c.volumes } # RAID volumes (per controller)
|
365
368
|
client.psus # Power supplies
|
366
369
|
```
|
367
370
|
|
data/lib/radfish/cli.rb
CHANGED
@@ -342,32 +342,76 @@ module Radfish
|
|
342
342
|
data = client.storage_summary
|
343
343
|
output_result(data, nil) if options[:json]
|
344
344
|
when 'controllers'
|
345
|
-
|
346
|
-
|
347
|
-
|
345
|
+
ctrls = client.controllers
|
346
|
+
if options[:json]
|
347
|
+
puts JSON.pretty_generate(ctrls.map(&:to_h))
|
348
|
+
else
|
348
349
|
puts "=== Storage Controllers ===".green
|
349
|
-
|
350
|
-
puts "#{ctrl
|
350
|
+
ctrls.each do |ctrl|
|
351
|
+
puts "#{ctrl.name || 'Controller'} (#{ctrl.id})".cyan
|
351
352
|
end
|
352
353
|
end
|
353
354
|
when 'drives', 'disks'
|
354
|
-
|
355
|
+
# Get all drives from all controllers
|
356
|
+
controllers = client.controllers
|
357
|
+
all_drives = []
|
358
|
+
|
359
|
+
controllers.each do |controller|
|
360
|
+
begin
|
361
|
+
drives = controller.drives
|
362
|
+
all_drives.concat(drives) if drives
|
363
|
+
rescue => e
|
364
|
+
ctrl_name = controller.respond_to?(:name) ? controller.name : 'controller'
|
365
|
+
puts "Error fetching drives for #{ctrl_name}: #{e.message}".yellow if options[:verbose]
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
355
369
|
if options[:json]
|
356
|
-
puts JSON.pretty_generate(
|
370
|
+
puts JSON.pretty_generate(all_drives)
|
357
371
|
else
|
358
372
|
puts "=== Physical Drives ===".green
|
359
|
-
|
360
|
-
puts "
|
373
|
+
if all_drives.empty?
|
374
|
+
puts "No drives found".yellow
|
375
|
+
else
|
376
|
+
all_drives.each do |drive|
|
377
|
+
cert_status = drive['certified'] || drive.certified rescue nil
|
378
|
+
cert_info = cert_status ? " [Certified: #{cert_status}]" : ""
|
379
|
+
capacity = drive['capacity_gb'] || drive.capacity_gb rescue "Unknown"
|
380
|
+
status = drive['status'] || drive.status rescue "Unknown"
|
381
|
+
name = drive['name'] || drive.name rescue "Unknown"
|
382
|
+
puts "#{name}: #{capacity} GB - #{status}#{cert_info}".cyan
|
383
|
+
end
|
361
384
|
end
|
362
385
|
end
|
363
386
|
when 'volumes', 'raids'
|
364
|
-
|
387
|
+
# Get all volumes from all controllers
|
388
|
+
controllers = client.controllers
|
389
|
+
all_volumes = []
|
390
|
+
|
391
|
+
controllers.each do |controller|
|
392
|
+
begin
|
393
|
+
volumes = controller.volumes
|
394
|
+
all_volumes.concat(volumes) if volumes
|
395
|
+
rescue => e
|
396
|
+
ctrl_name = controller.respond_to?(:name) ? controller.name : 'controller'
|
397
|
+
puts "Error fetching volumes for #{ctrl_name}: #{e.message}".yellow if options[:verbose]
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
365
401
|
if options[:json]
|
366
|
-
puts JSON.pretty_generate(
|
402
|
+
puts JSON.pretty_generate(all_volumes)
|
367
403
|
else
|
368
404
|
puts "=== Volumes ===".green
|
369
|
-
|
370
|
-
puts "
|
405
|
+
if all_volumes.empty?
|
406
|
+
puts "No volumes found".yellow
|
407
|
+
else
|
408
|
+
all_volumes.each do |vol|
|
409
|
+
name = vol['name'] || vol.name rescue "Unknown"
|
410
|
+
capacity = vol['capacity_gb'] || vol.capacity_gb rescue "Unknown"
|
411
|
+
raid_type = vol['raid_type'] || vol.raid_type rescue "Unknown"
|
412
|
+
status = vol['status'] || vol.status rescue "Unknown"
|
413
|
+
puts "#{name}: #{capacity} GB - #{raid_type} (Status: #{status})".cyan
|
414
|
+
end
|
371
415
|
end
|
372
416
|
end
|
373
417
|
else
|
@@ -795,7 +839,10 @@ module Radfish
|
|
795
839
|
puts "\n=== Power Supplies ===".green
|
796
840
|
data.each do |psu|
|
797
841
|
status_color = psu['status'] == 'OK' ? :green : :red
|
798
|
-
|
842
|
+
voltage_info = psu['voltage'] ? "#{psu['voltage']}V (#{psu['voltage_human'] || 'Unknown'})" : ""
|
843
|
+
puts "#{psu['name']}: #{voltage_info} #{psu['watts']}W - #{psu['status']}".send(status_color)
|
844
|
+
puts " Model: #{psu['model']}" if psu['model']
|
845
|
+
puts " Serial: #{psu['serial']}" if psu['serial']
|
799
846
|
end
|
800
847
|
end
|
801
848
|
end
|
@@ -821,4 +868,4 @@ module Radfish
|
|
821
868
|
end
|
822
869
|
end
|
823
870
|
end
|
824
|
-
end
|
871
|
+
end
|
data/lib/radfish/client.rb
CHANGED
@@ -165,5 +165,40 @@ module Radfish
|
|
165
165
|
base_url: @adapter.base_url
|
166
166
|
}
|
167
167
|
end
|
168
|
+
|
169
|
+
# Storage convenience API
|
170
|
+
# Return normalized Controller objects while keeping adapter APIs intact.
|
171
|
+
def controllers
|
172
|
+
raw = @adapter.storage_controllers
|
173
|
+
Array(raw).map { |c| build_controller(c) }
|
174
|
+
end
|
175
|
+
|
176
|
+
# Public storage API (not backward-compatible): require a Controller object.
|
177
|
+
def drives(controller)
|
178
|
+
raise ArgumentError, "Controller required" unless controller.is_a?(Controller)
|
179
|
+
@adapter.drives(controller)
|
180
|
+
end
|
181
|
+
|
182
|
+
def volumes(controller)
|
183
|
+
raise ArgumentError, "Controller required" unless controller.is_a?(Controller)
|
184
|
+
@adapter.volumes(controller)
|
185
|
+
end
|
186
|
+
|
187
|
+
private
|
188
|
+
|
189
|
+
def build_controller(raw)
|
190
|
+
# Only extract friendly name/id if plainly available; keep raw in adapter_data
|
191
|
+
id = if raw.respond_to?(:[])
|
192
|
+
raw['id'] || raw[:id]
|
193
|
+
elsif raw.respond_to?(:id)
|
194
|
+
raw.id
|
195
|
+
end
|
196
|
+
name = if raw.respond_to?(:[])
|
197
|
+
raw['name'] || raw[:name]
|
198
|
+
elsif raw.respond_to?(:name)
|
199
|
+
raw.name
|
200
|
+
end
|
201
|
+
Controller.new(client: self, id: id, name: name, vendor: @vendor, adapter_data: raw)
|
202
|
+
end
|
168
203
|
end
|
169
|
-
end
|
204
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Radfish
|
4
|
+
# Lightweight value object representing a storage controller.
|
5
|
+
# Holds a stable identifier and optional name.
|
6
|
+
class Controller
|
7
|
+
attr_reader :id, :name, :vendor, :adapter_data
|
8
|
+
|
9
|
+
def initialize(client:, id:, name: nil, vendor: nil, adapter_data: nil)
|
10
|
+
@client = client
|
11
|
+
@id = id
|
12
|
+
@name = name
|
13
|
+
@vendor = vendor
|
14
|
+
@adapter_data = adapter_data
|
15
|
+
end
|
16
|
+
|
17
|
+
# Convenience accessors delegate to the client wrappers
|
18
|
+
def drives
|
19
|
+
@client.drives(self)
|
20
|
+
end
|
21
|
+
|
22
|
+
def volumes
|
23
|
+
@client.volumes(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
{ id: id, name: name, vendor: vendor }
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(other)
|
31
|
+
other.is_a?(Controller) && other.id == id && other.vendor.to_s == vendor.to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/radfish/core/storage.rb
CHANGED
@@ -7,12 +7,12 @@ module Radfish
|
|
7
7
|
raise NotImplementedError, "Adapter must implement #storage_controllers"
|
8
8
|
end
|
9
9
|
|
10
|
-
def drives
|
11
|
-
raise NotImplementedError, "Adapter must implement #drives"
|
10
|
+
def drives(controller)
|
11
|
+
raise NotImplementedError, "Adapter must implement #drives(controller)"
|
12
12
|
end
|
13
13
|
|
14
|
-
def volumes
|
15
|
-
raise NotImplementedError, "Adapter must implement #volumes"
|
14
|
+
def volumes(controller)
|
15
|
+
raise NotImplementedError, "Adapter must implement #volumes(controller)"
|
16
16
|
end
|
17
17
|
|
18
18
|
def storage_summary
|
@@ -20,4 +20,4 @@ module Radfish
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
|
-
end
|
23
|
+
end
|
data/lib/radfish/system_info.rb
CHANGED
@@ -62,7 +62,7 @@ module Radfish
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def controllers
|
65
|
-
@cache[:controllers] ||= @client.
|
65
|
+
@cache[:controllers] ||= @client.controllers
|
66
66
|
end
|
67
67
|
|
68
68
|
private
|
@@ -71,4 +71,4 @@ module Radfish
|
|
71
71
|
@cache[:system_info] ||= @client.adapter.system_info
|
72
72
|
end
|
73
73
|
end
|
74
|
-
end
|
74
|
+
end
|
data/lib/radfish/version.rb
CHANGED
data/lib/radfish.rb
CHANGED
@@ -92,6 +92,7 @@ require_relative 'radfish/bmc_info'
|
|
92
92
|
require_relative 'radfish/power_info'
|
93
93
|
require_relative 'radfish/thermal_info'
|
94
94
|
require_relative 'radfish/pci_info'
|
95
|
+
require_relative 'radfish/controller'
|
95
96
|
require_relative 'radfish/client'
|
96
97
|
|
97
98
|
# Auto-load adapters if available
|
@@ -105,4 +106,4 @@ begin
|
|
105
106
|
require 'radfish/supermicro_adapter'
|
106
107
|
rescue LoadError
|
107
108
|
# radfish-supermicro gem not installed
|
108
|
-
end
|
109
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: radfish
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Siegel
|
@@ -169,6 +169,7 @@ files:
|
|
169
169
|
- lib/radfish/cli.rb
|
170
170
|
- lib/radfish/cli/base.rb
|
171
171
|
- lib/radfish/client.rb
|
172
|
+
- lib/radfish/controller.rb
|
172
173
|
- lib/radfish/core/base_client.rb
|
173
174
|
- lib/radfish/core/boot.rb
|
174
175
|
- lib/radfish/core/jobs.rb
|