ibm_power_hmc 0.18.0 → 0.19.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: 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