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 +4 -4
- data/lib/cloud/vsphere.rb +1 -0
- data/lib/cloud/vsphere/agent_env.rb +2 -2
- data/lib/cloud/vsphere/client.rb +2 -12
- data/lib/cloud/vsphere/cloud.rb +33 -20
- data/lib/cloud/vsphere/cloud_searcher.rb +3 -3
- data/lib/cloud/vsphere/disk_provider.rb +12 -1
- data/lib/cloud/vsphere/file_provider.rb +2 -2
- data/lib/cloud/vsphere/fixed_cluster_placer.rb +7 -0
- data/lib/cloud/vsphere/object_stringifier.rb +15 -0
- data/lib/cloud/vsphere/resources.rb +4 -2
- data/lib/cloud/vsphere/resources/cluster.rb +14 -4
- data/lib/cloud/vsphere/resources/cluster_provider.rb +2 -2
- data/lib/cloud/vsphere/resources/datacenter.rb +16 -9
- data/lib/cloud/vsphere/resources/datastore.rb +2 -0
- data/lib/cloud/vsphere/resources/disk/ephemeral_disk.rb +2 -1
- data/lib/cloud/vsphere/resources/folder.rb +1 -1
- data/lib/cloud/vsphere/resources/vm.rb +10 -2
- data/lib/cloud/vsphere/vm_creator.rb +9 -4
- data/lib/cloud/vsphere/vm_provider.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60b9ea302efbf07e91dd0adc105f975ec8dcacd8
|
4
|
+
data.tar.gz: 1c8ef64cfb700603dd0a14f8c3e4179461225e2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c86a93bead968a65f17b37c63b03110ec6a41d4ec8a6507796243a6d4a2da4e4327c41fb314e6deeeb4ee513d3c3321133fb45cd0cf7cbda8e4fba2132aa654
|
7
|
+
data.tar.gz: 07864ca78d8e30f593e91f031d24248eedacdb93472d20654e3409f79fd2aa746d844dd75f54b7f018eb797c0108b9906faae4f58f17d4b20a92d2efc5d5fc0a
|
data/lib/cloud/vsphere.rb
CHANGED
@@ -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(
|
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(
|
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
|
data/lib/cloud/vsphere/client.rb
CHANGED
@@ -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
|
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
|
data/lib/cloud/vsphere/cloud.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
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
|
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
|
-
|
390
|
-
|
391
|
-
raise "Could not find stemcell
|
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
|
-
|
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 =
|
497
|
-
ephemeral_disks.
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
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 "
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
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
|
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
|
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
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
@@ -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}
|
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
|
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
|
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}
|
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
|
-
|
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
|
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.
|
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-
|
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
|