ibm_power_hmc 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +0 -0
- data/.rubocop.yml +4 -0
- data/.rubocop_local.yml +7 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +0 -0
- data/Gemfile.lock +0 -0
- data/LICENSE +0 -0
- data/README.md +0 -0
- data/Rakefile +0 -0
- data/ibm_power_hmc.gemspec +0 -0
- data/lib/ibm_power_hmc/connection.rb +250 -102
- data/lib/ibm_power_hmc/job.rb +80 -19
- data/lib/ibm_power_hmc/objects.rb +22 -31
- data/lib/ibm_power_hmc/pcm.rb +55 -0
- data/lib/ibm_power_hmc/version.rb +1 -1
- data/lib/ibm_power_hmc.rb +0 -0
- metadata +10 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 214dfa7f9a89d236f1f9bc4ee927b619596a0fabe59c2f596359637e891601ab
|
4
|
+
data.tar.gz: 2affd160febc3952014ab522bb9b0f89b0ebef6d785720d2d8d2a875cd1df918
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e6e6ae8b4c7d84eea70e3328ea44834a5b95ecd98fbe6a31c045e575951b6c17751ca7d6517d3ad58647b5c8b7e1321470c368c48018c31a450a28ba40463e5
|
7
|
+
data.tar.gz: f9139f2ea1a83d0abedc3c73832450e20fa4fcf7c56cc65c50ec5b14750bb5bb2eb17d7948ffc22d5887984d0f412ae8213a237892350e55f0cd55a49af80f30
|
data/.gitignore
CHANGED
File without changes
|
data/.rubocop.yml
ADDED
data/.rubocop_local.yml
ADDED
data/CHANGELOG.md
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/Gemfile.lock
CHANGED
File without changes
|
data/LICENSE
CHANGED
File without changes
|
data/README.md
CHANGED
File without changes
|
data/Rakefile
CHANGED
File without changes
|
data/ibm_power_hmc.gemspec
CHANGED
File without changes
|
@@ -2,8 +2,22 @@
|
|
2
2
|
|
3
3
|
# Module for IBM HMC Rest API Client
|
4
4
|
module IbmPowerHmc
|
5
|
-
|
5
|
+
require_relative 'pcm.rb'
|
6
|
+
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
##
|
10
|
+
# HMC REST Client connection.
|
6
11
|
class Connection
|
12
|
+
##
|
13
|
+
# @!method initialize(host:, username: "hscroot", password:, port: 12_443, validate_ssl: true)
|
14
|
+
# Create a new HMC connection.
|
15
|
+
#
|
16
|
+
# @param host [String] Hostname of the HMC.
|
17
|
+
# @param username [String] User name.
|
18
|
+
# @param password [String] Password.
|
19
|
+
# @param port [Integer] TCP port number.
|
20
|
+
# @param validate_ssl [Boolean] Verify SSL certificates.
|
7
21
|
def initialize(host:, username: "hscroot", password:, port: 12_443, validate_ssl: true)
|
8
22
|
# Damien: use URI::HTTPS
|
9
23
|
@hostname = "#{host}:#{port}"
|
@@ -13,10 +27,14 @@ module IbmPowerHmc
|
|
13
27
|
@api_session_token = nil
|
14
28
|
end
|
15
29
|
|
30
|
+
##
|
31
|
+
# @!method logon
|
32
|
+
# Establish a trusted session with the Web Services APIs.
|
33
|
+
# @return [String] The X-API-Session token.
|
16
34
|
def logon
|
17
35
|
method_url = "/rest/api/web/Logon"
|
18
36
|
headers = {
|
19
|
-
content_type
|
37
|
+
:content_type => "application/vnd.ibm.powervm.web+xml; type=LogonRequest"
|
20
38
|
}
|
21
39
|
doc = REXML::Document.new("")
|
22
40
|
doc.add_element("LogonRequest", {
|
@@ -26,41 +44,84 @@ module IbmPowerHmc
|
|
26
44
|
doc.root.add_element("UserID").text = @username
|
27
45
|
doc.root.add_element("Password").text = @password
|
28
46
|
|
29
|
-
# Damien: begin/rescue
|
30
47
|
@api_session_token = ""
|
31
48
|
response = request(:put, method_url, headers, doc.to_s)
|
32
49
|
doc = REXML::Document.new(response.body)
|
33
|
-
|
50
|
+
elem = doc.elements["LogonResponse/X-API-Session"]
|
51
|
+
raise Error, "LogonResponse/X-API-Session not found" if elem.nil?
|
52
|
+
|
53
|
+
@api_session_token = elem.text
|
34
54
|
end
|
35
55
|
|
56
|
+
##
|
57
|
+
# @!method logoff
|
58
|
+
# Close the session.
|
36
59
|
def logoff
|
60
|
+
# Don't want to trigger automatic logon here!
|
61
|
+
return if @api_session_token.nil?
|
62
|
+
|
37
63
|
method_url = "/rest/api/web/Logon"
|
38
|
-
|
64
|
+
begin
|
65
|
+
request(:delete, method_url)
|
66
|
+
rescue
|
67
|
+
# Ignore exceptions as this is best effort attempt to log off.
|
68
|
+
end
|
39
69
|
@api_session_token = nil
|
40
70
|
end
|
41
71
|
|
72
|
+
def parse_feed(doc, myclass)
|
73
|
+
objs = []
|
74
|
+
doc.each_element("feed/entry") do |entry|
|
75
|
+
objs << myclass.new(entry)
|
76
|
+
end
|
77
|
+
objs
|
78
|
+
end
|
79
|
+
private :parse_feed
|
80
|
+
|
81
|
+
##
|
82
|
+
# @!method management_console
|
83
|
+
# Retrieve information about the management console.
|
84
|
+
# @return [IbmPowerHmc::ManagementConsole] The management console.
|
42
85
|
def management_console
|
43
86
|
method_url = "/rest/api/uom/ManagementConsole"
|
44
87
|
response = request(:get, method_url)
|
45
88
|
doc = REXML::Document.new(response.body)
|
46
|
-
|
47
|
-
ManagementConsole.
|
89
|
+
# This request returns a feed with a single entry.
|
90
|
+
parse_feed(doc, ManagementConsole).first
|
48
91
|
end
|
49
92
|
|
93
|
+
##
|
94
|
+
# @!method managed_systems
|
95
|
+
# Retrieve the list of systems managed by the HMC.
|
96
|
+
# @return [Array<IbmPowerHmc::ManagedSystem>] The list of managed systems.
|
50
97
|
def managed_systems
|
51
98
|
method_url = "/rest/api/uom/ManagedSystem"
|
52
99
|
response = request(:get, method_url)
|
53
100
|
doc = REXML::Document.new(response.body)
|
54
|
-
|
55
|
-
|
101
|
+
parse_feed(doc, ManagedSystem)
|
102
|
+
end
|
56
103
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
104
|
+
##
|
105
|
+
# @!method managed_system(lpar_uuid, sys_uuid = nil, group_name = nil)
|
106
|
+
# Retrieve information about a managed system.
|
107
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
108
|
+
# @param group_name [String] The extended group attributes.
|
109
|
+
# @return [IbmPowerHmc::ManagedSystem] The logical partition.
|
110
|
+
def managed_system(sys_uuid, group_name = nil)
|
111
|
+
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}"
|
112
|
+
method_url += "?group=#{group_name}" unless group_name.nil?
|
113
|
+
|
114
|
+
response = request(:get, method_url)
|
115
|
+
doc = REXML::Document.new(response.body)
|
116
|
+
entry = doc.elements["entry"]
|
117
|
+
ManagedSystem.new(entry)
|
62
118
|
end
|
63
119
|
|
120
|
+
##
|
121
|
+
# @!method lpars(sys_uuid = nil)
|
122
|
+
# Retrieve the list of logical partitions managed by the HMC.
|
123
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
124
|
+
# @return [Array<IbmPowerHmc::LogicalPartition>] The list of logical partitions.
|
64
125
|
def lpars(sys_uuid = nil)
|
65
126
|
if sys_uuid.nil?
|
66
127
|
method_url = "/rest/api/uom/LogicalPartition"
|
@@ -69,16 +130,16 @@ module IbmPowerHmc
|
|
69
130
|
end
|
70
131
|
response = request(:get, method_url)
|
71
132
|
doc = REXML::Document.new(response.body)
|
72
|
-
|
73
|
-
return lpars if doc.root.nil?
|
74
|
-
|
75
|
-
doc.root.each_element("entry") do |entry|
|
76
|
-
lpar = LogicalPartition.new(entry)
|
77
|
-
lpars += [lpar]
|
78
|
-
end
|
79
|
-
lpars
|
133
|
+
parse_feed(doc, LogicalPartition)
|
80
134
|
end
|
81
135
|
|
136
|
+
##
|
137
|
+
# @!method lpar(lpar_uuid, sys_uuid = nil, group_name = nil)
|
138
|
+
# Retrieve information about a logical partition.
|
139
|
+
# @param lpar_uuid [String] The UUID of the logical partition.
|
140
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
141
|
+
# @param group_name [String] The extended group attributes.
|
142
|
+
# @return [IbmPowerHmc::LogicalPartition] The logical partition.
|
82
143
|
def lpar(lpar_uuid, sys_uuid = nil, group_name = nil)
|
83
144
|
if sys_uuid.nil?
|
84
145
|
method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}"
|
@@ -93,6 +154,11 @@ module IbmPowerHmc
|
|
93
154
|
LogicalPartition.new(entry)
|
94
155
|
end
|
95
156
|
|
157
|
+
##
|
158
|
+
# @!method lpar_quick_property(lpar_uuid, property_name)
|
159
|
+
# Retrieve a quick property of a logical partition.
|
160
|
+
# @param lpar_uuid [String] The UUID of the logical partition.
|
161
|
+
# @return [String] The quick property value.
|
96
162
|
def lpar_quick_property(lpar_uuid, property_name)
|
97
163
|
method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/quick/#{property_name}"
|
98
164
|
|
@@ -100,141 +166,223 @@ module IbmPowerHmc
|
|
100
166
|
response.body[1..-2]
|
101
167
|
end
|
102
168
|
|
169
|
+
##
|
170
|
+
# @!method vioses(sys_uuid = nil)
|
171
|
+
# Retrieve the list of virtual I/O servers managed by the HMC.
|
172
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
173
|
+
# @return [Array<IbmPowerHmc::VirtualIOServer>] The list of virtual I/O servers.
|
103
174
|
def vioses(sys_uuid = nil)
|
104
175
|
if sys_uuid.nil?
|
105
176
|
method_url = "/rest/api/uom/VirtualIOServer"
|
106
177
|
else
|
107
178
|
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/VirtualIOServer"
|
108
179
|
end
|
109
|
-
|
110
|
-
response = request(:get, method_url)
|
111
|
-
rescue StandardError
|
112
|
-
return []
|
113
|
-
end
|
180
|
+
response = request(:get, method_url)
|
114
181
|
doc = REXML::Document.new(response.body)
|
115
|
-
|
116
|
-
return vioses if doc.root.nil?
|
117
|
-
|
118
|
-
doc.root.each_element("entry") do |entry|
|
119
|
-
vios = VirtualIOServer.new(entry)
|
120
|
-
vioses += [vios]
|
121
|
-
end
|
122
|
-
vioses
|
182
|
+
parse_feed(doc, VirtualIOServer)
|
123
183
|
end
|
124
184
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
185
|
+
##
|
186
|
+
# @!method vios(vios_uuid, sys_uuid = nil, group_name = nil)
|
187
|
+
# Retrieve information about a virtual I/O server.
|
188
|
+
# @param vios_uuid [String] The UUID of the virtual I/O server.
|
189
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
190
|
+
# @param group_name [String] The extended group attributes.
|
191
|
+
# @return [IbmPowerHmc::VirtualIOServer] The virtual I/O server.
|
192
|
+
def vios(vios_uuid, sys_uuid = nil, group_name = nil)
|
193
|
+
if sys_uuid.nil?
|
194
|
+
method_url = "/rest/api/uom/VirtualIOServer/#{vios_uuid}"
|
195
|
+
else
|
196
|
+
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/VirtualIOServer/#{vios_uuid}"
|
132
197
|
end
|
133
|
-
|
134
|
-
profiles = []
|
135
|
-
return profiles if doc.root.nil?
|
198
|
+
method_url += "?group=#{group_name}" unless group_name.nil?
|
136
199
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
profiles
|
200
|
+
response = request(:get, method_url)
|
201
|
+
doc = REXML::Document.new(response.body)
|
202
|
+
entry = doc.elements["entry"]
|
203
|
+
VirtualIOServer.new(entry)
|
142
204
|
end
|
143
205
|
|
144
|
-
|
206
|
+
##
|
207
|
+
# @!method poweron_lpar(lpar_uuid, params = {}, sync = true)
|
208
|
+
# Power on a logical partition.
|
209
|
+
# @param lpar_uuid [String] The UUID of the logical partition.
|
210
|
+
# @param params [Hash] Job parameters.
|
211
|
+
# @param sync [Boolean] Start the job and wait for its completion.
|
212
|
+
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
213
|
+
def poweron_lpar(lpar_uuid, params = {}, sync = true)
|
145
214
|
method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/do/PowerOn"
|
146
215
|
|
147
216
|
job = HmcJob.new(self, method_url, "PowerOn", "LogicalPartition", params)
|
148
|
-
job.
|
149
|
-
job
|
150
|
-
job.delete
|
217
|
+
job.run if sync
|
218
|
+
job
|
151
219
|
end
|
152
220
|
|
153
|
-
|
221
|
+
##
|
222
|
+
# @!method poweroff_lpar(lpar_uuid, params = {}, sync = true)
|
223
|
+
# Power off a logical partition.
|
224
|
+
# @param lpar_uuid [String] The UUID of the logical partition.
|
225
|
+
# @param params [Hash] Job parameters.
|
226
|
+
# @param sync [Boolean] Start the job and wait for its completion.
|
227
|
+
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
228
|
+
def poweroff_lpar(lpar_uuid, params = {}, sync = true)
|
154
229
|
method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/do/PowerOff"
|
155
230
|
|
156
231
|
job = HmcJob.new(self, method_url, "PowerOff", "LogicalPartition", params)
|
157
|
-
job.
|
158
|
-
job
|
159
|
-
job.delete
|
232
|
+
job.run if sync
|
233
|
+
job
|
160
234
|
end
|
161
235
|
|
162
|
-
|
163
|
-
|
236
|
+
##
|
237
|
+
# @!method poweron_vios(vios_uuid, params = {}, sync = true)
|
238
|
+
# Power on a virtual I/O server.
|
239
|
+
# @param vios_uuid [String] The UUID of the virtual I/O server.
|
240
|
+
# @param params [Hash] Job parameters.
|
241
|
+
# @param sync [Boolean] Start the job and wait for its completion.
|
242
|
+
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
243
|
+
def poweron_vios(vios_uuid, params = {}, sync = true)
|
164
244
|
method_url = "/rest/api/uom/VirtualIOServer/#{vios_uuid}/do/PowerOn"
|
165
245
|
|
166
246
|
job = HmcJob.new(self, method_url, "PowerOn", "VirtualIOServer", params)
|
167
|
-
job.
|
168
|
-
job
|
169
|
-
job.delete
|
247
|
+
job.run if sync
|
248
|
+
job
|
170
249
|
end
|
171
250
|
|
172
|
-
|
173
|
-
|
251
|
+
##
|
252
|
+
# @!method poweroff_vios(vios_uuid, params = {}, sync = true)
|
253
|
+
# Power off a virtual I/O server.
|
254
|
+
# @param vios_uuid [String] The UUID of the virtual I/O server.
|
255
|
+
# @param params [Hash] Job parameters.
|
256
|
+
# @param sync [Boolean] Start the job and wait for its completion.
|
257
|
+
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
258
|
+
def poweroff_vios(vios_uuid, params = {}, sync = true)
|
174
259
|
method_url = "/rest/api/uom/VirtualIOServer/#{vios_uuid}/do/PowerOff"
|
175
260
|
|
176
261
|
job = HmcJob.new(self, method_url, "PowerOff", "VirtualIOServer", params)
|
177
|
-
job.
|
178
|
-
job
|
179
|
-
job.delete
|
262
|
+
job.run if sync
|
263
|
+
job
|
180
264
|
end
|
181
265
|
|
182
|
-
|
266
|
+
##
|
267
|
+
# @!method poweron_managed_system(sys_uuid, params = {}, sync = true)
|
268
|
+
# Power on a managed system.
|
269
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
270
|
+
# @param params [Hash] Job parameters.
|
271
|
+
# @param sync [Boolean] Start the job and wait for its completion.
|
272
|
+
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
273
|
+
def poweron_managed_system(sys_uuid, params = {}, sync = true)
|
183
274
|
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/do/PowerOn"
|
184
275
|
|
185
276
|
job = HmcJob.new(self, method_url, "PowerOn", "ManagedSystem", params)
|
186
|
-
job.
|
187
|
-
job
|
188
|
-
job.delete
|
277
|
+
job.run if sync
|
278
|
+
job
|
189
279
|
end
|
190
280
|
|
191
|
-
|
281
|
+
##
|
282
|
+
# @!method poweroff_managed_system(sys_uuid, params = {}, sync = true)
|
283
|
+
# Power off a managed system.
|
284
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
285
|
+
# @param params [Hash] Job parameters.
|
286
|
+
# @param sync [Boolean] Start the job and wait for its completion.
|
287
|
+
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
288
|
+
def poweroff_managed_system(sys_uuid, params = {}, sync = true)
|
192
289
|
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/do/PowerOff"
|
193
290
|
|
194
291
|
job = HmcJob.new(self, method_url, "PowerOff", "ManagedSystem", params)
|
195
|
-
job.
|
196
|
-
job
|
197
|
-
job.delete
|
292
|
+
job.run if sync
|
293
|
+
job
|
198
294
|
end
|
199
295
|
|
200
|
-
|
201
|
-
|
296
|
+
##
|
297
|
+
# @!method cli_run(hmc_uuid, cmd, sync = true)
|
298
|
+
# Run a CLI command on the HMC as a job.
|
299
|
+
# @param hmc_uuid [String] The UUID of the management console.
|
300
|
+
# @param cmd [String] The command to run.
|
301
|
+
# @param sync [Boolean] Start the job and wait for its completion.
|
302
|
+
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
303
|
+
def cli_run(hmc_uuid, cmd, sync = true)
|
304
|
+
method_url = "/rest/api/uom/ManagementConsole/#{hmc_uuid}/do/CLIRunner"
|
305
|
+
|
306
|
+
params = {
|
307
|
+
"cmd" => cmd,
|
308
|
+
"acknowledgeThisAPIMayGoAwayInTheFuture" => "true",
|
309
|
+
}
|
310
|
+
job = HmcJob.new(self, method_url, "CLIRunner", "ManagementConsole", params)
|
311
|
+
job.run if sync
|
312
|
+
job
|
313
|
+
end
|
314
|
+
|
315
|
+
##
|
316
|
+
# @!method next_events(wait = true)
|
317
|
+
# Retrieve a list of events that occured since last call.
|
318
|
+
# @param wait [Boolean] If no event is available, block until new events occur.
|
319
|
+
# @return [Array<IbmPowerHmc::Event>] The list of events.
|
320
|
+
def next_events(wait = true)
|
202
321
|
method_url = "/rest/api/uom/Event"
|
203
322
|
|
204
|
-
|
323
|
+
response = nil
|
205
324
|
loop do
|
206
325
|
response = request(:get, method_url)
|
207
|
-
|
326
|
+
# No need to sleep as the HMC already waits a bit before returning 204
|
327
|
+
break if response.code != 204 || !wait
|
328
|
+
end
|
329
|
+
doc = REXML::Document.new(response.body)
|
330
|
+
parse_feed(doc, Event)
|
331
|
+
end
|
208
332
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
333
|
+
class HttpError < Error
|
334
|
+
attr_reader :status, :uri, :reason, :message
|
335
|
+
|
336
|
+
##
|
337
|
+
# @!method initialize(err)
|
338
|
+
# Create a new HttpError exception.
|
339
|
+
# @param err [RestClient::Exception] The REST client exception.
|
340
|
+
def initialize(err)
|
341
|
+
super
|
342
|
+
@status = err.http_code
|
343
|
+
|
344
|
+
# Try to parse body as an HttpErrorResponse
|
345
|
+
doc = REXML::Document.new(err.response.body)
|
346
|
+
entry = doc.elements["entry"]
|
347
|
+
unless entry.nil?
|
348
|
+
resp = HttpErrorResponse.new(entry)
|
349
|
+
@uri = resp.uri
|
350
|
+
@reason = resp.reason
|
351
|
+
@message = resp.message
|
213
352
|
end
|
214
|
-
break
|
215
353
|
end
|
216
|
-
events
|
217
354
|
end
|
218
355
|
|
356
|
+
##
|
357
|
+
# @!method request(method, url, headers = {}, payload = nil)
|
358
|
+
# Perform a REST API request.
|
359
|
+
# @param method [String] The HTTP method.
|
360
|
+
# @param url [String] The method URL.
|
361
|
+
# @param headers [Hash] HTTP headers.
|
362
|
+
# @param payload [String] HTTP request payload.
|
363
|
+
# @return [RestClient::Response] The response from the HMC.
|
219
364
|
def request(method, url, headers = {}, payload = nil)
|
220
365
|
logon if @api_session_token.nil?
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
#
|
233
|
-
@api_session_token
|
234
|
-
|
235
|
-
|
366
|
+
reauth = false
|
367
|
+
begin
|
368
|
+
headers = headers.merge({"X-API-Session" => @api_session_token})
|
369
|
+
RestClient::Request.execute(
|
370
|
+
:method => method,
|
371
|
+
:url => "https://" + @hostname + url,
|
372
|
+
:verify_ssl => @verify_ssl,
|
373
|
+
:payload => payload,
|
374
|
+
:headers => headers
|
375
|
+
)
|
376
|
+
rescue RestClient::Exception => e
|
377
|
+
# Do not retry on failed logon attempts
|
378
|
+
if e.http_code == 401 && @api_session_token != "" && !reauth
|
379
|
+
# Try to reauth
|
380
|
+
reauth = true
|
381
|
+
logon
|
382
|
+
retry
|
383
|
+
end
|
384
|
+
raise HttpError.new(e), "REST request failed"
|
236
385
|
end
|
237
|
-
response
|
238
386
|
end
|
239
387
|
end
|
240
388
|
end
|
data/lib/ibm_power_hmc/job.rb
CHANGED
@@ -1,20 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Module for IBM HMC Rest API Client
|
4
3
|
module IbmPowerHmc
|
5
|
-
|
4
|
+
##
|
5
|
+
# HMC Job for long running operations.
|
6
6
|
class HmcJob
|
7
|
-
|
8
|
-
|
7
|
+
class JobNotStarted < StandardError; end
|
8
|
+
|
9
|
+
##
|
10
|
+
# @!method initialize(conn, method_url, operation, group, params = {})
|
11
|
+
# Construct a new HMC Job.
|
12
|
+
#
|
13
|
+
# @param conn [IbmPowerHmc::Connection] The connection to the HMC.
|
14
|
+
# @param method_url [String] The method URL.
|
15
|
+
# @param operation [String] The name of the requested operation.
|
16
|
+
# @param group [String] The name of the group.
|
17
|
+
# @param params [Hash] The job name/value parameters.
|
18
|
+
def initialize(conn, method_url, operation, group, params = {})
|
19
|
+
@conn = conn
|
9
20
|
@method_url = method_url
|
10
21
|
@operation = operation
|
11
22
|
@group = group
|
12
23
|
@params = params
|
13
24
|
end
|
14
25
|
|
26
|
+
##
|
27
|
+
# @!method status
|
28
|
+
# Start the job asynchronously.
|
29
|
+
# @return [String] The ID of the job.
|
15
30
|
def start
|
16
31
|
headers = {
|
17
|
-
content_type
|
32
|
+
:content_type => "application/vnd.ibm.powervm.web+xml; type=JobRequest"
|
18
33
|
}
|
19
34
|
doc = REXML::Document.new("")
|
20
35
|
doc.add_element("JobRequest:JobRequest", {
|
@@ -22,49 +37,95 @@ module IbmPowerHmc
|
|
22
37
|
"xmlns" => "http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/",
|
23
38
|
"schemaVersion" => "V1_1_0"
|
24
39
|
})
|
25
|
-
op = doc.root.add_element("RequestedOperation", {
|
40
|
+
op = doc.root.add_element("RequestedOperation", {"schemaVersion" => "V1_1_0"})
|
26
41
|
op.add_element("OperationName").text = @operation
|
27
42
|
op.add_element("GroupName").text = @group
|
28
43
|
# Damien: ProgressType?
|
29
|
-
jobparams = doc.root.add_element("JobParameters", {
|
44
|
+
jobparams = doc.root.add_element("JobParameters", {"schemaVersion" => "V1_1_0"})
|
30
45
|
@params.each do |key, value|
|
31
|
-
jobparam = jobparams.add_element("JobParameter", {
|
46
|
+
jobparam = jobparams.add_element("JobParameter", {"schemaVersion" => "V1_1_0"})
|
32
47
|
jobparam.add_element("ParameterName").text = key
|
33
48
|
jobparam.add_element("ParameterValue").text = value
|
34
49
|
end
|
35
|
-
response = @
|
50
|
+
response = @conn.request(:put, @method_url, headers, doc.to_s)
|
36
51
|
doc = REXML::Document.new(response.body)
|
37
52
|
info = doc.root.elements["content/JobResponse:JobResponse"]
|
38
53
|
@id = info.elements["JobID"].text
|
39
54
|
end
|
40
55
|
|
56
|
+
# @return [Hash] The job results returned by the HMC.
|
57
|
+
attr_reader :results
|
58
|
+
|
59
|
+
##
|
60
|
+
# @!method status
|
61
|
+
# Return the status of the job.
|
62
|
+
# @return [String] The status of the job.
|
41
63
|
def status
|
42
|
-
|
64
|
+
raise JobNotStarted unless defined?(@id)
|
65
|
+
|
43
66
|
method_url = "/rest/api/uom/jobs/#{@id}"
|
44
67
|
headers = {
|
45
|
-
content_type
|
68
|
+
:content_type => "application/vnd.ibm.powervm.web+xml; type=JobRequest"
|
46
69
|
}
|
47
|
-
response = @
|
70
|
+
response = @conn.request(:get, method_url, headers)
|
48
71
|
doc = REXML::Document.new(response.body)
|
49
72
|
info = doc.root.elements["content/JobResponse:JobResponse"]
|
50
73
|
status = info.elements["Status"].text
|
51
|
-
# Damien: also retrieve "ResponseException/Message"
|
74
|
+
# Damien: also retrieve "ResponseException/Message"?
|
75
|
+
|
76
|
+
# Gather Job results returned by the HMC.
|
77
|
+
@results = {}
|
78
|
+
info.each_element("Results/JobParameter") do |result|
|
79
|
+
name = result.elements["ParameterName"].text.strip
|
80
|
+
value = result.elements["ParameterValue"].text.strip
|
81
|
+
@results[name] = value
|
82
|
+
end
|
83
|
+
|
52
84
|
status
|
53
85
|
end
|
54
86
|
|
55
|
-
|
56
|
-
|
57
|
-
|
87
|
+
##
|
88
|
+
# @!method wait(timeout = 120, poll_interval = 0)
|
89
|
+
# Wait for the job to complete.
|
90
|
+
# @param timeout [Integer] The maximum time in seconds to wait for the job to complete.
|
91
|
+
# @param poll_interval [Integer] The interval in seconds between status queries (0 means auto).
|
92
|
+
# @return [String] The status of the job.
|
93
|
+
def wait(timeout = 120, poll_interval = 0)
|
94
|
+
endtime = Time.now.utc + timeout
|
95
|
+
auto = poll_interval == 0
|
96
|
+
poll_interval = 1 if auto
|
97
|
+
while Time.now.utc < endtime
|
58
98
|
status = self.status
|
59
|
-
|
99
|
+
return status if status != "RUNNING" && status != "NOT_STARTED"
|
100
|
+
|
101
|
+
poll_interval *= 2 if auto && poll_interval < 30
|
60
102
|
sleep(poll_interval)
|
61
103
|
end
|
104
|
+
"TIMEDOUT"
|
62
105
|
end
|
63
106
|
|
107
|
+
##
|
108
|
+
# @!method run(timeout = 120, poll_interval = 0)
|
109
|
+
# Run the job synchronously.
|
110
|
+
# @param timeout [Integer] The maximum time in seconds to wait for the job to complete.
|
111
|
+
# @param poll_interval [Integer] The interval in seconds between status queries (0 means auto).
|
112
|
+
# @return [String] The status of the job.
|
113
|
+
def run(timeout = 120, poll_interval = 0)
|
114
|
+
start
|
115
|
+
status = wait(timeout, poll_interval)
|
116
|
+
status
|
117
|
+
ensure
|
118
|
+
delete if defined?(@id)
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# @!method delete
|
123
|
+
# Delete the job from the HMC.
|
64
124
|
def delete
|
65
|
-
|
125
|
+
raise JobNotStarted unless defined?(@id)
|
126
|
+
|
66
127
|
method_url = "/rest/api/uom/jobs/#{@id}"
|
67
|
-
@
|
128
|
+
@conn.request(:delete, method_url)
|
68
129
|
# Returns HTTP 204 if ok
|
69
130
|
end
|
70
131
|
end
|
@@ -16,7 +16,7 @@ module IbmPowerHmc
|
|
16
16
|
value = doc.elements[xpath]
|
17
17
|
value = value.text unless value.nil?
|
18
18
|
value = value.strip unless value.nil?
|
19
|
-
self.class.__send__(:attr_reader,
|
19
|
+
self.class.__send__(:attr_reader, varname)
|
20
20
|
instance_variable_set("@#{varname}", value)
|
21
21
|
end
|
22
22
|
|
@@ -25,10 +25,6 @@ module IbmPowerHmc
|
|
25
25
|
get_value(doc, key, value)
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
29
|
-
def to_s
|
30
|
-
"uuid=#{@uuid}"
|
31
|
-
end
|
32
28
|
end
|
33
29
|
|
34
30
|
# HMC information
|
@@ -44,10 +40,6 @@ module IbmPowerHmc
|
|
44
40
|
info = doc.elements["content/ManagementConsole:ManagementConsole"]
|
45
41
|
get_values(info, XMLMAP)
|
46
42
|
end
|
47
|
-
|
48
|
-
def to_s
|
49
|
-
"hmc name=#{@name} version=#{@version} build_level=#{@build_level}"
|
50
|
-
end
|
51
43
|
end
|
52
44
|
|
53
45
|
# Managed System information
|
@@ -60,7 +52,10 @@ module IbmPowerHmc
|
|
60
52
|
"AssociatedSystemMemoryConfiguration/InstalledSystemMemory" => "memory",
|
61
53
|
"AssociatedSystemMemoryConfiguration/CurrentAvailableSystemMemory" => "avail_mem",
|
62
54
|
"AssociatedSystemProcessorConfiguration/InstalledSystemProcessorUnits" => "cpus",
|
63
|
-
"AssociatedSystemProcessorConfiguration/CurrentAvailableSystemProcessorUnits" => "avail_cpus"
|
55
|
+
"AssociatedSystemProcessorConfiguration/CurrentAvailableSystemProcessorUnits" => "avail_cpus",
|
56
|
+
"MachineTypeModelAndSerialNumber/MachineType" => "mtype",
|
57
|
+
"MachineTypeModelAndSerialNumber/Model" => "model",
|
58
|
+
"MachineTypeModelAndSerialNumber/SerialNumber" => "serial",
|
64
59
|
}.freeze
|
65
60
|
|
66
61
|
def initialize(doc)
|
@@ -68,10 +63,6 @@ module IbmPowerHmc
|
|
68
63
|
info = doc.elements["content/ManagedSystem:ManagedSystem"]
|
69
64
|
get_values(info, XMLMAP)
|
70
65
|
end
|
71
|
-
|
72
|
-
def to_s
|
73
|
-
"sys name=#{@name} state=#{@state} ip=#{@ipaddr} mem=#{@memory}MB avail=#{@avail_mem}MB CPUs=#{@cpus} avail=#{@avail_cpus}"
|
74
|
-
end
|
75
66
|
end
|
76
67
|
|
77
68
|
# Logical Partition information
|
@@ -96,10 +87,6 @@ module IbmPowerHmc
|
|
96
87
|
@sys_uuid = URI(sys_href).path.split('/').last
|
97
88
|
get_values(info, XMLMAP)
|
98
89
|
end
|
99
|
-
|
100
|
-
def to_s
|
101
|
-
"lpar name=#{@name} id=#{@id} state=#{@state} type=#{@type} memory=#{@memory}MB dedicated cpus=#{@dedicated}"
|
102
|
-
end
|
103
90
|
end
|
104
91
|
|
105
92
|
# VIOS information
|
@@ -122,21 +109,12 @@ module IbmPowerHmc
|
|
122
109
|
@sys_uuid = URI(sys_href).path.split('/').last
|
123
110
|
get_values(info, XMLMAP)
|
124
111
|
end
|
125
|
-
|
126
|
-
def to_s
|
127
|
-
"vios name=#{@name} id=#{@id} state=#{@state} type=#{@type} memory=#{@memory}MB dedicated cpus=#{@dedicated}"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# LPAR profile
|
132
|
-
class LogicalPartitionProfile < HmcObject
|
133
|
-
attr_reader :lpar_uuid
|
134
|
-
|
135
|
-
# Damien: TBD
|
136
112
|
end
|
137
113
|
|
138
114
|
# HMC Event
|
139
115
|
class Event < HmcObject
|
116
|
+
attr_reader :published
|
117
|
+
|
140
118
|
XMLMAP = {
|
141
119
|
"EventID" => "id",
|
142
120
|
"EventType" => "type",
|
@@ -146,12 +124,25 @@ module IbmPowerHmc
|
|
146
124
|
|
147
125
|
def initialize(doc)
|
148
126
|
super(doc)
|
127
|
+
@published = doc.elements["published"].text
|
149
128
|
info = doc.elements["content/Event:Event"]
|
150
129
|
get_values(info, XMLMAP)
|
151
130
|
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Error response from HMC
|
134
|
+
class HttpErrorResponse < HmcObject
|
135
|
+
XMLMAP = {
|
136
|
+
"HTTPStatus" => "status",
|
137
|
+
"RequestURI" => "uri",
|
138
|
+
"ReasonCode" => "reason",
|
139
|
+
"Message" => "message",
|
140
|
+
}.freeze
|
152
141
|
|
153
|
-
def
|
154
|
-
|
142
|
+
def initialize(doc)
|
143
|
+
super(doc)
|
144
|
+
info = doc.elements["content/HttpErrorResponse:HttpErrorResponse"]
|
145
|
+
get_values(info, XMLMAP)
|
155
146
|
end
|
156
147
|
end
|
157
148
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module IbmPowerHmc
|
7
|
+
class Connection
|
8
|
+
##
|
9
|
+
# @!method managed_system_metrics(sys_uuid:, start_ts: nil, end_ts: nil, no_samples: nil)
|
10
|
+
# Retrieve metrics for a managed system.
|
11
|
+
# @param sys_uuid [String] The managed system UUID.
|
12
|
+
# @param start_ts [String] Start timestamp.
|
13
|
+
# @param end_ts [String] End timestamp.
|
14
|
+
# @param no_samples [Integer] Number of samples.
|
15
|
+
# @return [Array<Hash>] The processed metrics for the managed system.
|
16
|
+
def managed_system_metrics(sys_uuid:, start_ts: nil, end_ts: nil, no_samples: nil)
|
17
|
+
method_url = "/rest/api/pcm/ManagedSystem/#{sys_uuid}/ProcessedMetrics"
|
18
|
+
query = []
|
19
|
+
query << "StartTS=#{start_ts}" unless start_ts.nil?
|
20
|
+
query << "EndTS=#{end_ts}" unless end_ts.nil?
|
21
|
+
query << "NoOfSamples=#{no_samples}" unless no_samples.nil?
|
22
|
+
method_url += "?" + query.compact.join('&') unless query.empty?
|
23
|
+
|
24
|
+
response = request(:get, method_url)
|
25
|
+
doc = REXML::Document.new(response.body)
|
26
|
+
metrics = []
|
27
|
+
doc.each_element("feed/entry") do |entry|
|
28
|
+
category = entry.elements["category"]
|
29
|
+
next if category.nil?
|
30
|
+
|
31
|
+
term = category.attributes["term"]
|
32
|
+
next if term.nil? || term != "ManagedSystem"
|
33
|
+
|
34
|
+
link = entry.elements["link"]
|
35
|
+
next if link.nil?
|
36
|
+
|
37
|
+
href = link.attributes["href"]
|
38
|
+
next if href.nil?
|
39
|
+
|
40
|
+
# Validate URI
|
41
|
+
begin
|
42
|
+
href = URI(href)
|
43
|
+
rescue
|
44
|
+
next
|
45
|
+
end
|
46
|
+
# Remove https://hostname:port prefix.
|
47
|
+
href.scheme = href.host = href.port = nil
|
48
|
+
|
49
|
+
response = request(:get, href.to_s)
|
50
|
+
metrics << JSON.parse(response.body)
|
51
|
+
end
|
52
|
+
metrics
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/ibm_power_hmc.rb
CHANGED
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ibm_power_hmc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- IBM Power
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -25,12 +25,14 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.1'
|
27
27
|
description: A Ruby gem for interacting with the IBM Hardware Management Console (HMC).
|
28
|
-
email:
|
28
|
+
email:
|
29
29
|
executables: []
|
30
30
|
extensions: []
|
31
31
|
extra_rdoc_files: []
|
32
32
|
files:
|
33
33
|
- ".gitignore"
|
34
|
+
- ".rubocop.yml"
|
35
|
+
- ".rubocop_local.yml"
|
34
36
|
- CHANGELOG.md
|
35
37
|
- Gemfile
|
36
38
|
- Gemfile.lock
|
@@ -44,6 +46,7 @@ files:
|
|
44
46
|
- lib/ibm_power_hmc/connection.rb
|
45
47
|
- lib/ibm_power_hmc/job.rb
|
46
48
|
- lib/ibm_power_hmc/objects.rb
|
49
|
+
- lib/ibm_power_hmc/pcm.rb
|
47
50
|
- lib/ibm_power_hmc/version.rb
|
48
51
|
homepage: http://github.com/IBM/ibm_power_hmc_sdk_ruby
|
49
52
|
licenses:
|
@@ -53,7 +56,7 @@ metadata:
|
|
53
56
|
homepage_uri: http://github.com/IBM/ibm_power_hmc_sdk_ruby
|
54
57
|
source_code_uri: http://github.com/IBM/ibm_power_hmc_sdk_ruby
|
55
58
|
changelog_uri: http://github.com/IBM/ibm_power_hmc_sdk_ruby/blob/master/CHANGELOG.md
|
56
|
-
post_install_message:
|
59
|
+
post_install_message:
|
57
60
|
rdoc_options: []
|
58
61
|
require_paths:
|
59
62
|
- lib
|
@@ -68,8 +71,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
71
|
- !ruby/object:Gem::Version
|
69
72
|
version: '0'
|
70
73
|
requirements: []
|
71
|
-
rubygems_version: 3.
|
72
|
-
signing_key:
|
74
|
+
rubygems_version: 3.0.3
|
75
|
+
signing_key:
|
73
76
|
specification_version: 4
|
74
77
|
summary: IBM Power HMC Ruby gem.
|
75
78
|
test_files: []
|