Module: IDRAC::Power
- Included in:
- Client
- Defined in:
- lib/idrac/power.rb
Constant Summary collapse
- RESTART_TYPES =
Reset types that restart the host rather than leave it down. A restart never settles on "Off", so it must never be waited on — or escalated to — as if it were a shutdown.
%w[ForceRestart GracefulRestart PowerCycle].freeze
Instance Method Summary collapse
- #get_power_state ⇒ Object
- #get_power_usage_watts ⇒ Object (also: #power_consumption_watts)
- #power_off(wait: true, kind: "ForceOff") ⇒ Object
- #power_on(wait: true) ⇒ Object
- #reboot(kind: "ForceRestart", wait: false) ⇒ Object
Instance Method Details
#get_power_state ⇒ Object
139 140 141 142 143 144 145 146 |
# File 'lib/idrac/power.rb', line 139 def get_power_state ensure_authenticated! # Get system information response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$select=PowerState") JSON.parse(response.body)&.dig("PowerState") end |
#get_power_usage_watts ⇒ Object Also known as: power_consumption_watts
148 149 150 151 152 153 154 |
# File 'lib/idrac/power.rb', line 148 def get_power_usage_watts ensure_authenticated! response = authenticated_request(:get, "/redfish/v1/Chassis/System.Embedded.1/Power") JSON.parse(response.body)&.dig("PowerControl", 0, "PowerConsumedWatts")&.to_f end |
#power_off(wait: true, kind: "ForceOff") ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/idrac/power.rb', line 65 def power_off(wait: true, kind: "ForceOff") # A restart is not a shutdown. Sent down the power-off path it fails the wait for "Off" and # escalates to ForceOff, which leaves the host powered down. Route it to the restart instead. return reboot(kind: kind, wait: wait) if RESTART_TYPES.include?(kind) ensure_authenticated! puts "Powering off server...".light_cyan # Check current power state first current_state = get_power_state rescue "Unknown" if current_state == "Off" puts "Server is already powered OFF.".yellow return false end # Send power off command path = "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" payload = { "ResetType" => kind } response = authenticated_request(:post, path, body: payload.to_json) if response.status == 409 puts "Server is already powered OFF.".yellow end # Wait for power state change if requested if wait success = wait_for_power_state(target_state: "Off", tries: 6) # If graceful shutdown failed, try force shutdown if !success && kind != "ForceOff" return power_off(wait: wait, kind: "ForceOff") end end return true end |
#power_on(wait: true) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/idrac/power.rb', line 6 def power_on(wait: true) ensure_authenticated! puts "Powering on server...".light_cyan # Check current power state first current_state = get_power_state rescue "Unknown" if current_state == "On" puts "Server is already powered ON.".yellow return false end # Send power on command (Reset with ResetType=On) path = "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" payload = { "ResetType" => "On" } tries = 10 while tries > 0 response = authenticated_request(:post, path, body: payload.to_json) case response.status when 200, 204 puts "Server power on command sent successfully".green break when 409 begin error_data = JSON.parse(response.body) if error_data["error"] && error_data["error"]["@Message.ExtendedInfo"] && error_data["error"]["@Message.ExtendedInfo"].any? { |m| m["Message"] =~ /Server is already powered ON/ } puts "Server is already powered ON.".yellow return false else raise Error, "Failed to power on: #{error_data.inspect}" end rescue JSON::ParserError raise Error, "Failed to power on with status 409: #{response.body}" end when 500 puts "[iDRAC 500] Server is busy...".red tries -= 1 puts "Retrying... #{tries}/10".yellow if tries > 0 sleep 10 else raise Error, "Unknown response code #{response.status}: #{response.body}" end end raise Error, "Failed to power on after 10 retries" if tries <= 0 # Wait for power state change if requested wait_for_power_state(target_state: "On", tries: 10) if wait return true end |
#reboot(kind: "ForceRestart", wait: false) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/idrac/power.rb', line 104 def reboot(kind: "ForceRestart", wait: false) ensure_authenticated! puts "Rebooting server (#{kind})...".light_cyan # Check current power state first current_state = get_power_state rescue "Unknown" if current_state == "Off" puts "Server is currently off, powering on instead of rebooting".yellow return power_on(wait: wait) end path = "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset" response = authenticated_request(:post, path, body: { "ResetType" => kind }.to_json) if response.status >= 200 && response.status < 300 puts "Server reboot command sent successfully".green elsif response.status == 409 && kind != "GracefulRestart" error_data = JSON.parse(response.body) rescue nil puts "Received conflict (409) error from iDRAC: #{error_data.inspect}" # Try gracefulRestart as an alternative puts "Trying GracefulRestart instead...".yellow response = authenticated_request(:post, path, body: { "ResetType" => "GracefulRestart" }.to_json) raise Error, "Failed to reboot server. Status code: #{response.status}" unless response.status.between?(200, 299) else raise Error, "Failed to reboot server. Status code: #{response.status}" end # "On" is the only terminal state a restart reaches. Never wait for "Off" here: the host may # never report it, and treating that as failure is what turned a reboot into a shutdown. wait_for_power_state(target_state: "On", tries: 12) if wait return true end |