radfish 0.2.9 → 0.2.12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3eb7e0fad9f1c58627bb67908c36b48ee6345502dd697d060bfb2a2269168779
4
- data.tar.gz: 1d0773d739fc075885f9c49abaf719394695af6e7120c2d42b0478638f78d0f7
3
+ metadata.gz: 56ac8a4bd0fa74d4925bd369825c0d7df1b87e77acea9a41d1327461a058e2e4
4
+ data.tar.gz: 5089df7444609d31fd193e8d6c022640ec57cbda96baf26c1df920eeb17bc3ab
5
5
  SHA512:
6
- metadata.gz: 86cb61d2ce44dc0443bd41236074670645e8f16b8d6daa316b54159a6ebcacdf60184cc29ccbbce10747cd878a38b596703b631b2ef8b7e7fa8f922718928ed5
7
- data.tar.gz: ee102d72d959c36cf16f997ebf8bacb9ae8ed6811b68fc6a08961510f85565e46ec132f42bd6d58da5b06af0acfb12fa543b9e3178abc1e86b69bfde01a582b9
6
+ metadata.gz: 10cdabeb27695b1a66aeb6531fa83da737b2a66e9f6ab24505a870797968ec5de49a388299627a954f1641e45ef356182535dcd7e4916bb2e8469b447c1d7dc4
7
+ data.tar.gz: bb95d3be33e59529b53231948763f60803f637353a707395cbc674aa898932696868dae481108fc64545055ed26072a7fda308c948214b770635618ab850b8dc
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Radfish
4
+ # Boot configuration facade. Reached as +client.boot+.
5
+ #
6
+ # The vendor-neutral entry point for the boot mechanics that used to be hand-rolled in raw
7
+ # Redfish by callers (reading BootSources, disabling stale UEFI placeholders, scheduling the
8
+ # config job). The heavy lifting lives in the adapter; this object just exposes it cleanly and
9
+ # keeps +to_h+ pointing at the underlying boot configuration for backward compatibility.
10
+ class BootInfo
11
+ attr_reader :client
12
+
13
+ def initialize(client)
14
+ @client = client
15
+ end
16
+
17
+ # The still-enabled stale UEFI boot placeholders (Dell: "Unknown.Unknown.*"). [] when the
18
+ # adapter has nothing to report. Pass +match:+ to target a different set of entries.
19
+ def stale_uefi_entries(match: nil)
20
+ require_adapter!(:stale_uefi_boot_entries)
21
+ match ? adapter.stale_uefi_boot_entries(match: match) : adapter.stale_uefi_boot_entries
22
+ end
23
+
24
+ # Disable the matched UEFI boot entries via a config job and return the names disabled.
25
+ # With no +match:+ the adapter's default (the stale placeholders) applies. The adapter drains
26
+ # any pending LC config job first, so this never trips LC068.
27
+ def disable_entries(match: nil, **opts)
28
+ require_adapter!(:disable_boot_entries)
29
+ match ? adapter.disable_boot_entries(match: match, **opts) : adapter.disable_boot_entries(**opts)
30
+ end
31
+
32
+ # Underlying boot configuration hash (BootSourceOverride*, boot order, ...).
33
+ def to_h
34
+ adapter.boot_config
35
+ end
36
+ alias config to_h
37
+
38
+ private
39
+
40
+ def adapter
41
+ @client.adapter
42
+ end
43
+
44
+ def require_adapter!(method)
45
+ return if adapter.respond_to?(method)
46
+
47
+ raise NotImplementedError, "#{@client.vendor_name} adapter does not support ##{method}"
48
+ end
49
+ end
50
+ end
data/lib/radfish/cli.rb CHANGED
@@ -340,7 +340,15 @@ module Radfish
340
340
  case subcommand
341
341
  when 'summary', 'all'
342
342
  data = client.storage_summary
343
- output_result(data, nil) if options[:json]
343
+ if options[:json]
344
+ puts JSON.pretty_generate(data)
345
+ else
346
+ puts "=== Storage Summary ===".green
347
+ puts "Total Controllers: #{data[:controller_count]}".cyan
348
+ data[:controllers]&.each do |ctrl|
349
+ puts " #{ctrl[:name] || ctrl[:id]}: #{ctrl[:drive_count]} drives, #{ctrl[:volume_count]} volumes".cyan
350
+ end
351
+ end
344
352
  when 'controllers'
345
353
  ctrls = client.controllers
346
354
  if options[:json]
@@ -127,7 +127,67 @@ module Radfish
127
127
  def power
128
128
  @power ||= PowerInfo.new(self)
129
129
  end
130
-
130
+
131
+ # Boot facade: client.boot.stale_uefi_entries / client.boot.disable_entries(match:).
132
+ def boot
133
+ @boot ||= BootInfo.new(self)
134
+ end
135
+
136
+ # Live BMC power state (e.g. "On"/"Off"), read straight from the adapter. Replaces callers
137
+ # reaching through the adapter to the vendor client's own power-state call.
138
+ def power_state
139
+ @adapter.power_status
140
+ end
141
+
142
+ # Canonical Redfish BootProgress order (normalized to snake_case), earliest to latest. Used to
143
+ # decide when a host has reached OR passed a requested state.
144
+ BOOT_PROGRESS_ORDER = %i[
145
+ none
146
+ primary_processor_initialization_started
147
+ bus_initialization_started
148
+ memory_initialization_started
149
+ secondary_processor_initialization_started
150
+ pci_resource_config_started
151
+ system_hardware_initialization_complete
152
+ setup_entered
153
+ os_boot_started
154
+ os_running
155
+ ].freeze
156
+
157
+ # Normalized last BootProgress state (a snake_case symbol), or nil when the BMC omits
158
+ # BootProgress entirely (iDRAC8). nil means "cannot observe", never "not running".
159
+ def boot_progress
160
+ return nil unless @adapter.respond_to?(:boot_progress)
161
+
162
+ @adapter.boot_progress
163
+ end
164
+
165
+ # Wait until the host reaches (or passes) +target+ BootProgress, bounded by +timeout+ or, when
166
+ # not given, the adapter's per-model POST ceiling. Returns the observed state on success, or nil
167
+ # when the BMC does not report BootProgress (nothing to wait on -- the caller uses other signals).
168
+ # Raises Radfish::BootProgressTimeout on a stall.
169
+ def wait_for_boot_progress(target, timeout: nil, poll: 20)
170
+ target = target.to_sym
171
+ ceiling = timeout || (@adapter.respond_to?(:boot_progress_ceiling) ? @adapter.boot_progress_ceiling(target) : 900)
172
+ deadline = Time.now + ceiling
173
+ target_idx = BOOT_PROGRESS_ORDER.index(target)
174
+
175
+ loop do
176
+ state = boot_progress
177
+ return nil if state.nil? # BMC omits BootProgress (iDRAC8): unobservable, not a failure
178
+ return state if state == target
179
+
180
+ state_idx = BOOT_PROGRESS_ORDER.index(state)
181
+ return state if target_idx && state_idx && state_idx >= target_idx
182
+
183
+ if Time.now > deadline
184
+ raise BootProgressTimeout,
185
+ "BootProgress did not reach #{target.inspect} within #{ceiling}s (last: #{state.inspect})"
186
+ end
187
+ sleep poll
188
+ end
189
+ end
190
+
131
191
  def thermal
132
192
  @thermal ||= ThermalInfo.new(self)
133
193
  end
@@ -34,7 +34,16 @@ module Radfish
34
34
  def boot_to_cd
35
35
  raise NotImplementedError, "Adapter must implement #boot_to_cd"
36
36
  end
37
-
37
+
38
+ # Convenience: one-time boot to the virtual CD. Default delegates to the adapter's standard
39
+ # Redfish boot override (boot_to_cd, which defaults to a one-time override). Adapters with a
40
+ # more reliable vendor path (e.g. Dell's SCP ServerBoot) override this. `reboot:` is accepted
41
+ # for signature parity with those overrides; the default does not reboot -- the caller cycles
42
+ # power (the app's install_os! does).
43
+ def set_one_time_cd_boot(reboot: false)
44
+ boot_to_cd
45
+ end
46
+
38
47
  def boot_to_usb
39
48
  raise NotImplementedError, "Adapter must implement #boot_to_usb"
40
49
  end
@@ -124,7 +124,9 @@ module Radfish
124
124
  when /lenovo/i, /thinkserver/i, /thinksystem/i
125
125
  return 'lenovo'
126
126
  when /asrockrack/i, /asrock/i
127
- return 'asrockrack'
127
+ return 'ami'
128
+ when /ami/i, /megarac/i
129
+ return 'ami'
128
130
  end
129
131
  end
130
132
 
@@ -167,7 +169,8 @@ module Radfish
167
169
  return 'hpe' if model.match?(/ilo/i) || description.match?(/ilo/i)
168
170
  return 'supermicro' if model.match?(/supermicro/i) || description.match?(/smc/i)
169
171
  return 'lenovo' if model.match?(/lenovo/i) || description.match?(/xcc/i)
170
- return 'asrockrack' if model.match?(/asrock/i)
172
+ return 'ami' if model.match?(/asrock/i) || description.match?(/asrock/i)
173
+ return 'ami' if description.match?(/bmc/i) && manager_data.dig('Oem', 'Ami')
171
174
  end
172
175
  end
173
176
  end
@@ -199,7 +202,9 @@ module Radfish
199
202
  when /lenovo/i
200
203
  'lenovo'
201
204
  when /asrock/i
202
- 'asrockrack'
205
+ 'ami'
206
+ when /ami/i, /megarac/i
207
+ 'ami'
203
208
  else
204
209
  vendor_string.to_s.downcase
205
210
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Radfish
4
- VERSION = "0.2.9"
4
+ VERSION = "0.2.12"
5
5
  end
data/lib/radfish.rb CHANGED
@@ -30,6 +30,10 @@ module Radfish
30
30
  class TaskTimeoutError < TaskError; end
31
31
  class TaskFailedError < TaskError; end
32
32
 
33
+ # Raised by Client#wait_for_boot_progress when a host does not reach the requested
34
+ # BootProgress state within its (per-model) ceiling.
35
+ class BootProgressTimeout < TimeoutError; end
36
+
33
37
  module Debuggable
34
38
  def debug(message, level = 1, color = :light_cyan)
35
39
  return unless respond_to?(:verbosity) && verbosity >= level
@@ -90,6 +94,7 @@ require_relative 'radfish/vendor_detector'
90
94
  require_relative 'radfish/system_info'
91
95
  require_relative 'radfish/bmc_info'
92
96
  require_relative 'radfish/power_info'
97
+ require_relative 'radfish/boot_info'
93
98
  require_relative 'radfish/thermal_info'
94
99
  require_relative 'radfish/pci_info'
95
100
  require_relative 'radfish/controller'
@@ -98,13 +103,19 @@ require_relative 'radfish/client'
98
103
 
99
104
  # Auto-load adapters if available
100
105
  begin
101
- require 'radfish/idrac_adapter'
106
+ require 'radfish-idrac'
102
107
  rescue LoadError
103
108
  # radfish-idrac gem not installed
104
109
  end
105
110
 
106
111
  begin
107
- require 'radfish/supermicro_adapter'
112
+ require 'radfish-supermicro'
108
113
  rescue LoadError
109
114
  # radfish-supermicro gem not installed
110
115
  end
116
+
117
+ begin
118
+ require 'radfish-ami'
119
+ rescue LoadError
120
+ # radfish-ami gem not installed
121
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: radfish
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.2.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Siegel
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-09-18 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: thor
@@ -166,6 +165,7 @@ files:
166
165
  - exe/radfish
167
166
  - lib/radfish.rb
168
167
  - lib/radfish/bmc_info.rb
168
+ - lib/radfish/boot_info.rb
169
169
  - lib/radfish/cli.rb
170
170
  - lib/radfish/cli/base.rb
171
171
  - lib/radfish/client.rb
@@ -197,7 +197,6 @@ metadata:
197
197
  homepage_uri: https://github.com/buildio/radfish
198
198
  source_code_uri: https://github.com/buildio/radfish
199
199
  changelog_uri: https://github.com/buildio/radfish/blob/main/CHANGELOG.md
200
- post_install_message:
201
200
  rdoc_options: []
202
201
  require_paths:
203
202
  - lib
@@ -212,8 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
211
  - !ruby/object:Gem::Version
213
212
  version: '0'
214
213
  requirements: []
215
- rubygems_version: 3.5.22
216
- signing_key:
214
+ rubygems_version: 3.6.9
217
215
  specification_version: 4
218
216
  summary: Unified Redfish API Client for Server Management
219
217
  test_files: []