bosh_vsphere_cpi 2.0.0 → 2.1.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: 0a34eef018c05343002743fbf10d259455c34ebe
4
- data.tar.gz: 268febe0f8b3d79243d7edcd2749c2bf2c989935
3
+ metadata.gz: 60b9ea302efbf07e91dd0adc105f975ec8dcacd8
4
+ data.tar.gz: 1c8ef64cfb700603dd0a14f8c3e4179461225e2d
5
5
  SHA512:
6
- metadata.gz: 3c65dc3f129c698aeaed6bea1fd597e40b8d7b90a5fddb7933cad41a70af2e3db50509366dc834c1e857f7c690ca5497086c66c8c6ca6ddb3134cbe4157a6a35
7
- data.tar.gz: 6161c9e5cec6d4c97f94421bcac212c577a913140d566701ac2bf039edf6fc8bfaab455d5756b7d3c30b4f1013a336485535f66e0b447a3b9cefec5d5c34c1fb
6
+ metadata.gz: 6c86a93bead968a65f17b37c63b03110ec6a41d4ec8a6507796243a6d4a2da4e4327c41fb314e6deeeb4ee513d3c3321133fb45cd0cf7cbda8e4fba2132aa654
7
+ data.tar.gz: 07864ca78d8e30f593e91f031d24248eedacdb93472d20654e3409f79fd2aa746d844dd75f54b7f018eb797c0108b9906faae4f58f17d4b20a92d2efc5d5fc0a
@@ -5,6 +5,7 @@ require 'common/thread_formatter'
5
5
  require 'ruby_vim_sdk'
6
6
 
7
7
  require 'cloud/vsphere/retry_block'
8
+ require 'cloud/vsphere/object_stringifier'
8
9
  require 'cloud/vsphere/agent_env'
9
10
  require 'cloud/vsphere/client'
10
11
  require 'cloud/vsphere/cloud'
@@ -17,11 +17,11 @@ module VSphereCloud
17
17
  datastore_name = cdrom.backing.datastore.name
18
18
  datastore_pattern = Regexp.escape(datastore_name)
19
19
  result = env_iso_folder.match(/\[#{datastore_pattern}\] (.*)/)
20
- raise Bosh::Clouds::CloudError.new('Could not find matching datastore name') unless result
20
+ raise Bosh::Clouds::CloudError.new("Could not find matching datastore name '#{datastore_name}'") unless result
21
21
  env_path = result[1]
22
22
 
23
23
  contents = @file_provider.fetch_file(datacenter_name, datastore_name, "#{env_path}/env.json")
24
- raise Bosh::Clouds::CloudError.new('Unable to load env.json') unless contents
24
+ raise Bosh::Clouds::CloudError.new("Unable to load env.json from '#{env_path}/env.json'") unless contents
25
25
 
26
26
  JSON.load(contents)
27
27
  end
@@ -62,7 +62,7 @@ module VSphereCloud
62
62
  raise 'Recommendations were detected, you may be running in Manual DRS mode. Aborting.' if result.recommendations.any?
63
63
 
64
64
  if result.attempted.empty?
65
- raise "Could not power on VM: #{result.not_attempted.map(&:msg).join(', ')}"
65
+ raise "Could not power on VM '#{vm}': #{result.not_attempted.map(&:fault).map(&:msg).join(', ')}"
66
66
  else
67
67
  task = result.attempted.first.task
68
68
  wait_for_task(task)
@@ -120,16 +120,6 @@ module VSphereCloud
120
120
  @service_content.root_folder.create_folder(name)
121
121
  end
122
122
 
123
- def move_into_folder(folder, objects)
124
- task = folder.move_into(objects)
125
- wait_for_task(task)
126
- end
127
-
128
- def move_into_root_folder(objects)
129
- task = @service_content.root_folder.move_into(objects)
130
- wait_for_task(task)
131
- end
132
-
133
123
  def delete_folder(folder)
134
124
  task = folder.destroy
135
125
  wait_for_task(task)
@@ -152,7 +142,7 @@ module VSphereCloud
152
142
  )[task]
153
143
 
154
144
  duration = Time.now - started
155
- raise "Task taking too long" if duration > 3600 # 1 hour
145
+ raise "Task exceeded 60 minutes, task properties: #{properties}" if duration > 3600 # 1 hour
156
146
 
157
147
  # Update the polling interval based on task progress
158
148
  if properties["info.progress"] && properties["info.progress"] > 0
@@ -8,8 +8,16 @@ module VSphereCloud
8
8
  include RetryBlock
9
9
 
10
10
  class TimeoutException < StandardError; end
11
+ class NetworkException < StandardError
12
+ attr_accessor :vm_cid
13
+
14
+ def message
15
+ super + (vm_cid ? " for VM '#{vm_cid}'" : '')
16
+ end
17
+ end
11
18
 
12
19
  attr_accessor :client
20
+ attr_reader :datacenter
13
21
 
14
22
  def initialize(options)
15
23
  @config = Config.build(options)
@@ -71,10 +79,10 @@ module VSphereCloud
71
79
  Dir.mktmpdir do |temp_dir|
72
80
  @logger.info("Extracting stemcell to: #{temp_dir}")
73
81
  output = `tar -C #{temp_dir} -xzf #{image} 2>&1`
74
- raise "Corrupt image, tar exit status: #{$?.exitstatus} output: #{output}" if $?.exitstatus != 0
82
+ raise "Corrupt image '#{image}', tar exit status: #{$?.exitstatus}, output: #{output}" if $?.exitstatus != 0
75
83
 
76
84
  ovf_file = Dir.entries(temp_dir).find { |entry| File.extname(entry) == '.ovf' }
77
- raise 'Missing OVF' if ovf_file.nil?
85
+ raise "Missing OVF for stemcell '#{stemcell}'" if ovf_file.nil?
78
86
  ovf_file = File.join(temp_dir, ovf_file)
79
87
 
80
88
  name = "sc-#{SecureRandom.uuid}"
@@ -276,8 +284,12 @@ module VSphereCloud
276
284
  @logger.debug("Reading current agent env: #{env.pretty_inspect}")
277
285
 
278
286
  devices = @cloud_searcher.get_property(vm.mob, Vim::VirtualMachine, 'config.hardware.device', ensure_all: true)
279
- env['networks'] = generate_network_env(devices, networks, dvs_index)
280
-
287
+ begin
288
+ env['networks'] = generate_network_env(devices, networks, dvs_index)
289
+ rescue NetworkException => e
290
+ e.vm_cid = vm_cid
291
+ raise e
292
+ end
281
293
  @logger.debug("Updating agent env to: #{env.pretty_inspect}")
282
294
  location = get_vm_location(vm.mob, datacenter: @datacenter.name)
283
295
  @agent_env.set_env(vm.mob, location, env)
@@ -334,7 +346,7 @@ module VSphereCloud
334
346
 
335
347
  vm.reload
336
348
  virtual_disk = vm.disk_by_cid(disk.cid)
337
- raise Bosh::Clouds::DiskNotAttached.new(true), "Disk (#{disk.cid}) is not attached to VM (#{vm.cid})" if virtual_disk.nil?
349
+ raise Bosh::Clouds::DiskNotAttached.new(true), "Disk '#{disk.cid}' is not attached to VM '#{vm.cid}'" if virtual_disk.nil?
338
350
 
339
351
  config = Vim::Vm::ConfigSpec.new
340
352
  config.device_change = []
@@ -353,7 +365,7 @@ module VSphereCloud
353
365
  break if virtual_disk.nil?
354
366
  sleep(1.0)
355
367
  end
356
- raise "Failed to detach disk: #{disk.cid} from vm: #{vm.cid}" unless virtual_disk.nil?
368
+ raise "Failed to detach disk '#{disk.cid}' from vm '#{vm.cid}'" unless virtual_disk.nil?
357
369
 
358
370
  @logger.info('Finished detaching disk')
359
371
  end
@@ -386,9 +398,9 @@ module VSphereCloud
386
398
  end
387
399
 
388
400
  def replicate_stemcell(cluster, datastore, stemcell)
389
- stemcell_vm = client.find_by_inventory_path([cluster.datacenter.name, 'vm',
390
- cluster.datacenter.template_folder.path_components, stemcell])
391
- raise "Could not find stemcell: #{stemcell}" if stemcell_vm.nil?
401
+ stemcell_vm_path_components = [cluster.datacenter.name, 'vm', cluster.datacenter.template_folder.path_components, stemcell]
402
+ stemcell_vm = client.find_by_inventory_path(stemcell_vm_path_components)
403
+ raise "Could not find VM for stemcell '#{stemcell}' at path '#{stemcell_vm_path_components.join("/")}'" if stemcell_vm.nil?
392
404
  stemcell_datastore = @cloud_searcher.get_property(stemcell_vm, Vim::VirtualMachine, 'datastore', ensure_all: true)
393
405
 
394
406
  if stemcell_datastore != datastore.mob
@@ -435,7 +447,9 @@ module VSphereCloud
435
447
  networks.each do |network_name, network|
436
448
  network_entry = network.dup
437
449
  v_network_name = network['cloud_properties']['name']
438
- nic = nics[v_network_name].pop
450
+ network = nics[v_network_name]
451
+ raise NetworkException, "Could not find network '#{v_network_name}'" if network.nil?
452
+ nic = network.pop
439
453
  network_entry['mac'] = nic.mac_address
440
454
  network_env[network_name] = network_entry
441
455
  end
@@ -481,7 +495,7 @@ module VSphereCloud
481
495
 
482
496
  unless datastore_name
483
497
  devices = vm_properties['config.hardware.device']
484
- datastore = get_primary_datastore(devices)
498
+ datastore = get_primary_datastore(devices, vm_name)
485
499
  datastore_name = @cloud_searcher.get_property(datastore, Vim::Datastore, 'name')
486
500
  end
487
501
  end
@@ -489,17 +503,16 @@ module VSphereCloud
489
503
  { datacenter: datacenter_name, datastore: datastore_name, vm: vm_name }
490
504
  end
491
505
 
492
- def get_primary_datastore(devices)
506
+ def get_primary_datastore(devices, vm_name = nil)
493
507
  ephemeral_disks = devices.select { |device| device.kind_of?(Vim::Vm::Device::VirtualDisk) &&
494
508
  device.backing.disk_mode != Vim::Vm::Device::VirtualDiskOption::DiskMode::INDEPENDENT_PERSISTENT }
495
509
 
496
- datastore = nil
497
- ephemeral_disks.each do |disk|
498
- if datastore
499
- raise 'Ephemeral disks should all be on the same datastore.' unless datastore.eql?(disk.backing.datastore)
500
- else
501
- datastore = disk.backing.datastore
502
- end
510
+ datastore = ephemeral_disks.first.backing.datastore
511
+ disk_in_wrong_datastore = ephemeral_disks.find { |disk| !datastore.eql?(disk.backing.datastore) }
512
+ if disk_in_wrong_datastore
513
+ error_msg = vm_name ? "for VM '#{vm_name}'" : ""
514
+ raise "Ephemeral disks #{error_msg} should all be on the same datastore. " +
515
+ "Expected datastore '#{datastore}' to match datastore '#{disk_in_wrong_datastore.backing.datastore}'"
503
516
  end
504
517
 
505
518
  datastore
@@ -524,7 +537,7 @@ module VSphereCloud
524
537
  end
525
538
 
526
539
  def create_nic_config_spec(v_network_name, network, controller_key, dvs_index)
527
- raise "Can't find network: #{v_network_name}" if network.nil?
540
+ raise "Invalid network '#{v_network_name}'" if network.nil?
528
541
  if network.class == Vim::Dvs::DistributedVirtualPortgroup
529
542
  portgroup_properties = @cloud_searcher.get_properties(network,
530
543
  Vim::Dvs::DistributedVirtualPortgroup,
@@ -50,7 +50,7 @@ module VSphereCloud
50
50
  end
51
51
  end
52
52
  unless remaining_properties.empty?
53
- raise MissingPropertiesException.new("The object[s] #{obj} " +
53
+ raise MissingPropertiesException.new("The object[s] '#{obj}' " +
54
54
  "should have the following properties: #{properties.pretty_inspect}, " +
55
55
  "but they were missing these: #{remaining_properties.pretty_inspect}.")
56
56
  end
@@ -93,8 +93,8 @@ module VSphereCloud
93
93
 
94
94
  def get_managed_object(type, options)
95
95
  result = get_managed_objects(type, options)
96
- raise "Could not find #{type}: #{options.pretty_inspect}" if result.length == 0
97
- raise "Found more than one #{type}: #{options.pretty_inspect}" if result.length > 1
96
+ raise "Could not find '#{type}': #{options.pretty_inspect}" if result.length == 0
97
+ raise "Found more than one '#{type}': #{options.pretty_inspect}" if result.length > 1
98
98
  result.first
99
99
  end
100
100
 
@@ -26,7 +26,9 @@ module VSphereCloud
26
26
 
27
27
  def find_and_move(disk_cid, cluster, datacenter, accessible_datastores)
28
28
  disk = find(disk_cid)
29
- return disk if accessible_datastores.include?(disk.datastore.name)
29
+ disk_in_persistent_datastore = @datacenter.persistent_datastores.include?(disk.datastore.name)
30
+ disk_in_accessible_datastore = accessible_datastores.include?(disk.datastore.name)
31
+ return disk if disk_in_persistent_datastore && disk_in_accessible_datastore
30
32
 
31
33
  destination_datastore = @resources.pick_persistent_datastore_in_cluster(cluster.name, disk.size_in_mb)
32
34
 
@@ -46,6 +48,15 @@ module VSphereCloud
46
48
  @logger.debug("Looking for disk #{disk_cid} in datastores: #{persistent_datastores}")
47
49
  persistent_datastores.each do |_, datastore|
48
50
  disk = @client.find_disk(disk_cid, datastore, @disk_path)
51
+ @logger.debug("disk #{disk_cid} found in: #{datastore}") unless disk.nil?
52
+ return disk unless disk.nil?
53
+ end
54
+
55
+ other_datastores = @datacenter.all_datastores.reject{|datastore_name, _| persistent_datastores[datastore_name] }
56
+ @logger.debug("disk #{disk_cid} not found in filtered persistent datastores, trying other datastores: #{other_datastores}")
57
+ other_datastores.each do |_, datastore|
58
+ disk = @client.find_disk(disk_cid, datastore, @disk_path)
59
+ @logger.debug("disk #{disk_cid} found in: #{datastore}") unless disk.nil?
49
60
  return disk unless disk.nil?
50
61
  end
51
62
 
@@ -19,7 +19,7 @@ module VSphereCloud
19
19
  elsif response.code == 404
20
20
  nil
21
21
  else
22
- raise "Could not fetch file: #{url}, status code: #{response.code}"
22
+ raise "Could not fetch file '#{url}', received status code '#{response.code}'"
23
23
  end
24
24
  end
25
25
  end
@@ -35,7 +35,7 @@ module VSphereCloud
35
35
  { 'Content-Type' => 'application/octet-stream', 'Content-Length' => contents.length })
36
36
 
37
37
  unless response.code < 400
38
- raise "Could not upload file: #{url}, status code: #{response.code}"
38
+ raise "Could not upload file '#{url}', received status code '#{response.code}'"
39
39
  end
40
40
  end
41
41
  end
@@ -1,5 +1,8 @@
1
1
  module VSphereCloud
2
2
  class FixedClusterPlacer
3
+ include ObjectStringifier
4
+ stringify_with :cluster
5
+
3
6
  attr_reader :drs_rules
4
7
 
5
8
  def initialize(cluster, drs_rules)
@@ -21,5 +24,9 @@ module VSphereCloud
21
24
  def pick_persistent_datastore(_, _)
22
25
  raise NotImplementedError
23
26
  end
27
+
28
+ private
29
+
30
+ attr_reader :cluster
24
31
  end
25
32
  end
@@ -0,0 +1,15 @@
1
+ module VSphereCloud
2
+ module ObjectStringifier
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def stringify_with(*attributes)
9
+ define_method(:to_s) do
10
+ "(#{self.class.name} (#{attributes.map{|attr| "#{attr}=\"#{self.send(attr)}\""}.join(', ')}))"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,6 +2,8 @@ require 'cloud/vsphere/resources/datacenter'
2
2
 
3
3
  module VSphereCloud
4
4
  class Resources
5
+ include ObjectStringifier
6
+ stringify_with :datacenter
5
7
  MEMORY_HEADROOM = 128
6
8
  DISK_HEADROOM = 1024
7
9
  STALE_TIMEOUT = 60
@@ -28,7 +30,7 @@ module VSphereCloud
28
30
  @lock.synchronize do
29
31
  cluster = @datacenter.clusters[cluster_name]
30
32
  if cluster.nil?
31
- raise Bosh::Clouds::CloudError, "Couldn't find cluster '#{cluster_name}'. Found #{@datacenter.clusters.values.map(&:name)}"
33
+ raise Bosh::Clouds::CloudError, "Couldn't find cluster '#{cluster_name}'. Found: #{@datacenter.clusters.values.map(&:name)}"
32
34
  end
33
35
 
34
36
  datastore = cluster.pick_persistent(disk_size_in_mb)
@@ -122,7 +124,7 @@ module VSphereCloud
122
124
 
123
125
  private
124
126
 
125
- attr_reader :config
127
+ attr_reader :config, :datacenter
126
128
 
127
129
 
128
130
  class PersistentDiskIndex
@@ -4,6 +4,8 @@ module VSphereCloud
4
4
  class Resources
5
5
  class Cluster
6
6
  include VimSdk
7
+ include ObjectStringifier
8
+ stringify_with :name
7
9
 
8
10
  PROPERTIES = %w(name datastore resourcePool host)
9
11
  HOST_PROPERTIES = %w(hardware.memorySize runtime.inMaintenanceMode)
@@ -114,14 +116,22 @@ module VSphereCloud
114
116
  @persistent_datastores ||= select_datastores(@datacenter_persistent_datastore_pattern)
115
117
  end
116
118
 
119
+ def all_datastores
120
+ @all_datastores ||= Datastore.build_from_client(
121
+ @client,
122
+ properties['datastore']
123
+ ).inject({}) do |acc, datastore|
124
+ acc[datastore.name] = datastore
125
+ acc
126
+ end
127
+ end
128
+
117
129
  private
118
130
 
119
131
  attr_reader :config, :client, :properties, :logger
120
132
 
121
133
  def select_datastores(pattern)
122
- @datastores ||= Datastore.build_from_client(@client, properties['datastore'])
123
- matching_datastores = @datastores.select { |datastore| datastore.name =~ pattern }
124
- matching_datastores.inject({}) { |h, datastore| h[datastore.name] = datastore; h }
134
+ all_datastores.select { |name, datastore| name =~ pattern }
125
135
  end
126
136
 
127
137
  def pick_store(type, size)
@@ -204,7 +214,7 @@ module VSphereCloud
204
214
  # @return [void]
205
215
  def fetch_resource_pool_utilization
206
216
  properties = @client.cloud_searcher.get_properties(resource_pool.mob, Vim::ResourcePool, 'summary')
207
- raise "Failed to get utilization for resource pool #{resource_pool}" if properties.nil?
217
+ raise "Failed to get utilization for resource pool '#{resource_pool}'" if properties.nil?
208
218
 
209
219
  runtime_info = properties["summary"].runtime
210
220
 
@@ -9,13 +9,13 @@ module VSphereCloud
9
9
 
10
10
  def find(name, config)
11
11
  cluster_mob = cluster_mobs[name]
12
- raise "Can't find cluster: #{name}" if cluster_mob.nil?
12
+ raise "Can't find cluster '#{name}'" if cluster_mob.nil?
13
13
 
14
14
  cluster_properties = @client.cloud_searcher.get_properties(
15
15
  cluster_mob, VimSdk::Vim::ClusterComputeResource,
16
16
  Cluster::PROPERTIES, :ensure_all => true
17
17
  )
18
- raise "Can't find properties for cluster: #{name}" if cluster_properties.nil?
18
+ raise "Can't find properties for cluster '#{name}'" if cluster_properties.nil?
19
19
 
20
20
  Cluster.new(
21
21
  @datacenter,
@@ -4,6 +4,8 @@ module VSphereCloud
4
4
  class Resources
5
5
  class Datacenter
6
6
  include VimSdk
7
+ include ObjectStringifier
8
+ stringify_with :name
7
9
 
8
10
  attr_accessor :config
9
11
 
@@ -27,7 +29,7 @@ module VSphereCloud
27
29
 
28
30
  def mob
29
31
  mob = @client.find_by_inventory_path(name)
30
- raise "Datacenter: #{name} not found" if mob.nil?
32
+ raise "Datacenter '#{name}' not found" if mob.nil?
31
33
  mob
32
34
  end
33
35
 
@@ -70,17 +72,22 @@ module VSphereCloud
70
72
  @clusters.each do |cluster_name, cluster_config|
71
73
  clusters[cluster_name] = @cluster_provider.find(cluster_name, cluster_config)
72
74
  end
75
+ @logger.debug("All clusters provided: #{@clusters}")
73
76
  clusters
74
77
  end
75
78
 
76
79
  def persistent_datastores
77
- datastores = {}
78
- clusters.each do |_, cluster|
79
- cluster.persistent_datastores.each do |_, datastore|
80
- datastores[datastore.name] = datastore
81
- end
80
+ clusters.values.inject({}) do |acc, cluster|
81
+ acc.merge!(cluster.persistent_datastores)
82
+ acc
83
+ end
84
+ end
85
+
86
+ def all_datastores
87
+ clusters.values.inject({}) do |acc, cluster|
88
+ acc.merge!(cluster.all_datastores)
89
+ acc
82
90
  end
83
- datastores
84
91
  end
85
92
 
86
93
  def pick_persistent_datastore(size)
@@ -95,14 +102,14 @@ module VSphereCloud
95
102
  datastores = persistent_datastores.values
96
103
  available_datastores = datastores.reject { |datastore| datastore.free_space - size < DISK_HEADROOM }
97
104
 
98
- @logger.debug("Looking for a #{type} datastore with #{size}MB free space.")
105
+ @logger.debug("Looking for a '#{type}' datastore with #{size}MB free space.")
99
106
  @logger.debug("All datastores: #{datastores.map(&:debug_info)}")
100
107
  @logger.debug("Datastores with enough space: #{available_datastores.map(&:debug_info)}")
101
108
 
102
109
  selected_datastore = Util.weighted_random(available_datastores.map { |datastore| [datastore, datastore.free_space] })
103
110
 
104
111
  if selected_datastore.nil?
105
- raise Bosh::Clouds::NoDiskSpace.new(true), "Couldn't find a #{type} datastore with #{size}MB of free space. Found:\n #{datastores.map(&:debug_info).join("\n ")}\n"
112
+ raise Bosh::Clouds::NoDiskSpace.new(true), "Couldn't find a '#{type}' datastore with #{size}MB of free space. Found:\n #{datastores.map(&:debug_info).join("\n ")}\n"
106
113
  end
107
114
  selected_datastore
108
115
  end
@@ -4,6 +4,8 @@ module VSphereCloud
4
4
  class Resources
5
5
  class Datastore
6
6
  include VimSdk
7
+ include ObjectStringifier
8
+ stringify_with :name, :mob
7
9
  PROPERTIES = %w(summary.freeSpace summary.capacity name)
8
10
 
9
11
  def self.build_from_client(client, datastore_properties)
@@ -2,6 +2,7 @@ require 'cloud/vsphere/resources/disk/disk_config'
2
2
 
3
3
  module VSphereCloud
4
4
  class EphemeralDisk
5
+ DISK_NAME = 'ephemeral_disk'
5
6
  def initialize(size_in_mb, folder_name, datastore)
6
7
  @folder_name = folder_name
7
8
  @datastore = datastore
@@ -15,7 +16,7 @@ module VSphereCloud
15
16
  private
16
17
 
17
18
  def filename
18
- "[#{@datastore.name}] #{@folder_name}/ephemeral_disk.vmdk"
19
+ "[#{@datastore.name}] #{@folder_name}/#{DISK_NAME}.vmdk"
19
20
  end
20
21
  end
21
22
  end
@@ -18,7 +18,7 @@ module VSphereCloud
18
18
  def find_or_create_folder(path_components)
19
19
  if path_components.empty?
20
20
  folder = root_vm_folder
21
- raise "Root VM Folder not found: #{@datacenter_name}/vm" if folder.nil?
21
+ raise "Root VM Folder not found '#{@datacenter_name}/vm'" if folder.nil?
22
22
  return folder
23
23
  end
24
24
 
@@ -3,6 +3,8 @@ module VSphereCloud
3
3
  class VM
4
4
  include VimSdk
5
5
  include RetryBlock
6
+ include ObjectStringifier
7
+ stringify_with :cid
6
8
 
7
9
  attr_reader :mob, :cid
8
10
 
@@ -64,6 +66,12 @@ module VSphereCloud
64
66
  end
65
67
  end
66
68
 
69
+ def ephemeral_disk
70
+ devices.find do |device|
71
+ device.kind_of?(Vim::Vm::Device::VirtualDisk) && device.backing.file_name =~ /#{VSphereCloud::EphemeralDisk::DISK_NAME}.vmdk$/
72
+ end
73
+ end
74
+
67
75
  def pci_controller
68
76
  devices.find { |device| device.kind_of?(Vim::Vm::Device::VirtualPCIController) }
69
77
  end
@@ -157,12 +165,12 @@ module VSphereCloud
157
165
  end
158
166
  end
159
167
 
160
- private
161
-
162
168
  def power_state
163
169
  properties['runtime.powerState']
164
170
  end
165
171
 
172
+ private
173
+
166
174
  def properties
167
175
  @properties ||= cloud_searcher.get_properties(
168
176
  @mob,
@@ -19,7 +19,7 @@ module VSphereCloud
19
19
 
20
20
  def create(agent_id, stemcell_cid, networks, persistent_disk_cids, environment)
21
21
  stemcell_vm = @cpi.stemcell_vm(stemcell_cid)
22
- raise "Could not find stemcell: #{stemcell_cid}" if stemcell_vm.nil?
22
+ raise "Could not find VM for stemcell '#{stemcell_cid}'" if stemcell_vm.nil?
23
23
 
24
24
  stemcell_size =
25
25
  @cloud_searcher.get_property(stemcell_vm, VimSdk::Vim::VirtualMachine, 'summary.storage.committed', ensure_all: true)
@@ -94,13 +94,18 @@ module VSphereCloud
94
94
 
95
95
  @agent_env.set_env(created_vm.mob, location, env)
96
96
 
97
- @logger.info("Powering on VM: #{created_vm} (#{created_vm.cid})")
97
+ @logger.info("Powering on VM: #{created_vm}")
98
98
  created_vm.power_on
99
99
 
100
100
  create_drs_rules(created_vm.mob, cluster)
101
101
  rescue => e
102
+ e.vm_cid = vm_cid if e.instance_of?(Cloud::NetworkException)
102
103
  @logger.info("#{e} - #{e.backtrace.join("\n")}")
103
- created_vm.delete if created_vm
104
+ begin
105
+ created_vm.delete if created_vm
106
+ rescue => ex
107
+ @logger.info("Failed to delete vm '#{vm_cid}' with message: #{ex.inspect}")
108
+ end
104
109
  raise e
105
110
  end
106
111
 
@@ -118,7 +123,7 @@ module VSphereCloud
118
123
  rule_config = @placer.drs_rules.first
119
124
 
120
125
  if rule_config['type'] != 'separate_vms'
121
- raise "vSphere CPI only supports DRS rule of 'separate_vms' type"
126
+ raise "vSphere CPI only supports DRS rule of 'separate_vms' type, not '#{rule_config['type']}'"
122
127
  end
123
128
 
124
129
  drs_rule = VSphereCloud::DrsRule.new(
@@ -8,7 +8,7 @@ module VSphereCloud
8
8
 
9
9
  def find(vm_cid)
10
10
  vm_mob = @client.find_by_inventory_path(@datacenter.vm_path(vm_cid))
11
- raise Bosh::Clouds::VMNotFound, "VM `#{vm_cid}' not found" if vm_mob.nil?
11
+ raise Bosh::Clouds::VMNotFound, "VM '#{vm_cid}' not found at path '#{@datacenter.vm_path(vm_cid)}'" if vm_mob.nil?
12
12
 
13
13
  Resources::VM.new(vm_cid, vm_mob, @client, @logger)
14
14
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh_vsphere_cpi
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.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-09-02 00:00:00.000000000 Z
11
+ date: 2015-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bosh_common
@@ -133,6 +133,7 @@ files:
133
133
  - lib/cloud/vsphere/fixed_cluster_placer.rb
134
134
  - lib/cloud/vsphere/lease_obtainer.rb
135
135
  - lib/cloud/vsphere/lease_updater.rb
136
+ - lib/cloud/vsphere/object_stringifier.rb
136
137
  - lib/cloud/vsphere/path_finder.rb
137
138
  - lib/cloud/vsphere/resources.rb
138
139
  - lib/cloud/vsphere/resources/cluster.rb