bosh_vsphere_cpi 2.1.1 → 2.2.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/client.rb +82 -3
- data/lib/cloud/vsphere/cloud.rb +20 -21
- data/lib/cloud/vsphere/disk_provider.rb +25 -3
- data/lib/cloud/vsphere/ip_conflict_detector.rb +41 -0
- data/lib/cloud/vsphere/resources/cluster.rb +1 -1
- data/lib/cloud/vsphere/resources/datacenter.rb +10 -6
- data/lib/cloud/vsphere/vm_creator.rb +5 -0
- data/lib/cloud/vsphere/vm_provider.rb +2 -2
- data/lib/cloud/vsphere.rb +1 -0
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20484247b0bb76cefc40f2f28054428a6680991b
|
4
|
+
data.tar.gz: 1d48fb046acb02cf0417b6b803c28e6883291b0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ca9d5f7600ad20b84ce67c8ddeab6381c7d77ffa2baaff0323f492bfb267e57570385249b91f0c49970ddbb75b98c453b6422e02e5abd5c443f0e7f42d91627
|
7
|
+
data.tar.gz: 17673951c1c87149dc4e32ba21627f1d139a96af603d81cdd4deace7791dbcdf7a4cf341f9ec7ba0f5b825bb300e33ce3bd147beb60b2bc2cd387da756938bb1
|
data/lib/cloud/vsphere/client.rb
CHANGED
@@ -13,7 +13,7 @@ module VSphereCloud
|
|
13
13
|
def initialize(host, options={})
|
14
14
|
@soap_stub = SoapStub.new(host, options[:soap_log]).create
|
15
15
|
|
16
|
-
@service_instance =Vim::ServiceInstance.new('ServiceInstance', @soap_stub)
|
16
|
+
@service_instance = Vim::ServiceInstance.new('ServiceInstance', @soap_stub)
|
17
17
|
@service_content = @service_instance.content
|
18
18
|
|
19
19
|
@metrics_cache = {}
|
@@ -130,6 +130,31 @@ module VSphereCloud
|
|
130
130
|
@service_content.search_index.find_by_inventory_path(full_path)
|
131
131
|
end
|
132
132
|
|
133
|
+
def find_vm_by_ip(ip)
|
134
|
+
@service_content.search_index.find_by_ip(nil, ip, true)
|
135
|
+
end
|
136
|
+
|
137
|
+
def find_vm_by_name(datacenter, vm_name)
|
138
|
+
yield_all_resources_by_name(datacenter, 'VirtualMachine') do |vm_mob, name|
|
139
|
+
if name == vm_name
|
140
|
+
return vm_mob
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
|
147
|
+
def find_all_stemcell_replicas(datacenter, stemcell_id)
|
148
|
+
matches = []
|
149
|
+
yield_all_resources_by_name(datacenter, 'VirtualMachine') do |vm_mob, name|
|
150
|
+
if name =~ Regexp.new(stemcell_id)
|
151
|
+
matches << vm_mob
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
matches
|
156
|
+
end
|
157
|
+
|
133
158
|
def wait_for_task(task)
|
134
159
|
interval = 1.0
|
135
160
|
started = Time.now
|
@@ -208,13 +233,17 @@ module VSphereCloud
|
|
208
233
|
disk_size_in_mb.nil? ? nil : Resources::Disk.new(disk_cid, disk_size_in_mb, datastore, disk_path)
|
209
234
|
end
|
210
235
|
|
211
|
-
def create_disk(datacenter, datastore, disk_cid, disk_folder, disk_size_in_mb)
|
236
|
+
def create_disk(datacenter, datastore, disk_cid, disk_folder, disk_size_in_mb, disk_type)
|
237
|
+
if disk_type.nil?
|
238
|
+
raise 'no disk type specified'
|
239
|
+
end
|
240
|
+
|
212
241
|
disk_path = "[#{datastore.name}] #{disk_folder}/#{disk_cid}.vmdk"
|
213
242
|
|
214
243
|
create_parent_folder(datacenter, disk_path)
|
215
244
|
|
216
245
|
disk_spec = VimSdk::Vim::VirtualDiskManager::FileBackedVirtualDiskSpec.new
|
217
|
-
disk_spec.disk_type =
|
246
|
+
disk_spec.disk_type = disk_type
|
218
247
|
disk_spec.capacity_kb = disk_size_in_mb * 1024
|
219
248
|
disk_spec.adapter_type = 'lsiLogic'
|
220
249
|
|
@@ -296,5 +325,55 @@ module VSphereCloud
|
|
296
325
|
metrics.each { |metric| result[metric_names[metric.counter_id]] = metric }
|
297
326
|
result
|
298
327
|
end
|
328
|
+
|
329
|
+
def create_filter_spec(datacenter, resource_type, property_names)
|
330
|
+
# Create a view to list all the resources in the root folder
|
331
|
+
container_view = @service_content.view_manager.create_container_view(datacenter.mob, [resource_type], true)
|
332
|
+
|
333
|
+
# Create an object spec to define the beginning of the traversal
|
334
|
+
object_spec = VimSdk::Vmodl::Query::PropertyCollector::ObjectSpec.new
|
335
|
+
object_spec.obj = container_view
|
336
|
+
object_spec.skip = false
|
337
|
+
|
338
|
+
# Create a traversal spec to select all objects in the 'view' of the ContainerView
|
339
|
+
vm_traversal_spec = VimSdk::Vmodl::Query::PropertyCollector::TraversalSpec.new
|
340
|
+
vm_traversal_spec.name = 'searchTraversalSpec'
|
341
|
+
vm_traversal_spec.path = 'view'
|
342
|
+
vm_traversal_spec.type = 'ContainerView'
|
343
|
+
object_spec.select_set << vm_traversal_spec
|
344
|
+
|
345
|
+
# Specify the properties for retrieval
|
346
|
+
property_spec = VimSdk::Vmodl::Query::PropertyCollector::PropertySpec.new
|
347
|
+
property_spec.type = resource_type
|
348
|
+
property_spec.path_set.concat(property_names)
|
349
|
+
property_spec.all = false
|
350
|
+
|
351
|
+
filter_spec = VimSdk::Vmodl::Query::PropertyCollector::FilterSpec.new
|
352
|
+
filter_spec.object_set << object_spec
|
353
|
+
filter_spec.prop_set << property_spec
|
354
|
+
filter_spec
|
355
|
+
end
|
356
|
+
|
357
|
+
def yield_all_resources_by_name(datacenter, type)
|
358
|
+
raise 'Requires a vSphere object type' if type.nil?
|
359
|
+
# Collect all the 'name' attributes of all VMs in the datacenter
|
360
|
+
vm_filter_spec = create_filter_spec(datacenter, type, ['name'])
|
361
|
+
ro = VimSdk::Vmodl::Query::PropertyCollector::RetrieveOptions.new
|
362
|
+
result = @service_content.property_collector.retrieve_properties_ex([vm_filter_spec], ro)
|
363
|
+
|
364
|
+
# Retrieve Properties Ex returns paginated results, so we continue retrieving
|
365
|
+
# more pages if the token indicates there are more pages.
|
366
|
+
token = "not nil"
|
367
|
+
until token.nil?
|
368
|
+
result.objects.each do |object_content|
|
369
|
+
# Yield the object MOB and its name
|
370
|
+
yield object_content.obj, object_content.prop_set.first.val
|
371
|
+
end
|
372
|
+
token = result.token
|
373
|
+
unless token.nil?
|
374
|
+
result = @service_content.property_collector.continue_retrieve_properties_ex(token)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
299
378
|
end
|
300
379
|
end
|
data/lib/cloud/vsphere/cloud.rb
CHANGED
@@ -133,25 +133,24 @@ module VSphereCloud
|
|
133
133
|
with_thread_name("delete_stemcell(#{stemcell})") do
|
134
134
|
Bosh::ThreadPool.new(max_threads: 32, logger: @logger).wrap do |pool|
|
135
135
|
@logger.info("Looking for stemcell replicas in: #{@datacenter.name}")
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
@logger.info("Deleted: #{template_name}")
|
146
|
-
end
|
136
|
+
matches = client.find_all_stemcell_replicas(@datacenter, stemcell)
|
137
|
+
|
138
|
+
matches.each do |sc|
|
139
|
+
sc_name = sc.name
|
140
|
+
@logger.info("Found: #{sc_name}")
|
141
|
+
pool.process do
|
142
|
+
@logger.info("Deleting: #{sc_name}")
|
143
|
+
client.delete_vm(sc)
|
144
|
+
@logger.info("Deleted: #{sc_name}")
|
147
145
|
end
|
148
146
|
end
|
147
|
+
|
149
148
|
end
|
150
149
|
end
|
151
150
|
end
|
152
151
|
|
153
152
|
def stemcell_vm(name)
|
154
|
-
client.
|
153
|
+
client.find_vm_by_name(@datacenter, name)
|
155
154
|
end
|
156
155
|
|
157
156
|
def create_vm(agent_id, stemcell, cloud_properties, networks, disk_locality = nil, environment = nil)
|
@@ -381,7 +380,8 @@ module VSphereCloud
|
|
381
380
|
cluster = @datacenter.clusters[vm.cluster]
|
382
381
|
end
|
383
382
|
|
384
|
-
|
383
|
+
disk_type = cloud_properties['type']
|
384
|
+
disk = disk_provider.create(size_in_mb, disk_type, cluster)
|
385
385
|
@logger.info("Created disk: #{disk.inspect}")
|
386
386
|
disk.cid
|
387
387
|
end
|
@@ -398,21 +398,18 @@ module VSphereCloud
|
|
398
398
|
end
|
399
399
|
|
400
400
|
def replicate_stemcell(cluster, datastore, stemcell)
|
401
|
-
|
402
|
-
|
403
|
-
raise "Could not find VM for stemcell '#{stemcell}' at path '#{stemcell_vm_path_components.join("/")}'" if stemcell_vm.nil?
|
401
|
+
stemcell_vm = client.find_vm_by_name(@datacenter, stemcell)
|
402
|
+
raise "Could not find VM for stemcell '#{stemcell}'" if stemcell_vm.nil?
|
404
403
|
stemcell_datastore = @cloud_searcher.get_property(stemcell_vm, Vim::VirtualMachine, 'datastore', ensure_all: true)
|
405
404
|
|
406
405
|
if stemcell_datastore != datastore.mob
|
407
406
|
@logger.info("Stemcell lives on a different datastore, looking for a local copy of: #{stemcell}.")
|
408
407
|
local_stemcell_name = "#{stemcell} %2f #{datastore.mob.__mo_id__}"
|
409
|
-
local_stemcell_path =
|
410
|
-
[cluster.datacenter.name, 'vm', cluster.datacenter.template_folder.path_components, local_stemcell_name]
|
411
|
-
replicated_stemcell_vm = client.find_by_inventory_path(local_stemcell_path)
|
412
408
|
|
409
|
+
replicated_stemcell_vm = client.find_vm_by_name(@datacenter, local_stemcell_name)
|
413
410
|
if replicated_stemcell_vm.nil?
|
414
411
|
@logger.info("Cluster doesn't have stemcell #{stemcell}, replicating")
|
415
|
-
|
412
|
+
replicated_stemcell_vm = replicate_stemcell_helper(stemcell, stemcell_vm, local_stemcell_name, cluster, datastore, replicated_stemcell_vm)
|
416
413
|
else
|
417
414
|
@logger.info("Found local stemcell replica: #{replicated_stemcell_vm}")
|
418
415
|
end
|
@@ -704,7 +701,7 @@ module VSphereCloud
|
|
704
701
|
placer.nil? ? @resources : placer
|
705
702
|
end
|
706
703
|
|
707
|
-
def replicate_stemcell_helper(stemcell, stemcell_vm, local_stemcell_name, cluster, datastore, replicated_stemcell_vm
|
704
|
+
def replicate_stemcell_helper(stemcell, stemcell_vm, local_stemcell_name, cluster, datastore, replicated_stemcell_vm)
|
708
705
|
@logger.info("Replicating #{stemcell} (#{stemcell_vm}) to #{local_stemcell_name}")
|
709
706
|
task = clone_vm(stemcell_vm,
|
710
707
|
local_stemcell_name,
|
@@ -716,6 +713,8 @@ module VSphereCloud
|
|
716
713
|
@logger.info("Replicated #{stemcell} (#{stemcell_vm}) to #{local_stemcell_name} (#{replicated_stemcell_vm})")
|
717
714
|
rescue VSphereCloud::Client::DuplicateName => ex
|
718
715
|
@logger.info("Stemcell is being replicated by another thread, waiting for #{local_stemcell_name} to be ready")
|
716
|
+
local_stemcell_path =
|
717
|
+
[cluster.datacenter.name, 'vm', cluster.datacenter.template_folder.path_components, local_stemcell_name]
|
719
718
|
replicated_stemcell_vm = client.find_by_inventory_path(local_stemcell_path)
|
720
719
|
# get_properties will ensure the existence of the snapshot by retrying.
|
721
720
|
# This forces us to wait for a valid snapshot before returning with the
|
@@ -3,6 +3,16 @@ require 'cloud/vsphere/resources/disk'
|
|
3
3
|
|
4
4
|
module VSphereCloud
|
5
5
|
class DiskProvider
|
6
|
+
# https://pubs.vmware.com/vsphere-55/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvim.VirtualDiskManager.VirtualDiskType.html
|
7
|
+
SUPPORTED_DISK_TYPES = %w{
|
8
|
+
eagerZeroedThick
|
9
|
+
preallocated
|
10
|
+
thick
|
11
|
+
thin
|
12
|
+
}
|
13
|
+
|
14
|
+
DEFAULT_DISK_TYPE = 'preallocated'
|
15
|
+
|
6
16
|
def initialize(virtual_disk_manager, datacenter, resources, disk_path, client, logger)
|
7
17
|
@virtual_disk_manager = virtual_disk_manager
|
8
18
|
@datacenter = datacenter
|
@@ -12,7 +22,16 @@ module VSphereCloud
|
|
12
22
|
@logger = logger
|
13
23
|
end
|
14
24
|
|
15
|
-
def create(disk_size_in_mb, cluster)
|
25
|
+
def create(disk_size_in_mb, disk_type, cluster)
|
26
|
+
type = disk_type
|
27
|
+
if type.nil?
|
28
|
+
type = DEFAULT_DISK_TYPE
|
29
|
+
end
|
30
|
+
|
31
|
+
unless SUPPORTED_DISK_TYPES.include?(type)
|
32
|
+
raise "Disk type: '#{disk_type}' is not supported"
|
33
|
+
end
|
34
|
+
|
16
35
|
if cluster
|
17
36
|
datastore = @resources.pick_persistent_datastore_in_cluster(cluster.name, disk_size_in_mb)
|
18
37
|
else
|
@@ -21,14 +40,17 @@ module VSphereCloud
|
|
21
40
|
disk_cid = "disk-#{SecureRandom.uuid}"
|
22
41
|
@logger.debug("Creating disk '#{disk_cid}' in datastore '#{datastore.name}'")
|
23
42
|
|
24
|
-
@client.create_disk(@datacenter, datastore, disk_cid, @disk_path, disk_size_in_mb)
|
43
|
+
@client.create_disk(@datacenter, datastore, disk_cid, @disk_path, disk_size_in_mb, type)
|
25
44
|
end
|
26
45
|
|
27
46
|
def find_and_move(disk_cid, cluster, datacenter, accessible_datastores)
|
28
47
|
disk = find(disk_cid)
|
29
48
|
disk_in_persistent_datastore = @datacenter.persistent_datastores.include?(disk.datastore.name)
|
30
49
|
disk_in_accessible_datastore = accessible_datastores.include?(disk.datastore.name)
|
31
|
-
|
50
|
+
if disk_in_persistent_datastore && disk_in_accessible_datastore
|
51
|
+
@logger.info("Disk #{disk_cid} found in an accessible, persistent datastore '#{disk.datastore.name}'")
|
52
|
+
return disk
|
53
|
+
end
|
32
54
|
|
33
55
|
destination_datastore = @resources.pick_persistent_datastore_in_cluster(cluster.name, disk.size_in_mb)
|
34
56
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module VSphereCloud
|
2
|
+
class IPConflictDetector
|
3
|
+
|
4
|
+
def initialize(logger, client, networks)
|
5
|
+
@logger = logger
|
6
|
+
@client = client
|
7
|
+
@networks = networks
|
8
|
+
@desired_ip_mapping = []
|
9
|
+
|
10
|
+
@networks.map do |_, network_spec|
|
11
|
+
ip = network_spec['ip']
|
12
|
+
network_name = network_spec.fetch('cloud_properties', [])['name']
|
13
|
+
|
14
|
+
if ip && network_name
|
15
|
+
@desired_ip_mapping << {ip: ip, name: network_name}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def conflicts
|
21
|
+
conflicts = []
|
22
|
+
@desired_ip_mapping.each do |mapping|
|
23
|
+
@logger.info("Checking if ip '#{mapping[:ip]}' is in use")
|
24
|
+
vm = @client.find_vm_by_ip(mapping[:ip])
|
25
|
+
if vm.nil?
|
26
|
+
next
|
27
|
+
end
|
28
|
+
|
29
|
+
vm.guest.net.each do |nic|
|
30
|
+
if nic.ip_address.include?(mapping[:ip]) && nic.network == mapping[:name]
|
31
|
+
@logger.info("found conflicting vm: #{vm.name}, on network: #{mapping[:name]} with ip: #{mapping[:ip]}")
|
32
|
+
conflicts << {vm_name: vm.name, network_name: mapping[:name], ip: mapping[:ip]}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
conflicts
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -139,7 +139,7 @@ module VSphereCloud
|
|
139
139
|
available_datastores = datastores.reject { |datastore| datastore.free_space - size < DISK_HEADROOM }
|
140
140
|
|
141
141
|
@logger.debug("Looking for a #{type} datastore in #{self.name} with #{size}MB free space.")
|
142
|
-
@logger.debug("All datastores: #{datastores.map(&:debug_info)}")
|
142
|
+
@logger.debug("All datastores within cluster #{self.name}: #{datastores.map(&:debug_info)}")
|
143
143
|
@logger.debug("Datastores with enough space: #{available_datastores.map(&:debug_info)}")
|
144
144
|
|
145
145
|
selected_datastore = Util.weighted_random(available_datastores.map { |datastore| [datastore, datastore.free_space] })
|
@@ -68,12 +68,16 @@ module VSphereCloud
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def clusters
|
71
|
-
clusters = {}
|
72
|
-
@clusters.each do |cluster_name, cluster_config|
|
73
|
-
clusters[cluster_name] = @cluster_provider.find(cluster_name, cluster_config)
|
74
|
-
end
|
75
71
|
@logger.debug("All clusters provided: #{@clusters}")
|
76
|
-
clusters
|
72
|
+
@clusters.keys.inject({}) do |acc, cluster_name|
|
73
|
+
acc[cluster_name] = find_cluster(cluster_name)
|
74
|
+
acc
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def find_cluster(cluster_name)
|
79
|
+
cluster_config = @clusters[cluster_name]
|
80
|
+
@cluster_provider.find(cluster_name, cluster_config)
|
77
81
|
end
|
78
82
|
|
79
83
|
def persistent_datastores
|
@@ -103,7 +107,7 @@ module VSphereCloud
|
|
103
107
|
available_datastores = datastores.reject { |datastore| datastore.free_space - size < DISK_HEADROOM }
|
104
108
|
|
105
109
|
@logger.debug("Looking for a '#{type}' datastore with #{size}MB free space.")
|
106
|
-
@logger.debug("All datastores: #{datastores.map(&:debug_info)}")
|
110
|
+
@logger.debug("All datastores within datacenter #{self.name}: #{datastores.map(&:debug_info)}")
|
107
111
|
@logger.debug("Datastores with enough space: #{available_datastores.map(&:debug_info)}")
|
108
112
|
|
109
113
|
selected_datastore = Util.weighted_random(available_datastores.map { |datastore| [datastore, datastore.free_space] })
|
@@ -18,6 +18,11 @@ module VSphereCloud
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def create(agent_id, stemcell_cid, networks, persistent_disk_cids, environment)
|
21
|
+
ip_conflicts = IPConflictDetector.new(@logger, @client, networks).conflicts
|
22
|
+
unless ip_conflicts.empty?
|
23
|
+
raise "Cannot create new VM because of IP conflicts with other VMs on the same networks: #{ip_conflicts}"
|
24
|
+
end
|
25
|
+
|
21
26
|
stemcell_vm = @cpi.stemcell_vm(stemcell_cid)
|
22
27
|
raise "Could not find VM for stemcell '#{stemcell_cid}'" if stemcell_vm.nil?
|
23
28
|
|
@@ -7,8 +7,8 @@ module VSphereCloud
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def find(vm_cid)
|
10
|
-
vm_mob = @client.
|
11
|
-
raise Bosh::Clouds::VMNotFound, "VM '#{vm_cid}' not found
|
10
|
+
vm_mob = @client.find_vm_by_name(@datacenter, vm_cid)
|
11
|
+
raise Bosh::Clouds::VMNotFound, "VM '#{vm_cid}' not found in datacenter '#{@datacenter.name}'" if vm_mob.nil?
|
12
12
|
|
13
13
|
Resources::VM.new(vm_cid, vm_mob, @client, @logger)
|
14
14
|
end
|
data/lib/cloud/vsphere.rb
CHANGED
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.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- VMware
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bosh_common
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - '='
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 2.
|
89
|
+
version: 2.4.0
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - '='
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 2.
|
96
|
+
version: 2.4.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: mono_logger
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- lib/cloud/vsphere/drs_rules/vm_attribute_manager.rb
|
132
132
|
- lib/cloud/vsphere/file_provider.rb
|
133
133
|
- lib/cloud/vsphere/fixed_cluster_placer.rb
|
134
|
+
- lib/cloud/vsphere/ip_conflict_detector.rb
|
134
135
|
- lib/cloud/vsphere/lease_obtainer.rb
|
135
136
|
- lib/cloud/vsphere/lease_updater.rb
|
136
137
|
- lib/cloud/vsphere/object_stringifier.rb
|
@@ -198,7 +199,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
199
|
version: '0'
|
199
200
|
requirements: []
|
200
201
|
rubyforge_project:
|
201
|
-
rubygems_version: 2.2.
|
202
|
+
rubygems_version: 2.2.2
|
202
203
|
signing_key:
|
203
204
|
specification_version: 4
|
204
205
|
summary: BOSH VSphere CPI
|