bosh_vcloud_cpi 0.7.10 → 0.9.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 +4 -4
- data/lib/cloud/vcloud/cloud.rb +20 -21
- data/lib/cloud/vcloud/steps/create_disk.rb +1 -1
- data/lib/cloud/vcloud/steps/create_template.rb +13 -2
- data/lib/cloud/vcloud/steps/insert_catalog_media.rb +25 -0
- data/lib/cloud/vcloud/steps/save_agent_env.rb +12 -5
- data/lib/cloud/vcloud/vcd_client.rb +29 -17
- data/lib/cloud/vcloud/version.rb +1 -3
- data/lib/cloud/vcloud/xml/wrapper.rb +1 -2
- data/lib/cloud/vcloud/xml/wrapper_classes/catalog.rb +5 -0
- data/lib/cloud/vcloud/xml/wrapper_classes/task.rb +6 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4d97d94d84c1a9a705a9ba642388c1f47b34cf7
|
4
|
+
data.tar.gz: 34d48cd6dfe0feb24ed2e726b4787f852c50b4c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33d7e13c598313b197ee41be1979e3d86ad3de71c5584575f192708fa6b7840c5193dd98579a6b3e4e7e3a4a95a60c92cf111bbf889b1a2f76fd8ec89bb2a7be
|
7
|
+
data.tar.gz: d2d62fa77096ee532349c274d64f9e8ec3425cc34dba3771e43a55f5969b5b1d6b36b2903ebd1d211445eb96f0dd3bb52c6651b2dc119022f2de172bdba16825
|
data/lib/cloud/vcloud/cloud.rb
CHANGED
@@ -29,10 +29,15 @@ module VCloudCloud
|
|
29
29
|
def create_stemcell(image, _)
|
30
30
|
(steps "create_stemcell(#{image}, _)" do |s|
|
31
31
|
s.next Steps::StemcellInfo, image
|
32
|
-
|
33
|
-
s.next Steps::
|
34
|
-
s.next Steps::
|
35
|
-
|
32
|
+
catalog_type = :vapp
|
33
|
+
s.next Steps::AddCatalog, @client.catalog_name(catalog_type)
|
34
|
+
s.next Steps::CreateTemplate, "sc-#{unique_name}", catalog_type
|
35
|
+
|
36
|
+
# Retry upload template file in case of timeout
|
37
|
+
errors = [Timeout::Error]
|
38
|
+
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries: cpi_retries, on: errors) do |tries, error|
|
39
|
+
s.next Steps::UploadTemplateFiles
|
40
|
+
end
|
36
41
|
end)[:catalog_item].urn
|
37
42
|
end
|
38
43
|
|
@@ -60,6 +65,10 @@ module VCloudCloud
|
|
60
65
|
2
|
61
66
|
end
|
62
67
|
|
68
|
+
def cpi_retries
|
69
|
+
10
|
70
|
+
end
|
71
|
+
|
63
72
|
def create_vm(agent_id, catalog_vapp_id, resource_pool, networks, disk_locality = nil, environment = nil)
|
64
73
|
(steps "create_vm(#{agent_id}, #{catalog_vapp_id}, #{resource_pool}, ...)" do |s|
|
65
74
|
# disk_locality should be an array of disk ids
|
@@ -92,7 +101,7 @@ module VCloudCloud
|
|
92
101
|
container_vapp = nil
|
93
102
|
|
94
103
|
errors = [RuntimeError]
|
95
|
-
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries:
|
104
|
+
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries: cpi_retries, on: errors) do |tries, error|
|
96
105
|
begin
|
97
106
|
begin
|
98
107
|
@logger.debug "Requesting container vApp: #{requested_name}"
|
@@ -152,7 +161,7 @@ module VCloudCloud
|
|
152
161
|
# TODO refact this
|
153
162
|
if requested_name
|
154
163
|
errors = [RuntimeError]
|
155
|
-
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries:
|
164
|
+
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries: cpi_retries, on: errors) do |tries, error|
|
156
165
|
begin
|
157
166
|
save_agent_env s
|
158
167
|
s.next Steps::PowerOn, :vm
|
@@ -177,7 +186,7 @@ module VCloudCloud
|
|
177
186
|
vm = s.state[:vm] = client.resolve_entity(vm_id)
|
178
187
|
|
179
188
|
errors = [RuntimeError]
|
180
|
-
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries:
|
189
|
+
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries: cpi_retries, on: errors) do |tries, error|
|
181
190
|
begin
|
182
191
|
if vm['status'] == VCloudSdk::Xml::RESOURCE_ENTITY_STATUS[:SUSPENDED].to_s
|
183
192
|
s.next Steps::DiscardSuspendedState, :vm
|
@@ -219,18 +228,8 @@ module VCloudCloud
|
|
219
228
|
|
220
229
|
# poweroff vm before we are able to delete it
|
221
230
|
s.next Steps::PowerOff, :vm, true
|
222
|
-
|
223
|
-
|
224
|
-
if vapp.vms.size == 1
|
225
|
-
# Hack: if vApp is running, and the last VM is deleted, it is no longer stoppable and removable
|
226
|
-
# even from dashboard. So if there's only one VM, just stop and delete the vApp
|
227
|
-
s.next Steps::PowerOff, :vapp, true
|
228
|
-
s.next Steps::Undeploy, :vapp
|
229
|
-
s.next Steps::Delete, s.state[:vapp], true
|
230
|
-
else
|
231
|
-
s.next Steps::Undeploy, :vm
|
232
|
-
s.next Steps::Delete, s.state[:vm], true
|
233
|
-
end
|
231
|
+
s.next Steps::Undeploy, :vm
|
232
|
+
s.next Steps::Delete, s.state[:vm], true
|
234
233
|
|
235
234
|
s.next Steps::DeleteCatalogMedia, vm.name
|
236
235
|
rescue RestClient::Forbidden, ObjectNotFoundError => e
|
@@ -264,7 +263,7 @@ module VCloudCloud
|
|
264
263
|
s.state[:disk] = client.resolve_entity disk_id
|
265
264
|
|
266
265
|
errors = [RuntimeError]
|
267
|
-
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries:
|
266
|
+
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries: cpi_retries, on: errors) do |tries, error|
|
268
267
|
begin
|
269
268
|
s.next Steps::AttachDetachDisk, :attach
|
270
269
|
|
@@ -293,7 +292,7 @@ module VCloudCloud
|
|
293
292
|
next unless vm.find_attached_disk s.state[:disk]
|
294
293
|
|
295
294
|
errors = [RuntimeError]
|
296
|
-
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries:
|
295
|
+
Bosh::Common.retryable(sleep: cpi_call_wait_time, tries: cpi_retries, on: errors) do |tries, error|
|
297
296
|
begin
|
298
297
|
if vm['status'] == VCloudSdk::Xml::RESOURCE_ENTITY_STATUS[:SUSPENDED].to_s
|
299
298
|
s.next Steps::DiscardSuspendedState, :vm
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module VCloudCloud
|
2
2
|
module Steps
|
3
3
|
class CreateDisk < Step
|
4
|
-
def perform(name, size_mb, vm, storage_profile, &
|
4
|
+
def perform(name, size_mb, vm, storage_profile, &_block)
|
5
5
|
params = VCloudSdk::Xml::WrapperFactory.create_instance 'DiskCreateParams'
|
6
6
|
params.name = name
|
7
7
|
params.size_bytes = size_mb << 20 # VCD expects bytes
|
@@ -1,12 +1,23 @@
|
|
1
1
|
module VCloudCloud
|
2
2
|
module Steps
|
3
3
|
class CreateTemplate < Step
|
4
|
-
def perform(name, &block)
|
4
|
+
def perform(name, catalog_type, &block)
|
5
|
+
catalog = client.catalog catalog_type
|
6
|
+
|
5
7
|
params = VCloudSdk::Xml::WrapperFactory.create_instance 'UploadVAppTemplateParams'
|
6
8
|
params.name = name
|
7
|
-
|
9
|
+
upload_link = catalog.add_vapp_template_link
|
10
|
+
catalog_item = client.invoke(
|
11
|
+
:post,
|
12
|
+
upload_link,
|
13
|
+
:payload => params,
|
14
|
+
:headers => {:content_type => upload_link.type}
|
15
|
+
)
|
16
|
+
|
17
|
+
template = client.invoke :get, catalog_item.entity.href
|
8
18
|
|
9
19
|
# commit states
|
20
|
+
state[:catalog_item] = catalog_item
|
10
21
|
state[:vapp_template] = template
|
11
22
|
end
|
12
23
|
|
@@ -21,6 +21,31 @@ module VCloudCloud
|
|
21
21
|
end
|
22
22
|
state[:vm] = client.reload vm
|
23
23
|
end
|
24
|
+
|
25
|
+
def rollback
|
26
|
+
vm = state[:vm]
|
27
|
+
name = vm.name
|
28
|
+
|
29
|
+
catalog_media = client.catalog_item :media, name, VCloudSdk::Xml::MEDIA_TYPE[:MEDIA]
|
30
|
+
# return if doesn't exist
|
31
|
+
return unless catalog_media
|
32
|
+
media = client.resolve_link catalog_media.entity
|
33
|
+
params = VCloudSdk::Xml::WrapperFactory.create_instance 'MediaInsertOrEjectParams'
|
34
|
+
params.media_href = media.href
|
35
|
+
vm = state[:vm]
|
36
|
+
client.timed_loop do
|
37
|
+
media = client.reload media
|
38
|
+
vm = client.reload vm
|
39
|
+
if media.running_tasks.empty?
|
40
|
+
client.invoke_and_wait :post, vm.eject_media_link,
|
41
|
+
:payload => params,
|
42
|
+
:headers => { :content_type => VCloudSdk::Xml::MEDIA_TYPE[:MEDIA_INSERT_EJECT_PARAMS] }
|
43
|
+
break
|
44
|
+
else
|
45
|
+
media = client.wait_entity media
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
24
49
|
end
|
25
50
|
end
|
26
51
|
end
|
@@ -16,9 +16,11 @@ module VCloudCloud
|
|
16
16
|
env_path = File.join tmpdir, 'env'
|
17
17
|
iso_path = File.join tmpdir, 'env.iso'
|
18
18
|
File.open(env_path, 'w') { |f| f.write env_json }
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
command = "#{create_iso_cmd} -o #{iso_path} #{env_path} 2>&1"
|
20
|
+
output = `#{command}`
|
21
|
+
message = "command `#{command}`: exited with stats: `#{$?.exitstatus}`: and output `#{output}`"
|
22
|
+
@logger.debug message
|
23
|
+
raise message unless $?.success?
|
22
24
|
|
23
25
|
metadata = VCloudSdk::Xml::WrapperFactory.create_instance 'MetadataValue'
|
24
26
|
metadata.value = env_json
|
@@ -35,8 +37,13 @@ module VCloudCloud
|
|
35
37
|
|
36
38
|
private
|
37
39
|
|
38
|
-
def
|
39
|
-
@
|
40
|
+
def create_iso_cmd # TODO: this should exist in bosh_common, eventually
|
41
|
+
@create_iso_cmd ||= begin
|
42
|
+
possibilities = %w{genisoimage mkisofs}
|
43
|
+
cmd = Bosh::Common.which(possibilities)
|
44
|
+
raise("Unable to find a iso creation utility `#{possibilities.inspect}`") unless cmd
|
45
|
+
cmd
|
46
|
+
end
|
40
47
|
end
|
41
48
|
end
|
42
49
|
end
|
@@ -12,7 +12,7 @@ module VCloudCloud
|
|
12
12
|
class VCloudClient
|
13
13
|
attr_reader :logger
|
14
14
|
|
15
|
-
VCLOUD_VERSION_NUMBER = '5.
|
15
|
+
VCLOUD_VERSION_NUMBER = '5.5'
|
16
16
|
|
17
17
|
def initialize(vcd_settings, logger)
|
18
18
|
@logger = logger
|
@@ -144,7 +144,7 @@ module VCloudCloud
|
|
144
144
|
return task if status == VCloudSdk::Xml::TASK_STATUS[:SUCCESS]
|
145
145
|
if [:ABORTED, :ERROR, :CANCELED].any? { |s| status == VCloudSdk::Xml::TASK_STATUS[s] }
|
146
146
|
return task if accept_failure
|
147
|
-
raise "Task #{task.urn} #{task.operation} completed unsuccessfully"
|
147
|
+
raise "Task #{task.urn} #{task.operation} completed unsuccessfully, Details:#{task.details}"
|
148
148
|
end
|
149
149
|
end
|
150
150
|
task
|
@@ -164,12 +164,14 @@ module VCloudCloud
|
|
164
164
|
entity = reload entity
|
165
165
|
|
166
166
|
# verify all tasks succeeded
|
167
|
-
unless
|
167
|
+
unless entity.tasks.nil? || entity.tasks.empty?
|
168
168
|
failed_tasks = entity.tasks.find_all { |task| task.status.downcase != VCloudSdk::Xml::TASK_STATUS[:SUCCESS] }
|
169
169
|
unless failed_tasks.empty?
|
170
|
-
@logger.
|
171
|
-
|
172
|
-
|
170
|
+
@logger.debug "Failed tasks: #{failed_tasks}"
|
171
|
+
unless accept_failure
|
172
|
+
failed_tasks_info = failed_tasks.map { |t| "Task #{t.urn} #{t.operation}, Details:#{t.details}" }
|
173
|
+
raise "Some tasks failed: #{failed_tasks_info.join('; ')}"
|
174
|
+
end
|
173
175
|
end
|
174
176
|
end
|
175
177
|
|
@@ -247,13 +249,14 @@ module VCloudCloud
|
|
247
249
|
params = {
|
248
250
|
:method => method,
|
249
251
|
:url => if path.start_with?('/')
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
252
|
+
@url + path
|
253
|
+
else
|
254
|
+
path
|
255
|
+
end,
|
254
256
|
:headers => {
|
255
|
-
|
256
|
-
|
257
|
+
:Accept => "application/*+xml;version=#{VCLOUD_VERSION_NUMBER}",
|
258
|
+
:content_type => '*/*',
|
259
|
+
'X-VMWARE-VCLOUD-CLIENT-REQUEST-ID' => SecureRandom.uuid
|
257
260
|
}
|
258
261
|
}
|
259
262
|
params[:headers][:x_vcloud_authorization] = @auth_token if !options[:login] && @auth_token
|
@@ -280,11 +283,20 @@ module VCloudCloud
|
|
280
283
|
def session
|
281
284
|
unless cookie_available?
|
282
285
|
auth = "#{@user}@#{@entities['organization']}:#{@pass}"
|
283
|
-
auth_header = "Basic #{Base64.
|
284
|
-
response = send_request
|
285
|
-
|
286
|
-
|
287
|
-
|
286
|
+
auth_header = "Basic #{Base64.strict_encode64(auth)}"
|
287
|
+
response = send_request(
|
288
|
+
:post,
|
289
|
+
login_url,
|
290
|
+
:headers => {
|
291
|
+
:Authorization => auth_header,
|
292
|
+
:content_type => 'application/x-www-form-urlencoded'
|
293
|
+
},
|
294
|
+
:payload => URI.encode_www_form({
|
295
|
+
:Authorization => auth_header,
|
296
|
+
:Accept => "application/*+xml;version=#{VCLOUD_VERSION_NUMBER}"
|
297
|
+
}),
|
298
|
+
:with_response => true
|
299
|
+
)
|
288
300
|
|
289
301
|
@auth_token = response.headers[:x_vcloud_authorization]
|
290
302
|
@cookie = response.cookies
|
data/lib/cloud/vcloud/version.rb
CHANGED
@@ -35,8 +35,7 @@ module VCloudSdk
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def create_instance(type_name, ns = nil, namespace_defintions = nil,
|
39
|
-
*args)
|
38
|
+
def create_instance(type_name, ns = nil, namespace_defintions = nil, *args)
|
40
39
|
xml = @@xml_dictionary[type_name]
|
41
40
|
if (xml)
|
42
41
|
wrap_document(xml, ns, namespace_defintions, *args)
|
@@ -7,6 +7,11 @@ module VCloudSdk
|
|
7
7
|
"rel"=>"add"}).first
|
8
8
|
end
|
9
9
|
|
10
|
+
def add_vapp_template_link
|
11
|
+
get_nodes("Link", {"type" => MEDIA_TYPE[:UPLOAD_VAPP_TEMPLATE_PARAMS],
|
12
|
+
"rel"=>"add"}).first
|
13
|
+
end
|
14
|
+
|
10
15
|
def catalog_items(name = nil)
|
11
16
|
if name
|
12
17
|
get_nodes("CatalogItem", {"name" => name})
|
@@ -15,6 +15,12 @@ module VCloudSdk
|
|
15
15
|
self["operation"]
|
16
16
|
end
|
17
17
|
|
18
|
+
def details
|
19
|
+
details = get_nodes("Details")
|
20
|
+
return nil if details.nil?
|
21
|
+
return details.collect {|d| d.content}.join
|
22
|
+
end
|
23
|
+
|
18
24
|
# Short form name of the operation
|
19
25
|
def operation_name
|
20
26
|
self["operationName"]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh_vcloud_cpi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- VMware
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bosh_common
|
@@ -124,7 +124,7 @@ dependencies:
|
|
124
124
|
version: '0'
|
125
125
|
description: |-
|
126
126
|
BOSH vCloud CPI
|
127
|
-
|
127
|
+
b1e960
|
128
128
|
email: support@cloudfoundry.com
|
129
129
|
executables: []
|
130
130
|
extensions: []
|