ibm_power_hmc 0.18.0 → 0.19.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: 8e8b824464b658e795023dba5c23ec80a7b90e830c204d7184a786029d37f276
4
+ data.tar.gz: 5eb6491fd0d3f7d465acc0a8bbdac0063ceb1e028ad4c7b14b3ac92e7f79d622
5
5
  SHA512:
6
- metadata.gz: dc1d8e450a39902ea9aaee7765b2bd8c8850a9d7dc99abca96ee320287852d0d3fb7738fd4820edd3827c00030e66edaada481aab2de9e3850a9d8b32c98e2c1
7
- data.tar.gz: 01c46f3e296b808afccfcf37e4a3f259b51b807fc051929965e4f2d5eba0cd3f4e14e0432819c9626b36647128d0fb59e9a1e1b0b6c740e839662308991f3079
6
+ metadata.gz: 1a13e2dc82679cadc1ee2de5029aa30346402bf4d41e26932ab16325e097b63814d482ffcdd2d9e1fd14cb21e771231ca3ec52e5c5af6b2317fc1e43c3fd4adf
7
+ data.tar.gz: 1e502b797270f3b71bb9d01280dc40a3f60e81ed2782027273ca75e045347872b641499622f915ed36f1dc75605468c6b86caa5c4bbd1894cff38189b6023ded
data/CHANGELOG.md CHANGED
@@ -1,2 +1,77 @@
1
- = 0.1.0
1
+ ## v0.19.0
2
+ * Major code refactoring
3
+ * Add `serviceable_events` method
4
+ * Add schema definitions for serviceable events
5
+ * Add `lpar_delete` method
6
+ * Add HttpNotFound exception for 404 errors
7
+ ## v0.18.0
8
+ * Remove deprecated `rename_lpar` method (replaced by `modify_object`)
9
+ * Add schema definition for SEA
10
+ * Add schema definition for trunk adapters
11
+ * Add schema definition for IPInterface
12
+ ## v0.17.0
13
+ * Add extended group attributes to lpars and vioses methods
14
+ * Add `lpars_quick` and `vioses_quick` methods
15
+ ## v0.16.0
16
+ * Add timeout parameter for `IbmPowerHmc::Connection`
17
+ * Export `modify_object` method
18
+ * Add more attributes to ManagementConsole schema definition
19
+ * Add schema definitions for more IOAdapters
20
+ ## v0.15.0
21
+ * Add `managed_systems_quick` and `managed_system_quick` methods
22
+ ## v0.14.0
23
+ * Make search parameter a string instead of a hash
24
+ * Add `is_classic_hmc_mgmt` and `is_hmc_mgmt_master` to schema definitions
25
+ ## v0.13.0
26
+ * Add `lpar_migrate_validate` and `lpar_migrate` methods
27
+ * Add `vscsi_client_adapter` and `vfc_client_adapter` methods
28
+ * Add schema definition for SharedProcessorPool
29
+ ## 0.12.0
30
+ * Add permissive parameter to vioses method
31
+ * Add draft parameter to templates and `templates_summary` methods
32
+ * Add `template_copy` method
33
+ * Add `sys_uuid` parameter to `managed_system_pcm_preferences` method
34
+ ## v0.11.0
35
+ * Add `template_check`, `template_transform` and `template_provision` methods
36
+ * Add JobFailed exception
37
+ * Add vfc, vlans, vscsi setters to schema definition for templates
38
+ ## v0.10.0
39
+ * Add `managed_system_pcm_preferences` method
40
+ * Add schema definitions for PCM
41
+ ## v0.9.0
42
+ * Add groups method
43
+ * Add SSH public keys to ManagementConsole schema definition
44
+ * Add schema definitions for groups
45
+ * Add schema definition for SharedFileSystemFile
46
+ * Fix parsing of unknown backing devices
47
+ ## v0.8.0
48
+ * Add templates method
49
+ ## v0.7.0
50
+ * Add cluster, SSP and tier methods
51
+ * Add template methods
52
+ * Add `capture_lpar` method
53
+ * Add usertask method
54
+ * Add schema definition for IOAdapter
55
+ * Add schema definitions for disks
56
+ * Add schema definitions for VSCSI and VFC
57
+ * Add schema definitions for cluster, SSP and tier
58
+ * Add schema definitions for templates
59
+ ## v0.6.0
60
+ * Add SRIOV and VNIC methods
61
+ * Add schema definitions for SRIOVEthernetLogicalPort and VirtualNICDedicated
62
+ ## v0.5.0
63
+ * Add `virtual_networks` method for VLANs
64
+ * Add schema definitions for VirtualNetwork, VirtualIOAdapter, VirtualEthernetAdapter
65
+ ## v0.4.0
66
+ * Add `network_adapter_lpar` and `network_adapter_vios` methods
67
+ * Add `virtual_switches` and `virtual_switch` methods
68
+ * Add schema definitions for VirtualSwitch and ClientNetworkAdapter
69
+ ## v0.3.0
70
+ * Add `rename_lpar` method
71
+ * Add `remove_connection` method
72
+ ## v0.2.0
73
+ * Add rubocop local overrides
74
+ * Add PCM APIs
75
+ * Add search parameter
76
+ ## v0.1.0
2
77
  * Initial release
data/README.md CHANGED
@@ -70,7 +70,13 @@ Shutting down a logical partition:
70
70
  hc.poweroff_lpar(lpar_uuid, { "operation" => "shutdown" })
71
71
  ```
72
72
 
73
- Processing events:
73
+ Listing serviceable events:
74
+
75
+ ```ruby
76
+ puts hc.serviceable_events
77
+ ```
78
+
79
+ Processing HMC events:
74
80
 
75
81
  ```ruby
76
82
  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.path : 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