idrac 0.1.38 → 0.1.41

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.
@@ -0,0 +1,195 @@
1
+ require 'json'
2
+ require 'colorize'
3
+
4
+ module IDRAC
5
+ module PowerMethods
6
+ def power_on(wait: true)
7
+ # Login to iDRAC if needed
8
+ login unless @session_id
9
+
10
+ puts "Powering on server...".light_cyan
11
+
12
+ # Check current power state first
13
+ current_state = get_power_state rescue "Unknown"
14
+ if current_state == "On"
15
+ puts "Server is already powered ON.".yellow
16
+ return false
17
+ end
18
+
19
+ # Send power on command (Reset with ResetType=On)
20
+ path = "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"
21
+ payload = { "ResetType" => "On" }
22
+
23
+ tries = 10
24
+ while tries > 0
25
+ response = authenticated_request(:post, path, body: payload.to_json, headers: { 'Content-Type' => 'application/json' })
26
+
27
+ case response.status
28
+ when 200, 204
29
+ puts "Server power on command sent successfully".green
30
+ break
31
+ when 409
32
+ begin
33
+ error_data = JSON.parse(response.body)
34
+ if error_data["error"] && error_data["error"]["@Message.ExtendedInfo"] &&
35
+ error_data["error"]["@Message.ExtendedInfo"].any? { |m| m["Message"] =~ /Server is already powered ON/ }
36
+ puts "Server is already powered ON.".yellow
37
+ return false
38
+ else
39
+ raise Error, "Failed to power on: #{error_data.inspect}"
40
+ end
41
+ rescue JSON::ParserError
42
+ raise Error, "Failed to power on with status 409: #{response.body}"
43
+ end
44
+ when 500
45
+ puts "[iDRAC 500] Server is busy...".red
46
+ tries -= 1
47
+ puts "Retrying... #{tries}/10".yellow if tries > 0
48
+ sleep 10
49
+ else
50
+ raise Error, "Unknown response code #{response.status}: #{response.body}"
51
+ end
52
+ end
53
+
54
+ raise Error, "Failed to power on after 10 retries" if tries <= 0
55
+
56
+ # Wait for power state change if requested
57
+ wait_for_power_state(target_state: "On", tries: 10) if wait
58
+
59
+ return true
60
+ end
61
+
62
+ def power_off(wait: true, kind: "ForceOff")
63
+ # Login to iDRAC if needed
64
+ login unless @session_id
65
+
66
+ puts "Powering off server...".light_cyan
67
+
68
+ # Check current power state first
69
+ current_state = get_power_state rescue "Unknown"
70
+ if current_state == "Off"
71
+ puts "Server is already powered OFF.".yellow
72
+ return false
73
+ end
74
+
75
+ # Send power off command
76
+ path = "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"
77
+ payload = { "ResetType" => kind }
78
+
79
+ response = authenticated_request(:post, path, body: payload.to_json, headers: { 'Content-Type' => 'application/json' })
80
+
81
+ case response.status
82
+ when 200, 204
83
+ puts "Server power off command sent successfully".green
84
+ when 409
85
+ # Conflict -- Server is already off
86
+ begin
87
+ error_data = JSON.parse(response.body)
88
+ if error_data["error"] && error_data["error"]["@Message.ExtendedInfo"] &&
89
+ error_data["error"]["@Message.ExtendedInfo"].any? { |m| m["Message"] =~ /Server is already powered OFF/ }
90
+ puts "Server is already powered OFF.".yellow
91
+ return false
92
+ else
93
+ raise Error, "Failed to power off: #{error_data.inspect}"
94
+ end
95
+ rescue JSON::ParserError
96
+ raise Error, "Failed to power off with status 409: #{response.body}"
97
+ end
98
+ else
99
+ error_message = "Failed to power off server. Status code: #{response.status}"
100
+ begin
101
+ error_data = JSON.parse(response.body)
102
+ error_message += ", Message: #{error_data['error']['message']}" if error_data['error'] && error_data['error']['message']
103
+ rescue
104
+ # Ignore JSON parsing errors
105
+ end
106
+ raise Error, error_message
107
+ end
108
+
109
+ # Wait for power state change if requested
110
+ if wait
111
+ success = wait_for_power_state(target_state: "Off", tries: 6)
112
+
113
+ # If graceful shutdown failed, try force shutdown
114
+ if !success && kind != "ForceOff"
115
+ return power_off(wait: wait, kind: "ForceOff")
116
+ end
117
+ end
118
+
119
+ return true
120
+ end
121
+
122
+ def reboot
123
+ # Login to iDRAC if needed
124
+ login unless @session_id
125
+
126
+ puts "Rebooting server...".light_cyan
127
+
128
+ # Send reboot command (Reset with ResetType=ForceRestart)
129
+ path = "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset"
130
+ payload = { "ResetType" => "ForceRestart" }
131
+
132
+ response = authenticated_request(:post, path, body: payload.to_json, headers: { 'Content-Type' => 'application/json' })
133
+
134
+ if response.status >= 200 && response.status < 300
135
+ puts "Server reboot command sent successfully".green
136
+ return true
137
+ else
138
+ error_message = "Failed to reboot server. Status code: #{response.status}"
139
+ begin
140
+ error_data = JSON.parse(response.body)
141
+ error_message += ", Message: #{error_data['error']['message']}" if error_data['error'] && error_data['error']['message']
142
+ rescue
143
+ # Ignore JSON parsing errors
144
+ end
145
+
146
+ raise Error, error_message
147
+ end
148
+ end
149
+
150
+ def get_power_state
151
+ # Login to iDRAC if needed
152
+ login unless @session_id
153
+
154
+ # Get system information
155
+ response = authenticated_request(:get, "/redfish/v1/Systems/System.Embedded.1?$select=PowerState")
156
+
157
+ if response.status == 200
158
+ begin
159
+ system_data = JSON.parse(response.body)
160
+ return system_data["PowerState"]
161
+ rescue JSON::ParserError
162
+ raise Error, "Failed to parse power state response: #{response.body}"
163
+ end
164
+ else
165
+ raise Error, "Failed to get power state. Status code: #{response.status}"
166
+ end
167
+ end
168
+
169
+ private
170
+
171
+ def wait_for_power_state(target_state:, tries: 6)
172
+ retry_count = tries
173
+
174
+ while retry_count > 0
175
+ begin
176
+ current_state = get_power_state
177
+
178
+ return true if current_state == target_state
179
+
180
+ puts "Waiting for power #{target_state == 'On' ? 'on' : 'off'}...".yellow
181
+ puts "Current state: #{current_state}"
182
+ retry_count -= 1
183
+ sleep 8
184
+ rescue => e
185
+ puts "Error checking power state: #{e.message}".red
186
+ retry_count -= 1
187
+ sleep 5
188
+ end
189
+ end
190
+
191
+ puts "Failed to reach power state #{target_state}".red
192
+ return false
193
+ end
194
+ end
195
+ end