ibm_power_hmc 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 397feab84db9812185ab1125cd6778b52a1848519d6bae5950d69cb31e9b4845
4
- data.tar.gz: 27dd4d94cd61a19c66d0d6e438c17987ea5926af78b7677b5044a11a50acdb18
3
+ metadata.gz: e42aa4d6eaa8915b8c37ce96aab995801533b81d8fa70b1e351bc550cc6eaa02
4
+ data.tar.gz: 6022fb088c67eeb0c20e8435c20567ef62fb34e365419cfa20f6fb9bc1e769f5
5
5
  SHA512:
6
- metadata.gz: 1171816de48bed97b1837ab39d3bd639772928ebee98fb8f287c85006196bdf068320599b921a239d10d5ce74e98629cde754eca14b12c6cf6be85477e7a7fb3
7
- data.tar.gz: 10f7397e58acab288715283de98480caf915fb628021b2f8c5261b13b2c7b273cdec5e1d7a52b35560acbe5cae6dfed5c9e68516673d97ff5f91a9fb44daa370
6
+ metadata.gz: 7ca0280aaeff1a1a0ce0cf5c53c40b6f0ddfc94725536e53d19031b1b107de4c8b44919580eaf1716e60f302bf339363508597b9188634412511bcc7869e4f83
7
+ data.tar.gz: b0251d621a729e2b7d97c7655709fd68bd1e796466967f2021924ab7658a12c2dc13c34dfe71597f96f6ed2114e24c405362232c4dab2e88b653afbe2b7d679a
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ /Gemfile.lock
1
2
  /.bundle/
2
3
  /.yardoc
3
4
  /_yardoc/
data/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ inherit_gem:
2
+ manageiq-style: ".rubocop_base.yml"
3
+ inherit_from:
4
+ - ".rubocop_local.yml"
@@ -0,0 +1,7 @@
1
+ AllCops:
2
+ Exclude:
3
+ - '*.gemspec'
4
+ Layout/HashAlignment:
5
+ Enabled: false
6
+ Style/ConditionalAssignment:
7
+ Enabled: false
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,10 +2,21 @@
2
2
 
3
3
  # Module for IBM HMC Rest API Client
4
4
  module IbmPowerHmc
5
- # HMC REST Client connection
5
+ class Error < StandardError; end
6
+
7
+ ##
8
+ # HMC REST Client connection.
6
9
  class Connection
10
+ ##
11
+ # @!method initialize(host:, username: "hscroot", password:, port: 12_443, validate_ssl: true)
12
+ # Create a new HMC connection.
13
+ #
14
+ # @param host [String] Hostname of the HMC.
15
+ # @param username [String] User name.
16
+ # @param password [String] Password.
17
+ # @param port [Integer] TCP port number.
18
+ # @param validate_ssl [Boolean] Verify SSL certificates.
7
19
  def initialize(host:, username: "hscroot", password:, port: 12_443, validate_ssl: true)
8
- # Damien: use URI::HTTPS
9
20
  @hostname = "#{host}:#{port}"
10
21
  @username = username
11
22
  @password = password
@@ -13,72 +24,107 @@ module IbmPowerHmc
13
24
  @api_session_token = nil
14
25
  end
15
26
 
27
+ ##
28
+ # @!method logon
29
+ # Establish a trusted session with the Web Services APIs.
30
+ # @return [String] The X-API-Session token.
16
31
  def logon
17
32
  method_url = "/rest/api/web/Logon"
18
33
  headers = {
19
- content_type: "application/vnd.ibm.powervm.web+xml; type=LogonRequest"
34
+ :content_type => "application/vnd.ibm.powervm.web+xml; type=LogonRequest"
20
35
  }
21
36
  doc = REXML::Document.new("")
22
- doc.add_element("LogonRequest", {
23
- "xmlns" => "http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/",
24
- "schemaVersion" => "V1_1_0"
25
- })
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/")
26
39
  doc.root.add_element("UserID").text = @username
27
40
  doc.root.add_element("Password").text = @password
28
41
 
29
- # Damien: begin/rescue
30
42
  @api_session_token = ""
31
43
  response = request(:put, method_url, headers, doc.to_s)
32
44
  doc = REXML::Document.new(response.body)
33
- @api_session_token = doc.root.elements["X-API-Session"].text
45
+ elem = doc.elements["LogonResponse/X-API-Session"]
46
+ raise Error, "LogonResponse/X-API-Session not found" if elem.nil?
47
+
48
+ @api_session_token = elem.text
34
49
  end
35
50
 
51
+ ##
52
+ # @!method logoff
53
+ # Close the session.
36
54
  def logoff
55
+ # Don't want to trigger automatic logon here!
56
+ return if @api_session_token.nil?
57
+
37
58
  method_url = "/rest/api/web/Logon"
38
- request(:delete, method_url)
59
+ begin
60
+ request(:delete, method_url)
61
+ rescue
62
+ # Ignore exceptions as this is best effort attempt to log off.
63
+ end
39
64
  @api_session_token = nil
40
65
  end
41
66
 
67
+ ##
68
+ # @!method management_console
69
+ # Retrieve information about the management console.
70
+ # @return [IbmPowerHmc::ManagementConsole] The management console.
42
71
  def management_console
43
72
  method_url = "/rest/api/uom/ManagementConsole"
44
73
  response = request(:get, method_url)
45
- doc = REXML::Document.new(response.body)
46
- entry = doc.root.elements["entry"]
47
- ManagementConsole.new(entry)
74
+ # This request returns a feed with a single entry.
75
+ FeedParser.new(response.body).objects(:ManagementConsole).first
48
76
  end
49
77
 
50
- def managed_systems
78
+ ##
79
+ # @!method managed_systems(search = {})
80
+ # Retrieve the list of systems managed by the HMC.
81
+ # @param search [Hash] The optional property name and value to match.
82
+ # @return [Array<IbmPowerHmc::ManagedSystem>] The list of managed systems.
83
+ def managed_systems(search = {})
51
84
  method_url = "/rest/api/uom/ManagedSystem"
85
+ search.each { |key, value| method_url += "/search/(#{key}==#{value})" }
52
86
  response = request(:get, method_url)
53
- doc = REXML::Document.new(response.body)
54
- systems = []
55
- return systems if doc.root.nil?
87
+ FeedParser.new(response.body).objects(:ManagedSystem)
88
+ end
56
89
 
57
- doc.root.each_element("entry") do |entry|
58
- system = ManagedSystem.new(entry)
59
- systems += [system]
60
- end
61
- systems
90
+ ##
91
+ # @!method managed_system(lpar_uuid, sys_uuid = nil, group_name = nil)
92
+ # Retrieve information about a managed system.
93
+ # @param sys_uuid [String] The UUID of the managed system.
94
+ # @param group_name [String] The extended group attributes.
95
+ # @return [IbmPowerHmc::ManagedSystem] The managed system.
96
+ def managed_system(sys_uuid, group_name = nil)
97
+ method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}"
98
+ method_url += "?group=#{group_name}" unless group_name.nil?
99
+
100
+ response = request(:get, method_url)
101
+ Parser.new(response.body).object(:ManagedSystem)
62
102
  end
63
103
 
64
- def lpars(sys_uuid = nil)
104
+ ##
105
+ # @!method lpars(sys_uuid = nil, search = {})
106
+ # Retrieve the list of logical partitions managed by the HMC.
107
+ # @param sys_uuid [String] The UUID of the managed system.
108
+ # @param search [Hash] The optional property name and value to match.
109
+ # @return [Array<IbmPowerHmc::LogicalPartition>] The list of logical partitions.
110
+ def lpars(sys_uuid = nil, search = {})
65
111
  if sys_uuid.nil?
66
112
  method_url = "/rest/api/uom/LogicalPartition"
113
+ search.each { |key, value| method_url += "/search/(#{key}==#{value})" }
67
114
  else
68
115
  method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/LogicalPartition"
69
116
  end
70
117
  response = request(:get, method_url)
71
- doc = REXML::Document.new(response.body)
72
- lpars = []
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
118
+ FeedParser.new(response.body).objects(:LogicalPartition)
80
119
  end
81
120
 
121
+ ##
122
+ # @!method lpar(lpar_uuid, sys_uuid = nil, group_name = nil)
123
+ # Retrieve information about a logical partition.
124
+ # @param lpar_uuid [String] The UUID of the logical partition.
125
+ # @param sys_uuid [String] The UUID of the managed system.
126
+ # @param group_name [String] The extended group attributes.
127
+ # @return [IbmPowerHmc::LogicalPartition] The logical partition.
82
128
  def lpar(lpar_uuid, sys_uuid = nil, group_name = nil)
83
129
  if sys_uuid.nil?
84
130
  method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}"
@@ -88,11 +134,15 @@ module IbmPowerHmc
88
134
  method_url += "?group=#{group_name}" unless group_name.nil?
89
135
 
90
136
  response = request(:get, method_url)
91
- doc = REXML::Document.new(response.body)
92
- entry = doc.elements["entry"]
93
- LogicalPartition.new(entry)
137
+ Parser.new(response.body).object(:LogicalPartition)
94
138
  end
95
139
 
140
+ ##
141
+ # @!method lpar_quick_property(lpar_uuid, property_name)
142
+ # Retrieve a quick property of a logical partition.
143
+ # @param lpar_uuid [String] The UUID of the logical partition.
144
+ # @param property_name [String] The quick property name.
145
+ # @return [String] The quick property value.
96
146
  def lpar_quick_property(lpar_uuid, property_name)
97
147
  method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/quick/#{property_name}"
98
148
 
@@ -100,141 +150,292 @@ module IbmPowerHmc
100
150
  response.body[1..-2]
101
151
  end
102
152
 
103
- def vioses(sys_uuid = nil)
153
+ ##
154
+ # @!method rename_lpar(lpar_uuid, newname)
155
+ # Rename a logical partition.
156
+ # @param lpar_uuid [String] The UUID of the logical partition.
157
+ # @param newname [String] The new name of the logical partition.
158
+ def rename_lpar(lpar_uuid, newname)
159
+ method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}"
160
+ headers = {
161
+ :content_type => "application/vnd.ibm.powervm.uom+xml; type=LogicalPartition",
162
+ }
163
+ modify_object(method_url, headers) do |lpar|
164
+ lpar.xml.elements["PartitionName"].text = newname
165
+ end
166
+ end
167
+
168
+ ##
169
+ # @!method vioses(sys_uuid = nil, search = {})
170
+ # Retrieve the list of virtual I/O servers managed by the HMC.
171
+ # @param sys_uuid [String] The UUID of the managed system.
172
+ # @param search [Hash] The optional property name and value to match.
173
+ # @return [Array<IbmPowerHmc::VirtualIOServer>] The list of virtual I/O servers.
174
+ def vioses(sys_uuid = nil, search = {})
104
175
  if sys_uuid.nil?
105
176
  method_url = "/rest/api/uom/VirtualIOServer"
177
+ search.each { |key, value| method_url += "/search/(#{key}==#{value})" }
106
178
  else
107
179
  method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/VirtualIOServer"
108
180
  end
109
- begin
110
- response = request(:get, method_url)
111
- rescue StandardError
112
- return []
113
- end
114
- doc = REXML::Document.new(response.body)
115
- vioses = []
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
181
+ response = request(:get, method_url)
182
+ FeedParser.new(response.body).objects(:VirtualIOServer)
123
183
  end
124
184
 
125
- # Damien: share the same method for VIOS and LPAR?
126
- def lpar_profiles(lpar_uuid)
127
- method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/LogicalPartitionProfile"
128
- begin
129
- response = request(:get, method_url)
130
- rescue StandardError
131
- return []
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
- doc = REXML::Document.new(response.body)
134
- profiles = []
135
- return profiles if doc.root.nil?
198
+ method_url += "?group=#{group_name}" unless group_name.nil?
136
199
 
137
- doc.root.each_element("entry") do |entry|
138
- profile = LogicalPartitionProfile.new(lpar_uuid, entry)
139
- profiles += [profile]
140
- end
141
- profiles
200
+ response = request(:get, method_url)
201
+ Parser.new(response.body).object(:VirtualIOServer)
142
202
  end
143
203
 
144
- def poweron_lpar(lpar_uuid, params = {})
204
+ ##
205
+ # @!method poweron_lpar(lpar_uuid, params = {}, sync = true)
206
+ # Power on a logical partition.
207
+ # @param lpar_uuid [String] The UUID of the logical partition.
208
+ # @param params [Hash] Job parameters.
209
+ # @param sync [Boolean] Start the job and wait for its completion.
210
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
211
+ def poweron_lpar(lpar_uuid, params = {}, sync = true)
145
212
  method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/do/PowerOn"
146
213
 
147
214
  job = HmcJob.new(self, method_url, "PowerOn", "LogicalPartition", params)
148
- job.start
149
- job.wait
150
- job.delete
215
+ job.run if sync
216
+ job
151
217
  end
152
218
 
153
- def poweroff_lpar(lpar_uuid, params = {})
219
+ ##
220
+ # @!method poweroff_lpar(lpar_uuid, params = {}, sync = true)
221
+ # Power off a logical partition.
222
+ # @param lpar_uuid [String] The UUID of the logical partition.
223
+ # @param params [Hash] Job parameters.
224
+ # @param sync [Boolean] Start the job and wait for its completion.
225
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
226
+ def poweroff_lpar(lpar_uuid, params = {}, sync = true)
154
227
  method_url = "/rest/api/uom/LogicalPartition/#{lpar_uuid}/do/PowerOff"
155
228
 
156
229
  job = HmcJob.new(self, method_url, "PowerOff", "LogicalPartition", params)
157
- job.start
158
- job.wait
159
- job.delete
230
+ job.run if sync
231
+ job
160
232
  end
161
233
 
162
- # Damien: share with poweron_lpar?
163
- def poweron_vios(vios_uuid, params = {})
234
+ ##
235
+ # @!method poweron_vios(vios_uuid, params = {}, sync = true)
236
+ # Power on a virtual I/O server.
237
+ # @param vios_uuid [String] The UUID of the virtual I/O server.
238
+ # @param params [Hash] Job parameters.
239
+ # @param sync [Boolean] Start the job and wait for its completion.
240
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
241
+ def poweron_vios(vios_uuid, params = {}, sync = true)
164
242
  method_url = "/rest/api/uom/VirtualIOServer/#{vios_uuid}/do/PowerOn"
165
243
 
166
244
  job = HmcJob.new(self, method_url, "PowerOn", "VirtualIOServer", params)
167
- job.start
168
- job.wait
169
- job.delete
245
+ job.run if sync
246
+ job
170
247
  end
171
248
 
172
- # Damien: share with poweroff_lpar?
173
- def poweroff_vios(vios_uuid, params = {})
249
+ ##
250
+ # @!method poweroff_vios(vios_uuid, params = {}, sync = true)
251
+ # Power off a virtual I/O server.
252
+ # @param vios_uuid [String] The UUID of the virtual I/O server.
253
+ # @param params [Hash] Job parameters.
254
+ # @param sync [Boolean] Start the job and wait for its completion.
255
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
256
+ def poweroff_vios(vios_uuid, params = {}, sync = true)
174
257
  method_url = "/rest/api/uom/VirtualIOServer/#{vios_uuid}/do/PowerOff"
175
258
 
176
259
  job = HmcJob.new(self, method_url, "PowerOff", "VirtualIOServer", params)
177
- job.start
178
- job.wait
179
- job.delete
260
+ job.run if sync
261
+ job
180
262
  end
181
263
 
182
- def poweron_managed_system(sys_uuid, params = {})
264
+ ##
265
+ # @!method poweron_managed_system(sys_uuid, params = {}, sync = true)
266
+ # Power on a managed system.
267
+ # @param sys_uuid [String] The UUID of the managed system.
268
+ # @param params [Hash] Job parameters.
269
+ # @param sync [Boolean] Start the job and wait for its completion.
270
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
271
+ def poweron_managed_system(sys_uuid, params = {}, sync = true)
183
272
  method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/do/PowerOn"
184
273
 
185
274
  job = HmcJob.new(self, method_url, "PowerOn", "ManagedSystem", params)
186
- job.start
187
- job.wait
188
- job.delete
275
+ job.run if sync
276
+ job
189
277
  end
190
278
 
191
- def poweroff_managed_system(sys_uuid, params = {})
279
+ ##
280
+ # @!method poweroff_managed_system(sys_uuid, params = {}, sync = true)
281
+ # Power off a managed system.
282
+ # @param sys_uuid [String] The UUID of the managed system.
283
+ # @param params [Hash] Job parameters.
284
+ # @param sync [Boolean] Start the job and wait for its completion.
285
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
286
+ def poweroff_managed_system(sys_uuid, params = {}, sync = true)
192
287
  method_url = "/rest/api/uom/ManagedSystem/#{sys_uuid}/do/PowerOff"
193
288
 
194
289
  job = HmcJob.new(self, method_url, "PowerOff", "ManagedSystem", params)
195
- job.start
196
- job.wait
197
- job.delete
290
+ job.run if sync
291
+ job
292
+ end
293
+
294
+ ##
295
+ # @!method remove_connection(hmc_uuid, sys_uuid, sync = true)
296
+ # Remove a managed system from the management console.
297
+ # @param hmc_uuid [String] The UUID of the management console.
298
+ # @param sys_uuid [String] The UUID of the managed system.
299
+ # @param sync [Boolean] Start the job and wait for its completion.
300
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
301
+ def remove_connection(hmc_uuid, sys_uuid, sync = true)
302
+ method_url = "/rest/api/uom/ManagementConsole/#{hmc_uuid}/ManagedSystem/#{sys_uuid}/do/RemoveConnection"
303
+
304
+ job = HmcJob.new(self, method_url, "RemoveConnection", "ManagedSystem")
305
+ job.run if sync
306
+ job
198
307
  end
199
308
 
200
- # Blocks until new events occur.
201
- def next_events
309
+ ##
310
+ # @!method cli_run(hmc_uuid, cmd, sync = true)
311
+ # Run a CLI command on the HMC as a job.
312
+ # @param hmc_uuid [String] The UUID of the management console.
313
+ # @param cmd [String] The command to run.
314
+ # @param sync [Boolean] Start the job and wait for its completion.
315
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
316
+ def cli_run(hmc_uuid, cmd, sync = true)
317
+ method_url = "/rest/api/uom/ManagementConsole/#{hmc_uuid}/do/CLIRunner"
318
+
319
+ params = {
320
+ "cmd" => cmd,
321
+ "acknowledgeThisAPIMayGoAwayInTheFuture" => "true",
322
+ }
323
+ job = HmcJob.new(self, method_url, "CLIRunner", "ManagementConsole", params)
324
+ job.run if sync
325
+ job
326
+ end
327
+
328
+ ##
329
+ # @!method next_events(wait = true)
330
+ # Retrieve a list of events that occured since last call.
331
+ # @param wait [Boolean] If no event is available, block until new events occur.
332
+ # @return [Array<IbmPowerHmc::Event>] The list of events.
333
+ def next_events(wait = true)
202
334
  method_url = "/rest/api/uom/Event"
203
335
 
204
- events = []
336
+ response = nil
205
337
  loop do
206
338
  response = request(:get, method_url)
207
- next if response.code == 204
339
+ # No need to sleep as the HMC already waits a bit before returning 204
340
+ break if response.code != 204 || !wait
341
+ end
342
+ FeedParser.new(response.body).objects(:Event)
343
+ end
344
+
345
+ ##
346
+ # @!method schema(type)
347
+ # Retrieve the XML schema file for a given object type.
348
+ # @param type [String] The object type (e.g. "LogicalPartition", "inc/Types")
349
+ # @return [REXML::Document] The XML schema file.
350
+ def schema(type)
351
+ method_url = "/rest/api/web/schema/#{type}.xsd"
352
+ response = request(:get, method_url)
353
+ REXML::Document.new(response.body)
354
+ end
208
355
 
209
- doc = REXML::Document.new(response.body)
210
- doc.root.each_element("entry") do |entry|
211
- event = Event.new(entry)
212
- events += [event]
356
+ class HttpError < Error
357
+ attr_reader :status, :uri, :reason, :message, :original_exception
358
+
359
+ ##
360
+ # @!method initialize(err)
361
+ # Create a new HttpError exception.
362
+ # @param err [RestClient::Exception] The REST client exception.
363
+ def initialize(err)
364
+ super
365
+ @original_exception = err
366
+ @status = err.http_code
367
+ @message = err.message
368
+
369
+ # Try to parse body as an HttpErrorResponse
370
+ unless err.response.nil?
371
+ resp = Parser.new(err.response.body).object(:HttpErrorResponse)
372
+ unless resp.nil?
373
+ @uri = resp.uri
374
+ @reason = resp.reason
375
+ @message = resp.message
376
+ end
213
377
  end
214
- break
215
378
  end
216
- events
379
+
380
+ def to_s
381
+ "msg=\"#{@message}\" status=\"#{@status}\" reason=\"#{@reason}\" uri=#{@uri}"
382
+ end
217
383
  end
218
384
 
385
+ ##
386
+ # @!method request(method, url, headers = {}, payload = nil)
387
+ # Perform a REST API request.
388
+ # @param method [String] The HTTP method.
389
+ # @param url [String] The method URL.
390
+ # @param headers [Hash] HTTP headers.
391
+ # @param payload [String] HTTP request payload.
392
+ # @return [RestClient::Response] The response from the HMC.
219
393
  def request(method, url, headers = {}, payload = nil)
220
394
  logon if @api_session_token.nil?
395
+ reauth = false
396
+ # Check for relative URLs
397
+ url = "https://#{@hostname}#{url}" if url.start_with?("/")
398
+ begin
399
+ headers = headers.merge("X-API-Session" => @api_session_token)
400
+ RestClient::Request.execute(
401
+ :method => method,
402
+ :url => url,
403
+ :verify_ssl => @verify_ssl,
404
+ :payload => payload,
405
+ :headers => headers
406
+ )
407
+ rescue RestClient::Exception => e
408
+ # Do not retry on failed logon attempts
409
+ if e.http_code == 401 && @api_session_token != "" && !reauth
410
+ # Try to reauth
411
+ reauth = true
412
+ logon
413
+ retry
414
+ end
415
+ raise HttpError.new(e), "REST request failed"
416
+ end
417
+ end
221
418
 
222
- headers = headers.merge({ "X-API-Session" => @api_session_token })
223
- # Damien: use URI module and prepare in initialize?
224
- response = RestClient::Request.execute(
225
- method: method,
226
- url: "https://" + @hostname + url,
227
- verify_ssl: @verify_ssl,
228
- payload: payload,
229
- headers: headers
230
- )
231
- if response.code == 403
232
- # Damien: if token expires, reauth?
233
- @api_session_token = nil
234
- logon
235
- # Damien: retry TBD
419
+ private
420
+
421
+ def modify_object(method_url, headers = {}, attempts = 5)
422
+ while attempts > 0
423
+ response = request(:get, method_url)
424
+ obj = Parser.new(response.body).object
425
+
426
+ yield obj
427
+
428
+ # Use ETag to ensure object has not changed.
429
+ headers = headers.merge("If-Match" => obj.etag)
430
+ begin
431
+ request(:post, method_url, headers, obj.xml.to_s)
432
+ break
433
+ rescue HttpError => e
434
+ attempts -= 1
435
+ # Will get 412 ("Precondition Failed" if ETag mismatches)
436
+ raise if e.status != 412 || attempts == 0
437
+ end
236
438
  end
237
- response
238
439
  end
239
440
  end
240
441
  end
@@ -1,70 +1,116 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Module for IBM HMC Rest API Client
4
3
  module IbmPowerHmc
5
- # HMC Job for long running operations
4
+ ##
5
+ # HMC Job for long running operations.
6
6
  class HmcJob
7
- def initialize(hc, method_url, operation, group, params)
8
- @hc = hc
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 start
28
+ # Start the job asynchronously.
29
+ # @return [String] The ID of the job.
15
30
  def start
16
31
  headers = {
17
- content_type: "application/vnd.ibm.powervm.web+xml; type=JobRequest"
32
+ :content_type => "application/vnd.ibm.powervm.web+xml; type=JobRequest"
18
33
  }
19
34
  doc = REXML::Document.new("")
20
- doc.add_element("JobRequest:JobRequest", {
21
- "xmlns:JobRequest" => "http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/",
22
- "xmlns" => "http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/",
23
- "schemaVersion" => "V1_1_0"
24
- })
25
- 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")
26
39
  op.add_element("OperationName").text = @operation
27
40
  op.add_element("GroupName").text = @group
28
- # Damien: ProgressType?
29
- jobparams = doc.root.add_element("JobParameters", { "schemaVersion" => "V1_1_0" })
41
+
42
+ jobparams = doc.root.add_element("JobParameters", "schemaVersion" => "V1_1_0")
30
43
  @params.each do |key, value|
31
- jobparam = jobparams.add_element("JobParameter", { "schemaVersion" => "V1_1_0" })
44
+ jobparam = jobparams.add_element("JobParameter", "schemaVersion" => "V1_1_0")
32
45
  jobparam.add_element("ParameterName").text = key
33
46
  jobparam.add_element("ParameterValue").text = value
34
47
  end
35
- response = @hc.request(:put, @method_url, headers, doc.to_s)
36
- doc = REXML::Document.new(response.body)
37
- info = doc.root.elements["content/JobResponse:JobResponse"]
38
- @id = info.elements["JobID"].text
48
+ response = @conn.request(:put, @method_url, headers, doc.to_s)
49
+ jobresp = Parser.new(response.body).object(:JobResponse)
50
+ @id = jobresp.id
39
51
  end
40
52
 
53
+ # @return [Hash] The job results returned by the HMC.
54
+ attr_reader :results
55
+
56
+ ##
57
+ # @!method status
58
+ # Return the status of the job.
59
+ # @return [String] The status of the job.
41
60
  def status
42
- # Damien: check id is defined
61
+ raise JobNotStarted unless defined?(@id)
62
+
43
63
  method_url = "/rest/api/uom/jobs/#{@id}"
44
64
  headers = {
45
- content_type: "application/vnd.ibm.powervm.web+xml; type=JobRequest"
65
+ :content_type => "application/vnd.ibm.powervm.web+xml; type=JobRequest"
46
66
  }
47
- response = @hc.request(:get, method_url, headers)
48
- doc = REXML::Document.new(response.body)
49
- info = doc.root.elements["content/JobResponse:JobResponse"]
50
- status = info.elements["Status"].text
51
- # Damien: also retrieve "ResponseException/Message"
52
- status
67
+ response = @conn.request(:get, method_url, headers)
68
+ jobresp = Parser.new(response.body).object(:JobResponse)
69
+ @results = jobresp.results
70
+ jobresp.status
53
71
  end
54
72
 
55
- def wait(timeout = 120, poll_interval = 30)
56
- endtime = Time.now + timeout
57
- while Time.now < endtime do
73
+ ##
74
+ # @!method wait(timeout = 120, poll_interval = 0)
75
+ # Wait for the job to complete.
76
+ # @param timeout [Integer] The maximum time in seconds to wait for the job to complete.
77
+ # @param poll_interval [Integer] The interval in seconds between status queries (0 means auto).
78
+ # @return [String] The status of the job.
79
+ def wait(timeout = 120, poll_interval = 0)
80
+ endtime = Time.now.utc + timeout
81
+ auto = poll_interval == 0
82
+ poll_interval = 1 if auto
83
+ while Time.now.utc < endtime
58
84
  status = self.status
59
- break if status != "RUNNING" # Damien: and != "STARTING"?
85
+ return status if status != "RUNNING" && status != "NOT_STARTED"
86
+
87
+ poll_interval *= 2 if auto && poll_interval < 30
60
88
  sleep(poll_interval)
61
89
  end
90
+ "TIMEDOUT"
91
+ end
92
+
93
+ ##
94
+ # @!method run(timeout = 120, poll_interval = 0)
95
+ # Run the job synchronously.
96
+ # @param timeout [Integer] The maximum time in seconds to wait for the job to complete.
97
+ # @param poll_interval [Integer] The interval in seconds between status queries (0 means auto).
98
+ # @return [String] The status of the job.
99
+ def run(timeout = 120, poll_interval = 0)
100
+ start
101
+ wait(timeout, poll_interval)
102
+ ensure
103
+ delete if defined?(@id)
62
104
  end
63
105
 
106
+ ##
107
+ # @!method delete
108
+ # Delete the job from the HMC.
64
109
  def delete
65
- # Damien: check id is defined
110
+ raise JobNotStarted unless defined?(@id)
111
+
66
112
  method_url = "/rest/api/uom/jobs/#{@id}"
67
- @hc.request(:delete, method_url)
113
+ @conn.request(:delete, method_url)
68
114
  # Returns HTTP 204 if ok
69
115
  end
70
116
  end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'time'
4
+ require 'uri'
5
+
6
+ module IbmPowerHmc
7
+ # Parser for HMC feeds and entries.
8
+ class Parser
9
+ def initialize(body)
10
+ @doc = REXML::Document.new(body)
11
+ end
12
+
13
+ def entry
14
+ @doc.elements["entry"]
15
+ end
16
+
17
+ def object(filter_type = nil)
18
+ self.class.to_obj(entry, filter_type)
19
+ end
20
+
21
+ def self.to_obj(entry, filter_type = nil)
22
+ return if entry.nil?
23
+
24
+ content = entry.elements["content"]
25
+ return if content.nil?
26
+
27
+ type = content.attributes["type"]
28
+ return if type.nil?
29
+
30
+ type = type.split("=").last
31
+ return unless filter_type.nil? || filter_type.to_s == type
32
+
33
+ Module.const_get("IbmPowerHmc::#{type}").new(entry)
34
+ end
35
+ end
36
+
37
+ class FeedParser < Parser
38
+ def entries
39
+ objs = []
40
+ @doc.each_element("feed/entry") do |entry|
41
+ objs << yield(entry)
42
+ end
43
+ objs
44
+ end
45
+
46
+ def objects(filter_type = nil)
47
+ entries do |entry|
48
+ self.class.to_obj(entry, filter_type)
49
+ end.compact
50
+ end
51
+ end
52
+
53
+ private_constant :Parser
54
+ private_constant :FeedParser
55
+
56
+ # HMC generic XML entry
57
+ class AbstractRest
58
+ ATTRS = {}.freeze
59
+ attr_reader :uuid, :published, :etag, :xml
60
+
61
+ def initialize(doc)
62
+ @uuid = doc.elements["id"]&.text
63
+ @published = Time.xmlschema(doc.elements["published"]&.text)
64
+ @etag = doc.elements["etag:etag"]&.text&.strip
65
+ type = self.class.name.split("::").last
66
+ @xml = doc.elements["content/#{type}:#{type}"]
67
+ define_attrs(self.class::ATTRS)
68
+ end
69
+
70
+ def define_attr(varname, xpath)
71
+ value = text_element(xpath)
72
+ self.class.__send__(:attr_reader, varname)
73
+ instance_variable_set("@#{varname}", value)
74
+ end
75
+
76
+ def define_attrs(hash)
77
+ hash.each do |key, value|
78
+ define_attr(key, value)
79
+ end
80
+ end
81
+
82
+ def text_element(xpath)
83
+ xml.elements[xpath]&.text&.strip
84
+ end
85
+
86
+ def extract_uuid_from_href(href)
87
+ URI(href).path.split('/').last
88
+ end
89
+ end
90
+
91
+ # HMC information
92
+ class ManagementConsole < AbstractRest
93
+ ATTRS = {
94
+ :name => "ManagementConsoleName",
95
+ :build_level => "VersionInfo/BuildLevel",
96
+ :version => "BaseVersion"
97
+ }.freeze
98
+
99
+ def managed_systems_uuids
100
+ xml.get_elements("ManagedSystems/link").map do |link|
101
+ extract_uuid_from_href(link.attributes["href"])
102
+ end.compact
103
+ end
104
+ end
105
+
106
+ # Managed System information
107
+ class ManagedSystem < AbstractRest
108
+ ATTRS = {
109
+ :name => "SystemName",
110
+ :state => "State",
111
+ :hostname => "Hostname",
112
+ :ipaddr => "PrimaryIPAddress",
113
+ :fwversion => "SystemFirmware",
114
+ :memory => "AssociatedSystemMemoryConfiguration/InstalledSystemMemory",
115
+ :avail_mem => "AssociatedSystemMemoryConfiguration/CurrentAvailableSystemMemory",
116
+ :cpus => "AssociatedSystemProcessorConfiguration/InstalledSystemProcessorUnits",
117
+ :avail_cpus => "AssociatedSystemProcessorConfiguration/CurrentAvailableSystemProcessorUnits",
118
+ :mtype => "MachineTypeModelAndSerialNumber/MachineType",
119
+ :model => "MachineTypeModelAndSerialNumber/Model",
120
+ :serial => "MachineTypeModelAndSerialNumber/SerialNumber"
121
+ }.freeze
122
+
123
+ def lpars_uuids
124
+ xml.get_elements("AssociatedLogicalPartitions/link").map do |link|
125
+ extract_uuid_from_href(link.attributes["href"])
126
+ end.compact
127
+ end
128
+
129
+ def vioses_uuids
130
+ xml.get_elements("AssociatedVirtualIOServers/link").map do |link|
131
+ extract_uuid_from_href(link.attributes["href"])
132
+ end.compact
133
+ end
134
+ end
135
+
136
+ # Common class for LPAR and VIOS
137
+ class BasePartition < AbstractRest
138
+ ATTRS = {
139
+ :os => "OperatingSystemVersion",
140
+ :name => "PartitionName",
141
+ :id => "PartitionID",
142
+ :state => "PartitionState",
143
+ :type => "PartitionType",
144
+ :memory => "PartitionMemoryConfiguration/CurrentMemory",
145
+ :dedicated => "PartitionProcessorConfiguration/HasDedicatedProcessors",
146
+ :rmc_state => "ResourceMonitoringControlState",
147
+ :rmc_ipaddr => "ResourceMonitoringIPAddress",
148
+ :ref_code => "ReferenceCode"
149
+ }.freeze
150
+
151
+ def sys_uuid
152
+ sys_href = xml.elements["AssociatedManagedSystem"].attributes["href"]
153
+ extract_uuid_from_href(sys_href)
154
+ end
155
+ end
156
+
157
+ # Logical Partition information
158
+ class LogicalPartition < BasePartition
159
+ end
160
+
161
+ # VIOS information
162
+ class VirtualIOServer < BasePartition
163
+ end
164
+
165
+ # HMC Event
166
+ class Event < AbstractRest
167
+ ATTRS = {
168
+ :id => "EventID",
169
+ :type => "EventType",
170
+ :data => "EventData",
171
+ :detail => "EventDetail"
172
+ }.freeze
173
+ end
174
+
175
+ # Error response from HMC
176
+ class HttpErrorResponse < AbstractRest
177
+ ATTRS = {
178
+ :status => "HTTPStatus",
179
+ :uri => "RequestURI",
180
+ :reason => "ReasonCode",
181
+ :message => "Message"
182
+ }.freeze
183
+ end
184
+
185
+ # Job Response
186
+ class JobResponse < AbstractRest
187
+ ATTRS = {
188
+ :id => "JobID",
189
+ :status => "Status",
190
+ :message => "ResponseException/Message"
191
+ }.freeze
192
+
193
+ def results
194
+ results = {}
195
+ xml.each_element("Results/JobParameter") do |result|
196
+ name = result.elements["ParameterName"]&.text&.strip
197
+ value = result.elements["ParameterValue"]&.text&.strip
198
+ results[name] = value unless name.nil?
199
+ end
200
+ results
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'uri'
5
+
6
+ module IbmPowerHmc
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
+
44
+ ##
45
+ # @!method managed_system_metrics(sys_uuid:, start_ts: nil, end_ts: nil, no_samples: nil, aggregated: false)
46
+ # Retrieve metrics for a managed system.
47
+ # @param sys_uuid [String] The managed system UUID.
48
+ # @param start_ts [Time] Start timestamp.
49
+ # @param end_ts [Time] End timestamp.
50
+ # @param no_samples [Integer] Number of samples.
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?
61
+
62
+ response = request(:get, method_url)
63
+ FeedParser.new(response.body).entries do |entry|
64
+ category = entry.elements["category"]
65
+ next if category.nil?
66
+
67
+ term = category.attributes["term"]
68
+ next if term.nil? || term != "ManagedSystem"
69
+
70
+ link = entry.elements["link"]
71
+ next if link.nil?
72
+
73
+ href = link.attributes["href"]
74
+ next if href.nil?
75
+
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
120
+ end
121
+ end
122
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IbmPowerHmc
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
5
5
  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/objects.rb"
10
+ require_relative "./ibm_power_hmc/parser.rb"
11
11
  require_relative "./ibm_power_hmc/job.rb"
12
12
  require_relative "./ibm_power_hmc/connection.rb"
13
+ require_relative "./ibm_power_hmc/pcm.rb"
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.1.0
4
+ version: 0.3.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-09-06 00:00:00.000000000 Z
11
+ date: 2021-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -31,9 +31,10 @@ 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
- - Gemfile.lock
37
38
  - LICENSE
38
39
  - README.md
39
40
  - Rakefile
@@ -43,7 +44,8 @@ files:
43
44
  - lib/ibm_power_hmc.rb
44
45
  - lib/ibm_power_hmc/connection.rb
45
46
  - lib/ibm_power_hmc/job.rb
46
- - lib/ibm_power_hmc/objects.rb
47
+ - lib/ibm_power_hmc/parser.rb
48
+ - lib/ibm_power_hmc/pcm.rb
47
49
  - lib/ibm_power_hmc/version.rb
48
50
  homepage: http://github.com/IBM/ibm_power_hmc_sdk_ruby
49
51
  licenses:
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,157 +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
-
29
- def to_s
30
- "uuid=#{@uuid}"
31
- end
32
- end
33
-
34
- # HMC information
35
- class ManagementConsole < HmcObject
36
- XMLMAP = {
37
- "ManagementConsoleName" => "name",
38
- "VersionInfo/BuildLevel" => "build_level",
39
- "BaseVersion" => "version"
40
- }.freeze
41
-
42
- def initialize(doc)
43
- super(doc)
44
- info = doc.elements["content/ManagementConsole:ManagementConsole"]
45
- get_values(info, XMLMAP)
46
- end
47
-
48
- def to_s
49
- "hmc name=#{@name} version=#{@version} build_level=#{@build_level}"
50
- end
51
- end
52
-
53
- # Managed System information
54
- class ManagedSystem < HmcObject
55
- XMLMAP = {
56
- "SystemName" => "name",
57
- "State" => "state",
58
- "Hostname" => "hostname",
59
- "PrimaryIPAddress" => "ipaddr",
60
- "AssociatedSystemMemoryConfiguration/InstalledSystemMemory" => "memory",
61
- "AssociatedSystemMemoryConfiguration/CurrentAvailableSystemMemory" => "avail_mem",
62
- "AssociatedSystemProcessorConfiguration/InstalledSystemProcessorUnits" => "cpus",
63
- "AssociatedSystemProcessorConfiguration/CurrentAvailableSystemProcessorUnits" => "avail_cpus"
64
- }.freeze
65
-
66
- def initialize(doc)
67
- super(doc)
68
- info = doc.elements["content/ManagedSystem:ManagedSystem"]
69
- get_values(info, XMLMAP)
70
- 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
- end
76
-
77
- # Logical Partition information
78
- class LogicalPartition < HmcObject
79
- attr_reader :sys_uuid
80
-
81
- XMLMAP = {
82
- "PartitionName" => "name",
83
- "PartitionID" => "id",
84
- "PartitionState" => "state",
85
- "PartitionType" => "type",
86
- "PartitionMemoryConfiguration/CurrentMemory" => "memory",
87
- "PartitionProcessorConfiguration/HasDedicatedProcessors" => "dedicated",
88
- "ResourceMonitoringControlState" => "rmc_state",
89
- "ResourceMonitoringIPAddress" => "rmc_ipaddr"
90
- }.freeze
91
-
92
- def initialize(doc)
93
- super(doc)
94
- info = doc.elements["content/LogicalPartition:LogicalPartition"]
95
- sys_href = info.elements["AssociatedManagedSystem"].attributes["href"]
96
- @sys_uuid = URI(sys_href).path.split('/').last
97
- get_values(info, XMLMAP)
98
- 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
- end
104
-
105
- # VIOS information
106
- class VirtualIOServer < HmcObject
107
- attr_reader :sys_uuid
108
-
109
- XMLMAP = {
110
- "PartitionName" => "name",
111
- "PartitionID" => "id",
112
- "PartitionState" => "state",
113
- "PartitionType" => "type",
114
- "PartitionMemoryConfiguration/CurrentMemory" => "memory",
115
- "PartitionProcessorConfiguration/HasDedicatedProcessors" => "dedicated"
116
- }.freeze
117
-
118
- def initialize(doc)
119
- super(doc)
120
- info = doc.elements["content/VirtualIOServer:VirtualIOServer"]
121
- sys_href = info.elements["AssociatedManagedSystem"].attributes["href"]
122
- @sys_uuid = URI(sys_href).path.split('/').last
123
- get_values(info, XMLMAP)
124
- 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
- end
137
-
138
- # HMC Event
139
- class Event < HmcObject
140
- XMLMAP = {
141
- "EventID" => "id",
142
- "EventType" => "type",
143
- "EventData" => "data",
144
- "EventDetail" => "detail",
145
- }.freeze
146
-
147
- def initialize(doc)
148
- super(doc)
149
- info = doc.elements["content/Event:Event"]
150
- get_values(info, XMLMAP)
151
- end
152
-
153
- def to_s
154
- "event id=#{@id} type=#{@type} data=#{@data} detail=#{@detail}"
155
- end
156
- end
157
- end