ibm_power_hmc 0.1.1 → 0.4.0
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 +4 -4
- data/.gitignore +1 -0
- data/.rubocop_local.yml +4 -2
- data/README.md +6 -0
- data/lib/ibm_power_hmc/connection.rb +175 -64
- data/lib/ibm_power_hmc/job.rb +14 -29
- data/lib/ibm_power_hmc/parser.rb +302 -0
- data/lib/ibm_power_hmc/pcm.rb +94 -27
- data/lib/ibm_power_hmc/version.rb +1 -1
- data/lib/ibm_power_hmc.rb +4 -3
- metadata +4 -5
- data/Gemfile.lock +0 -37
- data/lib/ibm_power_hmc/objects.rb +0 -148
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c19305b95374164ab2a6e6168a4a292ea0666065cbcbe8f05dea30483b622055
|
4
|
+
data.tar.gz: be50d67e7c462cc17f20be3f643c6029e4f2ba7d43f872f1821bbe428f0e11fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1191f64dd2f5c550d25a372b4a0502dd4e7b5a8e779a2dacdf079a22f3a8b8092af6e4ddff514b0e06dddf8239985033034959e385f951f2f535f092866cbd12
|
7
|
+
data.tar.gz: d6af992547d99624f59e6eb5ec3404768c91d1b9c9809e9542966fee15b4a350e8b8803e6fd25a597c48699b630171b7cae8327108f0ec6616e2329c5441bf1c
|
data/.gitignore
CHANGED
data/.rubocop_local.yml
CHANGED
data/README.md
CHANGED
@@ -42,6 +42,12 @@ puts hmc.name
|
|
42
42
|
puts hmc.version
|
43
43
|
```
|
44
44
|
|
45
|
+
Retrieving managed systems that are powered on:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
hc.managed_systems("State" => "operating")
|
49
|
+
```
|
50
|
+
|
45
51
|
Listing the logical partitions and virtual I/O servers of each managed system:
|
46
52
|
|
47
53
|
```ruby
|
@@ -2,24 +2,21 @@
|
|
2
2
|
|
3
3
|
# Module for IBM HMC Rest API Client
|
4
4
|
module IbmPowerHmc
|
5
|
-
require_relative 'pcm.rb'
|
6
|
-
|
7
5
|
class Error < StandardError; end
|
8
6
|
|
9
7
|
##
|
10
8
|
# HMC REST Client connection.
|
11
9
|
class Connection
|
12
10
|
##
|
13
|
-
# @!method initialize(host:, username: "hscroot",
|
11
|
+
# @!method initialize(host:, password:, username: "hscroot", port: 12_443, validate_ssl: true)
|
14
12
|
# Create a new HMC connection.
|
15
13
|
#
|
16
14
|
# @param host [String] Hostname of the HMC.
|
17
|
-
# @param username [String] User name.
|
18
15
|
# @param password [String] Password.
|
16
|
+
# @param username [String] User name.
|
19
17
|
# @param port [Integer] TCP port number.
|
20
18
|
# @param validate_ssl [Boolean] Verify SSL certificates.
|
21
|
-
def initialize(host:, username: "hscroot",
|
22
|
-
# Damien: use URI::HTTPS
|
19
|
+
def initialize(host:, password:, username: "hscroot", port: 12_443, validate_ssl: true)
|
23
20
|
@hostname = "#{host}:#{port}"
|
24
21
|
@username = username
|
25
22
|
@password = password
|
@@ -37,10 +34,8 @@ module IbmPowerHmc
|
|
37
34
|
:content_type => "application/vnd.ibm.powervm.web+xml; type=LogonRequest"
|
38
35
|
}
|
39
36
|
doc = REXML::Document.new("")
|
40
|
-
doc.add_element("LogonRequest",
|
41
|
-
|
42
|
-
"schemaVersion" => "V1_1_0"
|
43
|
-
})
|
37
|
+
doc.add_element("LogonRequest", "schemaVersion" => "V1_1_0")
|
38
|
+
doc.root.add_namespace("http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/")
|
44
39
|
doc.root.add_element("UserID").text = @username
|
45
40
|
doc.root.add_element("Password").text = @password
|
46
41
|
|
@@ -69,15 +64,6 @@ module IbmPowerHmc
|
|
69
64
|
@api_session_token = nil
|
70
65
|
end
|
71
66
|
|
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
67
|
##
|
82
68
|
# @!method management_console
|
83
69
|
# Retrieve information about the management console.
|
@@ -85,20 +71,20 @@ module IbmPowerHmc
|
|
85
71
|
def management_console
|
86
72
|
method_url = "/rest/api/uom/ManagementConsole"
|
87
73
|
response = request(:get, method_url)
|
88
|
-
doc = REXML::Document.new(response.body)
|
89
74
|
# This request returns a feed with a single entry.
|
90
|
-
|
75
|
+
FeedParser.new(response.body).objects(:ManagementConsole).first
|
91
76
|
end
|
92
77
|
|
93
78
|
##
|
94
|
-
# @!method managed_systems
|
79
|
+
# @!method managed_systems(search = {})
|
95
80
|
# Retrieve the list of systems managed by the HMC.
|
81
|
+
# @param search [Hash] The optional property name and value to match.
|
96
82
|
# @return [Array<IbmPowerHmc::ManagedSystem>] The list of managed systems.
|
97
|
-
def managed_systems
|
83
|
+
def managed_systems(search = {})
|
98
84
|
method_url = "/rest/api/uom/ManagedSystem"
|
85
|
+
search.each { |key, value| method_url += "/search/(#{key}==#{value})" }
|
99
86
|
response = request(:get, method_url)
|
100
|
-
|
101
|
-
parse_feed(doc, ManagedSystem)
|
87
|
+
FeedParser.new(response.body).objects(:ManagedSystem)
|
102
88
|
end
|
103
89
|
|
104
90
|
##
|
@@ -106,31 +92,30 @@ module IbmPowerHmc
|
|
106
92
|
# Retrieve information about a managed system.
|
107
93
|
# @param sys_uuid [String] The UUID of the managed system.
|
108
94
|
# @param group_name [String] The extended group attributes.
|
109
|
-
# @return [IbmPowerHmc::ManagedSystem] The
|
95
|
+
# @return [IbmPowerHmc::ManagedSystem] The managed system.
|
110
96
|
def managed_system(sys_uuid, group_name = nil)
|
111
97
|
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}"
|
112
98
|
method_url += "?group=#{group_name}" unless group_name.nil?
|
113
99
|
|
114
100
|
response = request(:get, method_url)
|
115
|
-
|
116
|
-
entry = doc.elements["entry"]
|
117
|
-
ManagedSystem.new(entry)
|
101
|
+
Parser.new(response.body).object(:ManagedSystem)
|
118
102
|
end
|
119
103
|
|
120
104
|
##
|
121
|
-
# @!method lpars(sys_uuid = nil)
|
105
|
+
# @!method lpars(sys_uuid = nil, search = {})
|
122
106
|
# Retrieve the list of logical partitions managed by the HMC.
|
123
107
|
# @param sys_uuid [String] The UUID of the managed system.
|
108
|
+
# @param search [Hash] The optional property name and value to match.
|
124
109
|
# @return [Array<IbmPowerHmc::LogicalPartition>] The list of logical partitions.
|
125
|
-
def lpars(sys_uuid = nil)
|
110
|
+
def lpars(sys_uuid = nil, search = {})
|
126
111
|
if sys_uuid.nil?
|
127
112
|
method_url = "/rest/api/uom/LogicalPartition"
|
113
|
+
search.each { |key, value| method_url += "/search/(#{key}==#{value})" }
|
128
114
|
else
|
129
115
|
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/LogicalPartition"
|
130
116
|
end
|
131
117
|
response = request(:get, method_url)
|
132
|
-
|
133
|
-
parse_feed(doc, LogicalPartition)
|
118
|
+
FeedParser.new(response.body).objects(:LogicalPartition)
|
134
119
|
end
|
135
120
|
|
136
121
|
##
|
@@ -149,15 +134,14 @@ module IbmPowerHmc
|
|
149
134
|
method_url += "?group=#{group_name}" unless group_name.nil?
|
150
135
|
|
151
136
|
response = request(:get, method_url)
|
152
|
-
|
153
|
-
entry = doc.elements["entry"]
|
154
|
-
LogicalPartition.new(entry)
|
137
|
+
Parser.new(response.body).object(:LogicalPartition)
|
155
138
|
end
|
156
139
|
|
157
140
|
##
|
158
141
|
# @!method lpar_quick_property(lpar_uuid, property_name)
|
159
142
|
# Retrieve a quick property of a logical partition.
|
160
143
|
# @param lpar_uuid [String] The UUID of the logical partition.
|
144
|
+
# @param property_name [String] The quick property name.
|
161
145
|
# @return [String] The quick property value.
|
162
146
|
def lpar_quick_property(lpar_uuid, property_name)
|
163
147
|
method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/quick/#{property_name}"
|
@@ -167,19 +151,31 @@ module IbmPowerHmc
|
|
167
151
|
end
|
168
152
|
|
169
153
|
##
|
170
|
-
# @!method
|
154
|
+
# @!method rename_lpar(lpar_uuid, new_name)
|
155
|
+
# Rename a logical partition.
|
156
|
+
# @param lpar_uuid [String] The UUID of the logical partition.
|
157
|
+
# @param new_name [String] The new name of the logical partition.
|
158
|
+
def rename_lpar(lpar_uuid, new_name)
|
159
|
+
method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}"
|
160
|
+
|
161
|
+
modify_object(method_url) { |lpar| lpar.name = new_name }
|
162
|
+
end
|
163
|
+
|
164
|
+
##
|
165
|
+
# @!method vioses(sys_uuid = nil, search = {})
|
171
166
|
# Retrieve the list of virtual I/O servers managed by the HMC.
|
172
167
|
# @param sys_uuid [String] The UUID of the managed system.
|
168
|
+
# @param search [Hash] The optional property name and value to match.
|
173
169
|
# @return [Array<IbmPowerHmc::VirtualIOServer>] The list of virtual I/O servers.
|
174
|
-
def vioses(sys_uuid = nil)
|
170
|
+
def vioses(sys_uuid = nil, search = {})
|
175
171
|
if sys_uuid.nil?
|
176
172
|
method_url = "/rest/api/uom/VirtualIOServer"
|
173
|
+
search.each { |key, value| method_url += "/search/(#{key}==#{value})" }
|
177
174
|
else
|
178
175
|
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/VirtualIOServer"
|
179
176
|
end
|
180
177
|
response = request(:get, method_url)
|
181
|
-
|
182
|
-
parse_feed(doc, VirtualIOServer)
|
178
|
+
FeedParser.new(response.body).objects(:VirtualIOServer)
|
183
179
|
end
|
184
180
|
|
185
181
|
##
|
@@ -198,9 +194,27 @@ module IbmPowerHmc
|
|
198
194
|
method_url += "?group=#{group_name}" unless group_name.nil?
|
199
195
|
|
200
196
|
response = request(:get, method_url)
|
201
|
-
|
202
|
-
|
203
|
-
|
197
|
+
Parser.new(response.body).object(:VirtualIOServer)
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
201
|
+
# @!method network_adapter_lpar(lpar_uuid, netadap_uuid = nil)
|
202
|
+
# Retrieve one or all virtual ethernet network adapters attached to a logical partition.
|
203
|
+
# @param lpar_uuid [String] UUID of the logical partition.
|
204
|
+
# @param netadap_uuid [String] UUID of the adapter to match (returns all adapters if omitted).
|
205
|
+
# @return [Array<IbmPowerHmc::ClientNetworkAdapter>] The list of network adapters.
|
206
|
+
def network_adapter_lpar(lpar_uuid, netadap_uuid = nil)
|
207
|
+
network_adapter("LogicalPartition", lpar_uuid, netadap_uuid)
|
208
|
+
end
|
209
|
+
|
210
|
+
##
|
211
|
+
# @!method network_adapter_vios(vios_uuid, netadap_uuid = nil)
|
212
|
+
# Retrieve one or all virtual ethernet network adapters attached to a Virtual I/O Server.
|
213
|
+
# @param vios_uuid [String] UUID of the Virtual I/O Server.
|
214
|
+
# @param netadap_uuid [String] UUID of the adapter to match (returns all adapters if omitted).
|
215
|
+
# @return [Array<IbmPowerHmc::ClientNetworkAdapter>] The list of network adapters.
|
216
|
+
def network_adapter_vios(vios_uuid, netadap_uuid = nil)
|
217
|
+
network_adapter("VirtualIOServer", vios_uuid, netadap_uuid)
|
204
218
|
end
|
205
219
|
|
206
220
|
##
|
@@ -221,9 +235,7 @@ module IbmPowerHmc
|
|
221
235
|
##
|
222
236
|
# @!method poweroff_lpar(lpar_uuid, params = {}, sync = true)
|
223
237
|
# Power off a logical partition.
|
224
|
-
# @param
|
225
|
-
# @param params [Hash] Job parameters.
|
226
|
-
# @param sync [Boolean] Start the job and wait for its completion.
|
238
|
+
# @param (see #poweron_lpar)
|
227
239
|
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
228
240
|
def poweroff_lpar(lpar_uuid, params = {}, sync = true)
|
229
241
|
method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/do/PowerOff"
|
@@ -251,9 +263,7 @@ module IbmPowerHmc
|
|
251
263
|
##
|
252
264
|
# @!method poweroff_vios(vios_uuid, params = {}, sync = true)
|
253
265
|
# Power off a virtual I/O server.
|
254
|
-
# @param
|
255
|
-
# @param params [Hash] Job parameters.
|
256
|
-
# @param sync [Boolean] Start the job and wait for its completion.
|
266
|
+
# @param (see #poweron_vios)
|
257
267
|
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
258
268
|
def poweroff_vios(vios_uuid, params = {}, sync = true)
|
259
269
|
method_url = "/rest/api/uom/VirtualIOServer/#{vios_uuid}/do/PowerOff"
|
@@ -281,9 +291,7 @@ module IbmPowerHmc
|
|
281
291
|
##
|
282
292
|
# @!method poweroff_managed_system(sys_uuid, params = {}, sync = true)
|
283
293
|
# Power off a managed system.
|
284
|
-
# @param
|
285
|
-
# @param params [Hash] Job parameters.
|
286
|
-
# @param sync [Boolean] Start the job and wait for its completion.
|
294
|
+
# @param (see #poweron_managed_system)
|
287
295
|
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
288
296
|
def poweroff_managed_system(sys_uuid, params = {}, sync = true)
|
289
297
|
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/do/PowerOff"
|
@@ -293,6 +301,21 @@ module IbmPowerHmc
|
|
293
301
|
job
|
294
302
|
end
|
295
303
|
|
304
|
+
##
|
305
|
+
# @!method remove_connection(hmc_uuid, sys_uuid, sync = true)
|
306
|
+
# Remove a managed system from the management console.
|
307
|
+
# @param hmc_uuid [String] The UUID of the management console.
|
308
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
309
|
+
# @param sync [Boolean] Start the job and wait for its completion.
|
310
|
+
# @return [IbmPowerHmc::HmcJob] The HMC job.
|
311
|
+
def remove_connection(hmc_uuid, sys_uuid, sync = true)
|
312
|
+
method_url = "/rest/api/uom/ManagementConsole/#{hmc_uuid}/ManagedSystem/#{sys_uuid}/do/RemoveConnection"
|
313
|
+
|
314
|
+
job = HmcJob.new(self, method_url, "RemoveConnection", "ManagedSystem")
|
315
|
+
job.run if sync
|
316
|
+
job
|
317
|
+
end
|
318
|
+
|
296
319
|
##
|
297
320
|
# @!method cli_run(hmc_uuid, cmd, sync = true)
|
298
321
|
# Run a CLI command on the HMC as a job.
|
@@ -312,6 +335,29 @@ module IbmPowerHmc
|
|
312
335
|
job
|
313
336
|
end
|
314
337
|
|
338
|
+
##
|
339
|
+
# @!method virtual_switches(sys_uuid)
|
340
|
+
# Retrieve the list of virtual switches from a specified managed system.
|
341
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
342
|
+
# @return [Array<IbmPowerHmc::VirtualSwitch>] The list of virtual switches.
|
343
|
+
def virtual_switches(sys_uuid)
|
344
|
+
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/VirtualSwitch"
|
345
|
+
response = request(:get, method_url)
|
346
|
+
FeedParser.new(response.body).objects(:VirtualSwitch)
|
347
|
+
end
|
348
|
+
|
349
|
+
##
|
350
|
+
# @!method virtual_switch(vswitch_uuid, sys_uuid)
|
351
|
+
# Retrieve information about a virtual switch.
|
352
|
+
# @param vswitch_uuid [String] The UUID of the virtual switch.
|
353
|
+
# @param sys_uuid [String] The UUID of the managed system.
|
354
|
+
# @return [IbmPowerHmc::VirtualSwitch] The virtual switch.
|
355
|
+
def virtual_switch(vswitch_uuid, sys_uuid)
|
356
|
+
method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/VirtualSwitch/#{vswitch_uuid}"
|
357
|
+
response = request(:get, method_url)
|
358
|
+
Parser.new(response.body).object(:VirtualSwitch)
|
359
|
+
end
|
360
|
+
|
315
361
|
##
|
316
362
|
# @!method next_events(wait = true)
|
317
363
|
# Retrieve a list of events that occured since last call.
|
@@ -326,12 +372,22 @@ module IbmPowerHmc
|
|
326
372
|
# No need to sleep as the HMC already waits a bit before returning 204
|
327
373
|
break if response.code != 204 || !wait
|
328
374
|
end
|
329
|
-
|
330
|
-
|
375
|
+
FeedParser.new(response.body).objects(:Event)
|
376
|
+
end
|
377
|
+
|
378
|
+
##
|
379
|
+
# @!method schema(type)
|
380
|
+
# Retrieve the XML schema file for a given object type.
|
381
|
+
# @param type [String] The object type (e.g. "LogicalPartition", "inc/Types")
|
382
|
+
# @return [REXML::Document] The XML schema file.
|
383
|
+
def schema(type)
|
384
|
+
method_url = "/rest/api/web/schema/#{type}.xsd"
|
385
|
+
response = request(:get, method_url)
|
386
|
+
REXML::Document.new(response.body)
|
331
387
|
end
|
332
388
|
|
333
389
|
class HttpError < Error
|
334
|
-
attr_reader :status, :uri, :reason, :message
|
390
|
+
attr_reader :status, :uri, :reason, :message, :original_exception
|
335
391
|
|
336
392
|
##
|
337
393
|
# @!method initialize(err)
|
@@ -339,18 +395,24 @@ module IbmPowerHmc
|
|
339
395
|
# @param err [RestClient::Exception] The REST client exception.
|
340
396
|
def initialize(err)
|
341
397
|
super
|
398
|
+
@original_exception = err
|
342
399
|
@status = err.http_code
|
400
|
+
@message = err.message
|
343
401
|
|
344
402
|
# Try to parse body as an HttpErrorResponse
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
403
|
+
unless err.response.nil?
|
404
|
+
resp = Parser.new(err.response.body).object(:HttpErrorResponse)
|
405
|
+
unless resp.nil?
|
406
|
+
@uri = resp.uri
|
407
|
+
@reason = resp.reason
|
408
|
+
@message = resp.message
|
409
|
+
end
|
352
410
|
end
|
353
411
|
end
|
412
|
+
|
413
|
+
def to_s
|
414
|
+
"msg=\"#{@message}\" status=\"#{@status}\" reason=\"#{@reason}\" uri=#{@uri}"
|
415
|
+
end
|
354
416
|
end
|
355
417
|
|
356
418
|
##
|
@@ -364,11 +426,13 @@ module IbmPowerHmc
|
|
364
426
|
def request(method, url, headers = {}, payload = nil)
|
365
427
|
logon if @api_session_token.nil?
|
366
428
|
reauth = false
|
429
|
+
# Check for relative URLs
|
430
|
+
url = "https://#{@hostname}#{url}" if url.start_with?("/")
|
367
431
|
begin
|
368
|
-
headers = headers.merge(
|
432
|
+
headers = headers.merge("X-API-Session" => @api_session_token)
|
369
433
|
RestClient::Request.execute(
|
370
434
|
:method => method,
|
371
|
-
:url =>
|
435
|
+
:url => url,
|
372
436
|
:verify_ssl => @verify_ssl,
|
373
437
|
:payload => payload,
|
374
438
|
:headers => headers
|
@@ -384,5 +448,52 @@ module IbmPowerHmc
|
|
384
448
|
raise HttpError.new(e), "REST request failed"
|
385
449
|
end
|
386
450
|
end
|
451
|
+
|
452
|
+
private
|
453
|
+
|
454
|
+
# @!method modify_object(method_url, headers = {}, attempts = 5)
|
455
|
+
# Modify an object at a specified URI.
|
456
|
+
# @param method_url [String] The URL of the object to modify.
|
457
|
+
# @param headers [Hash] HTTP headers.
|
458
|
+
# @param attempts [Integer] Maximum number of retries.
|
459
|
+
# @yield [obj] The object to modify.
|
460
|
+
# @yieldparam obj [IbmPowerHmc::AbstractRest] The object to modify.
|
461
|
+
def modify_object(method_url, headers = {}, attempts = 5)
|
462
|
+
while attempts > 0
|
463
|
+
response = request(:get, method_url)
|
464
|
+
obj = Parser.new(response.body).object
|
465
|
+
|
466
|
+
yield obj
|
467
|
+
|
468
|
+
# Use ETag to ensure object has not changed.
|
469
|
+
headers = headers.merge("If-Match" => obj.etag, :content_type => obj.content_type)
|
470
|
+
begin
|
471
|
+
request(:post, method_url, headers, obj.xml.to_s)
|
472
|
+
break
|
473
|
+
rescue HttpError => e
|
474
|
+
attempts -= 1
|
475
|
+
# Will get 412 ("Precondition Failed") if ETag mismatches
|
476
|
+
raise if e.status != 412 || attempts == 0
|
477
|
+
end
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
##
|
482
|
+
# @!method network_adapter_lpar(lpar_uuid, netadap_uuid = nil)
|
483
|
+
# Retrieve one or all virtual ethernet network adapters attached to a Logical Partition or a Virtual I/O Server.
|
484
|
+
# @param vm_type [String] "Logical Partition" or "VirtualIOServer".
|
485
|
+
# @param lpar_uuid [String] UUID of the Logical Partition or the Virtual I/O Server.
|
486
|
+
# @param netadap_uuid [String] UUID of the adapter to match (returns all adapters if nil).
|
487
|
+
# @return [Array<IbmPowerHmc::ClientNetworkAdapter>] The list of network adapters.
|
488
|
+
def network_adapter(vm_type, lpar_uuid, netadap_uuid)
|
489
|
+
if netadap_uuid.nil?
|
490
|
+
method_url = "/rest/api/uom/#{vm_type}/#{lpar_uuid}/ClientNetworkAdapter"
|
491
|
+
else
|
492
|
+
method_url = "/rest/api/uom/#{vm_type}/#{lpar_uuid}/ClientNetworkAdapter/#{netadap_uuid}"
|
493
|
+
end
|
494
|
+
|
495
|
+
response = request(:get, method_url)
|
496
|
+
Parser.new(response.body).object(:ClientNetworkAdapter)
|
497
|
+
end
|
387
498
|
end
|
388
499
|
end
|
data/lib/ibm_power_hmc/job.rb
CHANGED
@@ -24,7 +24,7 @@ module IbmPowerHmc
|
|
24
24
|
end
|
25
25
|
|
26
26
|
##
|
27
|
-
# @!method
|
27
|
+
# @!method start
|
28
28
|
# Start the job asynchronously.
|
29
29
|
# @return [String] The ID of the job.
|
30
30
|
def start
|
@@ -32,25 +32,22 @@ module IbmPowerHmc
|
|
32
32
|
:content_type => "application/vnd.ibm.powervm.web+xml; type=JobRequest"
|
33
33
|
}
|
34
34
|
doc = REXML::Document.new("")
|
35
|
-
doc.add_element("JobRequest:JobRequest",
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
})
|
40
|
-
op = doc.root.add_element("RequestedOperation", {"schemaVersion" => "V1_1_0"})
|
35
|
+
doc.add_element("JobRequest:JobRequest", "schemaVersion" => "V1_1_0")
|
36
|
+
doc.root.add_namespace("http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/")
|
37
|
+
doc.root.add_namespace("JobRequest", "http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/")
|
38
|
+
op = doc.root.add_element("RequestedOperation", "schemaVersion" => "V1_1_0")
|
41
39
|
op.add_element("OperationName").text = @operation
|
42
40
|
op.add_element("GroupName").text = @group
|
43
|
-
|
44
|
-
jobparams = doc.root.add_element("JobParameters",
|
41
|
+
|
42
|
+
jobparams = doc.root.add_element("JobParameters", "schemaVersion" => "V1_1_0")
|
45
43
|
@params.each do |key, value|
|
46
|
-
jobparam = jobparams.add_element("JobParameter",
|
44
|
+
jobparam = jobparams.add_element("JobParameter", "schemaVersion" => "V1_1_0")
|
47
45
|
jobparam.add_element("ParameterName").text = key
|
48
46
|
jobparam.add_element("ParameterValue").text = value
|
49
47
|
end
|
50
48
|
response = @conn.request(:put, @method_url, headers, doc.to_s)
|
51
|
-
|
52
|
-
|
53
|
-
@id = info.elements["JobID"].text
|
49
|
+
jobresp = Parser.new(response.body).object(:JobResponse)
|
50
|
+
@id = jobresp.id
|
54
51
|
end
|
55
52
|
|
56
53
|
# @return [Hash] The job results returned by the HMC.
|
@@ -68,20 +65,9 @@ module IbmPowerHmc
|
|
68
65
|
:content_type => "application/vnd.ibm.powervm.web+xml; type=JobRequest"
|
69
66
|
}
|
70
67
|
response = @conn.request(:get, method_url, headers)
|
71
|
-
|
72
|
-
|
73
|
-
status
|
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
|
-
|
84
|
-
status
|
68
|
+
jobresp = Parser.new(response.body).object(:JobResponse)
|
69
|
+
@results = jobresp.results
|
70
|
+
jobresp.status
|
85
71
|
end
|
86
72
|
|
87
73
|
##
|
@@ -112,8 +98,7 @@ module IbmPowerHmc
|
|
112
98
|
# @return [String] The status of the job.
|
113
99
|
def run(timeout = 120, poll_interval = 0)
|
114
100
|
start
|
115
|
-
|
116
|
-
status
|
101
|
+
wait(timeout, poll_interval)
|
117
102
|
ensure
|
118
103
|
delete if defined?(@id)
|
119
104
|
end
|
@@ -0,0 +1,302 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module IbmPowerHmc
|
7
|
+
##
|
8
|
+
# Generic parser for HMC K2 XML responses.
|
9
|
+
class Parser
|
10
|
+
def initialize(body)
|
11
|
+
@doc = REXML::Document.new(body)
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# @!method entry
|
16
|
+
# Return the first K2 entry element in the response.
|
17
|
+
# @return [REXML::Element, nil] The first entry element.
|
18
|
+
def entry
|
19
|
+
@doc.elements["entry"]
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# @!method object(filter_type = nil)
|
24
|
+
# Parse the first K2 entry element into an object.
|
25
|
+
# @param filter_type [String] Entry type must match the specified type.
|
26
|
+
# @return [IbmPowerHmc::AbstractRest, nil] The parsed object.
|
27
|
+
def object(filter_type = nil)
|
28
|
+
self.class.to_obj(entry, filter_type)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.to_obj(entry, filter_type = nil)
|
32
|
+
return if entry.nil?
|
33
|
+
|
34
|
+
content = entry.elements["content[@type]"]
|
35
|
+
return if content.nil?
|
36
|
+
|
37
|
+
type = content.attributes["type"].split("=").last
|
38
|
+
return unless filter_type.nil? || filter_type.to_s == type
|
39
|
+
|
40
|
+
Module.const_get("IbmPowerHmc::#{type}").new(entry)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Parser for HMC K2 feeds.
|
46
|
+
# A feed encapsulates a list of entries like this:
|
47
|
+
# <feed>
|
48
|
+
# <entry>
|
49
|
+
# <!-- entry #1 -->
|
50
|
+
# </entry>
|
51
|
+
# <entry>
|
52
|
+
# <!-- entry #2 -->
|
53
|
+
# </entry>
|
54
|
+
# ...
|
55
|
+
# </feed>
|
56
|
+
class FeedParser < Parser
|
57
|
+
def entries
|
58
|
+
objs = []
|
59
|
+
@doc.each_element("feed/entry") do |entry|
|
60
|
+
objs << yield(entry)
|
61
|
+
end
|
62
|
+
objs
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# @!method objects(filter_type = nil)
|
67
|
+
# Parse feed entries into objects.
|
68
|
+
# @param filter_type [String] Filter entries based on content type.
|
69
|
+
# @return [Array<IbmPowerHmc::AbstractRest>] The list of objects.
|
70
|
+
def objects(filter_type = nil)
|
71
|
+
entries do |entry|
|
72
|
+
self.class.to_obj(entry, filter_type)
|
73
|
+
end.compact
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private_constant :Parser
|
78
|
+
private_constant :FeedParser
|
79
|
+
|
80
|
+
##
|
81
|
+
# HMC generic K2 XML entry.
|
82
|
+
# Encapsulate data for a single object.
|
83
|
+
# The XML looks like this:
|
84
|
+
# <entry>
|
85
|
+
# <id>uuid</id>
|
86
|
+
# <published>timestamp</published>
|
87
|
+
# <etag:etag>ETag</etag:etag>
|
88
|
+
# <content type="type">
|
89
|
+
# <!-- actual content here -->
|
90
|
+
# </content>
|
91
|
+
# </entry>
|
92
|
+
#
|
93
|
+
# @abstract
|
94
|
+
# @attr_reader [String] uuid The UUID of the object contained in the entry.
|
95
|
+
# @attr_reader [URI::HTTPS] href The URL of the object itself.
|
96
|
+
# @attr_reader [Time] published The time at which the entry was published.
|
97
|
+
# @attr_reader [String] etag The entity tag of the entry.
|
98
|
+
# @attr_reader [String] content_type The content type of the object contained in the entry.
|
99
|
+
# @attr_reader [REXML::Document] xml The XML document representing this object.
|
100
|
+
class AbstractRest
|
101
|
+
ATTRS = {}.freeze
|
102
|
+
attr_reader :uuid, :href, :published, :etag, :content_type, :xml
|
103
|
+
|
104
|
+
def initialize(doc)
|
105
|
+
@uuid = doc.elements["id"]&.text
|
106
|
+
link = doc.elements["link[@rel='SELF']"]
|
107
|
+
@href = URI(link.attributes["href"]) unless link.nil?
|
108
|
+
@published = Time.xmlschema(doc.elements["published"]&.text)
|
109
|
+
@etag = doc.elements["etag:etag"]&.text&.strip
|
110
|
+
content = doc.elements["content"]
|
111
|
+
@content_type = content.attributes["type"]
|
112
|
+
@xml = content.elements.first
|
113
|
+
define_attrs(self.class::ATTRS)
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# @!method define_attr(varname, xpath)
|
118
|
+
# Define an instance variable using the text of an XML element as value.
|
119
|
+
# @param varname [String] The name of the instance variable.
|
120
|
+
# @param xpath [String] The XPath of the XML element containing the text.
|
121
|
+
def define_attr(varname, xpath)
|
122
|
+
value = singleton(xpath)
|
123
|
+
self.class.__send__(:attr_reader, varname)
|
124
|
+
instance_variable_set("@#{varname}", value)
|
125
|
+
end
|
126
|
+
|
127
|
+
##
|
128
|
+
# @!method define_attrs(hash)
|
129
|
+
# Define instance variables using the texts of XML elements as values.
|
130
|
+
# @param hash [Hash] The name of the instance variables and the XPaths
|
131
|
+
# of the XML elements containing the values.
|
132
|
+
def define_attrs(hash)
|
133
|
+
hash.each do |key, value|
|
134
|
+
define_attr(key, value)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# @!method singleton(xpath, attr = nil)
|
140
|
+
# Get the text (or the value of a specified attribute) of an XML element.
|
141
|
+
# @param xpath [String] The XPath of the XML element.
|
142
|
+
# @param attr [String] The name of the attribute.
|
143
|
+
# @return [String, nil] The text or attribute value of the XML element or nil.
|
144
|
+
# @example lpar.singleton("PartitionProcessorConfiguration/*/MaximumVirtualProcessors").to_i
|
145
|
+
def singleton(xpath, attr = nil)
|
146
|
+
elem = xml.elements[xpath]
|
147
|
+
return if elem.nil?
|
148
|
+
|
149
|
+
attr.nil? ? elem.text&.strip : elem.attributes[attr]
|
150
|
+
end
|
151
|
+
|
152
|
+
def extract_uuid_from_href(href)
|
153
|
+
URI(href).path.split('/').last
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# HMC information
|
158
|
+
class ManagementConsole < AbstractRest
|
159
|
+
ATTRS = {
|
160
|
+
:name => "ManagementConsoleName",
|
161
|
+
:build_level => "VersionInfo/BuildLevel",
|
162
|
+
:version => "BaseVersion"
|
163
|
+
}.freeze
|
164
|
+
|
165
|
+
def managed_systems_uuids
|
166
|
+
xml.get_elements("ManagedSystems/link").map do |link|
|
167
|
+
extract_uuid_from_href(link.attributes["href"])
|
168
|
+
end.compact
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Managed System information
|
173
|
+
class ManagedSystem < AbstractRest
|
174
|
+
ATTRS = {
|
175
|
+
:name => "SystemName",
|
176
|
+
:state => "State",
|
177
|
+
:hostname => "Hostname",
|
178
|
+
:ipaddr => "PrimaryIPAddress",
|
179
|
+
:fwversion => "SystemFirmware",
|
180
|
+
:memory => "AssociatedSystemMemoryConfiguration/InstalledSystemMemory",
|
181
|
+
:avail_mem => "AssociatedSystemMemoryConfiguration/CurrentAvailableSystemMemory",
|
182
|
+
:cpus => "AssociatedSystemProcessorConfiguration/InstalledSystemProcessorUnits",
|
183
|
+
:avail_cpus => "AssociatedSystemProcessorConfiguration/CurrentAvailableSystemProcessorUnits",
|
184
|
+
:mtype => "MachineTypeModelAndSerialNumber/MachineType",
|
185
|
+
:model => "MachineTypeModelAndSerialNumber/Model",
|
186
|
+
:serial => "MachineTypeModelAndSerialNumber/SerialNumber"
|
187
|
+
}.freeze
|
188
|
+
|
189
|
+
def lpars_uuids
|
190
|
+
xml.get_elements("AssociatedLogicalPartitions/link").map do |link|
|
191
|
+
extract_uuid_from_href(link.attributes["href"])
|
192
|
+
end.compact
|
193
|
+
end
|
194
|
+
|
195
|
+
def vioses_uuids
|
196
|
+
xml.get_elements("AssociatedVirtualIOServers/link").map do |link|
|
197
|
+
extract_uuid_from_href(link.attributes["href"])
|
198
|
+
end.compact
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# Common class for LPAR and VIOS
|
203
|
+
class BasePartition < AbstractRest
|
204
|
+
ATTRS = {
|
205
|
+
:name => "PartitionName",
|
206
|
+
:id => "PartitionID",
|
207
|
+
:state => "PartitionState",
|
208
|
+
:type => "PartitionType",
|
209
|
+
:memory => "PartitionMemoryConfiguration/CurrentMemory",
|
210
|
+
:dedicated => "PartitionProcessorConfiguration/HasDedicatedProcessors",
|
211
|
+
:rmc_state => "ResourceMonitoringControlState",
|
212
|
+
:rmc_ipaddr => "ResourceMonitoringIPAddress",
|
213
|
+
:os => "OperatingSystemVersion",
|
214
|
+
:ref_code => "ReferenceCode"
|
215
|
+
}.freeze
|
216
|
+
|
217
|
+
def sys_uuid
|
218
|
+
sys_href = singleton("AssociatedManagedSystem", "href")
|
219
|
+
extract_uuid_from_href(sys_href)
|
220
|
+
end
|
221
|
+
|
222
|
+
def net_adap_uuids
|
223
|
+
xml.get_elements("ClientNetworkAdapters/link").map do |link|
|
224
|
+
extract_uuid_from_href(link.attributes["href"])
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def name=(name)
|
229
|
+
xml.elements[ATTRS[:name]].text = name
|
230
|
+
@name = name
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# Logical Partition information
|
235
|
+
class LogicalPartition < BasePartition
|
236
|
+
end
|
237
|
+
|
238
|
+
# VIOS information
|
239
|
+
class VirtualIOServer < BasePartition
|
240
|
+
end
|
241
|
+
|
242
|
+
# Virtual Switch information
|
243
|
+
class VirtualSwitch < AbstractRest
|
244
|
+
ATTRS = {
|
245
|
+
:id => "SwitchID",
|
246
|
+
:mode => "SwitchMode",
|
247
|
+
:name => "SwitchName"
|
248
|
+
}.freeze
|
249
|
+
|
250
|
+
def sys_uuid
|
251
|
+
href.path.split('/')[-3]
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# HMC Event
|
256
|
+
class Event < AbstractRest
|
257
|
+
ATTRS = {
|
258
|
+
:id => "EventID",
|
259
|
+
:type => "EventType",
|
260
|
+
:data => "EventData",
|
261
|
+
:detail => "EventDetail"
|
262
|
+
}.freeze
|
263
|
+
end
|
264
|
+
|
265
|
+
# Network adapter information
|
266
|
+
class ClientNetworkAdapter < AbstractRest
|
267
|
+
ATTRS = {
|
268
|
+
:macaddr => "MACAddress",
|
269
|
+
:vswitch_id => "VirtualSwitchID",
|
270
|
+
:vlan_id => "PortVLANID"
|
271
|
+
}.freeze
|
272
|
+
end
|
273
|
+
|
274
|
+
# Error response from HMC
|
275
|
+
class HttpErrorResponse < AbstractRest
|
276
|
+
ATTRS = {
|
277
|
+
:status => "HTTPStatus",
|
278
|
+
:uri => "RequestURI",
|
279
|
+
:reason => "ReasonCode",
|
280
|
+
:message => "Message"
|
281
|
+
}.freeze
|
282
|
+
end
|
283
|
+
|
284
|
+
# Job Response
|
285
|
+
class JobResponse < AbstractRest
|
286
|
+
ATTRS = {
|
287
|
+
:id => "JobID",
|
288
|
+
:status => "Status",
|
289
|
+
:message => "ResponseException/Message"
|
290
|
+
}.freeze
|
291
|
+
|
292
|
+
def results
|
293
|
+
results = {}
|
294
|
+
xml.each_element("Results/JobParameter") do |jobparam|
|
295
|
+
name = jobparam.elements["ParameterName"]&.text&.strip
|
296
|
+
value = jobparam.elements["ParameterValue"]&.text&.strip
|
297
|
+
results[name] = value unless name.nil?
|
298
|
+
end
|
299
|
+
results
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
data/lib/ibm_power_hmc/pcm.rb
CHANGED
@@ -5,26 +5,62 @@ require 'uri'
|
|
5
5
|
|
6
6
|
module IbmPowerHmc
|
7
7
|
class Connection
|
8
|
+
def pcm_preferences
|
9
|
+
method_url = "/rest/api/pcm/preferences"
|
10
|
+
|
11
|
+
response = request(:get, method_url)
|
12
|
+
REXML::Document.new(response.body)
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# @!method phyp_metrics(sys_uuid:, start_ts: nil, end_ts: nil, short_term: false)
|
17
|
+
# Retrieve PowerVM metrics for a given managed system.
|
18
|
+
# @param sys_uuid [String] The managed system UUID.
|
19
|
+
# @param start_ts [Time] Start timestamp.
|
20
|
+
# @param end_ts [Time] End timestamp.
|
21
|
+
# @param short_term [Boolean] Retrieve short term monitor metrics (default to long term).
|
22
|
+
# @return [Array<Hash>] The PowerVM metrics for the managed system.
|
23
|
+
def phyp_metrics(sys_uuid:, start_ts: nil, end_ts: nil, short_term: false)
|
24
|
+
type = short_term ? "ShortTermMonitor" : "LongTermMonitor"
|
25
|
+
method_url = "/rest/api/pcm/ManagedSystem/#{sys_uuid}/RawMetrics/#{type}"
|
26
|
+
query = {}
|
27
|
+
query["StartTS"] = self.class.format_time(start_ts) unless start_ts.nil?
|
28
|
+
query["EndTS"] = self.class.format_time(end_ts) unless end_ts.nil?
|
29
|
+
method_url += "?" + query.map { |h| h.join("=") }.join("&") unless query.empty?
|
30
|
+
|
31
|
+
response = request(:get, method_url)
|
32
|
+
FeedParser.new(response.body).entries do |entry|
|
33
|
+
link = entry.elements["link"]
|
34
|
+
next if link.nil?
|
35
|
+
|
36
|
+
href = link.attributes["href"]
|
37
|
+
next if href.nil?
|
38
|
+
|
39
|
+
response = request(:get, href)
|
40
|
+
JSON.parse(response.body)
|
41
|
+
end.compact
|
42
|
+
end
|
43
|
+
|
8
44
|
##
|
9
|
-
# @!method managed_system_metrics(sys_uuid:, start_ts: nil, end_ts: nil, no_samples: nil)
|
45
|
+
# @!method managed_system_metrics(sys_uuid:, start_ts: nil, end_ts: nil, no_samples: nil, aggregated: false)
|
10
46
|
# Retrieve metrics for a managed system.
|
11
47
|
# @param sys_uuid [String] The managed system UUID.
|
12
|
-
# @param start_ts [
|
13
|
-
# @param end_ts [
|
48
|
+
# @param start_ts [Time] Start timestamp.
|
49
|
+
# @param end_ts [Time] End timestamp.
|
14
50
|
# @param no_samples [Integer] Number of samples.
|
15
|
-
# @
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
query
|
21
|
-
query
|
22
|
-
|
51
|
+
# @param aggregated [Boolean] Retrieve aggregated metrics (default to Processed).
|
52
|
+
# @return [Array<Hash>] The metrics for the managed system.
|
53
|
+
def managed_system_metrics(sys_uuid:, start_ts: nil, end_ts: nil, no_samples: nil, aggregated: false)
|
54
|
+
type = aggregated ? "AggregatedMetrics" : "ProcessedMetrics"
|
55
|
+
method_url = "/rest/api/pcm/ManagedSystem/#{sys_uuid}/#{type}"
|
56
|
+
query = {}
|
57
|
+
query["StartTS"] = self.class.format_time(start_ts) unless start_ts.nil?
|
58
|
+
query["EndTS"] = self.class.format_time(end_ts) unless end_ts.nil?
|
59
|
+
query["NoOfSamples"] = no_samples unless no_samples.nil?
|
60
|
+
method_url += "?" + query.map { |h| h.join("=") }.join("&") unless query.empty?
|
23
61
|
|
24
62
|
response = request(:get, method_url)
|
25
|
-
|
26
|
-
metrics = []
|
27
|
-
doc.each_element("feed/entry") do |entry|
|
63
|
+
FeedParser.new(response.body).entries do |entry|
|
28
64
|
category = entry.elements["category"]
|
29
65
|
next if category.nil?
|
30
66
|
|
@@ -37,19 +73,50 @@ module IbmPowerHmc
|
|
37
73
|
href = link.attributes["href"]
|
38
74
|
next if href.nil?
|
39
75
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
76
|
+
response = request(:get, href)
|
77
|
+
JSON.parse(response.body)
|
78
|
+
end.compact
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# @!method lpar_metrics(sys_uuid:, lpar_uuid:, start_ts: nil, end_ts: nil, no_samples: nil, aggregated: false)
|
83
|
+
# Retrieve metrics for a logical partition.
|
84
|
+
# @param sys_uuid [String] The managed system UUID.
|
85
|
+
# @param lpar_uuid [String] The logical partition UUID.
|
86
|
+
# @param start_ts [Time] Start timestamp.
|
87
|
+
# @param end_ts [Time] End timestamp.
|
88
|
+
# @param no_samples [Integer] Number of samples.
|
89
|
+
# @param aggregated [Boolean] Retrieve aggregated metrics (default to Processed).
|
90
|
+
# @return [Array<Hash>] The metrics for the logical partition.
|
91
|
+
def lpar_metrics(sys_uuid:, lpar_uuid:, start_ts: nil, end_ts: nil, no_samples: nil, aggregated: false)
|
92
|
+
type = aggregated ? "AggregatedMetrics" : "ProcessedMetrics"
|
93
|
+
method_url = "/rest/api/pcm/ManagedSystem/#{sys_uuid}/LogicalPartition/#{lpar_uuid}/#{type}"
|
94
|
+
query = {}
|
95
|
+
query["StartTS"] = self.class.format_time(start_ts) unless start_ts.nil?
|
96
|
+
query["EndTS"] = self.class.format_time(end_ts) unless end_ts.nil?
|
97
|
+
query["NoOfSamples"] = no_samples unless no_samples.nil?
|
98
|
+
method_url += "?" + query.map { |h| h.join("=") }.join("&") unless query.empty?
|
99
|
+
|
100
|
+
response = request(:get, method_url)
|
101
|
+
FeedParser(response.body).entries do |entry|
|
102
|
+
link = entry.elements["link"]
|
103
|
+
next if link.nil?
|
104
|
+
|
105
|
+
href = link.attributes["href"]
|
106
|
+
next if href.nil?
|
107
|
+
|
108
|
+
response = request(:get, href)
|
109
|
+
JSON.parse(response.body)
|
110
|
+
end.compact
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# @!method format_time(time)
|
115
|
+
# Convert ruby time to HMC time format.
|
116
|
+
# @param time [Time] The ruby time to convert.
|
117
|
+
# @return [String] The time in HMC format.
|
118
|
+
def self.format_time(time)
|
119
|
+
time.utc.xmlschema
|
53
120
|
end
|
54
121
|
end
|
55
122
|
end
|
data/lib/ibm_power_hmc.rb
CHANGED
@@ -7,7 +7,8 @@ require "ibm_power_hmc/version"
|
|
7
7
|
|
8
8
|
# Module for IBM HMC Rest API Client
|
9
9
|
module IbmPowerHmc
|
10
|
-
require_relative "./ibm_power_hmc/
|
11
|
-
require_relative "./ibm_power_hmc/job
|
12
|
-
require_relative "./ibm_power_hmc/connection
|
10
|
+
require_relative "./ibm_power_hmc/parser"
|
11
|
+
require_relative "./ibm_power_hmc/job"
|
12
|
+
require_relative "./ibm_power_hmc/connection"
|
13
|
+
require_relative "./ibm_power_hmc/pcm"
|
13
14
|
end
|
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.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- IBM Power
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -35,7 +35,6 @@ files:
|
|
35
35
|
- ".rubocop_local.yml"
|
36
36
|
- CHANGELOG.md
|
37
37
|
- Gemfile
|
38
|
-
- Gemfile.lock
|
39
38
|
- LICENSE
|
40
39
|
- README.md
|
41
40
|
- Rakefile
|
@@ -45,7 +44,7 @@ files:
|
|
45
44
|
- lib/ibm_power_hmc.rb
|
46
45
|
- lib/ibm_power_hmc/connection.rb
|
47
46
|
- lib/ibm_power_hmc/job.rb
|
48
|
-
- lib/ibm_power_hmc/
|
47
|
+
- lib/ibm_power_hmc/parser.rb
|
49
48
|
- lib/ibm_power_hmc/pcm.rb
|
50
49
|
- lib/ibm_power_hmc/version.rb
|
51
50
|
homepage: http://github.com/IBM/ibm_power_hmc_sdk_ruby
|
@@ -71,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
70
|
- !ruby/object:Gem::Version
|
72
71
|
version: '0'
|
73
72
|
requirements: []
|
74
|
-
rubygems_version: 3.
|
73
|
+
rubygems_version: 3.1.4
|
75
74
|
signing_key:
|
76
75
|
specification_version: 4
|
77
76
|
summary: IBM Power HMC Ruby gem.
|
data/Gemfile.lock
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
ibm_power_hmc (0.1.0)
|
5
|
-
rest-client (~> 2.1)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
domain_name (0.5.20190701)
|
11
|
-
unf (>= 0.0.5, < 1.0.0)
|
12
|
-
http-accept (1.7.0)
|
13
|
-
http-cookie (1.0.4)
|
14
|
-
domain_name (~> 0.5)
|
15
|
-
mime-types (3.3.1)
|
16
|
-
mime-types-data (~> 3.2015)
|
17
|
-
mime-types-data (3.2021.0704)
|
18
|
-
netrc (0.11.0)
|
19
|
-
rake (12.3.3)
|
20
|
-
rest-client (2.1.0)
|
21
|
-
http-accept (>= 1.7.0, < 2.0)
|
22
|
-
http-cookie (>= 1.0.2, < 2.0)
|
23
|
-
mime-types (>= 1.16, < 4.0)
|
24
|
-
netrc (~> 0.8)
|
25
|
-
unf (0.1.4)
|
26
|
-
unf_ext
|
27
|
-
unf_ext (0.0.7.7)
|
28
|
-
|
29
|
-
PLATFORMS
|
30
|
-
ruby
|
31
|
-
|
32
|
-
DEPENDENCIES
|
33
|
-
ibm_power_hmc!
|
34
|
-
rake (~> 12.0)
|
35
|
-
|
36
|
-
BUNDLED WITH
|
37
|
-
2.1.4
|
@@ -1,148 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'uri'
|
4
|
-
|
5
|
-
# Module for IBM HMC Rest API Client
|
6
|
-
module IbmPowerHmc
|
7
|
-
# HMC generic object
|
8
|
-
class HmcObject
|
9
|
-
attr_reader :uuid
|
10
|
-
|
11
|
-
def initialize(doc)
|
12
|
-
@uuid = doc.elements["id"].text
|
13
|
-
end
|
14
|
-
|
15
|
-
def get_value(doc, xpath, varname)
|
16
|
-
value = doc.elements[xpath]
|
17
|
-
value = value.text unless value.nil?
|
18
|
-
value = value.strip unless value.nil?
|
19
|
-
self.class.__send__(:attr_reader, varname)
|
20
|
-
instance_variable_set("@#{varname}", value)
|
21
|
-
end
|
22
|
-
|
23
|
-
def get_values(doc, hash)
|
24
|
-
hash.each do |key, value|
|
25
|
-
get_value(doc, key, value)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# HMC information
|
31
|
-
class ManagementConsole < HmcObject
|
32
|
-
XMLMAP = {
|
33
|
-
"ManagementConsoleName" => "name",
|
34
|
-
"VersionInfo/BuildLevel" => "build_level",
|
35
|
-
"BaseVersion" => "version"
|
36
|
-
}.freeze
|
37
|
-
|
38
|
-
def initialize(doc)
|
39
|
-
super(doc)
|
40
|
-
info = doc.elements["content/ManagementConsole:ManagementConsole"]
|
41
|
-
get_values(info, XMLMAP)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Managed System information
|
46
|
-
class ManagedSystem < HmcObject
|
47
|
-
XMLMAP = {
|
48
|
-
"SystemName" => "name",
|
49
|
-
"State" => "state",
|
50
|
-
"Hostname" => "hostname",
|
51
|
-
"PrimaryIPAddress" => "ipaddr",
|
52
|
-
"AssociatedSystemMemoryConfiguration/InstalledSystemMemory" => "memory",
|
53
|
-
"AssociatedSystemMemoryConfiguration/CurrentAvailableSystemMemory" => "avail_mem",
|
54
|
-
"AssociatedSystemProcessorConfiguration/InstalledSystemProcessorUnits" => "cpus",
|
55
|
-
"AssociatedSystemProcessorConfiguration/CurrentAvailableSystemProcessorUnits" => "avail_cpus",
|
56
|
-
"MachineTypeModelAndSerialNumber/MachineType" => "mtype",
|
57
|
-
"MachineTypeModelAndSerialNumber/Model" => "model",
|
58
|
-
"MachineTypeModelAndSerialNumber/SerialNumber" => "serial",
|
59
|
-
}.freeze
|
60
|
-
|
61
|
-
def initialize(doc)
|
62
|
-
super(doc)
|
63
|
-
info = doc.elements["content/ManagedSystem:ManagedSystem"]
|
64
|
-
get_values(info, XMLMAP)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Logical Partition information
|
69
|
-
class LogicalPartition < HmcObject
|
70
|
-
attr_reader :sys_uuid
|
71
|
-
|
72
|
-
XMLMAP = {
|
73
|
-
"PartitionName" => "name",
|
74
|
-
"PartitionID" => "id",
|
75
|
-
"PartitionState" => "state",
|
76
|
-
"PartitionType" => "type",
|
77
|
-
"PartitionMemoryConfiguration/CurrentMemory" => "memory",
|
78
|
-
"PartitionProcessorConfiguration/HasDedicatedProcessors" => "dedicated",
|
79
|
-
"ResourceMonitoringControlState" => "rmc_state",
|
80
|
-
"ResourceMonitoringIPAddress" => "rmc_ipaddr"
|
81
|
-
}.freeze
|
82
|
-
|
83
|
-
def initialize(doc)
|
84
|
-
super(doc)
|
85
|
-
info = doc.elements["content/LogicalPartition:LogicalPartition"]
|
86
|
-
sys_href = info.elements["AssociatedManagedSystem"].attributes["href"]
|
87
|
-
@sys_uuid = URI(sys_href).path.split('/').last
|
88
|
-
get_values(info, XMLMAP)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# VIOS information
|
93
|
-
class VirtualIOServer < HmcObject
|
94
|
-
attr_reader :sys_uuid
|
95
|
-
|
96
|
-
XMLMAP = {
|
97
|
-
"PartitionName" => "name",
|
98
|
-
"PartitionID" => "id",
|
99
|
-
"PartitionState" => "state",
|
100
|
-
"PartitionType" => "type",
|
101
|
-
"PartitionMemoryConfiguration/CurrentMemory" => "memory",
|
102
|
-
"PartitionProcessorConfiguration/HasDedicatedProcessors" => "dedicated"
|
103
|
-
}.freeze
|
104
|
-
|
105
|
-
def initialize(doc)
|
106
|
-
super(doc)
|
107
|
-
info = doc.elements["content/VirtualIOServer:VirtualIOServer"]
|
108
|
-
sys_href = info.elements["AssociatedManagedSystem"].attributes["href"]
|
109
|
-
@sys_uuid = URI(sys_href).path.split('/').last
|
110
|
-
get_values(info, XMLMAP)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# HMC Event
|
115
|
-
class Event < HmcObject
|
116
|
-
attr_reader :published
|
117
|
-
|
118
|
-
XMLMAP = {
|
119
|
-
"EventID" => "id",
|
120
|
-
"EventType" => "type",
|
121
|
-
"EventData" => "data",
|
122
|
-
"EventDetail" => "detail",
|
123
|
-
}.freeze
|
124
|
-
|
125
|
-
def initialize(doc)
|
126
|
-
super(doc)
|
127
|
-
@published = doc.elements["published"].text
|
128
|
-
info = doc.elements["content/Event:Event"]
|
129
|
-
get_values(info, XMLMAP)
|
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
|
141
|
-
|
142
|
-
def initialize(doc)
|
143
|
-
super(doc)
|
144
|
-
info = doc.elements["content/HttpErrorResponse:HttpErrorResponse"]
|
145
|
-
get_values(info, XMLMAP)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|