idrac 0.10.5 → 0.10.6

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: 9c4504dd010f1458b9705e73489d4d68ec18214ef13a5a5187dde3ed52812d1a
4
- data.tar.gz: eb9ab621e77b1ad17ade9579b4286a7696f7f0bb9dc0761e8862446ee8f39963
3
+ metadata.gz: fae473e8260d010235ebf86c7ed40b33dae6b7a1c14c2576bce55fecc319c7be
4
+ data.tar.gz: 8c115aeb8c6399d2d3d167204b160ef691b64ec41570b371912df697b23d9789
5
5
  SHA512:
6
- metadata.gz: af0824a2ceb96d5c89a2552277d24bdf754eb748a7644d756deb3864620130b005d3f5cefa1f0921d6617fd03aab79c31fd8d9de8b0716a2e3124a8916f1bde4
7
- data.tar.gz: 3c85876b2e93b31bed8f8dd4a8ea2ab4ae851048a2767c18e319151b74748c797502971c0932b9e534150c95ce66c3bb9ff93e5194a0d6e37108714724363396
6
+ metadata.gz: 278b81e8955021924c44c496b0df20c34f59e3630f9df3decda96ee519cadc0445901cddbf3c78c174313c36eef558780ce444fb09f3d870039adc23e7da5056
7
+ data.tar.gz: c66f192778e2e32cf724b3b98ef45c2311a79ee8f0144e0f95a3106ff1d2d87f67f13c30eac4a47c2055e302bb5b2dc373cf37cfc760ff2566a8f949531db061
@@ -11,6 +11,8 @@ require_relative 'firmware_catalog'
11
11
  require 'faraday'
12
12
  require 'faraday/multipart'
13
13
 
14
+ require "timeout"
15
+
14
16
  module IDRAC
15
17
  class Firmware
16
18
  attr_reader :client
@@ -440,6 +442,51 @@ module IDRAC
440
442
 
441
443
 
442
444
 
445
+ # An iDRAC holds ONE staged package and refuses another while any update job is outstanding
446
+ # ("503: A deployment operation is already in progress"). Retrying cannot clear it, because
447
+ # the staged package IS the operation -- the caller has to wait for the slot. Anyone updating
448
+ # several components in sequence needs this: a straight loop over one R6525's 15 packages
449
+ # submitted 6 and lost 9 to 503.
450
+ #
451
+ # Every rule here is a Dell fact rather than a caller's policy, which is why it belongs in
452
+ # the gem. Each was a silent stall on real hardware:
453
+ #
454
+ # * "Available-" is a PREFIX, not a substring. The TPM ships an installed entry whose
455
+ # version is the literal string "NotAvailable"
456
+ # (Installed-12345-NotAvailable__TPM.Integrated.1-1); a substring test matches it and the
457
+ # slot then never reads free on that machine.
458
+ # * RebootCompleted is TERMINAL, as is anything at PercentComplete 100. Counting a finished
459
+ # reboot as active made a drained queue look busy for 67 minutes.
460
+ # * Jobs matter, not just the staging slot: triggering an install consumes the staged
461
+ # package into a job, so Available empties while the install is still pending.
462
+ TERMINAL_JOB_STATES = %w[Completed Failed CompletedWithErrors RebootCompleted RebootFailed].freeze
463
+
464
+ def update_slot_free?
465
+ staged = JSON.parse(client.authenticated_request(:get, "/redfish/v1/UpdateService/FirmwareInventory").body)["Members"]
466
+ .map { |m| m["@odata.id"].to_s.split("/").last }
467
+ .count { |id| id.start_with?("Available-") }
468
+ busy = JSON.parse(client.authenticated_request(:get, "/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/Jobs?$expand=*($levels=1)").body)["Members"]
469
+ .count { |job| !(TERMINAL_JOB_STATES.include?(job["JobState"]) || job["PercentComplete"].to_i == 100) }
470
+ staged.zero? && busy.zero?
471
+ end
472
+
473
+ # Block until the iDRAC can accept an update. Probes are bounded because a hung transport
474
+ # blocks without raising, so a bare rescue never fires and the wait wedges silently.
475
+ def wait_for_update_slot!(timeout: 2700, interval: 30, probe_timeout: 90)
476
+ deadline = Time.now + timeout
477
+ loop do
478
+ begin
479
+ return true if Timeout.timeout(probe_timeout) { update_slot_free? }
480
+ rescue StandardError => e
481
+ # Report rather than counting a probe failure as "busy": an unreachable BMC is
482
+ # otherwise indistinguishable from a working one, and the caller waits out the timeout.
483
+ puts "Update slot probe failed (#{e.class}); retrying".yellow
484
+ end
485
+ raise Error, "iDRAC update slot never freed within #{timeout}s" if Time.now > deadline
486
+ sleep interval
487
+ end
488
+ end
489
+
443
490
  private
444
491
 
445
492
  def upload_firmware(firmware_path)
data/lib/idrac/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IDRAC
4
- VERSION = "0.10.5"
4
+ VERSION = "0.10.6"
5
5
  end
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.10.5
4
+ version: 0.10.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Siegel