ibm_power_hmc 0.18.0 → 0.20.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a067e3697998766bac04fad91eafee2e1563a5203c9bdcd9570cccea7b8cf3d
4
- data.tar.gz: 0152c5e104b2fe95acb8a232e448708c3e44fd59cf2754a743da35a2856cc3a8
3
+ metadata.gz: 49c35a3e54753bb8c31a1eafc7c6e98e0ad2a662d4d24c284e873ec3d30aa144
4
+ data.tar.gz: 8429c8a52729102cfcdd2294fc25a2a27dd3f01b0ba9f3f0e46ebbea931903ac
5
5
  SHA512:
6
- metadata.gz: dc1d8e450a39902ea9aaee7765b2bd8c8850a9d7dc99abca96ee320287852d0d3fb7738fd4820edd3827c00030e66edaada481aab2de9e3850a9d8b32c98e2c1
7
- data.tar.gz: 01c46f3e296b808afccfcf37e4a3f259b51b807fc051929965e4f2d5eba0cd3f4e14e0432819c9626b36647128d0fb59e9a1e1b0b6c740e839662308991f3079
6
+ metadata.gz: 7b0cdb3f5348b221cd5fd147e63d391719b06324a49eec554fd1820d90f8000fb4000e005d5e638e6445be0608f7ea30a3a1db1d1345ac1cbf32526fd428f01f
7
+ data.tar.gz: 06d590cf0b6f2d92fbdd685d511ebd499597a285a248807cbe2814e5d569ad237753c7b2196c03b40d9f4be25d08071f990dc3d9d3fad0b20e4f5a8ef7a64438
data/CHANGELOG.md CHANGED
@@ -1,2 +1,85 @@
1
- = 0.1.0
1
+ ## v0.20.0
2
+ * Add permissive option (`ignoreError=true`) for cluster APIs
3
+ * Fix `modify_object` method when URI has a query part
4
+ * Add `chcomgmt` method
5
+ * Add `grow_lu` method
6
+ * Add `shared_memory_pool` method
7
+ * Improve schema definitions for CPU and memory
8
+ * Add schema definition for shared memory pool
9
+ ## v0.19.0
10
+ * Major code refactoring
11
+ * Add `serviceable_events` method
12
+ * Add schema definitions for serviceable events
13
+ * Add `lpar_delete` method
14
+ * Add HttpNotFound exception for 404 errors
15
+ ## v0.18.0
16
+ * Remove deprecated `rename_lpar` method (replaced by `modify_object`)
17
+ * Add schema definition for SEA
18
+ * Add schema definition for trunk adapters
19
+ * Add schema definition for IPInterface
20
+ ## v0.17.0
21
+ * Add extended group attributes to lpars and vioses methods
22
+ * Add `lpars_quick` and `vioses_quick` methods
23
+ ## v0.16.0
24
+ * Add timeout parameter for `IbmPowerHmc::Connection`
25
+ * Export `modify_object` method
26
+ * Add more attributes to ManagementConsole schema definition
27
+ * Add schema definitions for more IOAdapters
28
+ ## v0.15.0
29
+ * Add `managed_systems_quick` and `managed_system_quick` methods
30
+ ## v0.14.0
31
+ * Make search parameter a string instead of a hash
32
+ * Add `is_classic_hmc_mgmt` and `is_hmc_mgmt_master` to schema definitions
33
+ ## v0.13.0
34
+ * Add `lpar_migrate_validate` and `lpar_migrate` methods
35
+ * Add `vscsi_client_adapter` and `vfc_client_adapter` methods
36
+ * Add schema definition for SharedProcessorPool
37
+ ## 0.12.0
38
+ * Add permissive parameter to vioses method
39
+ * Add draft parameter to templates and `templates_summary` methods
40
+ * Add `template_copy` method
41
+ * Add `sys_uuid` parameter to `managed_system_pcm_preferences` method
42
+ ## v0.11.0
43
+ * Add `template_check`, `template_transform` and `template_provision` methods
44
+ * Add JobFailed exception
45
+ * Add vfc, vlans, vscsi setters to schema definition for templates
46
+ ## v0.10.0
47
+ * Add `managed_system_pcm_preferences` method
48
+ * Add schema definitions for PCM
49
+ ## v0.9.0
50
+ * Add groups method
51
+ * Add SSH public keys to ManagementConsole schema definition
52
+ * Add schema definitions for groups
53
+ * Add schema definition for SharedFileSystemFile
54
+ * Fix parsing of unknown backing devices
55
+ ## v0.8.0
56
+ * Add templates method
57
+ ## v0.7.0
58
+ * Add cluster, SSP and tier methods
59
+ * Add template methods
60
+ * Add `capture_lpar` method
61
+ * Add usertask method
62
+ * Add schema definition for IOAdapter
63
+ * Add schema definitions for disks
64
+ * Add schema definitions for VSCSI and VFC
65
+ * Add schema definitions for cluster, SSP and tier
66
+ * Add schema definitions for templates
67
+ ## v0.6.0
68
+ * Add SRIOV and VNIC methods
69
+ * Add schema definitions for SRIOVEthernetLogicalPort and VirtualNICDedicated
70
+ ## v0.5.0
71
+ * Add `virtual_networks` method for VLANs
72
+ * Add schema definitions for VirtualNetwork, VirtualIOAdapter, VirtualEthernetAdapter
73
+ ## v0.4.0
74
+ * Add `network_adapter_lpar` and `network_adapter_vios` methods
75
+ * Add `virtual_switches` and `virtual_switch` methods
76
+ * Add schema definitions for VirtualSwitch and ClientNetworkAdapter
77
+ ## v0.3.0
78
+ * Add `rename_lpar` method
79
+ * Add `remove_connection` method
80
+ ## v0.2.0
81
+ * Add rubocop local overrides
82
+ * Add PCM APIs
83
+ * Add search parameter
84
+ ## v0.1.0
2
85
  * Initial release
data/README.md CHANGED
@@ -70,7 +70,21 @@ Shutting down a logical partition:
70
70
  hc.poweroff_lpar(lpar_uuid, { "operation" => "shutdown" })
71
71
  ```
72
72
 
73
- Processing events:
73
+ Setting the memory of a logical partition to 32GB:
74
+
75
+ ```ruby
76
+ hc.modify_object do
77
+ hc.lpar(lpar_uuid).tap { |lpar| lpar.desired_memory = 32_768 }
78
+ end
79
+ ```
80
+
81
+ Listing serviceable events:
82
+
83
+ ```ruby
84
+ puts hc.serviceable_events
85
+ ```
86
+
87
+ Processing HMC events:
74
88
 
75
89
  ```ruby
76
90
  loop do
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Module for IBM HMC Rest API Client
4
+ module IbmPowerHmc
5
+ class Error < StandardError; end
6
+
7
+ ##
8
+ # HMC REST Client connection.
9
+ class Connection
10
+ ##
11
+ # @!method initialize(host:, password:, username: "hscroot", port: 12_443, validate_ssl: true, timeout: 60)
12
+ # Create a new HMC connection.
13
+ #
14
+ # @param host [String] Hostname of the HMC.
15
+ # @param password [String] Password.
16
+ # @param username [String] User name.
17
+ # @param port [Integer] TCP port number.
18
+ # @param validate_ssl [Boolean] Verify SSL certificates.
19
+ # @param timeout [Integer] The default HTTP timeout in seconds.
20
+ def initialize(host:, password:, username: "hscroot", port: 12_443, validate_ssl: true, timeout: 60)
21
+ @hostname = "#{host}:#{port}"
22
+ @username = username
23
+ @password = password
24
+ @verify_ssl = validate_ssl
25
+ @api_session_token = nil
26
+ @timeout = timeout
27
+ end
28
+
29
+ ##
30
+ # @!method logon
31
+ # Establish a trusted session with the Web Services APIs.
32
+ # @return [String] The X-API-Session token.
33
+ def logon
34
+ method_url = "/rest/api/web/Logon"
35
+ headers = {
36
+ :content_type => "application/vnd.ibm.powervm.web+xml; type=LogonRequest"
37
+ }
38
+ doc = REXML::Document.new("")
39
+ doc.add_element("LogonRequest", "schemaVersion" => "V1_1_0")
40
+ doc.root.add_namespace("http://www.ibm.com/xmlns/systems/power/firmware/web/mc/2012_10/")
41
+ doc.root.add_element("UserID").text = @username
42
+ doc.root.add_element("Password").text = @password
43
+
44
+ @api_session_token = ""
45
+ response = request(:put, method_url, headers, doc.to_s)
46
+ doc = REXML::Document.new(response.body)
47
+ elem = doc.elements["LogonResponse/X-API-Session"]
48
+ raise Error, "LogonResponse/X-API-Session not found" if elem.nil?
49
+
50
+ @api_session_token = elem.text
51
+ end
52
+
53
+ ##
54
+ # @!method logoff
55
+ # Close the session.
56
+ def logoff
57
+ # Don't want to trigger automatic logon here!
58
+ return if @api_session_token.nil?
59
+
60
+ method_url = "/rest/api/web/Logon"
61
+ begin
62
+ request(:delete, method_url)
63
+ rescue
64
+ # Ignore exceptions as this is best effort attempt to log off.
65
+ end
66
+ @api_session_token = nil
67
+ end
68
+
69
+ ##
70
+ # @!method usertask(uuid = true)
71
+ # Retrieve details of an event of type "user task".
72
+ # @param uuid [String] UUID of user task.
73
+ # @return [Hash] Hash of user task attributes.
74
+ def usertask(uuid)
75
+ method_url = "/rest/api/ui/UserTask/#{uuid}"
76
+ response = request(:get, method_url)
77
+ j = JSON.parse(response.body)
78
+ if j['status'].eql?("Completed")
79
+ case j['key']
80
+ when "TEMPLATE_PARTITION_SAVE", "TEMPLATE_PARTITION_SAVE_AS", "TEMPLATE_PARTITION_CAPTURE"
81
+ j['template_uuid'] = templates_summary.find { |t| t.name.eql?(j['labelParams'].first) }&.uuid
82
+ end
83
+ end
84
+ j
85
+ end
86
+
87
+ ##
88
+ # @!method schema(type)
89
+ # Retrieve the XML schema file for a given object type.
90
+ # @param type [String] The object type (e.g. "LogicalPartition", "inc/Types")
91
+ # @return [REXML::Document] The XML schema file.
92
+ def schema(type)
93
+ method_url = "/rest/api/web/schema/#{type}.xsd"
94
+ response = request(:get, method_url)
95
+ REXML::Document.new(response.body)
96
+ end
97
+
98
+ class HttpError < Error
99
+ attr_reader :status, :uri, :reason, :message, :original_exception
100
+
101
+ ##
102
+ # @!method initialize(err)
103
+ # Create a new HttpError exception.
104
+ # @param err [RestClient::Exception] The REST client exception.
105
+ def initialize(err)
106
+ super
107
+ @original_exception = err
108
+ @status = err.http_code
109
+ @message = err.message
110
+
111
+ # Try to parse body as an HttpErrorResponse.
112
+ unless err.response.nil?
113
+ begin
114
+ resp = Parser.new(err.response.body).object(:HttpErrorResponse)
115
+ @uri = resp.uri
116
+ @reason = resp.reason
117
+ @message = resp.message
118
+ rescue
119
+ # not an XML body
120
+ end
121
+ end
122
+ end
123
+
124
+ def to_s
125
+ "msg=\"#{@message}\" status=\"#{@status}\" reason=\"#{@reason}\" uri=#{@uri}"
126
+ end
127
+ end
128
+
129
+ class HttpNotFound < HttpError; end
130
+
131
+ ##
132
+ # @!method request(method, url, headers = {}, payload = nil)
133
+ # Perform a REST API request.
134
+ # @param method [String] The HTTP method.
135
+ # @param url [String] The method URL.
136
+ # @param headers [Hash] HTTP headers.
137
+ # @param payload [String] HTTP request payload.
138
+ # @return [RestClient::Response] The response from the HMC.
139
+ def request(method, url, headers = {}, payload = nil)
140
+ logon if @api_session_token.nil?
141
+ reauth = false
142
+ # Check for relative URLs
143
+ url = "https://#{@hostname}#{url}" if url.start_with?("/")
144
+ begin
145
+ headers = headers.merge("X-API-Session" => @api_session_token)
146
+ RestClient::Request.execute(
147
+ :method => method,
148
+ :url => url,
149
+ :verify_ssl => @verify_ssl,
150
+ :payload => payload,
151
+ :headers => headers,
152
+ :timeout => @timeout
153
+ )
154
+ rescue RestClient::Exception => e
155
+ raise HttpNotFound.new(e), "Not found" if e.http_code == 404
156
+
157
+ # Do not retry on failed logon attempts.
158
+ if e.http_code == 401 && @api_session_token != "" && !reauth
159
+ # Try to reauth.
160
+ reauth = true
161
+ logon
162
+ retry
163
+ end
164
+ raise HttpError.new(e), "REST request failed"
165
+ end
166
+ end
167
+
168
+ # @!method modify_object(headers = {}, attempts = 5)
169
+ # Post an IbmPowerHmc::AbstractRest object iteratively using ETag.
170
+ # @param headers [Hash] HTTP headers.
171
+ # @param attempts [Integer] Maximum number of retries.
172
+ # @yieldreturn [IbmPowerHmc::AbstractRest] The object to modify.
173
+ def modify_object(headers = {}, attempts = 5, &block)
174
+ modify_object_url(nil, headers, attempts, &block)
175
+ end
176
+
177
+ private
178
+
179
+ def modify_object_url(method_url = nil, headers = {}, attempts = 5)
180
+ while attempts > 0
181
+ obj = yield
182
+ raise "object has no href" if method_url.nil? && (!obj.kind_of?(AbstractRest) || obj.href.nil?)
183
+
184
+ # Use ETag to ensure object has not changed.
185
+ headers = headers.merge("If-Match" => obj.etag, :content_type => obj.content_type)
186
+ begin
187
+ request(:post, method_url.nil? ? obj.href.to_s : method_url, headers, obj.xml.to_s)
188
+ break
189
+ rescue HttpError => e
190
+ attempts -= 1
191
+ # Will get 412 ("Precondition Failed") if ETag mismatches.
192
+ raise if e.status != 412 || attempts == 0
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
File without changes
File without changes
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Serviceable Events Manager.
5
+
6
+ module IbmPowerHmc
7
+ class Connection
8
+ ##
9
+ # @!method serviceable_events(status = nil)
10
+ # Retrieve serviceable events from the HMC.
11
+ # @param status [String] Query only events in that state.
12
+ # @return [Array<IbmPowerHmc::ServiceableEvent>] The list of serviceable events.
13
+ def serviceable_events(status = nil)
14
+ method_url = "/rest/api/sem/ServiceableEvent"
15
+ method_url += "?status=#{status}" unless status.nil?
16
+ response = request(:get, method_url)
17
+ FeedParser.new(response.body).objects(:ServiceableEvent)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IbmPowerHmc
4
+ class Connection
5
+ ##
6
+ # @!method templates_summary(draft = false)
7
+ # Retrieve the list of partition template summaries.
8
+ # @param draft [Boolean] Retrieve draft templates as well
9
+ # @return [Array<IbmPowerHmc::PartitionTemplateSummary>] The list of partition template summaries.
10
+ def templates_summary(draft = false)
11
+ method_url = "/rest/api/templates/PartitionTemplate#{'?draft=false' unless draft}"
12
+ response = request(:get, method_url)
13
+ FeedParser.new(response.body).objects(:PartitionTemplateSummary)
14
+ end
15
+
16
+ ##
17
+ # @!method templates(draft = false)
18
+ # Retrieve the list of partition templates.
19
+ # @param draft [Boolean] Retrieve draft templates as well
20
+ # @return [Array<IbmPowerHmc::PartitionTemplate>] The list of partition templates.
21
+ def templates(draft = false)
22
+ method_url = "/rest/api/templates/PartitionTemplate?detail=full#{'&draft=false' unless draft}"
23
+ response = request(:get, method_url)
24
+ FeedParser.new(response.body).objects(:PartitionTemplate)
25
+ end
26
+
27
+ ##
28
+ # @!method template(template_uuid)
29
+ # Retrieve details for a particular partition template.
30
+ # @param template_uuid [String] UUID of the partition template.
31
+ # @return [IbmPowerHmc::PartitionTemplate] The partition template.
32
+ def template(template_uuid)
33
+ method_url = "/rest/api/templates/PartitionTemplate/#{template_uuid}"
34
+ response = request(:get, method_url)
35
+ Parser.new(response.body).object(:PartitionTemplate)
36
+ end
37
+
38
+ ##
39
+ # @!method capture_lpar(lpar_uuid, sys_uuid, template_name, sync = true)
40
+ # Capture partition configuration as template.
41
+ # @param lpar_uuid [String] The UUID of the logical partition.
42
+ # @param sys_uuid [String] The UUID of the managed system.
43
+ # @param template_name [String] The name to be given for the new template.
44
+ # @param sync [Boolean] Start the job and wait for its completion.
45
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
46
+ def capture_lpar(lpar_uuid, sys_uuid, template_name, sync = true)
47
+ # Need to include session token in payload so make sure we are logged in
48
+ logon if @api_session_token.nil?
49
+ method_url = "/rest/api/templates/PartitionTemplate/do/capture"
50
+ params = {
51
+ "TargetUuid" => lpar_uuid,
52
+ "NewTemplateName" => template_name,
53
+ "ManagedSystemUuid" => sys_uuid,
54
+ "K_X_API_SESSION_MEMENTO" => @api_session_token
55
+ }
56
+ job = HmcJob.new(self, method_url, "Capture", "PartitionTemplate", params)
57
+ job.run if sync
58
+ job
59
+ end
60
+
61
+ ##
62
+ # @!method template_check(template_uuid, target_sys_uuid, sync = true)
63
+ # Start Template Check job (first of three steps to deploy an LPAR from a Template).
64
+ # @param template_uuid [String] The UUID of the Template to deploy an LPAR from.
65
+ # @param target_sys_uuid [String] The UUID of the Managed System to deploy the LPAR on.
66
+ # @param sync [Boolean] Start the job and wait for its completion.
67
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
68
+ def template_check(template_uuid, target_sys_uuid, sync = true)
69
+ # Need to include session token in payload so make sure we are logged in
70
+ logon if @api_session_token.nil?
71
+ method_url = "/rest/api/templates/PartitionTemplate/#{template_uuid}/do/check"
72
+ params = {
73
+ "TargetUuid" => target_sys_uuid,
74
+ "K_X_API_SESSION_MEMENTO" => @api_session_token
75
+ }
76
+ job = HmcJob.new(self, method_url, "Check", "PartitionTemplate", params)
77
+ job.run if sync
78
+ job
79
+ end
80
+
81
+ ##
82
+ # @!method template_transform(draft_template_uuid, target_sys_uuid, sync = true)
83
+ # Start Template Transform job (second of three steps to deploy an LPAR from a Template).
84
+ # @param draft_template_uuid [String] The UUID of the Draft Template created by the Template Check job.
85
+ # @param target_sys_uuid [String] The UUID of the Managed System to deploy the LPAR on.
86
+ # @param sync [Boolean] Start the job and wait for its completion.
87
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
88
+ def template_transform(draft_template_uuid, target_sys_uuid, sync = true)
89
+ # Need to include session token in payload so make sure we are logged in
90
+ logon if @api_session_token.nil?
91
+ method_url = "/rest/api/templates/PartitionTemplate/#{draft_template_uuid}/do/transform"
92
+ params = {
93
+ "TargetUuid" => target_sys_uuid,
94
+ "K_X_API_SESSION_MEMENTO" => @api_session_token
95
+ }
96
+ job = HmcJob.new(self, method_url, "Transform", "PartitionTemplate", params)
97
+ job.run if sync
98
+ job
99
+ end
100
+
101
+ ##
102
+ # @!method template_deploy(draft_template_uuid, target_sys_uuid, sync = true)
103
+ # Start Template Deploy job (last of three steps to deploy an LPAR from a Template).
104
+ # @param draft_template_uuid [String] The UUID of the Draft Template created by the Template Check job.
105
+ # @param target_sys_uuid [String] The UUID of the Managed System to deploy the LPAR on.
106
+ # @param sync [Boolean] Start the job and wait for its completion.
107
+ # @return [IbmPowerHmc::HmcJob] The HMC job.
108
+ def template_deploy(draft_template_uuid, target_sys_uuid, sync = true)
109
+ # Need to include session token in payload so make sure we are logged in
110
+ logon if @api_session_token.nil?
111
+ method_url = "/rest/api/templates/PartitionTemplate/#{draft_template_uuid}/do/deploy"
112
+ params = {
113
+ "TargetUuid" => target_sys_uuid,
114
+ "TemplateUuid" => draft_template_uuid,
115
+ "K_X_API_SESSION_MEMENTO" => @api_session_token
116
+ }
117
+ job = HmcJob.new(self, method_url, "Deploy", "PartitionTemplate", params)
118
+ job.run if sync
119
+ job
120
+ end
121
+
122
+ ##
123
+ # @!method template_provision(template_uuid, target_sys_uuid, changes)
124
+ # Deploy Logical Partition from a Template (performs Check, Transform and Deploy steps in a single method).
125
+ # @param template_uuid [String] The UUID of the Template to deploy an LPAR from.
126
+ # @param target_sys_uuid [String] The UUID of the Managed System to deploy the LPAR on.
127
+ # @param changes [Hash] Modifications to apply to the Template before deploying Logical Partition.
128
+ # @return [String] The UUID of the deployed Logical Partition.
129
+ def template_provision(template_uuid, target_sys_uuid, changes)
130
+ draft_uuid = template_check(template_uuid, target_sys_uuid).results["TEMPLATE_UUID"]
131
+ template_transform(draft_uuid, target_sys_uuid)
132
+ template_modify(draft_uuid, changes)
133
+ template_deploy(draft_uuid, target_sys_uuid).results["PartitionUuid"]
134
+ end
135
+
136
+ ##
137
+ # @!method template_modify(template_uuid, changes)
138
+ # Modify a template.
139
+ # @param template_uuid [String] UUID of the partition template to modify.
140
+ # @param changes [Hash] Hash of changes to make.
141
+ def template_modify(template_uuid, changes)
142
+ method_url = "/rest/api/templates/PartitionTemplate/#{template_uuid}"
143
+
144
+ # Templates have no href so need to use modify_object_url.
145
+ modify_object_url(method_url) do
146
+ template(template_uuid).tap do |obj|
147
+ changes.each do |key, value|
148
+ obj.send("#{key}=", value)
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ ##
155
+ # @!method template_copy(template_uuid, new_name)
156
+ # Copy existing template to a new one.
157
+ # @param template_uuid [String] UUID of the partition template to copy.
158
+ # @param new_name [String] Name of the new template.
159
+ # @return [IbmPowerHmc::PartitionTemplate] The new partition template.
160
+ def template_copy(template_uuid, new_name)
161
+ method_url = "/rest/api/templates/PartitionTemplate"
162
+ headers = {
163
+ :content_type => "application/vnd.ibm.powervm.templates+xml;type=PartitionTemplate"
164
+ }
165
+ original = template(template_uuid)
166
+ original.name = new_name
167
+ response = request(:put, method_url, headers, original.xml.to_s)
168
+ Parser.new(response.body).object(:PartitionTemplate)
169
+ end
170
+ end
171
+ end