vra-restapi 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ #
2
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'json'
20
+
21
+ module Vra
22
+ module Exception
23
+ class DuplicateItemsDetected < RuntimeError; end
24
+ class NotFound < RuntimeError; end
25
+ class RequestError < RuntimeError; end
26
+ class Unauthorized < RuntimeError; end
27
+
28
+ class HTTPError < RuntimeError
29
+ attr_accessor :klass, :code, :body, :errors, :path
30
+ def initialize(opts={})
31
+ @code = opts[:code]
32
+ @body = opts[:body]
33
+ @path = opts[:path]
34
+ @klass = opts[:klass]
35
+ @errors = []
36
+
37
+ parse_errors
38
+ end
39
+
40
+ def parse_errors
41
+ begin
42
+ if @body.nil?
43
+ return
44
+ end
45
+ data = JSON.parse(@body)
46
+ rescue JSON::ParserError => e
47
+ return
48
+ end
49
+
50
+ return if data.nil?
51
+ return unless data['errors'].respond_to?(:each)
52
+
53
+ data['errors'].each do |error|
54
+ @errors << error['systemMessage']
55
+ end
56
+ end
57
+ end
58
+
59
+ class HTTPNotFound < HTTPError; end
60
+ end
61
+ end
@@ -0,0 +1,97 @@
1
+ #
2
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'json'
20
+
21
+ module Vra
22
+ class Request
23
+ attr_reader :client, :id
24
+ def initialize(client, id)
25
+ @client = client
26
+ @id = id
27
+
28
+ @request_data = nil
29
+ @status = nil
30
+ @completion_state = nil
31
+ @completion_details = nil
32
+ end
33
+
34
+ def refresh
35
+ @request_data = JSON.parse(client.http_get!("/catalog-service/api/consumer/requests/#{@id}"))
36
+ rescue Vra::Exception::HTTPNotFound
37
+ raise Vra::Exception::NotFound, "request ID #{@id} is not found"
38
+ end
39
+
40
+ def refresh_if_empty
41
+ refresh if request_empty?
42
+ end
43
+
44
+ def request_empty?
45
+ @request_data.nil?
46
+ end
47
+
48
+ def status
49
+ refresh_if_empty
50
+ return if request_empty?
51
+
52
+ @request_data['phase']
53
+ end
54
+
55
+ def completed?
56
+ successful? || failed?
57
+ end
58
+
59
+ def successful?
60
+ status == 'SUCCESSFUL'
61
+ end
62
+
63
+ def failed?
64
+ status == 'FAILED'
65
+ end
66
+
67
+ def completion_state
68
+ refresh_if_empty
69
+ return if request_empty?
70
+
71
+ @request_data['requestCompletion']['requestCompletionState']
72
+ end
73
+
74
+ def completion_details
75
+ refresh_if_empty
76
+ return if request_empty?
77
+
78
+ @request_data['requestCompletion']['completionDetails']
79
+ end
80
+
81
+ def resources
82
+ resources = []
83
+
84
+ begin
85
+ request_resources = client.http_get_paginated_array!("/catalog-service/api/consumer/requests/#{@id}/resources")
86
+ rescue Vra::Exception::HTTPNotFound
87
+ raise Vra::Exception::NotFound, "resources for request ID #{@id} are not found"
88
+ end
89
+
90
+ request_resources.each do |resource|
91
+ resources << Vra::Resource.new(client, data: resource)
92
+ end
93
+
94
+ resources
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,67 @@
1
+ #
2
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module Vra
20
+ class RequestParameters
21
+ def initialize
22
+ @entries = {}
23
+ end
24
+
25
+ def set(key, type, value)
26
+ @entries[key] = Vra::RequestParameter.new(key, type, value)
27
+ end
28
+
29
+ def delete(key)
30
+ @entries.delete(key)
31
+ end
32
+
33
+ def all_entries
34
+ @entries.values
35
+ end
36
+ end
37
+
38
+ class RequestParameter
39
+ attr_accessor :key, :type, :value
40
+ def initialize(key, type, value)
41
+ @key = key
42
+ @type = type
43
+ @value = value
44
+ end
45
+
46
+ def to_h
47
+ {
48
+ 'key' => @key,
49
+ 'value' => {
50
+ 'type' => @type,
51
+ 'value' => format_value
52
+ }
53
+ }
54
+ end
55
+
56
+ def format_value
57
+ case @type
58
+ when 'integer'
59
+ @value.to_i
60
+ when 'string'
61
+ @value.to_s
62
+ else
63
+ @value.to_s
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,40 @@
1
+ #
2
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module Vra
20
+ class Requests
21
+ def initialize(client)
22
+ @client = client
23
+ end
24
+
25
+ def all_requests
26
+ requests = []
27
+
28
+ items = @client.http_get_paginated_array!('/catalog-service/api/consumer/requests')
29
+ items.each do |item|
30
+ requests << Vra::Request.new(@client, item['id'])
31
+ end
32
+
33
+ requests
34
+ end
35
+
36
+ def by_id(id)
37
+ Vra::Request.new(@client, id)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,234 @@
1
+ #
2
+ # Author:: Chef Partner Engineering (<partnereng@chef.io>)
3
+ # Copyright:: Copyright (c) 2015 Chef Software, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require 'json'
20
+
21
+ module Vra
22
+ # rubocop:disable ClassLength
23
+ class Resource
24
+ attr_reader :client, :id, :resource_data
25
+
26
+ def initialize(client, opts)
27
+ @client = client
28
+ @id = opts[:id]
29
+ @resource_data = opts[:data]
30
+ @resource_actions = []
31
+
32
+ if @id.nil? && @resource_data.nil?
33
+ raise ArgumentError, 'must supply an id or a resource data hash'
34
+ end
35
+
36
+ if ! @id.nil? && ! @resource_data.nil?
37
+ raise ArgumentError, 'must supply an id OR a resource data hash, not both'
38
+ end
39
+
40
+ if @resource_data.nil?
41
+ fetch_resource_data
42
+ else
43
+ @id = @resource_data['id']
44
+ end
45
+ end
46
+
47
+ def fetch_resource_data
48
+ @resource_data = JSON.parse(client.http_get!("/catalog-service/api/consumer/resources/#{@id}"))
49
+ rescue Vra::Exception::HTTPNotFound
50
+ raise Vra::Exception::NotFound, "resource ID #{@id} does not exist"
51
+ end
52
+ alias refresh fetch_resource_data
53
+
54
+ def name
55
+ resource_data['name']
56
+ end
57
+
58
+ def description
59
+ resource_data['description']
60
+ end
61
+
62
+ def status
63
+ resource_data['status']
64
+ end
65
+
66
+ def vm?
67
+ %w(Infrastructure.Virtual Infrastructure.Cloud).include?(resource_data['resourceTypeRef']['id'])
68
+ end
69
+
70
+ def tenant_id
71
+ resource_data['organization']['tenantRef']
72
+ end
73
+
74
+ def tenant_name
75
+ resource_data['organization']['tenantLabel']
76
+ end
77
+
78
+ def subtenant_id
79
+ resource_data['organization']['subtenantRef']
80
+ end
81
+
82
+ def subtenant_name
83
+ resource_data['organization']['subtenantLabel']
84
+ end
85
+
86
+ def catalog_id
87
+ resource_data['catalogItem']['id']
88
+ end
89
+
90
+ def catalog_name
91
+ resource_data['catalogItem']['label']
92
+ end
93
+
94
+ def owner_ids
95
+ resource_data['owners'].map { |x| x['ref'] }
96
+ end
97
+
98
+ def owner_names
99
+ resource_data['owners'].map { |x| x['value'] }
100
+ end
101
+
102
+ def machine_status
103
+ status = resource_data['resourceData']['entries'].find { |x| x['key'] == 'MachineStatus' }
104
+ raise 'No MachineStatus entry available for resource' if status.nil?
105
+
106
+ status['value']['value']
107
+ end
108
+
109
+ def machine_on?
110
+ machine_status == 'On'
111
+ end
112
+
113
+ def machine_off?
114
+ machine_status == 'Off'
115
+ end
116
+
117
+ def machine_turning_on?
118
+ machine_status == 'TurningOn' || machine_status == 'MachineActivated'
119
+ end
120
+
121
+ def machine_turning_off?
122
+ %w(TurningOff ShuttingDown).include?(machine_status)
123
+ end
124
+
125
+ def machine_in_provisioned_state?
126
+ machine_status == 'MachineProvisioned'
127
+ end
128
+
129
+ def network_interfaces
130
+ return unless vm?
131
+
132
+ network_list = resource_data['resourceData']['entries'].find { |x| x['key'] == 'NETWORK_LIST' }
133
+ return if network_list.nil?
134
+
135
+ network_list['value']['items'].each_with_object([]) do |item, nics|
136
+ nic = {}
137
+ item['values']['entries'].each do |entry|
138
+ key = entry['key']
139
+ value = entry['value']['value']
140
+ nic[key] = value
141
+ end
142
+
143
+ nics << nic
144
+ end
145
+ end
146
+
147
+ def ip_addresses
148
+ return if !vm? || network_interfaces.nil?
149
+
150
+ addrs = []
151
+ network_interfaces.each do |nic|
152
+ next unless nic.key?('NETWORK_ADDRESS')
153
+ addrs << nic['NETWORK_ADDRESS']
154
+ end
155
+
156
+ addrs
157
+ end
158
+
159
+ def actions
160
+ # if this Resource instance was created with data from a "all_resources" fetch,
161
+ # it is likely missing operations data because the vRA API is not pleasant sometimes.
162
+ fetch_resource_data if resource_data['operations'].nil?
163
+
164
+ resource_data['operations']
165
+ end
166
+
167
+ def action_id_by_name(name)
168
+ return if actions.nil?
169
+
170
+ action = actions.find { |x| x['name'] == name }
171
+ return if action.nil?
172
+
173
+ action['id']
174
+ end
175
+
176
+ def destroy
177
+ action_id = action_id_by_name('Destroy')
178
+ raise Vra::Exception::NotFound, "No destroy action found for resource #{@id}" if action_id.nil?
179
+
180
+ submit_action_request(action_id)
181
+ end
182
+
183
+ def shutdown
184
+ action_id = action_id_by_name('Shutdown')
185
+ raise Vra::Exception::NotFound, "No shutdown action found for resource #{@id}" if action_id.nil?
186
+
187
+ submit_action_request(action_id)
188
+ end
189
+
190
+ def poweroff
191
+ action_id = action_id_by_name('Power Off')
192
+ raise Vra::Exception::NotFound, "No power-off action found for resource #{@id}" if action_id.nil?
193
+
194
+ submit_action_request(action_id)
195
+ end
196
+
197
+ def poweron
198
+ action_id = action_id_by_name('Power On')
199
+ raise Vra::Exception::NotFound, "No power-on action found for resource #{@id}" if action_id.nil?
200
+
201
+ submit_action_request(action_id)
202
+ end
203
+
204
+ def action_request_payload(action_id)
205
+ {
206
+ '@type' => 'ResourceActionRequest',
207
+ 'resourceRef' => {
208
+ 'id' => @id
209
+ },
210
+ 'resourceActionRef' => {
211
+ 'id' => action_id
212
+ },
213
+ 'organization' => {
214
+ 'tenantRef' => tenant_id,
215
+ 'tenantLabel' => tenant_name,
216
+ 'subtenantRef' => subtenant_id,
217
+ 'subtenantLabel' => subtenant_name
218
+ },
219
+ 'state' => 'SUBMITTED',
220
+ 'requestNumber' => 0,
221
+ 'requestData' => {
222
+ 'entries' => []
223
+ }
224
+ }
225
+ end
226
+
227
+ def submit_action_request(action_id)
228
+ payload = action_request_payload(action_id).to_json
229
+ response = client.http_post('/catalog-service/api/consumer/requests', payload)
230
+ request_id = response.headers[:location].split('/')[-1]
231
+ Vra::Request.new(client, request_id)
232
+ end
233
+ end
234
+ end