bosh_vcloud_cpi 0.7.10 → 0.9.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
  SHA1:
3
- metadata.gz: fb7cda14ebdb11a1c818ce26c463bc7fd9605bd3
4
- data.tar.gz: 7a6e5455d43ccd766749289d04592e9d61c630cd
3
+ metadata.gz: c4d97d94d84c1a9a705a9ba642388c1f47b34cf7
4
+ data.tar.gz: 34d48cd6dfe0feb24ed2e726b4787f852c50b4c8
5
5
  SHA512:
6
- metadata.gz: d644a6ecb8f31d59a23e18c11bd479233a1bd48420b449816d751c5f8d1bbf01836d8dbd12c630da58a383f75fd0af3dab8f2be2dfbb4da70365bacb9adc6998
7
- data.tar.gz: e5f5d04c699e5f7e56068be8f7c54c2add73396e8e12e77fbaffa4b1c45f446a7770b5f0c3c873345840c42730e27bb9b30472684e765e44ef4378645998bf4e
6
+ metadata.gz: 33d7e13c598313b197ee41be1979e3d86ad3de71c5584575f192708fa6b7840c5193dd98579a6b3e4e7e3a4a95a60c92cf111bbf889b1a2f76fd8ec89bb2a7be
7
+ data.tar.gz: d2d62fa77096ee532349c274d64f9e8ec3425cc34dba3771e43a55f5969b5b1d6b36b2903ebd1d211445eb96f0dd3bb52c6651b2dc119022f2de172bdba16825
@@ -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
- s.next Steps::CreateTemplate, "sc-#{unique_name}"
33
- s.next Steps::UploadTemplateFiles
34
- s.next Steps::AddCatalog, @client.catalog_name(:vapp)
35
- s.next Steps::AddCatalogItem, :vapp, s.state[:vapp_template]
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: 10, on: errors) do
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: 20, on: errors) do
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: 20, on: errors) do
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
- vapp = s.state[:vapp] = client.resolve_link vm.container_vapp_link
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: 20, on: errors) do
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: 20, on: errors) do
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, &block)
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
- template = client.invoke :post, client.vdc.upload_link, :payload => params
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
- output = `#{genisoimage} -o #{iso_path} #{env_path} 2>&1`
20
- @logger.debug "GENISOIMAGE #{output}"
21
- raise "genisoimage: #{$?.exitstatus}: #{output}" unless $?.success?
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 genisoimage # TODO: this should exist in bosh_common, eventually
39
- @genisoimage ||= Bosh::Common.which(%w{genisoimage mkisofs})
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.1'
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 accept_failure || entity.tasks.nil? || entity.tasks.empty?
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.error "Failed tasks: #{failed_tasks}"
171
- failed_tasks_info = failed_tasks.map {|t| "Task #{t.urn} #{t.operation}"}
172
- raise "Some tasks failed: #{failed_tasks_info.join('; ')}"
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
- @url + path
251
- else
252
- path
253
- end,
252
+ @url + path
253
+ else
254
+ path
255
+ end,
254
256
  :headers => {
255
- :Accept => "application/*+xml;version=#{VCLOUD_VERSION_NUMBER}",
256
- :content_type => '*/*'
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.encode64(auth)}"
284
- response = send_request :post, login_url,
285
- :headers => { :Authorization => auth_header, :content_type => 'application/x-www-form-urlencoded' },
286
- :payload => URI.encode_www_form({ :Authorization => auth_header, :Accept => "application/*+xml;version=#{VCLOUD_VERSION_NUMBER}" }),
287
- :with_response => true
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
@@ -1,9 +1,7 @@
1
1
  module Bosh
2
2
  module Clouds
3
-
4
3
  class VCloud
5
- VERSION = '0.5.5'
4
+ VERSION = '0.9.0'
6
5
  end
7
-
8
6
  end
9
7
  end
@@ -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.7.10
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-07-13 00:00:00.000000000 Z
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
- dc1c42
127
+ b1e960
128
128
  email: support@cloudfoundry.com
129
129
  executables: []
130
130
  extensions: []